1 /*
2  * Copyright (c) 2017 Oticon A/S
3  * Copyright (c) 2023 Nordic Semiconductor ASA
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 /*
9  * PPI - Programmable peripheral interconnect
10  * https://infocenter.nordicsemi.com/topic/ps_nrf52833/ppi.html?cp=5_1_0_5_14
11  *
12  * Notes:
13  *   * Many tasks and events are not yet plugged. If you try to use those you will get a warning.
14  *
15  *   * In the real PPI, if two separate events which trigger the same task come close enough to each other
16  *     (they are registered by the same 16MHz clock edge), that common task will only be triggered once.
17  *     In this model, such events would cause such a tasks to trigger twice.
18  */
19 
20 #include <stdbool.h>
21 #include <stdint.h>
22 #include <string.h>
23 #include "NHW_peri_types.h"
24 #include "NHW_AAR.h"
25 #include "NHW_AES_CCM.h"
26 #include "NRF_GPIOTE.h"
27 #include "NHW_RNG.h"
28 #include "NRF_PPI.h"
29 #include "NHW_RTC.h"
30 #include "NHW_TIMER.h"
31 #include "NHW_CLOCK.h"
32 #include "NHW_RADIO.h"
33 #include "NHW_EGU.h"
34 #include "NHW_UART.h"
35 #include "bs_tracing.h"
36 #include "bs_oswrap.h"
37 #include "nsi_tasks.h"
38 
39 NRF_PPI_Type NRF_PPI_regs; ///< The PPI registers
40 
41 /**
42  * PPI module own TASKs handlers
43  */
nrf_ppi_TASK_CHG_ENDIS(int groupnbr,bool enable)44 void nrf_ppi_TASK_CHG_ENDIS( int groupnbr, bool enable /*false=disable task*/ ){
45   if ( enable ){
46     bs_trace_raw_time(9, "ppi: Channel group %i enabled\n", groupnbr);
47     NRF_PPI_regs.CHEN |= NRF_PPI_regs.CHG[groupnbr];
48   } else {
49     bs_trace_raw_time(9 ,"ppi: Channel group %i disable\n", groupnbr);
50     NRF_PPI_regs.CHEN &= ~NRF_PPI_regs.CHG[groupnbr];
51   }
52   //Note of the author: From the spec I cannot guess if these tasks will affect
53   //CHEN or a separate hidden register
54 }
nrf_ppi_TASK_CHG0_EN(void)55 void nrf_ppi_TASK_CHG0_EN(void) { nrf_ppi_TASK_CHG_ENDIS(0,true); }
nrf_ppi_TASK_CHG1_EN(void)56 void nrf_ppi_TASK_CHG1_EN(void) { nrf_ppi_TASK_CHG_ENDIS(1,true); }
nrf_ppi_TASK_CHG2_EN(void)57 void nrf_ppi_TASK_CHG2_EN(void) { nrf_ppi_TASK_CHG_ENDIS(2,true); }
nrf_ppi_TASK_CHG3_EN(void)58 void nrf_ppi_TASK_CHG3_EN(void) { nrf_ppi_TASK_CHG_ENDIS(3,true); }
nrf_ppi_TASK_CHG4_EN(void)59 void nrf_ppi_TASK_CHG4_EN(void) { nrf_ppi_TASK_CHG_ENDIS(4,true); }
nrf_ppi_TASK_CHG5_EN(void)60 void nrf_ppi_TASK_CHG5_EN(void) { nrf_ppi_TASK_CHG_ENDIS(5,true); }
nrf_ppi_TASK_CHG0_DIS(void)61 void nrf_ppi_TASK_CHG0_DIS(void) { nrf_ppi_TASK_CHG_ENDIS(0,false); }
nrf_ppi_TASK_CHG1_DIS(void)62 void nrf_ppi_TASK_CHG1_DIS(void) { nrf_ppi_TASK_CHG_ENDIS(1,false); }
nrf_ppi_TASK_CHG2_DIS(void)63 void nrf_ppi_TASK_CHG2_DIS(void) { nrf_ppi_TASK_CHG_ENDIS(2,false); }
nrf_ppi_TASK_CHG3_DIS(void)64 void nrf_ppi_TASK_CHG3_DIS(void) { nrf_ppi_TASK_CHG_ENDIS(3,false); }
nrf_ppi_TASK_CHG4_DIS(void)65 void nrf_ppi_TASK_CHG4_DIS(void) { nrf_ppi_TASK_CHG_ENDIS(4,false); }
nrf_ppi_TASK_CHG5_DIS(void)66 void nrf_ppi_TASK_CHG5_DIS(void) { nrf_ppi_TASK_CHG_ENDIS(5,false); }
67 
68 typedef void (*dest_f_t)(void); ///<Syntactic sugar for task function pointer
69 
70 typedef struct{
71   uint32_t channels_mask; //bitmask indicating which channel the event is mapped to
72 } ppi_event_to_ch_t;
73 ///Table contain which channels each event is activating (one entry per event)
74 static ppi_event_to_ch_t ppi_evt_to_ch[NUMBER_PPI_EVENTS];
75 
76 typedef struct {
77   dest_f_t tep_f;
78   dest_f_t fork_tep_f;
79 } ppi_channel_tasks_t;
80 ///Table with TASKs each channel activates
81 static ppi_channel_tasks_t ppi_ch_tasks[NUMBER_PPI_CHANNELS];
82 
83 typedef struct {
84   void *task_addr;
85   dest_f_t dest; //function to be called when task is triggered
86 } ppi_tasks_table_t;
87 
88 /**
89  * Table of TASKs addresses (as provided by the SW) vs the model function
90  * pointer (which handles the task trigger)
91  */
92 static const ppi_tasks_table_t ppi_tasks_table[]={ //just the ones we may use
93     //POWER CLOCK:
94     { (void*)&NRF_CLKPWR_regs[0].CLK.TASKS_LFCLKSTART , nhw_clock0_TASKS_LFCLKSTART},
95     { (void*)&NRF_CLKPWR_regs[0].CLK.TASKS_LFCLKSTOP  , nhw_clock0_TASKS_LFCLKSTOP},
96     { (void*)&NRF_CLKPWR_regs[0].CLK.TASKS_HFCLKSTART , nhw_clock0_TASKS_HFCLKSTART},
97     { (void*)&NRF_CLKPWR_regs[0].CLK.TASKS_HFCLKSTOP  , nhw_clock0_TASKS_HFCLKSTOP},
98     { (void*)&NRF_CLKPWR_regs[0].CLK.TASKS_CAL        , nhw_clock0_TASKS_CAL},
99     { (void*)&NRF_CLKPWR_regs[0].CLK.TASKS_CTSTART    , nhw_clock0_TASKS_CTSTART},
100     { (void*)&NRF_CLKPWR_regs[0].CLK.TASKS_CTSTOP     , nhw_clock0_TASKS_CTSTOP},
101 
102     //RADIO:
103     { (void*)&NRF_RADIO_regs.TASKS_TXEN,         nhw_RADIO_TASK_TXEN},
104     { (void*)&NRF_RADIO_regs.TASKS_RXEN,         nhw_RADIO_TASK_RXEN},
105     { (void*)&NRF_RADIO_regs.TASKS_START,        nhw_RADIO_TASK_START},
106     { (void*)&NRF_RADIO_regs.TASKS_STOP,         nhw_RADIO_TASK_STOP},
107     { (void*)&NRF_RADIO_regs.TASKS_DISABLE,      nhw_RADIO_TASK_DISABLE},
108     { (void*)&NRF_RADIO_regs.TASKS_RSSISTART,    nhw_RADIO_TASK_RSSISTART},
109     { (void*)&NRF_RADIO_regs.TASKS_RSSISTOP,     nhw_RADIO_TASK_RSSISTOP},
110     { (void*)&NRF_RADIO_regs.TASKS_BCSTART,      nhw_RADIO_TASK_BCSTART},
111     { (void*)&NRF_RADIO_regs.TASKS_BCSTOP,       nhw_RADIO_TASK_BCSTOP},
112     { (void*)&NRF_RADIO_regs.TASKS_EDSTART,      nhw_RADIO_TASK_EDSTART},
113     { (void*)&NRF_RADIO_regs.TASKS_EDSTOP,       nhw_RADIO_TASK_EDSTOP},
114     { (void*)&NRF_RADIO_regs.TASKS_CCASTART,     nhw_RADIO_TASK_CCASTART},
115     { (void*)&NRF_RADIO_regs.TASKS_CCASTOP,      nhw_RADIO_TASK_CCASTOP},
116 
117     //UART
118     { (void*)&NRF_UARTE_regs[0].TASKS_STARTRX,  nhw_uarte0_TASKS_STARTRX},
119     { (void*)&NRF_UARTE_regs[0].TASKS_STOPRX,   nhw_uarte0_TASKS_STOPRX},
120     { (void*)&NRF_UARTE_regs[0].TASKS_STARTTX,  nhw_uarte0_TASKS_STARTTX},
121     { (void*)&NRF_UARTE_regs[0].TASKS_STOPTX,   nhw_uarte0_TASKS_STOPTX},
122     { (void*)&((NRF_UART_Type *)&NRF_UARTE_regs[0])->TASKS_SUSPEND,   nhw_uarte0_TASKS_SUSPEND},
123     { (void*)&NRF_UARTE_regs[0].TASKS_FLUSHRX,  nhw_uarte0_TASKS_FLUSHRX},
124 
125     { (void*)&NRF_UARTE_regs[1].TASKS_STARTRX,  nhw_uarte1_TASKS_STARTRX},
126     { (void*)&NRF_UARTE_regs[1].TASKS_STOPRX,   nhw_uarte1_TASKS_STOPRX},
127     { (void*)&NRF_UARTE_regs[1].TASKS_STARTTX,  nhw_uarte1_TASKS_STARTTX},
128     { (void*)&NRF_UARTE_regs[1].TASKS_STOPTX,   nhw_uarte1_TASKS_STOPTX},
129     { (void*)&((NRF_UART_Type *)&NRF_UARTE_regs[1])->TASKS_SUSPEND,   nhw_uarte1_TASKS_SUSPEND},
130     { (void*)&NRF_UARTE_regs[1].TASKS_FLUSHRX,  nhw_uarte1_TASKS_FLUSHRX},
131 
132     //SPI0
133     //TWI0
134     //SPI1
135     //TWI1
136     //NFCT
137 
138     //GPIOTE
139     { (void*)&NRF_GPIOTE_regs.TASKS_OUT[0],  nrf_gpiote_TASKS_OUT_0},
140     { (void*)&NRF_GPIOTE_regs.TASKS_OUT[1],  nrf_gpiote_TASKS_OUT_1},
141     { (void*)&NRF_GPIOTE_regs.TASKS_OUT[2],  nrf_gpiote_TASKS_OUT_2},
142     { (void*)&NRF_GPIOTE_regs.TASKS_OUT[3],  nrf_gpiote_TASKS_OUT_3},
143     { (void*)&NRF_GPIOTE_regs.TASKS_OUT[4],  nrf_gpiote_TASKS_OUT_4},
144     { (void*)&NRF_GPIOTE_regs.TASKS_OUT[5],  nrf_gpiote_TASKS_OUT_5},
145     { (void*)&NRF_GPIOTE_regs.TASKS_OUT[6],  nrf_gpiote_TASKS_OUT_6},
146     { (void*)&NRF_GPIOTE_regs.TASKS_OUT[7],  nrf_gpiote_TASKS_OUT_7},
147     { (void*)&NRF_GPIOTE_regs.TASKS_SET[0],  nrf_gpiote_TASKS_SET_0},
148     { (void*)&NRF_GPIOTE_regs.TASKS_SET[1],  nrf_gpiote_TASKS_SET_1},
149     { (void*)&NRF_GPIOTE_regs.TASKS_SET[2],  nrf_gpiote_TASKS_SET_2},
150     { (void*)&NRF_GPIOTE_regs.TASKS_SET[3],  nrf_gpiote_TASKS_SET_3},
151     { (void*)&NRF_GPIOTE_regs.TASKS_SET[4],  nrf_gpiote_TASKS_SET_4},
152     { (void*)&NRF_GPIOTE_regs.TASKS_SET[5],  nrf_gpiote_TASKS_SET_5},
153     { (void*)&NRF_GPIOTE_regs.TASKS_SET[6],  nrf_gpiote_TASKS_SET_6},
154     { (void*)&NRF_GPIOTE_regs.TASKS_SET[7],  nrf_gpiote_TASKS_SET_7},
155     { (void*)&NRF_GPIOTE_regs.TASKS_CLR[0],  nrf_gpiote_TASKS_CLR_0},
156     { (void*)&NRF_GPIOTE_regs.TASKS_CLR[1],  nrf_gpiote_TASKS_CLR_1},
157     { (void*)&NRF_GPIOTE_regs.TASKS_CLR[2],  nrf_gpiote_TASKS_CLR_2},
158     { (void*)&NRF_GPIOTE_regs.TASKS_CLR[3],  nrf_gpiote_TASKS_CLR_3},
159     { (void*)&NRF_GPIOTE_regs.TASKS_CLR[4],  nrf_gpiote_TASKS_CLR_4},
160     { (void*)&NRF_GPIOTE_regs.TASKS_CLR[5],  nrf_gpiote_TASKS_CLR_5},
161     { (void*)&NRF_GPIOTE_regs.TASKS_CLR[6],  nrf_gpiote_TASKS_CLR_6},
162     { (void*)&NRF_GPIOTE_regs.TASKS_CLR[7],  nrf_gpiote_TASKS_CLR_7},
163 
164     //SAADC
165 
166     //TIMER0:
167     { (void*)&NRF_TIMER_regs[0].TASKS_CAPTURE[0],  nhw_timer0_TASK_CAPTURE_0},
168     { (void*)&NRF_TIMER_regs[0].TASKS_CAPTURE[1],  nhw_timer0_TASK_CAPTURE_1},
169     { (void*)&NRF_TIMER_regs[0].TASKS_CAPTURE[2],  nhw_timer0_TASK_CAPTURE_2},
170     { (void*)&NRF_TIMER_regs[0].TASKS_CAPTURE[3],  nhw_timer0_TASK_CAPTURE_3},
171 //    { (void*)&NRF_TIMER_regs[0].TASKS_CAPTURE[4],  nhw_timer0_TASK_CAPTURE_4},
172 //    { (void*)&NRF_TIMER_regs[0].TASKS_CAPTURE[5],  nhw_timer0_TASK_CAPTURE_5},
173     { (void*)&NRF_TIMER_regs[0].TASKS_CLEAR,       nhw_timer0_TASK_CLEAR},
174     { (void*)&NRF_TIMER_regs[0].TASKS_COUNT,       nhw_timer0_TASK_COUNT},
175     { (void*)&NRF_TIMER_regs[0].TASKS_START,       nhw_timer0_TASK_START},
176     { (void*)&NRF_TIMER_regs[0].TASKS_STOP,        nhw_timer0_TASK_STOP},
177     //TIMER1:
178     { (void*)&NRF_TIMER_regs[1].TASKS_CAPTURE[0],  nhw_timer1_TASK_CAPTURE_0},
179     { (void*)&NRF_TIMER_regs[1].TASKS_CAPTURE[1],  nhw_timer1_TASK_CAPTURE_1},
180     { (void*)&NRF_TIMER_regs[1].TASKS_CAPTURE[2],  nhw_timer1_TASK_CAPTURE_2},
181     { (void*)&NRF_TIMER_regs[1].TASKS_CAPTURE[3],  nhw_timer1_TASK_CAPTURE_3},
182 //    { (void*)&NRF_TIMER_regs[1].TASKS_CAPTURE[4],  nhw_timer1_TASK_CAPTURE_4},
183 //    { (void*)&NRF_TIMER_regs[1].TASKS_CAPTURE[5],  nhw_timer1_TASK_CAPTURE_5},
184     { (void*)&NRF_TIMER_regs[1].TASKS_CLEAR,       nhw_timer1_TASK_CLEAR},
185     { (void*)&NRF_TIMER_regs[1].TASKS_COUNT,       nhw_timer1_TASK_COUNT},
186     { (void*)&NRF_TIMER_regs[1].TASKS_START,       nhw_timer1_TASK_START},
187     { (void*)&NRF_TIMER_regs[1].TASKS_STOP,        nhw_timer1_TASK_STOP},
188     //TIMER2:
189     { (void*)&NRF_TIMER_regs[2].TASKS_CAPTURE[0],  nhw_timer2_TASK_CAPTURE_0},
190     { (void*)&NRF_TIMER_regs[2].TASKS_CAPTURE[1],  nhw_timer2_TASK_CAPTURE_1},
191     { (void*)&NRF_TIMER_regs[2].TASKS_CAPTURE[2],  nhw_timer2_TASK_CAPTURE_2},
192     { (void*)&NRF_TIMER_regs[2].TASKS_CAPTURE[3],  nhw_timer2_TASK_CAPTURE_3},
193 //    { (void*)&NRF_TIMER_regs[2].TASKS_CAPTURE[4],  nhw_timer2_TASK_CAPTURE_4},
194 //    { (void*)&NRF_TIMER_regs[2].TASKS_CAPTURE[5],  nhw_timer2_TASK_CAPTURE_5},
195     { (void*)&NRF_TIMER_regs[2].TASKS_CLEAR,       nhw_timer2_TASK_CLEAR},
196     { (void*)&NRF_TIMER_regs[2].TASKS_COUNT,       nhw_timer2_TASK_COUNT},
197     { (void*)&NRF_TIMER_regs[2].TASKS_START,       nhw_timer2_TASK_START},
198     { (void*)&NRF_TIMER_regs[2].TASKS_STOP,        nhw_timer2_TASK_STOP},
199     //TIMER3:
200     { (void*)&NRF_TIMER_regs[3].TASKS_CAPTURE[0],  nhw_timer3_TASK_CAPTURE_0},
201     { (void*)&NRF_TIMER_regs[3].TASKS_CAPTURE[1],  nhw_timer3_TASK_CAPTURE_1},
202     { (void*)&NRF_TIMER_regs[3].TASKS_CAPTURE[2],  nhw_timer3_TASK_CAPTURE_2},
203     { (void*)&NRF_TIMER_regs[3].TASKS_CAPTURE[3],  nhw_timer3_TASK_CAPTURE_3},
204     { (void*)&NRF_TIMER_regs[3].TASKS_CAPTURE[4],  nhw_timer3_TASK_CAPTURE_4},
205     { (void*)&NRF_TIMER_regs[3].TASKS_CAPTURE[5],  nhw_timer3_TASK_CAPTURE_5},
206     { (void*)&NRF_TIMER_regs[3].TASKS_CLEAR,       nhw_timer3_TASK_CLEAR},
207     { (void*)&NRF_TIMER_regs[3].TASKS_COUNT,       nhw_timer3_TASK_COUNT},
208     { (void*)&NRF_TIMER_regs[3].TASKS_START,       nhw_timer3_TASK_START},
209     { (void*)&NRF_TIMER_regs[3].TASKS_STOP,        nhw_timer3_TASK_STOP},
210     //TIMER4:
211     { (void*)&NRF_TIMER_regs[4].TASKS_CAPTURE[0],  nhw_timer4_TASK_CAPTURE_0},
212     { (void*)&NRF_TIMER_regs[4].TASKS_CAPTURE[1],  nhw_timer4_TASK_CAPTURE_1},
213     { (void*)&NRF_TIMER_regs[4].TASKS_CAPTURE[2],  nhw_timer4_TASK_CAPTURE_2},
214     { (void*)&NRF_TIMER_regs[4].TASKS_CAPTURE[3],  nhw_timer4_TASK_CAPTURE_3},
215     { (void*)&NRF_TIMER_regs[4].TASKS_CAPTURE[4],  nhw_timer4_TASK_CAPTURE_4},
216     { (void*)&NRF_TIMER_regs[4].TASKS_CAPTURE[5],  nhw_timer4_TASK_CAPTURE_5},
217     { (void*)&NRF_TIMER_regs[4].TASKS_CLEAR,       nhw_timer4_TASK_CLEAR},
218     { (void*)&NRF_TIMER_regs[4].TASKS_COUNT,       nhw_timer4_TASK_COUNT},
219     { (void*)&NRF_TIMER_regs[4].TASKS_START,       nhw_timer4_TASK_START},
220     { (void*)&NRF_TIMER_regs[4].TASKS_STOP,        nhw_timer4_TASK_STOP},
221 
222     //RTC:
223     //{ (void*)&(NRF_RTC_regs[0]).TASKS_CLEAR, nhw_rtc0_TASKS_CLEAR},
224     //{ (void*)&(NRF_RTC_regs[0]).TASKS_START, nhw_rtc0_TASKS_START},
225     //{ (void*)&(NRF_RTC_regs[0]).TASKS_STOP , nhw_rtc0_TASKS_STOP},
226     //{ (void*)&(NRF_RTC_regs[0]).TASKS_TRIGOVRFLW , nhw_rtc0_TASKS_TRIGOVRFLW},
227     //{ (void*)&(NRF_RTC_regs[1]).TASKS_CLEAR, nhw_rtc1_TASKS_CLEAR},
228     //{ (void*)&(NRF_RTC_regs[1]).TASKS_START, nhw_rtc1_TASKS_START},
229     //{ (void*)&(NRF_RTC_regs[1]).TASKS_STOP , nhw_rtc1_TASKS_STOP},
230     //{ (void*)&(NRF_RTC_regs[1]).TASKS_TRIGOVRFLW , nhw_rtc1_TASKS_TRIGOVRFLW},
231     //{ (void*)&(NRF_RTC_regs[2]).TASKS_CLEAR, nhw_rtc2_TASKS_CLEAR},
232     //{ (void*)&(NRF_RTC_regs[2]).TASKS_START, nhw_rtc2_TASKS_START},
233     //{ (void*)&(NRF_RTC_regs[2]).TASKS_STOP , nhw_rtc2_TASKS_STOP},
234     //{ (void*)&(NRF_RTC_regs[2]).TASKS_TRIGOVRFLW , nhw_rtc2_TASKS_TRIGOVRFLW},
235 
236     //RNG:
237     { (void*)&NRF_RNG_regs.TASKS_START, nhw_RNG_TASK_START},
238     { (void*)&NRF_RNG_regs.TASKS_STOP , nhw_RNG_TASK_STOP},
239 
240     //ECB
241 
242     //AAR
243     { (void*)&NRF_AAR_regs.TASKS_START , nhw_AAR_TASK_START},
244 
245     //CCM
246     { (void*)&NRF_CCM_regs.TASKS_CRYPT , nhw_CCM_TASK_CRYPT},
247 
248     //PPI:
249     { (void*)&NRF_PPI_regs.TASKS_CHG[0].EN,  nrf_ppi_TASK_CHG0_EN},
250     { (void*)&NRF_PPI_regs.TASKS_CHG[1].EN,  nrf_ppi_TASK_CHG1_EN},
251     { (void*)&NRF_PPI_regs.TASKS_CHG[2].EN,  nrf_ppi_TASK_CHG2_EN},
252     { (void*)&NRF_PPI_regs.TASKS_CHG[3].EN,  nrf_ppi_TASK_CHG3_EN},
253     { (void*)&NRF_PPI_regs.TASKS_CHG[4].EN,  nrf_ppi_TASK_CHG4_EN},
254     { (void*)&NRF_PPI_regs.TASKS_CHG[5].EN,  nrf_ppi_TASK_CHG5_EN},
255     { (void*)&NRF_PPI_regs.TASKS_CHG[0].DIS, nrf_ppi_TASK_CHG0_DIS},
256     { (void*)&NRF_PPI_regs.TASKS_CHG[1].DIS, nrf_ppi_TASK_CHG1_DIS},
257     { (void*)&NRF_PPI_regs.TASKS_CHG[2].DIS, nrf_ppi_TASK_CHG2_DIS},
258     { (void*)&NRF_PPI_regs.TASKS_CHG[3].DIS, nrf_ppi_TASK_CHG3_DIS},
259     { (void*)&NRF_PPI_regs.TASKS_CHG[4].DIS, nrf_ppi_TASK_CHG4_DIS},
260     { (void*)&NRF_PPI_regs.TASKS_CHG[5].DIS, nrf_ppi_TASK_CHG5_DIS},
261 
262     //EGU:
263     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[0] , nhw_egu_0_TASK_TRIGGER_0},
264     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[1] , nhw_egu_0_TASK_TRIGGER_1},
265     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[2] , nhw_egu_0_TASK_TRIGGER_2},
266     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[3] , nhw_egu_0_TASK_TRIGGER_3},
267     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[4] , nhw_egu_0_TASK_TRIGGER_4},
268     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[5] , nhw_egu_0_TASK_TRIGGER_5},
269     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[6] , nhw_egu_0_TASK_TRIGGER_6},
270     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[7] , nhw_egu_0_TASK_TRIGGER_7},
271     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[8] , nhw_egu_0_TASK_TRIGGER_8},
272     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[9] , nhw_egu_0_TASK_TRIGGER_9},
273     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[10] , nhw_egu_0_TASK_TRIGGER_10},
274     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[11] , nhw_egu_0_TASK_TRIGGER_11},
275     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[12] , nhw_egu_0_TASK_TRIGGER_12},
276     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[13] , nhw_egu_0_TASK_TRIGGER_13},
277     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[14] , nhw_egu_0_TASK_TRIGGER_14},
278     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[15] , nhw_egu_0_TASK_TRIGGER_15},
279     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[0] , nhw_egu_1_TASK_TRIGGER_0},
280     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[1] , nhw_egu_1_TASK_TRIGGER_1},
281     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[2] , nhw_egu_1_TASK_TRIGGER_2},
282     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[3] , nhw_egu_1_TASK_TRIGGER_3},
283     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[4] , nhw_egu_1_TASK_TRIGGER_4},
284     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[5] , nhw_egu_1_TASK_TRIGGER_5},
285     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[6] , nhw_egu_1_TASK_TRIGGER_6},
286     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[7] , nhw_egu_1_TASK_TRIGGER_7},
287     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[8] , nhw_egu_1_TASK_TRIGGER_8},
288     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[9] , nhw_egu_1_TASK_TRIGGER_9},
289     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[10] , nhw_egu_1_TASK_TRIGGER_10},
290     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[11] , nhw_egu_1_TASK_TRIGGER_11},
291     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[12] , nhw_egu_1_TASK_TRIGGER_12},
292     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[13] , nhw_egu_1_TASK_TRIGGER_13},
293     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[14] , nhw_egu_1_TASK_TRIGGER_14},
294     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[15] , nhw_egu_1_TASK_TRIGGER_15},
295     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[0] , nhw_egu_2_TASK_TRIGGER_0},
296     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[1] , nhw_egu_2_TASK_TRIGGER_1},
297     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[2] , nhw_egu_2_TASK_TRIGGER_2},
298     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[3] , nhw_egu_2_TASK_TRIGGER_3},
299     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[4] , nhw_egu_2_TASK_TRIGGER_4},
300     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[5] , nhw_egu_2_TASK_TRIGGER_5},
301     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[6] , nhw_egu_2_TASK_TRIGGER_6},
302     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[7] , nhw_egu_2_TASK_TRIGGER_7},
303     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[8] , nhw_egu_2_TASK_TRIGGER_8},
304     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[9] , nhw_egu_2_TASK_TRIGGER_9},
305     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[10] , nhw_egu_2_TASK_TRIGGER_10},
306     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[11] , nhw_egu_2_TASK_TRIGGER_11},
307     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[12] , nhw_egu_2_TASK_TRIGGER_12},
308     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[13] , nhw_egu_2_TASK_TRIGGER_13},
309     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[14] , nhw_egu_2_TASK_TRIGGER_14},
310     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[15] , nhw_egu_2_TASK_TRIGGER_15},
311     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[0] , nhw_egu_3_TASK_TRIGGER_0},
312     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[1] , nhw_egu_3_TASK_TRIGGER_1},
313     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[2] , nhw_egu_3_TASK_TRIGGER_2},
314     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[3] , nhw_egu_3_TASK_TRIGGER_3},
315     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[4] , nhw_egu_3_TASK_TRIGGER_4},
316     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[5] , nhw_egu_3_TASK_TRIGGER_5},
317     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[6] , nhw_egu_3_TASK_TRIGGER_6},
318     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[7] , nhw_egu_3_TASK_TRIGGER_7},
319     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[8] , nhw_egu_3_TASK_TRIGGER_8},
320     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[9] , nhw_egu_3_TASK_TRIGGER_9},
321     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[10] , nhw_egu_3_TASK_TRIGGER_10},
322     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[11] , nhw_egu_3_TASK_TRIGGER_11},
323     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[12] , nhw_egu_3_TASK_TRIGGER_12},
324     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[13] , nhw_egu_3_TASK_TRIGGER_13},
325     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[14] , nhw_egu_3_TASK_TRIGGER_14},
326     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[15] , nhw_egu_3_TASK_TRIGGER_15},
327     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[0] , nhw_egu_4_TASK_TRIGGER_0},
328     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[1] , nhw_egu_4_TASK_TRIGGER_1},
329     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[2] , nhw_egu_4_TASK_TRIGGER_2},
330     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[3] , nhw_egu_4_TASK_TRIGGER_3},
331     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[4] , nhw_egu_4_TASK_TRIGGER_4},
332     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[5] , nhw_egu_4_TASK_TRIGGER_5},
333     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[6] , nhw_egu_4_TASK_TRIGGER_6},
334     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[7] , nhw_egu_4_TASK_TRIGGER_7},
335     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[8] , nhw_egu_4_TASK_TRIGGER_8},
336     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[9] , nhw_egu_4_TASK_TRIGGER_9},
337     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[10] , nhw_egu_4_TASK_TRIGGER_10},
338     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[11] , nhw_egu_4_TASK_TRIGGER_11},
339     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[12] , nhw_egu_4_TASK_TRIGGER_12},
340     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[13] , nhw_egu_4_TASK_TRIGGER_13},
341     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[14] , nhw_egu_4_TASK_TRIGGER_14},
342     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[15] , nhw_egu_4_TASK_TRIGGER_15},
343     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[0] , nhw_egu_5_TASK_TRIGGER_0},
344     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[1] , nhw_egu_5_TASK_TRIGGER_1},
345     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[2] , nhw_egu_5_TASK_TRIGGER_2},
346     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[3] , nhw_egu_5_TASK_TRIGGER_3},
347     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[4] , nhw_egu_5_TASK_TRIGGER_4},
348     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[5] , nhw_egu_5_TASK_TRIGGER_5},
349     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[6] , nhw_egu_5_TASK_TRIGGER_6},
350     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[7] , nhw_egu_5_TASK_TRIGGER_7},
351     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[8] , nhw_egu_5_TASK_TRIGGER_8},
352     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[9] , nhw_egu_5_TASK_TRIGGER_9},
353     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[10] , nhw_egu_5_TASK_TRIGGER_10},
354     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[11] , nhw_egu_5_TASK_TRIGGER_11},
355     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[12] , nhw_egu_5_TASK_TRIGGER_12},
356     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[13] , nhw_egu_5_TASK_TRIGGER_13},
357     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[14] , nhw_egu_5_TASK_TRIGGER_14},
358     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[15] , nhw_egu_5_TASK_TRIGGER_15},
359 
360     //End marker
361     { NULL, NULL }
362 };
363 
364 /**
365  * Table to convert from an event_address as programmed by the SW into an
366  * event_type used here to index tables
367  */
368 typedef struct {
369   ppi_event_types_t event_type;
370   void *event_addr;
371 } ppi_event_table_t;
372 
373 static const ppi_event_table_t ppi_events_table[] = { //better keep same order as in ppi_event_types_t
374     {CLOCK_EVENTS_HFCLKSTARTED, &NRF_CLKPWR_regs[0].CLK.EVENTS_HFCLKSTARTED},
375     {CLOCK_EVENTS_LFCLKSTARTED, &NRF_CLKPWR_regs[0].CLK.EVENTS_LFCLKSTARTED},
376     {CLOCK_EVENTS_DONE        , &NRF_CLKPWR_regs[0].CLK.EVENTS_DONE        },
377     {CLOCK_EVENTS_CTTO        , &NRF_CLKPWR_regs[0].CLK.EVENTS_CTTO        },
378     {CLOCK_EVENTS_CTSTARTED   , &NRF_CLKPWR_regs[0].CLK.EVENTS_CTSTARTED   },
379     {CLOCK_EVENTS_CTSTOPPED   , &NRF_CLKPWR_regs[0].CLK.EVENTS_CTSTOPPED   },
380 
381     {RADIO_EVENTS_READY,   &NRF_RADIO_regs.EVENTS_READY},
382     {RADIO_EVENTS_ADDRESS, &NRF_RADIO_regs.EVENTS_ADDRESS},
383     {RADIO_EVENTS_PAYLOAD, &NRF_RADIO_regs.EVENTS_PAYLOAD},
384     {RADIO_EVENTS_END,     &NRF_RADIO_regs.EVENTS_END},
385     {RADIO_EVENTS_DISABLED,&NRF_RADIO_regs.EVENTS_DISABLED},
386     {RADIO_EVENTS_DEVMATCH,&NRF_RADIO_regs.EVENTS_DEVMATCH},
387     {RADIO_EVENTS_DEVMISS ,&NRF_RADIO_regs.EVENTS_DEVMISS},
388     {RADIO_EVENTS_RSSIEND, &NRF_RADIO_regs.EVENTS_RSSIEND},
389     {RADIO_EVENTS_BCMATCH, &NRF_RADIO_regs.EVENTS_BCMATCH},
390     {RADIO_EVENTS_CRCOK,   &NRF_RADIO_regs.EVENTS_CRCOK},
391     {RADIO_EVENTS_CRCERROR,&NRF_RADIO_regs.EVENTS_CRCERROR},
392     {RADIO_EVENTS_FRAMESTART,&NRF_RADIO_regs.EVENTS_FRAMESTART},
393     {RADIO_EVENTS_EDEND,   &NRF_RADIO_regs.EVENTS_EDEND},
394     {RADIO_EVENTS_EDSTOPPED, &NRF_RADIO_regs.EVENTS_EDSTOPPED},
395     {RADIO_EVENTS_CCAIDLE, &NRF_RADIO_regs.EVENTS_CCAIDLE},
396     {RADIO_EVENTS_CCABUSY, &NRF_RADIO_regs.EVENTS_CCABUSY},
397     {RADIO_EVENTS_CCASTOPPED, &NRF_RADIO_regs.EVENTS_CCASTOPPED},
398     {RADIO_EVENTS_RATEBOOST, &NRF_RADIO_regs.EVENTS_RATEBOOST},
399     {RADIO_EVENTS_TXREADY, &NRF_RADIO_regs.EVENTS_TXREADY},
400     {RADIO_EVENTS_RXREADY, &NRF_RADIO_regs.EVENTS_RXREADY},
401     {RADIO_EVENTS_MHRMATCH,&NRF_RADIO_regs.EVENTS_MHRMATCH},
402     {RADIO_EVENTS_SYNC,    &NRF_RADIO_regs.EVENTS_SYNC},
403     {RADIO_EVENTS_PHYEND,  &NRF_RADIO_regs.EVENTS_PHYEND},
404     {RADIO_EVENTS_CTEPRESENT,&NRF_RADIO_regs.EVENTS_CTEPRESENT},
405 
406     {UARTE0_EVENTS_CTS      , &NRF_UARTE_regs[0].EVENTS_CTS      },
407     {UARTE0_EVENTS_NCTS     , &NRF_UARTE_regs[0].EVENTS_NCTS     },
408     {UARTE0_EVENTS_RXDRDY   , &NRF_UARTE_regs[0].EVENTS_RXDRDY   },
409     {UARTE0_EVENTS_ENDRX    , &NRF_UARTE_regs[0].EVENTS_ENDRX    },
410     {UARTE0_EVENTS_TXDRDY   , &NRF_UARTE_regs[0].EVENTS_TXDRDY   },
411     {UARTE0_EVENTS_ENDTX    , &NRF_UARTE_regs[0].EVENTS_ENDTX    },
412     {UARTE0_EVENTS_ERROR    , &NRF_UARTE_regs[0].EVENTS_ERROR    },
413     {UARTE0_EVENTS_RXTO     , &NRF_UARTE_regs[0].EVENTS_RXTO     },
414     {UARTE0_EVENTS_RXSTARTED, &NRF_UARTE_regs[0].EVENTS_RXSTARTED},
415     {UARTE0_EVENTS_TXSTARTED, &NRF_UARTE_regs[0].EVENTS_TXSTARTED},
416     {UARTE0_EVENTS_TXSTOPPED, &NRF_UARTE_regs[0].EVENTS_TXSTOPPED},
417 
418     {GPIOTE_EVENTS_IN_0, &NRF_GPIOTE_regs.EVENTS_IN[0]},
419     {GPIOTE_EVENTS_IN_1, &NRF_GPIOTE_regs.EVENTS_IN[1]},
420     {GPIOTE_EVENTS_IN_2, &NRF_GPIOTE_regs.EVENTS_IN[2]},
421     {GPIOTE_EVENTS_IN_3, &NRF_GPIOTE_regs.EVENTS_IN[3]},
422     {GPIOTE_EVENTS_IN_4, &NRF_GPIOTE_regs.EVENTS_IN[4]},
423     {GPIOTE_EVENTS_IN_5, &NRF_GPIOTE_regs.EVENTS_IN[5]},
424     {GPIOTE_EVENTS_IN_6, &NRF_GPIOTE_regs.EVENTS_IN[6]},
425     {GPIOTE_EVENTS_IN_7, &NRF_GPIOTE_regs.EVENTS_IN[7]},
426     {GPIOTE_EVENTS_PORT, &NRF_GPIOTE_regs.EVENTS_PORT},
427 
428     {TIMER0_EVENTS_COMPARE_0, &NRF_TIMER_regs[0].EVENTS_COMPARE[0]},
429     {TIMER0_EVENTS_COMPARE_1, &NRF_TIMER_regs[0].EVENTS_COMPARE[1]},
430     {TIMER0_EVENTS_COMPARE_2, &NRF_TIMER_regs[0].EVENTS_COMPARE[2]},
431     {TIMER0_EVENTS_COMPARE_3, &NRF_TIMER_regs[0].EVENTS_COMPARE[3]},
432 //    {TIMER0_EVENTS_COMPARE_4, &NRF_TIMER_regs[0].EVENTS_COMPARE[4]},
433 //    {TIMER0_EVENTS_COMPARE_5, &NRF_TIMER_regs[0].EVENTS_COMPARE[5]},
434 
435     {TIMER1_EVENTS_COMPARE_0, &NRF_TIMER_regs[1].EVENTS_COMPARE[0]},
436     {TIMER1_EVENTS_COMPARE_1, &NRF_TIMER_regs[1].EVENTS_COMPARE[1]},
437     {TIMER1_EVENTS_COMPARE_2, &NRF_TIMER_regs[1].EVENTS_COMPARE[2]},
438     {TIMER1_EVENTS_COMPARE_3, &NRF_TIMER_regs[1].EVENTS_COMPARE[3]},
439     //    {TIMER1_EVENTS_COMPARE_4, &NRF_TIMER_regs[1].EVENTS_COMPARE[4]},
440     //    {TIMER1_EVENTS_COMPARE_5, &NRF_TIMER_regs[1].EVENTS_COMPARE[5]},
441 
442     {TIMER2_EVENTS_COMPARE_0, &NRF_TIMER_regs[2].EVENTS_COMPARE[0]},
443     {TIMER2_EVENTS_COMPARE_1, &NRF_TIMER_regs[2].EVENTS_COMPARE[1]},
444     {TIMER2_EVENTS_COMPARE_2, &NRF_TIMER_regs[2].EVENTS_COMPARE[2]},
445     {TIMER2_EVENTS_COMPARE_3, &NRF_TIMER_regs[2].EVENTS_COMPARE[3]},
446     //    {TIMER2_EVENTS_COMPARE_4, &NRF_TIMER_regs[2].EVENTS_COMPARE[4]},
447     //    {TIMER2_EVENTS_COMPARE_5, &NRF_TIMER_regs[2].EVENTS_COMPARE[5]},
448 
449     {RTC0_EVENTS_OVRFLW, &NRF_RTC_regs[0].EVENTS_OVRFLW},
450     {RTC0_EVENTS_COMPARE_0, &NRF_RTC_regs[0].EVENTS_COMPARE[0]},
451     {RTC0_EVENTS_COMPARE_1, &NRF_RTC_regs[0].EVENTS_COMPARE[1]},
452     {RTC0_EVENTS_COMPARE_2, &NRF_RTC_regs[0].EVENTS_COMPARE[2]},
453     {RTC0_EVENTS_COMPARE_3, &NRF_RTC_regs[0].EVENTS_COMPARE[3]},
454 
455     {TEMP_EVENTS_DATARDY, &NRF_TEMP_regs.EVENTS_DATARDY},
456 
457     //{RNG_EVENTS_VALRDY, &NRF_RNG_regs.EVENTS_VALRDY},
458 
459     {CCM_EVENTS_ENDKSGEN, &NRF_CCM_regs.EVENTS_ENDKSGEN},
460     {CCM_EVENTS_ENDCRYPT, &NRF_CCM_regs.EVENTS_ENDCRYPT},
461     {CCM_EVENTS_ERROR,    &NRF_CCM_regs.EVENTS_ERROR},
462 
463     {RTC1_EVENTS_OVRFLW, &NRF_RTC_regs[1].EVENTS_OVRFLW},
464     {RTC1_EVENTS_COMPARE_0, &NRF_RTC_regs[1].EVENTS_COMPARE[0]},
465     {RTC1_EVENTS_COMPARE_1, &NRF_RTC_regs[1].EVENTS_COMPARE[1]},
466     {RTC1_EVENTS_COMPARE_2, &NRF_RTC_regs[1].EVENTS_COMPARE[2]},
467     {RTC1_EVENTS_COMPARE_3, &NRF_RTC_regs[1].EVENTS_COMPARE[3]},
468 
469     {EGU0_EVENTS_TRIGGERED_0, &NRF_EGU_regs[0].EVENTS_TRIGGERED[0]}, /*These are autogenerated (See NRF_EGU.c)*/
470     {EGU0_EVENTS_TRIGGERED_1, &NRF_EGU_regs[0].EVENTS_TRIGGERED[1]},
471     {EGU0_EVENTS_TRIGGERED_2, &NRF_EGU_regs[0].EVENTS_TRIGGERED[2]},
472     {EGU0_EVENTS_TRIGGERED_3, &NRF_EGU_regs[0].EVENTS_TRIGGERED[3]},
473     {EGU0_EVENTS_TRIGGERED_4, &NRF_EGU_regs[0].EVENTS_TRIGGERED[4]},
474     {EGU0_EVENTS_TRIGGERED_5, &NRF_EGU_regs[0].EVENTS_TRIGGERED[5]},
475     {EGU0_EVENTS_TRIGGERED_6, &NRF_EGU_regs[0].EVENTS_TRIGGERED[6]},
476     {EGU0_EVENTS_TRIGGERED_7, &NRF_EGU_regs[0].EVENTS_TRIGGERED[7]},
477     {EGU0_EVENTS_TRIGGERED_8, &NRF_EGU_regs[0].EVENTS_TRIGGERED[8]},
478     {EGU0_EVENTS_TRIGGERED_9, &NRF_EGU_regs[0].EVENTS_TRIGGERED[9]},
479     {EGU0_EVENTS_TRIGGERED_10, &NRF_EGU_regs[0].EVENTS_TRIGGERED[10]},
480     {EGU0_EVENTS_TRIGGERED_11, &NRF_EGU_regs[0].EVENTS_TRIGGERED[11]},
481     {EGU0_EVENTS_TRIGGERED_12, &NRF_EGU_regs[0].EVENTS_TRIGGERED[12]},
482     {EGU0_EVENTS_TRIGGERED_13, &NRF_EGU_regs[0].EVENTS_TRIGGERED[13]},
483     {EGU0_EVENTS_TRIGGERED_14, &NRF_EGU_regs[0].EVENTS_TRIGGERED[14]},
484     {EGU0_EVENTS_TRIGGERED_15, &NRF_EGU_regs[0].EVENTS_TRIGGERED[15]},
485     {EGU1_EVENTS_TRIGGERED_0, &NRF_EGU_regs[1].EVENTS_TRIGGERED[0]},
486     {EGU1_EVENTS_TRIGGERED_1, &NRF_EGU_regs[1].EVENTS_TRIGGERED[1]},
487     {EGU1_EVENTS_TRIGGERED_2, &NRF_EGU_regs[1].EVENTS_TRIGGERED[2]},
488     {EGU1_EVENTS_TRIGGERED_3, &NRF_EGU_regs[1].EVENTS_TRIGGERED[3]},
489     {EGU1_EVENTS_TRIGGERED_4, &NRF_EGU_regs[1].EVENTS_TRIGGERED[4]},
490     {EGU1_EVENTS_TRIGGERED_5, &NRF_EGU_regs[1].EVENTS_TRIGGERED[5]},
491     {EGU1_EVENTS_TRIGGERED_6, &NRF_EGU_regs[1].EVENTS_TRIGGERED[6]},
492     {EGU1_EVENTS_TRIGGERED_7, &NRF_EGU_regs[1].EVENTS_TRIGGERED[7]},
493     {EGU1_EVENTS_TRIGGERED_8, &NRF_EGU_regs[1].EVENTS_TRIGGERED[8]},
494     {EGU1_EVENTS_TRIGGERED_9, &NRF_EGU_regs[1].EVENTS_TRIGGERED[9]},
495     {EGU1_EVENTS_TRIGGERED_10, &NRF_EGU_regs[1].EVENTS_TRIGGERED[10]},
496     {EGU1_EVENTS_TRIGGERED_11, &NRF_EGU_regs[1].EVENTS_TRIGGERED[11]},
497     {EGU1_EVENTS_TRIGGERED_12, &NRF_EGU_regs[1].EVENTS_TRIGGERED[12]},
498     {EGU1_EVENTS_TRIGGERED_13, &NRF_EGU_regs[1].EVENTS_TRIGGERED[13]},
499     {EGU1_EVENTS_TRIGGERED_14, &NRF_EGU_regs[1].EVENTS_TRIGGERED[14]},
500     {EGU1_EVENTS_TRIGGERED_15, &NRF_EGU_regs[1].EVENTS_TRIGGERED[15]},
501     {EGU2_EVENTS_TRIGGERED_0, &NRF_EGU_regs[2].EVENTS_TRIGGERED[0]},
502     {EGU2_EVENTS_TRIGGERED_1, &NRF_EGU_regs[2].EVENTS_TRIGGERED[1]},
503     {EGU2_EVENTS_TRIGGERED_2, &NRF_EGU_regs[2].EVENTS_TRIGGERED[2]},
504     {EGU2_EVENTS_TRIGGERED_3, &NRF_EGU_regs[2].EVENTS_TRIGGERED[3]},
505     {EGU2_EVENTS_TRIGGERED_4, &NRF_EGU_regs[2].EVENTS_TRIGGERED[4]},
506     {EGU2_EVENTS_TRIGGERED_5, &NRF_EGU_regs[2].EVENTS_TRIGGERED[5]},
507     {EGU2_EVENTS_TRIGGERED_6, &NRF_EGU_regs[2].EVENTS_TRIGGERED[6]},
508     {EGU2_EVENTS_TRIGGERED_7, &NRF_EGU_regs[2].EVENTS_TRIGGERED[7]},
509     {EGU2_EVENTS_TRIGGERED_8, &NRF_EGU_regs[2].EVENTS_TRIGGERED[8]},
510     {EGU2_EVENTS_TRIGGERED_9, &NRF_EGU_regs[2].EVENTS_TRIGGERED[9]},
511     {EGU2_EVENTS_TRIGGERED_10, &NRF_EGU_regs[2].EVENTS_TRIGGERED[10]},
512     {EGU2_EVENTS_TRIGGERED_11, &NRF_EGU_regs[2].EVENTS_TRIGGERED[11]},
513     {EGU2_EVENTS_TRIGGERED_12, &NRF_EGU_regs[2].EVENTS_TRIGGERED[12]},
514     {EGU2_EVENTS_TRIGGERED_13, &NRF_EGU_regs[2].EVENTS_TRIGGERED[13]},
515     {EGU2_EVENTS_TRIGGERED_14, &NRF_EGU_regs[2].EVENTS_TRIGGERED[14]},
516     {EGU2_EVENTS_TRIGGERED_15, &NRF_EGU_regs[2].EVENTS_TRIGGERED[15]},
517     {EGU3_EVENTS_TRIGGERED_0, &NRF_EGU_regs[3].EVENTS_TRIGGERED[0]},
518     {EGU3_EVENTS_TRIGGERED_1, &NRF_EGU_regs[3].EVENTS_TRIGGERED[1]},
519     {EGU3_EVENTS_TRIGGERED_2, &NRF_EGU_regs[3].EVENTS_TRIGGERED[2]},
520     {EGU3_EVENTS_TRIGGERED_3, &NRF_EGU_regs[3].EVENTS_TRIGGERED[3]},
521     {EGU3_EVENTS_TRIGGERED_4, &NRF_EGU_regs[3].EVENTS_TRIGGERED[4]},
522     {EGU3_EVENTS_TRIGGERED_5, &NRF_EGU_regs[3].EVENTS_TRIGGERED[5]},
523     {EGU3_EVENTS_TRIGGERED_6, &NRF_EGU_regs[3].EVENTS_TRIGGERED[6]},
524     {EGU3_EVENTS_TRIGGERED_7, &NRF_EGU_regs[3].EVENTS_TRIGGERED[7]},
525     {EGU3_EVENTS_TRIGGERED_8, &NRF_EGU_regs[3].EVENTS_TRIGGERED[8]},
526     {EGU3_EVENTS_TRIGGERED_9, &NRF_EGU_regs[3].EVENTS_TRIGGERED[9]},
527     {EGU3_EVENTS_TRIGGERED_10, &NRF_EGU_regs[3].EVENTS_TRIGGERED[10]},
528     {EGU3_EVENTS_TRIGGERED_11, &NRF_EGU_regs[3].EVENTS_TRIGGERED[11]},
529     {EGU3_EVENTS_TRIGGERED_12, &NRF_EGU_regs[3].EVENTS_TRIGGERED[12]},
530     {EGU3_EVENTS_TRIGGERED_13, &NRF_EGU_regs[3].EVENTS_TRIGGERED[13]},
531     {EGU3_EVENTS_TRIGGERED_14, &NRF_EGU_regs[3].EVENTS_TRIGGERED[14]},
532     {EGU3_EVENTS_TRIGGERED_15, &NRF_EGU_regs[3].EVENTS_TRIGGERED[15]},
533     {EGU4_EVENTS_TRIGGERED_0, &NRF_EGU_regs[4].EVENTS_TRIGGERED[0]},
534     {EGU4_EVENTS_TRIGGERED_1, &NRF_EGU_regs[4].EVENTS_TRIGGERED[1]},
535     {EGU4_EVENTS_TRIGGERED_2, &NRF_EGU_regs[4].EVENTS_TRIGGERED[2]},
536     {EGU4_EVENTS_TRIGGERED_3, &NRF_EGU_regs[4].EVENTS_TRIGGERED[3]},
537     {EGU4_EVENTS_TRIGGERED_4, &NRF_EGU_regs[4].EVENTS_TRIGGERED[4]},
538     {EGU4_EVENTS_TRIGGERED_5, &NRF_EGU_regs[4].EVENTS_TRIGGERED[5]},
539     {EGU4_EVENTS_TRIGGERED_6, &NRF_EGU_regs[4].EVENTS_TRIGGERED[6]},
540     {EGU4_EVENTS_TRIGGERED_7, &NRF_EGU_regs[4].EVENTS_TRIGGERED[7]},
541     {EGU4_EVENTS_TRIGGERED_8, &NRF_EGU_regs[4].EVENTS_TRIGGERED[8]},
542     {EGU4_EVENTS_TRIGGERED_9, &NRF_EGU_regs[4].EVENTS_TRIGGERED[9]},
543     {EGU4_EVENTS_TRIGGERED_10, &NRF_EGU_regs[4].EVENTS_TRIGGERED[10]},
544     {EGU4_EVENTS_TRIGGERED_11, &NRF_EGU_regs[4].EVENTS_TRIGGERED[11]},
545     {EGU4_EVENTS_TRIGGERED_12, &NRF_EGU_regs[4].EVENTS_TRIGGERED[12]},
546     {EGU4_EVENTS_TRIGGERED_13, &NRF_EGU_regs[4].EVENTS_TRIGGERED[13]},
547     {EGU4_EVENTS_TRIGGERED_14, &NRF_EGU_regs[4].EVENTS_TRIGGERED[14]},
548     {EGU4_EVENTS_TRIGGERED_15, &NRF_EGU_regs[4].EVENTS_TRIGGERED[15]},
549     {EGU5_EVENTS_TRIGGERED_0, &NRF_EGU_regs[5].EVENTS_TRIGGERED[0]},
550     {EGU5_EVENTS_TRIGGERED_1, &NRF_EGU_regs[5].EVENTS_TRIGGERED[1]},
551     {EGU5_EVENTS_TRIGGERED_2, &NRF_EGU_regs[5].EVENTS_TRIGGERED[2]},
552     {EGU5_EVENTS_TRIGGERED_3, &NRF_EGU_regs[5].EVENTS_TRIGGERED[3]},
553     {EGU5_EVENTS_TRIGGERED_4, &NRF_EGU_regs[5].EVENTS_TRIGGERED[4]},
554     {EGU5_EVENTS_TRIGGERED_5, &NRF_EGU_regs[5].EVENTS_TRIGGERED[5]},
555     {EGU5_EVENTS_TRIGGERED_6, &NRF_EGU_regs[5].EVENTS_TRIGGERED[6]},
556     {EGU5_EVENTS_TRIGGERED_7, &NRF_EGU_regs[5].EVENTS_TRIGGERED[7]},
557     {EGU5_EVENTS_TRIGGERED_8, &NRF_EGU_regs[5].EVENTS_TRIGGERED[8]},
558     {EGU5_EVENTS_TRIGGERED_9, &NRF_EGU_regs[5].EVENTS_TRIGGERED[9]},
559     {EGU5_EVENTS_TRIGGERED_10, &NRF_EGU_regs[5].EVENTS_TRIGGERED[10]},
560     {EGU5_EVENTS_TRIGGERED_11, &NRF_EGU_regs[5].EVENTS_TRIGGERED[11]},
561     {EGU5_EVENTS_TRIGGERED_12, &NRF_EGU_regs[5].EVENTS_TRIGGERED[12]},
562     {EGU5_EVENTS_TRIGGERED_13, &NRF_EGU_regs[5].EVENTS_TRIGGERED[13]},
563     {EGU5_EVENTS_TRIGGERED_14, &NRF_EGU_regs[5].EVENTS_TRIGGERED[14]},
564     {EGU5_EVENTS_TRIGGERED_15, &NRF_EGU_regs[5].EVENTS_TRIGGERED[15]},
565 
566     {TIMER3_EVENTS_COMPARE_0, &NRF_TIMER_regs[3].EVENTS_COMPARE[0]},
567     {TIMER3_EVENTS_COMPARE_1, &NRF_TIMER_regs[3].EVENTS_COMPARE[1]},
568     {TIMER3_EVENTS_COMPARE_2, &NRF_TIMER_regs[3].EVENTS_COMPARE[2]},
569     {TIMER3_EVENTS_COMPARE_3, &NRF_TIMER_regs[3].EVENTS_COMPARE[3]},
570     {TIMER3_EVENTS_COMPARE_4, &NRF_TIMER_regs[3].EVENTS_COMPARE[4]},
571     {TIMER3_EVENTS_COMPARE_5, &NRF_TIMER_regs[3].EVENTS_COMPARE[5]},
572 
573     {TIMER4_EVENTS_COMPARE_0, &NRF_TIMER_regs[4].EVENTS_COMPARE[0]},
574     {TIMER4_EVENTS_COMPARE_1, &NRF_TIMER_regs[4].EVENTS_COMPARE[1]},
575     {TIMER4_EVENTS_COMPARE_2, &NRF_TIMER_regs[4].EVENTS_COMPARE[2]},
576     {TIMER4_EVENTS_COMPARE_3, &NRF_TIMER_regs[4].EVENTS_COMPARE[3]},
577     {TIMER4_EVENTS_COMPARE_4, &NRF_TIMER_regs[4].EVENTS_COMPARE[4]},
578     {TIMER4_EVENTS_COMPARE_5, &NRF_TIMER_regs[4].EVENTS_COMPARE[5]},
579 
580     {RTC2_EVENTS_OVRFLW, &NRF_RTC_regs[2].EVENTS_OVRFLW},
581     {RTC2_EVENTS_COMPARE_0, &NRF_RTC_regs[2].EVENTS_COMPARE[0]},
582     {RTC2_EVENTS_COMPARE_1, &NRF_RTC_regs[2].EVENTS_COMPARE[1]},
583     {RTC2_EVENTS_COMPARE_2, &NRF_RTC_regs[2].EVENTS_COMPARE[2]},
584     {RTC2_EVENTS_COMPARE_3, &NRF_RTC_regs[2].EVENTS_COMPARE[3]},
585 
586     {UARTE1_EVENTS_CTS      , &NRF_UARTE_regs[1].EVENTS_CTS      },
587     {UARTE1_EVENTS_NCTS     , &NRF_UARTE_regs[1].EVENTS_NCTS     },
588     {UARTE1_EVENTS_RXDRDY   , &NRF_UARTE_regs[1].EVENTS_RXDRDY   },
589     {UARTE1_EVENTS_ENDRX    , &NRF_UARTE_regs[1].EVENTS_ENDRX    },
590     {UARTE1_EVENTS_TXDRDY   , &NRF_UARTE_regs[1].EVENTS_TXDRDY   },
591     {UARTE1_EVENTS_ENDTX    , &NRF_UARTE_regs[1].EVENTS_ENDTX    },
592     {UARTE1_EVENTS_ERROR    , &NRF_UARTE_regs[1].EVENTS_ERROR    },
593     {UARTE1_EVENTS_RXTO     , &NRF_UARTE_regs[1].EVENTS_RXTO     },
594     {UARTE1_EVENTS_RXSTARTED, &NRF_UARTE_regs[1].EVENTS_RXSTARTED},
595     {UARTE1_EVENTS_TXSTARTED, &NRF_UARTE_regs[1].EVENTS_TXSTARTED},
596     {UARTE1_EVENTS_TXSTOPPED, &NRF_UARTE_regs[1].EVENTS_TXSTOPPED},
597 
598     {NUMBER_PPI_EVENTS, NULL} //End marker
599 };
600 
601 
set_fixed_channel_routes(void)602 static void set_fixed_channel_routes(void) {
603   //TODO: add handler function pointers as we add those functions while modelling the different parts
604 
605   //Set the fixed channels configuration:
606   //  20 TIMER0->EVENTS_COMPARE[0] RADIO->TASKS_TXEN
607     ppi_evt_to_ch[TIMER0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 20 );
608     ppi_ch_tasks[20].tep_f = nhw_RADIO_TASK_TXEN; //RADIO->TASKS_TXEN
609 
610   //  21 TIMER0->EVENTS_COMPARE[0] RADIO->TASKS_RXEN
611     ppi_evt_to_ch[TIMER0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 21 );
612     ppi_ch_tasks[21].tep_f = nhw_RADIO_TASK_RXEN; //RADIO->TASKS_RXEN
613 
614   //  22 TIMER0->EVENTS_COMPARE[1] RADIO->TASKS_DISABLE
615     ppi_evt_to_ch[TIMER0_EVENTS_COMPARE_1].channels_mask |= ( 1 << 22 );
616     ppi_ch_tasks[22].tep_f = nhw_RADIO_TASK_DISABLE; //RADIO->TASKS_DISABLE
617 
618   //  23 RADIO->EVENTS_BCMATCH AAR->TASKS_START
619     ppi_evt_to_ch[RADIO_EVENTS_BCMATCH].channels_mask |= ( 1 << 23 );
620     ppi_ch_tasks[23].tep_f = nhw_AAR_TASK_START; //AAR->TASKS_START
621 
622   //  24 RADIO->EVENTS_READY CCM->TASKS_KSGEN
623     ppi_evt_to_ch[RADIO_EVENTS_READY].channels_mask |= ( 1 << 24 );
624     ppi_ch_tasks[24].tep_f = nhw_CCM_TASK_KSGEN; //CCM->TASKS_KSGEN
625 
626   //  25 RADIO->EVENTS_ADDRESS CCM->TASKS_CRYPT
627     ppi_evt_to_ch[RADIO_EVENTS_ADDRESS].channels_mask |= ( 1 << 25 );
628     ppi_ch_tasks[25].tep_f = nhw_CCM_TASK_CRYPT; //CCM->TASKS_CRYPT
629 
630   //  26 RADIO->EVENTS_ADDRESS TIMER0->TASKS_CAPTURE[1]
631     ppi_evt_to_ch[RADIO_EVENTS_ADDRESS].channels_mask |= ( 1 << 26 );
632     ppi_ch_tasks[26].tep_f = nhw_timer0_TASK_CAPTURE_1; //TIMER0->TASKS_CAPTURE[1]
633 
634   //  27 RADIO->EVENTS_END TIMER0->TASKS_CAPTURE[2]
635     ppi_evt_to_ch[RADIO_EVENTS_END].channels_mask |= ( 1 << 27 );
636     ppi_ch_tasks[27].tep_f = nhw_timer0_TASK_CAPTURE_2; //TIMER0->TASKS_CAPTURE[2]
637 
638   //  28 RTC0->EVENTS_COMPARE[0] RADIO->TASKS_TXEN
639     ppi_evt_to_ch[RTC0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 28 );
640     ppi_ch_tasks[28].tep_f = nhw_RADIO_TASK_TXEN; //RADIO->TASKS_TXEN
641 
642   //  29 RTC0->EVENTS_COMPARE[0] RADIO->TASKS_RXEN
643     ppi_evt_to_ch[RTC0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 29 );
644     ppi_ch_tasks[29].tep_f = nhw_RADIO_TASK_RXEN; //RADIO->TASKS_RXEN
645 
646   //  30 RTC0->EVENTS_COMPARE[0] TIMER0->TASKS_CLEAR
647     ppi_evt_to_ch[RTC0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 30 );
648     ppi_ch_tasks[30].tep_f = nhw_timer0_TASK_CLEAR; //TIMER0->TASKS_CLEAR
649 
650   //  31 RTC0->EVENTS_COMPARE[0] TIMER0->TASKS_START
651     ppi_evt_to_ch[RTC0_EVENTS_COMPARE_0].channels_mask |= ( (uint32_t)1 << 31 );
652     ppi_ch_tasks[31].tep_f = nhw_timer0_TASK_START; //TIMER0->TASKS_START
653 }
654 
655 /*
656  * When an event comes, we first queue all tasks that would be triggered in tasks_queue,
657  * and then trigger them.
658  * We do this to filter out duplicate tasks caused by the same event,
659  * as this is a use case
660  */
661 volatile static struct {
662   dest_f_t* q;
663   uint used;
664   uint size;
665 } tasks_queue;
666 #define TASK_QUEUE_ALLOC_SIZE 64
667 
668 
669 /**
670  * Initialize the PPI model
671  */
nrf_ppi_init(void)672 static void nrf_ppi_init(void) {
673   memset(&NRF_PPI_regs, 0, sizeof(NRF_PPI_regs));
674   memset(ppi_ch_tasks, 0, sizeof(ppi_ch_tasks));
675   memset(ppi_evt_to_ch, 0, sizeof(ppi_evt_to_ch));
676   set_fixed_channel_routes();
677   tasks_queue.q = (dest_f_t*)bs_calloc(TASK_QUEUE_ALLOC_SIZE, sizeof(dest_f_t));
678   tasks_queue.size = TASK_QUEUE_ALLOC_SIZE;
679 }
680 
681 NSI_TASK(nrf_ppi_init, HW_INIT, 50);
682 
683 /**
684  * Cleanup the PPI model before exiting the program
685  */
nrf_ppi_clean_up(void)686 static void nrf_ppi_clean_up(void) {
687   if (tasks_queue.q) {
688     free(tasks_queue.q);
689     tasks_queue.q = NULL;
690   }
691 }
692 
693 NSI_TASK(nrf_ppi_clean_up, ON_EXIT_PRE, 50);
694 
nrf_ppi_enqueue_task(dest_f_t task)695 static void nrf_ppi_enqueue_task(dest_f_t task) {
696   int i;
697   for (i = 0; i < tasks_queue.used; i++){
698     if (tasks_queue.q[i] == task){ //We ignore dups
699       return;
700     }
701   }
702 
703   if (tasks_queue.used >= tasks_queue.size) {
704     tasks_queue.size += TASK_QUEUE_ALLOC_SIZE;
705     tasks_queue.q = bs_realloc(tasks_queue.q, tasks_queue.size*sizeof(dest_f_t));
706   }
707   tasks_queue.q[tasks_queue.used++] = task;
708 }
709 
nrf_ppi_dequeue_all_tasks(void)710 static void nrf_ppi_dequeue_all_tasks(void) {
711   int i;
712   for (i = 0; i < tasks_queue.used; i++) {
713     if (tasks_queue.q[i]) {
714       dest_f_t f = tasks_queue.q[i];
715       tasks_queue.q[i] = NULL;
716       f();
717     }
718   }
719   tasks_queue.used = 0;
720 }
721 
722 /**
723  * HW models call this function when they want to signal an event which
724  * may trigger a task
725  */
nrf_ppi_event(ppi_event_types_t event)726 void nrf_ppi_event(ppi_event_types_t event){
727 
728   uint32_t ch_mask = ppi_evt_to_ch[event].channels_mask;
729   ch_mask &= NRF_PPI_regs.CHEN;
730 
731   if ( ch_mask ){
732     for ( int ch_nbr = __builtin_ffs(ch_mask) - 1;
733           ( ch_mask != 0 ) && ( ch_nbr < NUMBER_PPI_CHANNELS ) ;
734           ch_nbr++ ) {
735       if ( ch_mask & ( (uint32_t) 1 << ch_nbr ) ){
736         ch_mask &= ~( (uint64_t) 1 << ch_nbr );
737         if ( ppi_ch_tasks[ch_nbr].tep_f != NULL ){
738           nrf_ppi_enqueue_task(ppi_ch_tasks[ch_nbr].tep_f);
739         }
740         if ( ppi_ch_tasks[ch_nbr].fork_tep_f != NULL ){
741           nrf_ppi_enqueue_task(ppi_ch_tasks[ch_nbr].fork_tep_f);
742         }
743       } //if event is mapped to this channel
744     } //for channels
745     nrf_ppi_dequeue_all_tasks();
746   } //if this event is in any channel
747 }
748 
749 /**
750  * Find the task in ppi_tasks_table whose address
751  * matches <TEP> and save the task handling function <in dest>
752  *
753  * Helper function for the TEP and FORK_TEP functions
754  */
find_task(void * TEP,dest_f_t * dest,int ch_nbr)755 static void find_task(void *TEP, dest_f_t *dest, int ch_nbr){
756   int tt = 0;
757   while ( ppi_tasks_table[tt].task_addr != NULL ){
758     if ( ppi_tasks_table[tt].task_addr == TEP ){
759        *dest = ppi_tasks_table[tt].dest;
760        return;
761     }
762     tt++;
763   }
764   bs_trace_warning_line_time(
765       "NRF_PPI: The task %p for chnbr %i does not match any modelled task in NRF_PPI.c => it will be ignored\n",
766       TEP, ch_nbr);
767 
768   *dest = NULL;
769 }
770 
771 /**
772  * Update PPI internal routing status after a
773  * CH[<ch_nbr>].EEP update
774  */
nrf_ppi_regw_sideeffects_EEP(int ch_nbr)775 void nrf_ppi_regw_sideeffects_EEP(int ch_nbr){
776   //To save execution time when an event is raised, we build the
777   //ppi_event_config_table & ppi_channel_config_table out of the registers
778 
779   //first remove this channel from all events masks
780   for (int i = 0 ; i < NUMBER_PPI_EVENTS ; i++){
781     ppi_evt_to_ch[i].channels_mask &= ~( 1 << ch_nbr );
782   }
783 
784   //then lets try to find which event (if any) is feeding this channel
785   if ( ( ch_nbr < 20 ) && ( (void*)NRF_PPI_regs.CH[ch_nbr].EEP != NULL ) ){
786     int i = 0;
787     while ( ppi_events_table[i].event_type != NUMBER_PPI_EVENTS ){
788       if ( ppi_events_table[i].event_addr == (void*)NRF_PPI_regs.CH[ch_nbr].EEP ) {
789         ppi_evt_to_ch[ppi_events_table[i].event_type].channels_mask |= ( 1 << ch_nbr );
790         return;
791       }
792       i++;
793     }
794     bs_trace_warning_line_time(
795         "NRF_PPI: The event NRF_PPI_regs.CH[%i].EEP(=%p) does not match any modelled event in NRF_PPI.c=> it will be ignored\n",
796         ch_nbr, NRF_PPI_regs.CH[ch_nbr].EEP);
797   }
798 }
799 
800 /**
801  * Update PPI internal routing status after a
802  * CH[<ch_nbr>].TEP update
803  */
nrf_ppi_regw_sideeffects_TEP(int ch_nbr)804 void nrf_ppi_regw_sideeffects_TEP(int ch_nbr){
805   //To save execution time when an event is raised, we build the
806   //ppi_event_config_table & ppi_channel_config_table out of the registers
807   if ( ch_nbr < 20 ){
808     if ( (void*)NRF_PPI_regs.CH[ch_nbr].TEP != NULL ){
809       find_task((void*)NRF_PPI_regs.CH[ch_nbr].TEP,
810                 &ppi_ch_tasks[ch_nbr].tep_f,
811                 ch_nbr);
812     } else {
813       ppi_ch_tasks[ch_nbr].tep_f = NULL;
814     }
815   }
816 }
817 /**
818  * Update PPI internal routing status after a
819  * FORK[<ch_nbr>].TEP update
820  */
nrf_ppi_regw_sideeffects_FORK_TEP(int ch_nbr)821 void nrf_ppi_regw_sideeffects_FORK_TEP(int ch_nbr){
822   if ( (void*)NRF_PPI_regs.FORK[ch_nbr].TEP != NULL ){
823     find_task((void*)NRF_PPI_regs.FORK[ch_nbr].TEP,
824               &ppi_ch_tasks[ch_nbr].fork_tep_f,
825               ch_nbr);
826   } else {
827     ppi_ch_tasks[ch_nbr].fork_tep_f = NULL;
828   }
829 }
830 
831 /**
832  * Update PPI CHEN mask after a write to CHENSET
833  * (writes to CHEN do not need sideeffects)
834  */
nrf_ppi_regw_sideeffects_CHENSET(void)835 void nrf_ppi_regw_sideeffects_CHENSET(void) {
836 	if ( NRF_PPI_regs.CHENSET != 0 ){
837 		NRF_PPI_regs.CHEN |= NRF_PPI_regs.CHENSET;
838 		NRF_PPI_regs.CHENSET = 0;
839 	}
840 }
841 
842 /**
843  * Update PPI CHEN mask after a write to CHENCLR
844  * (writes to CHEN do not need sideeffects)
845  */
nrf_ppi_regw_sideeffects_CHENCLR(void)846 void nrf_ppi_regw_sideeffects_CHENCLR(void) {
847 	if ( NRF_PPI_regs.CHENCLR != 0 ){
848 		NRF_PPI_regs.CHEN &= ~NRF_PPI_regs.CHENCLR;
849 		NRF_PPI_regs.CHENCLR = 0;
850 	}
851 }
852 
853 /**
854  * Update PPI CHEN mask after a write to CHENSET or CHENCLR
855  * (writes to CHEN do not need sideeffects)
856  */
nrf_ppi_regw_sideeffects_CHEN(void)857 void nrf_ppi_regw_sideeffects_CHEN(void) {
858 	//Note that we do not let people read CHEN from the SET and CLR
859 	//registers
860 	nrf_ppi_regw_sideeffects_CHENSET();
861 	nrf_ppi_regw_sideeffects_CHENCLR();
862 }
863 
nrf_ppi_regw_sideeffects_TASKS_CHG_DIS(int i)864 void nrf_ppi_regw_sideeffects_TASKS_CHG_DIS(int i){
865 	if ( NRF_PPI_regs.TASKS_CHG[i].DIS ) {
866 		NRF_PPI_regs.TASKS_CHG[i].DIS = 0;
867 		nrf_ppi_TASK_CHG_ENDIS( i, false );
868 	}
869 }
870 
nrf_ppi_regw_sideeffects_TASKS_CHG_EN(int i)871 void nrf_ppi_regw_sideeffects_TASKS_CHG_EN(int i){
872 	if ( NRF_PPI_regs.TASKS_CHG[i].EN ) {
873 		NRF_PPI_regs.TASKS_CHG[i].EN = 0;
874 		nrf_ppi_TASK_CHG_ENDIS( i, true );
875 	}
876 }
877 
nrf_ppi_taskw_sideeffects(void)878 void nrf_ppi_taskw_sideeffects(void) {
879 	int i;
880 	for ( i = 0 ; i < 6 ; i++){
881 		nrf_ppi_regw_sideeffects_TASKS_CHG_DIS(i);
882 	}
883 	for ( i = 0 ; i < 6 ; i++){
884 		nrf_ppi_regw_sideeffects_TASKS_CHG_EN(i);
885 	}
886 }
887