diff --git a/SJA1000_CAN.cs b/SJA1000_CAN.cs index 4d7d699..c9cfdc8 100644 --- a/SJA1000_CAN.cs +++ b/SJA1000_CAN.cs @@ -1,12 +1,15 @@ // -// SJA1000 CAN 控制器外设实现(简化版,支持发送/接收队列,提高速率) +// SJA1000 CAN 控制器外设实现(简化版,支持发送/接收队列,可配置长度) // 仅支持 PeliCAN 模式的标准帧,不考虑 BasicCAN、扩展帧、错误处理、多帧、验收滤波和发送中断。 // 寄存器地址映射基于 PeliCAN 模式,包含 MOD, CMR, SR, IR, IER, BTR0, BTR1, OCR, RXERR, TXERR, // 发送缓冲区(地址 16-26)、RBSA 和 CDR。命令寄存器位2=RRB,位3=CDO。 -// 接收为单帧,无 FIFO,无数据溢出处理。 // 所有寄存器可随时读写,无复位模式限制。 // -// author: Generated based on UART16550 template +// 队列长度可通过修改静态字段 MaxTxQueueSize 和 MaxRxQueueSize 调整。 +// 发送队列满时,CPU 发送请求被忽略,并设置 TBS=0(发送缓冲区忙); +// 接收队列满时,外部注入的新帧被丢弃。 +// +// 日志开关:EnableVerboseLog = false 可关闭所有日志输出。 // using System; @@ -25,6 +28,13 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals /// public class SJA1000_CAN : IDoubleWordPeripheral, IBytePeripheral, IKnownSize { + // 日志开关(设置为 false 可屏蔽所有日志) + public static bool EnableVerboseLog = false; + + // 队列长度配置(可修改) + public static int MaxTxQueueSize = 64; // 发送队列最大帧数 + public static int MaxRxQueueSize = 64; // 接收队列最大帧数 + public SJA1000_CAN(IMachine machine) { this.machine = machine; @@ -32,8 +42,8 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals txBuffer = new byte[11]; rxBuffer = new byte[11]; - txFrameQueue = new Queue(); // 新增:发送队列 - rxFrameQueue = new Queue(); // 新增:接收队列 + txFrameQueue = new Queue(); // 发送队列 + rxFrameQueue = new Queue(); // 接收队列 Reset(); } @@ -56,12 +66,14 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals Array.Clear(txBuffer, 0, txBuffer.Length); Array.Clear(rxBuffer, 0, rxBuffer.Length); - txFrameQueue.Clear(); // 清空发送队列 - rxFrameQueue.Clear(); // 清空接收队列 + txFrameQueue.Clear(); + rxFrameQueue.Clear(); + lastInterruptState = false; // 重置中断边沿状态 UpdateInterrupts(); - this.Log(LogLevel.Info, "SJA1000 CAN controller reset (simplified)"); + if (EnableVerboseLog) + this.Log(LogLevel.Info, $"SJA1000 CAN controller reset (txQueueMax={MaxTxQueueSize}, rxQueueMax={MaxRxQueueSize})"); } // ================ IBusPeripheral 接口实现 ================ @@ -79,269 +91,260 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals public byte ReadByte(long offset) { byte value = 0; - switch ((Registers)offset) + lock (lockObject) { - case Registers.MOD: - value = mod; - this.Log(LogLevel.Info, "Read MOD: 0x{0:X2}", value); - break; + switch ((Registers)offset) + { + case Registers.MOD: + value = mod; + if (EnableVerboseLog) this.Log(LogLevel.Info, "Read MOD: 0x{0:X2}", value); + break; - case Registers.CMR: - // 命令寄存器只写,读返回0 - this.Log(LogLevel.Info, "Read CMR (always 0)"); - value = 0; - break; + case Registers.CMR: + if (EnableVerboseLog) this.Log(LogLevel.Info, "Read CMR (always 0)"); + value = 0; + break; - case Registers.SR: - value = (byte)((sr_tbs << 2) | sr_rbs); // BS 恒为0 - this.Log(LogLevel.Info, "Read SR: TBS={0}, RBS={1} -> 0x{2:X2}", sr_tbs, sr_rbs, value); - break; + case Registers.SR: + value = (byte)((sr_tbs << 2) | sr_rbs); // BS 恒为0 + if (EnableVerboseLog) this.Log(LogLevel.Info, "Read SR: TBS={0}, RBS={1} -> 0x{2:X2}", sr_tbs, sr_rbs, value); + break; - case Registers.IR: - value = ir; - // 读 IR 后清零,但需要根据当前 RBS 重新评估 RI(电平触发) - ir = 0; - UpdateIrFromRbs(); - UpdateInterrupts(); - this.Log(LogLevel.Info, "Read IR: 0x{0:X2}, cleared", value); - break; + case Registers.IR: + value = ir; + ir = 0; + UpdateIrFromRbs(); + // 中断被软件清除,重置边沿检测状态,允许下次条件满足时再次触发中断 + lastInterruptState = false; + UpdateInterrupts(); + if (EnableVerboseLog) this.Log(LogLevel.Info, "Read IR: 0x{0:X2}, cleared", value); + break; - case Registers.IER: - value = ier; - this.Log(LogLevel.Info, "Read IER: 0x{0:X2}", value); - break; + case Registers.IER: + value = ier; + if (EnableVerboseLog) this.Log(LogLevel.Info, "Read IER: 0x{0:X2}", value); + break; - case Registers.BTR0: - value = btr0; - break; - case Registers.BTR1: - value = btr1; - break; - case Registers.OCR: - value = ocr; - break; - case Registers.RXERR: - value = rxerr; - break; - case Registers.TXERR: - value = txerr; - break; - case Registers.RBSA: - value = rbsa; - break; - case Registers.CDR: - value = cdr; - break; + case Registers.BTR0: + value = btr0; + break; + case Registers.BTR1: + value = btr1; + break; + case Registers.OCR: + value = ocr; + break; + case Registers.RXERR: + value = rxerr; + break; + case Registers.TXERR: + value = txerr; + break; + case Registers.RBSA: + value = rbsa; + break; + case Registers.CDR: + value = cdr; + break; - // 发送/接收缓冲区地址 16-26 - case Registers.TX_FRAME_INFO: - case Registers.TX_ID1: - case Registers.TX_ID2: - case Registers.TX_DATA1: - case Registers.TX_DATA2: - case Registers.TX_DATA3: - case Registers.TX_DATA4: - case Registers.TX_DATA5: - case Registers.TX_DATA6: - case Registers.TX_DATA7: - case Registers.TX_DATA8: - int bufIndex = (int)(offset - (long)Registers.TX_FRAME_INFO); - if (sr_rbs == 1) - { - // 接收缓冲区有数据时,读返回接收帧的内容 - value = rxBuffer[bufIndex/4]; - this.Log(LogLevel.Info, "Read RX buffer[{0}]: 0x{1:X2}", bufIndex/4, value); - } - else - { - //否则返回发送缓冲区的内容(通常无意义) - value = txBuffer[bufIndex/4]; - this.Log(LogLevel.Info, "Read TX buffer[{0}]: 0x{1:X2}", bufIndex/4, value); + // 发送/接收缓冲区地址 16-26 + case Registers.TX_FRAME_INFO: + case Registers.TX_ID1: + case Registers.TX_ID2: + case Registers.TX_DATA1: + case Registers.TX_DATA2: + case Registers.TX_DATA3: + case Registers.TX_DATA4: + case Registers.TX_DATA5: + case Registers.TX_DATA6: + case Registers.TX_DATA7: + case Registers.TX_DATA8: + int bufIndex = (int)(offset - (long)Registers.TX_FRAME_INFO) / 4; + if (sr_rbs == 1) + { + value = rxBuffer[bufIndex]; + if (EnableVerboseLog) this.Log(LogLevel.Info, "Read RX buffer[{0}]: 0x{1:X2}", bufIndex, value); + } + else + { + value = txBuffer[bufIndex]; + if (EnableVerboseLog) this.Log(LogLevel.Info, "Read TX buffer[{0}]: 0x{1:X2}", bufIndex, value); + } + break; - } - break; - - default: - // 未实现的寄存器返回0 - this.Log(LogLevel.Info, "Read from unimplemented offset 0x{0:X}", offset); - value = 0; - break; + default: + if (EnableVerboseLog) this.Log(LogLevel.Info, "Read from unimplemented offset 0x{0:X}", offset); + value = 0; + break; + } } return value; } public void WriteByte(long offset, byte value) { - switch ((Registers)offset) + lock (lockObject) { - case Registers.MOD: - mod = value; - this.Log(LogLevel.Info, "Write MOD: 0x{0:X2}", value); - break; + switch ((Registers)offset) + { + case Registers.MOD: + mod = value; + if (EnableVerboseLog) this.Log(LogLevel.Info, "Write MOD: 0x{0:X2}", value); + break; - case Registers.CMR: - // 命令寄存器只写,处理命令 - this.Log(LogLevel.Info, "Write CMR: 0x{0:X2}", value); - if ((value & CMR_TR) != 0) - { - // 发送请求 + case Registers.CMR: + if (EnableVerboseLog) this.Log(LogLevel.Info, "Write CMR: 0x{0:X2}", value); + if ((value & CMR_TR) != 0) + { + // 发送请求 + if (sr_tbs == 1) + { + var frame = new byte[11]; + + if (txFrameQueue.Count < (MaxTxQueueSize - 1)) + { + Array.Copy(txBuffer, frame, 11); + txFrameQueue.Enqueue(frame); + Array.Clear(txBuffer, 0, txBuffer.Length); + sr_tbs = 1; + if (EnableVerboseLog) this.Log(LogLevel.Info, "Frame enqueued for transmission, queue size: {0}", txFrameQueue.Count); + } + else if (txFrameQueue.Count == (MaxTxQueueSize - 1)) + { + Array.Copy(txBuffer, frame, 11); + txFrameQueue.Enqueue(frame); + Array.Clear(txBuffer, 0, txBuffer.Length); + sr_tbs = 0; + if (EnableVerboseLog) this.Log(LogLevel.Info, "Frame enqueued, TX queue now full, TBS cleared"); + } + else + { + sr_tbs = 0; + if (EnableVerboseLog) this.Log(LogLevel.Warning, "Send request while TBS=0 ignored"); + } + } + else + { + if (EnableVerboseLog) this.Log(LogLevel.Warning, "Send request while TBS=0 ignored"); + } + } + if ((value & CMR_RRB) != 0) + { + LoadNextRxFrame(); + if (EnableVerboseLog) this.Log(LogLevel.Info, "Receive buffer released"); + } + if ((value & CMR_CDO) != 0) + { + // 清除数据溢出(无操作,但保留接口) + if (EnableVerboseLog) this.Log(LogLevel.Info, "Clear data overflow (no effect)"); + } + break; + + case Registers.SR: + if (EnableVerboseLog) this.Log(LogLevel.Warning, "Attempted write to read-only SR"); + break; + + case Registers.IR: + if (EnableVerboseLog) this.Log(LogLevel.Warning, "Attempted write to read-only IR"); + break; + + case Registers.IER: + ier = (byte)(value & 0x01); + UpdateIrFromRbs(); + UpdateInterrupts(); + if (EnableVerboseLog) this.Log(LogLevel.Info, "Write IER: 0x{0:X2}", ier); + break; + + case Registers.BTR0: + btr0 = value; + if (EnableVerboseLog) this.Log(LogLevel.Info, "Write BTR0: 0x{0:X2}", value); + break; + case Registers.BTR1: + btr1 = value; + if (EnableVerboseLog) this.Log(LogLevel.Info, "Write BTR1: 0x{0:X2}", value); + break; + case Registers.OCR: + ocr = value; + if (EnableVerboseLog) this.Log(LogLevel.Info, "Write OCR: 0x{0:X2}", value); + break; + case Registers.RXERR: + rxerr = value; + if (EnableVerboseLog) this.Log(LogLevel.Info, "Write RXERR: 0x{0:X2}", value); + break; + case Registers.TXERR: + txerr = value; + if (EnableVerboseLog) this.Log(LogLevel.Info, "Write TXERR: 0x{0:X2}", value); + break; + case Registers.RBSA: + rbsa = value; + if (EnableVerboseLog) this.Log(LogLevel.Info, "Write RBSA: 0x{0:X2}", value); + break; + case Registers.CDR: + cdr = value; + if (EnableVerboseLog) this.Log(LogLevel.Info, "Write CDR: 0x{0:X2}", value); + break; + + // 发送缓冲区写入 + case Registers.TX_FRAME_INFO: + case Registers.TX_ID1: + case Registers.TX_ID2: + case Registers.TX_DATA1: + case Registers.TX_DATA2: + case Registers.TX_DATA3: + case Registers.TX_DATA4: + case Registers.TX_DATA5: + case Registers.TX_DATA6: + case Registers.TX_DATA7: + case Registers.TX_DATA8: + int bufIndex = (int)(offset - (long)Registers.TX_FRAME_INFO) / 4; if (sr_tbs == 1) { - // 将当前 txBuffer 复制一份加入发送队列 - var frame = new byte[11]; - Array.Copy(txBuffer, frame, 11); - lock (lockObject) - { - txFrameQueue.Enqueue(frame); - } - // 清空发送缓冲区,并立即释放 TBS,允许 CPU 继续写入下一帧 - Array.Clear(txBuffer, 0, txBuffer.Length); - sr_tbs = 1; - this.Log(LogLevel.Info, "Frame enqueued for transmission, queue size: {0}", txFrameQueue.Count); + txBuffer[bufIndex] = value; + if (EnableVerboseLog) this.Log(LogLevel.Info, "Write TX buffer[{0}]: 0x{1:X2}", bufIndex, value); } else { - this.Log(LogLevel.Warning, "Send request while TBS=0 ignored"); + if (EnableVerboseLog) this.Log(LogLevel.Warning, "Write to TX buffer while TBS=0 ignored"); } - } - if ((value & CMR_RRB) != 0) - { - // 释放接收缓冲器:尝试从接收队列中加载下一帧 - lock (lockObject) - { - LoadNextRxFrame(); - } - this.Log(LogLevel.Info, "Receive buffer released"); - } - if ((value & CMR_CDO) != 0) - { - // 清除数据溢出(无操作) - this.Log(LogLevel.Info, "Clear data overflow (no effect)"); - } - break; + break; - case Registers.SR: - if (sr_tbs == 1) - { - sr_tbs = 0; - } - else - { - sr_tbs = 1; - } - if (sr_rbs == 1) - { - sr_rbs = 0; - } - else - { - sr_rbs = 1; - } - break; - case Registers.IR: - // 只读,忽略写 - this.Log(LogLevel.Warning, "Attempted write to read-only IR"); - break; - - case Registers.IER: - ier = (byte)(value & 0x01); // 只使用 bit0 (RIE) - UpdateIrFromRbs(); - UpdateInterrupts(); - this.Log(LogLevel.Info, "Write IER: 0x{0:X2}", ier); - break; - - case Registers.BTR0: - btr0 = value; - this.Log(LogLevel.Info, "Write BTR0: 0x{0:X2}", value); - break; - case Registers.BTR1: - btr1 = value; - this.Log(LogLevel.Info, "Write BTR1: 0x{0:X2}", value); - break; - case Registers.OCR: - ocr = value; - this.Log(LogLevel.Info, "Write OCR: 0x{0:X2}", value); - break; - case Registers.RXERR: - rxerr = value; - this.Log(LogLevel.Info, "Write RXERR: 0x{0:X2}", value); - break; - case Registers.TXERR: - txerr = value; - this.Log(LogLevel.Info, "Write TXERR: 0x{0:X2}", value); - break; - case Registers.RBSA: - rbsa = value; - this.Log(LogLevel.Info, "Write RBSA: 0x{0:X2}", value); - break; - case Registers.CDR: - cdr = value; - this.Log(LogLevel.Info, "Write CDR: 0x{0:X2}", value); - break; - - // 发送缓冲区写入 - case Registers.TX_FRAME_INFO: - case Registers.TX_ID1: - case Registers.TX_ID2: - case Registers.TX_DATA1: - case Registers.TX_DATA2: - case Registers.TX_DATA3: - case Registers.TX_DATA4: - case Registers.TX_DATA5: - case Registers.TX_DATA6: - case Registers.TX_DATA7: - case Registers.TX_DATA8: - int bufIndex = (int)(offset - (long)Registers.TX_FRAME_INFO); - if (sr_tbs == 1) - { - txBuffer[bufIndex/4] = value; - this.Log(LogLevel.Info, "Write TX buffer[{0}]: 0x{1:X2}", bufIndex/4, value); - } - else - { - this.Log(LogLevel.Warning, "Write to TX buffer while TBS=0 ignored"); - } - break; - - default: - // 未实现的寄存器忽略写 - this.Log(LogLevel.Info, "Write to unimplemented offset 0x{0:X} = 0x{1:X2}", offset, value); - break; + default: + if (EnableVerboseLog) this.Log(LogLevel.Info, "Write to unimplemented offset 0x{0:X} = 0x{1:X2}", offset, value); + break; + } } } - // ================ 公共方法与事件 ================ + // ================ 内部辅助方法 ================ private void UpdateIrFromRbs() { if (sr_rbs == 1) ir |= IR_RI; else - ir = (byte)(ir & ~IR_RI); + ir = (byte)(ir & ~IR_RI); } private void UpdateInterrupts() { - bool interrupt = ((ir & IR_RI) != 0) && ((ier & IER_RIE) != 0); - IRQ.Set(interrupt); - if (interrupt) + bool currentInterrupt = ((ir & IR_RI) != 0) && ((ier & IER_RIE) != 0); + if (currentInterrupt && !lastInterruptState) { + IRQ.Set(true); machine.ScheduleAction(TimeInterval.FromMicroseconds(1), _ => { IRQ.Set(false); }); - this.Log(LogLevel.Info, "Interrupt asserted (RI)"); - } - else - { - this.Log(LogLevel.Info, "Interrupt deasserted"); - } + if (EnableVerboseLog) this.Log(LogLevel.Info, "Interrupt pulse generated (RI)"); + } + lastInterruptState = currentInterrupt; } - private readonly object lockObject = new object(); // 用于线程安全的锁对象 + + private readonly object lockObject = new object(); /// /// 获取发送队列中所有帧的字符串表示(每帧以空格分隔的十六进制字节,帧间用换行分隔) - /// 调用后清空发送队列。 + /// 调用后清空发送队列,并恢复发送缓冲区状态(如果之前因队列满被锁定)。 /// public string GetTxBufferDataString() { @@ -349,7 +352,8 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals { if (txFrameQueue.Count == 0) { - Console.WriteLine("GetTxBufferDataString: no frames in TX queue"); + if (EnableVerboseLog) Console.WriteLine("GetTxBufferDataString: no frames in TX queue"); + if (sr_tbs == 0) sr_tbs = 1; return null; } var sb = new StringBuilder(); @@ -361,17 +365,19 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals if (i > 0) sb.Append(" "); sb.Append(frame[i].ToString("X2")); } - sb.AppendLine(); // 帧间换行 + sb.AppendLine(); } string result = sb.ToString().TrimEnd(); - Console.WriteLine("GetTxBufferDataString returning: " + result); + sr_tbs = 1; + if (EnableVerboseLog) Console.WriteLine("GetTxBufferDataString returning: " + result); return result; } } - + /// /// 外部接口注入一帧接收数据(11字节的十六进制字符串,空格分隔) /// 可多次调用以注入多帧,帧将存入接收队列。 + /// 若接收队列已满,则新帧被丢弃。 /// public void SendRxBufferDataString(string frameString) { @@ -379,13 +385,13 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals { if (string.IsNullOrWhiteSpace(frameString)) { - Console.WriteLine("SendRxBufferDataString: empty string, ignored"); + if (EnableVerboseLog) Console.WriteLine("SendRxBufferDataString: empty string, ignored"); return; } string[] parts = frameString.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length != 11) { - Console.WriteLine($"SendRxBufferDataString: expected 11 bytes, got {parts.Length}, ignored"); + if (EnableVerboseLog) Console.WriteLine($"SendRxBufferDataString: expected 11 bytes, got {parts.Length}, ignored"); return; } byte[] frame = new byte[11]; @@ -395,15 +401,21 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals if (!byte.TryParse(part, System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture, out byte b)) { - Console.WriteLine($"SendRxBufferDataString: invalid hex byte '{part}' at index {i}, set to 0"); + if (EnableVerboseLog) Console.WriteLine($"SendRxBufferDataString: invalid hex byte '{part}' at index {i}, set to 0"); b = 0; } frame[i] = b; } - rxFrameQueue.Enqueue(frame); - Console.WriteLine($"Frame enqueued to RX queue, size: {rxFrameQueue.Count}"); - // 如果当前接收缓冲区空闲,立即加载第一帧 + if (rxFrameQueue.Count >= MaxRxQueueSize) + { + if (EnableVerboseLog) Console.WriteLine($"SendRxBufferDataString: RX queue full (max={MaxRxQueueSize}), frame dropped"); + return; + } + + rxFrameQueue.Enqueue(frame); + if (EnableVerboseLog) Console.WriteLine($"Frame enqueued to RX queue, size: {rxFrameQueue.Count}"); + if (sr_rbs == 0) { LoadNextRxFrame(); @@ -411,7 +423,6 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals } } - // 从接收队列中加载下一帧到 rxBuffer,并更新状态 private void LoadNextRxFrame() { if (rxFrameQueue.Count > 0) @@ -421,20 +432,20 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals sr_rbs = 1; UpdateIrFromRbs(); UpdateInterrupts(); - Console.WriteLine("Loaded next RX frame into buffer, queue remaining: {0}", rxFrameQueue.Count); + if (EnableVerboseLog) Console.WriteLine("Loaded next RX frame into buffer, queue remaining: {0}", rxFrameQueue.Count); } else { sr_rbs = 0; UpdateIrFromRbs(); UpdateInterrupts(); - Console.WriteLine("RX queue empty, buffer cleared"); + if (EnableVerboseLog) Console.WriteLine("RX queue empty, buffer cleared"); } } // ================ 属性 ================ - public long Size => 0x80; // 地址范围 0-31 + public long Size => 0x80; public GPIO IRQ { get; } @@ -444,15 +455,15 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals { MOD = 0x00, CMR = 0x04, - SR = 0x08, - IR = 0x0C, + SR = 0x08, + IR = 0x0C, IER = 0x10, BTR0 = 0x18, BTR1 = 0x1C, - OCR = 0x20, - RXERR = 0x38, // 14 - TXERR = 0x3C, // 15 - TX_FRAME_INFO = 0x40, // 16 + OCR = 0x20, + RXERR = 0x38, + TXERR = 0x3C, + TX_FRAME_INFO = 0x40, TX_ID1 = 0x44, TX_ID2 = 0x48, TX_DATA1 = 0x4C, @@ -462,31 +473,28 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals TX_DATA5 = 0x5C, TX_DATA6 = 0x60, TX_DATA7 = 0x64, - TX_DATA8 = 0x68, // 26 - RBSA = 0x78, // 30 - CDR = 0x7C, // 31 - + TX_DATA8 = 0x68, + RBSA = 0x78, + CDR = 0x7C, } // ================ 常量位定义 ================ - private const byte CMR_TR = 0x01; // 发送请求 (bit0) - private const byte CMR_RRB = 0x04; // 释放接收缓冲器 (bit2) - private const byte CMR_CDO = 0x08; // 清除数据溢出 (bit3) + private const byte CMR_TR = 0x01; + private const byte CMR_RRB = 0x04; + private const byte CMR_CDO = 0x08; - private const byte SR_BS = 0x80; // 总线状态 (bit7) - 本模拟中恒0 - private const byte SR_TBS = 0x04; // 发送缓冲器状态 (bit2) - private const byte SR_RBS = 0x01; // 接收缓冲器状态 (bit0) + private const byte SR_BS = 0x80; + private const byte SR_TBS = 0x04; + private const byte SR_RBS = 0x01; - private const byte IR_RI = 0x01; // 接收中断 (bit0) - - private const byte IER_RIE = 0x01; // 接收中断使能 (bit0) + private const byte IR_RI = 0x01; + private const byte IER_RIE = 0x01; // ================ 私有字段 ================ private readonly IMachine machine; - // 寄存器存储 private byte mod; private byte ier; private byte btr0, btr1; @@ -495,16 +503,16 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals private byte rbsa; private byte cdr; - // 状态位 - private byte sr_tbs; // 1=空闲 - private byte sr_rbs; // 1=有数据 + private byte sr_tbs; + private byte sr_rbs; + private byte ir; - private byte ir; // 仅 bit0 有效 + private bool lastInterruptState; // 用于中断边沿检测 - private readonly byte[] txBuffer; // 临时发送缓冲区(单帧) - private readonly byte[] rxBuffer; // 当前接收帧(单帧) + private readonly byte[] txBuffer; + private readonly byte[] rxBuffer; - private readonly Queue txFrameQueue; // 发送队列 - private readonly Queue rxFrameQueue; // 接收队列 + private readonly Queue txFrameQueue; + private readonly Queue rxFrameQueue; } } \ No newline at end of file