1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using System.Collections.Generic; 9 using Antmicro.Renode.Core.Structure.Registers; 10 using Antmicro.Renode.Core; 11 using Antmicro.Migrant; 12 using Antmicro.Renode.Peripherals.Bus; 13 using Antmicro.Renode.Peripherals.UART; 14 using Antmicro.Renode.Utilities; 15 using Antmicro.Renode.Logging; 16 17 namespace Antmicro.Renode.Peripherals.UART 18 { 19 [AllowedTranslations(AllowedTranslation.WordToDoubleWord | AllowedTranslation.ByteToDoubleWord)] 20 public class RCAR_UART : IUART, IDoubleWordPeripheral, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IKnownSize 21 { RCAR_UART()22 public RCAR_UART() 23 { 24 IRQ = new GPIO(); 25 26 receiveQueue = new Queue<byte>(); 27 RegistersCollection = new DoubleWordRegisterCollection(this); 28 DefineRegisters(); 29 Reset(); 30 } 31 ReadDoubleWord(long offset)32 public uint ReadDoubleWord(long offset) 33 { 34 return RegistersCollection.Read(offset); 35 } 36 WriteDoubleWord(long offset, uint value)37 public void WriteDoubleWord(long offset, uint value) 38 { 39 RegistersCollection.Write(offset, value); 40 } 41 WriteChar(byte value)42 public void WriteChar(byte value) 43 { 44 receiveQueue.Enqueue(value); 45 // UpdateInterrupts(); 46 } 47 TransmitData(byte value)48 private void TransmitData(byte value) 49 { 50 CharReceived?.Invoke(value); 51 } 52 DefineRegisters()53 private void DefineRegisters() 54 { 55 Registers.SerialMode.Define(this) 56 57 .WithTag("CKS", 0, 2) 58 .WithTaggedFlag("MP", 2) 59 .WithTaggedFlag("STOP", 3) 60 .WithTaggedFlag("PM", 4) 61 .WithTaggedFlag("PE", 5) 62 .WithTaggedFlag("CHR", 6) 63 .WithTaggedFlag("CM", 7) 64 .WithReservedBits(8, 24); 65 66 Registers.BitRate.Define(this, 0xff) 67 .WithTag("BRR", 0, 8) 68 .WithReservedBits(8, 24); 69 70 Registers.SerialControl.Define(this) 71 72 .WithTag("CKE", 0, 2) 73 .WithTaggedFlag("TOIE", 2) 74 .WithTaggedFlag("REIE", 3) 75 .WithTaggedFlag("RE", 4) 76 .WithTaggedFlag("TE", 5) 77 .WithTaggedFlag("RIE", 6) 78 .WithTaggedFlag("TIE", 7) 79 .WithReservedBits(8, 3) 80 .WithTaggedFlag("TEIE", 11) 81 .WithReservedBits(12, 20); 82 Registers.TransmitData.Define(this, 0xff) 83 .WithValueField(0, 8, FieldMode.Write, name: "TDR", 84 writeCallback: (_, value) => 85 { 86 TransmitData((byte)value); 87 //UpdateInterrupts(); 88 }) 89 .WithReservedBits(8, 24); 90 91 Registers.ReceiveData.Define(this) 92 .WithValueField(0, 8, FieldMode.Read, name: "RDAT", 93 valueProviderCallback: _ => 94 { 95 if(!receiveQueue.TryDequeue(out byte value)) 96 { 97 this.Log(LogLevel.Warning, "Trying to read data from empty receive fifo"); 98 return 0; 99 } 100 return value; 101 }); 102 103 Registers.FifoDataCount.Define(this) 104 .WithValueField(0, 16, valueProviderCallback: _ => (ulong) receiveQueue.Count); 105 106 Registers.SerialStatus.Define(this, 0x60) 107 108 .WithTaggedFlag("DR", 0) 109 .WithTaggedFlag("RDF", 1) 110 .WithTaggedFlag("PER", 2) 111 .WithTaggedFlag("FER", 3) 112 .WithTaggedFlag("BRK", 4) 113 .WithTaggedFlag("TDFE", 5) 114 .WithTaggedFlag("TEND", 6) 115 .WithTaggedFlag("ER", 7) 116 .WithTaggedFlag("FER0", 8) 117 .WithTaggedFlag("FER1", 9) 118 .WithTaggedFlag("FER2", 10) 119 .WithTaggedFlag("FER3", 11) 120 .WithTaggedFlag("PER0", 12) 121 .WithTaggedFlag("PER1", 13) 122 .WithTaggedFlag("PER2", 14) 123 .WithTaggedFlag("PER3", 15) 124 .WithReservedBits(16, 16); 125 } 126 127 private readonly Queue<byte> receiveQueue; 128 129 [field: Transient] 130 public event Action<byte> CharReceived; 131 132 public GPIO IRQ { get; } 133 134 public DoubleWordRegisterCollection RegistersCollection { get; } 135 136 public long Size => 0x100; 137 138 public uint BaudRate => 115200; 139 Reset()140 public void Reset() 141 { 142 RegistersCollection.Reset(); 143 } 144 145 public Bits StopBits => Bits.One; 146 147 public Parity ParityBit => Parity.None; 148 149 private enum Registers 150 { 151 SerialMode = 0x0, 152 BitRate = 0x4, 153 SerialControl = 0x8, 154 TransmitData = 0xc, 155 SerialStatus = 0x10, 156 ReceiveData = 0x14, 157 FifoControl = 0x18, 158 FifoDataCount = 0x1c, 159 SerialPort = 0x20, 160 LineStatus = 0x24, 161 FrequencyDivision = 0x30, 162 ClockSelect = 0x34, 163 } 164 } 165 } 166 167