Server: finish jtag controller; Web: finish sibebar animation
This commit is contained in:
@@ -33,9 +33,8 @@ if (app.Environment.IsDevelopment())
|
||||
});
|
||||
}
|
||||
|
||||
// Setup UDP Server
|
||||
var udpServer = new UDPServer(33000);
|
||||
udpServer.Start();
|
||||
// Setup Program
|
||||
MsgBus.Init();
|
||||
|
||||
// Router
|
||||
app.MapGet("/", () => "Hello World!");
|
||||
@@ -46,6 +45,5 @@ app.MapPut("/api/SendDataPackage", Router.API.SendDataPackage);
|
||||
app.Run("http://localhost:5000");
|
||||
|
||||
// Close UDP Server
|
||||
Console.WriteLine("UDP Server is Closing now...");
|
||||
udpServer.Stop();
|
||||
|
||||
Console.WriteLine("Program is Closing now...");
|
||||
MsgBus.Exit();
|
||||
|
@@ -9,6 +9,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="DotNext" Version="5.19.1" />
|
||||
<PackageReference Include="DotNext.Threading" Version="5.19.1" />
|
||||
<PackageReference Include="Microsoft.OpenApi" Version="1.6.23" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="8.1.0" />
|
||||
|
@@ -64,6 +64,21 @@ namespace Common
|
||||
return num;
|
||||
}
|
||||
|
||||
public static Result<byte[]> MultiBitsToBytes(ulong bits1, uint bits1Len, ulong bits2, uint bits2Len)
|
||||
{
|
||||
return NumberToBytes(MultiBitsToNumber(bits1, bits1Len, bits2, bits2Len).Value,
|
||||
(bits1Len + bits2Len) % 8 != 0 ? (bits1Len + bits2Len) / 8 + 1 : (bits1Len + bits2Len) / 8);
|
||||
}
|
||||
|
||||
public static Result<ulong> MultiBitsToNumber(ulong bits1, uint bits1Len, ulong bits2, uint bits2Len)
|
||||
{
|
||||
if (bits1Len + bits2Len > 64) throw new ArgumentException("Two Bits is more than 64 bits");
|
||||
|
||||
ulong num = (bits1 << (int)bits2Len) | bits2;
|
||||
return num;
|
||||
}
|
||||
|
||||
|
||||
public static Result<byte[]> StringToBytes(string str, int numBase = 16)
|
||||
{
|
||||
var len = str.Length;
|
||||
|
@@ -28,6 +28,93 @@ public static class JtagAddr
|
||||
public const UInt32 WRITE_CMD = 0x10_00_00_03;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The Command bits of Jtag
|
||||
/// </summary>
|
||||
public static class JtagCmd
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 旁路指令
|
||||
/// </summary>
|
||||
public const UInt32 JTAG_DR_BYPASS = 0b1111111111;
|
||||
/// <summary>
|
||||
/// 采样指令
|
||||
/// </summary>
|
||||
public const UInt32 JTAG_DR_SAMPLE = 0b1010000000;
|
||||
/// <summary>
|
||||
/// 预装指令
|
||||
/// </summary>
|
||||
public const UInt32 JTAG_DR_PRELOAD = 0b1010000000;
|
||||
/// <summary>
|
||||
/// 外测试指令
|
||||
/// </summary>
|
||||
public const UInt32 JTAG_DR_EXTEST = 0b1010000001;
|
||||
/// <summary>
|
||||
/// 内测试指令
|
||||
/// </summary>
|
||||
public const UInt32 JTAG_DR_INTEST = 0b1010000010;
|
||||
/// <summary>
|
||||
/// 标识指令
|
||||
/// </summary>
|
||||
public const UInt32 JTAG_DR_IDCODE = 0b1010000011;
|
||||
/// <summary>
|
||||
/// 高阻指令
|
||||
/// </summary>
|
||||
public const UInt32 JTAG_DR_HIGHZ = 0b1010000101;
|
||||
/// <summary>
|
||||
/// 复位指令
|
||||
/// </summary>
|
||||
public const UInt32 JTAG_DR_JRST = 0b1010001010;
|
||||
/// <summary>
|
||||
/// 配置指令
|
||||
/// </summary>
|
||||
public const UInt32 JTAG_DR_CFGI = 0b1010001011;
|
||||
/// <summary>
|
||||
/// 回读指令
|
||||
/// </summary>
|
||||
public const UInt32 JTAG_DR_CFGO = 0b1010001100;
|
||||
/// <summary>
|
||||
/// 唤醒指令
|
||||
/// </summary>
|
||||
public const UInt32 JTAG_DR_JWAKEUP = 0b1010001101;
|
||||
/// <summary>
|
||||
/// 读UID指令
|
||||
/// </summary>
|
||||
public const UInt32 JTAG_DR_READ_UID = 0b0101001100;
|
||||
/// <summary>
|
||||
/// 读状态寄存器指令
|
||||
/// </summary>
|
||||
public const UInt32 JTAG_DR_RDSR = 0b0101011001;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 设定JTAG默认状态为TEST_LOGIC_RESET态 (JTAG复位)
|
||||
/// </summary>
|
||||
public const UInt32 CMD_JTAG_CLOSE_TEST = 0b0000;
|
||||
/// <summary>
|
||||
/// 设定JTAG默认状态为RUN_TEST_IDLE态 (JTAG空闲)
|
||||
/// </summary>
|
||||
public const UInt32 CMD_JTAG_RUN_TEST = 0b0001;
|
||||
/// <summary>
|
||||
/// JTAG进入SHIFTIR循环cycle_num次后回到设定的默认状态
|
||||
/// </summary>
|
||||
public const UInt32 CMD_JTAG_LOAD_IR = 0b0010;
|
||||
/// <summary>
|
||||
/// JTAG进入SHIFTDR循环cycle_num次后回到设定的默认状态,同时输入shift_in
|
||||
/// </summary>
|
||||
public const UInt32 CMD_JTAG_LOAD_DR_CAREI = 0b0011;
|
||||
/// <summary>
|
||||
/// JTAG进入SHIFTDR循环cycle_num次后回到设定的默认状态,同时输出shift_out
|
||||
/// </summary>
|
||||
public const UInt32 CMD_JTAG_LOAD_DR_CAREO = 0b0100;
|
||||
/// <summary>
|
||||
/// JTAG进入RUN_TEST_IDLE态循环cycle_num次
|
||||
/// </summary>
|
||||
public const UInt32 CMD_JTAG_IDLE_DELAY = 0b0101;
|
||||
}
|
||||
|
||||
class Jtag
|
||||
{
|
||||
readonly int timeout;
|
||||
@@ -46,32 +133,78 @@ class Jtag
|
||||
this.timeout = outTime;
|
||||
}
|
||||
|
||||
public async ValueTask<Result<bool>> ClearRegisters()
|
||||
public async ValueTask<Result<bool>> RunCommand(uint devAddr, uint cmd, uint exRet)
|
||||
{
|
||||
var ret = true;
|
||||
var ret = false;
|
||||
var opts = new SendAddrPackOptions();
|
||||
|
||||
opts.burstType = BurstType.FixedBurst;
|
||||
opts.burstLength = 4;
|
||||
opts.commandID = 0;
|
||||
opts.address = JtagAddr.STATE;
|
||||
opts.address = devAddr;
|
||||
|
||||
// Write Jtag State Register
|
||||
opts.isWrite = true;
|
||||
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(0xFF_FF_FF_FF, 4).Value));
|
||||
new SendDataPackage(NumberProcessor.NumberToBytes(cmd, 4).Value));
|
||||
if (!ret) throw new Exception("Send Data Package Failed!");
|
||||
|
||||
// Read Jtag State Register
|
||||
opts.address = JtagAddr.STATE;
|
||||
ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
|
||||
if (!ret) throw new Exception("Send 2rd Address Package Failed!");
|
||||
|
||||
// Wait for Ack
|
||||
var data = await UDPServer.
|
||||
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 Current RecvDataPackage!", retPack.Error);
|
||||
|
||||
var retPackLen = retPack.Value.Options.data.Length;
|
||||
if (retPackLen != 3)
|
||||
throw new Exception($"RecvDataPackage BodyData Length not Equal to 3: Total {retPackLen} bytes");
|
||||
|
||||
if (NumberProcessor.BytesToNumber(retPack.Value.Options.data).Value == exRet)
|
||||
ret = true;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public async ValueTask<Result<bool>> ClearAllRegisters()
|
||||
{
|
||||
return await RunCommand(JtagAddr.STATE, 0xFF_FF_FF_FF, 0x00_00_00_00);
|
||||
}
|
||||
|
||||
public async ValueTask<Result<bool>> ClearWriteDataReg()
|
||||
{
|
||||
return await RunCommand(JtagAddr.STATE, 0x00_00_11_00, 0x00_00_00_00);
|
||||
}
|
||||
|
||||
public async ValueTask<Result<bool>> RunTest()
|
||||
{
|
||||
return await RunCommand(JtagAddr.WRITE_CMD, 0x10_00_00_00, 0x01_00_00_00);
|
||||
}
|
||||
|
||||
public async ValueTask<Result<bool>> WriteIDCode()
|
||||
{
|
||||
return await RunCommand(JtagAddr.WRITE_DATA, 0b1010000011, 0x01_00_00_00);
|
||||
}
|
||||
|
||||
public async ValueTask<Result<bool>> LoadIR()
|
||||
{
|
||||
return await RunCommand(JtagAddr.WRITE_CMD, 0x20_00_00_0A, 0x01_00_00_00);
|
||||
}
|
||||
|
||||
}
|
||||
|
22
server/src/MsgBus.cs
Normal file
22
server/src/MsgBus.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
|
||||
public static class MsgBus
|
||||
{
|
||||
private static readonly UDPServer udpServer = new UDPServer(33000);
|
||||
public static UDPServer UDPServer { get { return udpServer; } }
|
||||
|
||||
private static bool isRunning = false;
|
||||
public static bool IsRunning { get { return isRunning; } }
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
udpServer.Start();
|
||||
isRunning = true;
|
||||
}
|
||||
|
||||
public static void Exit()
|
||||
{
|
||||
udpServer.Stop();
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
@@ -2,6 +2,7 @@ using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using DotNext;
|
||||
using DotNext.Threading;
|
||||
|
||||
public struct UDPData
|
||||
{
|
||||
@@ -20,7 +21,7 @@ public class UDPServer
|
||||
private UdpClient listener;
|
||||
private IPEndPoint groupEP;
|
||||
private Dictionary<string, List<UDPData>> udpData = new Dictionary<string, List<UDPData>>();
|
||||
private Mutex mutUdpData = new Mutex();
|
||||
private AsyncReaderWriterLock udpDataLock = new AsyncReaderWriterLock(1);
|
||||
|
||||
/// <summary>
|
||||
/// Construct a udp server with fixed port
|
||||
@@ -50,32 +51,21 @@ public class UDPServer
|
||||
/// Find UDP Receive Data According to ip address
|
||||
/// </summary>
|
||||
/// <param name="ipAddr"> IP Address</param>
|
||||
/// <param name="rwTimeout"> Read and Write Wait for Milliseconds </param>
|
||||
/// <returns>UDP Data</returns>
|
||||
public Optional<UDPData> FindData(string ipAddr)
|
||||
public Optional<UDPData> FindData(string ipAddr, int rwTimeout = 1000)
|
||||
{
|
||||
UDPData? data = null;
|
||||
try
|
||||
using (udpDataLock.AcquireWriteLock(TimeSpan.FromMilliseconds(rwTimeout)))
|
||||
{
|
||||
var isOverTime = !mutUdpData.WaitOne(1000);
|
||||
if (isOverTime) return Optional.None<UDPData>();
|
||||
// Get
|
||||
var listData = udpData[ipAddr];
|
||||
data = listData[0];
|
||||
|
||||
// Delete
|
||||
listData.RemoveAt(0);
|
||||
}
|
||||
catch
|
||||
{
|
||||
data = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
mutUdpData.ReleaseMutex();
|
||||
if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0)
|
||||
{
|
||||
data = udpData[ipAddr][0];
|
||||
udpData[ipAddr].RemoveAt(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Return
|
||||
if (data is null)
|
||||
if (data == null)
|
||||
{
|
||||
return Optional.None<UDPData>();
|
||||
}
|
||||
@@ -93,35 +83,24 @@ public class UDPServer
|
||||
/// <returns>[TODO:return]</returns>
|
||||
public async ValueTask<Optional<UDPData>> FindDataAsync(string ipAddr, int timeout = 1000)
|
||||
{
|
||||
var time = 0;
|
||||
UDPData? data = null;
|
||||
while (time < timeout)
|
||||
using (await udpDataLock.AcquireWriteLockAsync(TimeSpan.FromMilliseconds(1000)))
|
||||
{
|
||||
await Task.Delay(1);
|
||||
try
|
||||
if (udpData.ContainsKey(ipAddr) && udpData[ipAddr].Count > 0)
|
||||
{
|
||||
var isOverTime = !mutUdpData.WaitOne(timeout - time);
|
||||
if (isOverTime) break;
|
||||
// Get
|
||||
var listData = udpData[ipAddr];
|
||||
data = listData[0];
|
||||
|
||||
// Delete
|
||||
listData.RemoveAt(0);
|
||||
data = udpData[ipAddr][0];
|
||||
udpData[ipAddr].RemoveAt(0);
|
||||
}
|
||||
catch
|
||||
{
|
||||
data = null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
mutUdpData.ReleaseMutex();
|
||||
}
|
||||
if (data is null) continue;
|
||||
else break;
|
||||
}
|
||||
if ((time >= timeout) || (data is null)) { return Optional.None<UDPData>(); }
|
||||
else { return Optional.Some((UDPData)data); }
|
||||
|
||||
if (data == null)
|
||||
{
|
||||
return Optional.None<UDPData>();
|
||||
}
|
||||
else
|
||||
{
|
||||
return Optional.Some((UDPData)data);
|
||||
}
|
||||
}
|
||||
|
||||
private void ReceiveHandler(IAsyncResult res)
|
||||
@@ -131,7 +110,7 @@ public class UDPServer
|
||||
var nowtime = DateTime.Now;
|
||||
|
||||
// Handle RemoteEP
|
||||
string remoteStr;
|
||||
string remoteStr = "Unknown";
|
||||
if (remoteEP is not null)
|
||||
{
|
||||
var remoteAddress = remoteEP.Address.ToString();
|
||||
@@ -160,14 +139,10 @@ public class UDPServer
|
||||
|
||||
remoteStr = $"{remoteAddress}:{remotePort}";
|
||||
}
|
||||
else
|
||||
{
|
||||
remoteStr = "Unknown";
|
||||
}
|
||||
|
||||
// Handle Package
|
||||
var sign = bytes[0];
|
||||
string recvData;
|
||||
string recvData = "";
|
||||
if (sign == (byte)WebProtocol.PackSign.SendAddr)
|
||||
{
|
||||
var resData = WebProtocol.SendAddrPackage.FromBytes(bytes);
|
||||
@@ -176,18 +151,9 @@ public class UDPServer
|
||||
else
|
||||
recvData = resData.Error.ToString();
|
||||
}
|
||||
else if (sign == (byte)WebProtocol.PackSign.SendData)
|
||||
{
|
||||
recvData = "";
|
||||
}
|
||||
else if (sign == (byte)WebProtocol.PackSign.RecvData)
|
||||
{
|
||||
recvData = "";
|
||||
}
|
||||
else if (sign == (byte)WebProtocol.PackSign.RecvResp)
|
||||
{
|
||||
recvData = "";
|
||||
}
|
||||
else if (sign == (byte)WebProtocol.PackSign.SendData) { }
|
||||
else if (sign == (byte)WebProtocol.PackSign.RecvData) { }
|
||||
else if (sign == (byte)WebProtocol.PackSign.RecvResp) { }
|
||||
else
|
||||
{
|
||||
recvData = Encoding.ASCII.GetString(bytes, 0, bytes.Length);
|
||||
|
@@ -59,6 +59,7 @@ namespace WebProtocol
|
||||
{
|
||||
public byte commandID;
|
||||
public bool isSuccess;
|
||||
public byte[] data;
|
||||
}
|
||||
|
||||
public struct SendAddrPackage
|
||||
@@ -184,13 +185,27 @@ namespace WebProtocol
|
||||
this.bodyData = bodyData;
|
||||
}
|
||||
|
||||
public RecvPackOptions Options()
|
||||
public RecvPackOptions Options
|
||||
{
|
||||
RecvPackOptions opts;
|
||||
opts.commandID = commandID;
|
||||
opts.isSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? true : false);
|
||||
get
|
||||
{
|
||||
RecvPackOptions opts;
|
||||
opts.commandID = commandID;
|
||||
opts.isSuccess = Convert.ToBoolean((resp >> 1) == 0b01 ? true : false);
|
||||
opts.data = bodyData;
|
||||
|
||||
return opts;
|
||||
return opts;
|
||||
}
|
||||
}
|
||||
|
||||
public static Result<RecvDataPackage> FromBytes(byte[] bytes)
|
||||
{
|
||||
if (bytes[0] != (byte)PackSign.RecvData)
|
||||
throw new ArgumentException(
|
||||
"The sign of bytes is not RecvData Package!",
|
||||
nameof(bytes)
|
||||
);
|
||||
return new RecvDataPackage(bytes[1], bytes[2], bytes[4..]);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user