From 482f44b7ccd7114e8f033d7c9a1e5f532ebd7d30 Mon Sep 17 00:00:00 2001 From: yangyanqing Date: Wed, 1 Apr 2026 10:46:42 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E8=87=B3?= =?UTF-8?q?=E3=80=8C/=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- UART_kx12A6.cs | 390 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 390 insertions(+) create mode 100644 UART_kx12A6.cs diff --git a/UART_kx12A6.cs b/UART_kx12A6.cs new file mode 100644 index 0000000..fafffdf --- /dev/null +++ b/UART_kx12A6.cs @@ -0,0 +1,390 @@ +// +// 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 控制器:同步串口、遥测、有中断 + /// 接收缓存0B,发送缓存2048B,输入时钟24MHz + /// + 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(); + rxFifo = new Queue(); + + // 创建中断线 + 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置0,D3置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置0,D3置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 rxFifo; + private readonly Queue txFifo; + private bool RxfifoEnabled; + private bool TxfifoEnabled; + private int fifoTriggerLevel; + } +}