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