|
|
|
@@ -61,11 +61,11 @@ static class Global
|
|
|
|
|
/// </summary>
|
|
|
|
|
public const UInt32 ReadSign = 0x2000_0006;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 单独擦除开关-读写地址——控制位
|
|
|
|
|
/// [31:24]: {-, -, -, -, -, -, -, - }
|
|
|
|
|
/// [23:17]: {-, -, -, -, -, -, -, - }
|
|
|
|
|
/// [16: 8]: {-, -, -, -, -, -, -, - }
|
|
|
|
|
/// [ 7: 0]: {-, -, -, -, -, -, -, clear_sw_en}
|
|
|
|
|
/// 单独擦除开关-读写地址——控制位 <br/>
|
|
|
|
|
/// [31:24]: {-, -, -, -, -, -, -, - } <br/>
|
|
|
|
|
/// [23:17]: {-, -, -, -, -, -, -, - } <br/>
|
|
|
|
|
/// [16: 8]: {-, -, -, -, -, -, -, - } <br/>
|
|
|
|
|
/// [ 7: 0]: {-, -, -, -, -, -, -, clear_sw_en} <br/>
|
|
|
|
|
/// </summary>
|
|
|
|
|
public const UInt32 ClearCtrl = 0x2000_0007;
|
|
|
|
|
/// <summary>
|
|
|
|
@@ -77,29 +77,29 @@ static class Global
|
|
|
|
|
/// </summary>
|
|
|
|
|
public const UInt32 ClearSign = 0x2000_0008;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 写开关-读写地址——标志位
|
|
|
|
|
/// [31:24]: {-, -, -, -, -, -, -, - }
|
|
|
|
|
/// [23:17]: {-, -, -, -, -, -, -, - }
|
|
|
|
|
/// [16: 8]: {-, -, -, -, -, -, { open_sw_num}}
|
|
|
|
|
/// [ 7: 0]: {-, -, -, -, -, -, -, write_sw_code_en}
|
|
|
|
|
/// 写开关-读写地址——控制位 <br/>
|
|
|
|
|
/// [31:24]: {-, -, -, -, -, -, -, - } <br/>
|
|
|
|
|
/// [23:17]: {-, -, -, -, -, -, -, - } <br/>
|
|
|
|
|
/// [16: 8]: {-, -, -, -, -, -, { open_sw_num}} <br/>
|
|
|
|
|
/// [ 7: 0]: {-, -, -, -, -, -, -, write_sw_code_en} <br/>
|
|
|
|
|
/// </summary>
|
|
|
|
|
public const UInt32 WriteSwitchSign = 0x2000_0009;
|
|
|
|
|
public const UInt32 WriteSwitchCtrl = 0x2000_0009;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 写开关-只读地址——控制位
|
|
|
|
|
/// [31:24]: {-, -, -, -, -, -, -, - }
|
|
|
|
|
/// [23:17]: {-, -, -, -, -, -, -, - }
|
|
|
|
|
/// [16: 8]: {-, -, -, -, -, -, -, ipal_busy}
|
|
|
|
|
/// [ 7: 0]: {-, -, -, -, -, -, -, open_sw_code_done}
|
|
|
|
|
/// 写开关-只读地址——标志位 <br/>
|
|
|
|
|
/// [31:24]: {-, -, -, -, -, -, -, - } <br/>
|
|
|
|
|
/// [23:17]: {-, -, -, -, -, -, -, - } <br/>
|
|
|
|
|
/// [16: 8]: {-, -, -, -, -, -, -, ipal_busy} <br/>
|
|
|
|
|
/// [ 7: 0]: {-, -, -, -, -, -, -, open_sw_code_done} <br/>
|
|
|
|
|
/// </summary>
|
|
|
|
|
public const UInt32 WriteSwitchCtrl = 0x2000_0010;
|
|
|
|
|
public const UInt32 WriteSwitchSign = 0x2000_000A;
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// 热启动开关-读写地址——控制位
|
|
|
|
|
/// [31:24]: {-, -, -, -, -, -, -, - }
|
|
|
|
|
/// [23:17]: {-, -, -, -, -, -, -, - }
|
|
|
|
|
/// [16: 8]: {-, -, -, -, -, -, }
|
|
|
|
|
/// [ 7: 0]: {-, -, -, -, -, -, -, hotreset_en}
|
|
|
|
|
/// 热启动开关-读写地址——控制位 <br/>
|
|
|
|
|
/// [31:24]: {-, -, -, -, -, -, -, - } <br/>
|
|
|
|
|
/// [23:17]: {-, -, -, -, -, -, -, - } <br/>
|
|
|
|
|
/// [16: 8]: {-, -, -, -, -, -, } <br/>
|
|
|
|
|
/// [ 7: 0]: {-, -, -, -, -, -, -, hotreset_en} <br/>
|
|
|
|
|
/// </summary>
|
|
|
|
|
public const UInt32 HotResetCtrl = 0x2000_0011;
|
|
|
|
|
public const UInt32 HotResetCtrl = 0x2000_000B;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
@@ -130,11 +130,11 @@ public class RemoteUpdater
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// [TODO:description]
|
|
|
|
|
/// Writes a bitstream to the FPGA device.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="bitstreamNum">[TODO:parameter]</param>
|
|
|
|
|
/// <param name="bitstream">[TODO:parameter]</param>
|
|
|
|
|
/// <returns>[TODO:return]</returns>
|
|
|
|
|
/// <param name="bitstreamNum">The bitstream number (0-3).</param>
|
|
|
|
|
/// <param name="bitstream">The bitstream data to write.</param>
|
|
|
|
|
/// <returns>A result indicating success or failure.</returns>
|
|
|
|
|
public async ValueTask<Result<bool>> WriteBitstream(int bitstreamNum, byte[] bitstream)
|
|
|
|
|
{
|
|
|
|
|
if (bitstreamNum < 0 || bitstreamNum > 0b11)
|
|
|
|
@@ -165,7 +165,7 @@ public class RemoteUpdater
|
|
|
|
|
// }
|
|
|
|
|
{
|
|
|
|
|
var ret = await UDPClientPool.ReadAddrWithWait(
|
|
|
|
|
this.remoteEP, Global.RemoteUpdaterAddr.WriteSign, 0x00_01, 0x00_01, 60 * 1000);
|
|
|
|
|
this.remoteEP, Global.RemoteUpdaterAddr.WriteSign, 0x00_00_00_01, 0x00_00_00_01, 60 * 1000);
|
|
|
|
|
if (!ret.IsSuccessful) return new(ret.Error);
|
|
|
|
|
if (!ret.Value) return new(new Exception("Clear bitstream failed even over time"));
|
|
|
|
|
}
|
|
|
|
@@ -178,7 +178,7 @@ public class RemoteUpdater
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
var ret = await UDPClientPool.ReadAddrWithWait(
|
|
|
|
|
this.remoteEP, Global.RemoteUpdaterAddr.WriteSign, 0x00_10, 0x00_10, timeout);
|
|
|
|
|
this.remoteEP, Global.RemoteUpdaterAddr.WriteSign, 0x00_00_01_00, 0x00_00_01_00, timeout);
|
|
|
|
|
if (!ret.IsSuccessful) return new(ret.Error);
|
|
|
|
|
if (!ret.Value) return new(new Exception("Write bitstream failed even over time"));
|
|
|
|
|
}
|
|
|
|
@@ -188,11 +188,11 @@ public class RemoteUpdater
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// [TODO:description]
|
|
|
|
|
/// Checks the CRC of a bitstream on the FPGA device.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="bitstreamNum">[TODO:parameter]</param>
|
|
|
|
|
/// <param name="checkSum">[TODO:parameter]</param>
|
|
|
|
|
/// <returns>[TODO:return]</returns>
|
|
|
|
|
/// <param name="bitstreamNum">The bitstream number (0-3).</param>
|
|
|
|
|
/// <param name="checkSum">The expected CRC checksum value.</param>
|
|
|
|
|
/// <returns>A result indicating whether the CRC matches.</returns>
|
|
|
|
|
public async ValueTask<Result<bool>> CheckBitstreamCRC(int bitstreamNum, UInt32 checkSum)
|
|
|
|
|
{
|
|
|
|
|
// Clear Data
|
|
|
|
@@ -210,7 +210,7 @@ public class RemoteUpdater
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
var ret = await UDPClientPool.ReadAddrWithWait(
|
|
|
|
|
this.remoteEP, Global.RemoteUpdaterAddr.ReadSign, 0x00_11, 0x00_11, 60 * 1000);
|
|
|
|
|
this.remoteEP, Global.RemoteUpdaterAddr.ReadSign, 0x00_00_01_00, 0x00_00_01_00, 60 * 1000);
|
|
|
|
|
if (!ret.IsSuccessful) return new(ret.Error);
|
|
|
|
|
if (!ret.Value) return new(new Exception("Read bitstream failed even over time"));
|
|
|
|
|
}
|
|
|
|
@@ -218,7 +218,7 @@ public class RemoteUpdater
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
var ret = await UDPClientPool.ReadAddr(
|
|
|
|
|
this.remoteEP, Global.RemoteUpdaterAddr.ReadSign, timeout);
|
|
|
|
|
this.remoteEP, Global.RemoteUpdaterAddr.ReadCRC, timeout);
|
|
|
|
|
if (!ret.IsSuccessful) return new(ret.Error);
|
|
|
|
|
if (ret.Value.Options.Data is null) return new(new Exception("Receive null when read sign"));
|
|
|
|
|
|
|
|
|
@@ -229,6 +229,8 @@ public class RemoteUpdater
|
|
|
|
|
var retCRC = crcCode.Value == checkSum;
|
|
|
|
|
logger.Trace($"Device {this.address} remote update check crc finished");
|
|
|
|
|
|
|
|
|
|
logger.Debug($"Expected CRC32/Mpeg Code: 0x{checkSum.ToString("X").PadLeft(8, '0')}");
|
|
|
|
|
logger.Debug($"Actually CRC32/Mpeg Code: 0x{crcCode.Value.ToString("X").PadLeft(8, '0')}");
|
|
|
|
|
return retCRC;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -237,8 +239,60 @@ public class RemoteUpdater
|
|
|
|
|
/// [TODO:description]
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="bitstreamNum">[TODO:parameter]</param>
|
|
|
|
|
/// <param name="bitstream">[TODO:parameter]</param>
|
|
|
|
|
/// <returns>[TODO:return]</returns>
|
|
|
|
|
public async ValueTask<Result<bool>> HotReset(int bitstreamNum)
|
|
|
|
|
{
|
|
|
|
|
// Clear Data
|
|
|
|
|
await MsgBus.UDPServer.ClearUDPData(this.address);
|
|
|
|
|
|
|
|
|
|
logger.Trace($"Clear up udp server {this.address} receive data");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
var ret = await UDPClientPool.WriteAddr(
|
|
|
|
|
this.remoteEP, Global.RemoteUpdaterAddr.ClearCtrl,
|
|
|
|
|
(UInt32)(0b1), timeout);
|
|
|
|
|
if (!ret.IsSuccessful) return new(ret.Error);
|
|
|
|
|
if (!ret.Value) return new(new Exception("Run clear failed"));
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
var ret = await UDPClientPool.ReadAddrWithWait(
|
|
|
|
|
this.remoteEP, Global.RemoteUpdaterAddr.ClearSign, 0x00_00_00_01, 0x00_00_00_01, 60 * 1000);
|
|
|
|
|
if (!ret.IsSuccessful) return new(ret.Error);
|
|
|
|
|
if (!ret.Value) return new(new Exception("Clear failed even over time"));
|
|
|
|
|
}
|
|
|
|
|
logger.Trace($"Device {this.address} remote update clear finished");
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
var ret = await UDPClientPool.WriteAddr(
|
|
|
|
|
this.remoteEP, Global.RemoteUpdaterAddr.WriteSwitchCtrl,
|
|
|
|
|
(UInt32)((bitstreamNum << 1) | 0b1), timeout);
|
|
|
|
|
if (!ret.IsSuccessful) return new(ret.Error);
|
|
|
|
|
if (!ret.Value) return new(new Exception("Run write switch code failed"));
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
var ret = await UDPClientPool.ReadAddrWithWait(
|
|
|
|
|
this.remoteEP, Global.RemoteUpdaterAddr.WriteSwitchSign,
|
|
|
|
|
0x00_00_00_01, 0x00_00_00_01, 60 * 1000);
|
|
|
|
|
if (!ret.IsSuccessful) return new(ret.Error);
|
|
|
|
|
if (!ret.Value) return new(new Exception("Write switch code failed even over time"));
|
|
|
|
|
}
|
|
|
|
|
logger.Trace($"Device {this.address} remote update write switch open finished");
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
var ret = await UDPClientPool.WriteAddr(
|
|
|
|
|
this.remoteEP, Global.RemoteUpdaterAddr.HotResetCtrl, (UInt32)(0b1), timeout);
|
|
|
|
|
if (!ret.IsSuccessful) return new(ret.Error);
|
|
|
|
|
return ret.Value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Updates the bitstream on the FPGA device.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="bitstreamNum">The bitstream number (0-3).</param>
|
|
|
|
|
/// <param name="bitstream">The bitstream data to update.</param>
|
|
|
|
|
/// <returns>A result indicating success or failure.</returns>
|
|
|
|
|
public async ValueTask<Result<bool>> UpdateBitstream(int bitstreamNum, byte[] bitstream)
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
@@ -247,11 +301,17 @@ public class RemoteUpdater
|
|
|
|
|
if (!ret.Value) return new(new Exception("Write bitstream failed"));
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
var crc = new System.IO.Hashing.Crc32();
|
|
|
|
|
crc.Append(bitstream);
|
|
|
|
|
var ret = await CheckBitstreamCRC(bitstreamNum, crc.GetCurrentHashAsUInt32());
|
|
|
|
|
if (!ret.IsSuccessful) return new(ret.Error);
|
|
|
|
|
var crc = Honoo.IO.Hashing.Crc.Create(Honoo.IO.Hashing.CrcName.CRC32_MPEG_2);
|
|
|
|
|
var checkSum = crc.ComputeFinal(bitstream);
|
|
|
|
|
|
|
|
|
|
var ret = await CheckBitstreamCRC(bitstreamNum, checkSum.ToUInt32());
|
|
|
|
|
if (!ret.IsSuccessful) return new(ret.Error);
|
|
|
|
|
// if (!ret.Value) return new(new Exception("Check bitstream crc32/mpeg-2 failed"));
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
var ret = await HotReset(bitstreamNum);
|
|
|
|
|
if (!ret.IsSuccessful) return new(ret.Error);
|
|
|
|
|
if (!ret.Value) return new(new Exception("Hot reset failed"));
|
|
|
|
|
return ret.Value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|