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 Antmicro.Renode.Peripherals.Bus; 8 using Antmicro.Renode.Core; 9 using Antmicro.Renode.Logging; 10 using Antmicro.Renode.Core.Structure.Registers; 11 12 namespace Antmicro.Renode.Peripherals.UART 13 { 14 [AllowedTranslations(AllowedTranslation.ByteToDoubleWord | AllowedTranslation.WordToDoubleWord)] 15 public class PL011 : UARTBase, IDoubleWordPeripheral, IKnownSize, IProvidesRegisterCollection<DoubleWordRegisterCollection> 16 { PL011(IMachine machine, uint fifoSize = 1, uint frequency = 24000000)17 public PL011(IMachine machine, uint fifoSize = 1, uint frequency = 24000000) : base(machine) 18 { 19 hardwareFifoSize = fifoSize; 20 uartClockFrequency = frequency; 21 22 IRQ = new GPIO(); 23 interruptRawStatuses = new bool[InterruptsCount]; 24 interruptMasks = new bool[InterruptsCount]; 25 26 RegistersCollection = new DoubleWordRegisterCollection(this); 27 DefineRegisters(); 28 29 Reset(); 30 } 31 ReadDoubleWord(long offset)32 public uint ReadDoubleWord(long offset) 33 { 34 lock(innerLock) 35 { 36 return RegistersCollection.Read(offset); 37 } 38 } 39 Reset()40 public override void Reset() 41 { 42 base.Reset(); 43 lock(innerLock) 44 { 45 RegistersCollection.Reset(); 46 47 // receiveFifoSize and receiveInterruptTriggerPoint depend on register values. 48 UpdateReceiveFifoSize(); 49 UpdateReceiveInterruptTriggerPoint(); 50 51 System.Array.ForEach(interruptRawStatuses, status => status = false); 52 System.Array.ForEach(interruptMasks, mask => mask = false); 53 UpdateInterrupts(); 54 } 55 } 56 WriteDoubleWord(long offset, uint value)57 public void WriteDoubleWord(long offset, uint value) 58 { 59 lock(innerLock) 60 { 61 RegistersCollection.Write(offset, value); 62 } 63 } 64 65 public override uint BaudRate 66 { 67 get 68 { 69 var divisor = 16 * (integerBaudRate.Value + (fractionalBaudRate.Value / 64)); 70 return (divisor > 0) ? (uartClockFrequency / (uint)divisor) : 0; 71 } 72 } 73 74 public GPIO IRQ { get; } 75 76 public override Parity ParityBit 77 { 78 get 79 { 80 if(!parityEnable.Value) 81 { 82 return Parity.None; 83 } 84 else 85 { 86 if(!evenParitySelect.Value) 87 { 88 return stickParitySelect.Value ? Parity.Forced1 : Parity.Odd; 89 } 90 else 91 { 92 return stickParitySelect.Value ? Parity.Forced0 : Parity.Even; 93 } 94 } 95 } 96 } 97 98 public DoubleWordRegisterCollection RegistersCollection { get; } 99 100 public long Size => 0x1000; 101 102 public override Bits StopBits => twoStopBitsSelect.Value ? Bits.Two : Bits.One; 103 CharWritten()104 protected override void CharWritten() 105 { 106 UpdateInterrupts(); 107 } 108 109 protected override bool IsReceiveEnabled 110 { 111 get 112 { 113 return AssertFlagEnabled(uartEnable, "Character cannot be received by UART; UARTEN is disabled!") 114 && AssertFlagEnabled(receiveEnable, "Character cannot be received by UART; RXE is disabled!"); 115 } 116 } 117 QueueEmptied()118 protected override void QueueEmptied() 119 { 120 UpdateInterrupts(); 121 } 122 AssertFlagEnabled(IFlagRegisterField flag, string errorMessage)123 private bool AssertFlagEnabled(IFlagRegisterField flag, string errorMessage) 124 { 125 if(!flag.Value) 126 { 127 this.Log(LogLevel.Error, errorMessage); 128 return false; 129 } 130 return true; 131 } 132 ClearInterrupt(int interrupt)133 private void ClearInterrupt(int interrupt) 134 { 135 this.Log(LogLevel.Noisy, "Clearing {0} interrupt.", (Interrupts)interrupt); 136 interruptRawStatuses[interrupt] = false; 137 UpdateInterrupts(); 138 } 139 DefineRegisters()140 private void DefineRegisters() 141 { 142 Registers.Data.Define(this) 143 .WithValueField(0, 8, name: "DATA - Receive (read) / Transmit (write) data character", 144 valueProviderCallback: _ => ReadDataRegister(), 145 writeCallback: (_, newValue) => WriteDataRegister((uint)newValue)) 146 .WithTaggedFlag("FE - Framing error", 8) 147 .WithTaggedFlag("PE - Parity error", 9) 148 .WithTaggedFlag("BE - Break error", 10) 149 .WithTaggedFlag("OE - Overrun error", 11) 150 .WithReservedBits(12, 4) 151 ; 152 153 Registers.Control.Define(this, 0x300) 154 .WithFlag(0, out uartEnable, name: "UARTEN - UART enable", 155 changeCallback: (_, value) => 156 { 157 if(value) 158 { 159 // Documentation states that the Transmit interrupt should be only set upon 160 // crossing the threshold and enabling/disabling FIFO, but some software 161 // requires it to be set after enabling UART 162 interruptRawStatuses[(int)Interrupts.Transmit] = true; 163 UpdateInterrupts(); 164 } 165 }) 166 .WithTaggedFlag("SIREN - SIR enable", 1) 167 .WithTaggedFlag("SIRLP - IrDA SIR low power mode", 2) 168 // These 4 bits can be written/read by software but there's no logic associated. 169 .WithFlags(3, 4, name: "Vendor specific") 170 .WithFlag(7, out loopbackEnable, name: "LBE - Loop back enable") 171 .WithFlag(8, out transmitEnable, name: "TXE - Transmit enable") 172 .WithFlag(9, out receiveEnable, name: "RXE - Receive enable") 173 // No logic needed for DTR/RTS so these are flags just to hush write warnings. 174 .WithFlag(10, name: "DTR - Data transmit ready") 175 .WithFlag(11, name: "RTS - Request to send") 176 .WithTaggedFlag("Out1", 12) 177 .WithTaggedFlag("Out2", 13) 178 .WithTaggedFlag("RTSEn - RTS hardware flow control enable", 14) 179 .WithTaggedFlag("CTSEn - CTS hardware flow control enable", 15) 180 ; 181 182 Registers.Flag.Define(this) // Doesn't need to have a reset value; it's 0b10010000 nevertheless. 183 .WithTaggedFlag("CTS - Clear to send", 0) 184 .WithTaggedFlag("DSR - Data set ready", 1) 185 .WithTaggedFlag("DCD - Data carrier detect", 2) 186 .WithTaggedFlag("BUSY - UART busy", 3) 187 .WithFlag(4, FieldMode.Read, name: "RXFE - Receive FIFO empty", valueProviderCallback: _ => Count == 0) 188 .WithTaggedFlag("TXFF - Transmit FIFO full", 5) 189 .WithFlag(6, FieldMode.Read, name: "RXFF - Receive FIFO full", valueProviderCallback: _ => Count >= receiveFifoSize) 190 .WithFlag(7, FieldMode.Read, name: "TXFE - Transmit FIFO empty", valueProviderCallback: _ => true) // Always set. 191 .WithTaggedFlag("RI - Ring indicator", 8) 192 .WithReservedBits(9, 7) 193 ; 194 195 Registers.RawInterruptStatus.Define(this) 196 .WithFlags(0, 11, FieldMode.Read, valueProviderCallback: (interrupt, _) => interruptRawStatuses[interrupt]) 197 .WithReservedBits(11, 5) 198 ; 199 200 Registers.LineControl.Define(this) 201 .WithTaggedFlag("BRK - Send break", 0) 202 .WithFlag(1, out parityEnable, name: "PEN - Parity enable") 203 .WithFlag(2, out evenParitySelect, name: "EPS - Even parity select") 204 .WithFlag(3, out twoStopBitsSelect, name: "STP2 - Two stop bits select") 205 .WithFlag(4, out enableFifoBuffers, name: "FEN - Enable FIFOs", changeCallback: (_, __) => UpdateReceiveFifoSize()) 206 .WithEnumField(5, 2, out wordLength, name: "WLEN - Word length") 207 .WithFlag(7, out stickParitySelect, name: "SPS - Stick parity select") 208 .WithReservedBits(8, 8) 209 ; 210 211 Registers.IrDALowPowerCounter.Define(this) 212 .WithTag("ILPDVSR - 8-bit low-power divisor value.", 0, 8) 213 .WithReservedBits(8, 24) 214 ; 215 216 Registers.InterruptMask.Define(this) 217 .WithFlags(0, 11, changeCallback: (interrupt, _, newValue) => { interruptMasks[interrupt] = newValue; UpdateInterrupts(); }) 218 .WithReservedBits(11, 5) 219 ; 220 221 Registers.IntegerBaudRate.Define(this) 222 .WithValueField(0, 16, out integerBaudRate, name: "BAUD DIVINT - The integer baud rate divisor.") 223 ; 224 225 Registers.FractionalBaudRate.Define(this) 226 .WithValueField(0, 6, out fractionalBaudRate, name: "BAUD DIVFRAC - The fractional baud rate divisor") 227 .WithReservedBits(6, 10) 228 ; 229 230 Registers.DMAControl.Define(this) 231 .WithTaggedFlag("RXDMAE - Receive DMA enable", 0) 232 .WithTaggedFlag("TXDMAE - Transmit DMA enable", 1) 233 .WithTaggedFlag("DMAONERR - DMA on error", 2) 234 .WithReservedBits(3, 13) 235 ; 236 237 Registers.InterruptFIFOLevel.Define(this, 0b010010) // The reset value is 2 for both fields. 238 .WithValueField(0, 3, name: "TXIFLSEL - Transmit interrupt FIFO level select") // Hush write warnings. Transmit interrupts are never triggered. 239 .WithValueField(3, 3, out receiveInterruptFifoLevelSelect, name: "RXIFLSEL - Receive interrupt FIFO level select", 240 changeCallback: (_, __) => UpdateReceiveInterruptTriggerPoint()) 241 .WithReservedBits(6, 10) 242 ; 243 244 Registers.InterruptClear.Define(this) 245 .WithFlags(0, 11, FieldMode.Write, writeCallback: (interrupt, _, newValue) => { if(newValue) ClearInterrupt(interrupt); }) 246 .WithReservedBits(11, 5) 247 ; 248 249 // Any write to this 8-bit register should clear all the errors if they're ever set. 250 Registers.ReceiveStatus.Define(this) 251 .WithFlag(0, name: "FE - Framing error", valueProviderCallback: _ => false) 252 .WithFlag(1, name: "PE - Parity error", valueProviderCallback: _ => false) 253 .WithFlag(2, name: "BE - Break error", valueProviderCallback: _ => false) 254 .WithFlag(3, name: "OE - Overrun error", valueProviderCallback: _ => false) 255 .WithFlags(4, 4, FieldMode.Write) 256 ; 257 258 Registers.MaskedInterruptStatus.Define(this) 259 .WithValueField(0, 11, FieldMode.Read, name: "Masked interrupt status", valueProviderCallback: _ => MaskedInterruptStatus) 260 .WithReservedBits(11, 5) 261 ; 262 263 Registers.UARTPeriphID0.DefineMany(this, 4, (register, idx) => 264 { 265 register.WithValueField(0, 8, FieldMode.Read, valueProviderCallback: _ => peripheralID[idx]) 266 .WithReservedBits(8, 8); 267 }, name: "Peripheral identification registers n"); 268 269 Registers.UARTPCellID0.DefineMany(this, 4, (register, idx) => 270 { 271 register.WithValueField(0, 8, FieldMode.Read, valueProviderCallback: _ => primeCellID[idx]) 272 .WithReservedBits(8, 8); 273 }, name: "PrimeCell identification registers n"); 274 } 275 ReadDataRegister()276 private byte ReadDataRegister() 277 { 278 // DATA register can be read to check errors so reading from an empty queue isn't a problem. 279 if(TryGetCharacter(out byte character)) 280 { 281 WarnIfWordLengthIncorrect(); 282 UpdateInterrupts(); 283 } 284 return character; 285 } 286 UpdateReceiveInterruptTriggerPoint()287 private void UpdateReceiveInterruptTriggerPoint() 288 { 289 var levelSelect = receiveInterruptFifoLevelSelect.Value; 290 switch(levelSelect) 291 { 292 case 0b000: receiveInterruptTriggerPoint = 1d / 8d * receiveFifoSize; break; 293 case 0b001: receiveInterruptTriggerPoint = 1d / 4d * receiveFifoSize; break; 294 case 0b010: receiveInterruptTriggerPoint = 1d / 2d * receiveFifoSize; break; 295 case 0b011: receiveInterruptTriggerPoint = 3d / 4d * receiveFifoSize; break; 296 case 0b100: receiveInterruptTriggerPoint = 7d / 8d * receiveFifoSize; break; 297 default: 298 this.Log(LogLevel.Warning, "Receive interrupt FIFO level select written with invalid value: {0}", levelSelect); 299 return; 300 } 301 this.Log(LogLevel.Debug, "Receive Interrupt Trigger Point set to: {0} (level select = {1}; fifo size = {2}{3})", 302 receiveInterruptTriggerPoint, levelSelect, receiveFifoSize, enableFifoBuffers.Value ? "" : " (FIFO buffers disabled)"); 303 304 UpdateInterrupts(); 305 } 306 UpdateInterrupts()307 private void UpdateInterrupts() 308 { 309 interruptRawStatuses[(int)Interrupts.Receive] = Count >= receiveInterruptTriggerPoint; 310 IRQ.Set(MaskedInterruptStatus != 0); 311 } 312 UpdateReceiveFifoSize()313 private void UpdateReceiveFifoSize() 314 { 315 if(enableFifoBuffers.Value) 316 { 317 receiveFifoSize = hardwareFifoSize; 318 this.Log(LogLevel.Debug, "FIFO buffers enabled."); 319 } 320 else 321 { 322 receiveFifoSize = 1; 323 this.Log(LogLevel.Debug, "FIFO buffers disabled."); 324 interruptRawStatuses[(int)Interrupts.Transmit] = true; 325 UpdateInterrupts(); 326 } 327 UpdateReceiveInterruptTriggerPoint(); 328 } 329 WarnIfWordLengthIncorrect()330 private void WarnIfWordLengthIncorrect() 331 { 332 if(wordLength.Value != WordLength.EightBits && wordLength.Value != WordLength.SevenBits) 333 { 334 this.Log(LogLevel.Warning, "DATA read or written while {0}-bit word length is set (WLEN={1}). Only 7-bit and 8-bit words are fully supported.", 335 wordLength.Value == WordLength.FiveBits ? "5" : "6", (uint)wordLength.Value); 336 } 337 } 338 WriteDataRegister(uint value)339 private void WriteDataRegister(uint value) 340 { 341 if(!AssertFlagEnabled(uartEnable, "DATA register cannot be written to; UARTEN is disabled!") 342 || !AssertFlagEnabled(transmitEnable, "DATA register cannot be written to; TXE is disabled!")) 343 { 344 return; 345 } 346 WarnIfWordLengthIncorrect(); 347 348 if(!loopbackEnable.Value) 349 { 350 TransmitCharacter((byte)value); 351 } 352 interruptRawStatuses[(int)Interrupts.Transmit] = true; 353 UpdateInterrupts(); 354 } 355 356 private uint InterruptMask => Renode.Utilities.BitHelper.GetValueFromBitsArray(interruptMasks); 357 358 private uint MaskedInterruptStatus => RawInterruptStatus & InterruptMask; 359 360 private uint RawInterruptStatus => Renode.Utilities.BitHelper.GetValueFromBitsArray(interruptRawStatuses); 361 362 private IFlagRegisterField enableFifoBuffers; 363 private IFlagRegisterField evenParitySelect; 364 private IValueRegisterField fractionalBaudRate; 365 private IValueRegisterField integerBaudRate; 366 private IFlagRegisterField loopbackEnable; 367 private IFlagRegisterField parityEnable; 368 private IFlagRegisterField receiveEnable; 369 private IValueRegisterField receiveInterruptFifoLevelSelect; 370 private IFlagRegisterField stickParitySelect; 371 private IFlagRegisterField transmitEnable; 372 private IFlagRegisterField twoStopBitsSelect; 373 private IFlagRegisterField uartEnable; 374 private IEnumRegisterField<WordLength> wordLength; 375 376 private readonly uint hardwareFifoSize; 377 private readonly bool[] interruptMasks; 378 private readonly bool[] interruptRawStatuses; 379 private readonly uint[] peripheralID = { 0x11, 0x10, 0x34, 0x0 }; 380 private readonly uint[] primeCellID = { 0x0D, 0xF0, 0x05, 0xB1 }; 381 private readonly uint uartClockFrequency; 382 383 private uint receiveFifoSize; 384 private double receiveInterruptTriggerPoint; 385 386 private const uint InterruptsCount = 11; 387 388 private enum Interrupts 389 { 390 ModemRingIndicator, 391 ModemClearToSend, 392 ModemDataCarrierDetect, 393 ModemDataSetReady, 394 Receive, 395 Transmit, 396 ReceiveTimeout, 397 FramingError, 398 ParityError, 399 BreakError, 400 OverrunError, 401 } 402 403 private enum Registers : long 404 { 405 Data = 0x000, 406 ReceiveStatus = 0x004, //aka ErrorClear 407 Flag = 0x018, 408 IrDALowPowerCounter = 0x020, 409 IntegerBaudRate = 0x024, 410 FractionalBaudRate = 0x028, 411 LineControl = 0x02c, 412 Control = 0x030, 413 InterruptFIFOLevel = 0x034, 414 InterruptMask = 0x038, 415 RawInterruptStatus = 0x03c, 416 MaskedInterruptStatus = 0x040, 417 InterruptClear = 0x044, 418 DMAControl = 0x048, 419 UARTPeriphID0 = 0xFE0, 420 UARTPeriphID1 = 0xFE4, 421 UARTPeriphID2 = 0xFE8, 422 UARTPeriphID3 = 0xFEC, 423 UARTPCellID0 = 0xFF0, 424 UARTPCellID1 = 0xFF4, 425 UARTPCellID2 = 0xFF8, 426 UARTPCellID3 = 0xFFC 427 } 428 429 private enum WordLength 430 { 431 FiveBits, 432 SixBits, 433 SevenBits, 434 EightBits, 435 } 436 } 437 } 438 439