diff --git a/server/Program.cs b/server/Program.cs
index de3c392..692e916 100644
--- a/server/Program.cs
+++ b/server/Program.cs
@@ -41,6 +41,8 @@ app.MapGet("/", () => "Hello World!");
app.MapPut("/api/SendString", Router.API.SendString);
app.MapPut("/api/SendAddrPackage", Router.API.SendAddrPackage);
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");
diff --git a/server/server.csproj b/server/server.csproj
index 72e9b6e..faf5a41 100644
--- a/server/server.csproj
+++ b/server/server.csproj
@@ -12,6 +12,7 @@
+
diff --git a/server/src/Common.cs b/server/src/Common.cs
index 714b566..465b096 100644
--- a/server/src/Common.cs
+++ b/server/src/Common.cs
@@ -27,13 +27,13 @@ namespace Common
{
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;
}
- public static Result BytesToNumber(byte[] bytes, bool isRightLeft = false)
+ public static Result BytesToNumber(byte[] bytes, bool isRightHigh = false)
{
if (bytes.Length > 8)
{
@@ -46,7 +46,7 @@ namespace Common
ulong num = 0;
int len = bytes.Length;
- if (isRightLeft)
+ if (isRightHigh)
{
for (var i = 0; i < len; i++)
{
@@ -57,13 +57,15 @@ namespace Common
{
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;
}
+
+
public static Result MultiBitsToBytes(ulong bits1, uint bits1Len, ulong bits2, uint bits2Len)
{
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");
- ulong num = (bits1 << (int)bits2Len) | bits2;
+ ulong num = (bits1 << Convert.ToInt32(bits2Len)) | bits2;
return num;
}
+ public static Result 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 StringToBytes(string str, int numBase = 16)
{
diff --git a/server/src/JtagController.cs b/server/src/JtagController.cs
index 0c092be..ae26c01 100644
--- a/server/src/JtagController.cs
+++ b/server/src/JtagController.cs
@@ -28,12 +28,107 @@ public static class JtagAddr
public const UInt32 WRITE_CMD = 0x10_00_00_03;
}
+///
+/// Jtag 状态寄存器的掩码及其确认函数
+///
+public static class JtagState
+{
+
+ /*
+ [0] 移位数据读fifo清空,1为有效,清空后自动置0
+ [1] 移位数据fifo读入口-空标识,只读,对JTAG_STATE_REG的写不改变其值
+ [2] 移位数据fifo读入口-满标识,只读,对JTAG_STATE_REG的写不改变其值
+ [7:3] 保留
+
+ [8] 移位数据写fifo清空,1为有效,清空后自动置0
+ [9] 移位数据fifo写入口-空标识,只读,对JTAG_STATE_REG的写不改变其值
+ [10] 移位数据fifo写入口-满标识,只读,对JTAG_STATE_REG的写不改变其值
+ [15:11]保留
+
+ [16] 移位命令写fifo清空,1为有效,清空后自动置0
+ [17] 移位命令fifo写入口-空标识,只读,对JTAG_STATE_REG的写不改变其值
+ [18] 移位命令fifo写入口-满标识,只读,对JTAG_STATE_REG的写不改变其值
+ [23:19]保留
+
+ [24] CMD执行完毕标识,只读,对JTAG_STATE_REG的写不改变其值
+ */
+
+ ///
+ /// 移位数据读fifo清空,1为有效,清空后自动置0,实际一直为零
+ ///
+ public const UInt32 READ_DATA_FIFO_CLEAR = 0b0001 << 0;
+ ///
+ /// 移位数据fifo读入口-空标识,只读,对JTAG_STATE_REG的写不改变其值
+ ///
+ public const UInt32 READ_DATA_FIFO_EMPTY = 0b0010 << 0;
+ ///
+ /// 移位数据fifo读入口-满标识,只读,对JTAG_STATE_REG的写不改变其值
+ ///
+ public const UInt32 READ_DATA_FIFO_AFULL = 0b0100 << 0;
+ ///
+ /// 移位数据读fifo
+ ///
+ public const UInt32 READ_DATA_FIFO = 0b0111 << 0;
+
+ ///
+ /// 移位数据写fifo清空,1为有效,清空后自动置0
+ ///
+ public const UInt32 WRITE_DATA_FIFO_CLEAR = 0b0001 << 8;
+ ///
+ /// 移位数据fifo写入口-空标识,只读,对JTAG_STATE_REG的写不改变其值
+ ///
+ public const UInt32 WRITE_DATA_FIFO_EMPTY = 0b0010 << 8;
+ ///
+ /// 移位数据fifo写入口-满标识,只读,对JTAG_STATE_REG的写不改变其值
+ ///
+ public const UInt32 WRITE_DATA_FIFO_AFULL = 0b0100 << 8;
+ ///
+ /// 移位数据写fifo
+ ///
+ public const UInt32 WRITE_DATA_FIFO = 0b0111 << 8;
+
+ ///
+ /// 移位命令写fifo清空,1为有效,清空后自动置0
+ ///
+ public const UInt32 WRITE_CMD_FIFO_CLEAR = 0b0001 << 16;
+ ///
+ /// 移位命令fifo写入口-空标识,只读,对JTAG_STATE_REG的写不改变其值
+ ///
+ public const UInt32 WRITE_CMD_FIFO_EMPTY = 0b0010 << 16;
+ ///
+ /// 移位命令fifo写入口-满标识,只读,对JTAG_STATE_REG的写不改变其值
+ ///
+ public const UInt32 WRITE_CMD_FIFO_AFULL = 0b0100 << 16;
+ ///
+ /// 移位命令写fifo
+ ///
+ public const UInt32 WRITE_CMD_FIFO = 0b0111 << 16;
+
+ ///
+ /// CMD执行完毕标识,只读,对JTAG_STATE_REG的写不改变其值
+ ///
+ public const UInt32 CMD_EXEC_FINISH = 0b0001 << 24;
+ ///
+ /// 全部FIFO
+ ///
+ public const UInt32 ALL_FIFO = READ_DATA_FIFO | WRITE_DATA_FIFO | WRITE_CMD_FIFO;
+ ///
+ /// 全部寄存器
+ ///
+ public const UInt32 ALL_REG = READ_DATA_FIFO | WRITE_DATA_FIFO | WRITE_CMD_FIFO | CMD_EXEC_FINISH;
+
+}
+
///
/// The Command bits of Jtag
///
public static class JtagCmd
{
+ ///
+ /// The length of JTAG_DR_XXXX
+ ///
+ public const UInt32 LEN_JTAG_DR = 10;
///
/// 旁路指令
///
@@ -89,6 +184,10 @@ public static class JtagCmd
+ ///
+ /// The length of CMD_JTAG_XXXX_XXXX
+ ///
+ public const UInt32 LEN_CMD_JTAG = 4;
///
/// 设定JTAG默认状态为TEST_LOGIC_RESET态 (JTAG复位)
///
@@ -122,18 +221,56 @@ class Jtag
readonly int port;
readonly string address;
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.port = port;
this.ep = new IPEndPoint(IPAddress.Parse(address), port);
- this.server = udpServer;
this.timeout = outTime;
}
- public async ValueTask> RunCommand(uint devAddr, uint cmd, uint exRet)
+ public async ValueTask> 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> RunCommand(uint devAddr, uint command)
{
var ret = false;
var opts = new SendAddrPackOptions();
@@ -148,7 +285,7 @@ class Jtag
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(cmd, 4).Value));
+ new SendDataPackage(NumberProcessor.NumberToBytes(command, 4).Value));
if (!ret) throw new Exception("Send Data Package Failed!");
// Read Jtag State Register
@@ -170,41 +307,88 @@ class Jtag
var retPack = RecvDataPackage.FromBytes(recvData.data);
if (!retPack.IsSuccessful)
- throw new Exception("Not Current RecvDataPackage!", retPack.Error);
+ throw new Exception("Not RecvDataPackage!", retPack.Error);
+
+
+ return retPack;
+ }
+
+ public async ValueTask> 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;
- if (retPackLen != 3)
- throw new Exception($"RecvDataPackage BodyData Length not Equal to 3: Total {retPackLen} bytes");
+ if (retPackLen != 4)
+ 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;
return ret;
}
+
public async ValueTask> 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> 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> 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> WriteIDCode()
+ public async ValueTask> 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> 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> 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> 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;
}
}
diff --git a/server/src/Router.cs b/server/src/Router.cs
index d8532a9..2b7ea41 100644
--- a/server/src/Router.cs
+++ b/server/src/Router.cs
@@ -1,10 +1,15 @@
using System.Net;
using Common;
-using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Router
{
+ struct Response
+ {
+ public bool IsSuccess;
+ public object? Data;
+ }
+
///
/// Web API
///
@@ -21,8 +26,8 @@ namespace Router
{
var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
var ret = await UDPClientPool.SendStringAsync(endPoint, [text]);
- if (ret) { return Results.Json(true); }
- else { return Results.Json(false); }
+ if (ret) { return Results.Json(new Response() { IsSuccess = true }); }
+ else { return Results.Json(new Response() { IsSuccess = false }); }
}
@@ -46,8 +51,8 @@ namespace Router
var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
var ret = await UDPClientPool.SendAddrPackAsync(endPoint, new WebProtocol.SendAddrPackage(opts));
- if (ret) { return Results.Json(true); }
- else { return Results.Json(false); }
+ if (ret) { return Results.Json(new Response() { IsSuccess = true }); }
+ else { return Results.Json(new Response() { IsSuccess = false }); }
}
public static async ValueTask SendDataPackage(string address, int port, string data)
@@ -55,12 +60,46 @@ namespace Router
var endPoint = new IPEndPoint(IPAddress.Parse(address), port);
var ret = await UDPClientPool.SendDataPackAsync(endPoint,
new WebProtocol.SendDataPackage(NumberProcessor.StringToBytes(data).Value));
- if (ret) { return Results.Json(true); }
- else { return Results.Json(false); }
+ if (ret) { return Results.Json(new Response() { IsSuccess = true }); }
+ else { return Results.Json(new Response() { IsSuccess = false }); }
}
- public static async ValueTask GetDeviceIDCode(string address, int port)
+ public class Jtag
{
+ ///
+ /// 执行一个Jtag命令
+ ///
+ /// 设备地址
+ /// 设备端口
+ /// 16进制设备目的地址(Jtag)
+ /// 16进制命令
+ /// 16进制预期结果
+ /// Response
+ public static async ValueTask 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 }); }
+ }
+
+
+ ///
+ /// 获取Jtag ID Code
+ ///
+ /// 设备地址
+ /// 设备端口
+ /// Response
+ public static async ValueTask 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 }); }
+ }
}
diff --git a/server/src/WebProtocol.cs b/server/src/WebProtocol.cs
index a224724..4c48312 100644
--- a/server/src/WebProtocol.cs
+++ b/server/src/WebProtocol.cs
@@ -49,19 +49,43 @@ namespace WebProtocol
/// 0x10_00_00_00
public UInt32 address;
+ ///
+ /// Convert to Json String
+ ///
+ /// Json String
public override string ToString()
{
return JsonConvert.SerializeObject(this);
}
}
+ /// Package Options which to receive from boards
public struct RecvPackOptions
{
+ ///
+ /// Task ID
+ ///
public byte commandID;
+ ///
+ /// Whether is succeed to finish command
+ ///
public bool isSuccess;
- public byte[] data;
+ ///
+ /// Return Data
+ ///
+ public byte[]? data;
+
+ ///
+ /// Convert to Json String
+ ///
+ /// Json String
+ public override string ToString()
+ {
+ return JsonConvert.SerializeObject(this);
+ }
}
+ /// Package which send address to write
public struct SendAddrPackage
{
readonly byte sign = (byte)PackSign.SendAddr;
@@ -227,6 +251,7 @@ namespace WebProtocol
RecvPackOptions opts;
opts.commandID = commandID;
opts.isSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? true : false);
+ opts.data = null;
return opts;
}