diff --git a/UART_kx12A1.cs b/UART_kx12A1.cs new file mode 100644 index 0000000..8ab08ec --- /dev/null +++ b/UART_kx12A1.cs @@ -0,0 +1,615 @@ +// +// 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; + +namespace Antmicro.Renode.Peripherals.CustomPeripherals +{ + /// + /// UART_771_RUHW_2CFG 控制器 + /// 接收缓存512B,发送缓存512B,时钟24MHz + /// + public class UART_771_RUHW_2CFG1 : IDoubleWordPeripheral, IBytePeripheral, IKnownSize + { + private readonly IMachine machine; //TODO + + public UART_771_RUHW_2CFG1(IMachine machine) + { + this.clockFrequency = 24000000; + this.machine = machine; //TODO + + // 创建 FIFO + rxFifo = new Queue(); + txFifo = new Queue(); + + // 创建中断线 + IRQ = new GPIO(); + + // 初始化寄存器 + DefineRegisters(); + Reset(); + + this.Log(LogLevel.Info, "771 UART initialized, clock: {0} Hz", clockFrequency); + } + + + public void Reset() + { + rxFifo.Clear(); + txFifo.Clear(); + + ucr = 0x00; // 控制寄存器 + usr = USR_TFE;// 状态寄存器 + mcr = 0x00; // 调制控制寄存器:中断使能,接收使能 + brsr_l = 0x00; // 波特率设置寄存器 + brsr_h = 0x00; + fsta = (byte)(FSTA_TEMP | FSTA_REMP); // FIFO状态寄存器 + tbr = 0; // 发送FIFO剩余字节数 + rbr = 0 ; // 接收FIFO剩余字节数 + rstr = 0x00; // 复位/使能寄存器 + + ext_signal = 0x00; // 向外部提供读写信号 + + RxfifoEnabled = true; //接收fifo使能 + TxfifoEnabled = true; //发送fifo使能 + fifoTriggerLevel = 1; + + IRQ.Set(false); + UpdateInterrupts(); + + this.Log(LogLevel.Info, "UART reset"); + } + + + private void DefineRegisters() + { + // 寄存器访问通过 ReadDoubleWord/WriteDoubleWord 实现 + + } + + + // ======================================== + // IBusPeripheral 接口实现 + // ======================================== + public uint ReadDoubleWord(long offset) + { + this.Log(LogLevel.Info, "entry ReadDoubleWord: 0x{0}", offset); + return ReadRegisters(offset); + } + + public void WriteDoubleWord(long offset, uint value) + { + WriteRegisters(offset, value); + } + + + // ======================================== + // 自定义 + // ======================================== + public uint ReadRegisters(long offset) + { + this.Log(LogLevel.Info, "entry ReadRegisters: 0x{0}", offset); + + uint value = 0; + + switch (offset) + { + case (long)Registers.TBR_RBR: //接收FIFO,读操作 + // 在接收FIFO寄存器中读取数据 + value = ReadRBR(); + this.Log(LogLevel.Info, "Read TBR_RBR: 0x{0:X2}", value); + break; + + case (long)Registers.UCR_USR: //USR状态寄存器 + value = (byte)(usr & 0xFF); + this.Log(LogLevel.Info, "Read USR: 0x{0:X2}", value); + // usr = (byte)(usr & (~USR_RBFI)); //usr寄存器,取消接收中断,与hw_uart_isr关联,暂定 + break; + + case (long)Registers.MCR: //MCR调制控制寄存器 + value = (byte)(mcr & 0xFF); + this.Log(LogLevel.Info, "Read MCR: 0x{0:X2}", value); + break; + + case (long)Registers.BRSR: //波特率寄存器,暂无读操作 + value = (uint)((brsr_h << 8) + brsr_l); + this.Log(LogLevel.Info, "Read MCR: 0x{0}", value); + break; + + case (long)Registers.FSTA: // FIFO状态寄存器 + value = (byte)(fsta & 0xFF); + this.Log(LogLevel.Info, "Read FSTA: 0x{0:X2}", value); + break; + + case (long)Registers.TBR_FreeBytes: //发送FIFO剩余字节数 + tbr = (ushort)txFifo.Count; + value = (uint)tbr; + this.Log(LogLevel.Info, "Read TBR_FreeBytes: {0}", value); + break; + + case (long)Registers.RBR_FreeBytes: //接收FIFO剩余字节数 + rbr = (ushort)rxFifo.Count; + value = (uint)rbr; + this.Log(LogLevel.Info, "Read RBR_FreeBytes: {0}", value); + break; + + case (long)Registers.RSTR: // 复位/使能,暂无读操作 + value = (uint)rstr; + break; + + case (long)Registers.EXTI: //自定义,向外部提供读写信号 + value = (uint)(ext_signal & 0xFF); + 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) + { + this.Log(LogLevel.Info, "entry WriteRegisters: 0x{0}, value: 0x{1}", offset, value); + switch (offset) + { + case (long)Registers.TBR_RBR: + WriteTBR((byte)value); + this.Log(LogLevel.Info, "Write TBR_RBR: 0x{0:X2}", value); + break; + + case (long)Registers.UCR_USR: //控制寄存器 + WriteByte(offset, (byte)value); + break; + + case (long)Registers.MCR: //调制控制寄存器 + WriteByte(offset, (byte)value); + break; + + case (long)Registers.BRSR: //波特率寄存器 + if(value != 0) + { + currentBaudRate = (uint)(clockFrequency / value);; + brsr_l = (byte)(value); + brsr_h = (byte)(value >> 8); + this.Log(LogLevel.Info, "Write BRSR: {0}", value); + WriteByte(offset, brsr_l); + WriteByte((offset + 0x01), brsr_h); + } + break; + + case (long)Registers.RSTR: // 复位/使能 + WriteByte(offset, (byte)value); + break; + + case (long)Registers.EXTI: //向外部提供写RXFIFO寄存器 + value = (uint)ext_signal; + break; + + default: + this.Log(LogLevel.Warning, "Write to unknown offset: 0x{0:X} = 0x{1:X2}", offset, value); + break; + } + } + + + public byte ReadByte(long offset) + { + this.Log(LogLevel.Info, "entry ReadByte: 0x{0}", offset); + return 0x00; + } + + + public void WriteByte(long offset, byte value) + { + this.Log(LogLevel.Info, "entry WriteByte: 0x{0}, value: 0x{1}", offset, value); + switch(offset) + { + + case (long)Registers.UCR_USR: //控制寄存器 + ucr = (byte)(value & 0xFF); + this.Log(LogLevel.Info, "Write UCR_USR: 0x{0:X2}", ucr); + break; + + case (long)Registers.MCR: //调制控制寄存器 + mcr = (byte)(value & 0xFF); + this.Log(LogLevel.Info, "Write MCR: 0x{0:X2}", mcr); + UpdateModemControl(); + break; + + case (long)Registers.BRSR: //波特率寄存器 + if(value != 0) + { + brsr_l = value; + this.Log(LogLevel.Info, "Write BRSR: 0x{0:X2}", brsr_l); + } + break; + + + case (long)Registers.BRSR_H: + if(value != 0) + { + brsr_h = value; + this.Log(LogLevel.Info, "Write BRSR: 0x{0:X2}", brsr_h); + } + 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; + + case (long)Registers.EXTI: //向外部提供写RXFIFO寄存器 + WriteRXFIFOData((byte)value); + break; + + default: + this.Log(LogLevel.Warning, "Write to unknown offset: 0x{0:X} = 0x{1:X2}", offset, value); + break; + + + } + } + + private void UpdateInterrupts() + { + bool interrupt = false; + + // D2中断使能 必须置位才能产生中断 + if ((mcr & MCR_BEN) != 0) + { + // 检查各种中断条件 + if ((usr & USR_TCMP) != 0 ) //发送完成,发送FIFO空(发送中断) + interrupt = true; + else if ((usr & USR_RBFI) != 0 ) //接收FIFO中有数据后,延迟10ms产生一次(接收中断) + interrupt = true; + else if ((usr & (USR_PE | USR_FE | USR_OE | USR_BI)) != 0 ) //校验错、帧错、溢出错、接收碎片 + interrupt = true; + } + + IRQ.Set(interrupt); + + if (interrupt) + { + this.Log(LogLevel.Info, "Interrupt asserted"); + machine.ScheduleAction(TimeInterval.FromMicroseconds(1), + _ => { + IRQ.Set(false); + this.Log(LogLevel.Info, "Interrupt deasserted"); + }); + } + } + + + private void UpdateModemControl() + { + if( (mcr & MCR_REN) == 0) + { + RxfifoEnabled = false; //待定 + } + this.Log(LogLevel.Info, "Modem control: MCR_BEN={0}, MCR_REN={1}", + (mcr & MCR_BEN) != 0, (mcr & MCR_REN) != 0); + + UpdateInterrupts(); + } + + + public void WriteTBR(byte value) + { + // 从星务接收数据 ,操作txFifo + this.Log(LogLevel.Info, "Write TBR: 0x{0:X2} ('{1}')", value, + (value >= 32 && value < 127) ? (char)value : '.'); + + if (TxfifoEnabled) + { + if (txFifo.Count < TX_FIFO_SIZE) + { + txFifo.Enqueue(value); + fsta = (byte)(fsta & (~FSTA_TEMP)); // 发送缓冲区不为空,D0置0 + usr = (byte)(usr & (~USR_TFE)); //发送FIFO不为空,D6置0 + } + else + { + fsta = (byte)(fsta | FSTA_TFUL); // 发送FIFO满 + this.Log(LogLevel.Warning, "TX FIFO overflow"); + } + } + else + { + // 非 FIFO 模式,待定 + txFifo.Clear(); + txFifo.Enqueue(value); + fsta = (byte)(fsta & (~FSTA_TEMP)); // 发送缓冲区不为空,D0置0 + } + + // 暂时不发送数据,由中间层自取 + } + + + public uint GetTXFIFOData() + { + uint data = 0x00; + + // 从 TX FIFO 发送数据,中间层获取txfifo接口 + if (txFifo.Count > 0) + { + data = txFifo.Dequeue(); + + // 调用基类的 TransmitCharacter 发送数据 + // TransmitCharacter(data); + + this.Log(LogLevel.Info, "Transmitted: 0x{0:X2} ('{1}')", data, + (data >= 32 && data < 127) ? (char)data : '.'); + } + else + { + this.Log(LogLevel.Info, "TXFIFO Null "); + } + + // 更新状态 + if (txFifo.Count == 0) + { + fsta = (byte)((fsta &0xF0) | FSTA_TEMP); // 发送缓冲区为空,D0置0 + usr = (byte)(usr | USR_TFE); // 发送FIFO空 + usr = (byte)(usr | USR_TCMP); // 发送完成(发送中断) + } + + UpdateInterrupts(); + + return data; + } + + 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); + ext_signal = (byte)(ext_signal & (~EXT_SIGNAL_READ)); // 通知外部不可读 + + + // 更新状态 + if (txFifo.Count == 0) + { + fsta = (byte)((fsta &0xF0) | FSTA_TEMP); // 发送缓冲区为空,D0置0 + usr = (byte)(usr | USR_TFE); // 发送FIFO空 + usr = (byte)(usr | USR_TCMP); // 发送完成(发送中断) + } + + UpdateInterrupts(); + + return data; + } + + + public byte ReadRBR() + { + + byte value = 0; + + if (rxFifo.Count > 0) + { + value = rxFifo.Dequeue(); + this.Log(LogLevel.Info, "Read: 0x{0:X2} ('{1}')", value, + (value >= 32 && value < 127) ? (char)value : '.'); + + } + else + { + this.Log(LogLevel.Warning, "Read from empty RBR"); + } + + // 更新状态 + if (rxFifo.Count == 0) + { + fsta = (byte)(fsta | FSTA_REMP); // 接收FIFO空 + usr = (byte)(usr & (~USR_OE)); // 清除溢出错误 + ext_signal = (byte)(ext_signal | EXT_SIGNAL_WRITE); // 通知外部可写 + } + + UpdateInterrupts(); + return value; + } + + public void WriteRXFIFOData(byte value) + { + // 向外部网络提供RXFIFO数据写入功能 + + if(RxfifoEnabled) + { + if(rxFifo.Count < RX_FIFO_SIZE) + { + rxFifo.Enqueue(value); + fsta = (byte)(fsta & (~FSTA_REMP)); //接收FIFO非空 + this.Log(LogLevel.Info, "External Write RXFIFO: 0x{0:X2} ('{1}')", value, + (value >= 32 && value < 127) ? (char)value : '.'); + } + else + { + //待定 + fsta = (byte)(fsta | FSTA_RFUL); //接收FIFO满 + this.Log(LogLevel.Warning, "RX FIFO Already Full"); + } + } + + // this.Wait(TimeInterval.FromMilliseconds(10)); 无法实现等待10ms,暂不实现 + usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断 + UpdateInterrupts(); + + } + + + public void WriteRXFIFODataString(string value) + { + // 向外部网络提供RXFIFO数据写入功能,value=0xAABB... + string data = value.StartsWith("0x",StringComparison.OrdinalIgnoreCase) ? value.Substring(2) : value; + this.Log(LogLevel.Info, "External Write RXFIFO: {0} ", value); + + string tmpString; + byte tmpHex; + int i; + + if(RxfifoEnabled) + { + if(data.Length % 2 != 0) + { + data = "0" + data; // 前面补0 + } + + if((data.Length/2) > (RX_FIFO_SIZE - rxFifo.Count)) //value超出fifo剩余 + { + this.Log(LogLevel.Warning, "Data too long"); + return; + } + + for(i = 0; i < data.Length ; i+=2) + { + tmpString = data.Substring(i, 2); + tmpHex = Convert.ToByte(tmpString, 16); + rxFifo.Enqueue(tmpHex); + } + + ext_signal = (byte)(ext_signal & (~EXT_SIGNAL_WRITE)); // 通知外部不可写 + fsta = (byte)(fsta & (~FSTA_REMP)); //接收FIFO非空 + + if(rxFifo.Count == RX_FIFO_SIZE) + { + fsta = (byte)(fsta | FSTA_RFUL); //接收FIFO满 + this.Log(LogLevel.Warning, "RX FIFO Already Full"); + } + + usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断 + machine.ScheduleAction(TimeInterval.FromMicroseconds(10000), + _ => { + UpdateInterrupts(); //等待10ms + }); + } + else + { + + } + + } + + + public long Size => 0x28; //uart地址长度总空间 + + public GPIO IRQ { get; } + + // ======================================== + // 寄存器定义 + // ======================================== + + private enum Registers : long + { + TBR_RBR = 0x00, // TBR发送FIFO,RBR接收FIFO + UCR_USR = 0x04, // UCR控制寄存器,USR状态寄存器 + MCR = 0x08, // 调制控制寄存器 + BRSR = 0x0C, // 波特率设置寄存器 + BRSR_H = 0x0D, // 波特率设置寄存器-高位 + FSTA = 0x10, // FIFO状态寄存器 + TBR_FreeBytes = 0x14, // 发送FIFO剩余字节数 + RBR_FreeBytes = 0x18, // 接收FIFO剩余字节数 + RSTR = 0x20, // 复位/使能 x55复位;其他使能 + EXTI = 0x24 // 向外部提供读写FIFO接口 + } + + // UCR控制寄存器 位定义 + private const byte UCR_STB = 0x01; // 停止位1位 + private const byte UCR_PB = 0x0E; // 奇偶校验3位 + + private const byte USR_PE = 0x01; // 校验错 + private const byte USR_FE = 0x02; // 帧错 + private const byte USR_OE = 0x04; // 溢出错 + private const byte USR_BI = 0x08; // 接收碎片 + private const byte USR_TCMP = 0x20; // 发送完成(发送中断) + private const byte USR_TFE = 0x40; // 发送FIFO空 + private const byte USR_RBFI = 0x80; // 接收中断 + + // MCR 调制控制寄存器 + private const byte MCR_BEN = 0x04; // 中断使能 + private const byte MCR_REN = 0x20; // 接收使能 + + // 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; // 发送FIFO高阈值半满 + private const byte FSTA_REMP = 0x10; // 接收FIFO空 + private const byte FSTA_RLHF = 0x20; // 接收FIFO低阈值半满 + private const byte FSTA_RFUL = 0x40; // 接收FIFO满 + private const byte FSTA_RHHF = 0x80; // 接收FIFO 高阈值半满 + + + // RSTR 复位/使能寄存器 + private const byte RSTR_RES = 0x55; // 复位 + private const byte RSTR_EN = 0xAA; // 使能 + + private const byte EXT_SIGNAL_WRITE = 0x0F; //0x0F表示外部可写 + private const byte EXT_SIGNAL_READ = 0xF0; //0xF0表示外部可读 + + // 常量 + private const int RX_FIFO_SIZE = 512; // 接收FIFO_SIZE + private const int TX_FIFO_SIZE = 512; // 发送FIFO_SIZE + + // ======================================== + // 私有字段 + // ======================================== + + private readonly uint clockFrequency; + private uint currentBaudRate; + + + // 寄存器 + private byte ucr; // 控制寄存器 + private byte usr; // 状态寄存器 + private byte mcr; // 调制控制寄存器 + private byte brsr_l; // 波特率设置寄存器 + private byte brsr_h; // 波特率设置寄存器 + private byte fsta; // FIFO状态寄存器 + private ushort tbr; // 发送FIFO剩余字节数 + private ushort rbr; // 接收FIFO剩余字节数 + private byte rstr; // 复位/使能寄存器 + + private byte ext_signal; //外部提供读写信号,读信号待确定 + + + // FIFO + private readonly Queue rxFifo; + private readonly Queue txFifo; + private bool RxfifoEnabled; + private bool TxfifoEnabled; + private int fifoTriggerLevel; + } +} diff --git a/UART_kx12A2.cs b/UART_kx12A2.cs new file mode 100644 index 0000000..12c2e2a --- /dev/null +++ b/UART_kx12A2.cs @@ -0,0 +1,402 @@ +// +//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; + +namespace Antmicro.Renode.Peripherals.CustomPeripherals +{ + /// + /// UART_771_RUHW_2CFG 控制器:高速通信HSP + /// 接收缓存0B,发送缓存512B,时钟25MHz + /// + public class UART_771_RUHW_2CFG2 : IDoubleWordPeripheral, IKnownSize + { + private readonly IMachine machine; //TODO + + public UART_771_RUHW_2CFG2(IMachine machine) + { + this.clockFrequency = 25000000; + this.machine = machine; //TODO + + // 创建 FIFO + rxFifo = new Queue(); + + // 创建中断线 + IRQ = new GPIO(); + + // 初始化寄存器 + DefineRegisters(); + Reset(); + + this.Log(LogLevel.Info, "771 UART initialized, clock: {0} Hz", clockFrequency); + } + + public void Reset() + { + rxFifo.Clear(); + + ucr = 0x00; // 控制寄存器(默认0x02) + usr = 0x00; // 状态寄存器 + mcr = MCR_REN; // 调制控制寄存器:中断使能,接收使能 + brsr = 0x43; // 波特率设置寄存器 + fsta = 0x00; // FIFO状态寄存器 + rstr = 0x00; // 复位/使能寄存器 + + RxfifoEnabled = true; //接收fifo使能 + fifoTriggerLevel = 1; + + IRQ.Set(false); + UpdateInterrupts(); + + this.Log(LogLevel.Info, "UART 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.RBR: //接收FIFO,读操作 + // 在接收FIFO寄存器中读取数据,高速数据串口为双字节读取,暂定小端TODO + value = (uint)(ReadRBR() << 8) + (uint)ReadRBR(); + this.Log(LogLevel.Info, "Read TBR_RBR: 0x{0:X8}", value); + break; + + case (long)Registers.UCR_USR: //USR状态寄存器 + value = (byte)(usr & 0xFF); + this.Log(LogLevel.Info, "Read USR: 0x{0:X2}", value); + usr = 0x00; // 高速上行:读取该寄存器后,自动清寄存器(来自需求) + break; + + case (long)Registers.MCR: //MCR调制控制寄存器 + value = (byte)(mcr & 0xFF); + this.Log(LogLevel.Info, "Read MCR: 0x{0:X2}", value); + break; + + case (long)Registers.BRSR: //波特率寄存器,暂无读操作 + value = (uint)brsr; + this.Log(LogLevel.Info, "Read FSTA: 0x{0:X2}", value); + break; + + case (long)Registers.FSTA: // FIFO状态寄存器 + value = (byte)(fsta & 0xFF); + this.Log(LogLevel.Info, "Read FSTA: 0x{0:X2}", value); + break; + + case (long)Registers.RSTR: // 复位/使能,暂无读操作 + value = (byte)(rstr & 0xFF); + this.Log(LogLevel.Info, "Read RSTR: 0x{0:X2}", 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.UCR_USR: //控制寄存器UCR + ucr = (byte)(value & 0xFF); + this.Log(LogLevel.Info, "Write UCR_USR: 0x{0:X2}", ucr); + break; + + case (long)Registers.MCR: //调制控制寄存器 + mcr = (byte)(value & 0xFF); + this.Log(LogLevel.Info, "Write MCR: 0x{0:X2}", mcr); + UpdateModemControl(); + break; + + case (long)Registers.BRSR: //波特率寄存器 + if(value != 0) + { + currentBaudRate = (uint)(clockFrequency / value); + brsr = (ushort)value; + this.Log(LogLevel.Info, "Write BRSR: {0}", brsr); + } + 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; + + case (long)Registers.EXTI: //向外部提供写RXFIFO寄存器 + //WriteRXFIFOData(value); + break; + + default: + this.Log(LogLevel.Warning, "Write to unknown offset: 0x{0:X} = 0x{1:X2}", offset, value); + break; + } + } + + + private void UpdateInterrupts() + { + bool interrupt = false; + + // D2中断使能 必须置位才能产生中断 + if ((mcr & MCR_BEN) != 0) + { + // 检查各种中断条件 + if ((usr & USR_RBFI) != 0 ) //接收FIFO中有数据后,延迟10ms产生一次(接收中断) + interrupt = true; + else if ((usr & (USR_PE | USR_FE | USR_OE | USR_BI)) != 0 ) //校验错、帧错、溢出错、接收碎片 + interrupt = true; + } + + IRQ.Set(interrupt); + + if (interrupt) + { + this.Log(LogLevel.Info, "Interrupt asserted"); + machine.ScheduleAction(TimeInterval.FromMicroseconds(1), + _ => { + IRQ.Set(false); + this.Log(LogLevel.Info, "Interrupt deasserted"); + }); + } + } + + + private void UpdateModemControl() + { + if( (mcr & MCR_REN) == 0) + { + RxfifoEnabled = false; + } + this.Log(LogLevel.Info, "Modem control: MCR_BEN={0}, MCR_REN={1}", + (mcr & MCR_BEN) != 0, (mcr & MCR_REN) != 0); + + UpdateInterrupts(); + } + + + + public byte ReadRBR() + { + //单字节读取 + byte value = 0; + + if (rxFifo.Count > 0) + { + value = rxFifo.Dequeue(); + this.Log(LogLevel.Info, "Read: 0x{0:X2} ('{1}')", value, + (value >= 32 && value < 127) ? (char)value : '.'); + + } + else + { + this.Log(LogLevel.Warning, "Read from empty RBR"); + } + + // 更新状态 + if (rxFifo.Count == 0) + { + fsta = (byte)(fsta | FSTA_REMP); // 接收FIFO空 + usr = (byte)(usr & (~USR_OE)); // 清除溢出错误 + } + + UpdateInterrupts(); + return value; + } + + + public void WriteRXFIFOData(uint value) + { + // 向外部网络提供RXFIFO数据写入功能,value低16位有效 + + if(RxfifoEnabled) + { + if(rxFifo.Count < RX_FIFO_SIZE) + { + byte tmp = (byte)(value >> 8); + rxFifo.Enqueue(tmp); + tmp = (byte)value; + rxFifo.Enqueue(tmp); + fsta = (byte)(fsta & (~FSTA_REMP)); //接收FIFO非空 + this.Log(LogLevel.Info, "External Write RXFIFO: 0x{0:X4} ('{1}')", (ushort)value); + } + else + { + //待定 + fsta = (byte)(fsta | FSTA_RFUL); //接收FIFO满 + this.Log(LogLevel.Warning, "RX FIFO Already Full"); + } + } + + // this.Wait(TimeInterval.FromMilliseconds(10)); 无法实现等待10ms,暂不实现 + usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断 + UpdateInterrupts(); + + } + + + public void WriteRXFIFODataString(string value) + { + // 向外部网络提供RXFIFO数据写入功能,value=0xAABB... + string data = value.StartsWith("0x",StringComparison.OrdinalIgnoreCase) ? value.Substring(2) : value; + this.Log(LogLevel.Info, "External Write RXFIFO: {0} ", value); + + string tmpString; + byte tmpHex; + int i; + + if(RxfifoEnabled) + { + if(data.Length % 2 != 0) + { + data = "0" + data; // 前面补0 + } + + if((data.Length/2) > (RX_FIFO_SIZE - rxFifo.Count)) //value超出fifo剩余 + { + this.Log(LogLevel.Warning, "Data too long"); + return; + } + + for(i = 0; i < data.Length ; i+=2) + { + tmpString = data.Substring(i, 2); + tmpHex = Convert.ToByte(tmpString, 16); + rxFifo.Enqueue(tmpHex); + } + + fsta = (byte)(fsta & (~FSTA_REMP)); //接收FIFO非空 + + if(rxFifo.Count == RX_FIFO_SIZE) + { + fsta = (byte)(fsta | FSTA_RFUL); //接收FIFO满 + this.Log(LogLevel.Warning, "RX FIFO Already Full"); + } + + // this.Wait(TimeInterval.FromMilliseconds(10)); 无法实现等待10ms,暂不实现 + usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断 + UpdateInterrupts(); + } + else + { + + } + + } + + public long Size => 0x28; //uart地址长度总空间 + + public GPIO IRQ { get; } + + // ======================================== + // 寄存器定义 + // ======================================== + + private enum Registers : long + { + RBR = 0x00, // RBR接收FIFO,无发送操作 + UCR_USR = 0x04, // UCR控制寄存器,USR状态寄存器 + MCR = 0x08, // 调制控制寄存器 + BRSR = 0x0C, // 波特率设置寄存器 + RSTR = 0x10, /// 复位/使能 x55复位;其他使能 + FSTA = 0x14, // FIFO状态寄存器 + EXTI = 0x24 // 向外部提供读写FIFO接口 + } + + // UCR控制寄存器 位定义 + private const byte UCR_STB = 0x01; // 停止位1位 + private const byte UCR_PB = 0x0E; // 奇偶校验3位 + + private const byte USR_PE = 0x01; // 校验错 + private const byte USR_FE = 0x02; // 帧错 + private const byte USR_OE = 0x04; // 溢出错 + private const byte USR_BI = 0x08; // 接收碎片 + private const byte USR_TCMP = 0x20; // 发送完成(发送中断) + private const byte USR_TFE = 0x40; // 发送FIFO空 + private const byte USR_RBFI = 0x80; // 接收中断 + + // MCR 调制控制寄存器 + private const byte MCR_BEN = 0x04; // 中断使能 + private const byte MCR_REN = 0x20; // 接收使能 + + // FSTA FIFO状态寄存器 + private const byte FSTA_REMP = 0x10; // 接收FIFO空 + private const byte FSTA_RLHF = 0x20; // 接收FIFO低阈值半满 + private const byte FSTA_RFUL = 0x40; // 接收FIFO满 + + + // RSTR 复位/使能寄存器 + private const byte RSTR_RES = 0x55; // 复位 + private const byte RSTR_EN = 0xAA; // 使能 + + // 常量 + private const int RX_FIFO_SIZE = 2048; // 接收FIFO_SIZE + private const int TX_FIFO_SIZE = 512; // 发送FIFO_SIZE + + // ======================================== + // 私有字段 + // ======================================== + + private readonly uint clockFrequency; + private uint currentBaudRate; + + + // 寄存器 + private byte ucr; // 控制寄存器 + private byte usr; // 状态寄存器 + private byte mcr; // 调制控制寄存器 + private ushort brsr; // 波特率设置寄存器 + private byte fsta; // FIFO状态寄存器 + private byte rstr; // 复位/使能寄存器 + + + // FIFO + private readonly Queue rxFifo; + private bool RxfifoEnabled; + private int fifoTriggerLevel; + } +} diff --git a/UART_kx12A3.cs b/UART_kx12A3.cs new file mode 100644 index 0000000..6a8ab71 --- /dev/null +++ b/UART_kx12A3.cs @@ -0,0 +1,542 @@ +// +// 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; + +namespace Antmicro.Renode.Peripherals.CustomPeripherals +{ + /// + /// UART_771_RUHW_2CFG 控制器 + /// 接收缓存512B,发送缓存2048B,时钟24MHz + /// + public class UART_771_RUHW_2CFG3 : IDoubleWordPeripheral, IKnownSize + { + private readonly IMachine machine; //TODO + + public UART_771_RUHW_2CFG3(IMachine machine) + { + this.clockFrequency = 24000000; + this.machine = machine; //TODO + + // 创建 FIFO + rxFifo = new Queue(); + txFifo = new Queue(); + + // 创建中断线 + IRQ = new GPIO(); + + // 初始化寄存器 + DefineRegisters(); + Reset(); + + this.Log(LogLevel.Info, "771 UART initialized, clock: {0} Hz", clockFrequency); + } + + public void Reset() + { + rxFifo.Clear(); + txFifo.Clear(); + + ucr = 0x00; // 控制寄存器 + usr = USR_TFE;// 状态寄存器 + mcr = 0x00; // 调制控制寄存器:中断使能,接收使能 + brsr = 0; // 波特率设置寄存器 + fsta = (byte)(FSTA_TEMP | FSTA_REMP); // FIFO状态寄存器 + tbr = 0; // 发送FIFO剩余字节数 + rbr = 0; // 接收FIFO剩余字节数 + rstr = 0x00; // 复位/使能寄存器 + + RxfifoEnabled = true; //接收fifo使能 + TxfifoEnabled = true; //发送fifo使能 + fifoTriggerLevel = 1; + + IRQ.Set(false); + UpdateInterrupts(); + + this.Log(LogLevel.Info, "UART 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.TBR_RBR: //接收FIFO,读操作 + // 在接收FIFO寄存器中读取数据 + value = ReadRBR(); + this.Log(LogLevel.Info, "Read TBR_RBR: 0x{0:X2}", value); + break; + + case (long)Registers.UCR_USR: //USR状态寄存器 + value = (byte)(usr & 0xFF); + this.Log(LogLevel.Info, "Read USR: 0x{0:X2}", value); + // usr = (byte)(usr & (~USR_RBFI)); //usr寄存器,取消接收中断,与hw_uart_isr关联,暂定 + break; + + case (long)Registers.MCR: //MCR调制控制寄存器 + value = (byte)(mcr & 0xFF); + this.Log(LogLevel.Info, "Read MCR: 0x{0:X2}", value); + break; + + case (long)Registers.BRSR: //波特率寄存器,暂无读操作 + value = (uint)(brsr); + this.Log(LogLevel.Info, "Read MCR: 0x{0}", value); + break; + + case (long)Registers.FSTA: // FIFO状态寄存器 + value = (byte)(fsta & 0xFF); + this.Log(LogLevel.Info, "Read FSTA: 0x{0:X2}", value); + //GetTXFIFODataString(); //测试TODO,删除 + break; + + case (long)Registers.TBR_FreeBytes: //发送FIFO剩余字节数 + tbr = (ushort)txFifo.Count; + value = (uint)tbr; + this.Log(LogLevel.Info, "Read TBR_FreeBytes: {0}", value); + break; + + case (long)Registers.RBR_FreeBytes: //接收FIFO剩余字节数 + rbr = (ushort)rxFifo.Count; + value = (uint)rbr; + this.Log(LogLevel.Info, "Read RBR_FreeBytes: {0}", value); + break; + + case (long)Registers.RSTR: // 复位/使能,暂无读操作 + value = (uint)rstr; + break; + + case (long)Registers.EXTI: //自定义,向外部提供读发送FIFO寄存器 + //value = (uint)GetTXFIFOData(); + 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: + WriteTBR((byte)value); + this.Log(LogLevel.Info, "Write TBR_RBR: 0x{0:X2}", value); + break; + + case (long)Registers.UCR_USR: //控制寄存器 + ucr = (byte)(value & 0xFF); + this.Log(LogLevel.Info, "Write UCR_USR: 0x{0:X2}", ucr); + break; + + case (long)Registers.MCR: //调制控制寄存器 + mcr = (byte)(value & 0xFF); + this.Log(LogLevel.Info, "Write MCR: 0x{0:X2}", mcr); + UpdateModemControl(); + break; + + case (long)Registers.BRSR: //波特率寄存器 + if(value != 0) + { + currentBaudRate = (uint)(clockFrequency / value); + brsr = (ushort)value; + this.Log(LogLevel.Info, "Write BRSR: {0}", brsr); + } + 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; + + case (long)Registers.EXTI: //向外部提供写RXFIFO寄存器 + //WriteRXFIFOData((byte)value); + break; + + default: + this.Log(LogLevel.Warning, "Write to unknown offset: 0x{0:X} = 0x{1:X2}", offset, value); + break; + } + } + + + private void UpdateInterrupts() + { + bool interrupt = false; + + // D2中断使能 必须置位才能产生中断 + if ((mcr & MCR_BEN) != 0) + { + // 检查各种中断条件 + if ((usr & USR_TCMP) != 0 ) //发送完成,发送FIFO空(发送中断) + interrupt = true; + else if ((usr & USR_RBFI) != 0 ) //接收FIFO中有数据后,延迟10ms产生一次(接收中断) + interrupt = true; + else if ((usr & (USR_PE | USR_FE | USR_OE | USR_BI)) != 0 ) //校验错、帧错、溢出错、接收碎片 + interrupt = true; + } + + IRQ.Set(interrupt); + + if (interrupt) + { + this.Log(LogLevel.Info, "Interrupt asserted"); + machine.ScheduleAction(TimeInterval.FromMicroseconds(1), + _ => { + IRQ.Set(false); + this.Log(LogLevel.Info, "Interrupt deasserted"); + }); + } + + + } + + + private void UpdateModemControl() + { + if((mcr & MCR_REN) == 0) + { + RxfifoEnabled = false; //待定 + } + this.Log(LogLevel.Info, "Modem control: MCR_BEN={0}, MCR_REN={1}", + (mcr & MCR_BEN) != 0, (mcr & MCR_REN) != 0); + + UpdateInterrupts(); + } + + + public void WriteTBR(byte value) + { + // 从星务接收数据 ,操作txFifo + this.Log(LogLevel.Info, "Write TBR: 0x{0:X2} ('{1}')", value, + (value >= 32 && value < 127) ? (char)value : '.'); + + if (TxfifoEnabled) + { + if (txFifo.Count < TX_FIFO_SIZE) + { + txFifo.Enqueue(value); + fsta = (byte)(fsta & (~FSTA_TEMP)); // 发送缓冲区不为空,D0置0 + usr = (byte)(usr & (~USR_TFE)); //发送FIFO不为空,D6置0 + } + else + { + fsta = (byte)(fsta | FSTA_TFUL); // 发送FIFO满 + this.Log(LogLevel.Warning, "TX FIFO overflow"); + } + } + else + { + // 非 FIFO 模式,待定 + txFifo.Clear(); + txFifo.Enqueue(value); + fsta = (byte)(fsta & (~FSTA_TEMP)); // 发送缓冲区不为空,D0置0 + } + + // 暂时不发送数据,由中间层自取 + } + + + public uint GetTXFIFOData() + { + uint data = 0x00; + + // 从 TX FIFO 发送数据,中间层获取txfifo接口 + if (txFifo.Count > 0) + { + data = txFifo.Dequeue(); + + // 调用基类的 TransmitCharacter 发送数据 + // TransmitCharacter(data); + + this.Log(LogLevel.Info, "Transmitted: 0x{0:X2} ('{1}')", data, + (data >= 32 && data < 127) ? (char)data : '.'); + } + else + { + this.Log(LogLevel.Info, "TXFIFO Null "); + } + + // 更新状态 + + if (txFifo.Count == 0) + { + fsta = (byte)((fsta &0xF0) | FSTA_TEMP); // 发送缓冲区为空,D0置0 + usr = (byte)(usr | USR_TFE); // 发送FIFO空 + usr = (byte)(usr | USR_TCMP); // 发送完成(发送中断) + } + + UpdateInterrupts(); + + return data; + } + + + 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); + + + // 更新状态 + if (txFifo.Count == 0) + { + fsta = (byte)((fsta &0xF0) | FSTA_TEMP); // 发送缓冲区为空,D0置0 + usr = (byte)(usr | USR_TFE); // 发送FIFO空 + usr = (byte)(usr | USR_TCMP); // 发送完成(发送中断) + } + + UpdateInterrupts(); + + return data; + } + + public byte ReadRBR() + { + byte value = 0; + + if (rxFifo.Count > 0) + { + value = rxFifo.Dequeue(); + this.Log(LogLevel.Info, "Read: 0x{0:X2} ('{1}')", value, + (value >= 32 && value < 127) ? (char)value : '.'); + + } + else + { + this.Log(LogLevel.Warning, "Read from empty RBR"); + } + + // 更新状态 + if (rxFifo.Count == 0) + { + fsta = (byte)(fsta | FSTA_REMP); // 接收FIFO空 + usr = (byte)(usr & (~USR_OE)); // 清除溢出错误 + } + + UpdateInterrupts(); + return value; + } + + public void WriteRXFIFOData(byte value) + { + // 向外部网络提供RXFIFO数据写入功能 + + if(RxfifoEnabled) + { + if(rxFifo.Count < RX_FIFO_SIZE) + { + rxFifo.Enqueue(value); + fsta = (byte)(fsta & (~FSTA_REMP)); //接收FIFO非空 + this.Log(LogLevel.Info, "External Write RXFIFO: 0x{0:X2} ('{1}')", value, + (value >= 32 && value < 127) ? (char)value : '.'); + } + else + { + //待定 + fsta = (byte)(fsta | FSTA_RFUL); //接收FIFO满 + this.Log(LogLevel.Warning, "RX FIFO Already Full"); + } + } + + usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断 + machine.ScheduleAction(TimeInterval.FromMicroseconds(10000), + _ => { + UpdateInterrupts(); //等待10ms + }); + + } + + + public void WriteRXFIFODataString(string value) + { + // 向外部网络提供RXFIFO数据写入功能,value=0xAABB... + string data = value.StartsWith("0x",StringComparison.OrdinalIgnoreCase) ? value.Substring(2) : value; + this.Log(LogLevel.Info, "External Write RXFIFO: {0} ", value); + + string tmpString; + byte tmpHex; + int i; + + if(RxfifoEnabled) + { + if(data.Length % 2 != 0) + { + data = "0" + data; // 前面补0 + } + + if((data.Length/2) > (RX_FIFO_SIZE - rxFifo.Count)) //value超出fifo剩余 + { + this.Log(LogLevel.Warning, "Data too long"); + return; + } + + for(i = 0; i < data.Length ; i+=2) + { + tmpString = data.Substring(i, 2); + tmpHex = Convert.ToByte(tmpString, 16); + rxFifo.Enqueue(tmpHex); + } + + fsta = (byte)(fsta & (~FSTA_REMP)); //接收FIFO非空 + + if(rxFifo.Count == RX_FIFO_SIZE) + { + fsta = (byte)(fsta | FSTA_RFUL); //接收FIFO满 + this.Log(LogLevel.Warning, "RX FIFO Already Full"); + } + + // this.Wait(TimeInterval.FromMilliseconds(10)); 无法实现等待10ms,暂不实现 + usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断 + UpdateInterrupts(); + } + else + { + + } + + } + + + public long Size => 0x28; //uart地址长度总空间 + + public GPIO IRQ { get; } + + // ======================================== + // 寄存器定义 + // ======================================== + + private enum Registers : long + { + TBR_RBR = 0x00, // TBR发送FIFO,RBR接收FIFO + UCR_USR = 0x04, // UCR控制寄存器,USR状态寄存器 + MCR = 0x08, // 调制控制寄存器 + BRSR = 0x0C, // 波特率设置寄存器 + FSTA = 0x10, // FIFO状态寄存器 + TBR_FreeBytes = 0x14, // 发送FIFO剩余字节数 + RBR_FreeBytes = 0x18, // 接收FIFO剩余字节数 + RSTR = 0x20, // 复位/使能 x55复位;其他使能 + EXTI = 0x24 // 向外部提供读写FIFO接口 + } + + // UCR控制寄存器 位定义 + private const byte UCR_STB = 0x01; // 停止位1位 + private const byte UCR_PB = 0x0E; // 奇偶校验3位 + + private const byte USR_PE = 0x01; // 校验错 + private const byte USR_FE = 0x02; // 帧错 + private const byte USR_OE = 0x04; // 溢出错 + private const byte USR_BI = 0x08; // 接收碎片 + private const byte USR_TCMP = 0x20; // 发送完成(发送中断) + private const byte USR_TFE = 0x40; // 发送FIFO空 + private const byte USR_RBFI = 0x80; // 接收中断 + + // MCR 调制控制寄存器 + private const byte MCR_BEN = 0x04; // 中断使能 + private const byte MCR_REN = 0x20; // 接收使能 + + // 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; // 发送FIFO高阈值半满 + private const byte FSTA_REMP = 0x10; // 接收FIFO空 + private const byte FSTA_RLHF = 0x20; // 接收FIFO低阈值半满 + private const byte FSTA_RFUL = 0x40; // 接收FIFO满 + private const byte FSTA_RHHF = 0x80; // 接收FIFO 高阈值半满 + + + // RSTR 复位/使能寄存器 + private const byte RSTR_RES = 0x55; // 复位 + private const byte RSTR_EN = 0xAA; // 使能 + + // 常量 + private const int RX_FIFO_SIZE = 512; // 接收FIFO_SIZE + private const int TX_FIFO_SIZE = 2048; // 发送FIFO_SIZE + + // ======================================== + // 私有字段 + // ======================================== + + private readonly uint clockFrequency; + private uint currentBaudRate; + + + // 寄存器 + private byte ucr; // 控制寄存器 + private byte usr; // 状态寄存器 + private byte mcr; // 调制控制寄存器 + private ushort brsr; // 波特率设置寄存器 + private byte fsta; // FIFO状态寄存器 + private ushort tbr; // 发送FIFO剩余字节数 + private ushort rbr; // 接收FIFO剩余字节数 + private byte rstr; // 复位/使能寄存器 + + + // FIFO + private readonly Queue rxFifo; + private readonly Queue txFifo; + private bool RxfifoEnabled; + private bool TxfifoEnabled; + private int fifoTriggerLevel; + } +} diff --git a/UART_kx12A4.cs b/UART_kx12A4.cs index 2254dab..10acffd 100644 --- a/UART_kx12A4.cs +++ b/UART_kx12A4.cs @@ -105,7 +105,8 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals case (long)Registers.UCR_USR: //USR状态寄存器 value = (byte)(usr & 0xFF); this.Log(LogLevel.Info, "Read USR: 0x{0:X2}", value); - // usr = (byte)(usr & (~USR_RBFI)); //usr寄存器,取消接收中断,与hw_uart_isr关联,暂定 + usr = (byte)(usr & (~(USR_RBFI | USR_TCMP))); //usr寄存器,取消中断,与hw_uart_isr关联,暂定 + UpdateInterrupts(); break; case (long)Registers.MCR: //MCR调制控制寄存器 @@ -224,13 +225,14 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals if (interrupt) { this.Log(LogLevel.Info, "Interrupt asserted"); + machine.ScheduleAction(TimeInterval.FromMicroseconds(1), + _ => { + IRQ.Set(false); + this.Log(LogLevel.Info, "Interrupt deasserted"); + }); } - machine.ScheduleAction(TimeInterval.FromMicroseconds(1), - _ => { - IRQ.Set(false); - this.Log(LogLevel.Info, "Interrupt deasserted"); - }); + } @@ -397,7 +399,6 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals } } - // this.Wait(TimeInterval.FromMilliseconds(10)); 无法实现等待10ms,暂不实现 usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断 UpdateInterrupts(); @@ -442,10 +443,9 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals this.Log(LogLevel.Warning, "RX FIFO Already Full"); } - // this.Wait(TimeInterval.FromMilliseconds(10)); 无法实现等待10ms,暂不实现 + usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断 machine.ScheduleAction(TimeInterval.FromMicroseconds(10000), _ => { - usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断 UpdateInterrupts(); }); diff --git a/UART_kx12A5.cs b/UART_kx12A5.cs new file mode 100644 index 0000000..1a85352 --- /dev/null +++ b/UART_kx12A5.cs @@ -0,0 +1,336 @@ +// +// 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; + +namespace Antmicro.Renode.Peripherals.CustomPeripherals +{ + /// + /// UART_771_RUHW_2CFG 控制器:同步串口,遥控,无中断 + /// 接收缓存1024B,发送缓存1024B,时钟2000Hz + /// + public class UART_771_RUHW_2CFG5 : IDoubleWordPeripheral, IKnownSize + { + private readonly IMachine machine; //TODO + + public UART_771_RUHW_2CFG5(IMachine machine) + { + this.clockFrequency = 2000; + this.machine = machine; //TODO + + // 创建 FIFO + rxFifo = new Queue(); + txFifo = new Queue(); + + // 创建中断线 + IRQ = new GPIO(); + + // 初始化寄存器 + DefineRegisters(); + Reset(); + + this.Log(LogLevel.Info, "771 UART initialized, clock: {0} Hz", clockFrequency); + } + + public void Reset() + { + rxFifo.Clear(); + txFifo.Clear(); + + fsta = 0x00; // FIFO状态寄存器 + frm_cnt = 0x00; //帧头校验正确计数 + rbr = 0; // 接收FIFO剩余字节数 + crc_rcnt = 0x00; //crc正确计数 + crc_ecnt = 0x00; //crc错误计数 + rstr = 0x00; // 复位/使能寄存器 + full_cnt = 0x00; //fifo 满计数 + + RxfifoEnabled = true; //接收fifo使能 + TxfifoEnabled = false; //发送fifo禁止 + fifoTriggerLevel = 1; + currentBaudRate = 0; + + IRQ.Set(false); + + this.Log(LogLevel.Info, "UART 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.TBR_RBR: //接收FIFO,读操作 + // 在接收FIFO寄存器中读取数据 + value = (uint)ReadRBR(); + this.Log(LogLevel.Info, "Read TBR_RBR: 0x{0:X2}", (ushort)value); + break; + + 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: //帧头校验正确计数,TODO如何修改 + value = (uint)frm_cnt; + this.Log(LogLevel.Info, "Read FRM_CNT: {0}", value); + break; + + case (long)Registers.RBR_FreeBytes: //接收FIFO剩余字节数 + rbr = (ushort)rxFifo.Count; + value = (uint)rbr; + this.Log(LogLevel.Info, "Read RBR_FreeBytes: {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.RSTR: // 复位/使能 + rstr = (byte)(value & 0xFF); + this.Log(LogLevel.Info, "Write RSTR: 0x{0:X2}", rstr); + if ((rstr & 0XFF) == RSTR_RES) + { + Reset(); + } + break; + + case (long)Registers.EXTI: //向外部提供写RXFIFO寄存器 + //WriteRXFIFOData((byte)value); + break; + + case (long)Registers.FSTA: + WriteFIFOStatus((byte)value); //向外部提供写FIFO状态,遥控数据是否接收完成 + break; + + default: + this.Log(LogLevel.Warning, "Write to unknown offset: 0x{0:X} = 0x{1:X2}", offset, value); + break; + } + } + + + + + + + public byte ReadRBR() + { + byte value = 0; + + if (rxFifo.Count > 0) + { + value = rxFifo.Dequeue(); + this.Log(LogLevel.Info, "Read: 0x{0:X2} ('{1}')", value, + (value >= 32 && value < 127) ? (char)value : '.'); + } + else + { + this.Log(LogLevel.Warning, "Read from empty RBR"); + } + + // 更新状态 + if (rxFifo.Count == 0) + { + fsta = (byte)(fsta | FSTA_REMP); // 接收FIFO空 + } + + return value; + } + + public void WriteRXFIFOData(byte value) + { + // 向外部网络提供RXFIFO数据写入功能,低16位有效 + + if(RxfifoEnabled) + { + if(rxFifo.Count < RX_FIFO_SIZE) + { + rxFifo.Enqueue(value); + fsta = (byte)(fsta & (~FSTA_REMP)); //接收FIFO非空 + this.Log(LogLevel.Info, "External Write RXFIFO: 0x{0:X2} ('{1}')", value, + (value >= 32 && value < 127) ? (char)value : '.'); + } + else + { + //待定 + fsta = (byte)(fsta | FSTA_RFUL); //接收FIFO满 + this.Log(LogLevel.Warning, "RX FIFO Already Full"); + } + } + fsta = (byte)(fsta & (~FSTA_RGF) ); // 遥控数据接收未完成 + } + + public void WriteFIFOStatus(byte value) + { + // 向外部网络提供FIFO状态寄存器数据写入功能:遥控数据是否接收完成 + //value=0x80为完成 + fsta = (byte)(fsta | value); // 遥控数据接收完成状态位设置 + this.Log(LogLevel.Info, "External Write RXFIFOStatus: 0x{0:X2} ('{1}')", value, + (value >= 32 && value < 127) ? (char)value : '.'); + + if ((value & FSTA_RGF) != 0) + { + frm_cnt++; //完整接收一帧,更新帧计数 + } + } + + + public void WriteRXFIFODataString(string value) + { + // 向外部网络提供RXFIFO数据写入功能,value=0xAABB... + string data = value.StartsWith("0x",StringComparison.OrdinalIgnoreCase) ? value.Substring(2) : value; + this.Log(LogLevel.Info, "External Write RXFIFO: {0} ", value); + + string tmpString; + byte tmpHex; + int i; + + if(RxfifoEnabled) + { + if(data.Length % 2 != 0) + { + data = "0" + data; // 前面补0 + } + + if((data.Length/2) > (RX_FIFO_SIZE - rxFifo.Count)) //value超出fifo剩余 + { + this.Log(LogLevel.Warning, "Data too long"); + return; + } + + for(i = 0; i < data.Length ; i+=2) + { + tmpString = data.Substring(i, 2); + tmpHex = Convert.ToByte(tmpString, 16); + rxFifo.Enqueue(tmpHex); + } + + fsta = (byte)(fsta & (~FSTA_REMP)); //接收FIFO非空 + fsta = (byte)(fsta | FSTA_RGF); //遥控数据接收完成状态位设置 + frm_cnt++; //完整接收一帧,更新帧计数 + + if(rxFifo.Count == RX_FIFO_SIZE) + { + fsta = (byte)(fsta | FSTA_RFUL); //接收FIFO满 + this.Log(LogLevel.Warning, "RX FIFO Already Full"); + } + } + else + { + + } + + } + + public long Size => 0x80; //uart地址长度总空间 + + public GPIO IRQ { get; } + + // ======================================== + // 寄存器定义 + // ======================================== + + private enum Registers : long + { + TBR_RBR = 0x00, // RBR接收FIFO + FSTA = 0x04, // FIFO状态寄存器 + FRM_CNT = 0x1C, // 帧头校验正确计数 + RBR_FreeBytes = 0x0C, // 接收FIFO剩余字节数 + CRC_RCNT = 0x14, // 同步头,航天识别字,虚拟信道号,crc正确计数 + CRC_ECNT = 0x18, //同步头,航天识别字,虚拟信道号正确,crc错误计数 + RSTR = 0x7C, // 复位/使能 x55复位;其他使能 + FULL_CNT = 0x10, // fifo 满计数 + EXTI = 0x24 // 向外部提供读写FIFO接口 + } + + + // FSTA FIFO状态寄存器 + private const byte FSTA_REMP = 0x01; // 接收FIFO空 + private const byte FSTA_RLHF= 0x02; // 接收FIFO半满 + private const byte FSTA_RFUL = 0x04; // 接收FIFO满 + private const byte FSTA_RGF = 0x08; // 接收FIFO门控空闲,遥控数据接收完成 + + + // RSTR 复位/使能寄存器 + private const byte RSTR_RES = 0x55; // 复位 + private const byte RSTR_EN = 0xAA; // 使能 + + // 常量 + private const int RX_FIFO_SIZE = 1024; // 接收FIFO_SIZE + private const int TX_FIFO_SIZE = 1024; // 发送FIFO_SIZE + + // ======================================== + // 私有字段 + // ======================================== + + private readonly uint clockFrequency; + private uint currentBaudRate; + + + // 寄存器 + + private byte fsta; // FIFO状态寄存器 + private ushort frm_cnt; // 帧头校验正确计数 + private ushort rbr; // 接收FIFO剩余字节数 + private ushort crc_rcnt; // crc正确计数 + private ushort crc_ecnt; // crc错误计数 + private byte rstr; // 复位/使能寄存器 + private ushort full_cnt; // fifo 满计数 + + + // FIFO + private readonly Queue rxFifo; + private readonly Queue txFifo; + private bool RxfifoEnabled; + private bool TxfifoEnabled; + private int fifoTriggerLevel; + } +}