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  * This file includes the RADIO event & signals functionality,
8  * the registers writes sideeffects for tasks, subscriptions, events,
9  * and interrupt masks.
10  * For signals, when a signal is generated:
11  *   Setting the EVENTS registers
12  *   Sending the signal to the PPI
13  *   Generating the corresponding interrupts
14  *   Calling tasks if the corresponding shortcuts are enabled
15  *
16  *
17  */
18 
19 #include "NHW_common_types.h"
20 #include "NHW_templates.h"
21 #include "NHW_config.h"
22 #include "NHW_peri_types.h"
23 #include "NHW_RADIO.h"
24 #include "NHW_RADIO_utils.h"
25 #include "NHW_xPPI.h"
26 #include "irq_ctrl.h"
27 #include "bs_tracing.h"
28 
29 #if (NHW_HAS_DPPI)
30 /* Mapping of peripheral instance to DPPI instance */
31 static uint nhw_RADIO_dppi_map[NHW_RADIO_TOTAL_INST] = NHW_RADIO_DPPI_MAP;
32 #endif
33 static uint32_t RADIO_INTEN; //interrupt enable
34 extern NRF_RADIO_Type NRF_RADIO_regs;
35 
36 extern void nhw_RADIO_fake_task_TRXEN_TIFS(void);
37 
nhwra_signalif_reset(void)38 void nhwra_signalif_reset(void){
39   RADIO_INTEN = 0;
40 }
41 
nhw_RADIO_eval_interrupt(uint inst)42 static void nhw_RADIO_eval_interrupt(uint inst) {
43   static bool radio_int_line[NHW_RADIO_TOTAL_INST]; /* Is the RADIO currently driving its interrupt line high */
44   /* Mapping of peripheral instance to {int controller instance, int number} */
45   static struct nhw_irq_mapping nhw_radio_irq_map[NHW_RADIO_TOTAL_INST] = NHW_RADIO_INT_MAP;
46   bool new_int_line = false;
47 
48   NHW_CHECK_INTERRUPT_si(RADIO, READY, RADIO_INTEN)
49   NHW_CHECK_INTERRUPT_si(RADIO, ADDRESS, RADIO_INTEN)
50   NHW_CHECK_INTERRUPT_si(RADIO, PAYLOAD, RADIO_INTEN)
51   NHW_CHECK_INTERRUPT_si(RADIO, END, RADIO_INTEN)
52   NHW_CHECK_INTERRUPT_si(RADIO, DISABLED, RADIO_INTEN)
53   NHW_CHECK_INTERRUPT_si(RADIO, DEVMATCH, RADIO_INTEN)
54   NHW_CHECK_INTERRUPT_si(RADIO, DEVMISS, RADIO_INTEN)
55   NHW_CHECK_INTERRUPT_si(RADIO, RSSIEND, RADIO_INTEN)
56   NHW_CHECK_INTERRUPT_si(RADIO, BCMATCH, RADIO_INTEN)
57   NHW_CHECK_INTERRUPT_si(RADIO, CRCOK, RADIO_INTEN)
58   NHW_CHECK_INTERRUPT_si(RADIO, CRCERROR, RADIO_INTEN)
59   NHW_CHECK_INTERRUPT_si(RADIO, FRAMESTART, RADIO_INTEN)
60   NHW_CHECK_INTERRUPT_si(RADIO, EDEND, RADIO_INTEN)
61   NHW_CHECK_INTERRUPT_si(RADIO, EDSTOPPED, RADIO_INTEN)
62   NHW_CHECK_INTERRUPT_si(RADIO, CCAIDLE, RADIO_INTEN)
63   NHW_CHECK_INTERRUPT_si(RADIO, CCABUSY, RADIO_INTEN)
64   NHW_CHECK_INTERRUPT_si(RADIO, CCASTOPPED, RADIO_INTEN)
65   NHW_CHECK_INTERRUPT_si(RADIO, RATEBOOST, RADIO_INTEN)
66   NHW_CHECK_INTERRUPT_si(RADIO, TXREADY, RADIO_INTEN)
67   NHW_CHECK_INTERRUPT_si(RADIO, RXREADY, RADIO_INTEN)
68   NHW_CHECK_INTERRUPT_si(RADIO, MHRMATCH, RADIO_INTEN)
69   NHW_CHECK_INTERRUPT_si(RADIO, SYNC, RADIO_INTEN)
70   NHW_CHECK_INTERRUPT_si(RADIO, PHYEND, RADIO_INTEN)
71   NHW_CHECK_INTERRUPT_si(RADIO, CTEPRESENT, RADIO_INTEN)
72 
73   hw_irq_ctrl_toggle_level_irq_line_if(&radio_int_line[inst],
74                                        new_int_line,
75                                        &nhw_radio_irq_map[inst]);
76 }
77 
78 NHW_SIDEEFFECTS_INTSET_si(RADIO, NRF_RADIO_regs., RADIO_INTEN)
79 NHW_SIDEEFFECTS_INTCLR_si(RADIO, NRF_RADIO_regs., RADIO_INTEN)
80 
NHW_SIDEEFFECTS_EVENTS(RADIO)81 NHW_SIDEEFFECTS_EVENTS(RADIO)
82 
83 static NHW_SIGNAL_EVENT_ns_si(RADIO, READY)
84 static NHW_SIGNAL_EVENT_ns_si(RADIO, ADDRESS)
85 NHW_SIGNAL_EVENT_si(RADIO, PAYLOAD)
86 static NHW_SIGNAL_EVENT_ns_si(RADIO, END)
87 static NHW_SIGNAL_EVENT_ns_si(RADIO, DISABLED)
88 NHW_SIGNAL_EVENT_si(RADIO, DEVMATCH)
89 NHW_SIGNAL_EVENT_si(RADIO, DEVMISS)
90 NHW_SIGNAL_EVENT_si(RADIO, RSSIEND)
91 NHW_SIGNAL_EVENT_si(RADIO, BCMATCH)
92 NHW_SIGNAL_EVENT_si(RADIO, CRCOK)
93 NHW_SIGNAL_EVENT_si(RADIO, CRCERROR)
94 static NHW_SIGNAL_EVENT_ns_si(RADIO, FRAMESTART)
95 static NHW_SIGNAL_EVENT_ns_si(RADIO, EDEND)
96 NHW_SIGNAL_EVENT_si(RADIO, EDSTOPPED)
97 static NHW_SIGNAL_EVENT_ns_si(RADIO, CCAIDLE)
98 static NHW_SIGNAL_EVENT_ns_si(RADIO, CCABUSY)
99 NHW_SIGNAL_EVENT_si(RADIO, CCASTOPPED)
100 NHW_SIGNAL_EVENT_si(RADIO, RATEBOOST)
101 static NHW_SIGNAL_EVENT_ns_si(RADIO, TXREADY)
102 static NHW_SIGNAL_EVENT_ns_si(RADIO, RXREADY)
103 NHW_SIGNAL_EVENT_si(RADIO, MHRMATCH)
104 NHW_SIGNAL_EVENT_si(RADIO, SYNC)
105 static NHW_SIGNAL_EVENT_ns_si(RADIO, PHYEND)
106 NHW_SIGNAL_EVENT_si(RADIO, CTEPRESENT)
107 
108 void nhw_RADIO_signal_EVENTS_READY(unsigned int inst) {
109   nhw_RADIO_signal_EVENTS_READY_noshort(inst);
110 
111   NHW_SHORT_si(RADIO, READY, START)
112   NHW_SHORT_si(RADIO, READY, EDSTART)
113 }
114 
nhw_RADIO_signal_EVENTS_ADDRESS(unsigned int inst)115 void nhw_RADIO_signal_EVENTS_ADDRESS(unsigned int inst) {
116   nhw_RADIO_signal_EVENTS_ADDRESS_noshort(inst);
117 
118   NHW_SHORT_si(RADIO, ADDRESS, RSSISTART)
119   NHW_SHORT_si(RADIO, ADDRESS, BCSTART)
120 }
121 
nhw_RADIO_signal_EVENTS_END(unsigned int inst)122 void nhw_RADIO_signal_EVENTS_END(unsigned int inst) {
123   nhw_RADIO_signal_EVENTS_END_noshort(inst);
124 
125   NHW_SHORT_si(RADIO, END, DISABLE)
126   NHW_SHORT_si(RADIO, END, START)
127 }
128 
nhw_RADIO_signal_EVENTS_DISABLED(unsigned int inst)129 void nhw_RADIO_signal_EVENTS_DISABLED(unsigned int inst) {
130   nhw_RADIO_signal_EVENTS_DISABLED_noshort(inst);
131 
132   /*
133    * Everything indicates that, when the HW TIFS is enabled
134    * what happens is that these DISABLED_[TR]XEN shorts are
135    * effectively disabled and the tasks_[TR]XEN is instead
136    * triggered when a HW counter/timer triggers a bit later
137    */
138   if (nhwra_is_HW_TIFS_enabled()) {
139      /* This is a fake task meant to start a HW timer for the TIFS
140       * which has effect only if the TIFS was enabled.
141       * In that case, the TXEN or RXEN will be triggered in a small
142       * while (as per the TIFS configuration/Timer_TIFS), instead of right now */
143       nhw_RADIO_fake_task_TRXEN_TIFS();
144   } else {
145     /* Otherwise the normal TXEN/RXEN shortcuts apply */
146     NHW_SHORT_si(RADIO, DISABLED, TXEN)
147     NHW_SHORT_si(RADIO, DISABLED, RXEN)
148   }
149 
150   NHW_SHORT_si(RADIO, DISABLED, RSSISTOP)
151 }
152 
nhw_RADIO_signal_EVENTS_FRAMESTART(unsigned int inst)153 void nhw_RADIO_signal_EVENTS_FRAMESTART(unsigned int inst) {
154   nhw_RADIO_signal_EVENTS_FRAMESTART_noshort(inst);
155 
156   NHW_SHORT_si(RADIO, FRAMESTART, BCSTART)
157 }
158 
nhw_RADIO_signal_EVENTS_EDEND(unsigned int inst)159 void nhw_RADIO_signal_EVENTS_EDEND(unsigned int inst) {
160   nhw_RADIO_signal_EVENTS_EDEND_noshort(inst);
161 
162   NHW_SHORT_si(RADIO, EDEND, DISABLE)
163 }
164 
nhw_RADIO_signal_EVENTS_CCAIDLE(unsigned int inst)165 void nhw_RADIO_signal_EVENTS_CCAIDLE(unsigned int inst) {
166   nhw_RADIO_signal_EVENTS_CCAIDLE_noshort(inst);
167 
168   NHW_SHORT_si(RADIO, CCAIDLE, STOP)
169   NHW_SHORT_si(RADIO, CCAIDLE, TXEN)
170 }
171 
nhw_RADIO_signal_EVENTS_CCABUSY(unsigned int inst)172 void nhw_RADIO_signal_EVENTS_CCABUSY(unsigned int inst) {
173   nhw_RADIO_signal_EVENTS_CCABUSY_noshort(inst);
174 
175   NHW_SHORT_si(RADIO, CCABUSY, DISABLE)
176 }
177 
nhw_RADIO_signal_EVENTS_TXREADY(unsigned int inst)178 void nhw_RADIO_signal_EVENTS_TXREADY(unsigned int inst) {
179   nhw_RADIO_signal_EVENTS_TXREADY_noshort(inst);
180 
181   NHW_SHORT_si(RADIO, TXREADY, START)
182 }
183 
nhw_RADIO_signal_EVENTS_RXREADY(unsigned int inst)184 void nhw_RADIO_signal_EVENTS_RXREADY(unsigned int inst) {
185   nhw_RADIO_signal_EVENTS_RXREADY_noshort(inst);
186 
187   NHW_SHORT_si(RADIO, RXREADY, START)
188   NHW_SHORT_si(RADIO, RXREADY, CCASTART)
189 }
190 
nhw_RADIO_signal_EVENTS_PHYEND(unsigned int inst)191 void nhw_RADIO_signal_EVENTS_PHYEND(unsigned int inst) {
192   nhw_RADIO_signal_EVENTS_PHYEND_noshort(inst);
193 
194   NHW_SHORT_si(RADIO, PHYEND, DISABLE)
195   NHW_SHORT_si(RADIO, PHYEND, START)
196 }
197 
198 
199 extern NRF_RADIO_Type NRF_RADIO_regs;
200 
201 
NHW_SIDEEFFECTS_TASKS_si(RADIO,TXEN)202 NHW_SIDEEFFECTS_TASKS_si(RADIO, TXEN)
203 NHW_SIDEEFFECTS_TASKS_si(RADIO, RXEN)
204 NHW_SIDEEFFECTS_TASKS_si(RADIO, START)
205 NHW_SIDEEFFECTS_TASKS_si(RADIO, STOP)
206 NHW_SIDEEFFECTS_TASKS_si(RADIO, DISABLE)
207 
208 void nhw_RADIO_regw_sideeffects_TASKS_RSSISTART(void) {
209   //We don't need to model this yet
210   if ( NRF_RADIO_regs.TASKS_RSSISTART ){
211     NRF_RADIO_regs.TASKS_RSSISTART = 0;
212     bs_trace_warning_line_time("RADIO: Sampling RSSI by writing to TASK_RSSISTART register is not supported by the model yet\n");
213   }
214 }
215 
nhw_RADIO_regw_sideeffects_TASKS_RSSISTOP(void)216 void nhw_RADIO_regw_sideeffects_TASKS_RSSISTOP(void) {
217   //We don't need to model this yet
218   if ( NRF_RADIO_regs.TASKS_RSSISTOP ){
219     NRF_RADIO_regs.TASKS_RSSISTOP = 0;
220     bs_trace_warning_line_time("RADIO: Sampling RSSI by writing to TASK_RSSISTOP register is not supported by the model yet\n");
221   }
222 }
223 
224 NHW_SIDEEFFECTS_TASKS_si(RADIO, BCSTART)
225 NHW_SIDEEFFECTS_TASKS_si(RADIO, BCSTOP)
226 NHW_SIDEEFFECTS_TASKS_si(RADIO, EDSTART)
227 NHW_SIDEEFFECTS_TASKS_si(RADIO, EDSTOP)
228 NHW_SIDEEFFECTS_TASKS_si(RADIO, CCASTART)
229 NHW_SIDEEFFECTS_TASKS_si(RADIO, CCASTOP)
230 
231 #if (NHW_HAS_DPPI)
232 NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, TXEN)
233 NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, RXEN)
234 NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, START)
235 NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, STOP)
236 NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, DISABLE)
237 NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, RSSISTART)
238 NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, RSSISTOP)
239 NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, BCSTART)
240 NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, BCSTOP)
241 NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, EDSTART)
242 NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, EDSTOP)
243 NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, CCASTART)
244 NHW_SIDEEFFECTS_SUBSCRIBE_si(RADIO, CCASTOP)
245 #endif /* NHW_HAS_DPPI */
246