// //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; } }