上传文件至「/」
This commit is contained in:
615
UART_kx12A1.cs
Normal file
615
UART_kx12A1.cs
Normal file
@@ -0,0 +1,615 @@
|
|||||||
|
//
|
||||||
|
// 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 控制器
|
||||||
|
/// 接收缓存512B,发送缓存512B,时钟24MHz
|
||||||
|
/// </summary>
|
||||||
|
public class UART_771_RUHW_2CFG1 : IDoubleWordPeripheral, IBytePeripheral, IKnownSize
|
||||||
|
{
|
||||||
|
private readonly IMachine machine; //TODO
|
||||||
|
|
||||||
|
public UART_771_RUHW_2CFG1(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_l = 0x00; // 波特率设置寄存器
|
||||||
|
brsr_h = 0x00;
|
||||||
|
fsta = (byte)(FSTA_TEMP | FSTA_REMP); // FIFO状态寄存器
|
||||||
|
tbr = 0; // 发送FIFO剩余字节数
|
||||||
|
rbr = 0 ; // 接收FIFO剩余字节数
|
||||||
|
rstr = 0x00; // 复位/使能寄存器
|
||||||
|
|
||||||
|
ext_signal = 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)
|
||||||
|
{
|
||||||
|
this.Log(LogLevel.Info, "entry ReadDoubleWord: 0x{0}", offset);
|
||||||
|
return ReadRegisters(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void WriteDoubleWord(long offset, uint value)
|
||||||
|
{
|
||||||
|
WriteRegisters(offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 自定义
|
||||||
|
// ========================================
|
||||||
|
public uint ReadRegisters(long offset)
|
||||||
|
{
|
||||||
|
this.Log(LogLevel.Info, "entry ReadRegisters: 0x{0}", 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_h << 8) + brsr_l);
|
||||||
|
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);
|
||||||
|
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: //自定义,向外部提供读写信号
|
||||||
|
value = (uint)(ext_signal & 0xFF);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
this.Log(LogLevel.Info, "entry WriteRegisters: 0x{0}, value: 0x{1}", offset, 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: //控制寄存器
|
||||||
|
WriteByte(offset, (byte)value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (long)Registers.MCR: //调制控制寄存器
|
||||||
|
WriteByte(offset, (byte)value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (long)Registers.BRSR: //波特率寄存器
|
||||||
|
if(value != 0)
|
||||||
|
{
|
||||||
|
currentBaudRate = (uint)(clockFrequency / value);;
|
||||||
|
brsr_l = (byte)(value);
|
||||||
|
brsr_h = (byte)(value >> 8);
|
||||||
|
this.Log(LogLevel.Info, "Write BRSR: {0}", value);
|
||||||
|
WriteByte(offset, brsr_l);
|
||||||
|
WriteByte((offset + 0x01), brsr_h);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (long)Registers.RSTR: // 复位/使能
|
||||||
|
WriteByte(offset, (byte)value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (long)Registers.EXTI: //向外部提供写RXFIFO寄存器
|
||||||
|
value = (uint)ext_signal;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
this.Log(LogLevel.Warning, "Write to unknown offset: 0x{0:X} = 0x{1:X2}", offset, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public byte ReadByte(long offset)
|
||||||
|
{
|
||||||
|
this.Log(LogLevel.Info, "entry ReadByte: 0x{0}", offset);
|
||||||
|
return 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void WriteByte(long offset, byte value)
|
||||||
|
{
|
||||||
|
this.Log(LogLevel.Info, "entry WriteByte: 0x{0}, value: 0x{1}", offset, value);
|
||||||
|
switch(offset)
|
||||||
|
{
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
brsr_l = value;
|
||||||
|
this.Log(LogLevel.Info, "Write BRSR: 0x{0:X2}", brsr_l);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case (long)Registers.BRSR_H:
|
||||||
|
if(value != 0)
|
||||||
|
{
|
||||||
|
brsr_h = value;
|
||||||
|
this.Log(LogLevel.Info, "Write BRSR: 0x{0:X2}", brsr_h);
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
ext_signal = (byte)(ext_signal & (~EXT_SIGNAL_READ)); // 通知外部不可读
|
||||||
|
|
||||||
|
|
||||||
|
// 更新状态
|
||||||
|
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)); // 清除溢出错误
|
||||||
|
ext_signal = (byte)(ext_signal | EXT_SIGNAL_WRITE); // 通知外部可写
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
ext_signal = (byte)(ext_signal & (~EXT_SIGNAL_WRITE)); // 通知外部不可写
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断
|
||||||
|
machine.ScheduleAction(TimeInterval.FromMicroseconds(10000),
|
||||||
|
_ => {
|
||||||
|
UpdateInterrupts(); //等待10ms
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public long Size => 0x28; //uart地址长度总空间
|
||||||
|
|
||||||
|
public GPIO IRQ { get; }
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 寄存器定义
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
private enum Registers : long
|
||||||
|
{
|
||||||
|
TBR_RBR = 0x00, // TBR发送FIFO,RBR接收FIFO
|
||||||
|
UCR_USR = 0x04, // UCR控制寄存器,USR状态寄存器
|
||||||
|
MCR = 0x08, // 调制控制寄存器
|
||||||
|
BRSR = 0x0C, // 波特率设置寄存器
|
||||||
|
BRSR_H = 0x0D, // 波特率设置寄存器-高位
|
||||||
|
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 byte EXT_SIGNAL_WRITE = 0x0F; //0x0F表示外部可写
|
||||||
|
private const byte EXT_SIGNAL_READ = 0xF0; //0xF0表示外部可读
|
||||||
|
|
||||||
|
// 常量
|
||||||
|
private const int RX_FIFO_SIZE = 512; // 接收FIFO_SIZE
|
||||||
|
private const int TX_FIFO_SIZE = 512; // 发送FIFO_SIZE
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 私有字段
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
private readonly uint clockFrequency;
|
||||||
|
private uint currentBaudRate;
|
||||||
|
|
||||||
|
|
||||||
|
// 寄存器
|
||||||
|
private byte ucr; // 控制寄存器
|
||||||
|
private byte usr; // 状态寄存器
|
||||||
|
private byte mcr; // 调制控制寄存器
|
||||||
|
private byte brsr_l; // 波特率设置寄存器
|
||||||
|
private byte brsr_h; // 波特率设置寄存器
|
||||||
|
private byte fsta; // FIFO状态寄存器
|
||||||
|
private ushort tbr; // 发送FIFO剩余字节数
|
||||||
|
private ushort rbr; // 接收FIFO剩余字节数
|
||||||
|
private byte rstr; // 复位/使能寄存器
|
||||||
|
|
||||||
|
private byte ext_signal; //外部提供读写信号,读信号待确定
|
||||||
|
|
||||||
|
|
||||||
|
// FIFO
|
||||||
|
private readonly Queue<byte> rxFifo;
|
||||||
|
private readonly Queue<byte> txFifo;
|
||||||
|
private bool RxfifoEnabled;
|
||||||
|
private bool TxfifoEnabled;
|
||||||
|
private int fifoTriggerLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
402
UART_kx12A2.cs
Normal file
402
UART_kx12A2.cs
Normal file
@@ -0,0 +1,402 @@
|
|||||||
|
//
|
||||||
|
//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 控制器:高速通信HSP
|
||||||
|
/// 接收缓存0B,发送缓存512B,时钟25MHz
|
||||||
|
/// </summary>
|
||||||
|
public class UART_771_RUHW_2CFG2 : IDoubleWordPeripheral, IKnownSize
|
||||||
|
{
|
||||||
|
private readonly IMachine machine; //TODO
|
||||||
|
|
||||||
|
public UART_771_RUHW_2CFG2(IMachine machine)
|
||||||
|
{
|
||||||
|
this.clockFrequency = 25000000;
|
||||||
|
this.machine = machine; //TODO
|
||||||
|
|
||||||
|
// 创建 FIFO
|
||||||
|
rxFifo = new Queue<byte>();
|
||||||
|
|
||||||
|
// 创建中断线
|
||||||
|
IRQ = new GPIO();
|
||||||
|
|
||||||
|
// 初始化寄存器
|
||||||
|
DefineRegisters();
|
||||||
|
Reset();
|
||||||
|
|
||||||
|
this.Log(LogLevel.Info, "771 UART initialized, clock: {0} Hz", clockFrequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
rxFifo.Clear();
|
||||||
|
|
||||||
|
ucr = 0x00; // 控制寄存器(默认0x02)
|
||||||
|
usr = 0x00; // 状态寄存器
|
||||||
|
mcr = MCR_REN; // 调制控制寄存器:中断使能,接收使能
|
||||||
|
brsr = 0x43; // 波特率设置寄存器
|
||||||
|
fsta = 0x00; // FIFO状态寄存器
|
||||||
|
rstr = 0x00; // 复位/使能寄存器
|
||||||
|
|
||||||
|
RxfifoEnabled = 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.RBR: //接收FIFO,读操作
|
||||||
|
// 在接收FIFO寄存器中读取数据,高速数据串口为双字节读取,暂定小端TODO
|
||||||
|
value = (uint)(ReadRBR() << 8) + (uint)ReadRBR();
|
||||||
|
this.Log(LogLevel.Info, "Read TBR_RBR: 0x{0:X8}", value);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (long)Registers.UCR_USR: //USR状态寄存器
|
||||||
|
value = (byte)(usr & 0xFF);
|
||||||
|
this.Log(LogLevel.Info, "Read USR: 0x{0:X2}", value);
|
||||||
|
usr = 0x00; // 高速上行:读取该寄存器后,自动清寄存器(来自需求)
|
||||||
|
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 FSTA: 0x{0:X2}", 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.RSTR: // 复位/使能,暂无读操作
|
||||||
|
value = (byte)(rstr & 0xFF);
|
||||||
|
this.Log(LogLevel.Info, "Read RSTR: 0x{0:X2}", 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.UCR_USR: //控制寄存器UCR
|
||||||
|
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(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_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 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(uint value)
|
||||||
|
{
|
||||||
|
// 向外部网络提供RXFIFO数据写入功能,value低16位有效
|
||||||
|
|
||||||
|
if(RxfifoEnabled)
|
||||||
|
{
|
||||||
|
if(rxFifo.Count < RX_FIFO_SIZE)
|
||||||
|
{
|
||||||
|
byte tmp = (byte)(value >> 8);
|
||||||
|
rxFifo.Enqueue(tmp);
|
||||||
|
tmp = (byte)value;
|
||||||
|
rxFifo.Enqueue(tmp);
|
||||||
|
fsta = (byte)(fsta & (~FSTA_REMP)); //接收FIFO非空
|
||||||
|
this.Log(LogLevel.Info, "External Write RXFIFO: 0x{0:X4} ('{1}')", (ushort)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,暂不实现
|
||||||
|
usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断
|
||||||
|
UpdateInterrupts();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public long Size => 0x28; //uart地址长度总空间
|
||||||
|
|
||||||
|
public GPIO IRQ { get; }
|
||||||
|
|
||||||
|
// ========================================
|
||||||
|
// 寄存器定义
|
||||||
|
// ========================================
|
||||||
|
|
||||||
|
private enum Registers : long
|
||||||
|
{
|
||||||
|
RBR = 0x00, // RBR接收FIFO,无发送操作
|
||||||
|
UCR_USR = 0x04, // UCR控制寄存器,USR状态寄存器
|
||||||
|
MCR = 0x08, // 调制控制寄存器
|
||||||
|
BRSR = 0x0C, // 波特率设置寄存器
|
||||||
|
RSTR = 0x10, /// 复位/使能 x55复位;其他使能
|
||||||
|
FSTA = 0x14, // FIFO状态寄存器
|
||||||
|
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_REMP = 0x10; // 接收FIFO空
|
||||||
|
private const byte FSTA_RLHF = 0x20; // 接收FIFO低阈值半满
|
||||||
|
private const byte FSTA_RFUL = 0x40; // 接收FIFO满
|
||||||
|
|
||||||
|
|
||||||
|
// RSTR 复位/使能寄存器
|
||||||
|
private const byte RSTR_RES = 0x55; // 复位
|
||||||
|
private const byte RSTR_EN = 0xAA; // 使能
|
||||||
|
|
||||||
|
// 常量
|
||||||
|
private const int RX_FIFO_SIZE = 2048; // 接收FIFO_SIZE
|
||||||
|
private const int TX_FIFO_SIZE = 512; // 发送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 byte rstr; // 复位/使能寄存器
|
||||||
|
|
||||||
|
|
||||||
|
// FIFO
|
||||||
|
private readonly Queue<byte> rxFifo;
|
||||||
|
private bool RxfifoEnabled;
|
||||||
|
private int fifoTriggerLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
542
UART_kx12A3.cs
Normal file
542
UART_kx12A3.cs
Normal file
@@ -0,0 +1,542 @@
|
|||||||
|
//
|
||||||
|
// 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 控制器
|
||||||
|
/// 接收缓存512B,发送缓存2048B,时钟24MHz
|
||||||
|
/// </summary>
|
||||||
|
public class UART_771_RUHW_2CFG3 : IDoubleWordPeripheral, IKnownSize
|
||||||
|
{
|
||||||
|
private readonly IMachine machine; //TODO
|
||||||
|
|
||||||
|
public UART_771_RUHW_2CFG3(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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断
|
||||||
|
machine.ScheduleAction(TimeInterval.FromMicroseconds(10000),
|
||||||
|
_ => {
|
||||||
|
UpdateInterrupts(); //等待10ms
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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,暂不实现
|
||||||
|
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发送FIFO,RBR接收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 = 512; // 接收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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -105,7 +105,8 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals
|
|||||||
case (long)Registers.UCR_USR: //USR状态寄存器
|
case (long)Registers.UCR_USR: //USR状态寄存器
|
||||||
value = (byte)(usr & 0xFF);
|
value = (byte)(usr & 0xFF);
|
||||||
this.Log(LogLevel.Info, "Read USR: 0x{0:X2}", value);
|
this.Log(LogLevel.Info, "Read USR: 0x{0:X2}", value);
|
||||||
// usr = (byte)(usr & (~USR_RBFI)); //usr寄存器,取消接收中断,与hw_uart_isr关联,暂定
|
usr = (byte)(usr & (~(USR_RBFI | USR_TCMP))); //usr寄存器,取消中断,与hw_uart_isr关联,暂定
|
||||||
|
UpdateInterrupts();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case (long)Registers.MCR: //MCR调制控制寄存器
|
case (long)Registers.MCR: //MCR调制控制寄存器
|
||||||
@@ -224,8 +225,6 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals
|
|||||||
if (interrupt)
|
if (interrupt)
|
||||||
{
|
{
|
||||||
this.Log(LogLevel.Info, "Interrupt asserted");
|
this.Log(LogLevel.Info, "Interrupt asserted");
|
||||||
}
|
|
||||||
|
|
||||||
machine.ScheduleAction(TimeInterval.FromMicroseconds(1),
|
machine.ScheduleAction(TimeInterval.FromMicroseconds(1),
|
||||||
_ => {
|
_ => {
|
||||||
IRQ.Set(false);
|
IRQ.Set(false);
|
||||||
@@ -234,6 +233,9 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void UpdateModemControl()
|
private void UpdateModemControl()
|
||||||
{
|
{
|
||||||
if((mcr & MCR_REN) == 0)
|
if((mcr & MCR_REN) == 0)
|
||||||
@@ -397,7 +399,6 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// this.Wait(TimeInterval.FromMilliseconds(10)); 无法实现等待10ms,暂不实现
|
|
||||||
usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断
|
usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
|
|
||||||
@@ -442,10 +443,9 @@ namespace Antmicro.Renode.Peripherals.CustomPeripherals
|
|||||||
this.Log(LogLevel.Warning, "RX FIFO Already Full");
|
this.Log(LogLevel.Warning, "RX FIFO Already Full");
|
||||||
}
|
}
|
||||||
|
|
||||||
// this.Wait(TimeInterval.FromMilliseconds(10)); 无法实现等待10ms,暂不实现
|
usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断
|
||||||
machine.ScheduleAction(TimeInterval.FromMicroseconds(10000),
|
machine.ScheduleAction(TimeInterval.FromMicroseconds(10000),
|
||||||
_ => {
|
_ => {
|
||||||
usr = (byte)(usr | USR_RBFI); //usr寄存器,置接收中断
|
|
||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
336
UART_kx12A5.cs
Normal file
336
UART_kx12A5.cs
Normal file
@@ -0,0 +1,336 @@
|
|||||||
|
//
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user