更新 SJA1000_CAN.cs

This commit is contained in:
2026-05-25 15:33:24 +08:00
parent 1bad9fd8ce
commit d07b18df57

View File

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