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

337 lines
11 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发送缓存1024B时钟2000Hz
/// </summary>
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<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();
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<byte> rxFifo;
private readonly Queue<byte> txFifo;
private bool RxfifoEnabled;
private bool TxfifoEnabled;
private int fifoTriggerLevel;
}
}