Files
simulation_Peripheral/UART_kx12A6.cs

391 lines
14 KiB
C#
Raw Normal View History

2026-04-01 10:46:42 +08:00
//
// 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 控制器:同步串口、遥测、有中断
/// 接收缓存0B发送缓存2048B输入时钟24MHz
/// </summary>
public class UART_771_RUHW_2CFG6 : IDoubleWordPeripheral, IKnownSize
{
private readonly IMachine machine; //TODO
public UART_771_RUHW_2CFG6(IMachine machine)
{
this.clockFrequency = 24000000;
this.machine = machine; //TODO
// 创建 FIFO
txFifo = new Queue<byte>();
rxFifo = new Queue<byte>();
// 创建中断线
IRQ = new GPIO();
// 初始化寄存器
DefineRegisters();
Reset();
this.Log(LogLevel.Info, "771 UART initialized, clock: {0} Hz", clockFrequency);
}
public void Reset()
{
txFifo.Clear();
fsta = FSTA_TEMP; // FIFO状态寄存器
frm_cnt = 0; // 帧计数
tbr = 0; // 发送FIFO剩余字节数
currentBaudRate = 16384; // 时钟配置缺省为16384Hz
clk_set = (ushort)(clockFrequency / (2 * currentBaudRate) - 1);
scramble_ctrl = 0x00; // 加解扰使能禁止
rstr = 0x00; // 复位/使能寄存器
TxfifoEnabled = true; //发送fifo使能
fifoTriggerLevel = 1;
byte_cnt = 0;
IRQ.Set(false);
UpdateInterrupts(false);
this.Log(LogLevel.Info, "TX_FIFO_SIZE 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.FSTA: // FIFO状态寄存器
value = (byte)(fsta & 0xFF);
this.Log(LogLevel.Info, "Read FSTA: 0x{0:X2}", value);
break;
case (long)Registers.FRM_CNT: //帧计数,待定
value = (uint)frm_cnt;
this.Log(LogLevel.Info, "Read TBR_FreeBytes: {0}", value);
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.CLK_SET: //时钟配置,暂无读操作
value = (uint)clk_set;
this.Log(LogLevel.Info, "Read CLK_SET: {0}", value);
break;
case (long)Registers.SCRAMBLE_CTRL: //加解扰使能禁止,暂无读操作
value = (uint)(scramble_ctrl & 0xFF);
this.Log(LogLevel.Info, "Read SCRAMBLE_CTRL: 0x{0}", value);
break;
case (long)Registers.RSTR: // 复位/使能,暂无读操作
value = (uint)(rstr & 0xFF);
this.Log(LogLevel.Info, "Read RSTR: 0x{0}", value);
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: // 发送FIFO
WriteTBR(value);
this.Log(LogLevel.Info, "Write TBR_RBR: {0}", value);
break;
case (long)Registers.CLK_SET: // 时钟配置
clk_set = (ushort)value;
currentBaudRate = (ushort)(clockFrequency / 2 / (1 + value));
this.Log(LogLevel.Info, "Write CLK_SET: {0}, currentBaudRate: {1}", value, currentBaudRate);
break;
case (long)Registers.SCRAMBLE_CTRL: // 加解扰使能禁止
scramble_ctrl = (byte)(value & 0xFF);
this.Log(LogLevel.Info, "Write SCRAMBLE_CTRL: 0x{0:X2}", value);
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;
default:
this.Log(LogLevel.Warning, "Write to unknown offset: 0x{0:X} = 0x{1:X2}", offset, value);
break;
}
}
private void UpdateInterrupts(bool flag)
{
IRQ.Set(flag);
if (flag)
{
this.Log(LogLevel.Info, "Interrupt asserted");
machine.ScheduleAction(TimeInterval.FromMicroseconds(1),
_ => {
IRQ.Set(false);
this.Log(LogLevel.Debug, "Interrupt deasserted");
});
}
}
public void WriteTBR(uint value)
{
// 从星务接收数据 操作txFifo
// value 低16位有效
if (TxfifoEnabled)
{
if (txFifo.Count < TX_FIFO_SIZE)
{
byte tmp = (byte)(value >> 8);
txFifo.Enqueue(tmp);
tmp = (byte)value;
txFifo.Enqueue(tmp);
fsta = (byte)(fsta & (~FSTA_TEMP)); // 发送缓冲区不为空D0置0
// 更新帧计数
byte_cnt += 2;
frm_cnt = (ushort)(byte_cnt / FRAME_LONG); // 遥测帧固定1024字节
if (txFifo.Count == (TX_FIFO_SIZE / 2))
{
// 置半满标志
fsta = (byte)(fsta | FSTA_TLHF); // 发送FIFO半满,D2置1
}
if (txFifo.Count > IRQ_MAXBYTES) //FIFO中的字节数大于96字节时中断自动清除
{
UpdateInterrupts(false);
}
}
else
{
fsta = (byte)(fsta | FSTA_TFUL); // 发送FIFO满
this.Log(LogLevel.Warning, "TX FIFO overflow");
}
}
else
{
// 非 FIFO 模式,待定
txFifo.Clear();
txFifo.Enqueue((byte)value);
fsta = (byte)(fsta & (~FSTA_TEMP)); // 发送缓冲区不为空D0置0
}
// 暂时不发送数据,由中间层自取
}
public uint GetTXFIFOData()
{
// 低16位有效
uint data = 0x00;
// 从 TX FIFO 发送数据中间层获取txfifo接口
if (txFifo.Count > 0)
{
data = (uint)(txFifo.Dequeue() << 8) + (uint)txFifo.Dequeue();
this.Log(LogLevel.Info, "Transmitted: {0} ", data);
}
else
{
this.Log(LogLevel.Info, "TXFIFO Null ");
}
// 更新状态
if (txFifo.Count == 0)
{
fsta = (byte)(FSTA_TEMP | FSTA_THHF); // 发送缓冲区为空D0置0,D2置0D3置1
}
else if(frm_cnt == 0)
{
// 遥测FIFO空时需要先写入大于64个字节数才能触发中断
// 无中断操作
}
else if(txFifo.Count < IRQ_MINBYTES) //FIFO中的字节数小于64字节时会产生中断
{
UpdateInterrupts(true);
}
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_TEMP | FSTA_THHF); // 发送缓冲区为空D0置0,D2置0D3置1
UpdateInterrupts(true);
}
else if(frm_cnt == 0)
{
// 遥测FIFO空时需要先写入大于64个字节数才能触发中断
// 无中断操作
}
else if(txFifo.Count < IRQ_MINBYTES) //FIFO中的字节数小于64字节时会产生中断
{
UpdateInterrupts(true);
}
return data;
}
public long Size => 0x80; //uart地址长度总空间
public GPIO IRQ { get; }
// ========================================
// 寄存器定义
// ========================================
private enum Registers : long
{
TBR_RBR = 0x00, // TBR发送FIFO
FSTA = 0x04, // FIFO状态寄存器
FRM_CNT = 0x08, // 帧计数
TBR_FreeBytes = 0x0C, // 发送FIFO剩余字节数
CLK_SET = 0x10, // 时钟配置
SCRAMBLE_CTRL = 0x14, // 加解扰使能禁止
RSTR = 0x7C, // 复位/使能 x55复位其他使能
EXTI = 0x24 // 向外部提供读写FIFO接口
}
// 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; // 1为空闲0为正在发送
// RSTR 复位/使能寄存器
private const byte RSTR_RES = 0x55; // 0x55复位其他使能
private const byte SCRAMBLE_CTRL_ENABLE = 0x55; // 0x55加解扰使能其他禁止
// 常量
private const int RX_FIFO_SIZE = 0; // 接收FIFO_SIZE
private const int TX_FIFO_SIZE = 2048; // 发送FIFO_SIZE
private const int FRAME_LONG = 1024; // 帧长固定为1024B
private const int IRQ_MINBYTES = 64; // FIFO中的字节数小于64字节时会产生中断
private const int IRQ_MAXBYTES = 96; // FIFO中的字节数大于96字节时会清中断
// ========================================
// 私有字段
// ========================================
private readonly uint clockFrequency;
private uint currentBaudRate;
private uint byte_cnt; // 字节计数,计算帧计数
// 寄存器
private byte fsta; // FIFO状态寄存器
private ushort frm_cnt; // 帧计数
private ushort tbr; // 发送FIFO剩余字节数
private ushort clk_set; // 时钟配置
private byte scramble_ctrl; // 加解扰使能禁止
private byte rstr; // 复位/使能
// FIFO
private readonly Queue<byte> rxFifo;
private readonly Queue<byte> txFifo;
private bool RxfifoEnabled;
private bool TxfifoEnabled;
private int fifoTriggerLevel;
}
}