1 // 2 // Copyright (c) 2010-2018 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using System; 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.Logging; 11 using Antmicro.Renode.Peripherals.Bus; 12 using System.Collections.Generic; 13 using Antmicro.Migrant; 14 15 namespace Antmicro.Renode.Peripherals.UART 16 { 17 public class ImxUart : IBytePeripheral, IUART, IKnownSize 18 { ImxUart()19 public ImxUart() 20 { 21 IRQ = new GPIO(); 22 charFifo = new Queue<byte>(); 23 } 24 25 public long Size 26 { 27 get 28 { 29 return 0x1000; 30 } 31 } 32 33 public GPIO IRQ { get; private set; } 34 35 [field: Transient] 36 public event Action<byte> CharReceived; 37 WriteChar(byte value)38 public void WriteChar(byte value) 39 { 40 lock(charFifo) 41 { 42 charFifo.Enqueue(value); 43 UpdateIRQ(); 44 } 45 } 46 ReadByte(long address)47 public byte ReadByte(long address) 48 { 49 switch((Register)address) 50 { 51 case Register.FifoParameters: 52 return fifoParametersRegister; 53 case Register.FifoWatermark: 54 return fifoWatermarkRegister; 55 case Register.Modem: 56 return modemRegister; 57 case Register.BaudRateH: 58 return baudRateH; 59 case Register.Control1: 60 return control1Register; 61 case Register.BaudRateL: 62 return baudRateL; 63 case Register.Control4: 64 return control4Register; 65 case Register.Status1: 66 return status1Register; 67 case Register.FifoStatus: 68 return (byte) ((charFifo.Count > 0) ? (1<<7) : ((1<<7) | (1<<6))); 69 case Register.Control2: 70 return control2Register; 71 case Register.Control3: 72 return 0; 73 case Register.Data: 74 lock(charFifo) 75 { 76 byte returnValue = (byte)0; 77 if(charFifo.Count > 0) 78 { 79 returnValue = charFifo.Dequeue(); 80 } 81 UpdateIRQ(); 82 return returnValue; 83 } 84 case Register.Control5: 85 return control5Register; 86 default: 87 this.LogUnhandledRead(address); 88 return 0; 89 } 90 } 91 WriteByte(long address, byte value)92 public void WriteByte(long address, byte value) 93 { 94 switch((Register)address) 95 { 96 case Register.FifoParameters: 97 fifoParametersRegister = value; 98 break; 99 case Register.FifoWatermark: 100 fifoWatermarkRegister = value; 101 break; 102 case Register.Modem: 103 modemRegister = value; 104 break; 105 case Register.Control1: 106 control1Register = value; 107 break; 108 case Register.Control2: 109 control2Register = value; 110 //bool rx_enabled = ((value & (1u << 2)) != 0); 111 //bool tx_enabled = ((value & (1u << 3)) != 0); 112 enableIRQ = /*(rx_enabled || tx_enabled) &&*/ (((value & (1u << 7)) != 0) || ((value & (1u << 5)) != 0)); // TX_IRQ_DMA | RX_IRQ_DMA 113 UpdateIRQ(); 114 break; 115 case Register.Control4: 116 control4Register = value; 117 break; 118 case Register.Control5: 119 control5Register = value; 120 break; 121 case Register.Data: 122 var handler = CharReceived; 123 if(handler != null) 124 { 125 handler(value); 126 } 127 break; 128 case Register.BaudRateH: 129 baudRateHBuffer = value; 130 break; 131 case Register.BaudRateL: 132 baudRateH = baudRateHBuffer; 133 baudRateL = value; 134 break; 135 case Register.InterruptEnable: 136 break; 137 default: 138 this.LogUnhandledWrite(address, value); 139 break; 140 } 141 UpdateIRQ(); 142 } 143 UpdateIRQ()144 private void UpdateIRQ() 145 { 146 TDRE = true; 147 TC = true; 148 RDRF = charFifo.Count > 0; 149 IDLE = !RDRF; 150 151 var irqState = ((TDRE && TIE && !TDMAS) || 152 (TC && TCIE) || 153 (IDLE && ILIE) || 154 (RDRF && RIE && !RDMAS)); 155 IRQ.Set(enableIRQ && irqState); 156 } 157 Reset()158 public void Reset() 159 { 160 // TODO! 161 } 162 163 private bool enableIRQ; 164 165 private byte status1Register = (byte)((1u << 7) | (1u << 6)); 166 167 private byte control1Register; 168 private byte control2Register; 169 private byte control4Register; 170 private byte control5Register; 171 172 private byte fifoWatermarkRegister; 173 private byte fifoParametersRegister; 174 175 private readonly Queue<byte> charFifo; 176 177 private byte baudRateHBuffer; 178 private byte baudRateH; 179 private byte baudRateL; 180 private byte modemRegister; 181 182 [Flags] 183 private enum Control1 : byte 184 { 185 ParityEnable = 1 << 1, 186 ParityType = 1 187 } 188 189 private enum Register : long 190 { 191 BaudRateH = 0x00, 192 BaudRateL = 0x01, 193 Control1 = 0x02, 194 Control2 = 0x03, 195 Status1 = 0x04, 196 Control3 = 0x06, 197 Data = 0x07, 198 Control4 = 0x0A, 199 Control5 = 0x0B, 200 Modem = 0x0D, 201 FifoParameters = 0x10, 202 FifoStatus = 0x12, 203 FifoWatermark = 0x13, 204 InterruptEnable = 0x19 205 } 206 #region Bits 207 208 private bool TDMAS { get { return (control5Register & (1u << 7)) != 0; } } 209 private bool RDMAS { get { return (control5Register & (1u << 5)) != 0; } } 210 private bool TIE { get { return (control2Register & (1u << 7)) != 0; } } 211 private bool RIE { get { return (control2Register & (1u << 5)) != 0; } } 212 private bool TCIE { get { return (control2Register & (1u << 6)) != 0; } } 213 private bool ILIE { get { return (control2Register & (1u << 4)) != 0; } } 214 215 private bool TDRE 216 { 217 get { return (status1Register & (1u << 7)) != 0; } 218 set 219 { 220 if (value) 221 { 222 status1Register |= (byte)(1u << 7); 223 } 224 } 225 } 226 private bool TC 227 { 228 get { return (status1Register & (1u << 6)) != 0; } 229 set 230 { 231 if (value) 232 { 233 status1Register |= (byte)(1u << 6); 234 } 235 } 236 } 237 private bool IDLE 238 { 239 get { return (status1Register & (1u << 4)) != 0; } 240 set 241 { 242 if (value) 243 { 244 status1Register |= (byte)(1u << 4); 245 } 246 else 247 { 248 status1Register &= (byte.MaxValue - (byte)(1u << 4)); 249 } 250 } 251 } 252 private bool RDRF 253 { 254 get { return (status1Register & (1u << 5)) != 0; } 255 set 256 { 257 if (value) 258 { 259 status1Register |= (byte)(1u << 5); 260 } 261 else 262 { 263 status1Register &= (byte.MaxValue - (byte)(1u << 5)); 264 } 265 } 266 } 267 268 #endregion 269 270 public Bits StopBits 271 { 272 get 273 { 274 return Bits.One; 275 } 276 } 277 public Parity ParityBit 278 { 279 get 280 { 281 if ((control1Register & (byte)Control1.ParityEnable) == 0) 282 { 283 return Parity.None; 284 } 285 else 286 { 287 return ((control1Register & (byte)Control1.ParityType) == 0) ? Parity.Even : Parity.Odd; 288 } 289 } 290 } 291 292 public uint BaudRate 293 { 294 get 295 { 296 var divisor = (16 * (((baudRateH & 0x1F) << 8) + baudRateL) + ((control4Register & 0x1F) / 32)); 297 return divisor == 0 ? 0 : (uint)(SystemClockFrequency / divisor); 298 } 299 } 300 301 private uint SystemClockFrequency = 0; 302 } 303 } 304 305