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