Files
simulation_Peripheral/UART_kx12A2.cs
2026-04-01 10:46:14 +08:00

403 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//
//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
{
/// <summary>
/// UART_771_RUHW_2CFG 控制器高速通信HSP
/// 接收缓存0B发送缓存512B时钟25MHz
/// </summary>
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<byte>();
// 创建中断线
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<byte> rxFifo;
private bool RxfifoEnabled;
private int fifoTriggerLevel;
}
}