更新 SJA1000_CAN.cs

修改缓冲区为队列
This commit is contained in:
2026-04-17 08:55:34 +08:00
parent 14e8fcb94b
commit dc5c201933

View File

@@ -1,480 +1,510 @@
// //
// 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无数据溢出处理。 // 接收为单帧,无 FIFO无数据溢出处理。
// 所有寄存器可随时读写,无复位模式限制。 // 所有寄存器可随时读写,无复位模式限制。
// //
// author: Generated based on UART16550 template // author: Generated based on UART16550 template
// //
using System; using System;
using System.Text; using System.Text;
using System.Collections.Generic; using System.Collections.Generic;
using Antmicro.Renode.Core; using Antmicro.Renode.Core;
using Antmicro.Renode.Logging; using Antmicro.Renode.Logging;
using Antmicro.Renode.Peripherals.Bus; using Antmicro.Renode.Peripherals.Bus;
using Antmicro.Renode.Utilities; using Antmicro.Renode.Utilities;
using Antmicro.Renode.Time; using Antmicro.Renode.Time;
namespace Antmicro.Renode.Peripherals.CustomPeripherals namespace Antmicro.Renode.Peripherals.CustomPeripherals
{ {
/// <summary> /// <summary>
/// 简化版 SJA1000 CAN 控制器PeliCAN 模式,仅标准帧) /// 简化版 SJA1000 CAN 控制器PeliCAN 模式,仅标准帧)
/// </summary> /// </summary>
public class SJA1000_CAN : IDoubleWordPeripheral, IBytePeripheral, IKnownSize public class SJA1000_CAN : IDoubleWordPeripheral, IBytePeripheral, IKnownSize
{ {
public SJA1000_CAN(IMachine machine) public SJA1000_CAN(IMachine machine)
{ {
this.machine = machine; this.machine = machine;
IRQ = new GPIO(); IRQ = new GPIO();
txBuffer = new byte[11]; txBuffer = new byte[11];
rxBuffer = new byte[11]; rxBuffer = new byte[11];
txFrameQueue = new Queue<byte[]>(); // 新增:发送队列
Reset(); rxFrameQueue = new Queue<byte[]>(); // 新增:接收队列
}
Reset();
public void Reset() }
{
mod = 0; public void Reset()
ier = 0; {
btr0 = 0; mod = 0;
btr1 = 0; ier = 0;
ocr = 0; btr0 = 0;
rxerr = 0; btr1 = 0;
txerr = 0; ocr = 0;
rbsa = 0; rxerr = 0;
cdr = 0; txerr = 0;
rbsa = 0;
sr_tbs = 1; // 发送缓冲区初始为空闲 cdr = 0;
sr_rbs = 0; // 接收缓冲区初始为空
ir = 0; sr_tbs = 1; // 发送缓冲区初始为空闲
sr_rbs = 0; // 接收缓冲区初始为空
Array.Clear(txBuffer, 0, txBuffer.Length); ir = 0;
Array.Clear(rxBuffer, 0, rxBuffer.Length);
Array.Clear(txBuffer, 0, txBuffer.Length);
UpdateInterrupts(); Array.Clear(rxBuffer, 0, rxBuffer.Length);
txFrameQueue.Clear(); // 清空发送队列
this.Log(LogLevel.Info, "SJA1000 CAN controller reset (simplified)"); rxFrameQueue.Clear(); // 清空接收队列
}
UpdateInterrupts();
// ================ IBusPeripheral 接口实现 ================
this.Log(LogLevel.Info, "SJA1000 CAN controller reset (simplified)");
public uint ReadDoubleWord(long offset) }
{
return ReadByte(offset); // ================ IBusPeripheral 接口实现 ================
}
public uint ReadDoubleWord(long offset)
public void WriteDoubleWord(long offset, uint value) {
{ return ReadByte(offset);
WriteByte(offset, (byte)value); }
}
public void WriteDoubleWord(long offset, uint value)
public byte ReadByte(long offset) {
{ WriteByte(offset, (byte)value);
byte value = 0; }
switch ((Registers)offset)
{ public byte ReadByte(long offset)
case Registers.MOD: {
value = mod; byte value = 0;
this.Log(LogLevel.Info, "Read MOD: 0x{0:X2}", value); switch ((Registers)offset)
break; {
case Registers.MOD:
case Registers.CMR: value = mod;
// 命令寄存器只写读返回0 this.Log(LogLevel.Info, "Read MOD: 0x{0:X2}", value);
this.Log(LogLevel.Info, "Read CMR (always 0)"); break;
value = 0;
break; case Registers.CMR:
// 命令寄存器只写读返回0
case Registers.SR: this.Log(LogLevel.Info, "Read CMR (always 0)");
value = (byte)((sr_tbs << 2) | sr_rbs); // BS 恒为0 value = 0;
this.Log(LogLevel.Info, "Read SR: TBS={0}, RBS={1} -> 0x{2:X2}", sr_tbs, sr_rbs, value); break;
break;
case Registers.SR:
case Registers.IR: value = (byte)((sr_tbs << 2) | sr_rbs); // BS 恒为0
value = ir; this.Log(LogLevel.Info, "Read SR: TBS={0}, RBS={1} -> 0x{2:X2}", sr_tbs, sr_rbs, value);
// 读 IR 后清零,但需要根据当前 RBS 重新评估 RI电平触发 break;
ir = 0;
UpdateIrFromRbs(); case Registers.IR:
UpdateInterrupts(); value = ir;
this.Log(LogLevel.Info, "Read IR: 0x{0:X2}, cleared", value); // 读 IR 后清零,但需要根据当前 RBS 重新评估 RI电平触发
break; ir = 0;
UpdateIrFromRbs();
case Registers.IER: UpdateInterrupts();
value = ier; this.Log(LogLevel.Info, "Read IR: 0x{0:X2}, cleared", value);
this.Log(LogLevel.Info, "Read IER: 0x{0:X2}", value); break;
break;
case Registers.IER:
case Registers.BTR0: value = ier;
value = btr0; this.Log(LogLevel.Info, "Read IER: 0x{0:X2}", value);
break; break;
case Registers.BTR1:
value = btr1; case Registers.BTR0:
break; value = btr0;
case Registers.OCR: break;
value = ocr; case Registers.BTR1:
break; value = btr1;
case Registers.RXERR: break;
value = rxerr; case Registers.OCR:
break; value = ocr;
case Registers.TXERR: break;
value = txerr; case Registers.RXERR:
break; value = rxerr;
case Registers.RBSA: break;
value = rbsa; case Registers.TXERR:
break; value = txerr;
case Registers.CDR: break;
value = cdr; case Registers.RBSA:
break; value = rbsa;
break;
// 发送/接收缓冲区地址 16-26 case Registers.CDR:
case Registers.TX_FRAME_INFO: value = cdr;
case Registers.TX_ID1: break;
case Registers.TX_ID2:
case Registers.TX_DATA1: // 发送/接收缓冲区地址 16-26
case Registers.TX_DATA2: case Registers.TX_FRAME_INFO:
case Registers.TX_DATA3: case Registers.TX_ID1:
case Registers.TX_DATA4: case Registers.TX_ID2:
case Registers.TX_DATA5: case Registers.TX_DATA1:
case Registers.TX_DATA6: case Registers.TX_DATA2:
case Registers.TX_DATA7: case Registers.TX_DATA3:
case Registers.TX_DATA8: case Registers.TX_DATA4:
int bufIndex = (int)(offset - (long)Registers.TX_FRAME_INFO); case Registers.TX_DATA5:
if (sr_rbs == 1) case Registers.TX_DATA6:
{ case Registers.TX_DATA7:
// 接收缓冲区有数据时,读返回接收帧的内容 case Registers.TX_DATA8:
value = rxBuffer[bufIndex/4]; int bufIndex = (int)(offset - (long)Registers.TX_FRAME_INFO);
this.Log(LogLevel.Info, "Read RX buffer[{0}]: 0x{1:X2}", bufIndex/4, value); if (sr_rbs == 1)
} {
else // 接收缓冲区有数据时,读返回接收帧的内容
{ value = rxBuffer[bufIndex/4];
//否则返回发送缓冲区的内容(通常无意义) this.Log(LogLevel.Info, "Read RX buffer[{0}]: 0x{1:X2}", bufIndex/4, value);
value = txBuffer[bufIndex/4]; }
this.Log(LogLevel.Info, "Read TX buffer[{0}]: 0x{1:X2}", bufIndex/4, value); else
{
} //否则返回发送缓冲区的内容(通常无意义)
break; value = txBuffer[bufIndex/4];
this.Log(LogLevel.Info, "Read TX buffer[{0}]: 0x{1:X2}", bufIndex/4, value);
default:
// 未实现的寄存器返回0 }
this.Log(LogLevel.Info, "Read from unimplemented offset 0x{0:X}", offset); break;
value = 0;
break; default:
} // 未实现的寄存器返回0
return value; this.Log(LogLevel.Info, "Read from unimplemented offset 0x{0:X}", offset);
} value = 0;
break;
public void WriteByte(long offset, byte value) }
{ return value;
switch ((Registers)offset) }
{
case Registers.MOD: public void WriteByte(long offset, byte value)
mod = value; {
this.Log(LogLevel.Info, "Write MOD: 0x{0:X2}", value); switch ((Registers)offset)
break; {
case Registers.MOD:
case Registers.CMR: mod = value;
// 命令寄存器只写,处理命令 this.Log(LogLevel.Info, "Write MOD: 0x{0:X2}", value);
this.Log(LogLevel.Info, "Write CMR: 0x{0:X2}", value); break;
if ((value & CMR_TR) != 0)
{ case Registers.CMR:
// 发送请求 // 命令寄存器只写,处理命令
if (sr_tbs == 1) this.Log(LogLevel.Info, "Write CMR: 0x{0:X2}", value);
{ if ((value & CMR_TR) != 0)
sr_tbs = 0; // 锁定发送缓冲区 {
/*** 测试 ***/ // 发送请求
GetTxBufferDataString(); if (sr_tbs == 1)
} {
else // 将当前 txBuffer 复制一份加入发送队列
{ var frame = new byte[11];
this.Log(LogLevel.Warning, "Send request while TBS=0 ignored"); Array.Copy(txBuffer, frame, 11);
} lock (lockObject)
} {
if ((value & CMR_RRB) != 0) txFrameQueue.Enqueue(frame);
{ }
// 释放接收缓冲器 // 清空发送缓冲区,并立即释放 TBS允许 CPU 继续写入下一帧
sr_rbs = 0; Array.Clear(txBuffer, 0, txBuffer.Length);
UpdateIrFromRbs(); sr_tbs = 1;
UpdateInterrupts(); this.Log(LogLevel.Info, "Frame enqueued for transmission, queue size: {0}", txFrameQueue.Count);
this.Log(LogLevel.Info, "Receive buffer released"); }
} else
if ((value & CMR_CDO) != 0) {
{ this.Log(LogLevel.Warning, "Send request while TBS=0 ignored");
// 清除数据溢出(无操作) }
this.Log(LogLevel.Info, "Clear data overflow (no effect)"); }
} if ((value & CMR_RRB) != 0)
break; {
// 释放接收缓冲器:尝试从接收队列中加载下一帧
case Registers.SR: lock (lockObject)
if (sr_tbs == 1) {
{ LoadNextRxFrame();
sr_tbs = 0; }
} this.Log(LogLevel.Info, "Receive buffer released");
else }
{ if ((value & CMR_CDO) != 0)
sr_tbs = 1; {
} // 清除数据溢出(无操作)
if (sr_rbs == 1) this.Log(LogLevel.Info, "Clear data overflow (no effect)");
{ }
sr_rbs = 0; break;
}
else case Registers.SR:
{ if (sr_tbs == 1)
sr_rbs = 1; {
} sr_tbs = 0;
break; }
case Registers.IR: else
// 只读,忽略写 {
this.Log(LogLevel.Warning, "Attempted write to read-only IR"); sr_tbs = 1;
break; }
if (sr_rbs == 1)
case Registers.IER: {
ier = (byte)(value & 0x01); // 只使用 bit0 (RIE) sr_rbs = 0;
UpdateIrFromRbs(); }
UpdateInterrupts(); else
this.Log(LogLevel.Info, "Write IER: 0x{0:X2}", ier); {
break; sr_rbs = 1;
}
case Registers.BTR0: break;
btr0 = value; case Registers.IR:
this.Log(LogLevel.Info, "Write BTR0: 0x{0:X2}", value); // 只读,忽略写
break; this.Log(LogLevel.Warning, "Attempted write to read-only IR");
case Registers.BTR1: break;
btr1 = value;
this.Log(LogLevel.Info, "Write BTR1: 0x{0:X2}", value); case Registers.IER:
break; ier = (byte)(value & 0x01); // 只使用 bit0 (RIE)
case Registers.OCR: UpdateIrFromRbs();
ocr = value; UpdateInterrupts();
this.Log(LogLevel.Info, "Write OCR: 0x{0:X2}", value); this.Log(LogLevel.Info, "Write IER: 0x{0:X2}", ier);
break; break;
case Registers.RXERR:
rxerr = value; case Registers.BTR0:
this.Log(LogLevel.Info, "Write RXERR: 0x{0:X2}", value); btr0 = value;
break; this.Log(LogLevel.Info, "Write BTR0: 0x{0:X2}", value);
case Registers.TXERR: break;
txerr = value; case Registers.BTR1:
this.Log(LogLevel.Info, "Write TXERR: 0x{0:X2}", value); btr1 = value;
break; this.Log(LogLevel.Info, "Write BTR1: 0x{0:X2}", value);
case Registers.RBSA: break;
rbsa = value; case Registers.OCR:
this.Log(LogLevel.Info, "Write RBSA: 0x{0:X2}", value); ocr = value;
break; this.Log(LogLevel.Info, "Write OCR: 0x{0:X2}", value);
case Registers.CDR: break;
cdr = value; case Registers.RXERR:
this.Log(LogLevel.Info, "Write CDR: 0x{0:X2}", value); rxerr = value;
break; this.Log(LogLevel.Info, "Write RXERR: 0x{0:X2}", value);
break;
// 发送缓冲区写入 case Registers.TXERR:
case Registers.TX_FRAME_INFO: txerr = value;
case Registers.TX_ID1: this.Log(LogLevel.Info, "Write TXERR: 0x{0:X2}", value);
case Registers.TX_ID2: break;
case Registers.TX_DATA1: case Registers.RBSA:
case Registers.TX_DATA2: rbsa = value;
case Registers.TX_DATA3: this.Log(LogLevel.Info, "Write RBSA: 0x{0:X2}", value);
case Registers.TX_DATA4: break;
case Registers.TX_DATA5: case Registers.CDR:
case Registers.TX_DATA6: cdr = value;
case Registers.TX_DATA7: this.Log(LogLevel.Info, "Write CDR: 0x{0:X2}", value);
case Registers.TX_DATA8: break;
int bufIndex = (int)(offset - (long)Registers.TX_FRAME_INFO);
if (sr_tbs == 1) // 发送缓冲区写入
{ case Registers.TX_FRAME_INFO:
txBuffer[bufIndex/4] = value; case Registers.TX_ID1:
this.Log(LogLevel.Info, "Write TX buffer[{0}]: 0x{1:X2}", bufIndex/4, value); case Registers.TX_ID2:
} case Registers.TX_DATA1:
else case Registers.TX_DATA2:
{ case Registers.TX_DATA3:
this.Log(LogLevel.Warning, "Write to TX buffer while TBS=0 ignored"); case Registers.TX_DATA4:
} case Registers.TX_DATA5:
break; case Registers.TX_DATA6:
case Registers.TX_DATA7:
default: case Registers.TX_DATA8:
// 未实现的寄存器忽略写 int bufIndex = (int)(offset - (long)Registers.TX_FRAME_INFO);
this.Log(LogLevel.Info, "Write to unimplemented offset 0x{0:X} = 0x{1:X2}", offset, value); if (sr_tbs == 1)
break; {
} 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;
private void UpdateIrFromRbs()
{ default:
if (sr_rbs == 1) // 未实现的寄存器忽略写
ir |= IR_RI; this.Log(LogLevel.Info, "Write to unimplemented offset 0x{0:X} = 0x{1:X2}", offset, value);
else break;
// ir &= (byte)~IR_RI; }
ir = (byte)(ir & ~IR_RI); }
}
// ================ 公共方法与事件 ================
private void UpdateInterrupts()
{ private void UpdateIrFromRbs()
bool interrupt = ((ir & IR_RI) != 0) && ((ier & IER_RIE) != 0); {
IRQ.Set(interrupt); if (sr_rbs == 1)
if (interrupt) ir |= IR_RI;
{ else
machine.ScheduleAction(TimeInterval.FromMicroseconds(1), _ => ir = (byte)(ir & ~IR_RI);
{ }
IRQ.Set(false);
}); private void UpdateInterrupts()
this.Log(LogLevel.Info, "Interrupt asserted (RI)"); {
} bool interrupt = ((ir & IR_RI) != 0) && ((ier & IER_RIE) != 0);
else IRQ.Set(interrupt);
{ if (interrupt)
this.Log(LogLevel.Info, "Interrupt deasserted"); {
} machine.ScheduleAction(TimeInterval.FromMicroseconds(1), _ =>
} {
private readonly object lockObject = new object(); // 用于线程安全的锁对象 IRQ.Set(false);
});
public string GetTxBufferDataString() this.Log(LogLevel.Info, "Interrupt asserted (RI)");
{ }
if(sr_tbs ==1) else
{ {
Console.WriteLine("sr_tbs=1"); this.Log(LogLevel.Info, "Interrupt deasserted");
return null; }
} }
lock (lockObject) private readonly object lockObject = new object(); // 用于线程安全的锁对象
{
var sb = new StringBuilder(); /// <summary>
for (int i = 0; i < txBuffer.Length; i++) /// 获取发送队列中所有帧的字符串表示(每帧以空格分隔的十六进制字节,帧间用换行分隔)
{ /// 调用后清空发送队列。
if (i > 0) sb.Append(" "); /// </summary>
sb.Append(txBuffer[i].ToString("X2")); public string GetTxBufferDataString()
} {
string result = sb.ToString(); lock (lockObject)
Console.WriteLine("GetTxBufferDataString returning: " + result); {
Array.Clear(txBuffer, 0, txBuffer.Length); if (txFrameQueue.Count == 0)
sr_tbs = 1; {
return result; Console.WriteLine("GetTxBufferDataString: no frames in TX queue");
} return null;
} }
var sb = new StringBuilder();
public void SendRxBufferDataString(string frameString) while (txFrameQueue.Count > 0)
{ {
lock (lockObject) var frame = txFrameQueue.Dequeue();
{ for (int i = 0; i < frame.Length; i++)
{
if (i > 0) sb.Append(" ");
if (string.IsNullOrWhiteSpace(frameString)) sb.Append(frame[i].ToString("X2"));
{ }
Console.WriteLine("ReceiveFrame: empty string, ignored"); sb.AppendLine(); // 帧间换行
return; }
} string result = sb.ToString().TrimEnd();
if (sr_rbs==1) Console.WriteLine("GetTxBufferDataString returning: " + result);
{ return result;
Console.WriteLine("rxBuffer is full"); }
return; }
}
Array.Clear(rxBuffer, 0, rxBuffer.Length); /// <summary>
string[] parts = frameString.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); /// 外部接口注入一帧接收数据11字节的十六进制字符串空格分隔
int count = Math.Min(parts.Length, rxBuffer.Length); /// 可多次调用以注入多帧,帧将存入接收队列。
/// </summary>
for (int i = 0; i < count; i++) public void SendRxBufferDataString(string frameString)
{ {
string part = parts[i].Trim(); lock (lockObject)
if (byte.TryParse(part, System.Globalization.NumberStyles.HexNumber, {
System.Globalization.CultureInfo.InvariantCulture, out byte b)) if (string.IsNullOrWhiteSpace(frameString))
{ {
rxBuffer[i] = b; Console.WriteLine("SendRxBufferDataString: empty string, ignored");
} return;
else }
{ string[] parts = frameString.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
Console.WriteLine($"ReceiveFrame: invalid hex byte '{part}' at index {i}, set to 0"); if (parts.Length != 11)
rxBuffer[i] = 0; {
} Console.WriteLine($"SendRxBufferDataString: expected 11 bytes, got {parts.Length}, ignored");
} return;
}
sr_rbs = 1; byte[] frame = new byte[11];
UpdateIrFromRbs(); for (int i = 0; i < 11; i++)
UpdateInterrupts(); {
string part = parts[i].Trim();
// 打印 rxBuffer 内容 if (!byte.TryParse(part, System.Globalization.NumberStyles.HexNumber,
var sb = new StringBuilder(); System.Globalization.CultureInfo.InvariantCulture, out byte b))
sb.Append("RX Buffer after receive: "); {
for (int i = 0; i < rxBuffer.Length; i++) Console.WriteLine($"SendRxBufferDataString: invalid hex byte '{part}' at index {i}, set to 0");
{ b = 0;
if (i > 0) sb.Append(" "); }
sb.Append(rxBuffer[i].ToString("X2")); frame[i] = b;
} }
Console.WriteLine(sb.ToString()); rxFrameQueue.Enqueue(frame);
Console.WriteLine($"Frame enqueued to RX queue, size: {rxFrameQueue.Count}");
Console.WriteLine($"Frame received from string: {frameString}");
} // 如果当前接收缓冲区空闲,立即加载第一帧
} if (sr_rbs == 0)
// ================ 属性 ================ {
LoadNextRxFrame();
public long Size => 0x80; // 地址范围 0-31 }
}
public GPIO IRQ { get; } }
// ================ 寄存器枚举 ================ // 从接收队列中加载下一帧到 rxBuffer并更新状态
private void LoadNextRxFrame()
private enum Registers : long {
{ if (rxFrameQueue.Count > 0)
MOD = 0x00, {
CMR = 0x04, var frame = rxFrameQueue.Dequeue();
SR = 0x08, Array.Copy(frame, rxBuffer, 11);
IR = 0x0C, sr_rbs = 1;
IER = 0x10, UpdateIrFromRbs();
BTR0 = 0x18, UpdateInterrupts();
BTR1 = 0x1C, Console.WriteLine("Loaded next RX frame into buffer, queue remaining: {0}", rxFrameQueue.Count);
OCR = 0x20, }
RXERR = 0x38, // 14 else
TXERR = 0x3C, // 15 {
TX_FRAME_INFO = 0x40, // 16 sr_rbs = 0;
TX_ID1 = 0x44, UpdateIrFromRbs();
TX_ID2 = 0x48, UpdateInterrupts();
TX_DATA1 = 0x4C, Console.WriteLine("RX queue empty, buffer cleared");
TX_DATA2 = 0x50, }
TX_DATA3 = 0x54, }
TX_DATA4 = 0x58,
TX_DATA5 = 0x5C, // ================ 属性 ================
TX_DATA6 = 0x60,
TX_DATA7 = 0x64, public long Size => 0x80; // 地址范围 0-31
TX_DATA8 = 0x68, // 26
RBSA = 0x78, // 30 public GPIO IRQ { get; }
CDR = 0x7C, // 31
// ================ 寄存器枚举 ================
}
private enum Registers : long
// ================ 常量位定义 ================ {
MOD = 0x00,
private const byte CMR_TR = 0x01; // 发送请求 (bit0) CMR = 0x04,
private const byte CMR_RRB = 0x04; // 释放接收缓冲器 (bit2) SR = 0x08,
private const byte CMR_CDO = 0x08; // 清除数据溢出 (bit3) IR = 0x0C,
IER = 0x10,
private const byte SR_BS = 0x80; // 总线状态 (bit7) - 本模拟中恒0 BTR0 = 0x18,
private const byte SR_TBS = 0x04; // 发送缓冲器状态 (bit2) BTR1 = 0x1C,
private const byte SR_RBS = 0x01; // 接收缓冲器状态 (bit0) OCR = 0x20,
RXERR = 0x38, // 14
private const byte IR_RI = 0x01; // 接收中断 (bit0) TXERR = 0x3C, // 15
TX_FRAME_INFO = 0x40, // 16
private const byte IER_RIE = 0x01; // 接收中断使能 (bit0) TX_ID1 = 0x44,
TX_ID2 = 0x48,
// ================ 私有字段 ================ TX_DATA1 = 0x4C,
TX_DATA2 = 0x50,
private readonly IMachine machine; TX_DATA3 = 0x54,
TX_DATA4 = 0x58,
// 寄存器存储 TX_DATA5 = 0x5C,
private byte mod; TX_DATA6 = 0x60,
private byte ier; TX_DATA7 = 0x64,
private byte btr0, btr1; TX_DATA8 = 0x68, // 26
private byte ocr; RBSA = 0x78, // 30
private byte rxerr, txerr; CDR = 0x7C, // 31
private byte rbsa;
private byte cdr; }
// 状态位 // ================ 常量位定义 ================
private byte sr_tbs; // 1=空闲
private byte sr_rbs; // 1=有数据 private const byte CMR_TR = 0x01; // 发送请求 (bit0)
private const byte CMR_RRB = 0x04; // 释放接收缓冲器 (bit2)
private byte ir; // 仅 bit0 有效 private const byte CMR_CDO = 0x08; // 清除数据溢出 (bit3)
private readonly byte[] txBuffer; // 地址16-26 private const byte SR_BS = 0x80; // 总线状态 (bit7) - 本模拟中恒0
private readonly byte[] rxBuffer; // 当前接收帧 private const byte SR_TBS = 0x04; // 发送缓冲器状态 (bit2)
} private const byte SR_RBS = 0x01; // 接收缓冲器状态 (bit0)
}
private const byte IR_RI = 0x01; // 接收中断 (bit0)
private const byte IER_RIE = 0x01; // 接收中断使能 (bit0)
// ================ 私有字段 ================
private readonly IMachine machine;
// 寄存器存储
private byte mod;
private byte ier;
private byte btr0, btr1;
private byte ocr;
private byte rxerr, txerr;
private byte rbsa;
private byte cdr;
// 状态位
private byte sr_tbs; // 1=空闲
private byte sr_rbs; // 1=有数据
private byte ir; // 仅 bit0 有效
private readonly byte[] txBuffer; // 临时发送缓冲区(单帧)
private readonly byte[] rxBuffer; // 当前接收帧(单帧)
private readonly Queue<byte[]> txFrameQueue; // 发送队列
private readonly Queue<byte[]> rxFrameQueue; // 接收队列
}
}