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 NLog;
using NLog.Web;
@ -22,6 +23,11 @@ try
builder.Host.UseNLog();
builder.Services.AddEndpointsApiExplorer();
builder.Services.Configure<FormOptions>(options =>
{
options.MultipartBodyLengthLimit = 32 * 1024 * 1024;
});
// Add Json.Net Serializer
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)
{
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<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 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<Result<RecvDataPackage>> RunCommand(uint devAddr, uint command)
public async ValueTask<Result<RecvDataPackage>> 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<Result<bool>> RunCommand
(uint devAddr, uint command, uint result, uint resultMask = 0xFF_FF_FF_FF)
public async ValueTask<Result<RecvDataPackage>> 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<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)
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<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;
return ret;
@ -332,42 +408,92 @@ class Jtag
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()
{
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()
{
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<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,
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(
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<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,
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<Result<uint>> 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<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>
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;

View File

@ -2,8 +2,9 @@
<div class="h-screen w-screen flex justify-center">
<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>
</template>