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 9 using System; 10 using Antmicro.Renode.Core; 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 STM32W_UART : IDoubleWordPeripheral, IUART 18 { STM32W_UART()19 public STM32W_UART() 20 { 21 IRQ = new GPIO(); 22 charFifo = new Queue<byte>(); 23 } 24 25 [field: Transient] 26 public event Action<byte> CharReceived; 27 28 public GPIO IRQ { get; private set; } 29 WriteChar(byte value)30 public void WriteChar(byte value) 31 { 32 lock(charFifo) 33 { 34 charFifo.Enqueue(value); 35 Update(); 36 } 37 } 38 39 [ConnectionRegion("irq")] WriteDoubleWordIRQ(long address, uint value)40 public void WriteDoubleWordIRQ(long address, uint value) 41 { 42 43 } 44 WriteDoubleWord(long address, uint value)45 public void WriteDoubleWord(long address, uint value) 46 { 47 if(address == 0x3C) 48 { 49 var handler = CharReceived; 50 if(handler != null) 51 { 52 handler((byte)(value & 0xFF)); 53 } 54 return; 55 // data register 56 } 57 58 switch((Register)address) 59 { 60 case Register.Control: 61 controlRegister = value; 62 break; 63 case Register.BaudRate1: 64 baudRate1 = value; 65 break; 66 case Register.BaudRate2: 67 baudRate2 = value; 68 break; 69 } 70 } 71 72 [ConnectionRegion("irq")] ReadDoubleWordIRQ(long offset)73 public uint ReadDoubleWordIRQ(long offset) 74 { 75 if(offset == 0) 76 { 77 uint res = (1 << 1); 78 if(charFifo.Count > 0) 79 res |= 1; 80 return res; 81 } 82 return 0; 83 } 84 ReadDoubleWord(long offset)85 public uint ReadDoubleWord(long offset) 86 { 87 switch(offset) 88 { 89 case 0x3c: 90 var returnValue = charFifo.Dequeue(); 91 Update(); 92 if(returnValue == 0x0D) 93 return 0x0A; 94 return returnValue; 95 default: 96 return 0; 97 } 98 } 99 Reset()100 public void Reset() 101 { 102 // TODO! 103 } 104 Update()105 private void Update() 106 { 107 IRQ.Set(/*txInterruptEnabled ||*/ charFifo.Count > 0); 108 } 109 110 private uint controlRegister; 111 private uint baudRate1; 112 private uint baudRate2; 113 private readonly Queue<byte> charFifo; 114 115 [Flags] 116 private enum Control : uint 117 { 118 Stop = 1 << 2, 119 ParityEnabled = 1 << 3, 120 ParitySelection = 1 << 4 121 } 122 123 private enum Register : long 124 { 125 // TODO: I don't know if the offset should be 0xC85C or Ox5C - check it! 126 Control = 0xC85C, // SC1_UARTCR 127 BaudRate1 = 0xC868, // SC1_UARTBRR1 128 BaudRate2 = 0xC86C // SC1_UARTBRR2 129 } 130 131 public Bits StopBits 132 { 133 get 134 { 135 return (controlRegister & (uint)Control.Stop) == 0 ? Bits.One : Bits.Two; 136 } 137 } 138 139 public Parity ParityBit 140 { 141 get 142 { 143 if ((controlRegister & (uint)Control.ParityEnabled) == 0) 144 { 145 return Parity.None; 146 } 147 else 148 { 149 return (controlRegister & (uint)Control.ParitySelection) == 0 ? Parity.Even : Parity.Odd; 150 } 151 } 152 } 153 154 public uint BaudRate 155 { 156 get 157 { 158 var divisor = ((2 * (baudRate1 & 0xFFFF) + (baudRate2 & 0x1))); 159 return divisor == 0 ? 0 : UARTClockFrequency / divisor; 160 } 161 } 162 163 private const uint UARTClockFrequency = 24000000; // 24Mhz 164 } 165 } 166 167