add remote update but not finished
This commit is contained in:
parent
42ddd0fcdb
commit
f35a295af2
|
@ -0,0 +1,166 @@
|
|||
using System.Net;
|
||||
using DotNext;
|
||||
namespace RemoteUpdate;
|
||||
|
||||
static class Global
|
||||
{
|
||||
/// <summary>
|
||||
/// FPGA 远程更新器地址
|
||||
/// </summary>
|
||||
public class RemoteUpdaterAddr
|
||||
{
|
||||
/// <summary>
|
||||
/// 基地址
|
||||
/// </summary>
|
||||
public const UInt32 BaseAddr = 0x3000_0000;
|
||||
/// <summary>
|
||||
/// 写比特流-读写地址——控制位
|
||||
/// [31:24]: 保留
|
||||
/// [23:17]: 保留
|
||||
/// [16: 8]: 保留
|
||||
/// [ 7: 0]: {-, -, -, -, -,{bitstream_wr_num}, flash_wr_en}
|
||||
/// </summary>
|
||||
public const UInt32 WriteCtrl = 0x3000_0000;
|
||||
/// <summary>
|
||||
/// 写比特流-只写地址——FIFO入口
|
||||
/// [31:0]: 写比特流数据入口
|
||||
/// </summary>
|
||||
public const UInt32 WriteFIFO = 0x3000_0001;
|
||||
/// <summary>
|
||||
/// 写比特流-只读地址——标志位
|
||||
/// [31:24]: {-, -, -, -, -, -, -, wr_fifo_full}
|
||||
/// [23:17]: {-, -, -, -, -, -, -, wr_fifo_empty}
|
||||
/// [16: 8]: {-, -, -, -, -, -, -, bitstream_wr_done}
|
||||
/// [ 7: 0]: {-, -, -, -, -, -, -, clear_bs_done}
|
||||
/// </summary>
|
||||
public const UInt32 WriteSign = 0x3000_0002;
|
||||
/// <summary>
|
||||
/// 读比特流-读写地址——控制位
|
||||
/// [31:24]: {-, -, -, -, -, -,{ bs_crc32_ok }}
|
||||
/// [23:17]: {-, -, -, -, -, -, -, crc_check_en}
|
||||
/// [16: 8]: {-, -, -, -, -, -, -, bitstream_up2cpu_en}
|
||||
/// [ 7: 0]: {-, -, -, -, -,{bitstream_rd_num},flash_rd_en}
|
||||
/// </summary>
|
||||
public const UInt32 ReadCtrl = 0x3000_0003;
|
||||
/// <summary>
|
||||
/// 读比特流-只读地址——FIFO出口
|
||||
/// [31:0]: 读比特流数据出口
|
||||
/// </summary>
|
||||
public const UInt32 ReadFIFO = 0x3000_0004;
|
||||
/// <summary>
|
||||
/// 读比特流-只读地址——CRC校验值
|
||||
/// [31:0]: CRC校验值 bs_readback_crc
|
||||
/// </summary>
|
||||
public const UInt32 ReadCRC = 0x3000_0005;
|
||||
/// <summary>
|
||||
/// 读比特流-只读地址——标志位
|
||||
/// [31:24]: {-, -, -, -, -, -, -, rd_fifo_afull}
|
||||
/// [23:17]: {-, -, -, -, -, -, -, rd_fifo_empty}
|
||||
/// [16: 8]: {-, -, -, -, -, -, -, bitstream_rd_done}
|
||||
/// [ 7: 0]: {-, -, -, -, -, -, -, bs_readback_crc_valid}
|
||||
/// </summary>
|
||||
public const UInt32 ReadSign = 0x3000_0006;
|
||||
/// <summary>
|
||||
/// 单独擦除开关-读写地址——控制位
|
||||
/// [31:24]: {-, -, -, -, -, -, -, - }
|
||||
/// [23:17]: {-, -, -, -, -, -, -, - }
|
||||
/// [16: 8]: {-, -, -, -, -, -, -, - }
|
||||
/// [ 7: 0]: {-, -, -, -, -, -, -, clear_sw_en}
|
||||
/// </summary>
|
||||
public const UInt32 ClearCtrl = 0x3000_0007;
|
||||
/// <summary>
|
||||
/// 单独擦除开关-只读地址——标志位
|
||||
/// [31:24]: {-, -, -, -, -, -, -, time_out_reg}
|
||||
/// [23:17]: { flash_flag_status[15:8]}
|
||||
/// [16: 8]: { flash_flag_status[7:0]}
|
||||
/// [ 7: 0]: {-, -, -, -, -, -, -, clear_sw_done}
|
||||
/// </summary>
|
||||
public const UInt32 ClearSign = 0x3000_0008;
|
||||
/// <summary>
|
||||
/// 写开关-读写地址——标志位
|
||||
/// [31:24]: {-, -, -, -, -, -, -, - }
|
||||
/// [23:17]: {-, -, -, -, -, -, -, - }
|
||||
/// [16: 8]: {-, -, -, -, -, -, { open_sw_num}}
|
||||
/// [ 7: 0]: {-, -, -, -, -, -, -, write_sw_code_en}
|
||||
/// </summary>
|
||||
public const UInt32 WriteSwitchSign = 0x3000_0009;
|
||||
/// <summary>
|
||||
/// 写开关-只读地址——控制位
|
||||
/// [31:24]: {-, -, -, -, -, -, -, - }
|
||||
/// [23:17]: {-, -, -, -, -, -, -, - }
|
||||
/// [16: 8]: {-, -, -, -, -, -, -, ipal_busy}
|
||||
/// [ 7: 0]: {-, -, -, -, -, -, -, open_sw_code_done}
|
||||
/// </summary>
|
||||
public const UInt32 WriteSwitchCtrl = 0x3000_0010;
|
||||
/// <summary>
|
||||
/// 热启动开关-读写地址——控制位
|
||||
/// [31:24]: {-, -, -, -, -, -, -, - }
|
||||
/// [23:17]: {-, -, -, -, -, -, -, - }
|
||||
/// [16: 8]: {-, -, -, -, -, -, }
|
||||
/// [ 7: 0]: {-, -, -, -, -, -, -, hotreset_en}
|
||||
/// </summary>
|
||||
public const UInt32 HotResetCtrl = 0x3000_0011;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// FPGA远程更新
|
||||
/// </summary>
|
||||
public class RemoteUpdater
|
||||
{
|
||||
private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||
|
||||
const int timeout = 1000;
|
||||
|
||||
int port { get; }
|
||||
string address { get; }
|
||||
private IPEndPoint remoteEP;
|
||||
|
||||
/// <summary>
|
||||
/// 初始化 FPGA 远程更新器
|
||||
/// </summary>
|
||||
/// <param name="address">目标设备的 IP 地址</param>
|
||||
/// <param name="port">目标设备的端口号</param>
|
||||
public RemoteUpdater(string address, int port)
|
||||
{
|
||||
this.address = address;
|
||||
this.port = port;
|
||||
this.remoteEP = new IPEndPoint(IPAddress.Parse(address), port);
|
||||
}
|
||||
|
||||
public async ValueTask<Result<bool>> UpdateBitstream(int bitstreamNum, byte[] bitstream)
|
||||
{
|
||||
if (bitstreamNum < 0 || bitstreamNum > 0b11)
|
||||
return new(new ArgumentException(
|
||||
"The number of bitstream can't be negative or over 3(0b11)", nameof(bitstreamNum)));
|
||||
|
||||
if (bitstream.Length % (4 * 1024) != 0)
|
||||
return new(new ArgumentException(
|
||||
"Bitstream doesn't match 4KB align, which should be divided by 4 * 1024", nameof(bitstream)));
|
||||
|
||||
// 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.WriteCtrl, (UInt32)((bitstreamNum << 1) | 0b1), timeout);
|
||||
if (!ret.IsSuccessful) return new(ret.Error);
|
||||
else if (!ret.Value) return new(new Exception("Enable write flash failed"));
|
||||
}
|
||||
|
||||
{
|
||||
var ret = await UDPClientPool.ReadAddr(
|
||||
this.remoteEP, Global.RemoteUpdaterAddr.ClearSign, timeout);
|
||||
if (!ret.IsSuccessful) return new(ret.Error);
|
||||
else if (!ret.Value.IsSuccessful) return new(new Exception("Read clear switch sign failed"));
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text;
|
||||
using DotNext;
|
||||
using WebProtocol;
|
||||
|
||||
/// <summary>
|
||||
/// UDP客户端发送池
|
||||
|
@ -161,4 +163,90 @@ public class UDPClientPool
|
|||
|
||||
return isSuccessful;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// [TODO:description]
|
||||
/// </summary>
|
||||
/// <param name="endPoint">[TODO:parameter]</param>
|
||||
/// <param name="devAddr">[TODO:parameter]</param>
|
||||
/// <param name="timeout">[TODO:parameter]</param>
|
||||
/// <returns>[TODO:return]</returns>
|
||||
public static async ValueTask<Result<RecvDataPackage>> ReadAddr(
|
||||
IPEndPoint endPoint, uint devAddr, int timeout = 1000)
|
||||
{
|
||||
var ret = false;
|
||||
var opts = new SendAddrPackOptions();
|
||||
|
||||
opts.BurstType = BurstType.FixedBurst;
|
||||
opts.BurstLength = 0;
|
||||
opts.CommandID = 0;
|
||||
opts.Address = devAddr;
|
||||
|
||||
// Read Jtag State Register
|
||||
opts.IsWrite = false;
|
||||
ret = await UDPClientPool.SendAddrPackAsync(endPoint, new SendAddrPackage(opts));
|
||||
if (!ret) return new(new Exception("Send Address Package Failed!"));
|
||||
|
||||
// Wait for Read Ack
|
||||
if (!MsgBus.IsRunning)
|
||||
return new(new Exception("Message Bus not Working!"));
|
||||
|
||||
var retPack = await MsgBus.UDPServer.WaitForDataAsync(
|
||||
endPoint.Address.ToString(), endPoint.Port, timeout);
|
||||
if (!retPack.IsSuccessful) return new(retPack.Error);
|
||||
else if (!retPack.Value.IsSuccessful)
|
||||
return new(new Exception("Send address package failed"));
|
||||
|
||||
var retPackOpts = retPack.Value.Options;
|
||||
if (retPackOpts.Data is null)
|
||||
return new(new Exception($"Data is Null, package: {retPackOpts.ToString()}"));
|
||||
|
||||
return retPack;
|
||||
}
|
||||
|
||||
public static async ValueTask<Result<RecvDataPackage>> ReadAddrWithCheck(
|
||||
IPEndPoint endPoint, uint devAddr, int timeout = 1000)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// [TODO:description]
|
||||
/// </summary>
|
||||
/// <param name="endPoint">[TODO:parameter]</param>
|
||||
/// <param name="devAddr">[TODO:parameter]</param>
|
||||
/// <param name="data">[TODO:parameter]</param>
|
||||
/// <param name="timeout">[TODO:parameter]</param>
|
||||
/// <returns>[TODO:return]</returns>
|
||||
public static async ValueTask<Result<bool>> WriteAddr(
|
||||
IPEndPoint endPoint, UInt32 devAddr, UInt32 data, int timeout = 1000)
|
||||
{
|
||||
var ret = false;
|
||||
var opts = new SendAddrPackOptions();
|
||||
|
||||
opts.BurstType = BurstType.FixedBurst;
|
||||
opts.BurstLength = 0;
|
||||
opts.CommandID = 0;
|
||||
opts.Address = devAddr;
|
||||
|
||||
// Write Jtag State Register
|
||||
opts.IsWrite = true;
|
||||
ret = await UDPClientPool.SendAddrPackAsync(endPoint, new SendAddrPackage(opts));
|
||||
if (!ret) return new(new Exception("Send 1st address package failed!"));
|
||||
// Send Data Package
|
||||
ret = await UDPClientPool.SendDataPackAsync(endPoint,
|
||||
new SendDataPackage(Common.Number.NumberToBytes(data, 4).Value));
|
||||
if (!ret) return new(new Exception("Send data package failed!"));
|
||||
|
||||
// Check Msg Bus
|
||||
if (!MsgBus.IsRunning)
|
||||
return new(new Exception("Message bus not working!"));
|
||||
|
||||
// Wait for Write Ack
|
||||
var udpWriteAck = await MsgBus.UDPServer.WaitForAckAsync(
|
||||
endPoint.Address.ToString(), endPoint.Port, timeout);
|
||||
if (!udpWriteAck.IsSuccessful) return new(udpWriteAck.Error);
|
||||
|
||||
return udpWriteAck.Value.IsSuccessful;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue