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     { (void*)&NRF_CCM_regs.TASKS_RATEOVERRIDE , nhw_CCM_TASK_RATEOVERRIDE},
248 
249     //PPI:
250     { (void*)&NRF_PPI_regs.TASKS_CHG[0].EN,  nrf_ppi_TASK_CHG0_EN},
251     { (void*)&NRF_PPI_regs.TASKS_CHG[1].EN,  nrf_ppi_TASK_CHG1_EN},
252     { (void*)&NRF_PPI_regs.TASKS_CHG[2].EN,  nrf_ppi_TASK_CHG2_EN},
253     { (void*)&NRF_PPI_regs.TASKS_CHG[3].EN,  nrf_ppi_TASK_CHG3_EN},
254     { (void*)&NRF_PPI_regs.TASKS_CHG[4].EN,  nrf_ppi_TASK_CHG4_EN},
255     { (void*)&NRF_PPI_regs.TASKS_CHG[5].EN,  nrf_ppi_TASK_CHG5_EN},
256     { (void*)&NRF_PPI_regs.TASKS_CHG[0].DIS, nrf_ppi_TASK_CHG0_DIS},
257     { (void*)&NRF_PPI_regs.TASKS_CHG[1].DIS, nrf_ppi_TASK_CHG1_DIS},
258     { (void*)&NRF_PPI_regs.TASKS_CHG[2].DIS, nrf_ppi_TASK_CHG2_DIS},
259     { (void*)&NRF_PPI_regs.TASKS_CHG[3].DIS, nrf_ppi_TASK_CHG3_DIS},
260     { (void*)&NRF_PPI_regs.TASKS_CHG[4].DIS, nrf_ppi_TASK_CHG4_DIS},
261     { (void*)&NRF_PPI_regs.TASKS_CHG[5].DIS, nrf_ppi_TASK_CHG5_DIS},
262 
263     //EGU:
264     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[0] , nhw_egu_0_TASK_TRIGGER_0},
265     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[1] , nhw_egu_0_TASK_TRIGGER_1},
266     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[2] , nhw_egu_0_TASK_TRIGGER_2},
267     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[3] , nhw_egu_0_TASK_TRIGGER_3},
268     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[4] , nhw_egu_0_TASK_TRIGGER_4},
269     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[5] , nhw_egu_0_TASK_TRIGGER_5},
270     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[6] , nhw_egu_0_TASK_TRIGGER_6},
271     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[7] , nhw_egu_0_TASK_TRIGGER_7},
272     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[8] , nhw_egu_0_TASK_TRIGGER_8},
273     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[9] , nhw_egu_0_TASK_TRIGGER_9},
274     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[10] , nhw_egu_0_TASK_TRIGGER_10},
275     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[11] , nhw_egu_0_TASK_TRIGGER_11},
276     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[12] , nhw_egu_0_TASK_TRIGGER_12},
277     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[13] , nhw_egu_0_TASK_TRIGGER_13},
278     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[14] , nhw_egu_0_TASK_TRIGGER_14},
279     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[15] , nhw_egu_0_TASK_TRIGGER_15},
280     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[0] , nhw_egu_1_TASK_TRIGGER_0},
281     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[1] , nhw_egu_1_TASK_TRIGGER_1},
282     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[2] , nhw_egu_1_TASK_TRIGGER_2},
283     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[3] , nhw_egu_1_TASK_TRIGGER_3},
284     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[4] , nhw_egu_1_TASK_TRIGGER_4},
285     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[5] , nhw_egu_1_TASK_TRIGGER_5},
286     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[6] , nhw_egu_1_TASK_TRIGGER_6},
287     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[7] , nhw_egu_1_TASK_TRIGGER_7},
288     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[8] , nhw_egu_1_TASK_TRIGGER_8},
289     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[9] , nhw_egu_1_TASK_TRIGGER_9},
290     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[10] , nhw_egu_1_TASK_TRIGGER_10},
291     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[11] , nhw_egu_1_TASK_TRIGGER_11},
292     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[12] , nhw_egu_1_TASK_TRIGGER_12},
293     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[13] , nhw_egu_1_TASK_TRIGGER_13},
294     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[14] , nhw_egu_1_TASK_TRIGGER_14},
295     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[15] , nhw_egu_1_TASK_TRIGGER_15},
296     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[0] , nhw_egu_2_TASK_TRIGGER_0},
297     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[1] , nhw_egu_2_TASK_TRIGGER_1},
298     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[2] , nhw_egu_2_TASK_TRIGGER_2},
299     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[3] , nhw_egu_2_TASK_TRIGGER_3},
300     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[4] , nhw_egu_2_TASK_TRIGGER_4},
301     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[5] , nhw_egu_2_TASK_TRIGGER_5},
302     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[6] , nhw_egu_2_TASK_TRIGGER_6},
303     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[7] , nhw_egu_2_TASK_TRIGGER_7},
304     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[8] , nhw_egu_2_TASK_TRIGGER_8},
305     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[9] , nhw_egu_2_TASK_TRIGGER_9},
306     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[10] , nhw_egu_2_TASK_TRIGGER_10},
307     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[11] , nhw_egu_2_TASK_TRIGGER_11},
308     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[12] , nhw_egu_2_TASK_TRIGGER_12},
309     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[13] , nhw_egu_2_TASK_TRIGGER_13},
310     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[14] , nhw_egu_2_TASK_TRIGGER_14},
311     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[15] , nhw_egu_2_TASK_TRIGGER_15},
312     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[0] , nhw_egu_3_TASK_TRIGGER_0},
313     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[1] , nhw_egu_3_TASK_TRIGGER_1},
314     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[2] , nhw_egu_3_TASK_TRIGGER_2},
315     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[3] , nhw_egu_3_TASK_TRIGGER_3},
316     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[4] , nhw_egu_3_TASK_TRIGGER_4},
317     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[5] , nhw_egu_3_TASK_TRIGGER_5},
318     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[6] , nhw_egu_3_TASK_TRIGGER_6},
319     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[7] , nhw_egu_3_TASK_TRIGGER_7},
320     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[8] , nhw_egu_3_TASK_TRIGGER_8},
321     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[9] , nhw_egu_3_TASK_TRIGGER_9},
322     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[10] , nhw_egu_3_TASK_TRIGGER_10},
323     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[11] , nhw_egu_3_TASK_TRIGGER_11},
324     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[12] , nhw_egu_3_TASK_TRIGGER_12},
325     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[13] , nhw_egu_3_TASK_TRIGGER_13},
326     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[14] , nhw_egu_3_TASK_TRIGGER_14},
327     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[15] , nhw_egu_3_TASK_TRIGGER_15},
328     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[0] , nhw_egu_4_TASK_TRIGGER_0},
329     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[1] , nhw_egu_4_TASK_TRIGGER_1},
330     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[2] , nhw_egu_4_TASK_TRIGGER_2},
331     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[3] , nhw_egu_4_TASK_TRIGGER_3},
332     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[4] , nhw_egu_4_TASK_TRIGGER_4},
333     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[5] , nhw_egu_4_TASK_TRIGGER_5},
334     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[6] , nhw_egu_4_TASK_TRIGGER_6},
335     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[7] , nhw_egu_4_TASK_TRIGGER_7},
336     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[8] , nhw_egu_4_TASK_TRIGGER_8},
337     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[9] , nhw_egu_4_TASK_TRIGGER_9},
338     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[10] , nhw_egu_4_TASK_TRIGGER_10},
339     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[11] , nhw_egu_4_TASK_TRIGGER_11},
340     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[12] , nhw_egu_4_TASK_TRIGGER_12},
341     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[13] , nhw_egu_4_TASK_TRIGGER_13},
342     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[14] , nhw_egu_4_TASK_TRIGGER_14},
343     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[15] , nhw_egu_4_TASK_TRIGGER_15},
344     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[0] , nhw_egu_5_TASK_TRIGGER_0},
345     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[1] , nhw_egu_5_TASK_TRIGGER_1},
346     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[2] , nhw_egu_5_TASK_TRIGGER_2},
347     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[3] , nhw_egu_5_TASK_TRIGGER_3},
348     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[4] , nhw_egu_5_TASK_TRIGGER_4},
349     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[5] , nhw_egu_5_TASK_TRIGGER_5},
350     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[6] , nhw_egu_5_TASK_TRIGGER_6},
351     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[7] , nhw_egu_5_TASK_TRIGGER_7},
352     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[8] , nhw_egu_5_TASK_TRIGGER_8},
353     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[9] , nhw_egu_5_TASK_TRIGGER_9},
354     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[10] , nhw_egu_5_TASK_TRIGGER_10},
355     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[11] , nhw_egu_5_TASK_TRIGGER_11},
356     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[12] , nhw_egu_5_TASK_TRIGGER_12},
357     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[13] , nhw_egu_5_TASK_TRIGGER_13},
358     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[14] , nhw_egu_5_TASK_TRIGGER_14},
359     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[15] , nhw_egu_5_TASK_TRIGGER_15},
360 
361     //End marker
362     { NULL, NULL }
363 };
364 
365 /**
366  * Table to convert from an event_address as programmed by the SW into an
367  * event_type used here to index tables
368  */
369 typedef struct {
370   ppi_event_types_t event_type;
371   void *event_addr;
372 } ppi_event_table_t;
373 
374 static const ppi_event_table_t ppi_events_table[] = { //better keep same order as in ppi_event_types_t
375     {CLOCK_EVENTS_HFCLKSTARTED, &NRF_CLKPWR_regs[0].CLK.EVENTS_HFCLKSTARTED},
376     {CLOCK_EVENTS_LFCLKSTARTED, &NRF_CLKPWR_regs[0].CLK.EVENTS_LFCLKSTARTED},
377     {CLOCK_EVENTS_DONE        , &NRF_CLKPWR_regs[0].CLK.EVENTS_DONE        },
378     {CLOCK_EVENTS_CTTO        , &NRF_CLKPWR_regs[0].CLK.EVENTS_CTTO        },
379     {CLOCK_EVENTS_CTSTARTED   , &NRF_CLKPWR_regs[0].CLK.EVENTS_CTSTARTED   },
380     {CLOCK_EVENTS_CTSTOPPED   , &NRF_CLKPWR_regs[0].CLK.EVENTS_CTSTOPPED   },
381 
382     {RADIO_EVENTS_READY,   &NRF_RADIO_regs.EVENTS_READY},
383     {RADIO_EVENTS_ADDRESS, &NRF_RADIO_regs.EVENTS_ADDRESS},
384     {RADIO_EVENTS_PAYLOAD, &NRF_RADIO_regs.EVENTS_PAYLOAD},
385     {RADIO_EVENTS_END,     &NRF_RADIO_regs.EVENTS_END},
386     {RADIO_EVENTS_DISABLED,&NRF_RADIO_regs.EVENTS_DISABLED},
387     {RADIO_EVENTS_DEVMATCH,&NRF_RADIO_regs.EVENTS_DEVMATCH},
388     {RADIO_EVENTS_DEVMISS ,&NRF_RADIO_regs.EVENTS_DEVMISS},
389     {RADIO_EVENTS_RSSIEND, &NRF_RADIO_regs.EVENTS_RSSIEND},
390     {RADIO_EVENTS_BCMATCH, &NRF_RADIO_regs.EVENTS_BCMATCH},
391     {RADIO_EVENTS_CRCOK,   &NRF_RADIO_regs.EVENTS_CRCOK},
392     {RADIO_EVENTS_CRCERROR,&NRF_RADIO_regs.EVENTS_CRCERROR},
393     {RADIO_EVENTS_FRAMESTART,&NRF_RADIO_regs.EVENTS_FRAMESTART},
394     {RADIO_EVENTS_EDEND,   &NRF_RADIO_regs.EVENTS_EDEND},
395     {RADIO_EVENTS_EDSTOPPED, &NRF_RADIO_regs.EVENTS_EDSTOPPED},
396     {RADIO_EVENTS_CCAIDLE, &NRF_RADIO_regs.EVENTS_CCAIDLE},
397     {RADIO_EVENTS_CCABUSY, &NRF_RADIO_regs.EVENTS_CCABUSY},
398     {RADIO_EVENTS_CCASTOPPED, &NRF_RADIO_regs.EVENTS_CCASTOPPED},
399     {RADIO_EVENTS_RATEBOOST, &NRF_RADIO_regs.EVENTS_RATEBOOST},
400     {RADIO_EVENTS_TXREADY, &NRF_RADIO_regs.EVENTS_TXREADY},
401     {RADIO_EVENTS_RXREADY, &NRF_RADIO_regs.EVENTS_RXREADY},
402     {RADIO_EVENTS_MHRMATCH,&NRF_RADIO_regs.EVENTS_MHRMATCH},
403     {RADIO_EVENTS_SYNC,    &NRF_RADIO_regs.EVENTS_SYNC},
404     {RADIO_EVENTS_PHYEND,  &NRF_RADIO_regs.EVENTS_PHYEND},
405     {RADIO_EVENTS_CTEPRESENT,&NRF_RADIO_regs.EVENTS_CTEPRESENT},
406 
407     {UARTE0_EVENTS_CTS      , &NRF_UARTE_regs[0].EVENTS_CTS      },
408     {UARTE0_EVENTS_NCTS     , &NRF_UARTE_regs[0].EVENTS_NCTS     },
409     {UARTE0_EVENTS_RXDRDY   , &NRF_UARTE_regs[0].EVENTS_RXDRDY   },
410     {UARTE0_EVENTS_ENDRX    , &NRF_UARTE_regs[0].EVENTS_ENDRX    },
411     {UARTE0_EVENTS_TXDRDY   , &NRF_UARTE_regs[0].EVENTS_TXDRDY   },
412     {UARTE0_EVENTS_ENDTX    , &NRF_UARTE_regs[0].EVENTS_ENDTX    },
413     {UARTE0_EVENTS_ERROR    , &NRF_UARTE_regs[0].EVENTS_ERROR    },
414     {UARTE0_EVENTS_RXTO     , &NRF_UARTE_regs[0].EVENTS_RXTO     },
415     {UARTE0_EVENTS_RXSTARTED, &NRF_UARTE_regs[0].EVENTS_RXSTARTED},
416     {UARTE0_EVENTS_TXSTARTED, &NRF_UARTE_regs[0].EVENTS_TXSTARTED},
417     {UARTE0_EVENTS_TXSTOPPED, &NRF_UARTE_regs[0].EVENTS_TXSTOPPED},
418 
419     {GPIOTE_EVENTS_IN_0, &NRF_GPIOTE_regs.EVENTS_IN[0]},
420     {GPIOTE_EVENTS_IN_1, &NRF_GPIOTE_regs.EVENTS_IN[1]},
421     {GPIOTE_EVENTS_IN_2, &NRF_GPIOTE_regs.EVENTS_IN[2]},
422     {GPIOTE_EVENTS_IN_3, &NRF_GPIOTE_regs.EVENTS_IN[3]},
423     {GPIOTE_EVENTS_IN_4, &NRF_GPIOTE_regs.EVENTS_IN[4]},
424     {GPIOTE_EVENTS_IN_5, &NRF_GPIOTE_regs.EVENTS_IN[5]},
425     {GPIOTE_EVENTS_IN_6, &NRF_GPIOTE_regs.EVENTS_IN[6]},
426     {GPIOTE_EVENTS_IN_7, &NRF_GPIOTE_regs.EVENTS_IN[7]},
427     {GPIOTE_EVENTS_PORT, &NRF_GPIOTE_regs.EVENTS_PORT},
428 
429     {TIMER0_EVENTS_COMPARE_0, &NRF_TIMER_regs[0].EVENTS_COMPARE[0]},
430     {TIMER0_EVENTS_COMPARE_1, &NRF_TIMER_regs[0].EVENTS_COMPARE[1]},
431     {TIMER0_EVENTS_COMPARE_2, &NRF_TIMER_regs[0].EVENTS_COMPARE[2]},
432     {TIMER0_EVENTS_COMPARE_3, &NRF_TIMER_regs[0].EVENTS_COMPARE[3]},
433 //    {TIMER0_EVENTS_COMPARE_4, &NRF_TIMER_regs[0].EVENTS_COMPARE[4]},
434 //    {TIMER0_EVENTS_COMPARE_5, &NRF_TIMER_regs[0].EVENTS_COMPARE[5]},
435 
436     {TIMER1_EVENTS_COMPARE_0, &NRF_TIMER_regs[1].EVENTS_COMPARE[0]},
437     {TIMER1_EVENTS_COMPARE_1, &NRF_TIMER_regs[1].EVENTS_COMPARE[1]},
438     {TIMER1_EVENTS_COMPARE_2, &NRF_TIMER_regs[1].EVENTS_COMPARE[2]},
439     {TIMER1_EVENTS_COMPARE_3, &NRF_TIMER_regs[1].EVENTS_COMPARE[3]},
440     //    {TIMER1_EVENTS_COMPARE_4, &NRF_TIMER_regs[1].EVENTS_COMPARE[4]},
441     //    {TIMER1_EVENTS_COMPARE_5, &NRF_TIMER_regs[1].EVENTS_COMPARE[5]},
442 
443     {TIMER2_EVENTS_COMPARE_0, &NRF_TIMER_regs[2].EVENTS_COMPARE[0]},
444     {TIMER2_EVENTS_COMPARE_1, &NRF_TIMER_regs[2].EVENTS_COMPARE[1]},
445     {TIMER2_EVENTS_COMPARE_2, &NRF_TIMER_regs[2].EVENTS_COMPARE[2]},
446     {TIMER2_EVENTS_COMPARE_3, &NRF_TIMER_regs[2].EVENTS_COMPARE[3]},
447     //    {TIMER2_EVENTS_COMPARE_4, &NRF_TIMER_regs[2].EVENTS_COMPARE[4]},
448     //    {TIMER2_EVENTS_COMPARE_5, &NRF_TIMER_regs[2].EVENTS_COMPARE[5]},
449 
450     {RTC0_EVENTS_OVRFLW, &NRF_RTC_regs[0].EVENTS_OVRFLW},
451     {RTC0_EVENTS_COMPARE_0, &NRF_RTC_regs[0].EVENTS_COMPARE[0]},
452     {RTC0_EVENTS_COMPARE_1, &NRF_RTC_regs[0].EVENTS_COMPARE[1]},
453     {RTC0_EVENTS_COMPARE_2, &NRF_RTC_regs[0].EVENTS_COMPARE[2]},
454     {RTC0_EVENTS_COMPARE_3, &NRF_RTC_regs[0].EVENTS_COMPARE[3]},
455 
456     {TEMP_EVENTS_DATARDY, &NRF_TEMP_regs.EVENTS_DATARDY},
457 
458     //{RNG_EVENTS_VALRDY, &NRF_RNG_regs.EVENTS_VALRDY},
459 
460     {CCM_EVENTS_ENDKSGEN, &NRF_CCM_regs.EVENTS_ENDKSGEN},
461     {CCM_EVENTS_ENDCRYPT, &NRF_CCM_regs.EVENTS_ENDCRYPT},
462     {CCM_EVENTS_ERROR,    &NRF_CCM_regs.EVENTS_ERROR},
463 
464     {RTC1_EVENTS_OVRFLW, &NRF_RTC_regs[1].EVENTS_OVRFLW},
465     {RTC1_EVENTS_COMPARE_0, &NRF_RTC_regs[1].EVENTS_COMPARE[0]},
466     {RTC1_EVENTS_COMPARE_1, &NRF_RTC_regs[1].EVENTS_COMPARE[1]},
467     {RTC1_EVENTS_COMPARE_2, &NRF_RTC_regs[1].EVENTS_COMPARE[2]},
468     {RTC1_EVENTS_COMPARE_3, &NRF_RTC_regs[1].EVENTS_COMPARE[3]},
469 
470     {EGU0_EVENTS_TRIGGERED_0, &NRF_EGU_regs[0].EVENTS_TRIGGERED[0]}, /*These are autogenerated (See NRF_EGU.c)*/
471     {EGU0_EVENTS_TRIGGERED_1, &NRF_EGU_regs[0].EVENTS_TRIGGERED[1]},
472     {EGU0_EVENTS_TRIGGERED_2, &NRF_EGU_regs[0].EVENTS_TRIGGERED[2]},
473     {EGU0_EVENTS_TRIGGERED_3, &NRF_EGU_regs[0].EVENTS_TRIGGERED[3]},
474     {EGU0_EVENTS_TRIGGERED_4, &NRF_EGU_regs[0].EVENTS_TRIGGERED[4]},
475     {EGU0_EVENTS_TRIGGERED_5, &NRF_EGU_regs[0].EVENTS_TRIGGERED[5]},
476     {EGU0_EVENTS_TRIGGERED_6, &NRF_EGU_regs[0].EVENTS_TRIGGERED[6]},
477     {EGU0_EVENTS_TRIGGERED_7, &NRF_EGU_regs[0].EVENTS_TRIGGERED[7]},
478     {EGU0_EVENTS_TRIGGERED_8, &NRF_EGU_regs[0].EVENTS_TRIGGERED[8]},
479     {EGU0_EVENTS_TRIGGERED_9, &NRF_EGU_regs[0].EVENTS_TRIGGERED[9]},
480     {EGU0_EVENTS_TRIGGERED_10, &NRF_EGU_regs[0].EVENTS_TRIGGERED[10]},
481     {EGU0_EVENTS_TRIGGERED_11, &NRF_EGU_regs[0].EVENTS_TRIGGERED[11]},
482     {EGU0_EVENTS_TRIGGERED_12, &NRF_EGU_regs[0].EVENTS_TRIGGERED[12]},
483     {EGU0_EVENTS_TRIGGERED_13, &NRF_EGU_regs[0].EVENTS_TRIGGERED[13]},
484     {EGU0_EVENTS_TRIGGERED_14, &NRF_EGU_regs[0].EVENTS_TRIGGERED[14]},
485     {EGU0_EVENTS_TRIGGERED_15, &NRF_EGU_regs[0].EVENTS_TRIGGERED[15]},
486     {EGU1_EVENTS_TRIGGERED_0, &NRF_EGU_regs[1].EVENTS_TRIGGERED[0]},
487     {EGU1_EVENTS_TRIGGERED_1, &NRF_EGU_regs[1].EVENTS_TRIGGERED[1]},
488     {EGU1_EVENTS_TRIGGERED_2, &NRF_EGU_regs[1].EVENTS_TRIGGERED[2]},
489     {EGU1_EVENTS_TRIGGERED_3, &NRF_EGU_regs[1].EVENTS_TRIGGERED[3]},
490     {EGU1_EVENTS_TRIGGERED_4, &NRF_EGU_regs[1].EVENTS_TRIGGERED[4]},
491     {EGU1_EVENTS_TRIGGERED_5, &NRF_EGU_regs[1].EVENTS_TRIGGERED[5]},
492     {EGU1_EVENTS_TRIGGERED_6, &NRF_EGU_regs[1].EVENTS_TRIGGERED[6]},
493     {EGU1_EVENTS_TRIGGERED_7, &NRF_EGU_regs[1].EVENTS_TRIGGERED[7]},
494     {EGU1_EVENTS_TRIGGERED_8, &NRF_EGU_regs[1].EVENTS_TRIGGERED[8]},
495     {EGU1_EVENTS_TRIGGERED_9, &NRF_EGU_regs[1].EVENTS_TRIGGERED[9]},
496     {EGU1_EVENTS_TRIGGERED_10, &NRF_EGU_regs[1].EVENTS_TRIGGERED[10]},
497     {EGU1_EVENTS_TRIGGERED_11, &NRF_EGU_regs[1].EVENTS_TRIGGERED[11]},
498     {EGU1_EVENTS_TRIGGERED_12, &NRF_EGU_regs[1].EVENTS_TRIGGERED[12]},
499     {EGU1_EVENTS_TRIGGERED_13, &NRF_EGU_regs[1].EVENTS_TRIGGERED[13]},
500     {EGU1_EVENTS_TRIGGERED_14, &NRF_EGU_regs[1].EVENTS_TRIGGERED[14]},
501     {EGU1_EVENTS_TRIGGERED_15, &NRF_EGU_regs[1].EVENTS_TRIGGERED[15]},
502     {EGU2_EVENTS_TRIGGERED_0, &NRF_EGU_regs[2].EVENTS_TRIGGERED[0]},
503     {EGU2_EVENTS_TRIGGERED_1, &NRF_EGU_regs[2].EVENTS_TRIGGERED[1]},
504     {EGU2_EVENTS_TRIGGERED_2, &NRF_EGU_regs[2].EVENTS_TRIGGERED[2]},
505     {EGU2_EVENTS_TRIGGERED_3, &NRF_EGU_regs[2].EVENTS_TRIGGERED[3]},
506     {EGU2_EVENTS_TRIGGERED_4, &NRF_EGU_regs[2].EVENTS_TRIGGERED[4]},
507     {EGU2_EVENTS_TRIGGERED_5, &NRF_EGU_regs[2].EVENTS_TRIGGERED[5]},
508     {EGU2_EVENTS_TRIGGERED_6, &NRF_EGU_regs[2].EVENTS_TRIGGERED[6]},
509     {EGU2_EVENTS_TRIGGERED_7, &NRF_EGU_regs[2].EVENTS_TRIGGERED[7]},
510     {EGU2_EVENTS_TRIGGERED_8, &NRF_EGU_regs[2].EVENTS_TRIGGERED[8]},
511     {EGU2_EVENTS_TRIGGERED_9, &NRF_EGU_regs[2].EVENTS_TRIGGERED[9]},
512     {EGU2_EVENTS_TRIGGERED_10, &NRF_EGU_regs[2].EVENTS_TRIGGERED[10]},
513     {EGU2_EVENTS_TRIGGERED_11, &NRF_EGU_regs[2].EVENTS_TRIGGERED[11]},
514     {EGU2_EVENTS_TRIGGERED_12, &NRF_EGU_regs[2].EVENTS_TRIGGERED[12]},
515     {EGU2_EVENTS_TRIGGERED_13, &NRF_EGU_regs[2].EVENTS_TRIGGERED[13]},
516     {EGU2_EVENTS_TRIGGERED_14, &NRF_EGU_regs[2].EVENTS_TRIGGERED[14]},
517     {EGU2_EVENTS_TRIGGERED_15, &NRF_EGU_regs[2].EVENTS_TRIGGERED[15]},
518     {EGU3_EVENTS_TRIGGERED_0, &NRF_EGU_regs[3].EVENTS_TRIGGERED[0]},
519     {EGU3_EVENTS_TRIGGERED_1, &NRF_EGU_regs[3].EVENTS_TRIGGERED[1]},
520     {EGU3_EVENTS_TRIGGERED_2, &NRF_EGU_regs[3].EVENTS_TRIGGERED[2]},
521     {EGU3_EVENTS_TRIGGERED_3, &NRF_EGU_regs[3].EVENTS_TRIGGERED[3]},
522     {EGU3_EVENTS_TRIGGERED_4, &NRF_EGU_regs[3].EVENTS_TRIGGERED[4]},
523     {EGU3_EVENTS_TRIGGERED_5, &NRF_EGU_regs[3].EVENTS_TRIGGERED[5]},
524     {EGU3_EVENTS_TRIGGERED_6, &NRF_EGU_regs[3].EVENTS_TRIGGERED[6]},
525     {EGU3_EVENTS_TRIGGERED_7, &NRF_EGU_regs[3].EVENTS_TRIGGERED[7]},
526     {EGU3_EVENTS_TRIGGERED_8, &NRF_EGU_regs[3].EVENTS_TRIGGERED[8]},
527     {EGU3_EVENTS_TRIGGERED_9, &NRF_EGU_regs[3].EVENTS_TRIGGERED[9]},
528     {EGU3_EVENTS_TRIGGERED_10, &NRF_EGU_regs[3].EVENTS_TRIGGERED[10]},
529     {EGU3_EVENTS_TRIGGERED_11, &NRF_EGU_regs[3].EVENTS_TRIGGERED[11]},
530     {EGU3_EVENTS_TRIGGERED_12, &NRF_EGU_regs[3].EVENTS_TRIGGERED[12]},
531     {EGU3_EVENTS_TRIGGERED_13, &NRF_EGU_regs[3].EVENTS_TRIGGERED[13]},
532     {EGU3_EVENTS_TRIGGERED_14, &NRF_EGU_regs[3].EVENTS_TRIGGERED[14]},
533     {EGU3_EVENTS_TRIGGERED_15, &NRF_EGU_regs[3].EVENTS_TRIGGERED[15]},
534     {EGU4_EVENTS_TRIGGERED_0, &NRF_EGU_regs[4].EVENTS_TRIGGERED[0]},
535     {EGU4_EVENTS_TRIGGERED_1, &NRF_EGU_regs[4].EVENTS_TRIGGERED[1]},
536     {EGU4_EVENTS_TRIGGERED_2, &NRF_EGU_regs[4].EVENTS_TRIGGERED[2]},
537     {EGU4_EVENTS_TRIGGERED_3, &NRF_EGU_regs[4].EVENTS_TRIGGERED[3]},
538     {EGU4_EVENTS_TRIGGERED_4, &NRF_EGU_regs[4].EVENTS_TRIGGERED[4]},
539     {EGU4_EVENTS_TRIGGERED_5, &NRF_EGU_regs[4].EVENTS_TRIGGERED[5]},
540     {EGU4_EVENTS_TRIGGERED_6, &NRF_EGU_regs[4].EVENTS_TRIGGERED[6]},
541     {EGU4_EVENTS_TRIGGERED_7, &NRF_EGU_regs[4].EVENTS_TRIGGERED[7]},
542     {EGU4_EVENTS_TRIGGERED_8, &NRF_EGU_regs[4].EVENTS_TRIGGERED[8]},
543     {EGU4_EVENTS_TRIGGERED_9, &NRF_EGU_regs[4].EVENTS_TRIGGERED[9]},
544     {EGU4_EVENTS_TRIGGERED_10, &NRF_EGU_regs[4].EVENTS_TRIGGERED[10]},
545     {EGU4_EVENTS_TRIGGERED_11, &NRF_EGU_regs[4].EVENTS_TRIGGERED[11]},
546     {EGU4_EVENTS_TRIGGERED_12, &NRF_EGU_regs[4].EVENTS_TRIGGERED[12]},
547     {EGU4_EVENTS_TRIGGERED_13, &NRF_EGU_regs[4].EVENTS_TRIGGERED[13]},
548     {EGU4_EVENTS_TRIGGERED_14, &NRF_EGU_regs[4].EVENTS_TRIGGERED[14]},
549     {EGU4_EVENTS_TRIGGERED_15, &NRF_EGU_regs[4].EVENTS_TRIGGERED[15]},
550     {EGU5_EVENTS_TRIGGERED_0, &NRF_EGU_regs[5].EVENTS_TRIGGERED[0]},
551     {EGU5_EVENTS_TRIGGERED_1, &NRF_EGU_regs[5].EVENTS_TRIGGERED[1]},
552     {EGU5_EVENTS_TRIGGERED_2, &NRF_EGU_regs[5].EVENTS_TRIGGERED[2]},
553     {EGU5_EVENTS_TRIGGERED_3, &NRF_EGU_regs[5].EVENTS_TRIGGERED[3]},
554     {EGU5_EVENTS_TRIGGERED_4, &NRF_EGU_regs[5].EVENTS_TRIGGERED[4]},
555     {EGU5_EVENTS_TRIGGERED_5, &NRF_EGU_regs[5].EVENTS_TRIGGERED[5]},
556     {EGU5_EVENTS_TRIGGERED_6, &NRF_EGU_regs[5].EVENTS_TRIGGERED[6]},
557     {EGU5_EVENTS_TRIGGERED_7, &NRF_EGU_regs[5].EVENTS_TRIGGERED[7]},
558     {EGU5_EVENTS_TRIGGERED_8, &NRF_EGU_regs[5].EVENTS_TRIGGERED[8]},
559     {EGU5_EVENTS_TRIGGERED_9, &NRF_EGU_regs[5].EVENTS_TRIGGERED[9]},
560     {EGU5_EVENTS_TRIGGERED_10, &NRF_EGU_regs[5].EVENTS_TRIGGERED[10]},
561     {EGU5_EVENTS_TRIGGERED_11, &NRF_EGU_regs[5].EVENTS_TRIGGERED[11]},
562     {EGU5_EVENTS_TRIGGERED_12, &NRF_EGU_regs[5].EVENTS_TRIGGERED[12]},
563     {EGU5_EVENTS_TRIGGERED_13, &NRF_EGU_regs[5].EVENTS_TRIGGERED[13]},
564     {EGU5_EVENTS_TRIGGERED_14, &NRF_EGU_regs[5].EVENTS_TRIGGERED[14]},
565     {EGU5_EVENTS_TRIGGERED_15, &NRF_EGU_regs[5].EVENTS_TRIGGERED[15]},
566 
567     {TIMER3_EVENTS_COMPARE_0, &NRF_TIMER_regs[3].EVENTS_COMPARE[0]},
568     {TIMER3_EVENTS_COMPARE_1, &NRF_TIMER_regs[3].EVENTS_COMPARE[1]},
569     {TIMER3_EVENTS_COMPARE_2, &NRF_TIMER_regs[3].EVENTS_COMPARE[2]},
570     {TIMER3_EVENTS_COMPARE_3, &NRF_TIMER_regs[3].EVENTS_COMPARE[3]},
571     {TIMER3_EVENTS_COMPARE_4, &NRF_TIMER_regs[3].EVENTS_COMPARE[4]},
572     {TIMER3_EVENTS_COMPARE_5, &NRF_TIMER_regs[3].EVENTS_COMPARE[5]},
573 
574     {TIMER4_EVENTS_COMPARE_0, &NRF_TIMER_regs[4].EVENTS_COMPARE[0]},
575     {TIMER4_EVENTS_COMPARE_1, &NRF_TIMER_regs[4].EVENTS_COMPARE[1]},
576     {TIMER4_EVENTS_COMPARE_2, &NRF_TIMER_regs[4].EVENTS_COMPARE[2]},
577     {TIMER4_EVENTS_COMPARE_3, &NRF_TIMER_regs[4].EVENTS_COMPARE[3]},
578     {TIMER4_EVENTS_COMPARE_4, &NRF_TIMER_regs[4].EVENTS_COMPARE[4]},
579     {TIMER4_EVENTS_COMPARE_5, &NRF_TIMER_regs[4].EVENTS_COMPARE[5]},
580 
581     {RTC2_EVENTS_OVRFLW, &NRF_RTC_regs[2].EVENTS_OVRFLW},
582     {RTC2_EVENTS_COMPARE_0, &NRF_RTC_regs[2].EVENTS_COMPARE[0]},
583     {RTC2_EVENTS_COMPARE_1, &NRF_RTC_regs[2].EVENTS_COMPARE[1]},
584     {RTC2_EVENTS_COMPARE_2, &NRF_RTC_regs[2].EVENTS_COMPARE[2]},
585     {RTC2_EVENTS_COMPARE_3, &NRF_RTC_regs[2].EVENTS_COMPARE[3]},
586 
587     {UARTE1_EVENTS_CTS      , &NRF_UARTE_regs[1].EVENTS_CTS      },
588     {UARTE1_EVENTS_NCTS     , &NRF_UARTE_regs[1].EVENTS_NCTS     },
589     {UARTE1_EVENTS_RXDRDY   , &NRF_UARTE_regs[1].EVENTS_RXDRDY   },
590     {UARTE1_EVENTS_ENDRX    , &NRF_UARTE_regs[1].EVENTS_ENDRX    },
591     {UARTE1_EVENTS_TXDRDY   , &NRF_UARTE_regs[1].EVENTS_TXDRDY   },
592     {UARTE1_EVENTS_ENDTX    , &NRF_UARTE_regs[1].EVENTS_ENDTX    },
593     {UARTE1_EVENTS_ERROR    , &NRF_UARTE_regs[1].EVENTS_ERROR    },
594     {UARTE1_EVENTS_RXTO     , &NRF_UARTE_regs[1].EVENTS_RXTO     },
595     {UARTE1_EVENTS_RXSTARTED, &NRF_UARTE_regs[1].EVENTS_RXSTARTED},
596     {UARTE1_EVENTS_TXSTARTED, &NRF_UARTE_regs[1].EVENTS_TXSTARTED},
597     {UARTE1_EVENTS_TXSTOPPED, &NRF_UARTE_regs[1].EVENTS_TXSTOPPED},
598 
599     {NUMBER_PPI_EVENTS, NULL} //End marker
600 };
601 
602 
set_fixed_channel_routes(void)603 static void set_fixed_channel_routes(void) {
604   //TODO: add handler function pointers as we add those functions while modelling the different parts
605 
606   //Set the fixed channels configuration:
607   //  20 TIMER0->EVENTS_COMPARE[0] RADIO->TASKS_TXEN
608     ppi_evt_to_ch[TIMER0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 20 );
609     ppi_ch_tasks[20].tep_f = nhw_RADIO_TASK_TXEN; //RADIO->TASKS_TXEN
610 
611   //  21 TIMER0->EVENTS_COMPARE[0] RADIO->TASKS_RXEN
612     ppi_evt_to_ch[TIMER0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 21 );
613     ppi_ch_tasks[21].tep_f = nhw_RADIO_TASK_RXEN; //RADIO->TASKS_RXEN
614 
615   //  22 TIMER0->EVENTS_COMPARE[1] RADIO->TASKS_DISABLE
616     ppi_evt_to_ch[TIMER0_EVENTS_COMPARE_1].channels_mask |= ( 1 << 22 );
617     ppi_ch_tasks[22].tep_f = nhw_RADIO_TASK_DISABLE; //RADIO->TASKS_DISABLE
618 
619   //  23 RADIO->EVENTS_BCMATCH AAR->TASKS_START
620     ppi_evt_to_ch[RADIO_EVENTS_BCMATCH].channels_mask |= ( 1 << 23 );
621     ppi_ch_tasks[23].tep_f = nhw_AAR_TASK_START; //AAR->TASKS_START
622 
623   //  24 RADIO->EVENTS_READY CCM->TASKS_KSGEN
624     ppi_evt_to_ch[RADIO_EVENTS_READY].channels_mask |= ( 1 << 24 );
625     ppi_ch_tasks[24].tep_f = nhw_CCM_TASK_KSGEN; //CCM->TASKS_KSGEN
626 
627   //  25 RADIO->EVENTS_ADDRESS CCM->TASKS_CRYPT
628     ppi_evt_to_ch[RADIO_EVENTS_ADDRESS].channels_mask |= ( 1 << 25 );
629     ppi_ch_tasks[25].tep_f = nhw_CCM_TASK_CRYPT; //CCM->TASKS_CRYPT
630 
631   //  26 RADIO->EVENTS_ADDRESS TIMER0->TASKS_CAPTURE[1]
632     ppi_evt_to_ch[RADIO_EVENTS_ADDRESS].channels_mask |= ( 1 << 26 );
633     ppi_ch_tasks[26].tep_f = nhw_timer0_TASK_CAPTURE_1; //TIMER0->TASKS_CAPTURE[1]
634 
635   //  27 RADIO->EVENTS_END TIMER0->TASKS_CAPTURE[2]
636     ppi_evt_to_ch[RADIO_EVENTS_END].channels_mask |= ( 1 << 27 );
637     ppi_ch_tasks[27].tep_f = nhw_timer0_TASK_CAPTURE_2; //TIMER0->TASKS_CAPTURE[2]
638 
639   //  28 RTC0->EVENTS_COMPARE[0] RADIO->TASKS_TXEN
640     ppi_evt_to_ch[RTC0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 28 );
641     ppi_ch_tasks[28].tep_f = nhw_RADIO_TASK_TXEN; //RADIO->TASKS_TXEN
642 
643   //  29 RTC0->EVENTS_COMPARE[0] RADIO->TASKS_RXEN
644     ppi_evt_to_ch[RTC0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 29 );
645     ppi_ch_tasks[29].tep_f = nhw_RADIO_TASK_RXEN; //RADIO->TASKS_RXEN
646 
647   //  30 RTC0->EVENTS_COMPARE[0] TIMER0->TASKS_CLEAR
648     ppi_evt_to_ch[RTC0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 30 );
649     ppi_ch_tasks[30].tep_f = nhw_timer0_TASK_CLEAR; //TIMER0->TASKS_CLEAR
650 
651   //  31 RTC0->EVENTS_COMPARE[0] TIMER0->TASKS_START
652     ppi_evt_to_ch[RTC0_EVENTS_COMPARE_0].channels_mask |= ( (uint32_t)1 << 31 );
653     ppi_ch_tasks[31].tep_f = nhw_timer0_TASK_START; //TIMER0->TASKS_START
654 }
655 
656 /*
657  * When an event comes, we first queue all tasks that would be triggered in tasks_queue,
658  * and then trigger them.
659  * We do this to filter out duplicate tasks caused by the same event,
660  * as this is a use case
661  */
662 volatile static struct {
663   dest_f_t* q;
664   uint used;
665   uint size;
666 } tasks_queue;
667 #define TASK_QUEUE_ALLOC_SIZE 64
668 
669 
670 /**
671  * Initialize the PPI model
672  */
nrf_ppi_init(void)673 static void nrf_ppi_init(void) {
674   memset(&NRF_PPI_regs, 0, sizeof(NRF_PPI_regs));
675   memset(ppi_ch_tasks, 0, sizeof(ppi_ch_tasks));
676   memset(ppi_evt_to_ch, 0, sizeof(ppi_evt_to_ch));
677   set_fixed_channel_routes();
678   tasks_queue.q = (dest_f_t*)bs_calloc(TASK_QUEUE_ALLOC_SIZE, sizeof(dest_f_t));
679   tasks_queue.size = TASK_QUEUE_ALLOC_SIZE;
680 }
681 
682 NSI_TASK(nrf_ppi_init, HW_INIT, 50);
683 
684 /**
685  * Cleanup the PPI model before exiting the program
686  */
nrf_ppi_clean_up(void)687 static void nrf_ppi_clean_up(void) {
688   if (tasks_queue.q) {
689     free(tasks_queue.q);
690     tasks_queue.q = NULL;
691   }
692 }
693 
694 NSI_TASK(nrf_ppi_clean_up, ON_EXIT_PRE, 50);
695 
nrf_ppi_enqueue_task(dest_f_t task)696 static void nrf_ppi_enqueue_task(dest_f_t task) {
697   int i;
698   for (i = 0; i < tasks_queue.used; i++){
699     if (tasks_queue.q[i] == task){ //We ignore dups
700       return;
701     }
702   }
703 
704   if (tasks_queue.used >= tasks_queue.size) {
705     tasks_queue.size += TASK_QUEUE_ALLOC_SIZE;
706     tasks_queue.q = bs_realloc(tasks_queue.q, tasks_queue.size*sizeof(dest_f_t));
707   }
708   tasks_queue.q[tasks_queue.used++] = task;
709 }
710 
nrf_ppi_dequeue_all_tasks(void)711 static void nrf_ppi_dequeue_all_tasks(void) {
712   int i;
713   for (i = 0; i < tasks_queue.used; i++) {
714     if (tasks_queue.q[i]) {
715       dest_f_t f = tasks_queue.q[i];
716       tasks_queue.q[i] = NULL;
717       f();
718     }
719   }
720   tasks_queue.used = 0;
721 }
722 
723 /**
724  * HW models call this function when they want to signal an event which
725  * may trigger a task
726  */
nrf_ppi_event(ppi_event_types_t event)727 void nrf_ppi_event(ppi_event_types_t event){
728 
729   uint32_t ch_mask = ppi_evt_to_ch[event].channels_mask;
730   ch_mask &= NRF_PPI_regs.CHEN;
731 
732   if ( ch_mask ){
733     for ( int ch_nbr = __builtin_ffs(ch_mask) - 1;
734           ( ch_mask != 0 ) && ( ch_nbr < NUMBER_PPI_CHANNELS ) ;
735           ch_nbr++ ) {
736       if ( ch_mask & ( (uint32_t) 1 << ch_nbr ) ){
737         ch_mask &= ~( (uint64_t) 1 << ch_nbr );
738         if ( ppi_ch_tasks[ch_nbr].tep_f != NULL ){
739           nrf_ppi_enqueue_task(ppi_ch_tasks[ch_nbr].tep_f);
740         }
741         if ( ppi_ch_tasks[ch_nbr].fork_tep_f != NULL ){
742           nrf_ppi_enqueue_task(ppi_ch_tasks[ch_nbr].fork_tep_f);
743         }
744       } //if event is mapped to this channel
745     } //for channels
746     nrf_ppi_dequeue_all_tasks();
747   } //if this event is in any channel
748 }
749 
750 /**
751  * Find the task in ppi_tasks_table whose address
752  * matches <TEP> and save the task handling function <in dest>
753  *
754  * Helper function for the TEP and FORK_TEP functions
755  */
find_task(void * TEP,dest_f_t * dest,int ch_nbr)756 static void find_task(void *TEP, dest_f_t *dest, int ch_nbr){
757   int tt = 0;
758   while ( ppi_tasks_table[tt].task_addr != NULL ){
759     if ( ppi_tasks_table[tt].task_addr == TEP ){
760        *dest = ppi_tasks_table[tt].dest;
761        return;
762     }
763     tt++;
764   }
765   bs_trace_warning_line_time(
766       "NRF_PPI: The task %p for chnbr %i does not match any modelled task in NRF_PPI.c => it will be ignored\n",
767       TEP, ch_nbr);
768 
769   *dest = NULL;
770 }
771 
772 /**
773  * Update PPI internal routing status after a
774  * CH[<ch_nbr>].EEP update
775  */
nrf_ppi_regw_sideeffects_EEP(int ch_nbr)776 void nrf_ppi_regw_sideeffects_EEP(int ch_nbr){
777   //To save execution time when an event is raised, we build the
778   //ppi_event_config_table & ppi_channel_config_table out of the registers
779 
780   //first remove this channel from all events masks
781   for (int i = 0 ; i < NUMBER_PPI_EVENTS ; i++){
782     ppi_evt_to_ch[i].channels_mask &= ~( 1 << ch_nbr );
783   }
784 
785   //then lets try to find which event (if any) is feeding this channel
786   if ( ( ch_nbr < 20 ) && ( (void*)NRF_PPI_regs.CH[ch_nbr].EEP != NULL ) ){
787     int i = 0;
788     while ( ppi_events_table[i].event_type != NUMBER_PPI_EVENTS ){
789       if ( ppi_events_table[i].event_addr == (void*)NRF_PPI_regs.CH[ch_nbr].EEP ) {
790         ppi_evt_to_ch[ppi_events_table[i].event_type].channels_mask |= ( 1 << ch_nbr );
791         return;
792       }
793       i++;
794     }
795     bs_trace_warning_line_time(
796         "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",
797         ch_nbr, NRF_PPI_regs.CH[ch_nbr].EEP);
798   }
799 }
800 
801 /**
802  * Update PPI internal routing status after a
803  * CH[<ch_nbr>].TEP update
804  */
nrf_ppi_regw_sideeffects_TEP(int ch_nbr)805 void nrf_ppi_regw_sideeffects_TEP(int ch_nbr){
806   //To save execution time when an event is raised, we build the
807   //ppi_event_config_table & ppi_channel_config_table out of the registers
808   if ( ch_nbr < 20 ){
809     if ( (void*)NRF_PPI_regs.CH[ch_nbr].TEP != NULL ){
810       find_task((void*)NRF_PPI_regs.CH[ch_nbr].TEP,
811                 &ppi_ch_tasks[ch_nbr].tep_f,
812                 ch_nbr);
813     } else {
814       ppi_ch_tasks[ch_nbr].tep_f = NULL;
815     }
816   }
817 }
818 /**
819  * Update PPI internal routing status after a
820  * FORK[<ch_nbr>].TEP update
821  */
nrf_ppi_regw_sideeffects_FORK_TEP(int ch_nbr)822 void nrf_ppi_regw_sideeffects_FORK_TEP(int ch_nbr){
823   if ( (void*)NRF_PPI_regs.FORK[ch_nbr].TEP != NULL ){
824     find_task((void*)NRF_PPI_regs.FORK[ch_nbr].TEP,
825               &ppi_ch_tasks[ch_nbr].fork_tep_f,
826               ch_nbr);
827   } else {
828     ppi_ch_tasks[ch_nbr].fork_tep_f = NULL;
829   }
830 }
831 
832 /**
833  * Update PPI CHEN mask after a write to CHENSET
834  * (writes to CHEN do not need sideeffects)
835  */
nrf_ppi_regw_sideeffects_CHENSET(void)836 void nrf_ppi_regw_sideeffects_CHENSET(void) {
837 	if ( NRF_PPI_regs.CHENSET != 0 ){
838 		NRF_PPI_regs.CHEN |= NRF_PPI_regs.CHENSET;
839 		NRF_PPI_regs.CHENSET = 0;
840 	}
841 }
842 
843 /**
844  * Update PPI CHEN mask after a write to CHENCLR
845  * (writes to CHEN do not need sideeffects)
846  */
nrf_ppi_regw_sideeffects_CHENCLR(void)847 void nrf_ppi_regw_sideeffects_CHENCLR(void) {
848 	if ( NRF_PPI_regs.CHENCLR != 0 ){
849 		NRF_PPI_regs.CHEN &= ~NRF_PPI_regs.CHENCLR;
850 		NRF_PPI_regs.CHENCLR = 0;
851 	}
852 }
853 
854 /**
855  * Update PPI CHEN mask after a write to CHENSET or CHENCLR
856  * (writes to CHEN do not need sideeffects)
857  */
nrf_ppi_regw_sideeffects_CHEN(void)858 void nrf_ppi_regw_sideeffects_CHEN(void) {
859 	//Note that we do not let people read CHEN from the SET and CLR
860 	//registers
861 	nrf_ppi_regw_sideeffects_CHENSET();
862 	nrf_ppi_regw_sideeffects_CHENCLR();
863 }
864 
nrf_ppi_regw_sideeffects_TASKS_CHG_DIS(int i)865 void nrf_ppi_regw_sideeffects_TASKS_CHG_DIS(int i){
866 	if ( NRF_PPI_regs.TASKS_CHG[i].DIS ) {
867 		NRF_PPI_regs.TASKS_CHG[i].DIS = 0;
868 		nrf_ppi_TASK_CHG_ENDIS( i, false );
869 	}
870 }
871 
nrf_ppi_regw_sideeffects_TASKS_CHG_EN(int i)872 void nrf_ppi_regw_sideeffects_TASKS_CHG_EN(int i){
873 	if ( NRF_PPI_regs.TASKS_CHG[i].EN ) {
874 		NRF_PPI_regs.TASKS_CHG[i].EN = 0;
875 		nrf_ppi_TASK_CHG_ENDIS( i, true );
876 	}
877 }
878 
nrf_ppi_taskw_sideeffects(void)879 void nrf_ppi_taskw_sideeffects(void) {
880 	int i;
881 	for ( i = 0 ; i < 6 ; i++){
882 		nrf_ppi_regw_sideeffects_TASKS_CHG_DIS(i);
883 	}
884 	for ( i = 0 ; i < 6 ; i++){
885 		nrf_ppi_regw_sideeffects_TASKS_CHG_EN(i);
886 	}
887 }
888