|
|
|
@@ -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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|