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