1 //
2 // Copyright (c) 2010-2022 Antmicro
3 //
4 //  This file is licensed under the MIT License.
5 //  Full license text is available in 'licenses/MIT.txt'.
6 //
7 
8 using System;
9 using Antmicro.Renode.Core;
10 using Antmicro.Renode.Core.Structure.Registers;
11 using Antmicro.Renode.Logging;
12 using Antmicro.Renode.Utilities;
13 
14 namespace Antmicro.Renode.Peripherals.Miscellaneous
15 {
16     public class NRF52840_EGU : BasicDoubleWordPeripheral, IKnownSize, INRFEventProvider
17     {
NRF52840_EGU(IMachine machine)18         public NRF52840_EGU(IMachine machine) : base(machine)
19         {
20             interruptManager = new InterruptManager<Events>(this, IRQ, "EGU_IRQ");
21 
22             DefineRegisters();
23             Reset();
24         }
25 
Reset()26         public override void Reset()
27         {
28             interruptManager.Reset();
29             base.Reset();
30         }
31 
DefineRegisters()32         private void DefineRegisters()
33         {
34             Registers.TasksTrigger0.DefineMany(this, NumberOfTasks, (reg, i) =>
35             {
36                 reg.WithFlag(0, FieldMode.Write, writeCallback: (_, value) =>
37                 {
38                     if(value)
39                     {
40                         interruptManager.SetInterrupt((Events)i);
41                         events[i].Value = true;
42 
43                         this.NoisyLog("Triggering event {0}.", i);
44 
45                         // Triggering a task results in raising an interrupt and generating an event
46                         EventTriggered?.Invoke((uint)Registers.EventsTriggered0 + (uint)i * EventsTriggerRegisterSize);
47                     }
48                 })
49                 .WithReservedBits(1, 31);
50             }, TasksTriggerRegisterSize, name: "TasksTrigger");
51 
52             // These registers are used to check if an event has been generated for a particular task (if a task has been triggered)
53             // and to reset event state on write
54             Registers.EventsTriggered0.DefineMany(this, NumberOfTasks, (reg, i) =>
55             {
56                 reg.WithFlag(0, flagField: out events[i], writeCallback: (_, value) =>
57                 {
58                     if(!value)
59                     {
60                         interruptManager.SetInterrupt((Events)i, false);
61                     }
62                     this.NoisyLog("Change event {0} to state {1}.", i, value);
63                 })
64                 .WithReservedBits(1, 31);
65             }, EventsTriggerRegisterSize, name: "EventsTriggered");
66 
67             RegistersCollection.AddRegister((long)Registers.InterruptEnableDisable, interruptManager.GetInterruptEnableRegister<DoubleWordRegister>());
68             RegistersCollection.AddRegister((long)Registers.InterruptSet, interruptManager.GetInterruptEnableSetRegister<DoubleWordRegister>());
69             RegistersCollection.AddRegister((long)Registers.InterruptClear, interruptManager.GetInterruptEnableClearRegister<DoubleWordRegister>());
70         }
71 
72         public long Size => 0x1000;
73 
74         public event Action<uint> EventTriggered;
75         public GPIO IRQ { get; } = new GPIO();
76         private readonly InterruptManager<Events> interruptManager;
77 
78         private const uint NumberOfTasks = 16;
79         private const uint TasksTriggerRegisterSize = 0x4;
80         private const uint EventsTriggerRegisterSize = 0x4;
81 
82         private readonly IFlagRegisterField[] events = new IFlagRegisterField[NumberOfTasks];
83 
84         private enum Events
85         {
86             Triggered0 = 0,
87             Triggered1,
88             Triggered2,
89             Triggered3,
90             Triggered4,
91             Triggered5,
92             Triggered6,
93             Triggered7,
94             Triggered8,
95             Triggered9,
96             Triggered10,
97             Triggered11,
98             Triggered12,
99             Triggered13,
100             Triggered14,
101             Triggered15,
102         }
103 
104         private enum Registers
105         {
106             TasksTrigger0 = 0x0,
107             EventsTriggered0 = 0x100,
108             InterruptEnableDisable = 0x300,
109             InterruptSet = 0x304,
110             InterruptClear = 0x308
111         }
112     }
113 }
114