From 1bad9fd8ce9a576aa48e86243ba135cab22d36cb Mon Sep 17 00:00:00 2001 From: yangyanqing Date: Thu, 7 May 2026 10:26:26 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20UART=5Fkx12A6=5Fevent.cs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改TransmitCharacter函数 --- UART_kx12A6_event.cs | 1003 +++++++++++++++++++++--------------------- 1 file changed, 501 insertions(+), 502 deletions(-) diff --git a/UART_kx12A6_event.cs b/UART_kx12A6_event.cs index b2ca13d..f2aadbc 100644 --- a/UART_kx12A6_event.cs +++ b/UART_kx12A6_event.cs @@ -1,502 +1,501 @@ -// -// UART 外设实现 -// 基于 UART 规格,包含完整的 FIFO、中断和调制解调器控制功能 -// - -using System; -using System.Collections.Generic; -using Antmicro.Renode.Core; -using Antmicro.Renode.Logging; -using Antmicro.Renode.Peripherals.Bus; -using Antmicro.Renode.Peripherals.UART; -using Antmicro.Renode.Utilities; -using Antmicro.Renode.Time; -// using Antmicro.Migrant; - -namespace Antmicro.Renode.Peripherals.CustomPeripherals -{ - /// - /// UART_771_RUHW_2CFG 控制器:同步串口、遥测、有中断 - /// 接收缓存0B,发送缓存2048B,输入时钟24MHz - /// - public class UART_771_RUHW_2CFG6 : IDoubleWordPeripheral, IKnownSize - { - private readonly IMachine machine; - private readonly object txFifoLock = new object(); - private readonly object rxFifoLock = new object(); - - public UART_771_RUHW_2CFG6(IMachine machine) - { - this.clockFrequency = 24000000; - this.machine = machine; - transmissionGeneration = 0; - - // 创建 FIFO - txFifo = new Queue(); - rxFifo = new Queue(); - - // 创建中断线 - IRQ = new GPIO(); - - // 初始化寄存器 - DefineRegisters(); - Reset(); - - this.Log(LogLevel.Info, "771 UART initialized, clock: {0} Hz", clockFrequency); - } - - public void Reset() - { - lock(txFifoLock) - { - txFifo.Clear(); - } - lock(rxFifoLock) - { - rxFifo.Clear(); - } - - fsta = FSTA_TEMP; // FIFO状态寄存器 - frm_cnt = 0; // 帧计数 - byte_cnt = 0; - tbr = 0; // 发送FIFO剩余字节数 - currentBaudRate = 16384; // 时钟配置缺省为16384Hz - clk_set = (ushort)(clockFrequency / (2 * currentBaudRate) - 1); - scramble_ctrl = 0x00; // 加解扰使能禁止 - rstr = 0x00; // 复位/使能寄存器 - - RxfifoEnabled = true; - TxfifoEnabled = true; //发送fifo使能 - - transmissionScheduled = false; - transmissionGeneration++; - InterruptTriggerCondition = false; //重置后不满足条件 - - IRQ.Set(false); - UpdateInterrupts(); - - this.Log(LogLevel.Info, "TX_FIFO_SIZE reset"); - } - - - private void DefineRegisters() - { - // 寄存器访问通过 ReadDoubleWord/WriteDoubleWord 实现 - - } - - - // ======================================== - // IBusPeripheral 接口实现 - // ======================================== - public uint ReadDoubleWord(long offset) - { - return ReadRegisters(offset); - } - - public void WriteDoubleWord(long offset, uint value) - { - WriteRegisters(offset, value); - } - - - // ======================================== - // 自定义 - // ======================================== - public uint ReadRegisters(long offset) - { - uint value = 0; - - switch (offset) - { - - case (long)Registers.FSTA: // FIFO状态寄存器 - lock(txFifoLock) - { - value = (byte)(fsta & 0xFF); - } - this.Log(LogLevel.Info, "Read FSTA: 0x{0:X2}", value); - break; - - case (long)Registers.FRM_CNT: //帧计数,待定 - lock(txFifoLock) - { - value = (uint)frm_cnt; - } - this.Log(LogLevel.Info, "Read FRM_CNT: {0}", value); - break; - - case (long)Registers.TBR_FreeBytes: //发送FIFO剩余字节数 - lock(txFifoLock) - { - tbr = (ushort)txFifo.Count; - } - value = (uint)tbr; - this.Log(LogLevel.Info, "Read TBR_FreeBytes: {0}", value); - break; - - case (long)Registers.CLK_SET: //时钟配置,暂无读操作 - value = (uint)clk_set; - this.Log(LogLevel.Info, "Read CLK_SET: {0}", value); - break; - - case (long)Registers.SCRAMBLE_CTRL: //加解扰使能禁止,暂无读操作 - value = (uint)(scramble_ctrl & 0xFF); - this.Log(LogLevel.Info, "Read SCRAMBLE_CTRL: 0x{0}", value); - break; - - case (long)Registers.RSTR: // 复位/使能,暂无读操作 - value = (uint)(rstr & 0xFF); - this.Log(LogLevel.Info, "Read RSTR: 0x{0}", value); - break; - - default: - this.Log(LogLevel.Warning, "Read to unknown offset: 0x{0:X} = 0x{1:X2}", offset, value); - break; - } - - return value; - } - - - public void WriteRegisters(long offset, uint value) - { - - switch (offset) - { - - case (long)Registers.TBR_RBR: // 发送FIFO - WriteTBR(value); - //this.Log(LogLevel.Info, "Write TBR_RBR: {0}", value); - break; - - case (long)Registers.CLK_SET: // 时钟配置 - clk_set = (ushort)value; - currentBaudRate = (ushort)(clockFrequency / 2 / (1 + value)); - this.Log(LogLevel.Info, "Write CLK_SET: {0}, currentBaudRate: {1}", value, currentBaudRate); - // 计算传输速率 - ComputeTransRate(); - break; - - case (long)Registers.SCRAMBLE_CTRL: // 加解扰使能禁止 - scramble_ctrl = (byte)(value & 0xFF); - this.Log(LogLevel.Info, "Write SCRAMBLE_CTRL: 0x{0:X2}", value); - break; - - case (long)Registers.RSTR: // 复位/使能 - rstr = (byte)(value & 0xFF); - this.Log(LogLevel.Info, "Write RSTR: 0x{0:X2}", rstr); - if ((rstr & 0XFF) == RSTR_RES) - { - Reset(); - } - break; - - default: - this.Log(LogLevel.Warning, "Write to unknown offset: 0x{0:X} = 0x{1:X2}", offset, value); - break; - } - } - - - // ======================================== - // 按波特率计算传输速率,同步串口无起始位、停止位、奇偶校验位 - // ======================================== - public void ComputeTransRate() - { - // 计算传输时间 - int bitsPerByte = 8; // 数据位 - - // 计算传输时间(秒),16384hz->488.24us - if(currentBaudRate == 0) - { - return; - } - double secondsPerByte = (double)bitsPerByte / currentBaudRate; - microsecondsPerByte = (ulong)(secondsPerByte * 1000000); - - this.Log(LogLevel.Debug, - "Scheduling byte transmission: {0} bits @ {1} bps = {2}μs", - bitsPerByte, currentBaudRate, microsecondsPerByte); - } - - private void UpdateInterrupts() - { - if(InterruptTriggerCondition == false) - { - // FIFO空 → 必须先写满>64,期间绝对不触发中断 - IRQ.Set(false); - return; - } - - lock(txFifoLock) - { - // <64 中断,>96 清除,中间保持 - if (txFifo.Count < IRQ_MINBYTES) - { - IRQ.Set(true); - this.Log(LogLevel.Info, "Interrupt asserted"); - } - else if (txFifo.Count > IRQ_MAXBYTES) - { - IRQ.Set(false); - } - } - - } - - - public void WriteTBR(uint value) - { - // 从星务接收数据 ,操作txFifo - // value 低16位有效 - this.Log(LogLevel.Info, "Write TBR: 0x{0:X2}", value); - - lock(txFifoLock) - { - if (TxfifoEnabled) - { - if ((txFifo.Count + 2) <= TX_FIFO_SIZE) - { - bool wasEmpty = (txFifo.Count == 0); - - byte tmp = (byte)(value >> 8); - txFifo.Enqueue(tmp); - tmp = (byte)value; - txFifo.Enqueue(tmp); - fsta = (byte)(fsta & (~FSTA_TEMP)); // 发送缓冲区不为空,D0置0 - - // 更新帧计数 - byte_cnt += 2; - frm_cnt = (ushort)(byte_cnt / FRAME_LONG); // 遥测帧固定1024字节 - - // FIFO从空变为非空 - if(wasEmpty) - { - this.Log(LogLevel.Info, "FIFO: Empty->NonEmpty"); - // 启动传输调度(事件驱动) - ScheduleNextByteTransmit(); - } - - if (txFifo.Count >= (TX_FIFO_SIZE / 2)) - { - // 置半满标志 - fsta = (byte)(fsta | FSTA_TLHF); // 发送FIFO半满,D2置1 - } - - if((InterruptTriggerCondition == false) && (txFifo.Count > IRQ_MINBYTES)) - { - InterruptTriggerCondition = true; - UpdateInterrupts(); - } - } - else - { - fsta = (byte)(fsta | FSTA_TFUL); // 发送FIFO满 - this.Log(LogLevel.Warning, "TX FIFO overflow"); - } - } - else - { - // 非 FIFO 模式,待定 - txFifo.Clear(); - txFifo.Enqueue((byte)value); - fsta = (byte)(fsta & (~FSTA_TEMP)); // 发送缓冲区不为空,D0置0 - } - } - - } - - - // ======================================== - // 核心:按波特率调度发送(事件驱动) - // ======================================== - private void ScheduleNextByteTransmit() - { - lock(txFifoLock) - { - // 防止重复调度 - if (transmissionScheduled) - { - return; - } - - if (txFifo.Count == 0) - { - // FIFO空 - fsta = (byte)((fsta & 0xF0) | FSTA_TEMP); - fsta |= FSTA_THHF; //空闲置1 - this.Log(LogLevel.Info, "TX FIFO empty"); - InterruptTriggerCondition = false; - return; - } - - if (txFifo.Count < (TX_FIFO_SIZE / 2)) - { - // 清半满标志 - fsta = (byte)(fsta & (~FSTA_TLHF)); // 发送FIFO非半满,D2清0 - } - - transmissionScheduled = true; - fsta = (byte)(fsta & (~FSTA_THHF)); //正在发送,置0 - var currentGeneration = transmissionGeneration; - - // 使用Renode虚拟时间调度 - machine.ScheduleAction( - TimeInterval.FromMicroseconds(microsecondsPerByte), - _ => TransmitOneByte(currentGeneration) - ); - } - } - - private void TransmitOneByte(ulong generation) - { - lock(txFifoLock) - { - transmissionScheduled = false; - - // 检查是否被Reset取消 - if (generation != transmissionGeneration) - { - this.Log(LogLevel.Debug, "Transmission cancelled (reset)"); - return; - } - - if (txFifo.Count > 0) - { - byte data = txFifo.Dequeue(); - - // 触发CharReceived事件(外部Backend可订阅 网络中间层改为订阅这个事件的方式) - TransmitCharacter(data); - - this.Log(LogLevel.Info, - "Transmitted: 0x{0:X2} ('{1}'), Remaining: {2}", - data, - (data >= 32 && data < 127) ? (char)data : '.', - txFifo.Count); - - // 继续调度下一个字节 - UpdateInterrupts(); - ScheduleNextByteTransmit(); - } - } - } - - - - - public string GetTXFIFODataString() - { - string data = "0x"; - byte tmp; - - // 从 TX FIFO 发送数据,中间层获取txfifo接口 - - if(txFifo.Count == 0) - { - this.Log(LogLevel.Info, "TXFIFO Null"); - return "0x00"; - } - - while (txFifo.Count > 0) - { - tmp = txFifo.Dequeue(); - data += tmp.ToString("X2"); // 转换为16进制字符串 - } - - this.Log(LogLevel.Info, "Transmitted: 0x{0}, TXFIFO Null", data); - - - UpdateInterrupts(); - - return data; - } - - // ======================================== - // 同步串口属性 - // ======================================== - public uint BaudRate => 0; - public enum Bits { None } - public Bits StopBits => Bits.None; - public enum Parity { None } - public Parity ParityBit => Parity.None; - - public uint GetFSTA() => fsta; - public uint GetByteCount() => byte_cnt; - public ushort GetFrameCount() => frm_cnt; - - private void TransmitCharacter(byte data) { } - - - public long Size => 0x80; //uart地址长度总空间 - - public GPIO IRQ { get; } - - // ======================================== - // 寄存器定义 - // ======================================== - - private enum Registers : long - { - TBR_RBR = 0x00, // TBR发送FIFO - FSTA = 0x04, // FIFO状态寄存器 - FRM_CNT = 0x08, // 帧计数 - TBR_FreeBytes = 0x0C, // 发送FIFO剩余字节数 - CLK_SET = 0x10, // 时钟配置 - SCRAMBLE_CTRL = 0x14, // 加解扰使能禁止 - RSTR = 0x7C // 复位/使能 x55复位;其他使能 - } - - - // FSTA FIFO状态寄存器 - private const byte FSTA_TEMP = 0x01; // 发送FIFO空 - private const byte FSTA_TLHF= 0x02; // 发送FIFO半满 - private const byte FSTA_TFUL = 0x04; // 发送FIFO满 - private const byte FSTA_THHF = 0x08; // 1为空闲;0为正在发送 - - - // RSTR 复位/使能寄存器 - private const byte RSTR_RES = 0x55; // 0x55复位,其他使能 - - private const byte SCRAMBLE_CTRL_ENABLE = 0x55; // 0x55加解扰使能,其他禁止 - - // 常量 - private const int RX_FIFO_SIZE = 0; // 接收FIFO_SIZE - private const int TX_FIFO_SIZE = 2048; // 发送FIFO_SIZE - private const int FRAME_LONG = 1024; // 帧长固定为1024B - private const int IRQ_MINBYTES = 64; // FIFO中的字节数小于64字节时会产生中断 - private const int IRQ_MAXBYTES = 96; // FIFO中的字节数大于96字节时会清中断 - - - - // ======================================== - // 私有字段 - // ======================================== - - private readonly uint clockFrequency; - private uint currentBaudRate; - private uint byte_cnt; // 字节计数,计算帧计数 - - // 寄存器 - private byte fsta; // FIFO状态寄存器 - private ushort frm_cnt; // 帧计数 - private ushort tbr; // 发送FIFO剩余字节数 - private ushort clk_set; // 时钟配置 - private byte scramble_ctrl; // 加解扰使能禁止 - private byte rstr; // 复位/使能 - - - // FIFO - private readonly Queue rxFifo; - private readonly Queue txFifo; - private bool RxfifoEnabled; - private bool TxfifoEnabled; - private bool transmissionScheduled; - private ulong transmissionGeneration; - private ulong microsecondsPerByte; - private bool InterruptTriggerCondition; //FIFO为空后写入64字节才允许触发中断 - - - - } -} +// +// UART 外设实现 +// 基于 UART 规格,包含完整的 FIFO、中断和调制解调器控制功能 +// + +using System; +using System.Collections.Generic; +using Antmicro.Renode.Core; +using Antmicro.Renode.Logging; +using Antmicro.Renode.Peripherals.Bus; +using Antmicro.Renode.Peripherals.UART; +using Antmicro.Renode.Utilities; +using Antmicro.Renode.Time; +using Antmicro.Migrant; + +namespace Antmicro.Renode.Peripherals.CustomPeripherals +{ + /// + /// UART_771_RUHW_2CFG 控制器:同步串口、遥测、有中断 + /// 接收缓存0B,发送缓存2048B,输入时钟24MHz + /// + public class UART_771_RUHW_2CFG6 : IDoubleWordPeripheral, IKnownSize + { + private readonly IMachine machine; + private readonly object txFifoLock = new object(); + private readonly object rxFifoLock = new object(); + + public UART_771_RUHW_2CFG6(IMachine machine) + { + this.clockFrequency = 24000000; + this.machine = machine; + transmissionGeneration = 0; + + // 创建 FIFO + txFifo = new Queue(); + rxFifo = new Queue(); + + // 创建中断线 + IRQ = new GPIO(); + + // 初始化寄存器 + DefineRegisters(); + Reset(); + + this.Log(LogLevel.Info, "771 UART initialized, clock: {0} Hz", clockFrequency); + } + + public void Reset() + { + lock(txFifoLock) + { + txFifo.Clear(); + } + lock(rxFifoLock) + { + rxFifo.Clear(); + } + + fsta = FSTA_TEMP; // FIFO状态寄存器 + frm_cnt = 0; // 帧计数 + byte_cnt = 0; + tbr = 0; // 发送FIFO剩余字节数 + currentBaudRate = 16384; // 时钟配置缺省为16384Hz + clk_set = (ushort)(clockFrequency / (2 * currentBaudRate) - 1); + scramble_ctrl = 0x00; // 加解扰使能禁止 + rstr = 0x00; // 复位/使能寄存器 + + RxfifoEnabled = true; + TxfifoEnabled = true; //发送fifo使能 + + transmissionScheduled = false; + transmissionGeneration++; + InterruptTriggerCondition = false; //重置后不满足条件 + + IRQ.Set(false); + UpdateInterrupts(); + + this.Log(LogLevel.Info, "TX_FIFO_SIZE reset"); + } + + + private void DefineRegisters() + { + // 寄存器访问通过 ReadDoubleWord/WriteDoubleWord 实现 + + } + + + // ======================================== + // IBusPeripheral 接口实现 + // ======================================== + public uint ReadDoubleWord(long offset) + { + return ReadRegisters(offset); + } + + public void WriteDoubleWord(long offset, uint value) + { + WriteRegisters(offset, value); + } + + + // ======================================== + // 自定义 + // ======================================== + public uint ReadRegisters(long offset) + { + uint value = 0; + + switch (offset) + { + + case (long)Registers.FSTA: // FIFO状态寄存器 + value = (byte)(fsta & 0xFF); + this.Log(LogLevel.Info, "Read FSTA: 0x{0:X2}", value); + break; + + case (long)Registers.FRM_CNT: //帧计数,待定 + value = (uint)frm_cnt; + this.Log(LogLevel.Info, "Read TBR_FreeBytes: {0}", value); + break; + + case (long)Registers.TBR_FreeBytes: //发送FIFO剩余字节数 + lock(txFifoLock) + { + tbr = (ushort)txFifo.Count; + } + value = (uint)tbr; + this.Log(LogLevel.Info, "Read TBR_FreeBytes: {0}", value); + break; + + case (long)Registers.CLK_SET: //时钟配置,暂无读操作 + value = (uint)clk_set; + this.Log(LogLevel.Info, "Read CLK_SET: {0}", value); + break; + + case (long)Registers.SCRAMBLE_CTRL: //加解扰使能禁止,暂无读操作 + value = (uint)(scramble_ctrl & 0xFF); + this.Log(LogLevel.Info, "Read SCRAMBLE_CTRL: 0x{0}", value); + break; + + case (long)Registers.RSTR: // 复位/使能,暂无读操作 + value = (uint)(rstr & 0xFF); + this.Log(LogLevel.Info, "Read RSTR: 0x{0}", value); + break; + + default: + this.Log(LogLevel.Warning, "Read to unknown offset: 0x{0:X} = 0x{1:X2}", offset, value); + break; + } + + return value; + } + + + public void WriteRegisters(long offset, uint value) + { + + switch (offset) + { + + case (long)Registers.TBR_RBR: // 发送FIFO + WriteTBR(value); + //this.Log(LogLevel.Info, "Write TBR_RBR: {0}", value); + break; + + case (long)Registers.CLK_SET: // 时钟配置 + clk_set = (ushort)value; + currentBaudRate = (ushort)(clockFrequency / 2 / (1 + value)); + this.Log(LogLevel.Info, "Write CLK_SET: {0}, currentBaudRate: {1}", value, currentBaudRate); + // 计算传输速率 + ComputeTransRate(); + break; + + case (long)Registers.SCRAMBLE_CTRL: // 加解扰使能禁止 + scramble_ctrl = (byte)(value & 0xFF); + this.Log(LogLevel.Info, "Write SCRAMBLE_CTRL: 0x{0:X2}", value); + break; + + case (long)Registers.RSTR: // 复位/使能 + rstr = (byte)(value & 0xFF); + this.Log(LogLevel.Info, "Write RSTR: 0x{0:X2}", rstr); + if ((rstr & 0XFF) == RSTR_RES) + { + Reset(); + } + break; + + default: + this.Log(LogLevel.Warning, "Write to unknown offset: 0x{0:X} = 0x{1:X2}", offset, value); + break; + } + } + + + // ======================================== + // 按波特率计算传输速率,同步串口无起始位、停止位、奇偶校验位 + // ======================================== + public void ComputeTransRate() + { + // 计算传输时间 + int bitsPerByte = 8; // 数据位 + + // 计算传输时间(秒),16384hz->488.24us + if(currentBaudRate == 0) + { + return; + } + double secondsPerByte = (double)bitsPerByte / currentBaudRate; + microsecondsPerByte = (ulong)(secondsPerByte * 1000000); + + this.Log(LogLevel.Debug, + "Scheduling byte transmission: {0} bits @ {1} bps = {2}μs", + bitsPerByte, currentBaudRate, microsecondsPerByte); + } + + private void UpdateInterrupts() + { + if(InterruptTriggerCondition == false) + { + // FIFO空 → 必须先写满>64,期间绝对不触发中断 + IRQ.Set(false); + return; + } + + lock(txFifoLock) + { + // <64 中断,>96 清除,中间保持 + if (txFifo.Count < IRQ_MINBYTES) + { + IRQ.Set(true); + this.Log(LogLevel.Info, "Interrupt asserted"); + } + else if (txFifo.Count > IRQ_MAXBYTES) + { + IRQ.Set(false); + } + } + + } + + + public void WriteTBR(uint value) + { + // 从星务接收数据 ,操作txFifo + // value 低16位有效 + this.Log(LogLevel.Info, "Write TBR: 0x{0:X2}", value); + + lock(txFifoLock) + { + if (TxfifoEnabled) + { + if ((txFifo.Count + 2) <= TX_FIFO_SIZE) + { + bool wasEmpty = (txFifo.Count == 0); + + byte tmp = (byte)(value >> 8); + txFifo.Enqueue(tmp); + tmp = (byte)value; + txFifo.Enqueue(tmp); + fsta = (byte)(fsta & (~FSTA_TEMP)); // 发送缓冲区不为空,D0置0 + + // 更新帧计数 + byte_cnt += 2; + frm_cnt = (ushort)(byte_cnt / FRAME_LONG); // 遥测帧固定1024字节 + + // FIFO从空变为非空 + if(wasEmpty) + { + this.Log(LogLevel.Info, "FIFO: Empty->NonEmpty"); + // 启动传输调度(事件驱动) + ScheduleNextByteTransmit(); + } + + if (txFifo.Count >= (TX_FIFO_SIZE / 2)) + { + // 置半满标志 + fsta = (byte)(fsta | FSTA_TLHF); // 发送FIFO半满,D2置1 + } + + if((InterruptTriggerCondition == false) && (txFifo.Count > IRQ_MINBYTES)) + { + InterruptTriggerCondition = true; + UpdateInterrupts(); + } + } + else + { + fsta = (byte)(fsta | FSTA_TFUL); // 发送FIFO满 + this.Log(LogLevel.Warning, "TX FIFO overflow"); + } + } + else + { + // 非 FIFO 模式,待定 + txFifo.Clear(); + txFifo.Enqueue((byte)value); + fsta = (byte)(fsta & (~FSTA_TEMP)); // 发送缓冲区不为空,D0置0 + } + } + + } + + + // ======================================== + // 核心:按波特率调度发送(事件驱动) + // ======================================== + private void ScheduleNextByteTransmit() + { + lock(txFifoLock) + { + // 防止重复调度 + if (transmissionScheduled) + { + return; + } + + if (txFifo.Count == 0) + { + // FIFO空 + fsta = (byte)((fsta & 0xF0) | FSTA_TEMP); + fsta |= FSTA_THHF; //空闲置1 + this.Log(LogLevel.Info, "TX FIFO empty"); + InterruptTriggerCondition = false; + return; + } + + if (txFifo.Count < (TX_FIFO_SIZE / 2)) + { + // 清半满标志 + fsta = (byte)(fsta & (~FSTA_TLHF)); // 发送FIFO非半满,D2清0 + } + + transmissionScheduled = true; + fsta = (byte)(fsta & (~FSTA_THHF)); //正在发送,置0 + var currentGeneration = transmissionGeneration; + + // 使用Renode虚拟时间调度 + machine.ScheduleAction( + TimeInterval.FromMicroseconds(microsecondsPerByte), + _ => TransmitOneByte(currentGeneration) + ); + } + } + + private void TransmitOneByte(ulong generation) + { + lock(txFifoLock) + { + transmissionScheduled = false; + + // 检查是否被Reset取消 + if (generation != transmissionGeneration) + { + this.Log(LogLevel.Debug, "Transmission cancelled (reset)"); + return; + } + + if (txFifo.Count > 0) + { + byte data = txFifo.Dequeue(); + + // 触发CharReceived事件(外部Backend可订阅 网络中间层改为订阅这个事件的方式) + TransmitCharacter(data); + + this.Log(LogLevel.Info, + "Transmitted: 0x{0:X2} ('{1}'), Remaining: {2}", + data, + (data >= 32 && data < 127) ? (char)data : '.', + txFifo.Count); + + // 继续调度下一个字节 + UpdateInterrupts(); + ScheduleNextByteTransmit(); + } + } + } + + + + + public string GetTXFIFODataString() + { + string data = "0x"; + byte tmp; + + // 从 TX FIFO 发送数据,中间层获取txfifo接口 + + if(txFifo.Count == 0) + { + this.Log(LogLevel.Info, "TXFIFO Null"); + return "0x00"; + } + + while (txFifo.Count > 0) + { + tmp = txFifo.Dequeue(); + data += tmp.ToString("X2"); // 转换为16进制字符串 + } + + this.Log(LogLevel.Info, "Transmitted: 0x{0}, TXFIFO Null", data); + + + UpdateInterrupts(); + + return data; + } + + // ======================================== + // 同步串口属性 + // ======================================== + public uint BaudRate => 0; + public enum Bits { None } + public Bits StopBits => Bits.None; + public enum Parity { None } + public Parity ParityBit => Parity.None; + + public uint GetFSTA() => fsta; + public uint GetByteCount() => byte_cnt; + public ushort GetFrameCount() => frm_cnt; + + public event Action CharReceived; + + private void TransmitCharacter(byte data) + { + CharReceived?.Invoke(data); + } + + + public long Size => 0x80; //uart地址长度总空间 + + public GPIO IRQ { get; } + + // ======================================== + // 寄存器定义 + // ======================================== + + private enum Registers : long + { + TBR_RBR = 0x00, // TBR发送FIFO + FSTA = 0x04, // FIFO状态寄存器 + FRM_CNT = 0x08, // 帧计数 + TBR_FreeBytes = 0x0C, // 发送FIFO剩余字节数 + CLK_SET = 0x10, // 时钟配置 + SCRAMBLE_CTRL = 0x14, // 加解扰使能禁止 + RSTR = 0x7C // 复位/使能 x55复位;其他使能 + } + + + // FSTA FIFO状态寄存器 + private const byte FSTA_TEMP = 0x01; // 发送FIFO空 + private const byte FSTA_TLHF= 0x02; // 发送FIFO半满 + private const byte FSTA_TFUL = 0x04; // 发送FIFO满 + private const byte FSTA_THHF = 0x08; // 1为空闲;0为正在发送 + + + // RSTR 复位/使能寄存器 + private const byte RSTR_RES = 0x55; // 0x55复位,其他使能 + + private const byte SCRAMBLE_CTRL_ENABLE = 0x55; // 0x55加解扰使能,其他禁止 + + // 常量 + private const int RX_FIFO_SIZE = 0; // 接收FIFO_SIZE + private const int TX_FIFO_SIZE = 2048; // 发送FIFO_SIZE + private const int FRAME_LONG = 1024; // 帧长固定为1024B + private const int IRQ_MINBYTES = 64; // FIFO中的字节数小于64字节时会产生中断 + private const int IRQ_MAXBYTES = 96; // FIFO中的字节数大于96字节时会清中断 + + + + // ======================================== + // 私有字段 + // ======================================== + + private readonly uint clockFrequency; + private uint currentBaudRate; + private uint byte_cnt; // 字节计数,计算帧计数 + + // 寄存器 + private byte fsta; // FIFO状态寄存器 + private ushort frm_cnt; // 帧计数 + private ushort tbr; // 发送FIFO剩余字节数 + private ushort clk_set; // 时钟配置 + private byte scramble_ctrl; // 加解扰使能禁止 + private byte rstr; // 复位/使能 + + + // FIFO + private readonly Queue rxFifo; + private readonly Queue txFifo; + private bool RxfifoEnabled; + private bool TxfifoEnabled; + private bool transmissionScheduled; + private ulong transmissionGeneration; + private ulong microsecondsPerByte; + private bool InterruptTriggerCondition; //FIFO为空后写入64字节才允许触发中断 + + + + } +}