1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 /*
7 * UART(E) - Universal asynchronous receiver/transmitter (with EasyDMA)
8 * https://infocenter.nordicsemi.com/topic/ps_nrf52833/uart.html?cp=5_1_0_5_30
9 * https://infocenter.nordicsemi.com/topic/ps_nrf52833/uarte.html?cp=5_1_0_5_317
10 *
11 * https://infocenter.nordicsemi.com/topic/ps_nrf5340/uarte.html?cp=4_0_0_6_37
12 */
13
14 /**
15 * Notes (common for all):
16 * * Check the selected backend notes, for more possible limitations
17 *
18 * * PSEL is ignored, pins are assumed connected.
19 *
20 * * Unlike in real HW, it is irrelevant if the external oscillator is enabled
21 * or not. The UART timing will always be equally precise.
22 *
23 * * After a STARTTX, the UART is ready to Tx right away
24 * (it does not take ~1 us as in the real HW)
25 *
26 * * The effective transmit rate is going to be marginally different than in reality, due to
27 * rounding of the frame time to an integer number of microseconds, and the
28 * logic having immediate response time.
29 *
30 * * Data line errors (parity, framing, break) are not yet modelled
31 *
32 * * (UART) In UART mode, in real HW, a TASK_STOPTX would break a currently ongoing Tx frame
33 * mid way, while in this model, the Tx is allowed to finish (just like for a TASK_SUSPEND
34 * or a TASK_STOPTX in UART-E mode).
35 * Due to this, in the model, a (UART) TASK_SUSPEND is equivalent to a combination of
36 * TASK_STOPTX & TASK_STOPRX, while in real HW it is not.
37 *
38 * * (UART) In real HW, it is unclear what happens when a STOPTX (in UART mode) is triggered, while
39 * a byte is queued for transmission (TXD was written), but where the transmission hasn't started
40 * yet due to the CTS line holding it. It seems the blocked pended Tx is just dropped/forgotten
41 * This is how the model behaves.
42 * * (UARTE) In real HW, when a STOPTX task is triggered (in UARTE mode),
43 * while a byte is queued for transmission, but where the transmission hasn't started yet
44 * due to the CTS line holding it. It seems that the blocked pended Tx is just dropped
45 * (and therefore TXSTOPPED comes right away).
46 * This is how the model behaves.
47 *
48 * * (UART & UARTE) It seems in real HW the Rx FIFO status is kept after a STOPRX & a new STARTRX.
49 * and (if flow control is on) will lower RTS on STARTRX only if the FIFO is empty.
50 * The model behaves this way.
51 *
52 * * In real HW, it seems RTS will be kept high (if flow control is on) if EITHER the Rx FIFO
53 * got more than 2 bytes used, and did not come back to empty yet, OR the Rx is not started/or stopped.
54 * (so just starting it, will not clear RTS unless the FIFO was emptied)
55 * The model behaves this way.
56 *
57 * * In real HW, it seems all internal status is lost when the enable register is cleared.
58 * The HW models behaves this way.
59 *
60 * * 52:
61 * * The plain UART functionality is present in all UARTEs,
62 * for the nRF52
63 *
64 * * 54:
65 * * DMA_{RX,TX}.TERMINATEONBUSERROR is ignored EVENTS_DMA.{RX,TX}.BUSERROR is never generated
66 * and BUSERRORADDRESS is never set
67 *
68 * * From the spec is unclear when DMA.RX.MATCH.CANDIDATE[n] is copied into the internal shadow
69 * register. It would seem it will happen when either TASKS_DMA.RX.START is triggered,
70 * or EVENTS_MATCH[n] happens. This is what the model does.
71 *
72 * * MATCH functionality is untested in this model
73 *
74 * * FRAMESIZE != 8 and ADDRESS functionality is untested in this model
75 *
76 * Implementation notes:
77 * * As for the 54 the data in the line can be a configurable amount between 4 and 9bits (due to address bit),
78 * the "byte" parameters were increased to 16bits. But the naming was kept in most of them as "byte".
79 */
80
81 #include <stdbool.h>
82 #include <stdint.h>
83 #include <string.h>
84 #include "NHW_common_types.h"
85 #include "NHW_config.h"
86 #include "NHW_peri_types.h"
87 #include "NHW_templates.h"
88 #include "NHW_UART.h"
89 #include "NHW_UART_private.h"
90 #include "NHW_UART_backend_if.h"
91 #include "NHW_xPPI.h"
92 #include "irq_ctrl.h"
93 #include "bs_tracing.h"
94 #include "bs_oswrap.h"
95 #include "bs_utils.h"
96 #include "bs_cmd_line.h"
97 #include "bs_dynargs.h"
98 #include "nsi_hw_scheduler.h"
99 #include "nsi_tasks.h"
100 #include "nsi_hws_models_if.h"
101
102 static struct uarte_status nhw_uarte_st[NHW_UARTE_TOTAL_INST];
103 NRF_UARTE_Type NRF_UARTE_regs[NHW_UARTE_TOTAL_INST];
104 #if (NHW_UARTE_HAS_UART)
105 NRF_UART_Type *NRF_UART_regs[NHW_UARTE_TOTAL_INST];
106 #endif
107
108 static bs_time_t Timer_UART_common = TIME_NEVER;
109 static bs_time_t Timer_UART_peri = TIME_NEVER;
110 extern bs_time_t nhw_Timer_ULoopback;
111
112 static void nhw_UARTE_signal_EVENTS_ERROR(unsigned int inst);
113 static void nhw_UARTE_signal_EVENTS_RXDRDY(unsigned int inst);
114 static void nhw_UARTE_signal_EVENTS_RXTO(unsigned int inst);
115 static void nhw_UARTE_signal_EVENTS_TXDRDY(unsigned int inst);
116 static void nhw_UARTE_signal_EVENTS_CTS(unsigned int inst);
117 static void nhw_UARTE_signal_EVENTS_NCTS(unsigned int inst);
118 static void nhw_UARTE_signal_EVENTS_TXSTARTED(unsigned int inst);
119 static void nhw_UARTE_signal_EVENTS_TXSTOPPED(unsigned int inst);
120 static void nhw_UARTE_signal_EVENTS_ENDTX(unsigned int inst);
121 static void nhw_UARTE_signal_EVENTS_RXSTARTED(unsigned int inst);
122 static void nhw_UARTE_signal_EVENTS_ENDRX(unsigned int inst);
123 #if (NHW_UARTE_HAS_FRAMETIMEOUT)
124 static void nhw_UARTE_signal_EVENTS_FRAMETIMEOUT(unsigned int inst);
125 #endif
126 #if (NHW_UARTE_HAS_MATCH)
127 static void nhw_UARTE_signal_EVENTS_DMA_RX_MATCH(unsigned int inst, unsigned int i);
128 #endif
129 static void nhw_UARTE_Tx_send_byte(unsigned int inst, struct uarte_status *u_el);
130 static void nhw_UART_Tx_queue_byte(uint inst, struct uarte_status *u_el, uint16_t byte);
131 static void nhw_UARTE_Rx_DMA_attempt(uint inst, struct uarte_status *u_el);
132 static void raise_RTS_R(uint inst, struct uarte_status *u_el);
133
nhw_uarte_init(void)134 static void nhw_uarte_init(void) {
135 #if (NHW_HAS_DPPI)
136 static uint nhw_UARTE_dppi_map[NHW_UARTE_TOTAL_INST] = NHW_UARTE_DPPI_MAP;
137 #endif
138 #if NHW_UARTE_HAS_MATCH
139 int n_match[] = NHW_UARTE_N_MATCH;
140 #endif
141
142 memset(NRF_UARTE_regs, 0, sizeof(NRF_UARTE_regs));
143
144 uint uart_clocks[] = NHW_UARTE_CLOCKS;
145
146 for (int i = 0; i < NHW_UARTE_TOTAL_INST; i++) {
147 struct uarte_status *u_el = &nhw_uarte_st[i];
148
149 u_el->inst = i;
150 u_el->clock_f = uart_clocks[i];
151
152 #if (NHW_UARTE_HAS_UART)
153 NRF_UART_regs[i] = (NRF_UART_Type *)&NRF_UARTE_regs[i];
154 u_el->UART_regs[i] = (NRF_UART_Type *)&NRF_UARTE_regs[i];
155 #endif
156 u_el->UARTE_regs[i] = (NRF_UARTE_Type *)&NRF_UARTE_regs[i];
157
158 u_el->Rx_TO_timer = TIME_NEVER;
159 u_el->Tx_byte_done_timer = TIME_NEVER;
160 u_el->frametimeout_timer = TIME_NEVER;
161
162 NRF_UARTE_regs[i].PSEL.RTS = 0xFFFFFFFF;
163 NRF_UARTE_regs[i].PSEL.TXD = 0xFFFFFFFF;
164 NRF_UARTE_regs[i].PSEL.CTS = 0xFFFFFFFF;
165 NRF_UARTE_regs[i].PSEL.RXD = 0xFFFFFFFF;
166 NRF_UARTE_regs[i].BAUDRATE = 0x04000000;
167
168 #if NHW_UARTE_HAS_MATCH
169 u_el->n_match = n_match[i];
170 u_el->MATCH_CANDIDATE = bs_calloc(n_match[i], sizeof(uint32_t));
171 u_el->DMA_RX_ENABLEMATCH_subscribed = bs_calloc(n_match[i], sizeof(struct nhw_subsc_mem));
172 u_el->DMA_RX_DISABLEMATCH_subscribed = bs_calloc(n_match[i], sizeof(struct nhw_subsc_mem));
173 #endif
174
175 #if (NHW_HAS_DPPI)
176 u_el->dppi_map = nhw_UARTE_dppi_map[i];
177 #endif
178
179 raise_RTS_R(i, u_el);
180
181 if (u_el->Tx_log_file_name) {
182 bs_create_folders_in_path(u_el->Tx_log_file_name);
183 u_el->Tx_log_file = bs_fopen(u_el->Tx_log_file_name, "w");
184 fprintf(u_el->Tx_log_file, "time(microsecond),byte\n");
185 }
186 if (u_el->Rx_log_file_name) {
187 bs_create_folders_in_path(u_el->Rx_log_file_name);
188 u_el->Rx_log_file = bs_fopen(u_el->Rx_log_file_name, "w");
189 fprintf(u_el->Rx_log_file, "time(microsecond),byte\n");
190 }
191 }
192 }
193
194 NSI_TASK(nhw_uarte_init, HW_INIT, 200); /* Allow backend to be registered before */
195
nhw_uarte_cleanup(void)196 static void nhw_uarte_cleanup(void) {
197 for (int i = 0; i < NHW_UARTE_TOTAL_INST; i++) {
198 struct uarte_status *u_el = &nhw_uarte_st[i];
199 if (u_el->Tx_log_file) {
200 fclose(u_el->Tx_log_file);
201 u_el->Tx_log_file = NULL;
202 }
203 if (u_el->Rx_log_file) {
204 fclose(u_el->Rx_log_file);
205 u_el->Rx_log_file = NULL;
206 }
207 if (u_el->MATCH_CANDIDATE) {
208 free(u_el->MATCH_CANDIDATE);
209 u_el->MATCH_CANDIDATE = NULL;
210 }
211 #if (NHW_HAS_DPPI)
212 if (u_el->DMA_RX_ENABLEMATCH_subscribed) {
213 free(u_el->DMA_RX_ENABLEMATCH_subscribed);
214 u_el->DMA_RX_ENABLEMATCH_subscribed = NULL;
215 }
216 if (u_el->DMA_RX_DISABLEMATCH_subscribed) {
217 free(u_el->DMA_RX_DISABLEMATCH_subscribed);
218 u_el->DMA_RX_DISABLEMATCH_subscribed = NULL;
219 }
220 #endif
221 }
222 }
223
224 NSI_TASK(nhw_uarte_cleanup, ON_EXIT_PRE, 100);
225
nhw_uarte_register_rx_cb(int inst,uart_rtxb_cb_f cb,bool Rx_NotTx)226 uart_rtxb_cb_f nhw_uarte_register_rx_cb(int inst, uart_rtxb_cb_f cb, bool Rx_NotTx) {
227 struct uarte_status *u_el = &nhw_uarte_st[inst];
228 uart_rtxb_cb_f prev = u_el->trx_callbacks[(int) Rx_NotTx];
229 u_el->trx_callbacks[(int) Rx_NotTx] = cb;
230 return prev;
231 }
232
233 /*
234 * Register a backend to be used for a given UART instance
235 */
nhw_UARTE_backend_register(uint inst,struct backend_if * backend)236 void nhw_UARTE_backend_register(uint inst, struct backend_if *backend) {
237 struct uarte_status *u_el = &nhw_uarte_st[inst];
238
239 if (u_el->backend.tx_byte_f != NULL) {
240 bs_trace_warning_line("UART%i backend selection overwritten\n", inst);
241 }
242 memcpy(&u_el->backend, backend, sizeof(struct backend_if));
243 }
244
nhw_uarte_update_common_timer(void)245 void nhw_uarte_update_common_timer(void) {
246 Timer_UART_common = BS_MIN(Timer_UART_peri, nhw_Timer_ULoopback);
247 nsi_hws_find_next_event();
248 }
249
nhw_uarte_update_timer(void)250 static void nhw_uarte_update_timer(void) {
251 Timer_UART_peri = TIME_NEVER;
252 for (int i = 0; i < NHW_UARTE_TOTAL_INST; i++) {
253 struct uarte_status * u_el = &nhw_uarte_st[i];
254 bs_time_t smaller = BS_MIN(u_el->Rx_TO_timer, u_el->Tx_byte_done_timer);
255 #if (NHW_UARTE_HAS_FRAMETIMEOUT)
256 smaller = BS_MIN(smaller, u_el->frametimeout_timer);
257 #endif
258 Timer_UART_peri = BS_MIN(Timer_UART_peri, smaller);
259 }
260 nhw_uarte_update_common_timer();
261 }
262
uart_enabled(uint inst)263 static bool uart_enabled(uint inst) {
264 #if (NHW_UARTE_HAS_UART)
265 return NRF_UARTE_regs[inst].ENABLE == 4;
266 #else
267 (void) inst;
268 return false;
269 #endif
270 }
271
uarte_enabled(uint inst)272 static bool uarte_enabled(uint inst) {
273 return NRF_UARTE_regs[inst].ENABLE == 8;
274 }
275
276 /**
277 * Return the duration of 1 bit in seconds, given the BAUDRATE register
278 * value and the clock_frequency in Hz.
279 *
280 * Note that the actual bit rate is just 1.0/{nhw_uarte_bit_dur_from_reg()}
281 */
nhw_uarte_bit_dur_from_reg(uint32_t reg,int clock_freq)282 static inline double nhw_uarte_bit_dur_from_reg(uint32_t reg, int clock_freq) {
283 int cc_per_bit = ((uint64_t)1<<32) / reg;
284 return (double)cc_per_bit / clock_freq;
285 }
286
287 /*
288 * Return the duration of <nbits> bits in *microseconds*
289 */
nhw_uarte_nbits_time(uint inst,uint nbits)290 static inline bs_time_t nhw_uarte_nbits_time(uint inst, uint nbits) {
291 //We provide the frequency in MHz, so we are already scaled in micros.
292 return nbits * nhw_uarte_bit_dur_from_reg(NRF_UARTE_regs[inst].BAUDRATE, nhw_uarte_st[inst].clock_f) + 0.5;
293 }
294
nhw_uarte_get_frame_size(uint inst)295 static int nhw_uarte_get_frame_size(uint inst) {
296 uint frame_size = 8;
297 #if defined(UARTE_CONFIG_FRAMESIZE_Msk)
298 frame_size = (NRF_UARTE_regs[inst].CONFIG & UARTE_CONFIG_FRAMESIZE_Msk) >> UARTE_CONFIG_FRAMESIZE_Pos;
299 if (frame_size < 4 || frame_size > 9) {
300 frame_size = 8;
301 }
302 #else
303 (void) inst;
304 #endif
305 return frame_size;
306 }
307
308 /**
309 * Return the time in microseconds it takes for one byte to be Tx or Rx
310 * including start, parity and stop bits.
311 * Accounting for the UART configuration and baud rate
312 */
nhw_uarte_one_byte_time(uint inst)313 bs_time_t nhw_uarte_one_byte_time(uint inst) {
314 bs_time_t duration = 1 + 1; /* Start bit, and at least 1 stop bit */
315 uint32_t CONFIG = NRF_UARTE_regs[inst].CONFIG;
316
317 duration += nhw_uarte_get_frame_size(inst); /* data byte itself */
318
319 if (CONFIG & UARTE_CONFIG_PARITY_Msk) {
320 duration +=1;
321 }
322 if (CONFIG & UARTE_CONFIG_STOP_Msk) { /* Two stop bits */
323 duration +=1;
324 }
325
326 return nhw_uarte_nbits_time(inst, duration);
327 }
328
Rx_FIFO_pop(uint inst,struct uarte_status * u_el)329 static uint8_t Rx_FIFO_pop(uint inst, struct uarte_status *u_el) {
330 uint8_t value;
331
332 if (u_el->Rx_FIFO_cnt <= 0) {
333 bs_trace_warning_time_line("UART%i: Attempted empty Rx FIFO pop\n", inst);
334 return 0;
335 }
336
337 value = u_el->Rx_FIFO[0];
338
339 for (int i = 1; i < u_el->Rx_FIFO_cnt; i++) {
340 u_el->Rx_FIFO[i-1] = u_el->Rx_FIFO[i];
341 }
342 u_el->Rx_FIFO_cnt -=1;
343
344 if (u_el->Rx_FIFO_cnt > 0) {
345 #if (NHW_UARTE_HAS_UART)
346 NRF_UART_regs[inst]->RXD = u_el->Rx_FIFO[0];
347 #endif
348 nhw_UARTE_signal_EVENTS_RXDRDY(inst);
349 }
350
351 return value;
352 }
353
Rx_FIFO_push(uint inst,struct uarte_status * u_el,uint8_t value)354 static void Rx_FIFO_push(uint inst, struct uarte_status *u_el, uint8_t value) {
355 if (u_el->Rx_FIFO_cnt >= RX_FIFO_SIZE) {
356 Rx_FIFO_pop(inst, u_el);
357 bs_trace_warning_time_line("UART%i: Pushed to full Rx FIFO, oldest value dropped\n", inst);
358 NRF_UARTE_regs[inst].ERRORSRC |= UARTE_ERRORSRC_OVERRUN_Msk;
359 nhw_UARTE_signal_EVENTS_ERROR(inst);
360 }
361 u_el->Rx_FIFO[u_el->Rx_FIFO_cnt++] = value;
362
363 if (u_el->Rx_FIFO_cnt == 1){
364 #if (NHW_UARTE_HAS_UART)
365 NRF_UART_regs[inst]->RXD = u_el->Rx_FIFO[0];
366 #endif
367 nhw_UARTE_signal_EVENTS_RXDRDY(inst);
368 }
369 }
370
nhw_UARTE_Rx_DMA_end(uint inst,struct uarte_status * u_el)371 static void nhw_UARTE_Rx_DMA_end(uint inst, struct uarte_status * u_el) {
372 u_el->rx_dma_status = DMA_Off;
373 #if NHW_UARTE_54NAMING
374 NRF_UARTE_regs[inst].DMA.RX.AMOUNT = u_el->RXD_AMOUNT;
375 #else
376 NRF_UARTE_regs[inst].RXD.AMOUNT = u_el->RXD_AMOUNT;
377 #endif
378 nhw_UARTE_signal_EVENTS_ENDRX(inst);
379 }
380
nhw_UARTE_Rx_match_check(uint inst,struct uarte_status * u_el,uint32_t value)381 static void nhw_UARTE_Rx_match_check(uint inst, struct uarte_status * u_el, uint32_t value) {
382 #if (NHW_UARTE_HAS_MATCH)
383 for (int i = 0; i < u_el->n_match; i++) {
384 uint32_t enable_mask = (UARTE_DMA_RX_MATCH_CONFIG_ENABLE0_Msk << i);
385 if ((NRF_UARTE_regs[inst].DMA.RX.MATCH.CONFIG & enable_mask)
386 && (NRF_UARTE_regs[inst].DMA.RX.MATCH.CANDIDATE[i] == value)) {
387 NRF_UARTE_regs[inst].DMA.RX.AMOUNT = u_el->RXD_AMOUNT;
388 NRF_UARTE_regs[inst].DMA.TX.AMOUNT = u_el->TXD_AMOUNT;
389 nhw_uarte_st[inst].MATCH_CANDIDATE[i] = NRF_UARTE_regs[i].DMA.RX.MATCH.CANDIDATE[i];
390
391 if (NRF_UARTE_regs[inst].DMA.RX.MATCH.CONFIG & (UARTE_DMA_RX_MATCH_CONFIG_ONESHOT0_Msk << i)) {
392 NRF_UARTE_regs[inst].DMA.RX.MATCH.CONFIG &= ~enable_mask;
393 }
394 nhw_UARTE_signal_EVENTS_DMA_RX_MATCH(inst, i);
395 }
396 }
397 #else
398 (void) inst;
399 (void) u_el;
400 (void) value;
401 #endif
402 }
403
nhw_UARTE_Rx_DMA_attempt(uint inst,struct uarte_status * u_el)404 static void nhw_UARTE_Rx_DMA_attempt(uint inst, struct uarte_status * u_el) {
405 if (u_el->rx_dma_status != DMAing) {
406 return;
407 }
408
409 uint8_t *p = (uint8_t *)(u_el->RXD_PTR + u_el->RXD_AMOUNT);
410
411 while (u_el->Rx_FIFO_cnt && (u_el->RXD_AMOUNT < u_el->RXD_MAXCNT)) {
412 uint8_t value = Rx_FIFO_pop(inst, u_el);
413 *p++ = value;
414 u_el->RXD_AMOUNT++;
415 nhw_UARTE_Rx_match_check(inst, u_el, value);
416 }
417 if (u_el->RXD_AMOUNT >= u_el->RXD_MAXCNT) {
418 nhw_UARTE_Rx_DMA_end(inst, u_el);
419 }
420 }
421
flow_control_on(uint inst)422 static bool flow_control_on(uint inst) {
423 return (NRF_UARTE_regs[inst].CONFIG & UARTE_CONFIG_HWFC_Msk) != 0;
424 }
425
propagate_RTS_R(uint inst,struct uarte_status * u_el)426 static void propagate_RTS_R(uint inst, struct uarte_status *u_el) {
427 if (flow_control_on(inst)) {
428 if (u_el->backend.RTS_pin_toggle_f) {
429 u_el->backend.RTS_pin_toggle_f(inst, u_el->RTSR);
430 }
431 }
432 }
433
lower_RTS_R(uint inst,struct uarte_status * u_el)434 static void lower_RTS_R(uint inst, struct uarte_status *u_el) {
435 if (u_el->RTSR == false) {
436 return;
437 }
438 u_el->RTSR = false;
439 propagate_RTS_R(inst, u_el);
440 }
441
raise_RTS_R(uint inst,struct uarte_status * u_el)442 static void raise_RTS_R(uint inst, struct uarte_status *u_el) {
443 if (u_el->RTSR == true) {
444 return;
445 }
446 u_el->RTSR = true;
447 propagate_RTS_R(inst, u_el);
448 }
449
notify_backend_RxOnOff(uint inst,struct uarte_status * u_el,bool OnNotOff)450 static void notify_backend_RxOnOff(uint inst, struct uarte_status *u_el, bool OnNotOff) {
451 if (u_el->backend.uart_enable_notify_f) {
452 u_el->backend.uart_enable_notify_f(inst, u_el->tx_status != Tx_Off, OnNotOff);
453 }
454 }
455
notify_backend_TxOnOff(uint inst,struct uarte_status * u_el,bool OnNotOff)456 static void notify_backend_TxOnOff(uint inst, struct uarte_status *u_el, bool OnNotOff) {
457 if (u_el->backend.uart_enable_notify_f) {
458 u_el->backend.uart_enable_notify_f(inst, OnNotOff, u_el->rx_status != Rx_Off);
459 }
460 }
461
462 /*
463 * Process the receive frame (up to 9 bits including address)
464 * which may be to shift the data up (if it was less than 4 bits and ENDIAN was set)
465 *
466 * Returns true if the frame should be dropped (due to address filtering)
467 * False otherwise
468 */
nhw_UARTE_process_Rx_byte(uint inst,struct uarte_status * u_el,uint16_t * byte)469 static bool nhw_UARTE_process_Rx_byte(uint inst, struct uarte_status *u_el, uint16_t *byte) {
470 #if defined(UARTE_CONFIG_FRAMESIZE_Msk)
471 uint frame_size = nhw_uarte_get_frame_size(inst);
472
473 if (frame_size == 8) {
474 /* Let's handle the typical case fast */
475 } else if (frame_size < 8) {
476 if (NRF_UARTE_regs[inst].CONFIG & UARTE_CONFIG_ENDIAN_Msk) { //Cut from LSB
477 uint shift = (8 - frame_size);
478 *byte = *byte << shift;
479 }
480 } else if (frame_size == 9) { //9 bits
481 if (*byte & 0x100) { //It's an address
482 if ((*byte & 0xFF) == NRF_UARTE_regs[inst].ADDRESS) {
483 u_el->rx_addr_filter_matched = true;
484 } else {
485 u_el->rx_addr_filter_matched = false;
486 }
487 return true; /* Address is always dropped */
488 }
489 return !u_el->rx_addr_filter_matched;
490 }
491 #else
492 (void) inst;
493 (void) u_el;
494 (void) byte;
495 #endif
496 return false;
497 }
498
499 /**
500 * Process a byte incoming to the UART from a backend
501 * This call should be done in the last micros when the byte frame is finishing in the line
502 */
nhw_UARTE_digest_Rx_byte(uint inst,uint16_t byte)503 void nhw_UARTE_digest_Rx_byte(uint inst, uint16_t byte) {
504 struct uarte_status *u_el = &nhw_uarte_st[inst];
505 bs_time_t frame_start, now;
506
507 if (u_el->rx_status == Rx_Off) {
508 static int Received_error_count;
509 Received_error_count++;
510 if ((Received_error_count & 0xFF) <= 4) {
511 bs_trace_warning_time_line("Byte received while UART%i is not enabled for Rx, ignoring it (warn count = %i)\n", inst, Received_error_count);
512 if ((Received_error_count & 0xFF) == 4) {
513 bs_trace_warning_time_line("Silencing this warning the next 252 times\n", inst);
514 }
515 }
516 return;
517 }
518
519 now = nsi_hws_get_time();
520 frame_start = now - nhw_uarte_one_byte_time(inst) + 1;
521
522 if (u_el->Last_Rx_off_time >= frame_start) {
523 bs_trace_warning_time_line("Byte partially received while UART%i was not enabled for Rx, "
524 "this would have likely caused a framing error. Ignoring it in the model\n", inst);
525 return;
526 }
527
528 if (u_el->Rx_log_file) {
529 fprintf(u_el->Rx_log_file, "%"PRItime",0x%02X\n", now, byte);
530 }
531
532 if (u_el->trx_callbacks[1]) {
533 u_el->trx_callbacks[1](inst, &byte);
534 }
535
536 if (nhw_UARTE_process_Rx_byte(inst, u_el, &byte)) {
537 return;
538 }
539
540 Rx_FIFO_push(inst, u_el, byte);
541 nhw_UARTE_Rx_DMA_attempt(inst, u_el);
542 if (u_el->Rx_FIFO_cnt >= RX_FIFO_RTS_THRESHOLD) {
543 raise_RTS_R(inst, u_el);
544 }
545 }
546
547 /**
548 * Propagate internally the CTS pin having been lowered
549 */
nhw_UARTE_CTS_lowered(uint inst)550 void nhw_UARTE_CTS_lowered(uint inst) {
551 struct uarte_status *u_el = &nhw_uarte_st[inst];
552
553 if (u_el->CTS_blocking == false) {
554 //It was already low (or perceived as such) => nothing to be done
555 return;
556 }
557
558 u_el->CTS_blocking = false;
559
560 if ( !(uart_enabled(inst) || uarte_enabled(inst)) ) {
561 return;
562 }
563
564 if (u_el->tx_status == Tx_Pend) {
565 nhw_UARTE_Tx_send_byte(inst, u_el);
566 }
567 nhw_UARTE_signal_EVENTS_CTS(inst);
568 }
569
570 /**
571 * Propagate internally the CTS pin having been raised
572 */
nhw_UARTE_CTS_raised(uint inst)573 void nhw_UARTE_CTS_raised(uint inst) {
574 if (nhw_uarte_st[inst].CTS_blocking == true) {
575 return;
576 }
577 nhw_uarte_st[inst].CTS_blocking = true;
578
579 if ( !(uart_enabled(inst) || uarte_enabled(inst)) ) {
580 return;
581 }
582 nhw_UARTE_signal_EVENTS_NCTS(inst);
583 }
584
nhw_UARTE_eval_interrupt(uint inst)585 static void nhw_UARTE_eval_interrupt(uint inst) {
586 static bool uart_int_line[NHW_UARTE_TOTAL_INST]; /* Is the UART currently driving its interrupt line high */
587 /* Mapping of peripheral instance to {int controller instance, int number} */
588 static struct nhw_irq_mapping nhw_uart_irq_map[NHW_UARTE_TOTAL_INST] = NHW_UARTE_INT_MAP;
589 bool new_int_line = false;
590 uint32_t inten = NRF_UARTE_regs[inst].INTEN;
591
592 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., CTS, inten)
593 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., NCTS, inten)
594 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., RXDRDY, inten)
595 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., TXDRDY, inten)
596 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., ERROR, inten)
597 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., RXTO, inten)
598
599 if (uarte_enabled(inst)) {
600 /* It is unclear if these UART*E* events being still pended would still keep
601 * the int line high even in UART(not E) mode */
602 #if !(NHW_UARTE_54NAMING)
603 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., ENDRX, inten)
604 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., ENDTX, inten)
605 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., RXSTARTED, inten)
606 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., TXSTARTED, inten)
607 #else
608 NHW_CHECK_INTERRUPT_ST(UARTE, NRF_UARTE_regs[inst]., DMA.RX.END, DMARXEND, inten)
609 NHW_CHECK_INTERRUPT_ST(UARTE, NRF_UARTE_regs[inst]., DMA.TX.END, DMATXEND, inten)
610 NHW_CHECK_INTERRUPT_ST(UARTE, NRF_UARTE_regs[inst]., DMA.RX.READY, DMARXREADY, inten)
611 NHW_CHECK_INTERRUPT_ST(UARTE, NRF_UARTE_regs[inst]., DMA.TX.READY, DMATXREADY, inten)
612 #endif
613 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., TXSTOPPED, inten)
614 #if defined(UARTE_INTENSET_FRAMETIMEOUT_Msk)
615 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., FRAMETIMEOUT, inten)
616 #endif
617 #if NHW_UARTE_HAS_MATCH
618 for (int i = 0; i < nhw_uarte_st[inst].n_match; i++) {
619 if (NRF_UARTE_regs[inst].EVENTS_DMA.RX.MATCH[i] &&
620 (inten & (UARTE_INTEN_DMARXMATCH0_Msk << i))) {
621 new_int_line = true;
622 }
623 }
624 #endif
625 }
626
627 hw_irq_ctrl_toggle_level_irq_line_if(&uart_int_line[inst],
628 new_int_line,
629 &nhw_uart_irq_map[inst]);
630 }
631
nhw_UARTE_RxDMA_start(int inst)632 static void nhw_UARTE_RxDMA_start(int inst) {
633 struct uarte_status * u_el = &nhw_uarte_st[inst];
634 #if !NHW_UARTE_54NAMING
635 u_el->RXD_PTR = NRF_UARTE_regs[inst].RXD.PTR;
636 u_el->RXD_MAXCNT = NRF_UARTE_regs[inst].RXD.MAXCNT;
637 #else
638 u_el->RXD_PTR = NRF_UARTE_regs[inst].DMA.RX.PTR;
639 u_el->RXD_MAXCNT = NRF_UARTE_regs[inst].DMA.RX.MAXCNT;
640 #endif
641 u_el->RXD_AMOUNT = 0;
642 u_el->rx_dma_status = DMAing;
643 #if NHW_UARTE_HAS_MATCH
644 for (int i = 0; i < u_el->n_match; i++) {
645 u_el->MATCH_CANDIDATE[i] = NRF_UARTE_regs[i].DMA.RX.MATCH.CANDIDATE[i];
646 }
647 #endif
648 nhw_UARTE_signal_EVENTS_RXSTARTED(inst); /* Instantaneously ready */
649
650 nhw_UARTE_Rx_DMA_attempt(inst, u_el);
651 }
652
nhw_UARTE_TASK_STARTRX(uint inst)653 void nhw_UARTE_TASK_STARTRX(uint inst)
654 {
655 struct uarte_status *u_el = &nhw_uarte_st[inst];
656
657 if (!uart_enabled(inst) && !uarte_enabled(inst)) {
658 bs_trace_warning_time_line("Start RX triggered while UART%i is not enabled (%u). "
659 "Ignoring it.\n", inst, NRF_UARTE_regs[inst].ENABLE);
660 return;
661 }
662
663 if (uart_enabled(inst) && (u_el->rx_status != Rx_Off)) {
664 bs_trace_warning_time_line("Start Rx triggered for UART%i whose Rx is already started (%i). "
665 "Ignoring it\n", inst, u_el->rx_status);
666 return;
667 }
668
669 if (u_el->rx_dma_status != DMA_Off) {
670 bs_trace_warning_time_line("Start Rx triggered for UARTE%i whose Rx is already DMA'ing. "
671 "This seems like a SW error which the model does not handle. "
672 "Ignoring it\n", inst);
673 return;
674 }
675
676 if (u_el->rx_status == Rx_turning_off) {
677 /* The HW seems to support a STARTRX while it is turning off the Rx
678 * In this case, it seems the Rx TO is just cancelled */
679 u_el->Rx_TO_timer = TIME_NEVER;
680 u_el->rx_status = Rx_On;
681 }
682
683 if (uarte_enabled(inst)) {
684 nhw_UARTE_RxDMA_start(inst);
685 }
686
687 if (u_el->rx_status == Rx_Off) {
688 u_el->Last_Rx_off_time = nsi_hws_get_time();
689 u_el->rx_status = Rx_On;
690 notify_backend_RxOnOff(inst, u_el, true);
691 }
692
693 if (u_el->Rx_FIFO_cnt == 0) {
694 lower_RTS_R(inst, u_el);
695 }
696 }
697
nhw_UARTE_TASK_STOPRX(uint inst)698 void nhw_UARTE_TASK_STOPRX(uint inst)
699 {
700 /*
701 * If in UART mode (at least) raise RTS/R
702 * Set Rx in Off mode
703 */
704 struct uarte_status *u_el = &nhw_uarte_st[inst];
705
706 if (u_el->rx_status == Rx_Off) {
707 bs_trace_warning_time_line("UART%i Rx stopped while already stopped => ignored\n", inst);
708 return;
709 }
710 if (u_el->rx_status == Rx_turning_off) {
711 bs_trace_warning_time_line("UART%i Rx stopped while already stopping => ignored\n", inst);
712 return;
713 }
714
715 raise_RTS_R(inst, u_el);
716
717 //Start Rx TO timer to turn Rx fully off and generate RXTO
718 u_el->Rx_TO_timer = nsi_hws_get_time() + 5*nhw_uarte_one_byte_time(inst);
719 u_el->rx_status = Rx_turning_off;
720 //And clear a possible frametimeout
721 u_el->frametimeout_timer = TIME_NEVER;
722 nhw_uarte_update_timer();
723 }
724
725 #if (NHW_UARTE_HAS_MATCH)
nhw_UARTE_TASK_DMA_RX_ENABLEMATCH(uint inst,uint i)726 void nhw_UARTE_TASK_DMA_RX_ENABLEMATCH(uint inst, uint i) {
727 NRF_UARTE_regs[inst].DMA.RX.MATCH.CONFIG |= UARTE_DMA_RX_MATCH_CONFIG_ENABLE0_Msk<<i;
728 }
nhw_UARTE_TASK_DMA_RX_DISABLEMATCH(uint inst,uint i)729 void nhw_UARTE_TASK_DMA_RX_DISABLEMATCH(uint inst, uint i) {
730 NRF_UARTE_regs[inst].DMA.RX.MATCH.CONFIG &= ~(UARTE_DMA_RX_MATCH_CONFIG_ENABLE0_Msk<<i);
731 }
732 #endif
733
nHW_UARTE_Tx_DMA_end(int inst,struct uarte_status * u_el)734 static void nHW_UARTE_Tx_DMA_end(int inst, struct uarte_status * u_el) {
735 u_el->tx_dma_status = DMA_Off;
736 #if !NHW_UARTE_54NAMING
737 NRF_UARTE_regs[inst].TXD.AMOUNT = u_el->TXD_AMOUNT;
738 #else
739 NRF_UARTE_regs[inst].DMA.TX.AMOUNT = u_el->TXD_AMOUNT;
740 #endif
741 nhw_UARTE_signal_EVENTS_ENDTX(inst);
742 }
743
nhw_UART_prep_Tx_data(uint inst,struct uarte_status * u_el,uint16_t byte)744 static uint16_t nhw_UART_prep_Tx_data(uint inst, struct uarte_status *u_el, uint16_t byte) {
745 #if defined(UARTE_CONFIG_FRAMESIZE_Msk)
746 uint frame_size = nhw_uarte_get_frame_size(inst);
747
748 if (frame_size == 8) {
749 return byte;
750 } else if (frame_size < 8) {
751 uint shift = (8 - frame_size);
752 if (NRF_UARTE_regs[inst].CONFIG & UARTE_CONFIG_ENDIAN_Msk) { //Cut from LSB
753 return byte >> shift;
754 } else {
755 return byte & (0xFF >> shift);
756 }
757 } else { //9 bits => adding address bit
758 if (u_el->TXD_AMOUNT == 0) {
759 return byte | 0x100;
760 } else {
761 return byte;
762 }
763 }
764 #else
765 (void) inst;
766 (void) u_el;
767 return byte;
768 #endif
769 }
770
nHW_UARTE_Tx_DMA_byte(int inst,struct uarte_status * u_el)771 static void nHW_UARTE_Tx_DMA_byte(int inst, struct uarte_status *u_el)
772 {
773 uint8_t *ptr = (uint8_t *)(u_el->TXD_PTR + u_el->TXD_AMOUNT);
774
775 uint16_t data = nhw_UART_prep_Tx_data(inst, u_el, *ptr);
776
777 nhw_UART_Tx_queue_byte(inst, u_el, data);
778 }
779
nhw_UARTE_TASK_STARTTX(uint inst)780 void nhw_UARTE_TASK_STARTTX(uint inst)
781 {
782 struct uarte_status *u_el = &nhw_uarte_st[inst];
783
784 if (!uart_enabled(inst) && !uarte_enabled(inst)) {
785 bs_trace_warning_time_line("Start TX triggered while UART%i is not enabled (%u). "
786 "Ignoring it.\n", inst, NRF_UARTE_regs[inst].ENABLE);
787 return;
788 }
789
790 if (u_el->tx_dma_status != DMA_Off) {
791 bs_trace_warning_time_line("Start Tx triggered for UARTE%i whose Rx is already DMA'ing. "
792 "This seems like a SW error which the model does not handle. "
793 "Ignoring it\n", inst);
794 return;
795 }
796
797 if (u_el->tx_status == Tx_Off) {
798 u_el->tx_status = Tx_Idle;
799 notify_backend_TxOnOff(inst, u_el, true);
800 } else if (u_el->tx_status == Tx_Stopping) {
801 /* A frame was still in flight and it was trying to stop
802 * We abort the stop */
803 u_el->tx_status = Txing;
804 }
805
806 if (uarte_enabled(inst)) {
807 #if !(NHW_UARTE_54NAMING)
808 u_el->TXD_PTR = NRF_UARTE_regs[inst].TXD.PTR;
809 u_el->TXD_MAXCNT = NRF_UARTE_regs[inst].TXD.MAXCNT;
810 #else
811 u_el->TXD_PTR = NRF_UARTE_regs[inst].DMA.TX.PTR;
812 u_el->TXD_MAXCNT = NRF_UARTE_regs[inst].DMA.TX.MAXCNT;
813 #endif
814 u_el->TXD_AMOUNT = 0;
815 u_el->tx_dma_status = DMAing;
816 nhw_UARTE_signal_EVENTS_TXSTARTED(inst); /* Instantaneously ready */
817 if (u_el->TXD_MAXCNT > 0) {
818 if (u_el->tx_status == Tx_Idle) {
819 nHW_UARTE_Tx_DMA_byte(inst, u_el);
820 }
821 } else {
822 nHW_UARTE_Tx_DMA_end(inst, u_el);
823 }
824 }
825 }
826
nhw_UARTE_tx_final_stop(int inst,struct uarte_status * u_el)827 static void nhw_UARTE_tx_final_stop(int inst, struct uarte_status *u_el) {
828 u_el->tx_status = Tx_Off;
829 notify_backend_TxOnOff(inst, u_el, false);
830
831 if (uarte_enabled(inst)) {
832 if (u_el->tx_dma_status == DMAing) {
833 nHW_UARTE_Tx_DMA_end(inst, u_el);
834 }
835 nhw_UARTE_signal_EVENTS_TXSTOPPED(inst);
836 }
837 }
838
nhw_UARTE_TASK_STOPTX(uint inst)839 void nhw_UARTE_TASK_STOPTX(uint inst)
840 {
841 struct uarte_status * u_el = &nhw_uarte_st[inst];
842
843 /* STOP behavior is slightly different in UART and UART-E modes */
844 if (uart_enabled(inst)) {
845 if (u_el->tx_status > Tx_Idle) {
846 bs_trace_warning_time_line("UART%i Tx stopped while not idle\n", inst);
847 if (u_el->tx_status == Tx_Pend) {
848 bs_trace_warning_time_line("A byte was pending to Tx awaiting CTS, it is dropped\n");
849 nhw_UARTE_tx_final_stop(inst, u_el);
850 } else if (u_el->tx_status == Txing) {
851 bs_trace_warning_time_line("A Tx byte is already in flight, it will be completed"
852 "(this is not how real HW behaves)\n");
853 /* In the model, the byte is already in flight, so nothing can't be done anymore */
854 u_el->tx_status = Tx_Stopping;
855 }
856 } else {
857 nhw_UARTE_tx_final_stop(inst, u_el);
858 }
859 }
860
861 if (uarte_enabled(inst)) {
862 if (u_el->tx_status == Txing) {
863 u_el->tx_status = Tx_Stopping;
864 } else if (u_el->tx_status == Tx_Stopping) {
865 bs_trace_info(3, "UART%i STOPTX received while already stopping, ignored\n", inst);
866 return;
867 } else { /* Pend or Idle */
868 nhw_UARTE_tx_final_stop(inst, u_el);
869 }
870 }
871 }
872
873 /*
874 * Queue a byte for transmission right away in the backends
875 */
nhw_UARTE_Tx_byte(unsigned int inst,struct uarte_status * u_el,uint16_t data)876 static void nhw_UARTE_Tx_byte(unsigned int inst, struct uarte_status *u_el, uint16_t data) {
877 if (u_el->trx_callbacks[0]) {
878 u_el->trx_callbacks[0](inst, &data);
879 }
880 if (u_el->backend.tx_byte_f) {
881 u_el->backend.tx_byte_f(inst, data);
882 }
883 if (u_el->Tx_log_file) {
884 fprintf(u_el->Tx_log_file, "%"PRItime",0x%02X\n", nsi_hws_get_time(), data);
885 }
886 }
887
888 /*
889 * Start the process of actually sending the byte thru the line
890 */
nhw_UARTE_Tx_send_byte(unsigned int inst,struct uarte_status * u_el)891 static void nhw_UARTE_Tx_send_byte(unsigned int inst, struct uarte_status *u_el) {
892 nhw_UARTE_Tx_byte(inst, u_el, u_el->Tx_byte);
893 u_el->Tx_byte_done_timer = nsi_hws_get_time() + nhw_uarte_one_byte_time(inst);
894 u_el->tx_status = Txing;
895 nhw_uarte_update_timer();
896
897 if (u_el->tx_dma_status == DMAing) {
898 u_el->TXD_AMOUNT++;
899 if (u_el->TXD_AMOUNT >= u_el->TXD_MAXCNT) {
900 nHW_UARTE_Tx_DMA_end(inst, u_el);
901 }
902 }
903 }
904
905 /*
906 * Queue a byte to Tx'ed as soon as possible
907 */
nhw_UART_Tx_queue_byte(uint inst,struct uarte_status * u_el,uint16_t byte)908 static void nhw_UART_Tx_queue_byte(uint inst, struct uarte_status *u_el, uint16_t byte)
909 {
910 if (u_el->tx_status != Tx_Idle) {
911 bs_trace_error_time_line("Attempted to queue a byte for Tx but a transmission is currently ongoing. "
912 "This should not have happened\n", inst);
913 return;
914 }
915
916 u_el->Tx_byte = byte;
917
918 /*
919 * If !flow_control or (flow control & CTS low)
920 * Start the actual Tx
921 * otherwise // (flow control & CTS high)
922 * "Pend" the Tx (set in a state in which a lower of CTS will start it)
923 */
924 if ((flow_control_on(inst) == false) || (u_el->CTS_blocking == false)) {
925 nhw_UARTE_Tx_send_byte(inst, u_el);
926 } else {
927 u_el->tx_status = Tx_Pend;
928 }
929 }
930
931 #if (NHW_UARTE_HAS_FRAMETIMEOUT)
nhw_uart_maybe_program_frametimeout(int inst)932 static void nhw_uart_maybe_program_frametimeout(int inst) {
933 if (!(NRF_UARTE_regs[inst].CONFIG & UARTE_CONFIG_FRAMETIMEOUT_Msk)) {
934 return;
935 }
936
937 struct uarte_status *u_el = &nhw_uarte_st[inst];
938
939 u_el->frametimeout_timer = nsi_hws_get_time() +
940 nhw_uarte_nbits_time(inst, NRF_UARTE_regs[inst].FRAMETIMEOUT);
941 nhw_uarte_update_timer();
942 }
943
944 /*
945 * The frame timeout timer has timed out
946 */
nhw_uart_frametimeout_timer_triggered(int inst,struct uarte_status * u_el)947 static void nhw_uart_frametimeout_timer_triggered(int inst, struct uarte_status *u_el)
948 {
949 u_el->frametimeout_timer = TIME_NEVER;
950 nhw_UARTE_signal_EVENTS_FRAMETIMEOUT(inst);
951 }
952 #endif
953
954 /*
955 * The Rx TO timer has timed out
956 */
nhw_uart_Rx_TO_timer_triggered(int inst,struct uarte_status * u_el)957 static void nhw_uart_Rx_TO_timer_triggered(int inst, struct uarte_status *u_el)
958 {
959 if (u_el->rx_status != Rx_turning_off) {
960 bs_trace_error_time_line("Programming error\n");
961 }
962 u_el->Rx_TO_timer = TIME_NEVER;
963 u_el->rx_status = Rx_Off;
964 if (u_el->rx_dma_status == DMAing) {
965 nhw_UARTE_Rx_DMA_end(inst, u_el);
966 }
967 if (u_el->rx_status == Rx_Off) {
968 /* The DMA end may have triggered thru a short ENDRX->STARTRX, which restarts the RX and
969 * prevents the RXTO from being generated */
970 nhw_UARTE_signal_EVENTS_RXTO(inst);
971 notify_backend_RxOnOff(inst, u_el, false);
972 }
973 }
974
nhw_uart_Tx_byte_done_timer_triggered(int inst,struct uarte_status * u_el)975 static void nhw_uart_Tx_byte_done_timer_triggered(int inst, struct uarte_status *u_el)
976 {
977 u_el->Tx_byte_done_timer = TIME_NEVER;
978 nhw_UARTE_signal_EVENTS_TXDRDY(inst);
979
980 if (u_el->tx_status == Txing) {
981 u_el->tx_status = Tx_Idle;
982
983 } else if (u_el->tx_status == Tx_Stopping) {
984 nhw_UARTE_tx_final_stop(inst, u_el);
985 return;
986 }
987
988 if (u_el->tx_dma_status == DMAing) {
989 nHW_UARTE_Tx_DMA_byte(inst, u_el);
990 }
991 }
992
nhw_uart_timer_triggered(void)993 static void nhw_uart_timer_triggered(void)
994 {
995 bs_time_t current_time = Timer_UART_peri;
996
997 for (int inst = 0; inst < NHW_UARTE_TOTAL_INST; inst++) {
998 struct uarte_status *u_el = &nhw_uarte_st[inst];
999
1000 #if (NHW_UARTE_HAS_FRAMETIMEOUT)
1001 if (current_time == u_el->frametimeout_timer) {
1002 nhw_uart_frametimeout_timer_triggered(inst, u_el);
1003 }
1004 #endif
1005 if (current_time == u_el->Rx_TO_timer) {
1006 nhw_uart_Rx_TO_timer_triggered(inst, u_el);
1007 }
1008 if (current_time == u_el->Tx_byte_done_timer) {
1009 nhw_uart_Tx_byte_done_timer_triggered(inst, u_el);
1010 }
1011 }
1012 nhw_uarte_update_timer();
1013 }
1014
nhw_uart_timer_common_triggered(void)1015 static void nhw_uart_timer_common_triggered(void)
1016 {
1017 bs_time_t current_time = Timer_UART_common;
1018 if (current_time == nhw_Timer_ULoopback) {
1019 extern void nhw_ublb_timer_triggered(void);
1020 nhw_ublb_timer_triggered();
1021 }
1022 if (current_time == Timer_UART_peri) {
1023 nhw_uart_timer_triggered();
1024 }
1025 }
1026
1027 NSI_HW_EVENT(Timer_UART_common, nhw_uart_timer_common_triggered, 50);
1028
nhw_UARTE_TASK_FLUSHRX(uint inst)1029 void nhw_UARTE_TASK_FLUSHRX(uint inst) {
1030 if (!uarte_enabled(inst)) {
1031 bs_trace_warning_time_line("TASK_FLUSHRX for UART%i while it is not enabled in UARTE mode\n",
1032 inst);
1033 return;
1034 }
1035
1036 struct uarte_status * u_el = &nhw_uarte_st[inst];
1037
1038 u_el->rx_dma_status = DMAing;
1039 if (!NHW_UARTE_FLUSH_AMOUNT_BUG || (u_el->Rx_FIFO_cnt > 0)) {
1040 nhw_UARTE_RxDMA_start(inst);
1041 }
1042
1043 if (u_el->rx_dma_status == DMAing) {
1044 nhw_UARTE_Rx_DMA_end(inst, u_el);
1045 }
1046 }
1047
1048 #if (NHW_UARTE_HAS_UART)
nhw_UARTE_TASK_SUSPEND(uint inst)1049 void nhw_UARTE_TASK_SUSPEND(uint inst) {
1050 /* UART(not-E) only task */
1051 nhw_UARTE_TASK_STOPTX(inst);
1052 nhw_UARTE_TASK_STOPRX(inst);
1053 }
1054 #endif
1055
nhw_UARTE_regw_sideeffects_ENABLE(unsigned int inst)1056 void nhw_UARTE_regw_sideeffects_ENABLE(unsigned int inst) {
1057 struct uarte_status * u_el = &nhw_uarte_st[inst];
1058
1059 if (NRF_UARTE_regs[inst].ENABLE != 0) {
1060 propagate_RTS_R(inst, u_el);
1061 return;
1062 }
1063
1064 if (u_el->tx_status != Tx_Off) {
1065 bs_trace_warning_time_line("UART%i disabled while Tx was not Off (%i)\n", inst, u_el->tx_status);
1066 }
1067 if (u_el->rx_status != Rx_Off) {
1068 bs_trace_warning_time_line("UART%i disabled while Rx was not Off (%i)\n", inst, u_el->rx_status);
1069 }
1070
1071 if (u_el->Rx_TO_timer != TIME_NEVER) {
1072 bs_trace_warning_time_line("UART%i disabled while Rx was shutting Off. Events will be missed\n", inst);
1073 }
1074 if (u_el->Tx_byte_done_timer != TIME_NEVER) {
1075 bs_trace_warning_time_line("UART%i disabled while Tx was mid frame. Events will be missed\n", inst);
1076 }
1077
1078 u_el->tx_status = Tx_Off;
1079 u_el->rx_status = Rx_Off;
1080
1081 u_el->Rx_TO_timer = TIME_NEVER;
1082 u_el->Tx_byte_done_timer = TIME_NEVER;
1083 nhw_uarte_update_timer();
1084
1085 u_el->Rx_FIFO_cnt = 0;
1086
1087 if (u_el->tx_dma_status != DMA_Off) {
1088 bs_trace_warning_time_line("UARTE%i disabled while Tx DMA was not Off. DMA interrupted mid way, ENDTX will be missing\n", inst);
1089 }
1090 if (u_el->rx_dma_status != DMA_Off) {
1091 bs_trace_warning_time_line("UARTE%i disabled while Rx DMA was not Off. DMA interrupted mid way, ENDRX will be missing\n", inst);
1092 }
1093
1094 u_el->tx_dma_status = DMA_Off;
1095 u_el->rx_dma_status = DMA_Off;
1096
1097 notify_backend_RxOnOff(inst, u_el, false);
1098 }
1099
nhw_UARTE_regw_sideeffects_CONFIG(unsigned int inst)1100 void nhw_UARTE_regw_sideeffects_CONFIG(unsigned int inst) {
1101 #if defined(UARTE_CONFIG_FRAMESIZE_Msk)
1102 uint frame_size = nhw_uarte_get_frame_size(inst);
1103 NRF_UARTE_regs[inst].CONFIG &= ~UARTE_CONFIG_FRAMESIZE_Msk;
1104 NRF_UARTE_regs[inst].CONFIG |= frame_size << UARTE_CONFIG_FRAMESIZE_Pos;
1105 #endif
1106 if (NRF_UARTE_regs[inst].ENABLE != 0) {
1107 struct uarte_status *u_el = &nhw_uarte_st[inst];
1108 propagate_RTS_R(inst, u_el);
1109 }
1110 }
1111
nhw_UARTE_regr_sideeffects_ERRORSRC(unsigned int inst)1112 uint32_t nhw_UARTE_regr_sideeffects_ERRORSRC(unsigned int inst) {
1113 uint32_t value = NRF_UARTE_regs[inst].ERRORSRC;
1114 NRF_UARTE_regs[inst].ERRORSRC = 0;
1115 return value;
1116 }
1117
nhw_UARTE_regw_sideeffects_ERRORSRC(unsigned int inst)1118 void nhw_UARTE_regw_sideeffects_ERRORSRC(unsigned int inst) {
1119 NRF_UARTE_regs[inst].ERRORSRC = 0;
1120 }
1121
1122 #if (NHW_UARTE_HAS_UART)
nhw_UARTE_regr_sideeffects_RXD(unsigned int inst)1123 uint32_t nhw_UARTE_regr_sideeffects_RXD(unsigned int inst) {
1124 if (!uart_enabled(inst)) {
1125 bs_trace_warning("RXD read while UART%i was not enabled\n", inst);
1126 }
1127 /*
1128 * Read logic: If RxFIFO has anything pop a new value into RXD, otherwise just warn.
1129 *
1130 * If RTS is high & Rx is not stopped & the FIFO is empty: lower RTS
1131 *
1132 * If there is anything else in the Rx FIFO, signal another RXDRDY
1133 */
1134
1135 uint32_t value;
1136 struct uarte_status * u_el = &nhw_uarte_st[inst];
1137
1138 if (u_el->Rx_FIFO_cnt == 0) {
1139 bs_trace_warning("UART%i: Reading RXD without any new data there\n", inst);
1140 return NRF_UART_regs[inst]->RXD;
1141 }
1142
1143 value = Rx_FIFO_pop(inst, u_el);
1144
1145 if ((u_el->Rx_FIFO_cnt == 0)
1146 && (u_el->rx_status == Rx_On)) {
1147 lower_RTS_R(inst, u_el);
1148 }
1149
1150 return value;
1151 }
1152
nhw_UARTE_regw_sideeffects_TXD(unsigned int inst)1153 void nhw_UARTE_regw_sideeffects_TXD(unsigned int inst)
1154 {
1155 if (!uart_enabled(inst)) {
1156 bs_trace_warning("TXD written while UART%i was not enabled (in non-E mode)\n", inst);
1157 }
1158
1159 /*
1160 * If Tx is off warn and ignore (return)
1161 * If Tx is busy, warn and ignore (return)
1162 */
1163
1164 struct uarte_status *u_el = &nhw_uarte_st[inst];
1165
1166 if ( u_el->tx_status == Tx_Off ) {
1167 bs_trace_warning("UART%i.TXD written but it was Tx was not started => ignoring\n", inst);
1168 return;
1169 }
1170 if ((u_el->tx_status == Tx_Pend) || (u_el->tx_status == Txing)) {
1171 bs_trace_warning("UART%i.TXD written but a transmission is currently ongoing => ignoring it\n", inst);
1172 return;
1173 }
1174
1175 nhw_UART_Tx_queue_byte(inst, u_el, NRF_UART_regs[inst]->TXD);
1176 }
1177 #endif
1178
1179 #if (NHW_HAS_PPI)
1180 #define _NHW_UARTE_XPPI_EVENT(inst, event, eventl) \
1181 if (inst == 0) { \
1182 nrf_ppi_event(UARTE0_EVENTS_##event); \
1183 } else { \
1184 nrf_ppi_event(UARTE1_EVENTS_##event); \
1185 }
1186 #elif (NHW_HAS_DPPI)
1187 #define _NHW_UARTE_XPPI_EVENT(inst, event, eventl) \
1188 nhw_dppi_event_signal_if(nhw_uarte_st[inst].dppi_map, \
1189 NRF_UARTE_regs[inst].PUBLISH_##eventl)
1190 #endif /* (NHW_HAS_PPI) / (NHW_HAS_DPPI)*/
1191
1192 #define _NHW_UARTE_SIGNAL_EVENT_body(event, eventl) \
1193 { \
1194 NRF_UARTE_regs[inst].EVENTS_##eventl = 1; \
1195 nhw_UARTE_eval_interrupt(inst); \
1196 _NHW_UARTE_XPPI_EVENT(inst, event, eventl); \
1197 }
1198
1199 #define NHW_UARTE_SIGNAL_EVENT(event, eventl) \
1200 static void nhw_UARTE_signal_EVENTS_##event(unsigned int inst) \
1201 _NHW_UARTE_SIGNAL_EVENT_body(event, eventl)
1202
1203 #define NHW_UARTE_SIGNAL_EVENT_ns(event, eventl) \
1204 static void nhw_UARTE_signal_EVENTS_##event##_noshort(unsigned int inst) \
1205 _NHW_UARTE_SIGNAL_EVENT_body(event, eventl)
1206
NHW_UARTE_SIGNAL_EVENT_ns(CTS,CTS)1207 NHW_UARTE_SIGNAL_EVENT_ns(CTS, CTS)
1208 NHW_UARTE_SIGNAL_EVENT_ns(NCTS, NCTS)
1209 NHW_UARTE_SIGNAL_EVENT_ns(RXDRDY, RXDRDY)
1210 #if !(NHW_UARTE_54NAMING)
1211 NHW_UARTE_SIGNAL_EVENT_ns(ENDRX, ENDRX) /* DMA Rx done */
1212 NHW_UARTE_SIGNAL_EVENT_ns(ENDTX, ENDTX) /* DMA Tx done */
1213 NHW_UARTE_SIGNAL_EVENT(RXSTARTED, RXSTARTED)
1214 NHW_UARTE_SIGNAL_EVENT(TXSTARTED, TXSTARTED)
1215 #else
1216 NHW_UARTE_SIGNAL_EVENT_ns(ENDRX, DMA.RX.END)
1217 NHW_UARTE_SIGNAL_EVENT_ns(ENDTX, DMA.TX.END)
1218 NHW_UARTE_SIGNAL_EVENT(RXSTARTED, DMA.RX.READY)
1219 NHW_UARTE_SIGNAL_EVENT(TXSTARTED, DMA.TX.READY)
1220 #endif
1221 #if (NHW_UARTE_HAS_FRAMETIMEOUT)
1222 NHW_UARTE_SIGNAL_EVENT_ns(FRAMETIMEOUT, FRAMETIMEOUT)
1223 #endif
1224 NHW_UARTE_SIGNAL_EVENT(TXDRDY, TXDRDY)
1225 NHW_UARTE_SIGNAL_EVENT(ERROR, ERROR)
1226 NHW_UARTE_SIGNAL_EVENT(RXTO, RXTO) /* Receiver done closing */
1227 NHW_UARTE_SIGNAL_EVENT(TXSTOPPED, TXSTOPPED)
1228
1229 static void nhw_UARTE_signal_EVENTS_CTS(unsigned int inst) {
1230 #if (NHW_UARTE_HAS_UART)
1231 #define UARTE_SHORTS_CTS_STARTRX_Msk UART_SHORTS_CTS_STARTRX_Msk
1232 if (uart_enabled(inst)) { //Only in UART mode
1233 NHW_SHORT(UARTE, inst, NRF_UARTE_regs[inst]., CTS, STARTRX)
1234 }
1235 #endif
1236 nhw_UARTE_signal_EVENTS_CTS_noshort(inst);
1237 }
1238
nhw_UARTE_signal_EVENTS_NCTS(unsigned int inst)1239 static void nhw_UARTE_signal_EVENTS_NCTS(unsigned int inst) {
1240 #if (NHW_UARTE_HAS_UART)
1241 #define UARTE_SHORTS_NCTS_STOPRX_Msk UART_SHORTS_NCTS_STOPRX_Msk
1242 if (uart_enabled(inst)) { //Only in UART mode
1243 NHW_SHORT(UARTE, inst, NRF_UARTE_regs[inst]., NCTS, STOPRX)
1244 }
1245 #endif
1246 nhw_UARTE_signal_EVENTS_NCTS_noshort(inst);
1247 }
1248
nhw_UARTE_signal_EVENTS_RXDRDY(unsigned int inst)1249 static void nhw_UARTE_signal_EVENTS_RXDRDY(unsigned int inst) {
1250 #if (NHW_UARTE_HAS_FRAMETIMEOUT)
1251 nhw_uart_maybe_program_frametimeout(inst);
1252 #endif
1253 nhw_UARTE_signal_EVENTS_RXDRDY_noshort(inst);
1254 }
1255
nhw_UARTE_signal_EVENTS_ENDRX(unsigned int inst)1256 static void nhw_UARTE_signal_EVENTS_ENDRX(unsigned int inst) {
1257 if (uarte_enabled(inst)) { //Only in UART-E mode
1258 #if !(NHW_UARTE_54NAMING)
1259 NHW_SHORT(UARTE, inst, NRF_UARTE_regs[inst]., ENDRX, STARTRX)
1260 NHW_SHORT(UARTE, inst, NRF_UARTE_regs[inst]., ENDRX, STOPRX)
1261 #else
1262 NHW_SHORT_ST(UARTE, inst, NRF_UARTE_regs[inst]., DMA_RX_END, STARTRX, DMA_RX_START)
1263 NHW_SHORT_ST(UARTE, inst, NRF_UARTE_regs[inst]., DMA_RX_END, STOPRX, DMA_RX_STOP)
1264 #endif
1265 }
1266 nhw_UARTE_signal_EVENTS_ENDRX_noshort(inst);
1267 }
1268
nhw_UARTE_signal_EVENTS_ENDTX(unsigned int inst)1269 static void nhw_UARTE_signal_EVENTS_ENDTX(unsigned int inst) {
1270 #if (NHW_UARTE_54NAMING)
1271 NHW_SHORT_ST(UARTE, inst, NRF_UARTE_regs[inst]., DMA_TX_END, STOPTX, DMA_TX_STOP)
1272 #endif
1273 nhw_UARTE_signal_EVENTS_ENDTX_noshort(inst);
1274 }
1275
1276 #if (NHW_UARTE_HAS_FRAMETIMEOUT)
nhw_UARTE_signal_EVENTS_FRAMETIMEOUT(unsigned int inst)1277 static void nhw_UARTE_signal_EVENTS_FRAMETIMEOUT(unsigned int inst) {
1278 NHW_SHORT_ST(UARTE, inst, NRF_UARTE_regs[inst]., FRAMETIMEOUT, STOPRX, DMA_RX_STOP)
1279 nhw_UARTE_signal_EVENTS_FRAMETIMEOUT_noshort(inst);
1280 }
1281 #endif
1282
1283 #if (NHW_UARTE_HAS_MATCH)
nhw_UARTE_signal_EVENTS_DMA_RX_MATCH(unsigned int inst,unsigned int i)1284 static void nhw_UARTE_signal_EVENTS_DMA_RX_MATCH(unsigned int inst, unsigned int i) {
1285 if (NRF_UARTE_regs[inst].SHORTS & (UARTE_SHORTS_DMA_RX_MATCH0_DMA_RX_ENABLEMATCH1_Msk << i)) {
1286 nhw_UARTE_TASK_DMA_RX_ENABLEMATCH(inst, (i+1) % nhw_uarte_st[inst].n_match);
1287 }
1288 if (NRF_UARTE_regs[inst].SHORTS & (UARTE_SHORTS_DMA_RX_MATCH0_DMA_RX_DISABLEMATCH0_Msk << i)) {
1289 nhw_UARTE_TASK_DMA_RX_ENABLEMATCH(inst, i);
1290 }
1291
1292 NRF_UARTE_regs[inst].EVENTS_DMA.RX.MATCH[i] = 1;
1293 nhw_UARTE_eval_interrupt(inst);
1294 nhw_dppi_event_signal_if(nhw_uarte_st[inst].dppi_map,
1295 NRF_UARTE_regs[inst].PUBLISH_DMA.RX.MATCH[i]);
1296 }
1297 #endif
1298
1299 NHW_SIDEEFFECTS_INTSET(UARTE, NRF_UARTE_regs[inst]., NRF_UARTE_regs[inst].INTEN)
1300 NHW_SIDEEFFECTS_INTCLR(UARTE, NRF_UARTE_regs[inst]., NRF_UARTE_regs[inst].INTEN)
1301 NHW_SIDEEFFECTS_INTEN(UARTE, NRF_UARTE_regs[inst]., NRF_UARTE_regs[inst].INTEN)
1302
NHW_SIDEEFFECTS_EVENTS(UARTE)1303 NHW_SIDEEFFECTS_EVENTS(UARTE)
1304
1305 #if !(NHW_UARTE_54NAMING)
1306 NHW_SIDEEFFECTS_TASKS(UARTE, NRF_UARTE_regs[inst]., STARTRX)
1307 NHW_SIDEEFFECTS_TASKS(UARTE, NRF_UARTE_regs[inst]., STOPRX)
1308 NHW_SIDEEFFECTS_TASKS(UARTE, NRF_UARTE_regs[inst]., STARTTX)
1309 NHW_SIDEEFFECTS_TASKS(UARTE, NRF_UARTE_regs[inst]., STOPTX)
1310 #else
1311 NHW_SIDEEFFECTS_TASKS_ST(UARTE, NRF_UARTE_regs[inst]., STARTRX, DMA.RX.START)
1312 NHW_SIDEEFFECTS_TASKS_ST(UARTE, NRF_UARTE_regs[inst]., STOPRX, DMA.RX.STOP)
1313 NHW_SIDEEFFECTS_TASKS_ST(UARTE, NRF_UARTE_regs[inst]., STARTTX, DMA.TX.START)
1314 NHW_SIDEEFFECTS_TASKS_ST(UARTE, NRF_UARTE_regs[inst]., STOPTX, DMA.TX.STOP)
1315 #endif
1316 #if NHW_UARTE_HAS_MATCH
1317 void nhw_UARTE_regw_sideeffects_TASKS_DMA_RX_ENABLEMATCH(uint inst, uint i) {
1318 if (NRF_UARTE_regs[inst].TASKS_DMA.RX.ENABLEMATCH[i]) {
1319 NRF_UARTE_regs[inst].TASKS_DMA.RX.ENABLEMATCH[i] = 0;
1320 nhw_UARTE_TASK_DMA_RX_ENABLEMATCH(inst, i);
1321 }
1322 }
1323
nhw_UARTE_regw_sideeffects_TASKS_DMA_RX_DISABLEMATCH(uint inst,uint i)1324 void nhw_UARTE_regw_sideeffects_TASKS_DMA_RX_DISABLEMATCH(uint inst, uint i) {
1325 if (NRF_UARTE_regs[inst].TASKS_DMA.RX.DISABLEMATCH[i]) {
1326 NRF_UARTE_regs[inst].TASKS_DMA.RX.DISABLEMATCH[i] = 0;
1327 nhw_UARTE_TASK_DMA_RX_DISABLEMATCH(inst, i);
1328 }
1329 }
1330 #endif
1331
1332 NHW_SIDEEFFECTS_TASKS(UARTE, NRF_UARTE_regs[inst]., FLUSHRX)
1333
1334 #if (NHW_UARTE_HAS_UART)
nhw_UARTE_regw_sideeffects_TASKS_SUSPEND(unsigned int inst)1335 void nhw_UARTE_regw_sideeffects_TASKS_SUSPEND(unsigned int inst) {
1336 /* Needs special treatment for being an UART(non-E) only task */
1337 if ( NRF_UART_regs[inst]->TASKS_SUSPEND ) {
1338 NRF_UART_regs[inst]->TASKS_SUSPEND = 0;
1339 nhw_UARTE_TASK_SUSPEND(inst);
1340 }
1341 }
1342 #endif
1343
1344 #define NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(TASK_N, TASK_ST_N) \
1345 static void nhw_UARTE_TASK_##TASK_N##_wrap(void* param) \
1346 { \
1347 nhw_UARTE_TASK_##TASK_N((int) param); \
1348 } \
1349 \
1350 void nhw_UARTE_regw_sideeffects_SUBSCRIBE_##TASK_N(uint inst) \
1351 { \
1352 static struct nhw_subsc_mem TASK_N##_subscribed[NHW_UARTE_TOTAL_INST]; \
1353 struct uarte_status *this = &nhw_uarte_st[inst]; \
1354 \
1355 nhw_dppi_common_subscribe_sideeffect(this->dppi_map, \
1356 this->UARTE_regs[inst]->SUBSCRIBE_##TASK_ST_N,\
1357 &TASK_N##_subscribed[inst], \
1358 nhw_UARTE_TASK_##TASK_N##_wrap, \
1359 (void*) inst); \
1360 }
1361
1362 #if (NHW_HAS_DPPI)
1363 #if !(NHW_UARTE_54NAMING)
NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(STARTRX,STARTRX)1364 NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(STARTRX, STARTRX)
1365 NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(STOPRX, STOPRX)
1366 NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(STARTTX, STARTTX)
1367 NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(STOPTX, STOPTX)
1368 #else
1369 NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(STARTRX, DMA.RX.START)
1370 NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(STOPRX, DMA.RX.STOP)
1371 NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(STARTTX, DMA.TX.START)
1372 NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(STOPTX, DMA.TX.STOP)
1373 #endif
1374 NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(FLUSHRX, FLUSHRX)
1375 #if NHW_UARTE_HAS_MATCH
1376 static void nhw_UARTE_TASK_nhw_UARTE_TASK_DMA_RX_ENABLEMATCH_wrap(void* param)
1377 {
1378 uint inst = (intptr_t)param >> 8;
1379 uint i = (intptr_t)param & 0xFF;
1380 nhw_UARTE_TASK_DMA_RX_ENABLEMATCH(inst, i);
1381 }
1382
nhw_UARTE_regw_sideeffects_SUBSCRIBE_DMA_RX_ENABLEMATCH(uint inst,uint i)1383 void nhw_UARTE_regw_sideeffects_SUBSCRIBE_DMA_RX_ENABLEMATCH(uint inst, uint i)
1384 {
1385 struct uarte_status *this = &nhw_uarte_st[inst];
1386 uint param = (inst << 8 || (i & 0xFF));
1387
1388 nhw_dppi_common_subscribe_sideeffect(this->dppi_map,
1389 this->UARTE_regs[inst]->SUBSCRIBE_DMA.RX.ENABLEMATCH[i],
1390 &this->DMA_RX_ENABLEMATCH_subscribed[i],
1391 nhw_UARTE_TASK_nhw_UARTE_TASK_DMA_RX_ENABLEMATCH_wrap,
1392 (void*) param);
1393 }
1394
nhw_UARTE_TASK_nhw_UARTE_TASK_DMA_RX_DISABLEMATCH_wrap(void * param)1395 static void nhw_UARTE_TASK_nhw_UARTE_TASK_DMA_RX_DISABLEMATCH_wrap(void* param)
1396 {
1397 uint inst = (intptr_t)param >> 8;
1398 uint i = (intptr_t)param & 0xFF;
1399 nhw_UARTE_TASK_DMA_RX_DISABLEMATCH(inst, i);
1400 }
1401
nhw_UARTE_regw_sideeffects_SUBSCRIBE_DMA_RX_DISABLEMATCH(uint inst,uint i)1402 void nhw_UARTE_regw_sideeffects_SUBSCRIBE_DMA_RX_DISABLEMATCH(uint inst, uint i)
1403 {
1404 struct uarte_status *this = &nhw_uarte_st[inst];
1405 uint param = (inst << 8 || (i & 0xFF));
1406
1407 nhw_dppi_common_subscribe_sideeffect(this->dppi_map,
1408 this->UARTE_regs[inst]->SUBSCRIBE_DMA.RX.DISABLEMATCH[i],
1409 &this->DMA_RX_DISABLEMATCH_subscribed[i],
1410 nhw_UARTE_TASK_nhw_UARTE_TASK_DMA_RX_DISABLEMATCH_wrap,
1411 (void*) param);
1412 }
1413 #endif
1414 #endif /* NHW_HAS_DPPI */
1415
1416 #if (NHW_HAS_PPI)
nhw_uarte0_TASKS_STARTRX(void)1417 void nhw_uarte0_TASKS_STARTRX(void) { nhw_UARTE_TASK_STARTRX(0); }
nhw_uarte0_TASKS_STOPRX(void)1418 void nhw_uarte0_TASKS_STOPRX(void) { nhw_UARTE_TASK_STOPRX(0); }
nhw_uarte0_TASKS_STARTTX(void)1419 void nhw_uarte0_TASKS_STARTTX(void) { nhw_UARTE_TASK_STARTTX(0); }
nhw_uarte0_TASKS_STOPTX(void)1420 void nhw_uarte0_TASKS_STOPTX(void) { nhw_UARTE_TASK_STOPTX(0); }
nhw_uarte0_TASKS_SUSPEND(void)1421 void nhw_uarte0_TASKS_SUSPEND(void) { nhw_UARTE_TASK_SUSPEND(0); }
nhw_uarte0_TASKS_FLUSHRX(void)1422 void nhw_uarte0_TASKS_FLUSHRX(void) { nhw_UARTE_TASK_FLUSHRX(0); }
1423
nhw_uarte1_TASKS_STARTRX(void)1424 void nhw_uarte1_TASKS_STARTRX(void) { nhw_UARTE_TASK_STARTRX(1); }
nhw_uarte1_TASKS_STOPRX(void)1425 void nhw_uarte1_TASKS_STOPRX(void) { nhw_UARTE_TASK_STOPRX(1); }
nhw_uarte1_TASKS_STARTTX(void)1426 void nhw_uarte1_TASKS_STARTTX(void) { nhw_UARTE_TASK_STARTTX(1); }
nhw_uarte1_TASKS_STOPTX(void)1427 void nhw_uarte1_TASKS_STOPTX(void) { nhw_UARTE_TASK_STOPTX(1); }
nhw_uarte1_TASKS_SUSPEND(void)1428 void nhw_uarte1_TASKS_SUSPEND(void) { nhw_UARTE_TASK_SUSPEND(1); }
nhw_uarte1_TASKS_FLUSHRX(void)1429 void nhw_uarte1_TASKS_FLUSHRX(void) { nhw_UARTE_TASK_FLUSHRX(1); }
1430 #endif /* (NHW_HAS_PPI) */
1431
uart_list(char * argv,int offset)1432 static void uart_list(char *argv, int offset) {
1433 (void) argv;
1434 (void) offset;
1435 char *uart_names[NHW_UARTE_TOTAL_INST] = NHW_UARTE_NAMES;
1436 printf("UART #: UART name\n");
1437 for (int i = 0; i < NHW_UARTE_TOTAL_INST; i++) {
1438 printf("%6i: %s\n", i, uart_names[i]);
1439 }
1440 bs_trace_exit(0);
1441 }
1442
nhw_uart_register_cmdline(void)1443 static void nhw_uart_register_cmdline(void) {
1444 static bs_args_struct_t args[] = {
1445 { .is_switch = true,
1446 .option = "uart_list",
1447 .type = 'b',
1448 .call_when_found = uart_list,
1449 .descript = "List available UARTs"
1450 },
1451 ARG_TABLE_ENDMARKER
1452 };
1453
1454 bs_add_extra_dynargs(args);
1455
1456 static bs_args_struct_t args2[2*NHW_UARTE_TOTAL_INST + 1 /* End marker */];
1457 static char descr_tx[] = "Path to a file where the Tx bytes will be logged. Setting this enables the Tx logging for this UART";
1458 static char descr_rx[] = "Path to a file where the Rx bytes will be logged. Setting this enables the Rx logging for this UART";
1459 #define OPTION_LEN (4 + 2 + 11 + 1)
1460 static char options[NHW_UARTE_TOTAL_INST][2][OPTION_LEN];
1461 static char opt_name[]= "path";
1462
1463 for (int i = 0 ; i < NHW_UARTE_TOTAL_INST; i++) {
1464 snprintf(options[i][0], OPTION_LEN, "uart%i_log_txfile", i);
1465 snprintf(options[i][1], OPTION_LEN, "uart%i_log_rxfile", i);
1466
1467 args2[2*i].option = options[i][0];
1468 args2[2*i].name = opt_name;
1469 args2[2*i].type = 's';
1470 args2[2*i].dest = &nhw_uarte_st[i].Tx_log_file_name;
1471 args2[2*i].descript = descr_tx;
1472
1473 args2[2*i + 1].option = options[i][1];
1474 args2[2*i + 1].name = opt_name;
1475 args2[2*i + 1].type = 's';
1476 args2[2*i + 1].dest = &nhw_uarte_st[i].Rx_log_file_name;
1477 args2[2*i + 1].descript = descr_rx;
1478 }
1479
1480 bs_add_extra_dynargs(args2);
1481 }
1482
1483 NSI_TASK(nhw_uart_register_cmdline, PRE_BOOT_1, 199); /* Just before the backends */
1484