add jtag get id code api

This commit is contained in:
SikongJueluo 2025-04-07 21:56:30 +08:00
parent 292c73e757
commit 93add0c315
No known key found for this signature in database
6 changed files with 300 additions and 29 deletions

View File

@ -41,6 +41,8 @@ app.MapGet("/", () => "Hello World!");
app.MapPut("/api/SendString", Router.API.SendString); app.MapPut("/api/SendString", Router.API.SendString);
app.MapPut("/api/SendAddrPackage", Router.API.SendAddrPackage); app.MapPut("/api/SendAddrPackage", Router.API.SendAddrPackage);
app.MapPut("/api/SendDataPackage", Router.API.SendDataPackage); app.MapPut("/api/SendDataPackage", Router.API.SendDataPackage);
app.MapPut("/api/jtag/RunCommand", Router.API.Jtag.RunCommand);
app.MapPut("/api/jtag/GetIDCode", Router.API.Jtag.GetDeviceIDCode);
app.Run("http://localhost:5000"); app.Run("http://localhost:5000");

View File

@ -12,6 +12,7 @@
<PackageReference Include="DotNext.Threading" Version="5.19.1" /> <PackageReference Include="DotNext.Threading" Version="5.19.1" />
<PackageReference Include="Microsoft.OpenApi" Version="1.6.23" /> <PackageReference Include="Microsoft.OpenApi" Version="1.6.23" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="NLog" Version="5.4.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" />
</ItemGroup> </ItemGroup>

View File

@ -27,13 +27,13 @@ namespace Common
{ {
for (var i = 0; i < length; i++) for (var i = 0; i < length; i++)
{ {
arr[i] = Convert.ToByte((num >> (i << 3)) & (0xFF)); arr[i] = Convert.ToByte((num >> ((int)(length - 1 - i) << 3)) & (0xFF));
} }
} }
return arr; return arr;
} }
public static Result<ulong> BytesToNumber(byte[] bytes, bool isRightLeft = false) public static Result<ulong> BytesToNumber(byte[] bytes, bool isRightHigh = false)
{ {
if (bytes.Length > 8) if (bytes.Length > 8)
{ {
@ -46,7 +46,7 @@ namespace Common
ulong num = 0; ulong num = 0;
int len = bytes.Length; int len = bytes.Length;
if (isRightLeft) if (isRightHigh)
{ {
for (var i = 0; i < len; i++) for (var i = 0; i < len; i++)
{ {
@ -57,13 +57,15 @@ namespace Common
{ {
for (var i = 0; i < len; i++) for (var i = 0; i < len; i++)
{ {
num += Convert.ToUInt64(bytes[i] << (i << 3)); num += Convert.ToUInt64(bytes[i] << ((int)(len - 1 - i) << 3));
} }
} }
return num; return num;
} }
public static Result<byte[]> MultiBitsToBytes(ulong bits1, uint bits1Len, ulong bits2, uint bits2Len) public static Result<byte[]> MultiBitsToBytes(ulong bits1, uint bits1Len, ulong bits2, uint bits2Len)
{ {
return NumberToBytes(MultiBitsToNumber(bits1, bits1Len, bits2, bits2Len).Value, return NumberToBytes(MultiBitsToNumber(bits1, bits1Len, bits2, bits2Len).Value,
@ -74,10 +76,28 @@ namespace Common
{ {
if (bits1Len + bits2Len > 64) throw new ArgumentException("Two Bits is more than 64 bits"); if (bits1Len + bits2Len > 64) throw new ArgumentException("Two Bits is more than 64 bits");
ulong num = (bits1 << (int)bits2Len) | bits2; ulong num = (bits1 << Convert.ToInt32(bits2Len)) | bits2;
return num; return num;
} }
public static Result<uint> MultiBitsToNumber(uint bits1, uint bits1Len, uint bits2, uint bits2Len)
{
if (bits1Len + bits2Len > 64) throw new ArgumentException("Two Bits is more than 64 bits");
uint num = (bits1 << Convert.ToInt32(bits2Len)) | bits2;
return num;
}
public static bool BitsCheck(ulong srcBits, ulong dstBits, ulong mask = 0xFFFF_FFFF_FFFF_FFFF)
{
return (srcBits & mask) == dstBits;
}
public static bool BitsCheck(uint srcBits, uint dstBits, uint mask = 0xFFFF_FFFF)
{
return (srcBits & mask) == dstBits;
}
public static Result<byte[]> StringToBytes(string str, int numBase = 16) public static Result<byte[]> StringToBytes(string str, int numBase = 16)
{ {

View File

@ -28,12 +28,107 @@ public static class JtagAddr
public const UInt32 WRITE_CMD = 0x10_00_00_03; public const UInt32 WRITE_CMD = 0x10_00_00_03;
} }
/// <summary>
/// Jtag 状态寄存器的掩码及其确认函数
/// </summary>
public static class JtagState
{
/*
[0] fifo清空10
[1] fifo读入口-JTAG_STATE_REG的写不改变其值
[2] fifo读入口-JTAG_STATE_REG的写不改变其值
[7:3]
[8] fifo清空10
[9] fifo写入口-JTAG_STATE_REG的写不改变其值
[10] fifo写入口-JTAG_STATE_REG的写不改变其值
[15:11]
[16] fifo清空10
[17] fifo写入口-JTAG_STATE_REG的写不改变其值
[18] fifo写入口-JTAG_STATE_REG的写不改变其值
[23:19]
[24] CMD执行完毕标识JTAG_STATE_REG的写不改变其值
*/
/// <summary>
/// 移位数据读fifo清空1为有效清空后自动置0实际一直为零
/// </summary>
public const UInt32 READ_DATA_FIFO_CLEAR = 0b0001 << 0;
/// <summary>
/// 移位数据fifo读入口-空标识只读对JTAG_STATE_REG的写不改变其值
/// </summary>
public const UInt32 READ_DATA_FIFO_EMPTY = 0b0010 << 0;
/// <summary>
/// 移位数据fifo读入口-满标识只读对JTAG_STATE_REG的写不改变其值
/// </summary>
public const UInt32 READ_DATA_FIFO_AFULL = 0b0100 << 0;
/// <summary>
/// 移位数据读fifo
/// </summary>
public const UInt32 READ_DATA_FIFO = 0b0111 << 0;
/// <summary>
/// 移位数据写fifo清空1为有效清空后自动置0
/// </summary>
public const UInt32 WRITE_DATA_FIFO_CLEAR = 0b0001 << 8;
/// <summary>
/// 移位数据fifo写入口-空标识只读对JTAG_STATE_REG的写不改变其值
/// </summary>
public const UInt32 WRITE_DATA_FIFO_EMPTY = 0b0010 << 8;
/// <summary>
/// 移位数据fifo写入口-满标识只读对JTAG_STATE_REG的写不改变其值
/// </summary>
public const UInt32 WRITE_DATA_FIFO_AFULL = 0b0100 << 8;
/// <summary>
/// 移位数据写fifo
/// </summary>
public const UInt32 WRITE_DATA_FIFO = 0b0111 << 8;
/// <summary>
/// 移位命令写fifo清空1为有效清空后自动置0
/// </summary>
public const UInt32 WRITE_CMD_FIFO_CLEAR = 0b0001 << 16;
/// <summary>
/// 移位命令fifo写入口-空标识只读对JTAG_STATE_REG的写不改变其值
/// </summary>
public const UInt32 WRITE_CMD_FIFO_EMPTY = 0b0010 << 16;
/// <summary>
/// 移位命令fifo写入口-满标识只读对JTAG_STATE_REG的写不改变其值
/// </summary>
public const UInt32 WRITE_CMD_FIFO_AFULL = 0b0100 << 16;
/// <summary>
/// 移位命令写fifo
/// </summary>
public const UInt32 WRITE_CMD_FIFO = 0b0111 << 16;
/// <summary>
/// CMD执行完毕标识只读对JTAG_STATE_REG的写不改变其值
/// </summary>
public const UInt32 CMD_EXEC_FINISH = 0b0001 << 24;
/// <summary>
/// 全部FIFO
/// </summary>
public const UInt32 ALL_FIFO = READ_DATA_FIFO | WRITE_DATA_FIFO | WRITE_CMD_FIFO;
/// <summary>
/// 全部寄存器
/// </summary>
public const UInt32 ALL_REG = READ_DATA_FIFO | WRITE_DATA_FIFO | WRITE_CMD_FIFO | CMD_EXEC_FINISH;
}
/// <summary> /// <summary>
/// The Command bits of Jtag /// The Command bits of Jtag
/// </summary> /// </summary>
public static class JtagCmd public static class JtagCmd
{ {
/// <summary>
/// The length of JTAG_DR_XXXX
/// </summary>
public const UInt32 LEN_JTAG_DR = 10;
/// <summary> /// <summary>
/// 旁路指令 /// 旁路指令
/// </summary> /// </summary>
@ -89,6 +184,10 @@ public static class JtagCmd
/// <summary>
/// The length of CMD_JTAG_XXXX_XXXX
/// </summary>
public const UInt32 LEN_CMD_JTAG = 4;
/// <summary> /// <summary>
/// 设定JTAG默认状态为TEST_LOGIC_RESET态 JTAG复位 /// 设定JTAG默认状态为TEST_LOGIC_RESET态 JTAG复位
/// </summary> /// </summary>
@ -122,18 +221,56 @@ class Jtag
readonly int port; readonly int port;
readonly string address; readonly string address;
private IPEndPoint ep; private IPEndPoint ep;
private UDPServer server;
public Jtag(string address, int port, UDPServer udpServer, int outTime = 2000) public Jtag(string address, int port, int outTime = 2000)
{ {
this.address = address; this.address = address;
this.port = port; this.port = port;
this.ep = new IPEndPoint(IPAddress.Parse(address), port); this.ep = new IPEndPoint(IPAddress.Parse(address), port);
this.server = udpServer;
this.timeout = outTime; this.timeout = outTime;
} }
public async ValueTask<Result<bool>> RunCommand(uint devAddr, uint cmd, uint exRet) public async ValueTask<Result<uint>> ReadFIFO(uint devAddr)
{
var ret = false;
var opts = new SendAddrPackOptions();
opts.burstType = BurstType.FixedBurst;
opts.burstLength = 4;
opts.commandID = 0;
opts.address = devAddr;
// Read Jtag State Register
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
if (!ret) throw new Exception("Send Address Package Failed!");
// Wait for Ack
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 RecvDataPackage!", retPack.Error);
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");
return (uint)(NumberProcessor.BytesToNumber(retPack.Value.Options.data));
}
public async ValueTask<Result<RecvDataPackage>> RunCommand(uint devAddr, uint command)
{ {
var ret = false; var ret = false;
var opts = new SendAddrPackOptions(); var opts = new SendAddrPackOptions();
@ -148,7 +285,7 @@ class Jtag
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts)); ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
if (!ret) throw new Exception("Send 1st Address Package Failed!"); if (!ret) throw new Exception("Send 1st Address Package Failed!");
ret = await UDPClientPool.SendDataPackAsync(ep, ret = await UDPClientPool.SendDataPackAsync(ep,
new SendDataPackage(NumberProcessor.NumberToBytes(cmd, 4).Value)); new SendDataPackage(NumberProcessor.NumberToBytes(command, 4).Value));
if (!ret) throw new Exception("Send Data Package Failed!"); if (!ret) throw new Exception("Send Data Package Failed!");
// Read Jtag State Register // Read Jtag State Register
@ -170,41 +307,88 @@ class Jtag
var retPack = RecvDataPackage.FromBytes(recvData.data); var retPack = RecvDataPackage.FromBytes(recvData.data);
if (!retPack.IsSuccessful) if (!retPack.IsSuccessful)
throw new Exception("Not Current RecvDataPackage!", retPack.Error); throw new Exception("Not RecvDataPackage!", retPack.Error);
return retPack;
}
public async ValueTask<Result<bool>> RunCommand(uint devAddr, uint command, uint result, uint resultMask = 0xFF_FF_FF_FF)
{
var ret = false;
var retPack = await RunCommand(devAddr, command);
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; var retPackLen = retPack.Value.Options.data.Length;
if (retPackLen != 3) if (retPackLen != 4)
throw new Exception($"RecvDataPackage BodyData Length not Equal to 3: Total {retPackLen} bytes"); throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes");
if (NumberProcessor.BytesToNumber(retPack.Value.Options.data).Value == exRet) if (NumberProcessor.BitsCheck(
NumberProcessor.BytesToNumber(retPack.Value.Options.data).Value, result, resultMask))
ret = true; ret = true;
return ret; return ret;
} }
public async ValueTask<Result<bool>> ClearAllRegisters() public async ValueTask<Result<bool>> ClearAllRegisters()
{ {
return await RunCommand(JtagAddr.STATE, 0xFF_FF_FF_FF, 0x00_00_00_00); return await RunCommand(JtagAddr.STATE, 0xFF_FF_FF_FF, 0x01_02_02_02, JtagState.ALL_REG);
} }
public async ValueTask<Result<bool>> ClearWriteDataReg() public async ValueTask<Result<bool>> ClearWriteDataReg()
{ {
return await RunCommand(JtagAddr.STATE, 0x00_00_11_00, 0x00_00_00_00); return await RunCommand(JtagAddr.STATE, 0x00_00_11_00, 0x01_00_02_00, JtagState.WRITE_DATA_FIFO | JtagState.CMD_EXEC_FINISH);
} }
public async ValueTask<Result<bool>> RunTest() public async ValueTask<Result<bool>> RunTest()
{ {
return await RunCommand(JtagAddr.WRITE_CMD, 0x10_00_00_00, 0x01_00_00_00); return await RunCommand(
JtagAddr.WRITE_CMD,
NumberProcessor.MultiBitsToNumber(JtagCmd.CMD_JTAG_RUN_TEST, JtagCmd.LEN_CMD_JTAG, 0, 28).Value,
0x01_00_00_00, JtagState.CMD_EXEC_FINISH);
} }
public async ValueTask<Result<bool>> WriteIDCode() public async ValueTask<Result<bool>> DRIDcode()
{ {
return await RunCommand(JtagAddr.WRITE_DATA, 0b1010000011, 0x01_00_00_00); return await RunCommand(
JtagAddr.WRITE_DATA,
NumberProcessor.MultiBitsToNumber(0, 22, JtagCmd.JTAG_DR_IDCODE, JtagCmd.LEN_JTAG_DR).Value, 0, 0);
} }
public async ValueTask<Result<bool>> LoadIR() public async ValueTask<Result<bool>> LoadIR()
{ {
return await RunCommand(JtagAddr.WRITE_CMD, 0x20_00_00_0A, 0x01_00_00_00); return await RunCommand(
JtagAddr.WRITE_CMD,
NumberProcessor.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_IR, JtagCmd.LEN_CMD_JTAG, 10, 28).Value,
0x01_00_00_00);
}
public async ValueTask<Result<uint>> LoadDRCareo()
{
var ret = await RunCommand(
JtagAddr.WRITE_CMD,
NumberProcessor.MultiBitsToNumber(JtagCmd.CMD_JTAG_LOAD_DR_CAREO, JtagCmd.LEN_CMD_JTAG, 32, 28).Value,
0x01_00_00_00, JtagState.CMD_EXEC_FINISH);
if (ret.Value)
return await ReadFIFO(JtagAddr.READ_DATA);
else
throw new Exception("LoadDRCareo Failed!");
}
public async ValueTask<Result<uint>> ReadIDCode()
{
var ret = false;
ret = (await ClearAllRegisters()).Value;
ret = (await RunTest()).Value;
ret = (await DRIDcode()).Value;
ret = (await LoadIR()).Value;
ret = (await ClearWriteDataReg()).Value;
return (await LoadDRCareo()).Value;
} }
} }

View File

@ -1,10 +1,15 @@
using System.Net; using System.Net;
using Common; using Common;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace Router namespace Router
{ {
struct Response
{
public bool IsSuccess;
public object? Data;
}
/// <summary> /// <summary>
/// Web API /// Web API
/// </summary> /// </summary>
@ -21,8 +26,8 @@ namespace Router
{ {
var endPoint = new IPEndPoint(IPAddress.Parse(address), port); var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
var ret = await UDPClientPool.SendStringAsync(endPoint, [text]); var ret = await UDPClientPool.SendStringAsync(endPoint, [text]);
if (ret) { return Results.Json(true); } if (ret) { return Results.Json(new Response() { IsSuccess = true }); }
else { return Results.Json(false); } else { return Results.Json(new Response() { IsSuccess = false }); }
} }
@ -46,8 +51,8 @@ namespace Router
var endPoint = new IPEndPoint(IPAddress.Parse(address), port); var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
var ret = await UDPClientPool.SendAddrPackAsync(endPoint, new WebProtocol.SendAddrPackage(opts)); var ret = await UDPClientPool.SendAddrPackAsync(endPoint, new WebProtocol.SendAddrPackage(opts));
if (ret) { return Results.Json(true); } if (ret) { return Results.Json(new Response() { IsSuccess = true }); }
else { return Results.Json(false); } else { return Results.Json(new Response() { IsSuccess = false }); }
} }
public static async ValueTask<IResult> SendDataPackage(string address, int port, string data) public static async ValueTask<IResult> SendDataPackage(string address, int port, string data)
@ -55,12 +60,46 @@ namespace Router
var endPoint = new IPEndPoint(IPAddress.Parse(address), port); var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
var ret = await UDPClientPool.SendDataPackAsync(endPoint, var ret = await UDPClientPool.SendDataPackAsync(endPoint,
new WebProtocol.SendDataPackage(NumberProcessor.StringToBytes(data).Value)); new WebProtocol.SendDataPackage(NumberProcessor.StringToBytes(data).Value));
if (ret) { return Results.Json(true); } if (ret) { return Results.Json(new Response() { IsSuccess = true }); }
else { return Results.Json(false); } else { return Results.Json(new Response() { IsSuccess = false }); }
} }
public static async ValueTask<IResult> GetDeviceIDCode(string address, int port) public class Jtag
{ {
/// <summary>
/// 执行一个Jtag命令
/// </summary>
/// <param name="address"> 设备地址 </param>
/// <param name="port"> 设备端口 </param>
/// <param name="hexDevAddr"> 16进制设备目的地址(Jtag) </param>
/// <param name="hexCmd"> 16进制命令 </param>
/// <param name="hexExRet"> 16进制预期结果 </param>
/// <returns> Response </returns>
public static async ValueTask<IResult> RunCommand(string address, int port, string hexDevAddr, string hexCmd, string hexExRet)
{
var jtagCtrl = new JtagController.Jtag(address, port);
var ret = await jtagCtrl.RunCommand(Convert.ToUInt32(hexDevAddr, 16), Convert.ToUInt32(hexCmd, 16), Convert.ToUInt32(hexExRet, 16));
if (ret.IsSuccessful) { return Results.Json(new Response() { IsSuccess = true }); }
else { return Results.Json(new Response() { IsSuccess = false, Data = ret.Error }); }
}
/// <summary>
/// 获取Jtag ID Code
/// </summary>
/// <param name="address"> 设备地址 </param>
/// <param name="port"> 设备端口 </param>
/// <returns> Response </returns>
public static async ValueTask<IResult> GetDeviceIDCode(string address, int port)
{
var jtagCtrl = new JtagController.Jtag(address, port);
var ret = await jtagCtrl.ReadIDCode();
if (ret.IsSuccessful) { return Results.Json(new Response() { IsSuccess = true, Data = ret.Value }); }
else { return Results.Json(new Response() { IsSuccess = false, Data = ret.Error }); }
}
} }

View File

@ -49,19 +49,43 @@ namespace WebProtocol
/// <example> 0x10_00_00_00 </example> /// <example> 0x10_00_00_00 </example>
public UInt32 address; public UInt32 address;
/// <summary>
/// Convert to Json String
/// </summary>
/// <returns> Json String </returns>
public override string ToString() public override string ToString()
{ {
return JsonConvert.SerializeObject(this); return JsonConvert.SerializeObject(this);
} }
} }
/// <summary> Package Options which to receive from boards </summary>
public struct RecvPackOptions public struct RecvPackOptions
{ {
/// <summary>
/// Task ID
/// </summary>
public byte commandID; public byte commandID;
/// <summary>
/// Whether is succeed to finish command
/// </summary>
public bool isSuccess; public bool isSuccess;
public byte[] data; /// <summary>
/// Return Data
/// </summary>
public byte[]? data;
/// <summary>
/// Convert to Json String
/// </summary>
/// <returns> Json String </returns>
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
} }
/// <summary> Package which send address to write </summary>
public struct SendAddrPackage public struct SendAddrPackage
{ {
readonly byte sign = (byte)PackSign.SendAddr; readonly byte sign = (byte)PackSign.SendAddr;
@ -227,6 +251,7 @@ namespace WebProtocol
RecvPackOptions opts; RecvPackOptions opts;
opts.commandID = commandID; opts.commandID = commandID;
opts.isSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? true : false); opts.isSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? true : false);
opts.data = null;
return opts; return opts;
} }