Files
simulation_Peripheral/UART_kx12A4.cs
2026-03-30 16:34:41 +08:00

544 lines
19 KiB
C#
Raw Permalink 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 控制器
/// 接收缓存1024B发送缓存2048B时钟24MHz
/// </summary>
public class UART_771_RUHW_2CFG4 : IDoubleWordPeripheral, IKnownSize
{
private readonly IMachine machine; //TODO
public UART_771_RUHW_2CFG4(IMachine machine)
{
this.clockFrequency = 24000000;
this.machine = machine; //TODO
// 创建 FIFO
rxFifo = new Queue<byte>();
txFifo = new Queue<byte>();
// 创建中断线
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");
}
}
// 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暂不实现
machine.ScheduleAction(TimeInterval.FromMicroseconds(10000),
_ => {
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发送FIFORBR接收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 = 1024; // 接收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<byte> rxFifo;
private readonly Queue<byte> txFifo;
private bool RxfifoEnabled;
private bool TxfifoEnabled;
private int fifoTriggerLevel;
}
}