Merge branch 'csharp'
This commit is contained in:
		@@ -3,6 +3,12 @@
 | 
			
		||||
  pwd
 | 
			
		||||
  echo
 | 
			
		||||
 | 
			
		||||
clean: 
 | 
			
		||||
  rm -rf "server/bin"
 | 
			
		||||
  rm -rf "server/obj"
 | 
			
		||||
  rm -rf "server.test/bin"
 | 
			
		||||
  rm -rf "server.test/obj"
 | 
			
		||||
 | 
			
		||||
[working-directory: "server"]
 | 
			
		||||
publish: _show-dir
 | 
			
		||||
  dotnet publish --self-contained false -t:PublishAllRids
 | 
			
		||||
 
 | 
			
		||||
@@ -18,10 +18,10 @@ namespace Common
 | 
			
		||||
        {
 | 
			
		||||
            if (length > 8)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentException(
 | 
			
		||||
                return new(new ArgumentException(
 | 
			
		||||
                    "Unsigned long number can't over 8 bytes(64 bits).",
 | 
			
		||||
                    nameof(length)
 | 
			
		||||
                );
 | 
			
		||||
                ));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var arr = new byte[length];
 | 
			
		||||
@@ -53,10 +53,10 @@ namespace Common
 | 
			
		||||
        {
 | 
			
		||||
            if (bytes.Length > 8)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentException(
 | 
			
		||||
                return new(new ArgumentException(
 | 
			
		||||
                    "Unsigned long number can't over 8 bytes(64 bits).",
 | 
			
		||||
                    nameof(bytes)
 | 
			
		||||
                );
 | 
			
		||||
                ));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            ulong num = 0;
 | 
			
		||||
@@ -106,7 +106,7 @@ namespace Common
 | 
			
		||||
        /// <returns>[TODO:return]</returns>
 | 
			
		||||
        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");
 | 
			
		||||
            if (bits1Len + bits2Len > 64) return new(new ArgumentException("Two Bits is more than 64 bits"));
 | 
			
		||||
 | 
			
		||||
            ulong num = (bits1 << Convert.ToInt32(bits2Len)) | bits2;
 | 
			
		||||
            return num;
 | 
			
		||||
@@ -122,7 +122,7 @@ namespace Common
 | 
			
		||||
        /// <returns>[TODO:return]</returns>
 | 
			
		||||
        public static Result<uint> MultiBitsToNumber(uint bits1, uint bits1Len, uint bits2, uint bits2Len)
 | 
			
		||||
        {
 | 
			
		||||
            if (bits1Len + bits2Len > 64) throw new ArgumentException("Two Bits is more than 64 bits");
 | 
			
		||||
            if (bits1Len + bits2Len > 64) return new(new ArgumentException("Two Bits is more than 64 bits"));
 | 
			
		||||
 | 
			
		||||
            uint num = (bits1 << Convert.ToInt32(bits2Len)) | bits2;
 | 
			
		||||
            return num;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
using System.Net;
 | 
			
		||||
using Common;
 | 
			
		||||
using DotNext;
 | 
			
		||||
using Microsoft.AspNetCore.Mvc;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using WebProtocol;
 | 
			
		||||
@@ -149,6 +150,7 @@ public class JtagController : ControllerBase
 | 
			
		||||
    {
 | 
			
		||||
        return "This is Jtag Controller";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 执行一个Jtag命令
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -182,8 +184,16 @@ public class JtagController : ControllerBase
 | 
			
		||||
        var jtagCtrl = new JtagClient.Jtag(address, port);
 | 
			
		||||
        var ret = await jtagCtrl.ReadIDCode();
 | 
			
		||||
 | 
			
		||||
        if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); }
 | 
			
		||||
        else { return TypedResults.InternalServerError(ret.Error); }
 | 
			
		||||
        if (ret.IsSuccessful)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Info($"Get device {address} ID code: 0x{ret.Value:X4}");
 | 
			
		||||
            return TypedResults.Ok(ret.Value);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            logger.Error(ret.Error);
 | 
			
		||||
            return TypedResults.InternalServerError(ret.Error);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -217,7 +227,8 @@ public class JtagController : ControllerBase
 | 
			
		||||
            await file.CopyToAsync(stream);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return TypedResults.Ok("文件上传成功");
 | 
			
		||||
        logger.Info($"Device {address} Upload Bitstream Successfully");
 | 
			
		||||
        return TypedResults.Ok("Bitstream Upload Successfully");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
@@ -265,8 +276,16 @@ public class JtagController : ControllerBase
 | 
			
		||||
                var jtagCtrl = new JtagClient.Jtag(address, port);
 | 
			
		||||
                var ret = await jtagCtrl.DownloadBitstream(fileBytes);
 | 
			
		||||
 | 
			
		||||
                if (ret.IsSuccessful) { return TypedResults.Ok(ret.Value); }
 | 
			
		||||
                else { return TypedResults.InternalServerError(ret.Error); }
 | 
			
		||||
                if (ret.IsSuccessful)
 | 
			
		||||
                {
 | 
			
		||||
                    logger.Info($"Device {address} dowload bitstream successfully");
 | 
			
		||||
                    return TypedResults.Ok(ret.Value);
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    logger.Error(ret.Error);
 | 
			
		||||
                    return TypedResults.InternalServerError(ret.Error);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception error)
 | 
			
		||||
 
 | 
			
		||||
@@ -213,23 +213,34 @@ public static class JtagCmd
 | 
			
		||||
    public const UInt32 CMD_JTAG_IDLE_DELAY = 0b0101;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class Jtag
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// Jtag控制器
 | 
			
		||||
/// </summary>
 | 
			
		||||
public class Jtag
 | 
			
		||||
{
 | 
			
		||||
    private static readonly NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
 | 
			
		||||
 | 
			
		||||
    readonly int timeout;
 | 
			
		||||
 | 
			
		||||
    readonly int port;
 | 
			
		||||
    readonly string address;
 | 
			
		||||
    private IPEndPoint ep;
 | 
			
		||||
 | 
			
		||||
    public Jtag(string address, int port, int outTime = 2000)
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Jtag构造函数
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    /// <param name="address">目标IP地址</param>
 | 
			
		||||
    /// <param name="port">目标UDP端口</param>
 | 
			
		||||
    /// <param name="timeout">超时时间</param>
 | 
			
		||||
    public Jtag(string address, int port, int timeout = 2000)
 | 
			
		||||
    {
 | 
			
		||||
        this.address = address;
 | 
			
		||||
        this.port = port;
 | 
			
		||||
        this.ep = new IPEndPoint(IPAddress.Parse(address), port);
 | 
			
		||||
        this.timeout = outTime;
 | 
			
		||||
        this.timeout = timeout;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async ValueTask<Result<uint>> ReadFIFO(uint devAddr)
 | 
			
		||||
    async ValueTask<Result<uint>> ReadFIFO(uint devAddr)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = false;
 | 
			
		||||
        var opts = new SendAddrPackOptions();
 | 
			
		||||
@@ -242,23 +253,23 @@ class Jtag
 | 
			
		||||
        // Read Jtag State Register
 | 
			
		||||
        opts.IsWrite = false;
 | 
			
		||||
        ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
 | 
			
		||||
        if (!ret) throw new Exception("Send Address Package Failed!");
 | 
			
		||||
        if (!ret) return new(new Exception("Send Address Package Failed!"));
 | 
			
		||||
 | 
			
		||||
        // Wait for Read Ack
 | 
			
		||||
        if (!MsgBus.IsRunning)
 | 
			
		||||
            throw new Exception("Message Bus not Working!");
 | 
			
		||||
            return new(new Exception("Message Bus not Working!"));
 | 
			
		||||
 | 
			
		||||
        var retPack = await MsgBus.UDPServer.WaitForDataAsync(address, port);
 | 
			
		||||
        if (!retPack.IsSuccessful || !retPack.Value.IsSuccessful)
 | 
			
		||||
            throw new Exception("Send address package failed");
 | 
			
		||||
            return new(new Exception("Send address package failed"));
 | 
			
		||||
 | 
			
		||||
        var retPackOpts = retPack.Value.Options;
 | 
			
		||||
        if (retPackOpts.Data is null)
 | 
			
		||||
            throw new Exception($"Data is Null, package: {retPackOpts.ToString()}");
 | 
			
		||||
            return new(new Exception($"Data is Null, package: {retPackOpts.ToString()}"));
 | 
			
		||||
 | 
			
		||||
        var retPackLen = retPackOpts.Data.Length;
 | 
			
		||||
        if (retPackLen != 4)
 | 
			
		||||
            throw new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes");
 | 
			
		||||
            return new(new Exception($"RecvDataPackage BodyData Length not Equal to 4: Total {retPackLen} bytes"));
 | 
			
		||||
 | 
			
		||||
        return Convert.ToUInt32(Common.Number.BytesToNumber(retPackOpts.Data).Value);
 | 
			
		||||
    }
 | 
			
		||||
@@ -277,36 +288,36 @@ class Jtag
 | 
			
		||||
        // 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!");
 | 
			
		||||
        if (!ret) return new(new Exception("Send 1st address package failed!"));
 | 
			
		||||
        // Send Data Package
 | 
			
		||||
        ret = await UDPClientPool.SendDataPackAsync(ep,
 | 
			
		||||
                new SendDataPackage(Common.Number.NumberToBytes(data, 4).Value));
 | 
			
		||||
        if (!ret) throw new Exception("Send data package failed!");
 | 
			
		||||
        if (!ret) return new(new Exception("Send data package failed!"));
 | 
			
		||||
 | 
			
		||||
        // Check Msg Bus
 | 
			
		||||
        if (!MsgBus.IsRunning)
 | 
			
		||||
            throw new Exception("Message bus not working!");
 | 
			
		||||
            return new(new Exception("Message bus not working!"));
 | 
			
		||||
        // Wait for Write Ack
 | 
			
		||||
        var udpWriteAck = await MsgBus.UDPServer.WaitForAckAsync(address, port);
 | 
			
		||||
        if (!udpWriteAck.IsSuccessful) throw udpWriteAck.Error;
 | 
			
		||||
        if (!udpWriteAck.IsSuccessful) return new(udpWriteAck.Error);
 | 
			
		||||
        else if (!udpWriteAck.Value.IsSuccessful)
 | 
			
		||||
            throw new Exception("Send address package failed");
 | 
			
		||||
            return new(new Exception("Send address package failed"));
 | 
			
		||||
 | 
			
		||||
        // Read Jtag State Register
 | 
			
		||||
        opts.IsWrite = false;
 | 
			
		||||
        opts.Address = JtagAddr.STATE;
 | 
			
		||||
        ret = await UDPClientPool.SendAddrPackAsync(ep, new SendAddrPackage(opts));
 | 
			
		||||
        if (!ret) throw new Exception("Send 2rd Address Package Failed!");
 | 
			
		||||
        if (!ret) return new(new Exception("Send 2rd Address Package Failed!"));
 | 
			
		||||
        // Wait for Read Data
 | 
			
		||||
        var udpDataResp = await MsgBus.UDPServer.WaitForDataAsync(address, port);
 | 
			
		||||
        if (!udpDataResp.IsSuccessful) throw udpDataResp.Error;
 | 
			
		||||
        if (!udpDataResp.IsSuccessful) return new(udpDataResp.Error);
 | 
			
		||||
        else if (!udpDataResp.Value.IsSuccessful)
 | 
			
		||||
            throw new Exception("Send address package failed");
 | 
			
		||||
            return new(new Exception("Send address package failed"));
 | 
			
		||||
 | 
			
		||||
        return udpDataResp.Value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async ValueTask<Result<RecvDataPackage>> WriteFIFO(UInt32 devAddr, byte[] dataArray)
 | 
			
		||||
    async ValueTask<Result<RecvDataPackage>> WriteFIFO(UInt32 devAddr, byte[] dataArray)
 | 
			
		||||
    {
 | 
			
		||||
        var ret = false;
 | 
			
		||||
        var opts = new SendAddrPackOptions();
 | 
			
		||||
@@ -318,7 +329,7 @@ class Jtag
 | 
			
		||||
 | 
			
		||||
        // Check Msg Bus
 | 
			
		||||
        if (!MsgBus.IsRunning)
 | 
			
		||||
            throw new Exception("Message bus not working!");
 | 
			
		||||
            return new(new Exception("Message bus not working!"));
 | 
			
		||||
 | 
			
		||||
        var writeTimes = dataArray.Length / (256 * (32 / 8)) + 1;
 | 
			
		||||
        for (var i = 0; i < writeTimes; i++)
 | 
			
		||||
@@ -328,7 +339,7 @@ class Jtag
 | 
			
		||||
            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!");
 | 
			
		||||
            if (!ret) return new(new Exception("Send 1st address package failed!"));
 | 
			
		||||
            // Send Data Package
 | 
			
		||||
            ret = await UDPClientPool.SendDataPackAsync(ep,
 | 
			
		||||
                    new SendDataPackage(
 | 
			
		||||
@@ -337,13 +348,13 @@ class Jtag
 | 
			
		||||
                        dataArray[(i * (256 * (32 / 8)))..((i + 1) * (256 * (32 / 8)) - 1)]
 | 
			
		||||
                    )
 | 
			
		||||
                );
 | 
			
		||||
            if (!ret) throw new Exception("Send data package failed!");
 | 
			
		||||
            if (!ret) return new(new Exception("Send data package failed!"));
 | 
			
		||||
 | 
			
		||||
            // Wait for Write Ack
 | 
			
		||||
            var udpWriteAck = await MsgBus.UDPServer.WaitForAckAsync(address, port);
 | 
			
		||||
            if (!udpWriteAck.IsSuccessful) throw udpWriteAck.Error;
 | 
			
		||||
            if (!udpWriteAck.IsSuccessful) return new(udpWriteAck.Error);
 | 
			
		||||
            else if (!udpWriteAck.Value.IsSuccessful)
 | 
			
		||||
                throw new Exception("Send address package failed");
 | 
			
		||||
                return new(new Exception("Send address package failed"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Read Jtag State Register
 | 
			
		||||
@@ -351,29 +362,29 @@ class Jtag
 | 
			
		||||
        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!");
 | 
			
		||||
        if (!ret) return new(new Exception("Send 2rd Address Package Failed!"));
 | 
			
		||||
        // Wait for Read Data
 | 
			
		||||
        var udpDataResp = await MsgBus.UDPServer.WaitForDataAsync(address, port);
 | 
			
		||||
        if (!udpDataResp.IsSuccessful) throw udpDataResp.Error;
 | 
			
		||||
        if (!udpDataResp.IsSuccessful) return new(udpDataResp.Error);
 | 
			
		||||
        else if (!udpDataResp.Value.IsSuccessful)
 | 
			
		||||
            throw new Exception("Send address package failed");
 | 
			
		||||
            return new(new Exception("Send address package failed"));
 | 
			
		||||
 | 
			
		||||
        return udpDataResp.Value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async ValueTask<Result<bool>> WriteFIFO
 | 
			
		||||
    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.IsSuccessful) throw retPack.Error;
 | 
			
		||||
        if (!retPack.IsSuccessful) return new(retPack.Error);
 | 
			
		||||
 | 
			
		||||
        if (retPack.Value.Options.Data is null)
 | 
			
		||||
            throw new Exception($"Data is Null, package: {retPack.Value.Options.ToString()}");
 | 
			
		||||
            return new(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 new(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))
 | 
			
		||||
@@ -382,18 +393,18 @@ class Jtag
 | 
			
		||||
        return ret;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async ValueTask<Result<bool>> WriteFIFO
 | 
			
		||||
    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()}");
 | 
			
		||||
            return new(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 new(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))
 | 
			
		||||
@@ -431,7 +442,7 @@ class Jtag
 | 
			
		||||
 | 
			
		||||
    async ValueTask<Result<bool>> IdleDelay(UInt32 milliseconds)
 | 
			
		||||
    {
 | 
			
		||||
        if (milliseconds > Math.Pow(2, 28)) throw new Exception("Timespan is over 2^28 milliseconds");
 | 
			
		||||
        if (milliseconds > Math.Pow(2, 28)) return new(new Exception("Timespan is over 2^28 milliseconds"));
 | 
			
		||||
 | 
			
		||||
        return await WriteFIFO(
 | 
			
		||||
                JtagAddr.WRITE_CMD,
 | 
			
		||||
@@ -446,8 +457,8 @@ class Jtag
 | 
			
		||||
                JtagAddr.WRITE_DATA,
 | 
			
		||||
                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");
 | 
			
		||||
            if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
            else if (!ret.Value) return new(new Exception("Write JTAG_DR_IDCODE Failed"));
 | 
			
		||||
        }
 | 
			
		||||
        {
 | 
			
		||||
            var ret = await WriteFIFO(
 | 
			
		||||
@@ -455,8 +466,8 @@ class Jtag
 | 
			
		||||
                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");
 | 
			
		||||
            if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
            else if (!ret.Value) return new(new Exception("Write CMD_JTAG_LOAD_IR Failed"));
 | 
			
		||||
        }
 | 
			
		||||
        return await ClearWriteDataReg();
 | 
			
		||||
    }
 | 
			
		||||
@@ -464,7 +475,7 @@ class Jtag
 | 
			
		||||
    async ValueTask<Result<bool>> LoadDRCareInput(byte[] bytesArray)
 | 
			
		||||
    {
 | 
			
		||||
        var bytesLen = ((uint)(bytesArray.Length * 8));
 | 
			
		||||
        if (bytesLen > Math.Pow(2, 28)) throw new Exception("Length is over 2^(28 - 3)");
 | 
			
		||||
        if (bytesLen > Math.Pow(2, 28)) return new(new Exception("Length is over 2^(28 - 3)"));
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            var ret = await WriteFIFO(
 | 
			
		||||
@@ -472,21 +483,21 @@ class Jtag
 | 
			
		||||
                    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");
 | 
			
		||||
            if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
            else if (!ret.Value) return new(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");
 | 
			
		||||
            if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
            else if (!ret.Value) return new(new Exception("Write Data Failed"));
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async ValueTask<Result<UInt32>> LoadDRCareOutput(UInt32 bytesLen)
 | 
			
		||||
    {
 | 
			
		||||
        if (bytesLen > Math.Pow(2, 28)) throw new Exception("Length is over 2^(28 - 3)");
 | 
			
		||||
        if (bytesLen > Math.Pow(2, 28)) return new(new Exception("Length is over 2^(28 - 3)"));
 | 
			
		||||
 | 
			
		||||
        var ret = await WriteFIFO(
 | 
			
		||||
                JtagAddr.WRITE_CMD,
 | 
			
		||||
@@ -496,7 +507,7 @@ class Jtag
 | 
			
		||||
        if (ret.Value)
 | 
			
		||||
            return await ReadFIFO(JtagAddr.READ_DATA);
 | 
			
		||||
        else
 | 
			
		||||
            throw new Exception("LoadDRCareo Failed!");
 | 
			
		||||
            return new(new Exception("LoadDRCareo Failed!"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public async ValueTask<Result<uint>> ReadIDCode()
 | 
			
		||||
@@ -504,28 +515,30 @@ class Jtag
 | 
			
		||||
        // Clear Data
 | 
			
		||||
        await MsgBus.UDPServer.ClearUDPData(this.address);
 | 
			
		||||
 | 
			
		||||
        logger.Trace($"Clear up udp server {this.address} receive data");
 | 
			
		||||
 | 
			
		||||
        Result<bool> ret;
 | 
			
		||||
 | 
			
		||||
        ret = await ClearAllRegisters();
 | 
			
		||||
        if (!ret.IsSuccessful) throw ret.Error;
 | 
			
		||||
        else if (!ret.Value) throw new Exception("Jtag Clear All Registers Failed");
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag Clear All Registers Failed"));
 | 
			
		||||
 | 
			
		||||
        ret = await RunTest();
 | 
			
		||||
        if (!ret.IsSuccessful) throw ret.Error;
 | 
			
		||||
        else if (!ret.Value) throw new Exception("Jtag Run Test Failed");
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag Run Test Failed"));
 | 
			
		||||
 | 
			
		||||
        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");
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag Execute Command JTAG_DR_IDCODE Failed"));
 | 
			
		||||
 | 
			
		||||
        ret = await ClearWriteDataReg();
 | 
			
		||||
        if (!ret.IsSuccessful) throw ret.Error;
 | 
			
		||||
        else if (!ret.Value) throw new Exception("Jtag Clear Write Registers Failed");
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag Clear Write Registers Failed"));
 | 
			
		||||
 | 
			
		||||
        var retData = await LoadDRCareOutput(4);
 | 
			
		||||
        if (!retData.IsSuccessful)
 | 
			
		||||
        {
 | 
			
		||||
            throw new Exception("Get ID Code Failed");
 | 
			
		||||
            return new(new Exception("Get ID Code Failed"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return retData.Value;
 | 
			
		||||
@@ -536,66 +549,66 @@ class Jtag
 | 
			
		||||
        // Clear Data
 | 
			
		||||
        await MsgBus.UDPServer.ClearUDPData(this.address);
 | 
			
		||||
 | 
			
		||||
        logger.Trace($"Clear up udp server {this.address} receive data");
 | 
			
		||||
 | 
			
		||||
        Result<bool> ret;
 | 
			
		||||
 | 
			
		||||
        ret = await CloseTest();
 | 
			
		||||
        if (!ret.IsSuccessful) throw ret.Error;
 | 
			
		||||
        else if (!ret.Value) throw new Exception("Jtag Close Test Failed");
 | 
			
		||||
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag Close Test Failed"));
 | 
			
		||||
 | 
			
		||||
        ret = await RunTest();
 | 
			
		||||
        if (!ret.IsSuccessful) throw ret.Error;
 | 
			
		||||
        else if (!ret.Value) throw new Exception("Jtag Run Test Failed");
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag Run Test Failed"));
 | 
			
		||||
 | 
			
		||||
        logger.Trace("Jtag initialize");
 | 
			
		||||
 | 
			
		||||
        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");
 | 
			
		||||
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag Execute Command JTAG_DR_JRST Failed"));
 | 
			
		||||
 | 
			
		||||
        ret = await RunTest();
 | 
			
		||||
        if (!ret.IsSuccessful) throw ret.Error;
 | 
			
		||||
        else if (!ret.Value) throw new Exception("Jtag Run Test Failed");
 | 
			
		||||
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag Run Test Failed"));
 | 
			
		||||
 | 
			
		||||
        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");
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag Execute Command JTAG_DR_CFGI Failed"));
 | 
			
		||||
 | 
			
		||||
        logger.Trace("Jtag ready to write bitstream");
 | 
			
		||||
 | 
			
		||||
        ret = await IdleDelay(75000);
 | 
			
		||||
        if (!ret.IsSuccessful) throw ret.Error;
 | 
			
		||||
        else if (!ret.Value) throw new Exception("Jtag IDLE Delay Failed");
 | 
			
		||||
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag IDLE Delay Failed"));
 | 
			
		||||
 | 
			
		||||
        ret = await LoadDRCareInput(bitstream);
 | 
			
		||||
        if (!ret.IsSuccessful) throw ret.Error;
 | 
			
		||||
        else if (!ret.Value) throw new Exception("Jtag Load Data Failed");
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag Load Data Failed"));
 | 
			
		||||
 | 
			
		||||
        logger.Trace("Jtag write bitstream");
 | 
			
		||||
 | 
			
		||||
        ret = await CloseTest();
 | 
			
		||||
        if (!ret.IsSuccessful) throw ret.Error;
 | 
			
		||||
        else if (!ret.Value) throw new Exception("Jtag Close Test Failed");
 | 
			
		||||
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag Close Test Failed"));
 | 
			
		||||
 | 
			
		||||
        ret = await RunTest();
 | 
			
		||||
        if (!ret.IsSuccessful) throw ret.Error;
 | 
			
		||||
        else if (!ret.Value) throw new Exception("Jtag Run Test Failed");
 | 
			
		||||
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag Run Test Failed"));
 | 
			
		||||
 | 
			
		||||
        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");
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag Execute Command JTAG_DR_JWAKEUP Failed"));
 | 
			
		||||
 | 
			
		||||
        logger.Trace("Jtag reset device");
 | 
			
		||||
 | 
			
		||||
        ret = await IdleDelay(1000);
 | 
			
		||||
        if (!ret.IsSuccessful) throw ret.Error;
 | 
			
		||||
        else if (!ret.Value) throw new Exception("Jtag IDLE Delay Failed");
 | 
			
		||||
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag IDLE Delay Failed"));
 | 
			
		||||
 | 
			
		||||
        ret = await CloseTest();
 | 
			
		||||
        if (!ret.IsSuccessful) throw ret.Error;
 | 
			
		||||
        else if (!ret.Value) throw new Exception("Jtag Close Test Failed");
 | 
			
		||||
        if (!ret.IsSuccessful) return new(ret.Error);
 | 
			
		||||
        else if (!ret.Value) return new(new Exception("Jtag Close Test Failed"));
 | 
			
		||||
        logger.Trace("Jtag download bitstream successfully");
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,7 @@ using System.Text;
 | 
			
		||||
using DotNext;
 | 
			
		||||
using DotNext.Threading;
 | 
			
		||||
using Newtonsoft.Json;
 | 
			
		||||
using WebProtocol;
 | 
			
		||||
 | 
			
		||||
/// <summary> UDP接受数据包格式 </summary>
 | 
			
		||||
public class UDPData
 | 
			
		||||
@@ -58,9 +59,6 @@ public class UDPData
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// UDP Server
 | 
			
		||||
/// </summary>
 | 
			
		||||
/// <summary>
 | 
			
		||||
/// UDP 服务器
 | 
			
		||||
/// </summary>
 | 
			
		||||
@@ -80,6 +78,15 @@ public class UDPServer
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public bool IsRunning { get { return isRunning; } }
 | 
			
		||||
 | 
			
		||||
    /// <summary> UDP 服务器的错误代码 </summary>
 | 
			
		||||
    public enum ErrorCode
 | 
			
		||||
    {
 | 
			
		||||
        Success = 0,
 | 
			
		||||
        GetNoneAfterTimeout,
 | 
			
		||||
        ResponseWrong,
 | 
			
		||||
        NotRecvDataPackage,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Construct a udp server with fixed port
 | 
			
		||||
    /// </summary>
 | 
			
		||||
@@ -132,8 +139,9 @@ public class UDPServer
 | 
			
		||||
        {
 | 
			
		||||
            var elapsed = DateTime.Now - startTime;
 | 
			
		||||
            isTimeout = elapsed >= TimeSpan.FromMilliseconds(timeout);
 | 
			
		||||
            timeleft = TimeSpan.FromMilliseconds(timeout) - elapsed;
 | 
			
		||||
            if (isTimeout) break;
 | 
			
		||||
 | 
			
		||||
            timeleft = TimeSpan.FromMilliseconds(timeout) - elapsed;
 | 
			
		||||
            using (await udpData.AcquireWriteLockAsync(timeleft))
 | 
			
		||||
            {
 | 
			
		||||
                if (udpData.ContainsKey(ipAddr) &&
 | 
			
		||||
@@ -150,11 +158,11 @@ public class UDPServer
 | 
			
		||||
        if (data is null)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Trace("Get nothing even after time out");
 | 
			
		||||
            return Optional<UDPData>.None;
 | 
			
		||||
            return new(null);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return Optional.Some((UDPData)data.DeepClone());
 | 
			
		||||
            return new(data.DeepClone());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -175,8 +183,9 @@ public class UDPServer
 | 
			
		||||
        {
 | 
			
		||||
            var elapsed = DateTime.Now - startTime;
 | 
			
		||||
            isTimeout = elapsed >= TimeSpan.FromMilliseconds(timeout);
 | 
			
		||||
            timeleft = TimeSpan.FromMilliseconds(timeout) - elapsed;
 | 
			
		||||
            if (isTimeout) break;
 | 
			
		||||
 | 
			
		||||
            timeleft = TimeSpan.FromMilliseconds(timeout) - elapsed;
 | 
			
		||||
            using (await udpData.AcquireReadLockAsync(timeleft))
 | 
			
		||||
            {
 | 
			
		||||
                if (udpData.ContainsKey(ipAddr) &&
 | 
			
		||||
@@ -193,11 +202,11 @@ public class UDPServer
 | 
			
		||||
        if (data is null)
 | 
			
		||||
        {
 | 
			
		||||
            logger.Trace("Get nothing even after time out");
 | 
			
		||||
            return Optional<List<UDPData>>.None;
 | 
			
		||||
            return new(null);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            return Optional.Some((List<UDPData>)data);
 | 
			
		||||
            return new(data);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -213,15 +222,15 @@ public class UDPServer
 | 
			
		||||
    {
 | 
			
		||||
        var data = await FindDataAsync(address, timeout);
 | 
			
		||||
        if (!data.HasValue)
 | 
			
		||||
            throw new Exception("Get None even after time out!");
 | 
			
		||||
            return new(new Exception("Get None even after time out!"));
 | 
			
		||||
 | 
			
		||||
        var recvData = data.Value;
 | 
			
		||||
        if (recvData.Address != address || (port > 0 && recvData.Port != port))
 | 
			
		||||
            throw new Exception("Receive Data From Wrong Board!");
 | 
			
		||||
            return new(new Exception("Receive Data From Wrong Board!"));
 | 
			
		||||
 | 
			
		||||
        var retPack = WebProtocol.RecvRespPackage.FromBytes(recvData.Data);
 | 
			
		||||
        if (!retPack.IsSuccessful)
 | 
			
		||||
            throw new Exception("Not RecvDataPackage!", retPack.Error);
 | 
			
		||||
            return new(new Exception("Not RecvDataPackage!", retPack.Error));
 | 
			
		||||
 | 
			
		||||
        return retPack.Value;
 | 
			
		||||
    }
 | 
			
		||||
@@ -233,20 +242,20 @@ public class UDPServer
 | 
			
		||||
    /// <param name="port">UDP 端口</param>
 | 
			
		||||
    /// <param name="timeout">超时时间范围</param>
 | 
			
		||||
    /// <returns>接收数据包</returns>
 | 
			
		||||
    public async ValueTask<Result<WebProtocol.RecvDataPackage>> WaitForDataAsync
 | 
			
		||||
    public async ValueTask<Result<RecvDataPackage>> WaitForDataAsync
 | 
			
		||||
        (string address, int port = -1, int timeout = 1000)
 | 
			
		||||
    {
 | 
			
		||||
        var data = await FindDataAsync(address, timeout);
 | 
			
		||||
        if (!data.HasValue)
 | 
			
		||||
            throw new Exception("Get None even after time out!");
 | 
			
		||||
            return new(new Exception("Get None even after time out!"));
 | 
			
		||||
 | 
			
		||||
        var recvData = data.Value;
 | 
			
		||||
        if (recvData.Address != address || (port >= 0 && recvData.Port != port))
 | 
			
		||||
            throw new Exception("Receive Data From Wrong Board!");
 | 
			
		||||
            return new(new Exception("Receive Data From Wrong Board!"));
 | 
			
		||||
 | 
			
		||||
        var retPack = WebProtocol.RecvDataPackage.FromBytes(recvData.Data);
 | 
			
		||||
        if (!retPack.IsSuccessful)
 | 
			
		||||
            throw new Exception("Not RecvDataPackage!", retPack.Error);
 | 
			
		||||
            return new(new Exception("Not RecvDataPackage!", retPack.Error));
 | 
			
		||||
 | 
			
		||||
        return retPack.Value;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -234,18 +234,18 @@ namespace WebProtocol
 | 
			
		||||
        {
 | 
			
		||||
            if (bytes.Length != 8)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentException(
 | 
			
		||||
                return new(new ArgumentException(
 | 
			
		||||
                    "Bytes are not equal to 8 bytes.",
 | 
			
		||||
                    nameof(bytes)
 | 
			
		||||
                );
 | 
			
		||||
                ));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (checkSign && bytes[0] != (byte)PackSign.SendAddr)
 | 
			
		||||
            {
 | 
			
		||||
                throw new ArgumentException(
 | 
			
		||||
                    "The sign of bytes is not SendAddr Package, but you can disable it by set checkSign false.",
 | 
			
		||||
                    nameof(bytes)
 | 
			
		||||
                );
 | 
			
		||||
                return new(new ArgumentException(
 | 
			
		||||
                            "The sign of bytes is not SendAddr Package, but you can disable it by set checkSign false.",
 | 
			
		||||
                            nameof(bytes)
 | 
			
		||||
                            ));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var address = Common.Number.BytesToNumber(bytes[4..]).Value;
 | 
			
		||||
@@ -377,10 +377,10 @@ namespace WebProtocol
 | 
			
		||||
        public static Result<RecvDataPackage> FromBytes(byte[] bytes)
 | 
			
		||||
        {
 | 
			
		||||
            if (bytes[0] != (byte)PackSign.RecvData)
 | 
			
		||||
                throw new ArgumentException(
 | 
			
		||||
                return new(new ArgumentException(
 | 
			
		||||
                    $"The sign of bytes is not RecvData Package, Sign: 0x{BitConverter.ToString([bytes[0]])}",
 | 
			
		||||
                    nameof(bytes)
 | 
			
		||||
                );
 | 
			
		||||
                ));
 | 
			
		||||
            return new RecvDataPackage(bytes[1], bytes[2], bytes[4..]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@@ -480,10 +480,10 @@ namespace WebProtocol
 | 
			
		||||
        public static Result<RecvRespPackage> FromBytes(byte[] bytes)
 | 
			
		||||
        {
 | 
			
		||||
            if (bytes[0] != (byte)PackSign.RecvResp)
 | 
			
		||||
                throw new ArgumentException(
 | 
			
		||||
                return new(new ArgumentException(
 | 
			
		||||
                    $"The sign of bytes is not RecvResp Package, Sign: 0x{BitConverter.ToString([bytes[0]])}",
 | 
			
		||||
                    nameof(bytes)
 | 
			
		||||
                );
 | 
			
		||||
                ));
 | 
			
		||||
            return new RecvRespPackage(bytes[1], bytes[2]);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user