1 /*
2  * Copyright (c) 2017 Oticon A/S
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <stdbool.h>
7 #include <stdint.h>
8 #include <string.h>
9 #include "time_machine_if.h"
10 #include "NRF_HW_model_top.h"
11 #include "NRF_AAR.h"
12 #include "NRF_AES_CCM.h"
13 #include "NRF_RNG.h"
14 #include "NRF_PPI.h"
15 #include "NRF_RTC.h"
16 #include "NRF_TIMER.h"
17 #include "NRF_CLOCK.h"
18 #include "NRF_RADIO.h"
19 #include "NRF_EGU.h"
20 #include "bs_tracing.h"
21 
22 /*
23  * PPI — Programmable peripheral interconnect
24  * https://infocenter.nordicsemi.com/topic/ps_nrf52833/ppi.html?cp=4_1_0_5_14
25  *
26  */
27 
28 NRF_PPI_Type NRF_PPI_regs; ///< The PPI registers
29 
30 /**
31  * PPI module own TASKs handlers
32  */
nrf_ppi_TASK_CHG_ENDIS(int groupnbr,bool enable)33 void nrf_ppi_TASK_CHG_ENDIS( int groupnbr, bool enable /*false=disable task*/ ){
34   if ( enable ){
35     bs_trace_raw_time(9, "ppi: Channel group %i enabled\n", groupnbr);
36     NRF_PPI_regs.CHEN |= NRF_PPI_regs.CHG[groupnbr];
37   } else {
38     bs_trace_raw_time(9 ,"ppi: Channel group %i disable\n", groupnbr);
39     NRF_PPI_regs.CHEN &= ~NRF_PPI_regs.CHG[groupnbr];
40   }
41   //Note of the author: From the spec I cannot guess if these tasks will affect
42   //CHEN or a separate hidden register
43 }
nrf_ppi_TASK_CHG0_EN()44 void nrf_ppi_TASK_CHG0_EN() { nrf_ppi_TASK_CHG_ENDIS(0,true); }
nrf_ppi_TASK_CHG1_EN()45 void nrf_ppi_TASK_CHG1_EN() { nrf_ppi_TASK_CHG_ENDIS(1,true); }
nrf_ppi_TASK_CHG2_EN()46 void nrf_ppi_TASK_CHG2_EN() { nrf_ppi_TASK_CHG_ENDIS(2,true); }
nrf_ppi_TASK_CHG3_EN()47 void nrf_ppi_TASK_CHG3_EN() { nrf_ppi_TASK_CHG_ENDIS(3,true); }
nrf_ppi_TASK_CHG4_EN()48 void nrf_ppi_TASK_CHG4_EN() { nrf_ppi_TASK_CHG_ENDIS(4,true); }
nrf_ppi_TASK_CHG5_EN()49 void nrf_ppi_TASK_CHG5_EN() { nrf_ppi_TASK_CHG_ENDIS(5,true); }
nrf_ppi_TASK_CHG0_DIS()50 void nrf_ppi_TASK_CHG0_DIS(){ nrf_ppi_TASK_CHG_ENDIS(0,false); }
nrf_ppi_TASK_CHG1_DIS()51 void nrf_ppi_TASK_CHG1_DIS(){ nrf_ppi_TASK_CHG_ENDIS(1,false); }
nrf_ppi_TASK_CHG2_DIS()52 void nrf_ppi_TASK_CHG2_DIS(){ nrf_ppi_TASK_CHG_ENDIS(2,false); }
nrf_ppi_TASK_CHG3_DIS()53 void nrf_ppi_TASK_CHG3_DIS(){ nrf_ppi_TASK_CHG_ENDIS(3,false); }
nrf_ppi_TASK_CHG4_DIS()54 void nrf_ppi_TASK_CHG4_DIS(){ nrf_ppi_TASK_CHG_ENDIS(4,false); }
nrf_ppi_TASK_CHG5_DIS()55 void nrf_ppi_TASK_CHG5_DIS(){ nrf_ppi_TASK_CHG_ENDIS(5,false); }
56 
57 typedef void (*dest_f_t)(void); ///<Syntactic sugar for task function pointer
58 
59 typedef struct{
60   uint32_t channels_mask; //bitmask indicating which channel the event is mapped to
61 } ppi_event_to_ch_t;
62 ///Table contain which channels each event is activating (one entry per event)
63 static ppi_event_to_ch_t ppi_evt_to_ch[NUMBER_PPI_EVENTS];
64 
65 typedef struct {
66   dest_f_t tep_f;
67   dest_f_t fork_tep_f;
68 } ppi_channel_tasks_t;
69 ///Table with TASKs each channel activates
70 static ppi_channel_tasks_t ppi_ch_tasks[NUMBER_PPI_CHANNELS];
71 
72 typedef struct {
73   void *task_addr;
74   dest_f_t dest; //function to be called when task is triggered
75 } ppi_tasks_table_t;
76 
77 /**
78  * Table of TASKs addresses (as provided by the SW) vs the model function
79  * pointer (which handles the task trigger)
80  */
81 static const ppi_tasks_table_t ppi_tasks_table[]={ //just the ones we may use
82     //POWER CLOCK:
83     //{ (void*)&NRF_CLOCK_regs.TASKS_LFCLKSTART , nrf_clock_TASKS_LFCLKSTART},
84     { (void*)&NRF_CLOCK_regs.TASKS_HFCLKSTART , nrf_clock_TASKS_HFCLKSTART},
85     //{ (void*)&NRF_CLOCK_regs.TASKS_HFCLKSTOP , nrf_clock_TASKS_HFCLKSTOP},
86 
87     //RADIO:
88     { (void*)&NRF_RADIO_regs.TASKS_TXEN,         nrf_radio_tasks_TXEN},
89     { (void*)&NRF_RADIO_regs.TASKS_RXEN,         nrf_radio_tasks_RXEN},
90     { (void*)&NRF_RADIO_regs.TASKS_START,        nrf_radio_tasks_START},
91     { (void*)&NRF_RADIO_regs.TASKS_STOP,         nrf_radio_tasks_STOP},
92     { (void*)&NRF_RADIO_regs.TASKS_DISABLE,      nrf_radio_tasks_DISABLE},
93     { (void*)&NRF_RADIO_regs.TASKS_RSSISTART,    nrf_radio_tasks_RSSISTART},
94     { (void*)&NRF_RADIO_regs.TASKS_RSSISTOP,     nrf_radio_tasks_RSSISTOP},
95     { (void*)&NRF_RADIO_regs.TASKS_BCSTART,      nrf_radio_tasks_BCSTART},
96     { (void*)&NRF_RADIO_regs.TASKS_BCSTOP,       nrf_radio_tasks_BCSTOP},
97     { (void*)&NRF_RADIO_regs.TASKS_EDSTART,      nrf_radio_tasks_EDSTART},
98     { (void*)&NRF_RADIO_regs.TASKS_EDSTOP,       nrf_radio_tasks_EDSTOP},
99     { (void*)&NRF_RADIO_regs.TASKS_CCASTART,     nrf_radio_tasks_CCASTART},
100     { (void*)&NRF_RADIO_regs.TASKS_CCASTOP,      nrf_radio_tasks_CCASTOP},
101 
102     //TIMER0:
103     { (void*)&NRF_TIMER_regs[0].TASKS_CAPTURE[0],  nrf_timer0_TASK_CAPTURE_0},
104     { (void*)&NRF_TIMER_regs[0].TASKS_CAPTURE[1],  nrf_timer0_TASK_CAPTURE_1},
105     { (void*)&NRF_TIMER_regs[0].TASKS_CAPTURE[2],  nrf_timer0_TASK_CAPTURE_2},
106     { (void*)&NRF_TIMER_regs[0].TASKS_CAPTURE[3],  nrf_timer0_TASK_CAPTURE_3},
107 //    { (void*)&NRF_TIMER_regs[0].TASKS_CAPTURE[4],  nrf_timer0_TASK_CAPTURE_4},
108 //    { (void*)&NRF_TIMER_regs[0].TASKS_CAPTURE[5],  nrf_timer0_TASK_CAPTURE_5},
109     { (void*)&NRF_TIMER_regs[0].TASKS_CLEAR,       nrf_timer0_TASK_CLEAR},
110     { (void*)&NRF_TIMER_regs[0].TASKS_COUNT,       nrf_timer0_TASK_COUNT},
111     { (void*)&NRF_TIMER_regs[0].TASKS_START,       nrf_timer0_TASK_START},
112     { (void*)&NRF_TIMER_regs[0].TASKS_STOP,        nrf_timer0_TASK_STOP},
113     //TIMER1:
114     { (void*)&NRF_TIMER_regs[1].TASKS_CAPTURE[0],  nrf_timer1_TASK_CAPTURE_0},
115     { (void*)&NRF_TIMER_regs[1].TASKS_CAPTURE[1],  nrf_timer1_TASK_CAPTURE_1},
116     { (void*)&NRF_TIMER_regs[1].TASKS_CAPTURE[2],  nrf_timer1_TASK_CAPTURE_2},
117     { (void*)&NRF_TIMER_regs[1].TASKS_CAPTURE[3],  nrf_timer1_TASK_CAPTURE_3},
118 //    { (void*)&NRF_TIMER_regs[1].TASKS_CAPTURE[4],  nrf_timer1_TASK_CAPTURE_4},
119 //    { (void*)&NRF_TIMER_regs[1].TASKS_CAPTURE[5],  nrf_timer1_TASK_CAPTURE_5},
120     { (void*)&NRF_TIMER_regs[1].TASKS_CLEAR,       nrf_timer1_TASK_CLEAR},
121     { (void*)&NRF_TIMER_regs[1].TASKS_COUNT,       nrf_timer1_TASK_COUNT},
122     { (void*)&NRF_TIMER_regs[1].TASKS_START,       nrf_timer1_TASK_START},
123     { (void*)&NRF_TIMER_regs[1].TASKS_STOP,        nrf_timer1_TASK_STOP},
124     //TIMER2:
125     { (void*)&NRF_TIMER_regs[2].TASKS_CAPTURE[0],  nrf_timer2_TASK_CAPTURE_0},
126     { (void*)&NRF_TIMER_regs[2].TASKS_CAPTURE[1],  nrf_timer2_TASK_CAPTURE_1},
127     { (void*)&NRF_TIMER_regs[2].TASKS_CAPTURE[2],  nrf_timer2_TASK_CAPTURE_2},
128     { (void*)&NRF_TIMER_regs[2].TASKS_CAPTURE[3],  nrf_timer2_TASK_CAPTURE_3},
129 //    { (void*)&NRF_TIMER_regs[2].TASKS_CAPTURE[4],  nrf_timer2_TASK_CAPTURE_4},
130 //    { (void*)&NRF_TIMER_regs[2].TASKS_CAPTURE[5],  nrf_timer2_TASK_CAPTURE_5},
131     { (void*)&NRF_TIMER_regs[2].TASKS_CLEAR,       nrf_timer2_TASK_CLEAR},
132     { (void*)&NRF_TIMER_regs[2].TASKS_COUNT,       nrf_timer2_TASK_COUNT},
133     { (void*)&NRF_TIMER_regs[2].TASKS_START,       nrf_timer2_TASK_START},
134     { (void*)&NRF_TIMER_regs[2].TASKS_STOP,        nrf_timer2_TASK_STOP},
135     //TIMER3:
136     { (void*)&NRF_TIMER_regs[3].TASKS_CAPTURE[0],  nrf_timer3_TASK_CAPTURE_0},
137     { (void*)&NRF_TIMER_regs[3].TASKS_CAPTURE[1],  nrf_timer3_TASK_CAPTURE_1},
138     { (void*)&NRF_TIMER_regs[3].TASKS_CAPTURE[2],  nrf_timer3_TASK_CAPTURE_2},
139     { (void*)&NRF_TIMER_regs[3].TASKS_CAPTURE[3],  nrf_timer3_TASK_CAPTURE_3},
140     { (void*)&NRF_TIMER_regs[3].TASKS_CAPTURE[4],  nrf_timer3_TASK_CAPTURE_4},
141     { (void*)&NRF_TIMER_regs[3].TASKS_CAPTURE[5],  nrf_timer3_TASK_CAPTURE_5},
142     { (void*)&NRF_TIMER_regs[3].TASKS_CLEAR,       nrf_timer3_TASK_CLEAR},
143     { (void*)&NRF_TIMER_regs[3].TASKS_COUNT,       nrf_timer3_TASK_COUNT},
144     { (void*)&NRF_TIMER_regs[3].TASKS_START,       nrf_timer3_TASK_START},
145     { (void*)&NRF_TIMER_regs[3].TASKS_STOP,        nrf_timer3_TASK_STOP},
146     //TIMER4:
147     { (void*)&NRF_TIMER_regs[4].TASKS_CAPTURE[0],  nrf_timer4_TASK_CAPTURE_0},
148     { (void*)&NRF_TIMER_regs[4].TASKS_CAPTURE[1],  nrf_timer4_TASK_CAPTURE_1},
149     { (void*)&NRF_TIMER_regs[4].TASKS_CAPTURE[2],  nrf_timer4_TASK_CAPTURE_2},
150     { (void*)&NRF_TIMER_regs[4].TASKS_CAPTURE[3],  nrf_timer4_TASK_CAPTURE_3},
151     { (void*)&NRF_TIMER_regs[4].TASKS_CAPTURE[4],  nrf_timer4_TASK_CAPTURE_4},
152     { (void*)&NRF_TIMER_regs[4].TASKS_CAPTURE[5],  nrf_timer4_TASK_CAPTURE_5},
153     { (void*)&NRF_TIMER_regs[4].TASKS_CLEAR,       nrf_timer4_TASK_CLEAR},
154     { (void*)&NRF_TIMER_regs[4].TASKS_COUNT,       nrf_timer4_TASK_COUNT},
155     { (void*)&NRF_TIMER_regs[4].TASKS_START,       nrf_timer4_TASK_START},
156     { (void*)&NRF_TIMER_regs[4].TASKS_STOP,        nrf_timer4_TASK_STOP},
157 
158     //RTC:
159     //{ (void*)&(NRF_RTC_regs[0]).TASKS_CLEAR, nrf_rtc0_TASKS_CLEAR},
160     //{ (void*)&(NRF_RTC_regs[0]).TASKS_START, nrf_rtc0_TASKS_START},
161     //{ (void*)&(NRF_RTC_regs[0]).TASKS_STOP , nrf_rtc0_TASKS_STOP},
162     //{ (void*)&(NRF_RTC_regs[0]).TASKS_TRIGOVRFLW , nrf_rtc0_TASKS_TRIGOVRFLW},
163     //{ (void*)&(NRF_RTC_regs[1]).TASKS_CLEAR, nrf_rtc1_TASKS_CLEAR},
164     //{ (void*)&(NRF_RTC_regs[1]).TASKS_START, nrf_rtc1_TASKS_START},
165     //{ (void*)&(NRF_RTC_regs[1]).TASKS_STOP , nrf_rtc1_TASKS_STOP},
166     //{ (void*)&(NRF_RTC_regs[1]).TASKS_TRIGOVRFLW , nrf_rtc1_TASKS_TRIGOVRFLW},
167     //{ (void*)&(NRF_RTC_regs[2]).TASKS_CLEAR, nrf_rtc2_TASKS_CLEAR},
168     //{ (void*)&(NRF_RTC_regs[2]).TASKS_START, nrf_rtc2_TASKS_START},
169     //{ (void*)&(NRF_RTC_regs[2]).TASKS_STOP , nrf_rtc2_TASKS_STOP},
170     //{ (void*)&(NRF_RTC_regs[2]).TASKS_TRIGOVRFLW , nrf_rtc2_TASKS_TRIGOVRFLW},
171 
172     //RNG:
173     { (void*)&NRF_RNG_regs.TASKS_START, nrf_rng_task_start},
174     { (void*)&NRF_RNG_regs.TASKS_STOP , nrf_rng_task_stop},
175 
176     //ECB
177 
178     //AAR
179     { (void*)&NRF_AAR_regs.TASKS_START , nrf_aar_TASK_START},
180 
181     //CCM
182     { (void*)&NRF_CCM_regs.TASKS_CRYPT , nrf_ccm_TASK_CRYPT},
183 
184     //PPI:
185     { (void*)&NRF_PPI_regs.TASKS_CHG[0].EN,  nrf_ppi_TASK_CHG0_EN},
186     { (void*)&NRF_PPI_regs.TASKS_CHG[1].EN,  nrf_ppi_TASK_CHG1_EN},
187     { (void*)&NRF_PPI_regs.TASKS_CHG[2].EN,  nrf_ppi_TASK_CHG2_EN},
188     { (void*)&NRF_PPI_regs.TASKS_CHG[3].EN,  nrf_ppi_TASK_CHG3_EN},
189     { (void*)&NRF_PPI_regs.TASKS_CHG[4].EN,  nrf_ppi_TASK_CHG4_EN},
190     { (void*)&NRF_PPI_regs.TASKS_CHG[5].EN,  nrf_ppi_TASK_CHG5_EN},
191     { (void*)&NRF_PPI_regs.TASKS_CHG[0].DIS, nrf_ppi_TASK_CHG0_DIS},
192     { (void*)&NRF_PPI_regs.TASKS_CHG[1].DIS, nrf_ppi_TASK_CHG1_DIS},
193     { (void*)&NRF_PPI_regs.TASKS_CHG[2].DIS, nrf_ppi_TASK_CHG2_DIS},
194     { (void*)&NRF_PPI_regs.TASKS_CHG[3].DIS, nrf_ppi_TASK_CHG3_DIS},
195     { (void*)&NRF_PPI_regs.TASKS_CHG[4].DIS, nrf_ppi_TASK_CHG4_DIS},
196     { (void*)&NRF_PPI_regs.TASKS_CHG[5].DIS, nrf_ppi_TASK_CHG5_DIS},
197 
198     //EGU:
199     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[0] , nrf_egu_0_TASK_TRIGGER_0},
200     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[1] , nrf_egu_0_TASK_TRIGGER_1},
201     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[2] , nrf_egu_0_TASK_TRIGGER_2},
202     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[3] , nrf_egu_0_TASK_TRIGGER_3},
203     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[4] , nrf_egu_0_TASK_TRIGGER_4},
204     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[5] , nrf_egu_0_TASK_TRIGGER_5},
205     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[6] , nrf_egu_0_TASK_TRIGGER_6},
206     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[7] , nrf_egu_0_TASK_TRIGGER_7},
207     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[8] , nrf_egu_0_TASK_TRIGGER_8},
208     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[9] , nrf_egu_0_TASK_TRIGGER_9},
209     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[10] , nrf_egu_0_TASK_TRIGGER_10},
210     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[11] , nrf_egu_0_TASK_TRIGGER_11},
211     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[12] , nrf_egu_0_TASK_TRIGGER_12},
212     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[13] , nrf_egu_0_TASK_TRIGGER_13},
213     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[14] , nrf_egu_0_TASK_TRIGGER_14},
214     {(void*)&NRF_EGU_regs[0].TASKS_TRIGGER[15] , nrf_egu_0_TASK_TRIGGER_15},
215     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[0] , nrf_egu_1_TASK_TRIGGER_0},
216     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[1] , nrf_egu_1_TASK_TRIGGER_1},
217     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[2] , nrf_egu_1_TASK_TRIGGER_2},
218     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[3] , nrf_egu_1_TASK_TRIGGER_3},
219     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[4] , nrf_egu_1_TASK_TRIGGER_4},
220     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[5] , nrf_egu_1_TASK_TRIGGER_5},
221     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[6] , nrf_egu_1_TASK_TRIGGER_6},
222     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[7] , nrf_egu_1_TASK_TRIGGER_7},
223     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[8] , nrf_egu_1_TASK_TRIGGER_8},
224     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[9] , nrf_egu_1_TASK_TRIGGER_9},
225     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[10] , nrf_egu_1_TASK_TRIGGER_10},
226     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[11] , nrf_egu_1_TASK_TRIGGER_11},
227     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[12] , nrf_egu_1_TASK_TRIGGER_12},
228     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[13] , nrf_egu_1_TASK_TRIGGER_13},
229     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[14] , nrf_egu_1_TASK_TRIGGER_14},
230     {(void*)&NRF_EGU_regs[1].TASKS_TRIGGER[15] , nrf_egu_1_TASK_TRIGGER_15},
231     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[0] , nrf_egu_2_TASK_TRIGGER_0},
232     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[1] , nrf_egu_2_TASK_TRIGGER_1},
233     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[2] , nrf_egu_2_TASK_TRIGGER_2},
234     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[3] , nrf_egu_2_TASK_TRIGGER_3},
235     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[4] , nrf_egu_2_TASK_TRIGGER_4},
236     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[5] , nrf_egu_2_TASK_TRIGGER_5},
237     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[6] , nrf_egu_2_TASK_TRIGGER_6},
238     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[7] , nrf_egu_2_TASK_TRIGGER_7},
239     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[8] , nrf_egu_2_TASK_TRIGGER_8},
240     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[9] , nrf_egu_2_TASK_TRIGGER_9},
241     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[10] , nrf_egu_2_TASK_TRIGGER_10},
242     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[11] , nrf_egu_2_TASK_TRIGGER_11},
243     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[12] , nrf_egu_2_TASK_TRIGGER_12},
244     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[13] , nrf_egu_2_TASK_TRIGGER_13},
245     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[14] , nrf_egu_2_TASK_TRIGGER_14},
246     {(void*)&NRF_EGU_regs[2].TASKS_TRIGGER[15] , nrf_egu_2_TASK_TRIGGER_15},
247     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[0] , nrf_egu_3_TASK_TRIGGER_0},
248     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[1] , nrf_egu_3_TASK_TRIGGER_1},
249     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[2] , nrf_egu_3_TASK_TRIGGER_2},
250     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[3] , nrf_egu_3_TASK_TRIGGER_3},
251     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[4] , nrf_egu_3_TASK_TRIGGER_4},
252     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[5] , nrf_egu_3_TASK_TRIGGER_5},
253     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[6] , nrf_egu_3_TASK_TRIGGER_6},
254     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[7] , nrf_egu_3_TASK_TRIGGER_7},
255     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[8] , nrf_egu_3_TASK_TRIGGER_8},
256     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[9] , nrf_egu_3_TASK_TRIGGER_9},
257     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[10] , nrf_egu_3_TASK_TRIGGER_10},
258     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[11] , nrf_egu_3_TASK_TRIGGER_11},
259     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[12] , nrf_egu_3_TASK_TRIGGER_12},
260     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[13] , nrf_egu_3_TASK_TRIGGER_13},
261     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[14] , nrf_egu_3_TASK_TRIGGER_14},
262     {(void*)&NRF_EGU_regs[3].TASKS_TRIGGER[15] , nrf_egu_3_TASK_TRIGGER_15},
263     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[0] , nrf_egu_4_TASK_TRIGGER_0},
264     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[1] , nrf_egu_4_TASK_TRIGGER_1},
265     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[2] , nrf_egu_4_TASK_TRIGGER_2},
266     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[3] , nrf_egu_4_TASK_TRIGGER_3},
267     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[4] , nrf_egu_4_TASK_TRIGGER_4},
268     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[5] , nrf_egu_4_TASK_TRIGGER_5},
269     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[6] , nrf_egu_4_TASK_TRIGGER_6},
270     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[7] , nrf_egu_4_TASK_TRIGGER_7},
271     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[8] , nrf_egu_4_TASK_TRIGGER_8},
272     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[9] , nrf_egu_4_TASK_TRIGGER_9},
273     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[10] , nrf_egu_4_TASK_TRIGGER_10},
274     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[11] , nrf_egu_4_TASK_TRIGGER_11},
275     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[12] , nrf_egu_4_TASK_TRIGGER_12},
276     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[13] , nrf_egu_4_TASK_TRIGGER_13},
277     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[14] , nrf_egu_4_TASK_TRIGGER_14},
278     {(void*)&NRF_EGU_regs[4].TASKS_TRIGGER[15] , nrf_egu_4_TASK_TRIGGER_15},
279     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[0] , nrf_egu_5_TASK_TRIGGER_0},
280     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[1] , nrf_egu_5_TASK_TRIGGER_1},
281     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[2] , nrf_egu_5_TASK_TRIGGER_2},
282     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[3] , nrf_egu_5_TASK_TRIGGER_3},
283     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[4] , nrf_egu_5_TASK_TRIGGER_4},
284     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[5] , nrf_egu_5_TASK_TRIGGER_5},
285     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[6] , nrf_egu_5_TASK_TRIGGER_6},
286     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[7] , nrf_egu_5_TASK_TRIGGER_7},
287     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[8] , nrf_egu_5_TASK_TRIGGER_8},
288     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[9] , nrf_egu_5_TASK_TRIGGER_9},
289     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[10] , nrf_egu_5_TASK_TRIGGER_10},
290     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[11] , nrf_egu_5_TASK_TRIGGER_11},
291     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[12] , nrf_egu_5_TASK_TRIGGER_12},
292     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[13] , nrf_egu_5_TASK_TRIGGER_13},
293     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[14] , nrf_egu_5_TASK_TRIGGER_14},
294     {(void*)&NRF_EGU_regs[5].TASKS_TRIGGER[15] , nrf_egu_5_TASK_TRIGGER_15},
295 
296     //End marker
297     { NULL, NULL }
298 };
299 
300 /**
301  * Table to convert from an event_address as programmed by the SW into an
302  * event_type used here to index tables
303  */
304 typedef struct {
305   ppi_event_types_t event_type;
306   void *event_addr;
307 } ppi_event_table_t;
308 
309 static const ppi_event_table_t ppi_events_table[] = { //better keep same order as in ppi_event_types_t
310     {RADIO_EVENTS_READY,   &NRF_RADIO_regs.EVENTS_READY},
311     {RADIO_EVENTS_ADDRESS, &NRF_RADIO_regs.EVENTS_ADDRESS},
312     {RADIO_EVENTS_PAYLOAD, &NRF_RADIO_regs.EVENTS_PAYLOAD},
313     {RADIO_EVENTS_END,     &NRF_RADIO_regs.EVENTS_END},
314     {RADIO_EVENTS_DISABLED,&NRF_RADIO_regs.EVENTS_DISABLED},
315     {RADIO_EVENTS_DEVMATCH,&NRF_RADIO_regs.EVENTS_DEVMATCH},
316     {RADIO_EVENTS_DEVMISS ,&NRF_RADIO_regs.EVENTS_DEVMISS},
317     {RADIO_EVENTS_RSSIEND, &NRF_RADIO_regs.EVENTS_RSSIEND},
318     {RADIO_EVENTS_BCMATCH, &NRF_RADIO_regs.EVENTS_BCMATCH},
319     {RADIO_EVENTS_CRCOK,   &NRF_RADIO_regs.EVENTS_CRCOK},
320     {RADIO_EVENTS_CRCERROR,&NRF_RADIO_regs.EVENTS_CRCERROR},
321     {RADIO_EVENTS_FRAMESTART,&NRF_RADIO_regs.EVENTS_FRAMESTART},
322     {RADIO_EVENTS_EDEND,   &NRF_RADIO_regs.EVENTS_EDEND},
323     {RADIO_EVENTS_EDSTOPPED, &NRF_RADIO_regs.EVENTS_EDSTOPPED},
324     {RADIO_EVENTS_CCAIDLE, &NRF_RADIO_regs.EVENTS_CCAIDLE},
325     {RADIO_EVENTS_CCABUSY, &NRF_RADIO_regs.EVENTS_CCABUSY},
326     {RADIO_EVENTS_CCASTOPPED, &NRF_RADIO_regs.EVENTS_CCASTOPPED},
327     {RADIO_EVENTS_RATEBOOST, &NRF_RADIO_regs.EVENTS_RATEBOOST},
328     {RADIO_EVENTS_TXREADY, &NRF_RADIO_regs.EVENTS_TXREADY},
329     {RADIO_EVENTS_RXREADY, &NRF_RADIO_regs.EVENTS_RXREADY},
330     {RADIO_EVENTS_MHRMATCH,&NRF_RADIO_regs.EVENTS_MHRMATCH},
331     {RADIO_EVENTS_SYNC,    &NRF_RADIO_regs.EVENTS_SYNC},
332     {RADIO_EVENTS_PHYEND,  &NRF_RADIO_regs.EVENTS_PHYEND},
333     {RADIO_EVENTS_CTEPRESENT,&NRF_RADIO_regs.EVENTS_CTEPRESENT},
334 
335     {TIMER0_EVENTS_COMPARE_0, &NRF_TIMER_regs[0].EVENTS_COMPARE[0]},
336     {TIMER0_EVENTS_COMPARE_1, &NRF_TIMER_regs[0].EVENTS_COMPARE[1]},
337     {TIMER0_EVENTS_COMPARE_2, &NRF_TIMER_regs[0].EVENTS_COMPARE[2]},
338     {TIMER0_EVENTS_COMPARE_3, &NRF_TIMER_regs[0].EVENTS_COMPARE[3]},
339 //    {TIMER0_EVENTS_COMPARE_4, &NRF_TIMER_regs[0].EVENTS_COMPARE[4]},
340 //    {TIMER0_EVENTS_COMPARE_5, &NRF_TIMER_regs[0].EVENTS_COMPARE[5]},
341 
342     {TIMER1_EVENTS_COMPARE_0, &NRF_TIMER_regs[1].EVENTS_COMPARE[0]},
343     {TIMER1_EVENTS_COMPARE_1, &NRF_TIMER_regs[1].EVENTS_COMPARE[1]},
344     {TIMER1_EVENTS_COMPARE_2, &NRF_TIMER_regs[1].EVENTS_COMPARE[2]},
345     {TIMER1_EVENTS_COMPARE_3, &NRF_TIMER_regs[1].EVENTS_COMPARE[3]},
346     //    {TIMER1_EVENTS_COMPARE_4, &NRF_TIMER_regs[1].EVENTS_COMPARE[4]},
347     //    {TIMER1_EVENTS_COMPARE_5, &NRF_TIMER_regs[1].EVENTS_COMPARE[5]},
348 
349     {TIMER2_EVENTS_COMPARE_0, &NRF_TIMER_regs[2].EVENTS_COMPARE[0]},
350     {TIMER2_EVENTS_COMPARE_1, &NRF_TIMER_regs[2].EVENTS_COMPARE[1]},
351     {TIMER2_EVENTS_COMPARE_2, &NRF_TIMER_regs[2].EVENTS_COMPARE[2]},
352     {TIMER2_EVENTS_COMPARE_3, &NRF_TIMER_regs[2].EVENTS_COMPARE[3]},
353     //    {TIMER2_EVENTS_COMPARE_4, &NRF_TIMER_regs[2].EVENTS_COMPARE[4]},
354     //    {TIMER2_EVENTS_COMPARE_5, &NRF_TIMER_regs[2].EVENTS_COMPARE[5]},
355 
356     {RTC0_EVENTS_OVRFLW, &NRF_RTC_regs[0].EVENTS_OVRFLW},
357     {RTC0_EVENTS_COMPARE_0, &NRF_RTC_regs[0].EVENTS_COMPARE[0]},
358     {RTC0_EVENTS_COMPARE_1, &NRF_RTC_regs[0].EVENTS_COMPARE[1]},
359     {RTC0_EVENTS_COMPARE_2, &NRF_RTC_regs[0].EVENTS_COMPARE[2]},
360     {RTC0_EVENTS_COMPARE_3, &NRF_RTC_regs[0].EVENTS_COMPARE[3]},
361 
362     {TEMP_EVENTS_DATARDY, &NRF_TEMP_regs.EVENTS_DATARDY},
363 
364     //{RNG_EVENTS_VALRDY, &NRF_RNG_regs.EVENTS_VALRDY},
365 
366     {CCM_EVENTS_ENDKSGEN, &NRF_CCM_regs.EVENTS_ENDKSGEN},
367     {CCM_EVENTS_ENDCRYPT, &NRF_CCM_regs.EVENTS_ENDCRYPT},
368     {CCM_EVENTS_ERROR,    &NRF_CCM_regs.EVENTS_ERROR},
369 
370     {RTC1_EVENTS_OVRFLW, &NRF_RTC_regs[1].EVENTS_OVRFLW},
371     {RTC1_EVENTS_COMPARE_0, &NRF_RTC_regs[1].EVENTS_COMPARE[0]},
372     {RTC1_EVENTS_COMPARE_1, &NRF_RTC_regs[1].EVENTS_COMPARE[1]},
373     {RTC1_EVENTS_COMPARE_2, &NRF_RTC_regs[1].EVENTS_COMPARE[2]},
374     {RTC1_EVENTS_COMPARE_3, &NRF_RTC_regs[1].EVENTS_COMPARE[3]},
375 
376     {EGU0_EVENTS_TRIGGERED_0, &NRF_EGU_regs[0].EVENTS_TRIGGERED[0]}, /*These are autogenerated (See NRF_EGU.c)*/
377     {EGU0_EVENTS_TRIGGERED_1, &NRF_EGU_regs[0].EVENTS_TRIGGERED[1]},
378     {EGU0_EVENTS_TRIGGERED_2, &NRF_EGU_regs[0].EVENTS_TRIGGERED[2]},
379     {EGU0_EVENTS_TRIGGERED_3, &NRF_EGU_regs[0].EVENTS_TRIGGERED[3]},
380     {EGU0_EVENTS_TRIGGERED_4, &NRF_EGU_regs[0].EVENTS_TRIGGERED[4]},
381     {EGU0_EVENTS_TRIGGERED_5, &NRF_EGU_regs[0].EVENTS_TRIGGERED[5]},
382     {EGU0_EVENTS_TRIGGERED_6, &NRF_EGU_regs[0].EVENTS_TRIGGERED[6]},
383     {EGU0_EVENTS_TRIGGERED_7, &NRF_EGU_regs[0].EVENTS_TRIGGERED[7]},
384     {EGU0_EVENTS_TRIGGERED_8, &NRF_EGU_regs[0].EVENTS_TRIGGERED[8]},
385     {EGU0_EVENTS_TRIGGERED_9, &NRF_EGU_regs[0].EVENTS_TRIGGERED[9]},
386     {EGU0_EVENTS_TRIGGERED_10, &NRF_EGU_regs[0].EVENTS_TRIGGERED[10]},
387     {EGU0_EVENTS_TRIGGERED_11, &NRF_EGU_regs[0].EVENTS_TRIGGERED[11]},
388     {EGU0_EVENTS_TRIGGERED_12, &NRF_EGU_regs[0].EVENTS_TRIGGERED[12]},
389     {EGU0_EVENTS_TRIGGERED_13, &NRF_EGU_regs[0].EVENTS_TRIGGERED[13]},
390     {EGU0_EVENTS_TRIGGERED_14, &NRF_EGU_regs[0].EVENTS_TRIGGERED[14]},
391     {EGU0_EVENTS_TRIGGERED_15, &NRF_EGU_regs[0].EVENTS_TRIGGERED[15]},
392     {EGU1_EVENTS_TRIGGERED_0, &NRF_EGU_regs[1].EVENTS_TRIGGERED[0]},
393     {EGU1_EVENTS_TRIGGERED_1, &NRF_EGU_regs[1].EVENTS_TRIGGERED[1]},
394     {EGU1_EVENTS_TRIGGERED_2, &NRF_EGU_regs[1].EVENTS_TRIGGERED[2]},
395     {EGU1_EVENTS_TRIGGERED_3, &NRF_EGU_regs[1].EVENTS_TRIGGERED[3]},
396     {EGU1_EVENTS_TRIGGERED_4, &NRF_EGU_regs[1].EVENTS_TRIGGERED[4]},
397     {EGU1_EVENTS_TRIGGERED_5, &NRF_EGU_regs[1].EVENTS_TRIGGERED[5]},
398     {EGU1_EVENTS_TRIGGERED_6, &NRF_EGU_regs[1].EVENTS_TRIGGERED[6]},
399     {EGU1_EVENTS_TRIGGERED_7, &NRF_EGU_regs[1].EVENTS_TRIGGERED[7]},
400     {EGU1_EVENTS_TRIGGERED_8, &NRF_EGU_regs[1].EVENTS_TRIGGERED[8]},
401     {EGU1_EVENTS_TRIGGERED_9, &NRF_EGU_regs[1].EVENTS_TRIGGERED[9]},
402     {EGU1_EVENTS_TRIGGERED_10, &NRF_EGU_regs[1].EVENTS_TRIGGERED[10]},
403     {EGU1_EVENTS_TRIGGERED_11, &NRF_EGU_regs[1].EVENTS_TRIGGERED[11]},
404     {EGU1_EVENTS_TRIGGERED_12, &NRF_EGU_regs[1].EVENTS_TRIGGERED[12]},
405     {EGU1_EVENTS_TRIGGERED_13, &NRF_EGU_regs[1].EVENTS_TRIGGERED[13]},
406     {EGU1_EVENTS_TRIGGERED_14, &NRF_EGU_regs[1].EVENTS_TRIGGERED[14]},
407     {EGU1_EVENTS_TRIGGERED_15, &NRF_EGU_regs[1].EVENTS_TRIGGERED[15]},
408     {EGU2_EVENTS_TRIGGERED_0, &NRF_EGU_regs[2].EVENTS_TRIGGERED[0]},
409     {EGU2_EVENTS_TRIGGERED_1, &NRF_EGU_regs[2].EVENTS_TRIGGERED[1]},
410     {EGU2_EVENTS_TRIGGERED_2, &NRF_EGU_regs[2].EVENTS_TRIGGERED[2]},
411     {EGU2_EVENTS_TRIGGERED_3, &NRF_EGU_regs[2].EVENTS_TRIGGERED[3]},
412     {EGU2_EVENTS_TRIGGERED_4, &NRF_EGU_regs[2].EVENTS_TRIGGERED[4]},
413     {EGU2_EVENTS_TRIGGERED_5, &NRF_EGU_regs[2].EVENTS_TRIGGERED[5]},
414     {EGU2_EVENTS_TRIGGERED_6, &NRF_EGU_regs[2].EVENTS_TRIGGERED[6]},
415     {EGU2_EVENTS_TRIGGERED_7, &NRF_EGU_regs[2].EVENTS_TRIGGERED[7]},
416     {EGU2_EVENTS_TRIGGERED_8, &NRF_EGU_regs[2].EVENTS_TRIGGERED[8]},
417     {EGU2_EVENTS_TRIGGERED_9, &NRF_EGU_regs[2].EVENTS_TRIGGERED[9]},
418     {EGU2_EVENTS_TRIGGERED_10, &NRF_EGU_regs[2].EVENTS_TRIGGERED[10]},
419     {EGU2_EVENTS_TRIGGERED_11, &NRF_EGU_regs[2].EVENTS_TRIGGERED[11]},
420     {EGU2_EVENTS_TRIGGERED_12, &NRF_EGU_regs[2].EVENTS_TRIGGERED[12]},
421     {EGU2_EVENTS_TRIGGERED_13, &NRF_EGU_regs[2].EVENTS_TRIGGERED[13]},
422     {EGU2_EVENTS_TRIGGERED_14, &NRF_EGU_regs[2].EVENTS_TRIGGERED[14]},
423     {EGU2_EVENTS_TRIGGERED_15, &NRF_EGU_regs[2].EVENTS_TRIGGERED[15]},
424     {EGU3_EVENTS_TRIGGERED_0, &NRF_EGU_regs[3].EVENTS_TRIGGERED[0]},
425     {EGU3_EVENTS_TRIGGERED_1, &NRF_EGU_regs[3].EVENTS_TRIGGERED[1]},
426     {EGU3_EVENTS_TRIGGERED_2, &NRF_EGU_regs[3].EVENTS_TRIGGERED[2]},
427     {EGU3_EVENTS_TRIGGERED_3, &NRF_EGU_regs[3].EVENTS_TRIGGERED[3]},
428     {EGU3_EVENTS_TRIGGERED_4, &NRF_EGU_regs[3].EVENTS_TRIGGERED[4]},
429     {EGU3_EVENTS_TRIGGERED_5, &NRF_EGU_regs[3].EVENTS_TRIGGERED[5]},
430     {EGU3_EVENTS_TRIGGERED_6, &NRF_EGU_regs[3].EVENTS_TRIGGERED[6]},
431     {EGU3_EVENTS_TRIGGERED_7, &NRF_EGU_regs[3].EVENTS_TRIGGERED[7]},
432     {EGU3_EVENTS_TRIGGERED_8, &NRF_EGU_regs[3].EVENTS_TRIGGERED[8]},
433     {EGU3_EVENTS_TRIGGERED_9, &NRF_EGU_regs[3].EVENTS_TRIGGERED[9]},
434     {EGU3_EVENTS_TRIGGERED_10, &NRF_EGU_regs[3].EVENTS_TRIGGERED[10]},
435     {EGU3_EVENTS_TRIGGERED_11, &NRF_EGU_regs[3].EVENTS_TRIGGERED[11]},
436     {EGU3_EVENTS_TRIGGERED_12, &NRF_EGU_regs[3].EVENTS_TRIGGERED[12]},
437     {EGU3_EVENTS_TRIGGERED_13, &NRF_EGU_regs[3].EVENTS_TRIGGERED[13]},
438     {EGU3_EVENTS_TRIGGERED_14, &NRF_EGU_regs[3].EVENTS_TRIGGERED[14]},
439     {EGU3_EVENTS_TRIGGERED_15, &NRF_EGU_regs[3].EVENTS_TRIGGERED[15]},
440     {EGU4_EVENTS_TRIGGERED_0, &NRF_EGU_regs[4].EVENTS_TRIGGERED[0]},
441     {EGU4_EVENTS_TRIGGERED_1, &NRF_EGU_regs[4].EVENTS_TRIGGERED[1]},
442     {EGU4_EVENTS_TRIGGERED_2, &NRF_EGU_regs[4].EVENTS_TRIGGERED[2]},
443     {EGU4_EVENTS_TRIGGERED_3, &NRF_EGU_regs[4].EVENTS_TRIGGERED[3]},
444     {EGU4_EVENTS_TRIGGERED_4, &NRF_EGU_regs[4].EVENTS_TRIGGERED[4]},
445     {EGU4_EVENTS_TRIGGERED_5, &NRF_EGU_regs[4].EVENTS_TRIGGERED[5]},
446     {EGU4_EVENTS_TRIGGERED_6, &NRF_EGU_regs[4].EVENTS_TRIGGERED[6]},
447     {EGU4_EVENTS_TRIGGERED_7, &NRF_EGU_regs[4].EVENTS_TRIGGERED[7]},
448     {EGU4_EVENTS_TRIGGERED_8, &NRF_EGU_regs[4].EVENTS_TRIGGERED[8]},
449     {EGU4_EVENTS_TRIGGERED_9, &NRF_EGU_regs[4].EVENTS_TRIGGERED[9]},
450     {EGU4_EVENTS_TRIGGERED_10, &NRF_EGU_regs[4].EVENTS_TRIGGERED[10]},
451     {EGU4_EVENTS_TRIGGERED_11, &NRF_EGU_regs[4].EVENTS_TRIGGERED[11]},
452     {EGU4_EVENTS_TRIGGERED_12, &NRF_EGU_regs[4].EVENTS_TRIGGERED[12]},
453     {EGU4_EVENTS_TRIGGERED_13, &NRF_EGU_regs[4].EVENTS_TRIGGERED[13]},
454     {EGU4_EVENTS_TRIGGERED_14, &NRF_EGU_regs[4].EVENTS_TRIGGERED[14]},
455     {EGU4_EVENTS_TRIGGERED_15, &NRF_EGU_regs[4].EVENTS_TRIGGERED[15]},
456     {EGU5_EVENTS_TRIGGERED_0, &NRF_EGU_regs[5].EVENTS_TRIGGERED[0]},
457     {EGU5_EVENTS_TRIGGERED_1, &NRF_EGU_regs[5].EVENTS_TRIGGERED[1]},
458     {EGU5_EVENTS_TRIGGERED_2, &NRF_EGU_regs[5].EVENTS_TRIGGERED[2]},
459     {EGU5_EVENTS_TRIGGERED_3, &NRF_EGU_regs[5].EVENTS_TRIGGERED[3]},
460     {EGU5_EVENTS_TRIGGERED_4, &NRF_EGU_regs[5].EVENTS_TRIGGERED[4]},
461     {EGU5_EVENTS_TRIGGERED_5, &NRF_EGU_regs[5].EVENTS_TRIGGERED[5]},
462     {EGU5_EVENTS_TRIGGERED_6, &NRF_EGU_regs[5].EVENTS_TRIGGERED[6]},
463     {EGU5_EVENTS_TRIGGERED_7, &NRF_EGU_regs[5].EVENTS_TRIGGERED[7]},
464     {EGU5_EVENTS_TRIGGERED_8, &NRF_EGU_regs[5].EVENTS_TRIGGERED[8]},
465     {EGU5_EVENTS_TRIGGERED_9, &NRF_EGU_regs[5].EVENTS_TRIGGERED[9]},
466     {EGU5_EVENTS_TRIGGERED_10, &NRF_EGU_regs[5].EVENTS_TRIGGERED[10]},
467     {EGU5_EVENTS_TRIGGERED_11, &NRF_EGU_regs[5].EVENTS_TRIGGERED[11]},
468     {EGU5_EVENTS_TRIGGERED_12, &NRF_EGU_regs[5].EVENTS_TRIGGERED[12]},
469     {EGU5_EVENTS_TRIGGERED_13, &NRF_EGU_regs[5].EVENTS_TRIGGERED[13]},
470     {EGU5_EVENTS_TRIGGERED_14, &NRF_EGU_regs[5].EVENTS_TRIGGERED[14]},
471     {EGU5_EVENTS_TRIGGERED_15, &NRF_EGU_regs[5].EVENTS_TRIGGERED[15]},
472 
473     {TIMER3_EVENTS_COMPARE_0, &NRF_TIMER_regs[3].EVENTS_COMPARE[0]},
474     {TIMER3_EVENTS_COMPARE_1, &NRF_TIMER_regs[3].EVENTS_COMPARE[1]},
475     {TIMER3_EVENTS_COMPARE_2, &NRF_TIMER_regs[3].EVENTS_COMPARE[2]},
476     {TIMER3_EVENTS_COMPARE_3, &NRF_TIMER_regs[3].EVENTS_COMPARE[3]},
477     {TIMER3_EVENTS_COMPARE_4, &NRF_TIMER_regs[3].EVENTS_COMPARE[4]},
478     {TIMER3_EVENTS_COMPARE_5, &NRF_TIMER_regs[3].EVENTS_COMPARE[5]},
479 
480     {TIMER4_EVENTS_COMPARE_0, &NRF_TIMER_regs[4].EVENTS_COMPARE[0]},
481     {TIMER4_EVENTS_COMPARE_1, &NRF_TIMER_regs[4].EVENTS_COMPARE[1]},
482     {TIMER4_EVENTS_COMPARE_2, &NRF_TIMER_regs[4].EVENTS_COMPARE[2]},
483     {TIMER4_EVENTS_COMPARE_3, &NRF_TIMER_regs[4].EVENTS_COMPARE[3]},
484     {TIMER4_EVENTS_COMPARE_4, &NRF_TIMER_regs[4].EVENTS_COMPARE[4]},
485     {TIMER4_EVENTS_COMPARE_5, &NRF_TIMER_regs[4].EVENTS_COMPARE[5]},
486 
487     {RTC2_EVENTS_OVRFLW, &NRF_RTC_regs[2].EVENTS_OVRFLW},
488     {RTC2_EVENTS_COMPARE_0, &NRF_RTC_regs[2].EVENTS_COMPARE[0]},
489     {RTC2_EVENTS_COMPARE_1, &NRF_RTC_regs[2].EVENTS_COMPARE[1]},
490     {RTC2_EVENTS_COMPARE_2, &NRF_RTC_regs[2].EVENTS_COMPARE[2]},
491     {RTC2_EVENTS_COMPARE_3, &NRF_RTC_regs[2].EVENTS_COMPARE[3]},
492 
493     {NUMBER_PPI_EVENTS, NULL} //End marker
494 };
495 
496 
set_fixed_channel_routes()497 static void set_fixed_channel_routes(){
498   //TODO: add handler function pointers as we add those functions while modelling the different parts
499 
500   //Set the fixed channels configuration:
501   //  20 TIMER0->EVENTS_COMPARE[0] RADIO->TASKS_TXEN
502     ppi_evt_to_ch[TIMER0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 20 );
503     ppi_ch_tasks[20].tep_f = nrf_radio_tasks_TXEN; //RADIO->TASKS_TXEN
504 
505   //  21 TIMER0->EVENTS_COMPARE[0] RADIO->TASKS_RXEN
506     ppi_evt_to_ch[TIMER0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 21 );
507     ppi_ch_tasks[21].tep_f = nrf_radio_tasks_RXEN; //RADIO->TASKS_RXEN
508 
509   //  22 TIMER0->EVENTS_COMPARE[1] RADIO->TASKS_DISABLE
510     ppi_evt_to_ch[TIMER0_EVENTS_COMPARE_1].channels_mask |= ( 1 << 22 );
511     ppi_ch_tasks[22].tep_f = nrf_radio_tasks_DISABLE; //RADIO->TASKS_DISABLE
512 
513   //  23 RADIO->EVENTS_BCMATCH AAR->TASKS_START
514     ppi_evt_to_ch[RADIO_EVENTS_BCMATCH].channels_mask |= ( 1 << 23 );
515     ppi_ch_tasks[23].tep_f = nrf_aar_TASK_START; //AAR->TASKS_START
516 
517   //  24 RADIO->EVENTS_READY CCM->TASKS_KSGEN
518     ppi_evt_to_ch[RADIO_EVENTS_READY].channels_mask |= ( 1 << 24 );
519     ppi_ch_tasks[24].tep_f = nrf_ccm_TASK_KSGEN; //CCM->TASKS_KSGEN
520 
521   //  25 RADIO->EVENTS_ADDRESS CCM->TASKS_CRYPT
522     ppi_evt_to_ch[RADIO_EVENTS_ADDRESS].channels_mask |= ( 1 << 25 );
523     ppi_ch_tasks[25].tep_f = nrf_ccm_TASK_CRYPT; //CCM->TASKS_CRYPT
524 
525   //  26 RADIO->EVENTS_ADDRESS TIMER0->TASKS_CAPTURE[1]
526     ppi_evt_to_ch[RADIO_EVENTS_ADDRESS].channels_mask |= ( 1 << 26 );
527     ppi_ch_tasks[26].tep_f = nrf_timer0_TASK_CAPTURE_1; //TIMER0->TASKS_CAPTURE[1]
528 
529   //  27 RADIO->EVENTS_END TIMER0->TASKS_CAPTURE[2]
530     ppi_evt_to_ch[RADIO_EVENTS_END].channels_mask |= ( 1 << 27 );
531     ppi_ch_tasks[27].tep_f = nrf_timer0_TASK_CAPTURE_2; //TIMER0->TASKS_CAPTURE[2]
532 
533   //  28 RTC0->EVENTS_COMPARE[0] RADIO->TASKS_TXEN
534     ppi_evt_to_ch[RTC0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 28 );
535     ppi_ch_tasks[28].tep_f = nrf_radio_tasks_TXEN; //RADIO->TASKS_TXEN
536 
537   //  29 RTC0->EVENTS_COMPARE[0] RADIO->TASKS_RXEN
538     ppi_evt_to_ch[RTC0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 29 );
539     ppi_ch_tasks[29].tep_f = nrf_radio_tasks_RXEN; //RADIO->TASKS_RXEN
540 
541   //  30 RTC0->EVENTS_COMPARE[0] TIMER0->TASKS_CLEAR
542     ppi_evt_to_ch[RTC0_EVENTS_COMPARE_0].channels_mask |= ( 1 << 30 );
543     ppi_ch_tasks[30].tep_f = nrf_timer0_TASK_CLEAR; //TIMER0->TASKS_CLEAR
544 
545   //  31 RTC0->EVENTS_COMPARE[0] TIMER0->TASKS_START
546     ppi_evt_to_ch[RTC0_EVENTS_COMPARE_0].channels_mask |= ( (uint32_t)1 << 31 );
547     ppi_ch_tasks[31].tep_f = nrf_timer0_TASK_START; //TIMER0->TASKS_START
548 }
549 
550 /**
551  * Initialize the PPI model
552  */
nrf_ppi_init()553 void nrf_ppi_init(){
554   memset(&NRF_PPI_regs, 0, sizeof(NRF_PPI_regs));
555   memset(ppi_ch_tasks, 0, sizeof(ppi_ch_tasks));
556   memset(ppi_evt_to_ch, 0, sizeof(ppi_evt_to_ch));
557   set_fixed_channel_routes();
558 }
559 
560 /**
561  * Cleanup the PPI model before exiting the program
562  */
nrf_ppi_clean_up()563 void nrf_ppi_clean_up(){
564 
565 }
566 
567 /**
568  * HW models call this function when they want to signal an event which
569  * may trigger a task
570  */
nrf_ppi_event(ppi_event_types_t event)571 void nrf_ppi_event(ppi_event_types_t event){
572 
573   uint32_t ch_mask = ppi_evt_to_ch[event].channels_mask;
574   ch_mask &= NRF_PPI_regs.CHEN;
575 
576   if ( ch_mask ){
577     for ( int ch_nbr = __builtin_ffs(ch_mask) - 1;
578           ( ch_mask != 0 ) && ( ch_nbr < NUMBER_PPI_CHANNELS ) ;
579           ch_nbr++ ) {
580       if ( ch_mask & ( 1 << ch_nbr ) ){
581         ch_mask &= ~( (uint64_t) 1 << ch_nbr );
582         if ( ppi_ch_tasks[ch_nbr].tep_f != NULL ){
583           ppi_ch_tasks[ch_nbr].tep_f();
584         }
585         if ( ppi_ch_tasks[ch_nbr].fork_tep_f != NULL ){
586           ppi_ch_tasks[ch_nbr].fork_tep_f();
587         }
588       } //if event is mapped to this channel
589     } //for channels
590   } //if this event is in any channel
591 }
592 
593 /**
594  * Find the task in ppi_tasks_table whose address
595  * matches <TEP> and save the task handling function <in dest>
596  *
597  * Helper function for the TEP and FORK_TEP functions
598  */
find_task(void * TEP,dest_f_t * dest,int ch_nbr)599 static void find_task(void *TEP, dest_f_t *dest, int ch_nbr){
600   int tt = 0;
601   while ( ppi_tasks_table[tt].task_addr != NULL ){
602     if ( ppi_tasks_table[tt].task_addr == TEP ){
603        *dest = ppi_tasks_table[tt].dest;
604        return;
605     }
606     tt++;
607   }
608   bs_trace_warning_line_time(
609       "NRF_PPI: The task %p for chnbr %i does not match any modelled task in NRF_PPI.c => it will be ignored\n",
610       TEP, ch_nbr);
611 
612   *dest = NULL;
613 }
614 
615 /**
616  * Update PPI internal routing status after a
617  * CH[<ch_nbr>].EEP update
618  */
nrf_ppi_regw_sideeffects_EEP(int ch_nbr)619 void nrf_ppi_regw_sideeffects_EEP(int ch_nbr){
620   //To save execution time when an event is raised, we build the
621   //ppi_event_config_table & ppi_channel_config_table out of the registers
622 
623   //first remove this channel from all events masks
624   for (int i = 0 ; i < NUMBER_PPI_EVENTS ; i++){
625     ppi_evt_to_ch[i].channels_mask &= ~( 1 << ch_nbr );
626   }
627 
628   //then lets try to find which event (if any) is feeding this channel
629   if ( ( ch_nbr < 20 ) && ( (void*)NRF_PPI_regs.CH[ch_nbr].EEP != NULL ) ){
630     int i = 0;
631     while ( ppi_events_table[i].event_type != NUMBER_PPI_EVENTS ){
632       if ( ppi_events_table[i].event_addr == (void*)NRF_PPI_regs.CH[ch_nbr].EEP ) {
633         ppi_evt_to_ch[ppi_events_table[i].event_type].channels_mask |= ( 1 << ch_nbr );
634         return;
635       }
636       i++;
637     }
638     bs_trace_warning_line_time(
639         "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",
640         ch_nbr, NRF_PPI_regs.CH[ch_nbr].EEP);
641   }
642 }
643 
644 /**
645  * Update PPI internal routing status after a
646  * CH[<ch_nbr>].TEP update
647  */
nrf_ppi_regw_sideeffects_TEP(int ch_nbr)648 void nrf_ppi_regw_sideeffects_TEP(int ch_nbr){
649   //To save execution time when an event is raised, we build the
650   //ppi_event_config_table & ppi_channel_config_table out of the registers
651   if ( ch_nbr < 20 ){
652     if ( (void*)NRF_PPI_regs.CH[ch_nbr].TEP != NULL ){
653       find_task((void*)NRF_PPI_regs.CH[ch_nbr].TEP,
654                 &ppi_ch_tasks[ch_nbr].tep_f,
655                 ch_nbr);
656     } else {
657       ppi_ch_tasks[ch_nbr].tep_f = NULL;
658     }
659   }
660 }
661 /**
662  * Update PPI internal routing status after a
663  * FORK[<ch_nbr>].TEP update
664  */
nrf_ppi_regw_sideeffects_FORK_TEP(int ch_nbr)665 void nrf_ppi_regw_sideeffects_FORK_TEP(int ch_nbr){
666   if ( (void*)NRF_PPI_regs.FORK[ch_nbr].TEP != NULL ){
667     find_task((void*)NRF_PPI_regs.FORK[ch_nbr].TEP,
668               &ppi_ch_tasks[ch_nbr].fork_tep_f,
669               ch_nbr);
670   } else {
671     ppi_ch_tasks[ch_nbr].fork_tep_f = NULL;
672   }
673 }
674 
675 /**
676  * Update PPI CHEN mask after a write to CHENSET
677  * (writes to CHEN do not need sideeffects)
678  */
nrf_ppi_regw_sideeffects_CHENSET()679 void nrf_ppi_regw_sideeffects_CHENSET(){
680 	if ( NRF_PPI_regs.CHENSET != 0 ){
681 		NRF_PPI_regs.CHEN |= NRF_PPI_regs.CHENSET;
682 		NRF_PPI_regs.CHENSET = 0;
683 	}
684 }
685 
686 /**
687  * Update PPI CHEN mask after a write to CHENCLR
688  * (writes to CHEN do not need sideeffects)
689  */
nrf_ppi_regw_sideeffects_CHENCLR()690 void nrf_ppi_regw_sideeffects_CHENCLR(){
691 	if ( NRF_PPI_regs.CHENCLR != 0 ){
692 		NRF_PPI_regs.CHEN &= ~NRF_PPI_regs.CHENCLR;
693 		NRF_PPI_regs.CHENCLR = 0;
694 	}
695 }
696 
697 /**
698  * Update PPI CHEN mask after a write to CHENSET or CHENCLR
699  * (writes to CHEN do not need sideeffects)
700  */
nrf_ppi_regw_sideeffects_CHEN()701 void nrf_ppi_regw_sideeffects_CHEN(){
702 	//Note that we do not let people read CHEN from the SET and CLR
703 	//registers
704 	nrf_ppi_regw_sideeffects_CHENSET();
705 	nrf_ppi_regw_sideeffects_CHENCLR();
706 }
707 
708 /**
709  * If you dont want to bother about individual calls,
710  * when any PPI register is written which changes the configuration of the PPI
711  * call this to update the routing table or cause other sideeffects
712  * This call will inspect all input registers
713  *
714  * (otherwise call the correspondent sideeffect function above for each register
715  * write)
716  */
nrf_ppi_regw_sideeffects()717 void nrf_ppi_regw_sideeffects(){
718 
719   for (int ch_nbr = 0; ch_nbr < 32 ; ch_nbr++){
720     if ( ch_nbr < 20 ){
721       nrf_ppi_regw_sideeffects_EEP(ch_nbr);
722       nrf_ppi_regw_sideeffects_TEP(ch_nbr);
723     }
724     nrf_ppi_regw_sideeffects_FORK_TEP(ch_nbr);
725   }
726 
727   nrf_ppi_regw_sideeffects_CHEN();
728 }
729 
nrf_ppi_regw_sideeffects_TASKS_CHG_DIS(int i)730 void nrf_ppi_regw_sideeffects_TASKS_CHG_DIS(int i){
731 	if ( NRF_PPI_regs.TASKS_CHG[i].DIS ) {
732 		NRF_PPI_regs.TASKS_CHG[i].DIS = 0;
733 		nrf_ppi_TASK_CHG_ENDIS( i, false );
734 	}
735 }
736 
nrf_ppi_regw_sideeffects_TASKS_CHG_EN(int i)737 void nrf_ppi_regw_sideeffects_TASKS_CHG_EN(int i){
738 	if ( NRF_PPI_regs.TASKS_CHG[i].EN ) {
739 		NRF_PPI_regs.TASKS_CHG[i].EN = 0;
740 		nrf_ppi_TASK_CHG_ENDIS( i, true );
741 	}
742 }
743 
nrf_ppi_taskw_sideeffects()744 void nrf_ppi_taskw_sideeffects(){
745 	int i;
746 	for ( i = 0 ; i < 6 ; i++){
747 		nrf_ppi_regw_sideeffects_TASKS_CHG_DIS(i);
748 	}
749 	for ( i = 0 ; i < 6 ; i++){
750 		nrf_ppi_regw_sideeffects_TASKS_CHG_EN(i);
751 	}
752 }
753