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