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