1 // 2 // Copyright (c) 2010-2023 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.Collections.Generic; 8 using Antmicro.Renode.Peripherals.Bus; 9 using Antmicro.Renode.Core.Structure.Registers; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Utilities; 12 using Antmicro.Renode.Logging; 13 14 namespace Antmicro.Renode.Peripherals.UART 15 { 16 [AllowedTranslations(AllowedTranslation.ByteToDoubleWord)] 17 public class Renesas_SCI : UARTBase, IDoubleWordPeripheral, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IKnownSize 18 { Renesas_SCI(IMachine machine)19 public Renesas_SCI(IMachine machine) : base(machine) 20 { 21 RegistersCollection = new DoubleWordRegisterCollection(this); 22 23 DefineRegisters(); 24 } 25 WriteChar(byte value)26 public override void WriteChar(byte value) 27 { 28 receiveFifo.Enqueue(value); 29 UpdateInterrupts(); 30 } 31 ReadDoubleWord(long offset)32 public uint ReadDoubleWord(long offset) 33 { 34 return RegistersCollection.Read(offset); 35 } 36 Reset()37 public override void Reset() 38 { 39 base.Reset(); 40 RegistersCollection.Reset(); 41 receiveFifo.Clear(); 42 } 43 WriteDoubleWord(long offset, uint value)44 public void WriteDoubleWord(long offset, uint value) 45 { 46 RegistersCollection.Write(offset, value); 47 } 48 49 public DoubleWordRegisterCollection RegistersCollection { get; } 50 51 public long Size => 0x400; 52 53 public override Bits StopBits => Bits.One; 54 55 public override Parity ParityBit => Parity.None; 56 57 public override uint BaudRate => 115200; 58 59 public GPIO RxIRQ { get; } = new GPIO(); 60 public GPIO TxIRQ { get; } = new GPIO(); 61 public GPIO TxEndIRQ { get; } = new GPIO(); 62 CharWritten()63 protected override void CharWritten() 64 { 65 // intentionally left blank 66 } 67 QueueEmptied()68 protected override void QueueEmptied() 69 { 70 // intentionally left blank 71 } 72 UpdateInterrupts()73 private void UpdateInterrupts() 74 { 75 // On real hardware FCR.RTRG value doesn't affect interrupt requests, 76 // they are triggered for every character in RX fifo. 77 RxIRQ.Set(receiveInterruptEnable.Value && receiveFifo.Count > 0); 78 79 TxEndIRQ.Set(transmitEndInterruptEnable.Value); 80 TxIRQ.Set(transmitInterruptEnable.Value); 81 } 82 DefineRegisters()83 private void DefineRegisters() 84 { 85 Registers.ReceiveData.Define(this, resetValue: 0x0) 86 .WithValueField(0, 9, FieldMode.Read, name: "RDAT", 87 valueProviderCallback: _ => 88 { 89 if(!receiveFifo.TryDequeue(out byte value)) 90 { 91 this.Log(LogLevel.Warning, "Trying to read data from empty receive fifo"); 92 } 93 UpdateInterrupts(); 94 return value; 95 }) 96 .WithTaggedFlag("MPB", 9) 97 .WithFlag(10, mode: FieldMode.Read, name: "DR", 98 valueProviderCallback: _ => 99 { 100 return receiveFifo.Count > 0; 101 }) 102 .WithTaggedFlag("FPER", 11) 103 .WithTaggedFlag("FFER", 12) 104 .WithReservedBits(13, 11) 105 .WithTaggedFlag("ORER", 24) 106 .WithReservedBits(25, 2) 107 .WithTaggedFlag("PER", 27) 108 .WithTaggedFlag("FER", 28) 109 .WithReservedBits(29, 3); 110 111 Registers.TransmitData.Define(this, resetValue: 0xffffffff) 112 .WithValueField(0, 9, FieldMode.Write, name: "TDAT", 113 writeCallback: (_, value) => 114 { 115 if(BitHelper.IsBitSet(value, 8)) 116 { 117 this.Log(LogLevel.Warning, "Trying to transmit data with 9-th bit set: {0:X}, sending: {1:X}", value, (byte)value); 118 } 119 this.TransmitCharacter((byte)value); 120 }) 121 .WithTaggedFlag("MPBT", 9) 122 .WithReservedBits(10, 22); 123 124 // no special effects, software requires RE and TE flags to be settable 125 Registers.CommonControl0.Define(this, resetValue: 0x0) 126 .WithFlag(0, name: "RE") 127 .WithReservedBits(1, 3) 128 .WithFlag(4, name: "TE") 129 .WithReservedBits(5, 3) 130 .WithTaggedFlag("MPIE", 8) 131 .WithTaggedFlag("DCME", 9) 132 .WithTaggedFlag("IDSEL", 10) 133 .WithReservedBits(11, 5) 134 .WithFlag(16, out receiveInterruptEnable, name: "RIE") 135 .WithReservedBits(17, 3) 136 .WithFlag(20, out transmitInterruptEnable, name: "TIE") 137 .WithFlag(21, out transmitEndInterruptEnable, name: "TEIE") 138 .WithReservedBits(22, 2) 139 .WithTaggedFlag("SSE", 24) 140 .WithReservedBits(25, 7) 141 .WithWriteCallback((_, __) => UpdateInterrupts()); 142 143 Registers.FIFOControlRegister.Define(this, resetValue: 0x1f1f0000) 144 .WithTaggedFlag("DRES", 0) 145 .WithReservedBits(1, 7) 146 .WithTag("TTRG", 8, 5) 147 .WithReservedBits(13, 2) 148 .WithTaggedFlag("TFRST", 15) 149 // On real hardware FCR.RTRG value doesn't affect interrupt requests 150 // they are triggered for every character in RX fifo. 151 .WithValueField(16, 5, out receiveFifoDataTriggerNumber, name: "RTRG", 152 writeCallback: (oldValue, newValue) => 153 { 154 if(newValue > 0xf) 155 { 156 this.Log(LogLevel.Warning, "{0:X} - value prohibited for FCR.RTRG field, keeping the previous value: {1:X}", newValue, oldValue); 157 receiveFifoDataTriggerNumber.Value = oldValue; 158 } 159 UpdateInterrupts(); 160 }) 161 .WithReservedBits(21, 2) 162 .WithTaggedFlag("RFRST", 23) 163 .WithTag("RSTRG", 24, 5) 164 .WithReservedBits(29, 3); 165 166 Registers.FIFOReceiveStatus.Define(this, resetValue: 0x0) 167 .WithFlag(0, mode: FieldMode.Read, name: "DR", 168 valueProviderCallback: _ => 169 { 170 return receiveFifo.Count > 0; 171 }) 172 .WithReservedBits(1, 7) 173 .WithValueField(8, 6, FieldMode.Read, name: "R", 174 valueProviderCallback: _ => (ulong)receiveFifo.Count) 175 .WithReservedBits(14, 2) 176 .WithTag("PNUM", 16, 6) 177 .WithReservedBits(22, 2) 178 .WithTag("FNUM", 24, 6) 179 .WithReservedBits(30, 2); 180 } 181 182 private IValueRegisterField receiveFifoDataTriggerNumber; 183 private IFlagRegisterField receiveInterruptEnable; 184 private IFlagRegisterField transmitInterruptEnable; 185 private IFlagRegisterField transmitEndInterruptEnable; 186 187 private readonly Queue<byte> receiveFifo = new Queue<byte>(); 188 189 private enum Registers : long 190 { 191 ReceiveData = 0x0, 192 TransmitData = 0x4, 193 CommonControl0 = 0x8, 194 FIFOControlRegister = 0x24, 195 FIFOReceiveStatus = 0x50, 196 } 197 } 198 } 199