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 using Antmicro.Renode.Core.Structure; 15 using Antmicro.Renode.Peripherals.SENT; 16 using Antmicro.Renode.Core; 17 using Antmicro.Renode.Peripherals.Timers; 18 using Antmicro.Renode.Peripherals.Bus; 19 20 namespace Antmicro.Renode.Peripherals.Miscellaneous 21 { 22 public class S32K3XX_FlexIO_SENT : NullRegistrationPointPeripheralContainer<ISENTPeripheral>, IEndpoint 23 { S32K3XX_FlexIO_SENT(IMachine machine, uint timerId, long? frequency = null)24 public S32K3XX_FlexIO_SENT(IMachine machine, uint timerId, long? frequency = null) 25 : base(machine) 26 { 27 this.timerId = timerId; 28 this.frequency = frequency; 29 } 30 RegisterInFlexIO(S32K3XX_FlexIO flexIO)31 public void RegisterInFlexIO(S32K3XX_FlexIO flexIO) 32 { 33 this.flexIO = flexIO; 34 if(!flexIO.TimersManager.Reserve(this, timerId, out timer)) 35 { 36 throw new ConstructionException($"Timer with id: {timerId} could not be reserved"); 37 } 38 39 sysbus = flexIO.GetMachine().GetSystemBus(flexIO); 40 innerTimer = new LimitTimer(Machine.ClockSource, frequency ?? flexIO.Frequency, this, $"SENT Timer{timerId}", TimerLimit, divider: (int)timer.Divider); 41 timer.ConfigurationChanged += ConfigureTimer; 42 timer.ControlChanged += ConfigureTimer; 43 } 44 Reset()45 public override void Reset() 46 { 47 if(RegisteredPeripheral != null) 48 { 49 RegisteredPeripheral.TransmissionEnabled = false; 50 } 51 innerTimer?.Reset(); 52 } 53 Register(ISENTPeripheral peripheral, NullRegistrationPoint registrationPoint)54 public override void Register(ISENTPeripheral peripheral, NullRegistrationPoint registrationPoint) 55 { 56 base.Register(peripheral, registrationPoint); 57 peripheral.SENTEdgeChanged += EdgeHandler; 58 } 59 Unregister(ISENTPeripheral peripheral)60 public override void Unregister(ISENTPeripheral peripheral) 61 { 62 base.Unregister(peripheral); 63 peripheral.SENTEdgeChanged -= EdgeHandler; 64 } 65 EdgeHandler(SENTEdge edge)66 private void EdgeHandler(SENTEdge edge) 67 { 68 if(edge != SENTEdge.Falling) 69 { 70 return; 71 } 72 73 if(sysbus.TryGetCurrentCPU(out var cpu)) 74 { 75 cpu.SyncTime(); 76 } 77 78 var timerValue = (uint)(TimerLimit - innerTimer.Value); 79 timer.Compare = timerValue; 80 timer.Status.SetFlag(true); 81 innerTimer.ResetValue(); 82 } 83 ConfigureTimer()84 private void ConfigureTimer() 85 { 86 var enableSENT = 87 timer.TriggerSource == TimerTriggerSource.Internal && 88 timer.Disable == TimerDisable.OnTriggerFallingEdge && 89 timer.Mode == TimerMode.SingleInputCapture; 90 91 innerTimer.Divider = (int)timer.Divider; 92 innerTimer.Frequency = frequency ?? flexIO.Frequency; 93 innerTimer.Enabled = enableSENT; 94 95 if(RegisteredPeripheral != null) 96 { 97 RegisteredPeripheral.TransmissionEnabled = enableSENT; 98 } 99 100 this.DebugLog("SENT transmission {0}", enableSENT ? "enabled" : "disabled"); 101 } 102 103 private S32K3XX_FlexIO flexIO; 104 private Timer timer; 105 private LimitTimer innerTimer; 106 private IBusController sysbus; 107 108 private readonly uint timerId; 109 private readonly long? frequency; 110 111 private const ulong TimerLimit = (1 << 16) - 1; 112 } 113 } 114