上传文件至「/」
修改地测、遥测中断处理方式,改为事件驱动
This commit is contained in:
642
UART_kx12A4_event_1.cs
Normal file
642
UART_kx12A4_event_1.cs
Normal file
@@ -0,0 +1,642 @@
|
|||||||
|
// 配合地测中断更改版本
|
||||||
|
//author:liuwenbo
|
||||||
|
// 修改为事件驱动的中断触发逻辑
|
||||||
|
|
||||||
|
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.Time;
|
||||||
|
using Antmicro.Migrant;
|
||||||
|
|
||||||
|
namespace Antmicro.Renode.Peripherals.CustomPeripherals
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UART_771_RUHW_2CFG 控制器
|
||||||
|
/// 接收缓存1024B,发送缓存2048B,时钟24MHz
|
||||||
|
/// 事件驱动版本 - 使用machine.ScheduleAction精确模拟波特率
|
||||||
|
/// </summary>
|
||||||
|
public class UART_771_RUHW_2CFG4 : IDoubleWordPeripheral, IKnownSize, IUART
|
||||||
|
{
|
||||||
|
private readonly IMachine machine;
|
||||||
|
private readonly object txFifoLock = new object();
|
||||||
|
private readonly object rxFifoLock = new object();
|
||||||
|
|
||||||
|
public UART_771_RUHW_2CFG4(IMachine machine)
|
||||||
|
{
|
||||||
|
this.clockFrequency = 24000000;
|
||||||
|
this.machine = machine;
|
||||||
|
transmissionGeneration = 0;
|
||||||
|
|
||||||
|
// 创建 FIFO
|
||||||
|
rxFifo = new Queue<byte>();
|
||||||
|
txFifo = new Queue<byte>();
|
||||||
|
|
||||||
|
// 创建中断线
|
||||||
|
IRQ = new GPIO();
|
||||||
|
|
||||||
|
// 初始化寄存器
|
||||||
|
DefineRegisters();
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
this.Log(LogLevel.Info, "771 UART initialized (event-driven), clock: {0} Hz", clockFrequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
lock(txFifoLock)
|
||||||
|
{
|
||||||
|
txFifo.Clear();
|
||||||
|
}
|
||||||
|
lock(rxFifoLock)
|
||||||
|
{
|
||||||
|
rxFifo.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
ucr = 0x00;
|
||||||
|
usr = USR_TFE; // 初始FIFO空
|
||||||
|
mcr = 0x00;
|
||||||
|
brsr = 0;
|
||||||
|
fsta = (byte)(FSTA_TEMP | FSTA_REMP);
|
||||||
|
tbr = 0;
|
||||||
|
rbr = 0;
|
||||||
|
rstr = 0x00;
|
||||||
|
currentBaudRate = 115200;
|
||||||
|
|
||||||
|
RxfifoEnabled = true;
|
||||||
|
TxfifoEnabled = true;
|
||||||
|
fifoTriggerLevel = 1;
|
||||||
|
|
||||||
|
transmissionScheduled = false;
|
||||||
|
transmissionGeneration++;
|
||||||
|
|
||||||
|
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:
|
||||||
|
value = ReadRBR();
|
||||||
|
this.Log(LogLevel.Info, "Read RBR: 0x{0:X2}", value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (long)Registers.UCR_USR:
|
||||||
|
value = (byte)(usr & 0xFF);
|
||||||
|
this.Log(LogLevel.Info, "Read USR: 0x{0:X2}", value);
|
||||||
|
// 读取USR会清除中断标志
|
||||||
|
usr = (byte)(usr & (~(USR_RBFI | USR_TCMP)));
|
||||||
|
UpdateInterrupts();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (long)Registers.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.Debug, "Read BRSR: {0}", value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (long)Registers.FSTA:
|
||||||
|
value = (byte)(fsta & 0xFF);
|
||||||
|
this.Log(LogLevel.Debug, "Read FSTA: 0x{0:X2}", value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (long)Registers.TBR_FreeBytes:
|
||||||
|
lock(txFifoLock)
|
||||||
|
{
|
||||||
|
tbr = (ushort)txFifo.Count;
|
||||||
|
}
|
||||||
|
value = (uint)tbr;
|
||||||
|
this.Log(LogLevel.Debug, "Read TBR_FreeBytes: {0}", value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (long)Registers.RBR_FreeBytes:
|
||||||
|
lock(rxFifoLock)
|
||||||
|
{
|
||||||
|
rbr = (ushort)rxFifo.Count;
|
||||||
|
}
|
||||||
|
value = (uint)rbr;
|
||||||
|
this.Log(LogLevel.Debug, "Read RBR_FreeBytes: {0}", value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (long)Registers.RSTR:
|
||||||
|
value = (uint)rstr;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
this.Log(LogLevel.Warning, "Read to unknown offset: 0x{0:X}", offset);
|
||||||
|
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: 0x{0:X2}", value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (long)Registers.UCR_USR:
|
||||||
|
ucr = (byte)(value & 0xFF);
|
||||||
|
this.Log(LogLevel.Info, "Write UCR: 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}, BaudRate: {1}", brsr, currentBaudRate);
|
||||||
|
// 计算传输速率
|
||||||
|
ComputeTransRate();
|
||||||
|
}
|
||||||
|
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 interrupt = false;
|
||||||
|
|
||||||
|
if ((mcr & MCR_BEN) != 0)
|
||||||
|
{
|
||||||
|
if ((usr & USR_TCMP) != 0) // 发送完成中断
|
||||||
|
interrupt = true;
|
||||||
|
else if ((usr & USR_RBFI) != 0) // 接收中断
|
||||||
|
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, "UART interrupt triggered: USR=0x{0:X2}", usr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateModemControl()
|
||||||
|
{
|
||||||
|
if((mcr & MCR_REN) == 0)
|
||||||
|
{
|
||||||
|
RxfifoEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Log(LogLevel.Info, "Modem control: INT_EN={0}, RX_EN={1}",
|
||||||
|
(mcr & MCR_BEN) != 0, (mcr & MCR_REN) != 0);
|
||||||
|
|
||||||
|
UpdateInterrupts();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 按波特率计算传输速率
|
||||||
|
// ========================================
|
||||||
|
public void ComputeTransRate()
|
||||||
|
{
|
||||||
|
// 计算传输时间(使用官方IUART扩展方法的逻辑)
|
||||||
|
int bitsPerByte = 1; // 起始位
|
||||||
|
bitsPerByte += 8; // 数据位
|
||||||
|
|
||||||
|
// 校验位判断
|
||||||
|
byte parityBits = (byte)((ucr & UCR_PB) >> 1); // 提取bits 1-3
|
||||||
|
if (parityBits != 0x07)
|
||||||
|
{
|
||||||
|
bitsPerByte += 1; // ?有校验位(奇校验或偶校验)
|
||||||
|
|
||||||
|
// 对于你的配置:
|
||||||
|
// ucr应该被设置为 0x02 (二进制: 00000010)
|
||||||
|
// parityBits = (0x02 & 0x0E) >> 1 = 0x02 >> 1 = 0x01 (奇校验)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据配置添加停止位
|
||||||
|
if ((ucr & UCR_STB) != 0)
|
||||||
|
{
|
||||||
|
bitsPerByte += 2; // 2停止位
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bitsPerByte += 1; // 1停止位
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算传输时间(秒)
|
||||||
|
if(currentBaudRate == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
double secondsPerByte = (double)bitsPerByte / currentBaudRate;
|
||||||
|
microsecondsPerByte = (ulong)(secondsPerByte * 1000000);
|
||||||
|
|
||||||
|
this.Log(LogLevel.Debug,
|
||||||
|
"Scheduling byte transmission: {0} bits @ {1} bps = {2}μs",
|
||||||
|
bitsPerByte, currentBaudRate, microsecondsPerByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// CPU写TBR寄存器(发送数据)- 事件驱动
|
||||||
|
// ========================================
|
||||||
|
public void WriteTBR(byte value)
|
||||||
|
{
|
||||||
|
this.Log(LogLevel.Info, "Write TBR: 0x{0:X2} ('{1}')", value,
|
||||||
|
(value >= 32 && value < 127) ? (char)value : '.');
|
||||||
|
|
||||||
|
lock(txFifoLock)
|
||||||
|
{
|
||||||
|
if (TxfifoEnabled)
|
||||||
|
{
|
||||||
|
if (txFifo.Count < TX_FIFO_SIZE)
|
||||||
|
{
|
||||||
|
bool wasEmpty = (txFifo.Count == 0);
|
||||||
|
|
||||||
|
txFifo.Enqueue(value);
|
||||||
|
|
||||||
|
// 更新FIFO状态
|
||||||
|
fsta = (byte)(fsta & (~FSTA_TEMP)); // FIFO非空
|
||||||
|
usr = (byte)(usr & (~USR_TFE)); // 清除FIFO空标志
|
||||||
|
|
||||||
|
// FIFO从空变为非空,清除发送完成中断
|
||||||
|
if (wasEmpty)
|
||||||
|
{
|
||||||
|
usr = (byte)(usr & (~USR_TCMP));
|
||||||
|
this.Log(LogLevel.Info, "FIFO: Empty->NonEmpty, clearing TCMP");
|
||||||
|
|
||||||
|
// 启动传输调度(事件驱动)
|
||||||
|
ScheduleNextByteTransmit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (txFifo.Count == TX_FIFO_SIZE)
|
||||||
|
{
|
||||||
|
fsta = (byte)(fsta | FSTA_TFUL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fsta = (byte)(fsta | FSTA_TFUL);
|
||||||
|
usr = (byte)(usr | USR_OE); // 溢出错误
|
||||||
|
this.Log(LogLevel.Warning, "TX FIFO overflow");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
txFifo.Clear();
|
||||||
|
txFifo.Enqueue(value);
|
||||||
|
fsta = (byte)(fsta & (~FSTA_TEMP));
|
||||||
|
usr = (byte)(usr & (~USR_TFE));
|
||||||
|
usr = (byte)(usr & (~USR_TCMP));
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateInterrupts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 核心:按波特率调度发送(事件驱动)
|
||||||
|
// ========================================
|
||||||
|
private void ScheduleNextByteTransmit()
|
||||||
|
{
|
||||||
|
lock(txFifoLock)
|
||||||
|
{
|
||||||
|
// 防止重复调度
|
||||||
|
if (transmissionScheduled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (txFifo.Count == 0)
|
||||||
|
{
|
||||||
|
// FIFO空,设置发送完成标志
|
||||||
|
fsta = (byte)((fsta & 0xF0) | FSTA_TEMP);
|
||||||
|
usr = (byte)(usr | USR_TFE);
|
||||||
|
usr = (byte)(usr | USR_TCMP); // 触发发送完成中断
|
||||||
|
|
||||||
|
this.Log(LogLevel.Info, "TX FIFO empty, setting TCMP interrupt");
|
||||||
|
|
||||||
|
UpdateInterrupts();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
transmissionScheduled = true;
|
||||||
|
var currentGeneration = transmissionGeneration;
|
||||||
|
|
||||||
|
// 使用Renode虚拟时间调度
|
||||||
|
machine.ScheduleAction(
|
||||||
|
TimeInterval.FromMicroseconds(microsecondsPerByte),
|
||||||
|
_ => TransmitOneByte(currentGeneration)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TransmitOneByte(ulong generation)
|
||||||
|
{
|
||||||
|
lock(txFifoLock)
|
||||||
|
{
|
||||||
|
transmissionScheduled = false;
|
||||||
|
|
||||||
|
// 检查是否被Reset取消
|
||||||
|
if (generation != transmissionGeneration)
|
||||||
|
{
|
||||||
|
this.Log(LogLevel.Debug, "Transmission cancelled (reset)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (txFifo.Count > 0)
|
||||||
|
{
|
||||||
|
byte data = txFifo.Dequeue();
|
||||||
|
|
||||||
|
// 触发CharReceived事件(外部Backend可订阅 网络中间层改为订阅这个事件的方式)
|
||||||
|
TransmitCharacter(data);
|
||||||
|
|
||||||
|
this.Log(LogLevel.Info,
|
||||||
|
"Transmitted: 0x{0:X2} ('{1}'), Remaining: {2}",
|
||||||
|
data,
|
||||||
|
(data >= 32 && data < 127) ? (char)data : '.',
|
||||||
|
txFifo.Count);
|
||||||
|
|
||||||
|
// 继续调度下一个字节
|
||||||
|
ScheduleNextByteTransmit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实现IUART接口的TransmitCharacter(触发事件)
|
||||||
|
protected void TransmitCharacter(byte character)
|
||||||
|
{
|
||||||
|
CharReceived?.Invoke(character);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 可选:提供批量读取接口(给网络层用)
|
||||||
|
// ========================================
|
||||||
|
public string GetTXFIFODataString()
|
||||||
|
{
|
||||||
|
// 这个方法现在只是读取接口,不负责触发中断
|
||||||
|
// 中断逻辑完全由ScheduleNextByteTransmit处理
|
||||||
|
|
||||||
|
string data = "110118"; // 协议头
|
||||||
|
|
||||||
|
lock(txFifoLock)
|
||||||
|
{
|
||||||
|
if (txFifo.Count == 0)
|
||||||
|
{
|
||||||
|
return "0x001800"; // 空数据标识
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量读取(可选,用于网络传输优化)
|
||||||
|
int bytesToRead = Math.Min(txFifo.Count, 128);
|
||||||
|
|
||||||
|
for (int i = 0; i < bytesToRead; i++)
|
||||||
|
{
|
||||||
|
if (txFifo.Count > 0)
|
||||||
|
{
|
||||||
|
byte tmp = txFifo.Dequeue();
|
||||||
|
data += tmp.ToString("X2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Log(LogLevel.Debug, "Batch read: {0} bytes, Remaining: {1}",
|
||||||
|
bytesToRead, txFifo.Count);
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// RX方向:接收数据
|
||||||
|
// ========================================
|
||||||
|
public byte ReadRBR()
|
||||||
|
{
|
||||||
|
byte value = 0;
|
||||||
|
|
||||||
|
lock(rxFifoLock)
|
||||||
|
{
|
||||||
|
if (rxFifo.Count > 0)
|
||||||
|
{
|
||||||
|
value = rxFifo.Dequeue();
|
||||||
|
this.Log(LogLevel.Info, "Read RBR: 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);
|
||||||
|
usr = (byte)(usr & (~USR_OE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateInterrupts();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 实现IUART接口的WriteChar(外部写入)
|
||||||
|
public void WriteChar(byte value)
|
||||||
|
{
|
||||||
|
WriteRXFIFOData(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteRXFIFOData(byte value)
|
||||||
|
{
|
||||||
|
lock(rxFifoLock)
|
||||||
|
{
|
||||||
|
if(RxfifoEnabled)
|
||||||
|
{
|
||||||
|
if(rxFifo.Count < RX_FIFO_SIZE)
|
||||||
|
{
|
||||||
|
rxFifo.Enqueue(value);
|
||||||
|
fsta = (byte)(fsta & (~FSTA_REMP));
|
||||||
|
this.Log(LogLevel.Info, "External Write RXFIFO: 0x{0:X2} ('{1}')", value,
|
||||||
|
(value >= 32 && value < 127) ? (char)value : '.');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fsta = (byte)(fsta | FSTA_RFUL);
|
||||||
|
this.Log(LogLevel.Warning, "RX FIFO full");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usr = (byte)(usr | USR_RBFI);
|
||||||
|
UpdateInterrupts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// IUART接口实现
|
||||||
|
// ========================================
|
||||||
|
public uint BaudRate => currentBaudRate;
|
||||||
|
|
||||||
|
public Bits StopBits => ((ucr & UCR_STB) != 0) ? Bits.Two : Bits.One;
|
||||||
|
|
||||||
|
public Parity ParityBit
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
// 提取UCR的bits 1-3
|
||||||
|
byte parityBits = (byte)((ucr & UCR_PB) >> 1);
|
||||||
|
|
||||||
|
if (parityBits == 0x07) // 111b = 0x07 = 无校验
|
||||||
|
return Parity.None;
|
||||||
|
|
||||||
|
if (parityBits == 0x01) // 001b = 0x01 = 奇校验
|
||||||
|
return Parity.Odd;
|
||||||
|
|
||||||
|
if (parityBits == 0x00) // 000b = 0x00 = 偶校验
|
||||||
|
return Parity.Even;
|
||||||
|
|
||||||
|
// 其他值默认为无校验
|
||||||
|
return Parity.None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[field: Transient]
|
||||||
|
public event Action<byte> CharReceived; // 事件:外部可订阅
|
||||||
|
|
||||||
|
public long Size => 0x28;
|
||||||
|
public GPIO IRQ { get; }
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 寄存器定义
|
||||||
|
// ========================================
|
||||||
|
private enum Registers : long
|
||||||
|
{
|
||||||
|
TBR_RBR = 0x00,
|
||||||
|
UCR_USR = 0x04,
|
||||||
|
MCR = 0x08,
|
||||||
|
BRSR = 0x0C,
|
||||||
|
FSTA = 0x10,
|
||||||
|
TBR_FreeBytes = 0x14,
|
||||||
|
RBR_FreeBytes = 0x18,
|
||||||
|
RSTR = 0x20,
|
||||||
|
EXTI = 0x24
|
||||||
|
}
|
||||||
|
|
||||||
|
// 位定义
|
||||||
|
private const byte UCR_STB = 0x01;
|
||||||
|
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;
|
||||||
|
private const byte USR_RBFI = 0x80;
|
||||||
|
private const byte MCR_BEN = 0x04;
|
||||||
|
private const byte MCR_REN = 0x20;
|
||||||
|
private const byte FSTA_TEMP = 0x01;
|
||||||
|
private const byte FSTA_TFUL = 0x04;
|
||||||
|
private const byte FSTA_REMP = 0x10;
|
||||||
|
private const byte FSTA_RFUL = 0x40;
|
||||||
|
private const byte RSTR_RES = 0x55;
|
||||||
|
private const int RX_FIFO_SIZE = 1024;
|
||||||
|
private const int TX_FIFO_SIZE = 2048;
|
||||||
|
|
||||||
|
// 私有字段
|
||||||
|
private readonly uint clockFrequency;
|
||||||
|
private uint currentBaudRate;
|
||||||
|
private byte ucr;
|
||||||
|
private byte usr;
|
||||||
|
private byte mcr;
|
||||||
|
private ushort brsr;
|
||||||
|
private byte fsta;
|
||||||
|
private ushort tbr;
|
||||||
|
private ushort rbr;
|
||||||
|
private byte rstr;
|
||||||
|
private readonly Queue<byte> rxFifo;
|
||||||
|
private readonly Queue<byte> txFifo;
|
||||||
|
private bool RxfifoEnabled;
|
||||||
|
private bool TxfifoEnabled;
|
||||||
|
private int fifoTriggerLevel;
|
||||||
|
private bool transmissionScheduled;
|
||||||
|
private ulong transmissionGeneration;
|
||||||
|
private ulong microsecondsPerByte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// // 网络层修改示例(伪代码)
|
||||||
|
// class UDPNetworkLayer
|
||||||
|
// {
|
||||||
|
// private List<byte> buffer = new List<byte>();
|
||||||
|
|
||||||
|
// public void Initialize(UART_771_RUHW_2CFG4 uart)
|
||||||
|
// {
|
||||||
|
// // 订阅事件,替代25Hz定时器
|
||||||
|
// uart.CharReceived += OnUartDataReceived;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// private void OnUartDataReceived(byte data)
|
||||||
|
// {
|
||||||
|
// buffer.Add(data);
|
||||||
|
|
||||||
|
// // 批量发送(可选的优化)
|
||||||
|
// if (buffer.Count >= 128 || bufferTimeout)
|
||||||
|
// {
|
||||||
|
// SendToUDP(buffer.ToArray());
|
||||||
|
// buffer.Clear();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
502
UART_kx12A6_event.cs
Normal file
502
UART_kx12A6_event.cs
Normal file
@@ -0,0 +1,502 @@
|
|||||||
|
//
|
||||||
|
// 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;
|
||||||
|
// using Antmicro.Migrant;
|
||||||
|
|
||||||
|
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;
|
||||||
|
private readonly object txFifoLock = new object();
|
||||||
|
private readonly object rxFifoLock = new object();
|
||||||
|
|
||||||
|
public UART_771_RUHW_2CFG6(IMachine machine)
|
||||||
|
{
|
||||||
|
this.clockFrequency = 24000000;
|
||||||
|
this.machine = machine;
|
||||||
|
transmissionGeneration = 0;
|
||||||
|
|
||||||
|
// 创建 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()
|
||||||
|
{
|
||||||
|
lock(txFifoLock)
|
||||||
|
{
|
||||||
|
txFifo.Clear();
|
||||||
|
}
|
||||||
|
lock(rxFifoLock)
|
||||||
|
{
|
||||||
|
rxFifo.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
fsta = FSTA_TEMP; // FIFO状态寄存器
|
||||||
|
frm_cnt = 0; // 帧计数
|
||||||
|
byte_cnt = 0;
|
||||||
|
tbr = 0; // 发送FIFO剩余字节数
|
||||||
|
currentBaudRate = 16384; // 时钟配置缺省为16384Hz
|
||||||
|
clk_set = (ushort)(clockFrequency / (2 * currentBaudRate) - 1);
|
||||||
|
scramble_ctrl = 0x00; // 加解扰使能禁止
|
||||||
|
rstr = 0x00; // 复位/使能寄存器
|
||||||
|
|
||||||
|
RxfifoEnabled = true;
|
||||||
|
TxfifoEnabled = true; //发送fifo使能
|
||||||
|
|
||||||
|
transmissionScheduled = false;
|
||||||
|
transmissionGeneration++;
|
||||||
|
InterruptTriggerCondition = false; //重置后不满足条件
|
||||||
|
|
||||||
|
IRQ.Set(false);
|
||||||
|
UpdateInterrupts();
|
||||||
|
|
||||||
|
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状态寄存器
|
||||||
|
lock(txFifoLock)
|
||||||
|
{
|
||||||
|
value = (byte)(fsta & 0xFF);
|
||||||
|
}
|
||||||
|
this.Log(LogLevel.Info, "Read FSTA: 0x{0:X2}", value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (long)Registers.FRM_CNT: //帧计数,待定
|
||||||
|
lock(txFifoLock)
|
||||||
|
{
|
||||||
|
value = (uint)frm_cnt;
|
||||||
|
}
|
||||||
|
this.Log(LogLevel.Info, "Read FRM_CNT: {0}", value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (long)Registers.TBR_FreeBytes: //发送FIFO剩余字节数
|
||||||
|
lock(txFifoLock)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
// 计算传输速率
|
||||||
|
ComputeTransRate();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 按波特率计算传输速率,同步串口无起始位、停止位、奇偶校验位
|
||||||
|
// ========================================
|
||||||
|
public void ComputeTransRate()
|
||||||
|
{
|
||||||
|
// 计算传输时间
|
||||||
|
int bitsPerByte = 8; // 数据位
|
||||||
|
|
||||||
|
// 计算传输时间(秒),16384hz->488.24us
|
||||||
|
if(currentBaudRate == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
double secondsPerByte = (double)bitsPerByte / currentBaudRate;
|
||||||
|
microsecondsPerByte = (ulong)(secondsPerByte * 1000000);
|
||||||
|
|
||||||
|
this.Log(LogLevel.Debug,
|
||||||
|
"Scheduling byte transmission: {0} bits @ {1} bps = {2}μs",
|
||||||
|
bitsPerByte, currentBaudRate, microsecondsPerByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateInterrupts()
|
||||||
|
{
|
||||||
|
if(InterruptTriggerCondition == false)
|
||||||
|
{
|
||||||
|
// FIFO空 → 必须先写满>64,期间绝对不触发中断
|
||||||
|
IRQ.Set(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock(txFifoLock)
|
||||||
|
{
|
||||||
|
// <64 中断,>96 清除,中间保持
|
||||||
|
if (txFifo.Count < IRQ_MINBYTES)
|
||||||
|
{
|
||||||
|
IRQ.Set(true);
|
||||||
|
this.Log(LogLevel.Info, "Interrupt asserted");
|
||||||
|
}
|
||||||
|
else if (txFifo.Count > IRQ_MAXBYTES)
|
||||||
|
{
|
||||||
|
IRQ.Set(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void WriteTBR(uint value)
|
||||||
|
{
|
||||||
|
// 从星务接收数据 ,操作txFifo
|
||||||
|
// value 低16位有效
|
||||||
|
this.Log(LogLevel.Info, "Write TBR: 0x{0:X2}", value);
|
||||||
|
|
||||||
|
lock(txFifoLock)
|
||||||
|
{
|
||||||
|
if (TxfifoEnabled)
|
||||||
|
{
|
||||||
|
if ((txFifo.Count + 2) <= TX_FIFO_SIZE)
|
||||||
|
{
|
||||||
|
bool wasEmpty = (txFifo.Count == 0);
|
||||||
|
|
||||||
|
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字节
|
||||||
|
|
||||||
|
// FIFO从空变为非空
|
||||||
|
if(wasEmpty)
|
||||||
|
{
|
||||||
|
this.Log(LogLevel.Info, "FIFO: Empty->NonEmpty");
|
||||||
|
// 启动传输调度(事件驱动)
|
||||||
|
ScheduleNextByteTransmit();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (txFifo.Count >= (TX_FIFO_SIZE / 2))
|
||||||
|
{
|
||||||
|
// 置半满标志
|
||||||
|
fsta = (byte)(fsta | FSTA_TLHF); // 发送FIFO半满,D2置1
|
||||||
|
}
|
||||||
|
|
||||||
|
if((InterruptTriggerCondition == false) && (txFifo.Count > IRQ_MINBYTES))
|
||||||
|
{
|
||||||
|
InterruptTriggerCondition = true;
|
||||||
|
UpdateInterrupts();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 核心:按波特率调度发送(事件驱动)
|
||||||
|
// ========================================
|
||||||
|
private void ScheduleNextByteTransmit()
|
||||||
|
{
|
||||||
|
lock(txFifoLock)
|
||||||
|
{
|
||||||
|
// 防止重复调度
|
||||||
|
if (transmissionScheduled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (txFifo.Count == 0)
|
||||||
|
{
|
||||||
|
// FIFO空
|
||||||
|
fsta = (byte)((fsta & 0xF0) | FSTA_TEMP);
|
||||||
|
fsta |= FSTA_THHF; //空闲置1
|
||||||
|
this.Log(LogLevel.Info, "TX FIFO empty");
|
||||||
|
InterruptTriggerCondition = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (txFifo.Count < (TX_FIFO_SIZE / 2))
|
||||||
|
{
|
||||||
|
// 清半满标志
|
||||||
|
fsta = (byte)(fsta & (~FSTA_TLHF)); // 发送FIFO非半满,D2清0
|
||||||
|
}
|
||||||
|
|
||||||
|
transmissionScheduled = true;
|
||||||
|
fsta = (byte)(fsta & (~FSTA_THHF)); //正在发送,置0
|
||||||
|
var currentGeneration = transmissionGeneration;
|
||||||
|
|
||||||
|
// 使用Renode虚拟时间调度
|
||||||
|
machine.ScheduleAction(
|
||||||
|
TimeInterval.FromMicroseconds(microsecondsPerByte),
|
||||||
|
_ => TransmitOneByte(currentGeneration)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TransmitOneByte(ulong generation)
|
||||||
|
{
|
||||||
|
lock(txFifoLock)
|
||||||
|
{
|
||||||
|
transmissionScheduled = false;
|
||||||
|
|
||||||
|
// 检查是否被Reset取消
|
||||||
|
if (generation != transmissionGeneration)
|
||||||
|
{
|
||||||
|
this.Log(LogLevel.Debug, "Transmission cancelled (reset)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (txFifo.Count > 0)
|
||||||
|
{
|
||||||
|
byte data = txFifo.Dequeue();
|
||||||
|
|
||||||
|
// 触发CharReceived事件(外部Backend可订阅 网络中间层改为订阅这个事件的方式)
|
||||||
|
TransmitCharacter(data);
|
||||||
|
|
||||||
|
this.Log(LogLevel.Info,
|
||||||
|
"Transmitted: 0x{0:X2} ('{1}'), Remaining: {2}",
|
||||||
|
data,
|
||||||
|
(data >= 32 && data < 127) ? (char)data : '.',
|
||||||
|
txFifo.Count);
|
||||||
|
|
||||||
|
// 继续调度下一个字节
|
||||||
|
UpdateInterrupts();
|
||||||
|
ScheduleNextByteTransmit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
UpdateInterrupts();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 同步串口属性
|
||||||
|
// ========================================
|
||||||
|
public uint BaudRate => 0;
|
||||||
|
public enum Bits { None }
|
||||||
|
public Bits StopBits => Bits.None;
|
||||||
|
public enum Parity { None }
|
||||||
|
public Parity ParityBit => Parity.None;
|
||||||
|
|
||||||
|
public uint GetFSTA() => fsta;
|
||||||
|
public uint GetByteCount() => byte_cnt;
|
||||||
|
public ushort GetFrameCount() => frm_cnt;
|
||||||
|
|
||||||
|
private void TransmitCharacter(byte 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复位;其他使能
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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 bool transmissionScheduled;
|
||||||
|
private ulong transmissionGeneration;
|
||||||
|
private ulong microsecondsPerByte;
|
||||||
|
private bool InterruptTriggerCondition; //FIFO为空后写入64字节才允许触发中断
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user