diff --git a/server/Program.cs b/server/Program.cs index 1c4b39c..2a3902a 100644 --- a/server/Program.cs +++ b/server/Program.cs @@ -1,3 +1,4 @@ +using Microsoft.AspNetCore.Http.Features; using Newtonsoft.Json; using NLog; using NLog.Web; @@ -22,6 +23,11 @@ try builder.Host.UseNLog(); builder.Services.AddEndpointsApiExplorer(); + builder.Services.Configure(options => + { + options.MultipartBodyLengthLimit = 32 * 1024 * 1024; + }); + // Add Json.Net Serializer builder.Services.AddControllersWithViews().AddNewtonsoftJson(options => { diff --git a/server/src/Controllers.cs b/server/src/Controllers.cs index d563152..d910b3d 100644 --- a/server/src/Controllers.cs +++ b/server/src/Controllers.cs @@ -160,7 +160,7 @@ public class JtagController : ControllerBase public async ValueTask RunCommand(string address, int port, string hexDevAddr, string hexCmd) { var jtagCtrl = new JtagClient.Jtag(address, port); - var ret = await jtagCtrl.RunCommand(Convert.ToUInt32(hexDevAddr, 16), Convert.ToUInt32(hexCmd, 16)); + var ret = await jtagCtrl.WriteFIFO(Convert.ToUInt32(hexDevAddr, 16), Convert.ToUInt32(hexCmd, 16)); if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); } else { return TypedResults.InternalServerError(ret.Error); } @@ -183,4 +183,16 @@ public class JtagController : ControllerBase if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); } else { return TypedResults.InternalServerError(ret.Error); } } + + [HttpGet("DownloadBitstream")] + [ProducesResponseType(StatusCodes.Status200OK)] + [ProducesResponseType(StatusCodes.Status500InternalServerError)] + public async ValueTask DownloadBitstream(string address, int port, IFormFile file) + { + var jtagCtrl = new JtagClient.Jtag(address, port); + var ret = await jtagCtrl.DownloadBitstream(); + + if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); } + else { return TypedResults.InternalServerError(ret.Error); } + } } diff --git a/server/src/JtagClient.cs b/server/src/JtagClient.cs index 5fb6e4e..d515763 100644 --- a/server/src/JtagClient.cs +++ b/server/src/JtagClient.cs @@ -1,5 +1,4 @@ using System.Net; -using Common; using DotNext; using WebProtocol; @@ -261,10 +260,10 @@ class Jtag if (retPackLen != 4) throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes"); - return Convert.ToUInt32(Number.BytesToNumber(retPackOpts.Data).Value); + return Convert.ToUInt32(Common.Number.BytesToNumber(retPackOpts.Data).Value); } - public async ValueTask> RunCommand(uint devAddr, uint command) + public async ValueTask> WriteFIFO(UInt32 devAddr, UInt32 data) { var ret = false; var opts = new SendAddrPackOptions(); @@ -281,7 +280,7 @@ class Jtag if (!ret) throw new Exception("Send 1st address package failed!"); // Send Data Package ret = await UDPClientPool.SendDataPackAsync(ep, - new SendDataPackage(Number.NumberToBytes(command, 4).Value)); + new SendDataPackage(Common.Number.NumberToBytes(data, 4).Value)); if (!ret) throw new Exception("Send data package failed!"); // Check Msg Bus @@ -309,11 +308,68 @@ class Jtag } } - public async ValueTask> RunCommand - (uint devAddr, uint command, uint result, uint resultMask = 0xFF_FF_FF_FF) + public async ValueTask> WriteFIFO(UInt32 devAddr, byte[] dataArray) { var ret = false; - var retPack = await RunCommand(devAddr, command); + var opts = new SendAddrPackOptions(); + + + opts.BurstType = BurstType.FixedBurst; + opts.CommandID = 0; + opts.Address = devAddr; + + // Check Msg Bus + if (!MsgBus.IsRunning) + throw new Exception("Message bus not working!"); + + var writeTimes = dataArray.Length / (256 * (32 / 8)) + 1; + for (var i = 0; i < writeTimes; i++) + { + var isLastData = i == writeTimes - 1; + // Write Jtag State Register + opts.IsWrite = true; + opts.BurstLength = isLastData ? (byte)(dataArray.Length - i * (256 * (32 / 8)) - 1) : (byte)255; + ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts)); + if (!ret) throw new Exception("Send 1st address package failed!"); + // Send Data Package + ret = await UDPClientPool.SendDataPackAsync(ep, + new SendDataPackage( + isLastData ? + dataArray[(i * (256 * (32 / 8)))..] : + dataArray[(i * (256 * (32 / 8)))..((i + 1) * (256 * (32 / 8)) - 1)] + ) + ); + if (!ret) throw new Exception("Send data package failed!"); + + // Wait for Write Ack + { + var udpResp = await MsgBus.UDPServer.WaitForAckAsync(address, port); + if (!udpResp.IsSuccessful || !udpResp.Value.IsSuccessful) + throw new Exception("Send address package failed"); + } + } + + // Read Jtag State Register + opts.IsWrite = false; + opts.BurstLength = 0; + opts.Address = JtagAddr.STATE; + ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts)); + if (!ret) throw new Exception("Send 2rd Address Package Failed!"); + // Wait for Read Data + { + var udpResp = await MsgBus.UDPServer.WaitForDataAsync(address, port); + if (!udpResp.IsSuccessful || !udpResp.Value.IsSuccessful) + throw new Exception("Send address package failed"); + + return udpResp.Value; + } + } + + public async ValueTask> WriteFIFO + (UInt32 devAddr, UInt32 data, UInt32 result, UInt32 resultMask = 0xFF_FF_FF_FF) + { + var ret = false; + var retPack = await WriteFIFO(devAddr, data); if (retPack.Value.Options.Data is null) throw new Exception($"Data is Null, package: {retPack.Value.Options.ToString()}"); @@ -322,8 +378,28 @@ class Jtag if (retPackLen != 4) throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes"); - if (Number.BitsCheck( - Number.BytesToNumber(retPack.Value.Options.Data).Value, result, resultMask)) + if (Common.Number.BitsCheck( + Common.Number.BytesToNumber(retPack.Value.Options.Data).Value, result, resultMask)) + ret = true; + + return ret; + } + + public async ValueTask> WriteFIFO + (UInt32 devAddr, byte[] data, UInt32 result, UInt32 resultMask = 0xFF_FF_FF_FF) + { + var ret = false; + var retPack = await WriteFIFO(devAddr, data); + + if (retPack.Value.Options.Data is null) + throw new Exception($"Data is Null, package: {retPack.Value.Options.ToString()}"); + + var retPackLen = retPack.Value.Options.Data.Length; + if (retPackLen != 4) + throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes"); + + if (Common.Number.BitsCheck( + Common.Number.BytesToNumber(retPack.Value.Options.Data).Value, result, resultMask)) ret = true; return ret; @@ -332,42 +408,92 @@ class Jtag async ValueTask> ClearAllRegisters() { - return await RunCommand(JtagAddr.STATE, 0xFF_FF_FF_FF, 0x01_02_02_02, JtagState.ALL_REG); + return await WriteFIFO(JtagAddr.STATE, 0xFF_FF_FF_FF, 0x01_02_02_02, JtagState.ALL_REG); } async ValueTask> ClearWriteDataReg() { - return await RunCommand(JtagAddr.STATE, 0x00_00_11_00, 0x01_00_02_00, JtagState.WRITE_DATA_FIFO | JtagState.CMD_EXEC_FINISH); + return await WriteFIFO(JtagAddr.STATE, 0x00_00_11_00, 0x01_00_02_00, JtagState.WRITE_DATA_FIFO | JtagState.CMD_EXEC_FINISH); + } + + async ValueTask> CloseTest() + { + return await WriteFIFO( + JtagAddr.WRITE_CMD, + Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_CLOSE_TEST, JtagCmd.LEN_CMD_JTAG, 0, 28).Value, + 0x01_00_00_00, JtagState.CMD_EXEC_FINISH); } async ValueTask> RunTest() { - return await RunCommand( + return await WriteFIFO( JtagAddr.WRITE_CMD, - Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_RUN_TEST, JtagCmd.LEN_CMD_JTAG, 0, 28).Value, + Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_RUN_TEST, JtagCmd.LEN_CMD_JTAG, 0, 28).Value, 0x01_00_00_00, JtagState.CMD_EXEC_FINISH); } - async ValueTask> DRIDcode() + async ValueTask> IdleDelay(UInt32 milliseconds) { - return await RunCommand( + if (milliseconds > Math.Pow(2, 28)) throw new Exception("Timespan is over 2^28 milliseconds"); + + return await WriteFIFO( + JtagAddr.WRITE_CMD, + Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_IDLE_DELAY, JtagCmd.LEN_CMD_JTAG, milliseconds, 28).Value, + 0x01_00_00_00, JtagState.CMD_EXEC_FINISH); + } + + async ValueTask> ExecRDCmd(uint command) + { + { + var ret = await WriteFIFO( JtagAddr.WRITE_DATA, - Number.MultiBitsToNumber(0, 22, JtagCmd.JTAG_DR_IDCODE, JtagCmd.LEN_JTAG_DR).Value, 0, 0); + Common.Number.MultiBitsToNumber(0, 22, command, JtagCmd.LEN_JTAG_DR).Value, 0, 0); + + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Write JTAG_DR_IDCODE Failed"); + } + { + var ret = await WriteFIFO( + JtagAddr.WRITE_CMD, + Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_IR, JtagCmd.LEN_CMD_JTAG, 10, 28).Value, + 0x01_00_00_00, JtagState.CMD_EXEC_FINISH); + + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Write CMD_JTAG_LOAD_IR Failed"); + } + return await ClearWriteDataReg(); } - async ValueTask> LoadIR() + async ValueTask> LoadDRCareInput(byte[] bytesArray) { - return await RunCommand( - JtagAddr.WRITE_CMD, - Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_IR, JtagCmd.LEN_CMD_JTAG, 10, 28).Value, - 0x01_00_00_00); + var bytesLen = ((uint)(bytesArray.Length * 8)); + if (bytesLen > Math.Pow(2, 28)) throw new Exception("Length is over 2^(28 - 3)"); + + { + var ret = await WriteFIFO( + JtagAddr.WRITE_CMD, + Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_DR_CAREI, JtagCmd.LEN_CMD_JTAG, bytesLen, 28).Value, + 0x01_00_00_00, JtagState.CMD_EXEC_FINISH); + + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Write CMD_JTAG_LOAD_DR_CAREI Failed"); + } + { + var ret = await WriteFIFO(JtagAddr.WRITE_DATA, bytesArray, 0x01_00_00_00, JtagState.CMD_EXEC_FINISH); + + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Write Data Failed"); + } + return true; } - async ValueTask> LoadDRCareo() + async ValueTask> LoadDRCareOutput(UInt32 bytesLen) { - var ret = await RunCommand( + if (bytesLen > Math.Pow(2, 28)) throw new Exception("Length is over 2^(28 - 3)"); + + var ret = await WriteFIFO( JtagAddr.WRITE_CMD, - Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_DR_CAREO, JtagCmd.LEN_CMD_JTAG, 32, 28).Value, + Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_DR_CAREO, JtagCmd.LEN_CMD_JTAG, 8 * bytesLen, 28).Value, 0x01_00_00_00, JtagState.CMD_EXEC_FINISH); if (ret.Value) @@ -378,17 +504,96 @@ class Jtag public async ValueTask> ReadIDCode() { - var ret = false; - // Clear Data await MsgBus.UDPServer.ClearUDPData(this.address); - ret = (await ClearAllRegisters()).Value; - ret = (await RunTest()).Value; - ret = (await DRIDcode()).Value; - ret = (await LoadIR()).Value; - ret = (await ClearWriteDataReg()).Value; - return (await LoadDRCareo()).Value; + { + var ret = await ClearAllRegisters(); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag Clear All Registers Failed"); + } + { + var ret = await RunTest(); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag Run Test Failed"); + } + { + var ret = await ExecRDCmd(JtagCmd.JTAG_DR_IDCODE); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag Execute Command JTAG_DR_IDCODE Failed"); + } + { + var ret = await ClearWriteDataReg(); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag Clear Write Registers Failed"); + } + return (await LoadDRCareOutput(1)).Value; + } + + public async ValueTask> DownloadBitstream(byte[] bitstream) + { + { + var ret = await CloseTest(); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag Close Test Failed"); + } + { + var ret = await RunTest(); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag Run Test Failed"); + } + { + var ret = await ExecRDCmd(JtagCmd.JTAG_DR_JRST); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag Execute Command JTAG_DR_JRST Failed"); + } + { + var ret = await RunTest(); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag Run Test Failed"); + } + { + var ret = await ExecRDCmd(JtagCmd.JTAG_DR_CFGI); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag Execute Command JTAG_DR_CFGI Failed"); + } + { + var ret = await IdleDelay(75000); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag IDLE Delay Failed"); + } + { + var ret = await LoadDRCareInput(bitstream); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag Load Data Failed"); + } + { + var ret = await CloseTest(); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag Close Test Failed"); + } + { + var ret = await RunTest(); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag Run Test Failed"); + } + { + var ret = await ExecRDCmd(JtagCmd.JTAG_DR_JWAKEUP); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag Execute Command JTAG_DR_JWAKEUP Failed"); + } + { + var ret = await IdleDelay(1000); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag IDLE Delay Failed"); + } + { + var ret = await CloseTest(); + if (!ret.IsSuccessful) throw ret.Error; + else if (!ret.Value) throw new Exception("Jtag Close Test Failed"); + } + + return true; } } diff --git a/server/src/WebProtocol.cs b/server/src/WebProtocol.cs index ed6d94d..bbd71ba 100644 --- a/server/src/WebProtocol.cs +++ b/server/src/WebProtocol.cs @@ -266,6 +266,9 @@ namespace WebProtocol /// 数据 public SendDataPackage(byte[] bodyData) { + if (bodyData.Length > 256 * (32 / 8)) + throw new Exception("The data of SendDataPackage can't over 256 * 32bits"); + this.bodyData = bodyData; _ = _reserved; diff --git a/src/views/JtagTest.vue b/src/views/JtagTest.vue index ee3a796..c20d582 100644 --- a/src/views/JtagTest.vue +++ b/src/views/JtagTest.vue @@ -2,8 +2,9 @@
-
+
+