jtag add download bitstream

This commit is contained in:
SikongJueluo 2025-04-21 21:54:09 +08:00
parent acd6a68507
commit 70f96701f7
No known key found for this signature in database
5 changed files with 261 additions and 34 deletions

View File

@ -1,3 +1,4 @@
using Microsoft.AspNetCore.Http.Features;
using Newtonsoft.Json; using Newtonsoft.Json;
using NLog; using NLog;
using NLog.Web; using NLog.Web;
@ -22,6 +23,11 @@ try
builder.Host.UseNLog(); builder.Host.UseNLog();
builder.Services.AddEndpointsApiExplorer(); builder.Services.AddEndpointsApiExplorer();
builder.Services.Configure<FormOptions>(options =>
{
options.MultipartBodyLengthLimit = 32 * 1024 * 1024;
});
// Add Json.Net Serializer // Add Json.Net Serializer
builder.Services.AddControllersWithViews().AddNewtonsoftJson(options => builder.Services.AddControllersWithViews().AddNewtonsoftJson(options =>
{ {

View File

@ -160,7 +160,7 @@ public class JtagController : ControllerBase
public async ValueTask<IResult> RunCommand(string address, int port, string hexDevAddr, string hexCmd) public async ValueTask<IResult> RunCommand(string address, int port, string hexDevAddr, string hexCmd)
{ {
var jtagCtrl = new JtagClient.Jtag(address, port); 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); } if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); }
else { return TypedResults.InternalServerError(ret.Error); } else { return TypedResults.InternalServerError(ret.Error); }
@ -183,4 +183,16 @@ public class JtagController : ControllerBase
if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); } if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); }
else { return TypedResults.InternalServerError(ret.Error); } else { return TypedResults.InternalServerError(ret.Error); }
} }
[HttpGet("DownloadBitstream")]
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
public async ValueTask<IResult> 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); }
}
} }

View File

@ -1,5 +1,4 @@
using System.Net; using System.Net;
using Common;
using DotNext; using DotNext;
using WebProtocol; using WebProtocol;
@ -261,10 +260,10 @@ class Jtag
if (retPackLen != 4) if (retPackLen != 4)
throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes"); 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<Result<RecvDataPackage>> RunCommand(uint devAddr, uint command) public async ValueTask<Result<RecvDataPackage>> WriteFIFO(UInt32 devAddr, UInt32 data)
{ {
var ret = false; var ret = false;
var opts = new SendAddrPackOptions(); var opts = new SendAddrPackOptions();
@ -281,7 +280,7 @@ class Jtag
if (!ret) throw new Exception("Send 1st address package failed!"); if (!ret) throw new Exception("Send 1st address package failed!");
// Send Data Package // Send Data Package
ret = await UDPClientPool.SendDataPackAsync(ep, 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!"); if (!ret) throw new Exception("Send data package failed!");
// Check Msg Bus // Check Msg Bus
@ -309,11 +308,68 @@ class Jtag
} }
} }
public async ValueTask<Result<bool>> RunCommand public async ValueTask<Result<RecvDataPackage>> WriteFIFO(UInt32 devAddr, byte[] dataArray)
(uint devAddr, uint command, uint result, uint resultMask = 0xFF_FF_FF_FF)
{ {
var ret = false; 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<Result<bool>> 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) if (retPack.Value.Options.Data is null)
throw new Exception($"Data is Null, package: {retPack.Value.Options.ToString()}"); throw new Exception($"Data is Null, package: {retPack.Value.Options.ToString()}");
@ -322,8 +378,28 @@ class Jtag
if (retPackLen != 4) if (retPackLen != 4)
throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes"); throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes");
if (Number.BitsCheck( if (Common.Number.BitsCheck(
Number.BytesToNumber(retPack.Value.Options.Data).Value, result, resultMask)) Common.Number.BytesToNumber(retPack.Value.Options.Data).Value, result, resultMask))
ret = true;
return ret;
}
public async ValueTask<Result<bool>> 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; ret = true;
return ret; return ret;
@ -332,42 +408,92 @@ class Jtag
async ValueTask<Result<bool>> ClearAllRegisters() async ValueTask<Result<bool>> 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<Result<bool>> ClearWriteDataReg() async ValueTask<Result<bool>> 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<Result<bool>> 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<Result<bool>> RunTest() async ValueTask<Result<bool>> RunTest()
{ {
return await RunCommand( return await WriteFIFO(
JtagAddr.WRITE_CMD, 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); 0x01_00_00_00, JtagState.CMD_EXEC_FINISH);
} }
async ValueTask<Result<bool>> DRIDcode() async ValueTask<Result<bool>> 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<Result<bool>> ExecRDCmd(uint command)
{
{
var ret = await WriteFIFO(
JtagAddr.WRITE_DATA, 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<Result<bool>> LoadIR() async ValueTask<Result<bool>> LoadDRCareInput(byte[] bytesArray)
{ {
return await RunCommand( 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, JtagAddr.WRITE_CMD,
Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_IR, JtagCmd.LEN_CMD_JTAG, 10, 28).Value, Common.Number.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_DR_CAREI, JtagCmd.LEN_CMD_JTAG, bytesLen, 28).Value,
0x01_00_00_00); 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<Result<uint>> LoadDRCareo() async ValueTask<Result<UInt32>> 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, 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); 0x01_00_00_00, JtagState.CMD_EXEC_FINISH);
if (ret.Value) if (ret.Value)
@ -378,17 +504,96 @@ class Jtag
public async ValueTask<Result<uint>> ReadIDCode() public async ValueTask<Result<uint>> ReadIDCode()
{ {
var ret = false;
// Clear Data // Clear Data
await MsgBus.UDPServer.ClearUDPData(this.address); await MsgBus.UDPServer.ClearUDPData(this.address);
ret = (await ClearAllRegisters()).Value; {
ret = (await RunTest()).Value; var ret = await ClearAllRegisters();
ret = (await DRIDcode()).Value; if (!ret.IsSuccessful) throw ret.Error;
ret = (await LoadIR()).Value; else if (!ret.Value) throw new Exception("Jtag Clear All Registers Failed");
ret = (await ClearWriteDataReg()).Value; }
return (await LoadDRCareo()).Value; {
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<Result<bool>> 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;
} }
} }

View File

@ -266,6 +266,9 @@ namespace WebProtocol
/// <param name="bodyData">数据</param> /// <param name="bodyData">数据</param>
public SendDataPackage(byte[] bodyData) 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; this.bodyData = bodyData;
_ = _reserved; _ = _reserved;

View File

@ -2,8 +2,9 @@
<div class="h-screen w-screen flex justify-center"> <div class="h-screen w-screen flex justify-center">
<div class="h-full w-32"></div> <div class="h-full w-32"></div>
<div class="h-full w-[70%] shadow-2xl"> <div class="h-full w-[70%] shadow-2xl flex">
<button class="btn btn-primary h-10 w-30">获取ID Code</button>
</div> </div>
</div> </div>
</template> </template>