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 System; 8 using System.Collections.Generic; 9 using Antmicro.Migrant; 10 using Antmicro.Renode.Exceptions; 11 using Antmicro.Renode.Logging; 12 using Antmicro.Renode.Peripherals.UART; 13 using Antmicro.Renode.Peripherals.Miscellaneous.S32K3XX_FlexIOModel; 14 15 namespace Antmicro.Renode.Peripherals.Miscellaneous 16 { 17 public class S32K3XX_FlexIO_UART : IUART, IEndpoint 18 { S32K3XX_FlexIO_UART(uint? rxShifterId = null, uint? txShifterId = null)19 public S32K3XX_FlexIO_UART(uint? rxShifterId = null, uint? txShifterId = null) 20 { 21 this.rxShifterId = rxShifterId; 22 this.txShifterId = txShifterId; 23 } 24 RegisterInFlexIO(S32K3XX_FlexIO flexIO)25 public void RegisterInFlexIO(S32K3XX_FlexIO flexIO) 26 { 27 this.flexIO = flexIO; 28 if(!rxShifterId.HasValue && !txShifterId.HasValue) 29 { 30 this.Log(LogLevel.Warning, "The endpoint doesn't have set any shifter identifier"); 31 return; 32 } 33 34 var errors = new List<string>(); 35 36 if(TryReserveShifter(flexIO, rxShifterId, out var shifter, errors, nameof(rxShifterId))) 37 { 38 receiver = new UARTReceiver(this, shifter); 39 } 40 41 if(TryReserveShifter(flexIO, txShifterId, out shifter, errors, nameof(txShifterId))) 42 { 43 transmitter = new UARTTransmitter(this, shifter); 44 transmitter.CharReceived += val => CharReceived?.Invoke(val); 45 } 46 47 if(errors.Count > 0) 48 { 49 throw new ConstructionException(String.Join(" ", errors)); 50 } 51 } 52 Reset()53 public void Reset() 54 { 55 receiver?.Reset(); 56 transmitter?.Reset(); 57 } 58 WriteChar(byte value)59 public void WriteChar(byte value) 60 { 61 if(receiver == null) 62 { 63 this.Log(LogLevel.Warning, "The UART doesn't support receiving, no shifter set"); 64 return; 65 } 66 receiver.WriteChar(value); 67 } 68 69 [field: Transient] 70 public event Action<byte> CharReceived; 71 72 public uint BaudRate => LogWarningWhenDirectionsDiffer(GetBaudRate(receiver), GetBaudRate(transmitter), "BaudRate") ?? 0; 73 public Bits StopBits => LogWarningWhenDirectionsDiffer(receiver?.StopBits, transmitter?.StopBits, "StopBits") ?? Bits.None; 74 public Parity ParityBit => Parity.None; 75 TryReserveShifter(S32K3XX_FlexIO flexIO, uint? id, out Shifter shifter, IList<string> errors, string parameterName)76 private bool TryReserveShifter(S32K3XX_FlexIO flexIO, uint? id, out Shifter shifter, IList<string> errors, string parameterName) 77 { 78 if(!id.HasValue) 79 { 80 shifter = null; 81 return false; 82 } 83 84 if(!flexIO.ShiftersManager.Reserve(this, id.Value, out shifter)) 85 { 86 errors.Add($"Invalid {parameterName}, unable to reserve shifter with the {id.Value} identifier."); 87 return false; 88 } 89 90 return true; 91 } 92 GetBaudRate(UARTDirectionBase uart)93 private uint? GetBaudRate(UARTDirectionBase uart) 94 { 95 if(uart == null) 96 { 97 return null; 98 } 99 return flexIO.Frequency / uart.BaudRateDivider; 100 } 101 LogWarningWhenDirectionsDiffer(T receiverProperty, T transmitterProperty, string propertyName)102 private T LogWarningWhenDirectionsDiffer<T>(T receiverProperty, T transmitterProperty, string propertyName) 103 { 104 if(receiverProperty != null && transmitterProperty != null && !receiverProperty.Equals(transmitterProperty)) 105 { 106 this.Log(LogLevel.Warning, "The {0} property is different for the receiver ({1}) and transmitter ({2}) sides", propertyName, receiverProperty, transmitterProperty); 107 } 108 return receiverProperty != null ? receiverProperty : transmitterProperty; 109 } 110 111 private S32K3XX_FlexIO flexIO; 112 private UARTReceiver receiver; 113 private UARTTransmitter transmitter; 114 115 private readonly uint? rxShifterId; 116 private readonly uint? txShifterId; 117 } 118 } 119