diff --git a/server/Program.cs b/server/Program.cs index 0ed5a83..de3c392 100644 --- a/server/Program.cs +++ b/server/Program.cs @@ -33,9 +33,8 @@ if (app.Environment.IsDevelopment()) }); } -// Setup UDP Server -var udpServer = new UDPServer(33000); -udpServer.Start(); +// Setup Program +MsgBus.Init(); // Router app.MapGet("/", () => "Hello World!"); @@ -46,6 +45,5 @@ app.MapPut("/api/SendDataPackage", Router.API.SendDataPackage); app.Run("http://localhost:5000"); // Close UDP Server -Console.WriteLine("UDP Server is Closing now..."); -udpServer.Stop(); - +Console.WriteLine("Program is Closing now..."); +MsgBus.Exit(); diff --git a/server/server.csproj b/server/server.csproj index c74cb1d..72e9b6e 100644 --- a/server/server.csproj +++ b/server/server.csproj @@ -9,6 +9,7 @@ + diff --git a/server/src/Common.cs b/server/src/Common.cs index 5970d07..714b566 100644 --- a/server/src/Common.cs +++ b/server/src/Common.cs @@ -64,6 +64,21 @@ namespace Common return num; } + public static Result MultiBitsToBytes(ulong bits1, uint bits1Len, ulong bits2, uint bits2Len) + { + return NumberToBytes(MultiBitsToNumber(bits1, bits1Len, bits2, bits2Len).Value, + (bits1Len + bits2Len) % 8 != 0 ? (bits1Len + bits2Len) / 8 + 1 : (bits1Len + bits2Len) / 8); + } + + public static Result MultiBitsToNumber(ulong bits1, uint bits1Len, ulong bits2, uint bits2Len) + { + if (bits1Len + bits2Len > 64) throw new ArgumentException("Two Bits is more than 64 bits"); + + ulong num = (bits1 << (int)bits2Len) | bits2; + return num; + } + + public static Result StringToBytes(string str, int numBase = 16) { var len = str.Length; diff --git a/server/src/JtagController.cs b/server/src/JtagController.cs index 850ccf2..0c092be 100644 --- a/server/src/JtagController.cs +++ b/server/src/JtagController.cs @@ -28,6 +28,93 @@ public static class JtagAddr public const UInt32 WRITE_CMD = 0x10_00_00_03; } +/// +/// The Command bits of Jtag +/// +public static class JtagCmd +{ + + /// + /// 旁路指令 + /// + public const UInt32 JTAG_DR_BYPASS = 0b1111111111; + /// + /// 采样指令 + /// + public const UInt32 JTAG_DR_SAMPLE = 0b1010000000; + /// + /// 预装指令 + /// + public const UInt32 JTAG_DR_PRELOAD = 0b1010000000; + /// + /// 外测试指令 + /// + public const UInt32 JTAG_DR_EXTEST = 0b1010000001; + /// + /// 内测试指令 + /// + public const UInt32 JTAG_DR_INTEST = 0b1010000010; + /// + /// 标识指令 + /// + public const UInt32 JTAG_DR_IDCODE = 0b1010000011; + /// + /// 高阻指令 + /// + public const UInt32 JTAG_DR_HIGHZ = 0b1010000101; + /// + /// 复位指令 + /// + public const UInt32 JTAG_DR_JRST = 0b1010001010; + /// + /// 配置指令 + /// + public const UInt32 JTAG_DR_CFGI = 0b1010001011; + /// + /// 回读指令 + /// + public const UInt32 JTAG_DR_CFGO = 0b1010001100; + /// + /// 唤醒指令 + /// + public const UInt32 JTAG_DR_JWAKEUP = 0b1010001101; + /// + /// 读UID指令 + /// + public const UInt32 JTAG_DR_READ_UID = 0b0101001100; + /// + /// 读状态寄存器指令 + /// + public const UInt32 JTAG_DR_RDSR = 0b0101011001; + + + + /// + /// 设定JTAG默认状态为TEST_LOGIC_RESET态 (JTAG复位) + /// + public const UInt32 CMD_JTAG_CLOSE_TEST = 0b0000; + /// + /// 设定JTAG默认状态为RUN_TEST_IDLE态 (JTAG空闲) + /// + public const UInt32 CMD_JTAG_RUN_TEST = 0b0001; + /// + /// JTAG进入SHIFTIR循环cycle_num次后回到设定的默认状态 + /// + public const UInt32 CMD_JTAG_LOAD_IR = 0b0010; + /// + /// JTAG进入SHIFTDR循环cycle_num次后回到设定的默认状态,同时输入shift_in + /// + public const UInt32 CMD_JTAG_LOAD_DR_CAREI = 0b0011; + /// + /// JTAG进入SHIFTDR循环cycle_num次后回到设定的默认状态,同时输出shift_out + /// + public const UInt32 CMD_JTAG_LOAD_DR_CAREO = 0b0100; + /// + /// JTAG进入RUN_TEST_IDLE态循环cycle_num次 + /// + public const UInt32 CMD_JTAG_IDLE_DELAY = 0b0101; +} + class Jtag { readonly int timeout; @@ -46,32 +133,78 @@ class Jtag this.timeout = outTime; } - public async ValueTask> ClearRegisters() + public async ValueTask> RunCommand(uint devAddr, uint cmd, uint exRet) { - var ret = true; + var ret = false; var opts = new SendAddrPackOptions(); opts.burstType = BurstType.FixedBurst; opts.burstLength = 4; opts.commandID = 0; - opts.address = JtagAddr.STATE; + opts.address = devAddr; // Write Jtag State Register opts.isWrite = true; ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts)); if (!ret) throw new Exception("Send 1st Address Package Failed!"); ret = await UDPClientPool.SendDataPackAsync(ep, - new SendDataPackage(NumberProcessor.NumberToBytes(0xFF_FF_FF_FF, 4).Value)); + new SendDataPackage(NumberProcessor.NumberToBytes(cmd, 4).Value)); if (!ret) throw new Exception("Send Data Package Failed!"); // Read Jtag State Register + opts.address = JtagAddr.STATE; ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts)); if (!ret) throw new Exception("Send 2rd Address Package Failed!"); // Wait for Ack - var data = await UDPServer. + if (!MsgBus.IsRunning) + throw new Exception("Message Bus not Working!"); + var data = await MsgBus.UDPServer.FindDataAsync(address); + if (!data.HasValue) + throw new Exception("Get None after Time out!"); + + var recvData = data.Value; + if (recvData.addr != address || recvData.port != port) + throw new Exception("Receive Data From Wrong Board!"); + + var retPack = RecvDataPackage.FromBytes(recvData.data); + if (!retPack.IsSuccessful) + throw new Exception("Not Current RecvDataPackage!", retPack.Error); + + var retPackLen = retPack.Value.Options.data.Length; + if (retPackLen != 3) + throw new Exception($"RecvDataPackage BodyData Length not Equal to 3: Total {retPackLen} bytes"); + + if (NumberProcessor.BytesToNumber(retPack.Value.Options.data).Value == exRet) + ret = true; return ret; } + + public async ValueTask> ClearAllRegisters() + { + return await RunCommand(JtagAddr.STATE, 0xFF_FF_FF_FF, 0x00_00_00_00); + } + + public async ValueTask> ClearWriteDataReg() + { + return await RunCommand(JtagAddr.STATE, 0x00_00_11_00, 0x00_00_00_00); + } + + public async ValueTask> RunTest() + { + return await RunCommand(JtagAddr.WRITE_CMD, 0x10_00_00_00, 0x01_00_00_00); + } + + public async ValueTask> WriteIDCode() + { + return await RunCommand(JtagAddr.WRITE_DATA, 0b1010000011, 0x01_00_00_00); + } + + public async ValueTask> LoadIR() + { + return await RunCommand(JtagAddr.WRITE_CMD, 0x20_00_00_0A, 0x01_00_00_00); + } + } diff --git a/server/src/MsgBus.cs b/server/src/MsgBus.cs new file mode 100644 index 0000000..2f9510a --- /dev/null +++ b/server/src/MsgBus.cs @@ -0,0 +1,22 @@ + + +public static class MsgBus +{ + private static readonly UDPServer udpServer = new UDPServer(33000); + public static UDPServer UDPServer { get { return udpServer; } } + + private static bool isRunning = false; + public static bool IsRunning { get { return isRunning; } } + + public static void Init() + { + udpServer.Start(); + isRunning = true; + } + + public static void Exit() + { + udpServer.Stop(); + isRunning = false; + } +} diff --git a/server/src/UdpServer.cs b/server/src/UdpServer.cs index 87fac63..28fe6e3 100644 --- a/server/src/UdpServer.cs +++ b/server/src/UdpServer.cs @@ -2,6 +2,7 @@ using System.Net; using System.Net.Sockets; using System.Text; using DotNext; +using DotNext.Threading; public struct UDPData { @@ -20,7 +21,7 @@ public class UDPServer private UdpClient listener; private IPEndPoint groupEP; private Dictionary> udpData = new Dictionary>(); - private Mutex mutUdpData = new Mutex(); + private AsyncReaderWriterLock udpDataLock = new AsyncReaderWriterLock(1); /// /// Construct a udp server with fixed port @@ -50,32 +51,21 @@ public class UDPServer /// Find UDP Receive Data According to ip address /// /// IP Address + /// Read and Write Wait for Milliseconds /// UDP Data - public Optional FindData(string ipAddr) + public Optional FindData(string ipAddr, int rwTimeout = 1000) { UDPData? data = null; - try + using (udpDataLock.AcquireWriteLock(TimeSpan.FromMilliseconds(rwTimeout))) { - var isOverTime = !mutUdpData.WaitOne(1000); - if (isOverTime) return Optional.None(); - // Get - var listData = udpData[ipAddr]; - data = listData[0]; - - // Delete - listData.RemoveAt(0); - } - catch - { - data = null; - } - finally - { - mutUdpData.ReleaseMutex(); + if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0) + { + data = udpData[ipAddr][0]; + udpData[ipAddr].RemoveAt(0); + } } - // Return - if (data is null) + if (data == null) { return Optional.None(); } @@ -93,35 +83,24 @@ public class UDPServer /// [TODO:return] public async ValueTask> FindDataAsync(string ipAddr, int timeout = 1000) { - var time = 0; UDPData? data = null; - while (time < timeout) + using (await udpDataLock.AcquireWriteLockAsync(TimeSpan.FromMilliseconds(1000))) { - await Task.Delay(1); - try + if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0) { - var isOverTime = !mutUdpData.WaitOne(timeout - time); - if (isOverTime) break; - // Get - var listData = udpData[ipAddr]; - data = listData[0]; - - // Delete - listData.RemoveAt(0); + data = udpData[ipAddr][0]; + udpData[ipAddr].RemoveAt(0); } - catch - { - data = null; - } - finally - { - mutUdpData.ReleaseMutex(); - } - if (data is null) continue; - else break; } - if ((time >= timeout) || (data is null)) { return Optional.None(); } - else { return Optional.Some((UDPData)data); } + + if (data == null) + { + return Optional.None(); + } + else + { + return Optional.Some((UDPData)data); + } } private void ReceiveHandler(IAsyncResult res) @@ -131,7 +110,7 @@ public class UDPServer var nowtime = DateTime.Now; // Handle RemoteEP - string remoteStr; + string remoteStr = "Unknown"; if (remoteEP is not null) { var remoteAddress = remoteEP.Address.ToString(); @@ -160,14 +139,10 @@ public class UDPServer remoteStr = $"{remoteAddress}:{remotePort}"; } - else - { - remoteStr = "Unknown"; - } // Handle Package var sign = bytes[0]; - string recvData; + string recvData = ""; if (sign == (byte)WebProtocol.PackSign.SendAddr) { var resData = WebProtocol.SendAddrPackage.FromBytes(bytes); @@ -176,18 +151,9 @@ public class UDPServer else recvData = resData.Error.ToString(); } - else if (sign == (byte)WebProtocol.PackSign.SendData) - { - recvData = ""; - } - else if (sign == (byte)WebProtocol.PackSign.RecvData) - { - recvData = ""; - } - else if (sign == (byte)WebProtocol.PackSign.RecvResp) - { - recvData = ""; - } + else if (sign == (byte)WebProtocol.PackSign.SendData) { } + else if (sign == (byte)WebProtocol.PackSign.RecvData) { } + else if (sign == (byte)WebProtocol.PackSign.RecvResp) { } else { recvData = Encoding.ASCII.GetString(bytes, 0, bytes.Length); diff --git a/server/src/WebProtocol.cs b/server/src/WebProtocol.cs index 8b721aa..a224724 100644 --- a/server/src/WebProtocol.cs +++ b/server/src/WebProtocol.cs @@ -59,6 +59,7 @@ namespace WebProtocol { public byte commandID; public bool isSuccess; + public byte[] data; } public struct SendAddrPackage @@ -184,13 +185,27 @@ namespace WebProtocol this.bodyData = bodyData; } - public RecvPackOptions Options() + public RecvPackOptions Options { - RecvPackOptions opts; - opts.commandID = commandID; - opts.isSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? true : false); + get + { + RecvPackOptions opts; + opts.commandID = commandID; + opts.isSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? true : false); + opts.data = bodyData; - return opts; + return opts; + } + } + + public static Result FromBytes(byte[] bytes) + { + if (bytes[0] != (byte)PackSign.RecvData) + throw new ArgumentException( + "The sign of bytes is not RecvData Package!", + nameof(bytes) + ); + return new RecvDataPackage(bytes[1], bytes[2], bytes[4..]); } } diff --git a/src/App.vue b/src/App.vue index 6898241..139e28d 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,4 +1,5 @@ + + diff --git a/src/components/Sidebar.vue b/src/components/Sidebar.vue index 38d0561..97eaed7 100644 --- a/src/components/Sidebar.vue +++ b/src/components/Sidebar.vue @@ -1,123 +1,139 @@ diff --git a/src/components/UploadCard.vue b/src/components/UploadCard.vue index 1cfe5ce..c9e0d76 100644 --- a/src/components/UploadCard.vue +++ b/src/components/UploadCard.vue @@ -1,29 +1,31 @@ diff --git a/src/views/UserView.vue b/src/views/UserView.vue index 1bd7e7d..d9c8e94 100644 --- a/src/views/UserView.vue +++ b/src/views/UserView.vue @@ -1,10 +1,6 @@ diff --git a/tsconfig.json b/tsconfig.json index bf2d6db..66b5e57 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,9 +6,6 @@ }, { "path": "./tsconfig.app.json" - }, - { - "path": "./tsconfig.bun.json" } ] }