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; 8 using Antmicro.Renode.Logging; 9 using Antmicro.Renode.Peripherals.Bus; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Core.Structure.Registers; 12 13 namespace Antmicro.Renode.Peripherals.UART 14 { 15 [AllowedTranslations(AllowedTranslation.DoubleWordToByte | AllowedTranslation.WordToByte)] 16 public class SAMD5_UART : UARTBase, IBytePeripheral, IKnownSize, IProvidesRegisterCollection<ByteRegisterCollection> 17 { SAMD5_UART(IMachine machine)18 public SAMD5_UART(IMachine machine) : base(machine) 19 { 20 RegistersCollection = new ByteRegisterCollection(this); 21 IRQ = new GPIO(); 22 DefineRegisters(); 23 Reset(); 24 } 25 ReadByte(long offset)26 public byte ReadByte(long offset) 27 { 28 return RegistersCollection.Read(offset); 29 } 30 WriteByte(long offset, byte value)31 public void WriteByte(long offset, byte value) 32 { 33 RegistersCollection.Write(offset, value); 34 } 35 Reset()36 public override void Reset() 37 { 38 base.Reset(); 39 RegistersCollection.Reset(); 40 } 41 42 public GPIO IRQ { get; } 43 44 public ByteRegisterCollection RegistersCollection { get; } 45 46 public long Size => 0x100; 47 48 public override Bits StopBits => Bits.None; 49 50 public override Parity ParityBit => Parity.None; 51 52 public override uint BaudRate => 0; 53 CharWritten()54 protected override void CharWritten() 55 { 56 receiveStart.Value = true; 57 receiveComplete.Value = true; 58 UpdateInterrupt(); 59 } 60 QueueEmptied()61 protected override void QueueEmptied() 62 { 63 receiveStart.Value = false; 64 receiveComplete.Value = false; 65 UpdateInterrupt(); 66 } 67 DefineRegisters()68 private void DefineRegisters() 69 { 70 Registers.DataRegister0.Define(this) 71 .WithValueField(0, 8, name: "DATA", 72 valueProviderCallback: _ => 73 { 74 if(TryGetCharacter(out var b)) 75 { 76 return b; 77 } 78 79 this.Log(LogLevel.Warning, "Tried to read DATA, but there is nothing in the queue"); 80 return 0; 81 }, 82 writeCallback: (_, val) => 83 { 84 TransmitCharacter((byte)val); 85 transmitComplete.Value = true; 86 UpdateInterrupt(); 87 }) 88 ; 89 90 Registers.InterruptFlag.Define(this) 91 .WithFlag(0, FieldMode.Read, name: "DRE - Data Register Empty", valueProviderCallback: _ => Count == 0) 92 .WithFlag(1, out transmitComplete, FieldMode.Read | FieldMode.WriteOneToClear, name: "TXC - Transmit Complete") 93 .WithFlag(2, out receiveComplete, FieldMode.Read, name: "RXC - Receive Complete") 94 .WithFlag(3, out receiveStart, FieldMode.Read | FieldMode.WriteOneToClear, name: "RXS - Receive Start") 95 .WithTaggedFlag("CTSIC - Clear To Send Input Change", 4) 96 .WithTaggedFlag("RXBRK - Receive Break", 5) 97 .WithReservedBits(6, 1) 98 .WithTaggedFlag("ERROR", 7) 99 .WithWriteCallback((_, __) => UpdateInterrupt()) 100 ; 101 102 Registers.InterruptEnableClear.Define(this) 103 .WithFlag(0, out dataRegisterEmptyInterruptEnable, FieldMode.Read | FieldMode.WriteOneToClear, name: "DRE - Data Register Empty Interrupt Enable") 104 .WithFlag(1, out transmitCompleteInterruptEnable, FieldMode.Read | FieldMode.WriteOneToClear, name: "TXC - Transmit Complete Interrupt Enable") 105 .WithFlag(2, out receiveCompleteInterruptEnable, FieldMode.Read | FieldMode.WriteOneToClear, name: "RXC - Receive Complete Interrupt Enable") 106 .WithFlag(3, out receiveStartInterruptEnable, FieldMode.Read | FieldMode.WriteOneToClear, name: "RXS - Receive Start Interrupt Enable") 107 .WithTaggedFlag("CTSIC - Clear To Send Input Change Interrupt Enable", 4) 108 .WithTaggedFlag("RXBRK - Receive Break Interrupt Enable", 5) 109 .WithReservedBits(6, 1) 110 .WithTaggedFlag("ERROR Interrupt Enable", 7) 111 .WithWriteCallback((_, __) => UpdateInterrupt()) 112 ; 113 114 Registers.InterruptEnableSet.Define(this) 115 .WithFlag(0, name: "DRE - Data Register Empty Interrupt Enable", valueProviderCallback: _ => dataRegisterEmptyInterruptEnable.Value, writeCallback: (_, val) => { dataRegisterEmptyInterruptEnable.Value |= val; }) 116 .WithFlag(1, name: "TXC - Transmit Complete Interrupt Enable", valueProviderCallback: _ => transmitCompleteInterruptEnable.Value, writeCallback: (_, val) => { transmitCompleteInterruptEnable.Value |= val; }) 117 .WithFlag(2, name: "RXC - Receive Complete Interrupt Enable", valueProviderCallback: _ => receiveCompleteInterruptEnable.Value, writeCallback: (_, val) => { receiveCompleteInterruptEnable.Value |= val; }) 118 .WithFlag(3, name: "RXS - Receive Start Interrupt Enable", valueProviderCallback: _ => receiveStartInterruptEnable.Value, writeCallback: (_, val) => { receiveStartInterruptEnable.Value |= val; }) 119 .WithTaggedFlag("CTSIC - Clear To Send Input Change Interrupt Enable", 4) 120 .WithTaggedFlag("RXBRK - Receive Break Interrupt Enable", 5) 121 .WithReservedBits(6, 1) 122 .WithTaggedFlag("ERROR Interrupt Enable", 7) 123 .WithWriteCallback((_, __) => UpdateInterrupt()) 124 ; 125 } 126 UpdateInterrupt()127 private void UpdateInterrupt() 128 { 129 var flag = (dataRegisterEmptyInterruptEnable.Value && Count == 0) 130 || (transmitCompleteInterruptEnable.Value && transmitComplete.Value) 131 || (receiveCompleteInterruptEnable.Value && receiveComplete.Value) 132 || (receiveStartInterruptEnable.Value && receiveStart.Value); 133 134 this.Log(LogLevel.Debug, "IRQ set to: {0}", flag); 135 IRQ.Set(flag); 136 } 137 138 private IFlagRegisterField transmitComplete; 139 private IFlagRegisterField receiveComplete; 140 private IFlagRegisterField receiveStart; 141 142 private IFlagRegisterField dataRegisterEmptyInterruptEnable; 143 private IFlagRegisterField transmitCompleteInterruptEnable; 144 private IFlagRegisterField receiveCompleteInterruptEnable; 145 private IFlagRegisterField receiveStartInterruptEnable; 146 147 private enum Registers : long 148 { 149 ControlA0 = 0x0, 150 ControlA1 = 0x1, 151 ControlA2 = 0x2, 152 ControlA3 = 0x3, 153 ControlB0 = 0x4, 154 ControlB1 = 0x5, 155 ControlB2 = 0x6, 156 ControlB3 = 0x7, 157 ControlC0 = 0x8, 158 ControlC1 = 0x9, 159 ControlC2 = 0xA, 160 ControlC3 = 0xB, 161 Baud0 = 0xC, 162 Baud1 = 0xD, 163 ReceivePulseLength = 0xE, 164 InterruptEnableClear = 0x14, 165 InterruptEnableSet = 0x16, 166 InterruptFlag = 0x18, 167 Status0 = 0x1A, 168 Status1 = 0x1B, 169 SynchronizationBusy0 = 0x1C, 170 SynchronizationBusy1 = 0x1D, 171 SynchronizationBusy2 = 0x1E, 172 SynchronizationBusy3 = 0x1F, 173 ReceiveErrorCount = 0x20, 174 Length0 = 0x22, 175 Length1 = 0x23, 176 DataRegister0 = 0x28, 177 DataRegister1 = 0x29, 178 DataRegister2 = 0x2A, 179 DataRegister3 = 0x2B, 180 DebugControl = 0x30 181 } 182 } 183 } 184 185