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:
16 * * Check the selected backend notes, for more possible limitations
17 *
18 * * The plain UART functionality is present in all UARTEs,
19 * and both for the nRF52 and nRF5340.
20 * (though it is not reachable in practice in an nRF5340 due to the lack of HAL)
21 *
22 * * PSEL is ignored, pins are assumed connected.
23 *
24 * * Unlike in real HW, it is irrelevant if the external oscillator is enabled
25 * or not. The UART timing will always be equally precise.
26 *
27 * * After a StartTx, the UART is ready to Tx right away
28 * (it does not take ~1 us as in the real HW)
29 *
30 * * The effective transmit rate is going to be marginally different than in reality, due to
31 * rounding of the frame time to an integer number of microseconds, and the
32 * logic having immediate response time.
33 *
34 * * Data line errors (parity, framing, break) are not yet modelled
35 *
36 * * (UART) In UART mode, in real HW, a TASK_STOPTX would break a currently ongoing Tx frame
37 * mid way, while in this model, the Tx is allowed to finish (just like for a TASK_SUSPEND
38 * or a TASK_STOPTX in UART-E mode).
39 * Due to this, in the model, a (UART) TASK_SUSPEND is equivalent to a combination of
40 * TASK_STOPTX & TASK_STOPRX, while in real HW it is not.
41 *
42 * * (UART) In real HW, it is unclear what happens when a STOPTX (in UART mode) is triggered, while
43 * a byte is queued for transmission (TXD was written), but where the transmission hasn't started
44 * yet due to the CTS line holding it. It seems the blocked pended Tx is just dropped/forgotten
45 * This is how the model behaves.
46 * * (UARTE) In real HW, when a STOPTX task is triggered (in UARTE mode),
47 * while a byte is queued for transmission, but where the transmission hasn't started yet
48 * due to the CTS line holding it. It seems that the blocked pended Tx is just dropped
49 * (and therefore TXSTOPPED comes right away).
50 * This is how the model behaves.
51 *
52 * * (UART & UARTE) It seems in real HW the Rx FIFO status is kept after a STOPRX & a new STARTRX.
53 * and (if flow control is on) will lower RTS on STARTRX only if the FIFO is empty.
54 * The model behaves this way.
55 *
56 * * In real HW, it seems RTS will be kept high (if flow control is on) if EITHER the Rx FIFO
57 * got more than 2 bytes used, and did not come back to empty yet, OR the Rx is not started/or stopped.
58 * (so just starting it, will not clear RTS unless the FIFO was emptied)
59 * The model behaves this way.
60 *
61 * * In real HW, it seems all internal status is lost when the enable register is cleared.
62 * The HW models behaves this way.
63 *
64 *
65 * Implementation notes:
66 *
67 */
68
69 #include <stdbool.h>
70 #include <stdint.h>
71 #include <string.h>
72 #include "NHW_common_types.h"
73 #include "NHW_config.h"
74 #include "NHW_peri_types.h"
75 #include "NHW_templates.h"
76 #include "NHW_UART.h"
77 #include "NHW_UART_private.h"
78 #include "NHW_UART_backend_if.h"
79 #include "NHW_xPPI.h"
80 #include "irq_ctrl.h"
81 #include "bs_tracing.h"
82 #include "bs_oswrap.h"
83 #include "bs_utils.h"
84 #include "bs_cmd_line.h"
85 #include "bs_dynargs.h"
86 #include "nsi_hw_scheduler.h"
87 #include "nsi_tasks.h"
88 #include "nsi_hws_models_if.h"
89
90 static struct uarte_status nhw_uarte_st[NHW_UARTE_TOTAL_INST];
91 NRF_UARTE_Type NRF_UARTE_regs[NHW_UARTE_TOTAL_INST];
92 NRF_UART_Type *NRF_UART_regs[NHW_UARTE_TOTAL_INST];
93
94 static bs_time_t Timer_UART_common = TIME_NEVER;
95 static bs_time_t Timer_UART_peri = TIME_NEVER;
96 extern bs_time_t nhw_Timer_ULoopback;
97
98 static void nhw_UARTE_signal_EVENTS_ERROR(unsigned int inst);
99 static void nhw_UARTE_signal_EVENTS_RXDRDY(unsigned int inst);
100 static void nhw_UARTE_signal_EVENTS_RXTO(unsigned int inst);
101 static void nhw_UARTE_signal_EVENTS_TXDRDY(unsigned int inst);
102 static void nhw_UARTE_signal_EVENTS_CTS(unsigned int inst);
103 static void nhw_UARTE_signal_EVENTS_NCTS(unsigned int inst);
104 static void nhw_UARTE_signal_EVENTS_TXSTARTED(unsigned int inst);
105 static void nhw_UARTE_signal_EVENTS_TXSTOPPED(unsigned int inst);
106 static void nhw_UARTE_signal_EVENTS_ENDTX(unsigned int inst);
107 static void nhw_UARTE_signal_EVENTS_RXSTARTED(unsigned int inst);
108 static void nhw_UARTE_signal_EVENTS_ENDRX(unsigned int inst);
109 static void nhw_UARTE_Tx_send_byte(unsigned int inst, struct uarte_status *u_el);
110 static void nhw_UART_Tx_queue_byte(uint inst, struct uarte_status *u_el, uint8_t byte);
111 static void nhw_UARTE_Rx_DMA_attempt(uint inst, struct uarte_status *u_el);
112 static void raise_RTS_R(uint inst, struct uarte_status *u_el);
113
nhw_uarte_init(void)114 static void nhw_uarte_init(void) {
115 #if (NHW_HAS_DPPI)
116 static uint nhw_UARTE_dppi_map[NHW_UARTE_TOTAL_INST] = NHW_UARTE_DPPI_MAP;
117 #endif
118
119 memset(NRF_UARTE_regs, 0, sizeof(NRF_UARTE_regs));
120
121 for (int i = 0; i < NHW_UARTE_TOTAL_INST; i++) {
122 struct uarte_status *u_el = &nhw_uarte_st[i];
123
124 u_el->inst = i;
125
126 NRF_UART_regs[i] = (NRF_UART_Type *)&NRF_UARTE_regs[i];
127 u_el->UART_regs[i] = (NRF_UART_Type *)&NRF_UARTE_regs[i];
128 u_el->UARTE_regs[i] = (NRF_UARTE_Type *)&NRF_UARTE_regs[i];
129
130 u_el->Rx_TO_timer = TIME_NEVER;
131 u_el->Tx_byte_done_timer = TIME_NEVER;
132
133 NRF_UARTE_regs[i].PSEL.RTS = 0xFFFFFFFF;
134 NRF_UARTE_regs[i].PSEL.TXD = 0xFFFFFFFF;
135 NRF_UARTE_regs[i].PSEL.CTS = 0xFFFFFFFF;
136 NRF_UARTE_regs[i].PSEL.RXD = 0xFFFFFFFF;
137 NRF_UARTE_regs[i].BAUDRATE = 0x04000000;
138
139 #if (NHW_HAS_DPPI)
140 u_el->dppi_map = nhw_UARTE_dppi_map[i];
141 #endif
142
143 raise_RTS_R(i, u_el);
144
145 if (u_el->Tx_log_file_name) {
146 bs_create_folders_in_path(u_el->Tx_log_file_name);
147 u_el->Tx_log_file = bs_fopen(u_el->Tx_log_file_name, "w");
148 fprintf(u_el->Tx_log_file, "time(microsecond),byte\n");
149 }
150 if (u_el->Rx_log_file_name) {
151 bs_create_folders_in_path(u_el->Rx_log_file_name);
152 u_el->Rx_log_file = bs_fopen(u_el->Rx_log_file_name, "w");
153 fprintf(u_el->Rx_log_file, "time(microsecond),byte\n");
154 }
155 }
156 }
157
158 NSI_TASK(nhw_uarte_init, HW_INIT, 200); /* Allow backend to be registered before */
159
nhw_uarte_cleanup(void)160 static void nhw_uarte_cleanup(void) {
161 for (int i = 0; i < NHW_UARTE_TOTAL_INST; i++) {
162 struct uarte_status *u_el = &nhw_uarte_st[i];
163 if (u_el->Tx_log_file) {
164 fclose(u_el->Tx_log_file);
165 u_el->Tx_log_file = NULL;
166 }
167 if (u_el->Rx_log_file) {
168 fclose(u_el->Rx_log_file);
169 u_el->Rx_log_file = NULL;
170 }
171 }
172 }
173
174 NSI_TASK(nhw_uarte_cleanup, ON_EXIT_PRE, 100);
175
nhw_uarte_register_rx_cb(int inst,uart_rtxb_cb_f cb,bool Rx_NotTx)176 uart_rtxb_cb_f nhw_uarte_register_rx_cb(int inst, uart_rtxb_cb_f cb, bool Rx_NotTx) {
177 struct uarte_status *u_el = &nhw_uarte_st[inst];
178 uart_rtxb_cb_f prev = u_el->trx_callbacks[(int) Rx_NotTx];
179 u_el->trx_callbacks[(int) Rx_NotTx] = cb;
180 return prev;
181 }
182
183 /*
184 * Register a backend to be used for a given UART instance
185 */
nhw_UARTE_backend_register(uint inst,struct backend_if * backend)186 void nhw_UARTE_backend_register(uint inst, struct backend_if *backend) {
187 struct uarte_status *u_el = &nhw_uarte_st[inst];
188
189 if (u_el->backend.tx_byte_f != NULL) {
190 bs_trace_warning_line("UART%i backend selection overwritten\n", inst);
191 }
192 memcpy(&u_el->backend, backend, sizeof(struct backend_if));
193 }
194
nhw_uarte_update_common_timer(void)195 void nhw_uarte_update_common_timer(void) {
196 Timer_UART_common = BS_MIN(Timer_UART_peri, nhw_Timer_ULoopback);
197 nsi_hws_find_next_event();
198 }
199
nhw_uarte_update_timer(void)200 static void nhw_uarte_update_timer(void) {
201 Timer_UART_peri = TIME_NEVER;
202 for (int i = 0; i < NHW_UARTE_TOTAL_INST; i++) {
203 struct uarte_status * u_el = &nhw_uarte_st[i];
204 bs_time_t smaller = BS_MIN(u_el->Rx_TO_timer, u_el->Tx_byte_done_timer);
205 Timer_UART_peri = BS_MIN(Timer_UART_peri, smaller);
206 }
207 nhw_uarte_update_common_timer();
208 }
209
uart_enabled(uint inst)210 static bool uart_enabled(uint inst) {
211 return NRF_UARTE_regs[inst].ENABLE == 4;
212 }
213
uarte_enabled(uint inst)214 static bool uarte_enabled(uint inst) {
215 return NRF_UARTE_regs[inst].ENABLE == 8;
216 }
217
218 /**
219 * Return the time in microseconds it takes for one byte to be Tx or Rx
220 * including start, parity and stop bits.
221 * Accounting for the UART configuration and baud rate
222 */
nhw_uarte_one_byte_time(uint inst)223 bs_time_t nhw_uarte_one_byte_time(uint inst) {
224 bs_time_t duration = 1 + 8 + 1; /* Start bit, byte, and at least 1 stop bit */
225 uint32_t CONFIG = NRF_UARTE_regs[inst].CONFIG;
226
227 if (CONFIG & UART_CONFIG_PARITY_Msk) {
228 duration +=1;
229 }
230 if (CONFIG & UART_CONFIG_STOP_Msk) { /* Two stop bits */
231 duration +=1;
232 }
233
234 if (uart_enabled(inst)) {
235 /* We round to the nearest microsecond */
236 switch (NRF_UARTE_regs[inst].BAUDRATE)
237 {
238 case UART_BAUDRATE_BAUDRATE_Baud1M:
239 break;
240 case UART_BAUDRATE_BAUDRATE_Baud921600:
241 duration = (double)duration * 1e6 / 921600 + 0.5;
242 break;
243 case UART_BAUDRATE_BAUDRATE_Baud460800:
244 duration = (double)duration * 1e6 / 460800 + 0.5;
245 break;
246 case UART_BAUDRATE_BAUDRATE_Baud250000:
247 duration = duration * 4;
248 break;
249 case UART_BAUDRATE_BAUDRATE_Baud230400:
250 duration = (double)duration * 1e6 / 230400 + 0.5;
251 break;
252 case UART_BAUDRATE_BAUDRATE_Baud115200:
253 duration = (double)duration * 1e6 / 115200 + 0.5;
254 break;
255 case UART_BAUDRATE_BAUDRATE_Baud76800:
256 duration = (double)duration * 1e6 / 76800 + 0.5;
257 break;
258 case UART_BAUDRATE_BAUDRATE_Baud57600:
259 duration = (double)duration * 1e6 / 57600 + 0.5;
260 break;
261 case UART_BAUDRATE_BAUDRATE_Baud56000:
262 duration = (double)duration * 1e6 / 56000 + 0.5;
263 break;
264 case UART_BAUDRATE_BAUDRATE_Baud38400:
265 duration = (double)duration * 1e6 / 38400 + 0.5;
266 break;
267 case UART_BAUDRATE_BAUDRATE_Baud31250:
268 duration = duration * 32;
269 break;
270 case UART_BAUDRATE_BAUDRATE_Baud28800:
271 duration = (double)duration * 1e6 / 28800 + 0.5;
272 break;
273 case UART_BAUDRATE_BAUDRATE_Baud19200:
274 duration = (double)duration * 1e6 / 19200 + 0.5;
275 break;
276 case UART_BAUDRATE_BAUDRATE_Baud14400:
277 duration = (double)duration * 1e6 / 14400 + 0.5;
278 break;
279 case UART_BAUDRATE_BAUDRATE_Baud9600:
280 duration = (double)duration * 1e6 / 9600 + 0.5;
281 break;
282 case UART_BAUDRATE_BAUDRATE_Baud4800:
283 duration = (double)duration * 1e6 / 4800 + 0.5;
284 break;
285 case UART_BAUDRATE_BAUDRATE_Baud2400:
286 duration = (double)duration * 1e6 / 2400 + 0.5;
287 break;
288 case UART_BAUDRATE_BAUDRATE_Baud1200:
289 duration = (double)duration * 1e6 / 1200 + 0.5;
290 break;
291 default:
292 bs_trace_error_time_line("NRF_UARTE_regs[%i]->BAUDRATE=%i no supported\n",
293 inst, NRF_UARTE_regs[inst].BAUDRATE);
294 break;
295 }
296 } else /* UARTE */ {
297 /* We round to the nearest microsecond */
298 switch (NRF_UARTE_regs[inst].BAUDRATE)
299 {
300 case UARTE_BAUDRATE_BAUDRATE_Baud1M:
301 break;
302 case UARTE_BAUDRATE_BAUDRATE_Baud921600:
303 duration = (double)duration * 1e6 / 921600 + 0.5;
304 break;
305 case UARTE_BAUDRATE_BAUDRATE_Baud460800:
306 duration = (double)duration * 1e6 / 460800 + 0.5;
307 break;
308 case UARTE_BAUDRATE_BAUDRATE_Baud250000:
309 duration = duration * 4;
310 break;
311 case UARTE_BAUDRATE_BAUDRATE_Baud230400:
312 duration = (double)duration * 1e6 / 230400 + 0.5;
313 break;
314 case UARTE_BAUDRATE_BAUDRATE_Baud115200:
315 duration = (double)duration * 1e6 / 115200 + 0.5;
316 break;
317 case UARTE_BAUDRATE_BAUDRATE_Baud76800:
318 duration = (double)duration * 1e6 / 76800 + 0.5;
319 break;
320 case UARTE_BAUDRATE_BAUDRATE_Baud57600:
321 duration = (double)duration * 1e6 / 57600 + 0.5;
322 break;
323 case UARTE_BAUDRATE_BAUDRATE_Baud56000:
324 duration = (double)duration * 1e6 / 56000 + 0.5;
325 break;
326 case UARTE_BAUDRATE_BAUDRATE_Baud38400:
327 duration = (double)duration * 1e6 / 38400 + 0.5;
328 break;
329 case UARTE_BAUDRATE_BAUDRATE_Baud31250:
330 duration = duration * 32;
331 break;
332 case UARTE_BAUDRATE_BAUDRATE_Baud28800:
333 duration = (double)duration * 1e6 / 28800 + 0.5;
334 break;
335 case UARTE_BAUDRATE_BAUDRATE_Baud19200:
336 duration = (double)duration * 1e6 / 19200 + 0.5;
337 break;
338 case UARTE_BAUDRATE_BAUDRATE_Baud14400:
339 duration = (double)duration * 1e6 / 14400 + 0.5;
340 break;
341 case UARTE_BAUDRATE_BAUDRATE_Baud9600:
342 duration = (double)duration * 1e6 / 9600 + 0.5;
343 break;
344 case UARTE_BAUDRATE_BAUDRATE_Baud4800:
345 duration = (double)duration * 1e6 / 4800 + 0.5;
346 break;
347 case UARTE_BAUDRATE_BAUDRATE_Baud2400:
348 duration = (double)duration * 1e6 / 2400 + 0.5;
349 break;
350 case UARTE_BAUDRATE_BAUDRATE_Baud1200:
351 duration = (double)duration * 1e6 / 1200 + 0.5;
352 break;
353 default:
354 bs_trace_error_time_line("NRF_UARTE_regs[%i]->BAUDRATE=%i no supported\n",
355 inst, NRF_UARTE_regs[inst].BAUDRATE);
356 break;
357 }
358 }
359
360 return duration;
361 }
362
Rx_FIFO_pop(uint inst,struct uarte_status * u_el)363 static uint8_t Rx_FIFO_pop(uint inst, struct uarte_status *u_el) {
364 uint8_t value;
365
366 if (u_el->Rx_FIFO_cnt <= 0) {
367 bs_trace_warning_time_line("UART%i: Attempted empty Rx FIFO pop\n", inst);
368 return 0;
369 }
370
371 value = u_el->Rx_FIFO[0];
372
373 for (int i = 1; i < u_el->Rx_FIFO_cnt; i++) {
374 u_el->Rx_FIFO[i-1] = u_el->Rx_FIFO[i];
375 }
376 u_el->Rx_FIFO_cnt -=1;
377
378 if (u_el->Rx_FIFO_cnt > 0) {
379 NRF_UART_regs[inst]->RXD = u_el->Rx_FIFO[0];
380 nhw_UARTE_signal_EVENTS_RXDRDY(inst);
381 }
382
383 return value;
384 }
385
Rx_FIFO_push(uint inst,struct uarte_status * u_el,uint8_t value)386 static void Rx_FIFO_push(uint inst, struct uarte_status *u_el, uint8_t value) {
387 if (u_el->Rx_FIFO_cnt >= RX_FIFO_SIZE) {
388 Rx_FIFO_pop(inst, u_el);
389 bs_trace_warning_time_line("UART%i: Pushed to full Rx FIFO, oldest value dropped\n", inst);
390 NRF_UART_regs[inst]->ERRORSRC |= UART_ERRORSRC_OVERRUN_Msk;
391 nhw_UARTE_signal_EVENTS_ERROR(inst);
392 }
393 u_el->Rx_FIFO[u_el->Rx_FIFO_cnt++] = value;
394
395 if (u_el->Rx_FIFO_cnt == 1){
396 NRF_UART_regs[inst]->RXD = u_el->Rx_FIFO[0];
397 nhw_UARTE_signal_EVENTS_RXDRDY(inst);
398 }
399 }
400
nhw_UARTE_Rx_DMA_end(uint inst,struct uarte_status * u_el)401 static void nhw_UARTE_Rx_DMA_end(uint inst, struct uarte_status * u_el) {
402 u_el->rx_dma_status = DMA_Off;
403 NRF_UARTE_regs[inst].RXD.AMOUNT = u_el->RXD_AMOUNT;
404 nhw_UARTE_signal_EVENTS_ENDRX(inst);
405 }
406
nhw_UARTE_Rx_DMA_attempt(uint inst,struct uarte_status * u_el)407 static void nhw_UARTE_Rx_DMA_attempt(uint inst, struct uarte_status * u_el) {
408 if (u_el->rx_dma_status != DMAing) {
409 return;
410 }
411
412 uint8_t *p = (uint8_t *)(u_el->RXD_PTR + u_el->RXD_AMOUNT);
413
414 while (u_el->Rx_FIFO_cnt && (u_el->RXD_AMOUNT < u_el->RXD_MAXCNT)) {
415 uint8_t value = Rx_FIFO_pop(inst, u_el);
416 *p++ = value;
417 u_el->RXD_AMOUNT++;
418 }
419 if (u_el->RXD_AMOUNT >= u_el->RXD_MAXCNT) {
420 nhw_UARTE_Rx_DMA_end(inst, u_el);
421 }
422 }
423
flow_control_on(uint inst)424 static bool flow_control_on(uint inst) {
425 return (NRF_UART_regs[inst]->CONFIG & UART_CONFIG_HWFC_Msk) != 0;
426 }
427
propagate_RTS_R(uint inst,struct uarte_status * u_el)428 static void propagate_RTS_R(uint inst, struct uarte_status *u_el) {
429 if (flow_control_on(inst)) {
430 if (u_el->backend.RTS_pin_toggle_f) {
431 u_el->backend.RTS_pin_toggle_f(inst, u_el->RTSR);
432 }
433 }
434 }
435
lower_RTS_R(uint inst,struct uarte_status * u_el)436 static void lower_RTS_R(uint inst, struct uarte_status *u_el) {
437 if (u_el->RTSR == false) {
438 return;
439 }
440 u_el->RTSR = false;
441 propagate_RTS_R(inst, u_el);
442 }
443
raise_RTS_R(uint inst,struct uarte_status * u_el)444 static void raise_RTS_R(uint inst, struct uarte_status *u_el) {
445 if (u_el->RTSR == true) {
446 return;
447 }
448 u_el->RTSR = true;
449 propagate_RTS_R(inst, u_el);
450 }
451
notify_backend_RxOnOff(uint inst,struct uarte_status * u_el,bool OnNotOff)452 static void notify_backend_RxOnOff(uint inst, struct uarte_status *u_el, bool OnNotOff) {
453 if (u_el->backend.uart_enable_notify_f) {
454 u_el->backend.uart_enable_notify_f(inst, u_el->tx_status != Tx_Off, OnNotOff);
455 }
456 }
457
notify_backend_TxOnOff(uint inst,struct uarte_status * u_el,bool OnNotOff)458 static void notify_backend_TxOnOff(uint inst, struct uarte_status *u_el, bool OnNotOff) {
459 if (u_el->backend.uart_enable_notify_f) {
460 u_el->backend.uart_enable_notify_f(inst, OnNotOff, u_el->rx_status != Rx_Off);
461 }
462 }
463
464 /**
465 * Process a byte incoming to the UART from a backend
466 * This call should be done in the last micros when the byte frame is finishing in the line
467 */
nhw_UARTE_digest_Rx_byte(uint inst,uint8_t byte)468 void nhw_UARTE_digest_Rx_byte(uint inst, uint8_t byte) {
469 struct uarte_status *u_el = &nhw_uarte_st[inst];
470 bs_time_t frame_start, now;
471
472 if (u_el->rx_status == Rx_Off) {
473 static int Received_error_count;
474 Received_error_count++;
475 if ((Received_error_count & 0xFF) <= 4) {
476 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);
477 if ((Received_error_count & 0xFF) == 4) {
478 bs_trace_warning_time_line("Silencing this warning the next 252 times\n", inst);
479 }
480 }
481 return;
482 }
483
484 now = nsi_hws_get_time();
485 frame_start = now - nhw_uarte_one_byte_time(inst) + 1;
486
487 if (u_el->Last_Rx_off_time >= frame_start) {
488 bs_trace_warning_time_line("Byte partially received while UART%i was not enabled for Rx, "
489 "this would have likely caused a framing error. Ignoring it in the model\n", inst);
490 return;
491 }
492
493 if (u_el->trx_callbacks[1]) {
494 u_el->trx_callbacks[1](inst, &byte);
495 }
496 if (u_el->Rx_log_file) {
497 fprintf(u_el->Rx_log_file, "%"PRItime",0x%02X\n", now, byte);
498 }
499
500 Rx_FIFO_push(inst, u_el, byte);
501 nhw_UARTE_Rx_DMA_attempt(inst, u_el);
502 if (u_el->Rx_FIFO_cnt >= RX_FIFO_RTS_THRESHOLD) {
503 raise_RTS_R(inst, u_el);
504 }
505 }
506
507 /**
508 * Propagate internally the CTS pin having been lowered
509 */
nhw_UARTE_CTS_lowered(uint inst)510 void nhw_UARTE_CTS_lowered(uint inst) {
511 struct uarte_status *u_el = &nhw_uarte_st[inst];
512
513 if (u_el->CTS_blocking == false) {
514 //It was already low (or perceived as such) => nothing to be done
515 return;
516 }
517
518 u_el->CTS_blocking = false;
519
520 if ( !(uart_enabled(inst) || uarte_enabled(inst)) ) {
521 return;
522 }
523
524 if (u_el->tx_status == Tx_Pend) {
525 nhw_UARTE_Tx_send_byte(inst, u_el);
526 }
527 nhw_UARTE_signal_EVENTS_CTS(inst);
528 }
529
530 /**
531 * Propagate internally the CTS pin having been lowered
532 */
nhw_UARTE_CTS_raised(uint inst)533 void nhw_UARTE_CTS_raised(uint inst) {
534 if (nhw_uarte_st[inst].CTS_blocking == true) {
535 return;
536 }
537 nhw_uarte_st[inst].CTS_blocking = true;
538
539 if ( !(uart_enabled(inst) || uarte_enabled(inst)) ) {
540 return;
541 }
542 nhw_UARTE_signal_EVENTS_NCTS(inst);
543 }
544
nhw_UARTE_eval_interrupt(uint inst)545 static void nhw_UARTE_eval_interrupt(uint inst) {
546 static bool uart_int_line[NHW_UARTE_TOTAL_INST]; /* Is the UART currently driving its interrupt line high */
547 /* Mapping of peripheral instance to {int controller instance, int number} */
548 static struct nhw_irq_mapping nhw_uart_irq_map[NHW_UARTE_TOTAL_INST] = NHW_UARTE_INT_MAP;
549 bool new_int_line = false;
550 uint32_t inten = NRF_UARTE_regs[inst].INTEN;
551
552 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., CTS, inten)
553 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., NCTS, inten)
554 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., RXDRDY, inten)
555 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., TXDRDY, inten)
556 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., ERROR, inten)
557 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., RXTO, inten)
558
559 if (uarte_enabled(inst)) {
560 /* It is unclear if these UART*E* events being still pended would still keep
561 * the int line high even in UART(not E) mode */
562 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., ENDRX, inten)
563 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., ENDTX, inten)
564 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., RXSTARTED, inten)
565 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., TXSTARTED, inten)
566 NHW_CHECK_INTERRUPT(UARTE, NRF_UARTE_regs[inst]., TXSTOPPED, inten)
567 }
568
569 hw_irq_ctrl_toggle_level_irq_line_if(&uart_int_line[inst],
570 new_int_line,
571 &nhw_uart_irq_map[inst]);
572 }
573
nhw_UARTE_TASK_STARTRX(int inst)574 void nhw_UARTE_TASK_STARTRX(int inst)
575 {
576 struct uarte_status *u_el = &nhw_uarte_st[inst];
577
578 if (!uart_enabled(inst) && !uarte_enabled(inst)) {
579 bs_trace_warning_time_line("Start RX triggered while UART%i is not enabled (%u). "
580 "Ignoring it.\n", inst, NRF_UARTE_regs[inst].ENABLE);
581 return;
582 }
583
584 if (uart_enabled(inst) && (u_el->rx_status != Rx_Off)) {
585 bs_trace_warning_time_line("Start Rx triggered for UART%i whose Rx is already started (%i). "
586 "Ignoring it\n", inst, u_el->rx_status);
587 return;
588 }
589
590 if (u_el->rx_dma_status != DMA_Off) {
591 bs_trace_warning_time_line("Start Rx triggered for UARTE%i whose Rx is already DMA'ing. "
592 "This seems like a SW error which the model does not handle. "
593 "Ignoring it\n", inst);
594 return;
595 }
596
597 if (u_el->rx_status == Rx_turning_off) {
598 /* The HW seems to support a STARTRX while it is turning off the Rx
599 * In this case, it seems the Rx TO is just cancelled */
600 u_el->Rx_TO_timer = TIME_NEVER;
601 u_el->rx_status = Rx_On;
602 }
603
604 if (uarte_enabled(inst)) {
605 u_el->RXD_PTR = NRF_UARTE_regs[inst].RXD.PTR;
606 u_el->RXD_MAXCNT = NRF_UARTE_regs[inst].RXD.MAXCNT;
607 u_el->RXD_AMOUNT = 0;
608 u_el->rx_dma_status = DMAing;
609 nhw_UARTE_signal_EVENTS_RXSTARTED(inst); /* Instantaneously ready */
610 nhw_UARTE_Rx_DMA_attempt(inst, u_el);
611 }
612
613 if (u_el->rx_status == Rx_Off) {
614 u_el->Last_Rx_off_time = nsi_hws_get_time();
615 u_el->rx_status = Rx_On;
616 notify_backend_RxOnOff(inst, u_el, true);
617 }
618
619 if (u_el->Rx_FIFO_cnt == 0) {
620 lower_RTS_R(inst, u_el);
621 }
622 }
623
nhw_UARTE_TASK_STOPRX(int inst)624 void nhw_UARTE_TASK_STOPRX(int inst)
625 {
626 /*
627 * If in UART mode (at least) raise RTS/R
628 * Set Rx in Off mode
629 */
630 struct uarte_status *u_el = &nhw_uarte_st[inst];
631
632 if (u_el->rx_status == Rx_Off) {
633 bs_trace_warning_time_line("UART%i Rx stopped while already stopped => ignored\n", inst);
634 return;
635 }
636 if (u_el->rx_status == Rx_turning_off) {
637 bs_trace_warning_time_line("UART%i Rx stopped while already stopping => ignored\n", inst);
638 return;
639 }
640
641 raise_RTS_R(inst, u_el);
642
643 //Start Rx TO timer to turn Rx fully off and generate RXTO
644 u_el->Rx_TO_timer = nsi_hws_get_time() + 5*nhw_uarte_one_byte_time(inst);
645 u_el->rx_status = Rx_turning_off;
646 nhw_uarte_update_timer();
647 }
648
nHW_UARTE_Tx_DMA_end(int inst,struct uarte_status * u_el)649 static void nHW_UARTE_Tx_DMA_end(int inst, struct uarte_status * u_el) {
650 u_el->tx_dma_status = DMA_Off;
651 NRF_UARTE_regs[inst].TXD.AMOUNT = u_el->TXD_AMOUNT;
652 nhw_UARTE_signal_EVENTS_ENDTX(inst);
653 }
654
nHW_UARTE_Tx_DMA_byte(int inst,struct uarte_status * u_el)655 static void nHW_UARTE_Tx_DMA_byte(int inst, struct uarte_status *u_el)
656 {
657 uint8_t *ptr = (uint8_t *)(u_el->TXD_PTR + u_el->TXD_AMOUNT);
658
659 nhw_UART_Tx_queue_byte(inst, u_el, *ptr);
660 }
661
nhw_UARTE_TASK_STARTTX(int inst)662 void nhw_UARTE_TASK_STARTTX(int inst)
663 {
664 struct uarte_status *u_el = &nhw_uarte_st[inst];
665
666 if (!uart_enabled(inst) && !uarte_enabled(inst)) {
667 bs_trace_warning_time_line("Start TX triggered while UART%i is not enabled (%u). "
668 "Ignoring it.\n", inst, NRF_UARTE_regs[inst].ENABLE);
669 return;
670 }
671
672 if (u_el->tx_dma_status != DMA_Off) {
673 bs_trace_warning_time_line("Start Tx triggered for UARTE%i whose Rx is already DMA'ing. "
674 "This seems like a SW error which the model does not handle. "
675 "Ignoring it\n", inst);
676 return;
677 }
678
679 if (u_el->tx_status == Tx_Off) {
680 u_el->tx_status = Tx_Idle;
681 notify_backend_TxOnOff(inst, u_el, true);
682 } else if (u_el->tx_status == Tx_Stopping) {
683 /* A frame was still in flight and it was trying to stop
684 * We abort the stop */
685 u_el->tx_status = Txing;
686 }
687
688 if (uarte_enabled(inst)) {
689 u_el->TXD_PTR = NRF_UARTE_regs[inst].TXD.PTR;
690 u_el->TXD_MAXCNT = NRF_UARTE_regs[inst].TXD.MAXCNT;
691 u_el->TXD_AMOUNT = 0;
692 u_el->tx_dma_status = DMAing;
693 nhw_UARTE_signal_EVENTS_TXSTARTED(inst); /* Instantaneously ready */
694 if (u_el->TXD_MAXCNT > 0) {
695 if (u_el->tx_status == Tx_Idle) {
696 nHW_UARTE_Tx_DMA_byte(inst, u_el);
697 }
698 } else {
699 nHW_UARTE_Tx_DMA_end(inst, u_el);
700 }
701 }
702 }
703
nhw_UARTE_tx_final_stop(int inst,struct uarte_status * u_el)704 static void nhw_UARTE_tx_final_stop(int inst, struct uarte_status *u_el) {
705 u_el->tx_status = Tx_Off;
706 notify_backend_TxOnOff(inst, u_el, false);
707
708 if (uarte_enabled(inst)) {
709 if (u_el->tx_dma_status == DMAing) {
710 nHW_UARTE_Tx_DMA_end(inst, u_el);
711 }
712 nhw_UARTE_signal_EVENTS_TXSTOPPED(inst);
713 }
714 }
715
nhw_UARTE_TASK_STOPTX(int inst)716 void nhw_UARTE_TASK_STOPTX(int inst)
717 {
718 struct uarte_status * u_el = &nhw_uarte_st[inst];
719
720 /* STOP behavior is slightly different in UART and UART-E modes */
721 if (uart_enabled(inst)) {
722 if (u_el->tx_status > Tx_Idle) {
723 bs_trace_warning_time_line("UART%i Tx stopped while not idle\n", inst);
724 if (u_el->tx_status == Tx_Pend) {
725 bs_trace_warning_time_line("A byte was pending to Tx awaiting CTS, it is dropped\n");
726 nhw_UARTE_tx_final_stop(inst, u_el);
727 } else if (u_el->tx_status == Txing) {
728 bs_trace_warning_time_line("A Tx byte is already in flight, it will be completed"
729 "(this is not how real HW behaves)\n");
730 /* In the model, the byte is already in flight, so nothing can't be done anymore */
731 u_el->tx_status = Tx_Stopping;
732 }
733 } else {
734 nhw_UARTE_tx_final_stop(inst, u_el);
735 }
736 }
737
738 if (uarte_enabled(inst)) {
739 if (u_el->tx_status == Txing) {
740 u_el->tx_status = Tx_Stopping;
741 } else if (u_el->tx_status == Tx_Stopping) {
742 bs_trace_info(3, "UART%i STOPTX received while already stopping, ignored\n", inst);
743 return;
744 } else { /* Pend or Idle */
745 nhw_UARTE_tx_final_stop(inst, u_el);
746 }
747 }
748 }
749
750 /*
751 * Queue a byte for transmission right away in the backends
752 */
nhw_UARTE_Tx_byte(unsigned int inst,struct uarte_status * u_el,uint8_t data)753 static void nhw_UARTE_Tx_byte(unsigned int inst, struct uarte_status *u_el, uint8_t data) {
754 if (u_el->trx_callbacks[0]) {
755 u_el->trx_callbacks[0](inst, &data);
756 }
757 if (u_el->backend.tx_byte_f) {
758 u_el->backend.tx_byte_f(inst, data);
759 }
760 if (u_el->Tx_log_file) {
761 fprintf(u_el->Tx_log_file, "%"PRItime",0x%02X\n", nsi_hws_get_time(), data);
762 }
763 }
764
765 /*
766 * Start the process of actually sending the byte thru the line
767 */
nhw_UARTE_Tx_send_byte(unsigned int inst,struct uarte_status * u_el)768 static void nhw_UARTE_Tx_send_byte(unsigned int inst, struct uarte_status *u_el) {
769 nhw_UARTE_Tx_byte(inst, u_el, u_el->Tx_byte);
770 u_el->Tx_byte_done_timer = nsi_hws_get_time() + nhw_uarte_one_byte_time(inst);
771 u_el->tx_status = Txing;
772 nhw_uarte_update_timer();
773
774 if (u_el->tx_dma_status == DMAing) {
775 u_el->TXD_AMOUNT++;
776 if (u_el->TXD_AMOUNT >= u_el->TXD_MAXCNT) {
777 nHW_UARTE_Tx_DMA_end(inst, u_el);
778 }
779 }
780 }
781
782 /*
783 * Queue a byte to Tx'ed as soon as possible
784 */
nhw_UART_Tx_queue_byte(uint inst,struct uarte_status * u_el,uint8_t byte)785 static void nhw_UART_Tx_queue_byte(uint inst, struct uarte_status *u_el, uint8_t byte)
786 {
787 if (u_el->tx_status != Tx_Idle) {
788 bs_trace_error_time_line("Attempted to queue a byte for Tx but a transmission is currently ongoing. "
789 "This should not have happened\n", inst);
790 return;
791 }
792
793 u_el->Tx_byte = byte;
794
795 /*
796 * If !flow_control or (flow control & CTS low)
797 * Start the actual Tx
798 * otherwise // (flow control & CTS high)
799 * "Pend" the Tx (set in a state in which a lower of CTS will start it)
800 */
801 if ((flow_control_on(inst) == false) || (u_el->CTS_blocking == false)) {
802 nhw_UARTE_Tx_send_byte(inst, u_el);
803 } else {
804 u_el->tx_status = Tx_Pend;
805 }
806 }
807
808
809 /*
810 * The Rx TO timer has timed out
811 */
nhw_uart_Rx_TO_timer_triggered(int inst,struct uarte_status * u_el)812 static void nhw_uart_Rx_TO_timer_triggered(int inst, struct uarte_status *u_el)
813 {
814 if (u_el->rx_status != Rx_turning_off) {
815 bs_trace_error_time_line("Programming error\n");
816 }
817 u_el->Rx_TO_timer = TIME_NEVER;
818 u_el->rx_status = Rx_Off;
819 if (u_el->rx_dma_status == DMAing) {
820 nhw_UARTE_Rx_DMA_end(inst, u_el);
821 }
822 if (u_el->rx_status == Rx_Off) {
823 /* The DMA end may have triggered thru a short ENDRX->STARTRX, which restarts the RX and
824 * prevents the RXTO from being generated */
825 nhw_UARTE_signal_EVENTS_RXTO(inst);
826 notify_backend_RxOnOff(inst, u_el, false);
827 }
828 }
829
nhw_uart_Tx_byte_done_timer_triggered(int inst,struct uarte_status * u_el)830 static void nhw_uart_Tx_byte_done_timer_triggered(int inst, struct uarte_status *u_el)
831 {
832 u_el->Tx_byte_done_timer = TIME_NEVER;
833 nhw_UARTE_signal_EVENTS_TXDRDY(inst);
834
835 if (u_el->tx_status == Txing) {
836 u_el->tx_status = Tx_Idle;
837
838 } else if (u_el->tx_status == Tx_Stopping) {
839 nhw_UARTE_tx_final_stop(inst, u_el);
840 return;
841 }
842
843 if (u_el->tx_dma_status == DMAing) {
844 nHW_UARTE_Tx_DMA_byte(inst, u_el);
845 }
846 }
847
nhw_uart_timer_triggered(void)848 static void nhw_uart_timer_triggered(void)
849 {
850 bs_time_t current_time = Timer_UART_peri;
851
852 for (int inst = 0; inst < NHW_UARTE_TOTAL_INST; inst++) {
853 struct uarte_status *u_el = &nhw_uarte_st[inst];
854
855 if (current_time == u_el->Rx_TO_timer) {
856 nhw_uart_Rx_TO_timer_triggered(inst, u_el);
857 }
858 if (current_time == u_el->Tx_byte_done_timer) {
859 nhw_uart_Tx_byte_done_timer_triggered(inst, u_el);
860 }
861 }
862 nhw_uarte_update_timer();
863 }
864
nhw_uart_timer_common_triggered(void)865 static void nhw_uart_timer_common_triggered(void)
866 {
867 bs_time_t current_time = Timer_UART_common;
868 if (current_time == nhw_Timer_ULoopback) {
869 extern void nhw_ublb_timer_triggered(void);
870 nhw_ublb_timer_triggered();
871 }
872 if (current_time == Timer_UART_peri) {
873 nhw_uart_timer_triggered();
874 }
875 }
876
877 NSI_HW_EVENT(Timer_UART_common, nhw_uart_timer_common_triggered, 50);
878
nhw_UARTE_TASK_FLUSHRX(int inst)879 void nhw_UARTE_TASK_FLUSHRX(int inst) {
880 if (!uarte_enabled(inst)) {
881 bs_trace_warning_time_line("TASK_FLUSHRX for UART%i while it is not enabled in UARTE mode\n",
882 inst);
883 return;
884 }
885
886 struct uarte_status * u_el = &nhw_uarte_st[inst];
887
888 u_el->RXD_PTR = NRF_UARTE_regs[inst].RXD.PTR;
889 u_el->RXD_MAXCNT = NRF_UARTE_regs[inst].RXD.MAXCNT;
890 u_el->RXD_AMOUNT = 0;
891 u_el->rx_dma_status = DMAing;
892 nhw_UARTE_Rx_DMA_attempt(inst, u_el);
893 if (u_el->rx_dma_status == DMAing) {
894 nhw_UARTE_Rx_DMA_end(inst, u_el);
895 }
896 }
897
nhw_UARTE_TASK_SUSPEND(int inst)898 void nhw_UARTE_TASK_SUSPEND(int inst) {
899 /* UART(not-E) only task */
900 nhw_UARTE_TASK_STOPTX(inst);
901 nhw_UARTE_TASK_STOPRX(inst);
902 }
903
nhw_UARTE_regw_sideeffects_ENABLE(unsigned int inst)904 void nhw_UARTE_regw_sideeffects_ENABLE(unsigned int inst) {
905 struct uarte_status * u_el = &nhw_uarte_st[inst];
906
907 if (NRF_UARTE_regs[inst].ENABLE != 0) {
908 propagate_RTS_R(inst, u_el);
909 return;
910 }
911
912 if (u_el->tx_status != Tx_Off) {
913 bs_trace_warning_time_line("UART%i disabled while Tx was not Off (%i)\n", inst, u_el->tx_status);
914 }
915 if (u_el->rx_status != Rx_Off) {
916 bs_trace_warning_time_line("UART%i disabled while Rx was not Off (%i)\n", inst, u_el->rx_status);
917 }
918
919 if (u_el->Rx_TO_timer != TIME_NEVER) {
920 bs_trace_warning_time_line("UART%i disabled while Rx was shutting Off. Events will be missed\n", inst);
921 }
922 if (u_el->Tx_byte_done_timer != TIME_NEVER) {
923 bs_trace_warning_time_line("UART%i disabled while Tx was mid frame. Events will be missed\n", inst);
924 }
925
926 u_el->tx_status = Tx_Off;
927 u_el->tx_status = Rx_Off;
928
929 u_el->Rx_TO_timer = TIME_NEVER;
930 u_el->Tx_byte_done_timer = TIME_NEVER;
931 nhw_uarte_update_timer();
932
933 u_el->Rx_FIFO_cnt = 0;
934
935 if (u_el->tx_dma_status != DMA_Off) {
936 bs_trace_warning_time_line("UARTE%i disabled while Tx DMA was not Off. DMA interrupted mid way, ENDTX will be missing\n", inst);
937 }
938 if (u_el->rx_dma_status != DMA_Off) {
939 bs_trace_warning_time_line("UARTE%i disabled while Rx DMA was not Off. DMA interrupted mid way, ENDRX will be missing\n", inst);
940 }
941
942 u_el->tx_dma_status = DMA_Off;
943 u_el->rx_dma_status = DMA_Off;
944
945 notify_backend_RxOnOff(inst, u_el, false);
946 }
947
nhw_UARTE_regw_sideeffects_CONFIG(unsigned int inst)948 void nhw_UARTE_regw_sideeffects_CONFIG(unsigned int inst) {
949 if (NRF_UARTE_regs[inst].ENABLE != 0) {
950 struct uarte_status *u_el = &nhw_uarte_st[inst];
951 propagate_RTS_R(inst, u_el);
952 }
953 }
954
nhw_UARTE_regr_sideeffects_ERRORSRC(unsigned int inst)955 uint32_t nhw_UARTE_regr_sideeffects_ERRORSRC(unsigned int inst) {
956 uint32_t value = NRF_UARTE_regs[inst].ERRORSRC;
957 NRF_UARTE_regs[inst].ERRORSRC = 0;
958 return value;
959 }
960
nhw_UARTE_regw_sideeffects_ERRORSRC(unsigned int inst)961 void nhw_UARTE_regw_sideeffects_ERRORSRC(unsigned int inst) {
962 NRF_UARTE_regs[inst].ERRORSRC = 0;
963 }
964
nhw_UARTE_regr_sideeffects_RXD(unsigned int inst)965 uint32_t nhw_UARTE_regr_sideeffects_RXD(unsigned int inst) {
966 if (!uart_enabled(inst)) {
967 bs_trace_warning("RXD read while UART%i was not enabled\n", inst);
968 }
969 /*
970 * Read logic: If RxFIFO has anything pop a new value into RXD, otherwise just warn.
971 *
972 * If RTS is high & Rx is not stopped & the FIFO is empty: lower RTS
973 *
974 * If there is anything else in the Rx FIFO, signal another RXDRDY
975 */
976
977 uint32_t value;
978 struct uarte_status * u_el = &nhw_uarte_st[inst];
979
980 if (u_el->Rx_FIFO_cnt == 0) {
981 bs_trace_warning("UART%i: Reading RXD without any new data there\n", inst);
982 return NRF_UART_regs[inst]->RXD;
983 }
984
985 value = Rx_FIFO_pop(inst, u_el);
986
987 if ((u_el->Rx_FIFO_cnt == 0)
988 && (u_el->rx_status == Rx_On)) {
989 lower_RTS_R(inst, u_el);
990 }
991
992 return value;
993 }
994
nhw_UARTE_regw_sideeffects_TXD(unsigned int inst)995 void nhw_UARTE_regw_sideeffects_TXD(unsigned int inst)
996 {
997 if (!uart_enabled(inst)) {
998 bs_trace_warning("TXD written while UART%i was not enabled (in non-E mode)\n", inst);
999 }
1000
1001 /*
1002 * If Tx is off warn and ignore (return)
1003 * If Tx is busy, warn and ignore (return)
1004 */
1005
1006 struct uarte_status *u_el = &nhw_uarte_st[inst];
1007
1008 if ( u_el->tx_status == Tx_Off ) {
1009 bs_trace_warning("UART%i.TXD written but it was Tx was not started => ignoring\n", inst);
1010 return;
1011 }
1012 if ((u_el->tx_status == Tx_Pend) || (u_el->tx_status == Txing)) {
1013 bs_trace_warning("UART%i.TXD written but a transmission is currently ongoing => ignoring it\n", inst);
1014 return;
1015 }
1016
1017 nhw_UART_Tx_queue_byte(inst, u_el, NRF_UART_regs[inst]->TXD);
1018 }
1019
1020 #if (NHW_HAS_PPI)
1021 #define _NHW_UARTE_XPPI_EVENT(inst, event) \
1022 if (inst == 0) { \
1023 nrf_ppi_event(UARTE0_EVENTS_##event); \
1024 } else { \
1025 nrf_ppi_event(UARTE1_EVENTS_##event); \
1026 }
1027 #elif (NHW_HAS_DPPI)
1028 #define _NHW_UARTE_XPPI_EVENT(inst, event) \
1029 nhw_dppi_event_signal_if(nhw_uarte_st[inst].dppi_map, \
1030 NRF_UARTE_regs[inst].PUBLISH_##event)
1031 #endif /* (NHW_HAS_PPI) / (NHW_HAS_DPPI)*/
1032
1033 #define _NHW_UARTE_SIGNAL_EVENT_body(event) \
1034 { \
1035 NRF_UARTE_regs[inst].EVENTS_##event = 1; \
1036 nhw_UARTE_eval_interrupt(inst); \
1037 _NHW_UARTE_XPPI_EVENT(inst, event); \
1038 }
1039
1040 #define NHW_UARTE_SIGNAL_EVENT(event) \
1041 static void nhw_UARTE_signal_EVENTS_##event(unsigned int inst) \
1042 _NHW_UARTE_SIGNAL_EVENT_body(event)
1043
1044 #define NHW_UARTE_SIGNAL_EVENT_ns(event) \
1045 static void nhw_UARTE_signal_EVENTS_##event##_noshort(unsigned int inst) \
1046 _NHW_UARTE_SIGNAL_EVENT_body(event)
1047
1048 NHW_UARTE_SIGNAL_EVENT_ns(CTS)
NHW_UARTE_SIGNAL_EVENT_ns(NCTS)1049 NHW_UARTE_SIGNAL_EVENT_ns(NCTS)
1050 NHW_UARTE_SIGNAL_EVENT(RXDRDY)
1051 NHW_UARTE_SIGNAL_EVENT_ns(ENDRX) /* DMA Rx done */
1052 NHW_UARTE_SIGNAL_EVENT(TXDRDY)
1053 NHW_UARTE_SIGNAL_EVENT(ENDTX) /* DMA Tx done */
1054 NHW_UARTE_SIGNAL_EVENT(ERROR)
1055 NHW_UARTE_SIGNAL_EVENT(RXTO) /* Receiver done closing */
1056 NHW_UARTE_SIGNAL_EVENT(RXSTARTED)
1057 NHW_UARTE_SIGNAL_EVENT(TXSTARTED)
1058 NHW_UARTE_SIGNAL_EVENT(TXSTOPPED)
1059
1060 static void nhw_UARTE_signal_EVENTS_CTS(unsigned int inst) {
1061 #define UARTE_SHORTS_CTS_STARTRX_Msk UART_SHORTS_CTS_STARTRX_Msk
1062 if (uart_enabled(inst)) { //Only in UART mode
1063 NHW_SHORT(UARTE, inst, NRF_UARTE_regs[inst]., CTS, STARTRX)
1064 }
1065 nhw_UARTE_signal_EVENTS_CTS_noshort(inst);
1066 }
1067
nhw_UARTE_signal_EVENTS_NCTS(unsigned int inst)1068 static void nhw_UARTE_signal_EVENTS_NCTS(unsigned int inst) {
1069 #define UARTE_SHORTS_NCTS_STOPRX_Msk UART_SHORTS_NCTS_STOPRX_Msk
1070 if (uart_enabled(inst)) { //Only in UART mode
1071 NHW_SHORT(UARTE, inst, NRF_UARTE_regs[inst]., NCTS, STOPRX)
1072 }
1073 nhw_UARTE_signal_EVENTS_NCTS_noshort(inst);
1074 }
1075
nhw_UARTE_signal_EVENTS_ENDRX(unsigned int inst)1076 static void nhw_UARTE_signal_EVENTS_ENDRX(unsigned int inst) {
1077 if (uarte_enabled(inst)) { //Only in UART-E mode
1078 NHW_SHORT(UARTE, inst, NRF_UARTE_regs[inst]., ENDRX, STARTRX)
1079 NHW_SHORT(UARTE, inst, NRF_UARTE_regs[inst]., ENDRX, STOPRX)
1080 }
1081 nhw_UARTE_signal_EVENTS_ENDRX_noshort(inst);
1082 }
1083
1084 NHW_SIDEEFFECTS_INTSET(UARTE, NRF_UARTE_regs[inst]., NRF_UARTE_regs[inst].INTEN)
1085 NHW_SIDEEFFECTS_INTCLR(UARTE, NRF_UARTE_regs[inst]., NRF_UARTE_regs[inst].INTEN)
1086 NHW_SIDEEFFECTS_INTEN(UARTE, NRF_UARTE_regs[inst]., NRF_UARTE_regs[inst].INTEN)
1087
NHW_SIDEEFFECTS_EVENTS(UARTE)1088 NHW_SIDEEFFECTS_EVENTS(UARTE)
1089
1090 NHW_SIDEEFFECTS_TASKS(UARTE, NRF_UARTE_regs[inst]., STARTRX)
1091 NHW_SIDEEFFECTS_TASKS(UARTE, NRF_UARTE_regs[inst]., STOPRX)
1092 NHW_SIDEEFFECTS_TASKS(UARTE, NRF_UARTE_regs[inst]., STARTTX)
1093 NHW_SIDEEFFECTS_TASKS(UARTE, NRF_UARTE_regs[inst]., STOPTX)
1094 NHW_SIDEEFFECTS_TASKS(UARTE, NRF_UARTE_regs[inst]., FLUSHRX)
1095
1096 void nhw_UARTE_regw_sideeffects_TASKS_SUSPEND(unsigned int inst) {
1097 /* Needs special treatment for being an UART(non-E) only task */
1098 if ( NRF_UART_regs[inst]->TASKS_SUSPEND ) {
1099 NRF_UART_regs[inst]->TASKS_SUSPEND = 0;
1100 nhw_UARTE_TASK_SUSPEND(inst);
1101 }
1102 }
1103
1104 #define NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(TASK_N) \
1105 static void nhw_UARTE_TASK_##TASK_N##_wrap(void* param) \
1106 { \
1107 nhw_UARTE_TASK_##TASK_N((int) param); \
1108 } \
1109 \
1110 void nhw_uarte_regw_sideeffects_SUBSCRIBE_##TASK_N(uint inst) \
1111 { \
1112 static struct nhw_subsc_mem TASK_N##_subscribed[NHW_UARTE_TOTAL_INST]; \
1113 struct uarte_status *this = &nhw_uarte_st[inst]; \
1114 \
1115 nhw_dppi_common_subscribe_sideeffect(this->dppi_map, \
1116 this->UARTE_regs[inst]->SUBSCRIBE_##TASK_N,\
1117 &TASK_N##_subscribed[inst], \
1118 nhw_UARTE_TASK_##TASK_N##_wrap, \
1119 (void*) inst); \
1120 }
1121
1122 #if (NHW_HAS_DPPI)
1123 NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(STARTRX)
NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(STOPRX)1124 NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(STOPRX)
1125 NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(STARTTX)
1126 NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(STOPTX)
1127 NHW_UARTE_REGW_SIDEFFECTS_SUBSCRIBE(FLUSHRX)
1128 #endif /* NHW_HAS_DPPI */
1129
1130 #if (NHW_HAS_PPI)
1131 void nhw_uarte0_TASKS_STARTRX(void) { nhw_UARTE_TASK_STARTRX(0); }
nhw_uarte0_TASKS_STOPRX(void)1132 void nhw_uarte0_TASKS_STOPRX(void) { nhw_UARTE_TASK_STOPRX(0); }
nhw_uarte0_TASKS_STARTTX(void)1133 void nhw_uarte0_TASKS_STARTTX(void) { nhw_UARTE_TASK_STARTTX(0); }
nhw_uarte0_TASKS_STOPTX(void)1134 void nhw_uarte0_TASKS_STOPTX(void) { nhw_UARTE_TASK_STOPTX(0); }
nhw_uarte0_TASKS_SUSPEND(void)1135 void nhw_uarte0_TASKS_SUSPEND(void) { nhw_UARTE_TASK_SUSPEND(0); }
nhw_uarte0_TASKS_FLUSHRX(void)1136 void nhw_uarte0_TASKS_FLUSHRX(void) { nhw_UARTE_TASK_FLUSHRX(0); }
1137
nhw_uarte1_TASKS_STARTRX(void)1138 void nhw_uarte1_TASKS_STARTRX(void) { nhw_UARTE_TASK_STARTRX(1); }
nhw_uarte1_TASKS_STOPRX(void)1139 void nhw_uarte1_TASKS_STOPRX(void) { nhw_UARTE_TASK_STOPRX(1); }
nhw_uarte1_TASKS_STARTTX(void)1140 void nhw_uarte1_TASKS_STARTTX(void) { nhw_UARTE_TASK_STARTTX(1); }
nhw_uarte1_TASKS_STOPTX(void)1141 void nhw_uarte1_TASKS_STOPTX(void) { nhw_UARTE_TASK_STOPTX(1); }
nhw_uarte1_TASKS_SUSPEND(void)1142 void nhw_uarte1_TASKS_SUSPEND(void) { nhw_UARTE_TASK_SUSPEND(1); }
nhw_uarte1_TASKS_FLUSHRX(void)1143 void nhw_uarte1_TASKS_FLUSHRX(void) { nhw_UARTE_TASK_FLUSHRX(1); }
1144 #endif /* (NHW_HAS_PPI) */
1145
uart_list(char * argv,int offset)1146 static void uart_list(char *argv, int offset) {
1147 char *uart_names[NHW_UARTE_TOTAL_INST] = NHW_UARTE_NAMES;
1148 printf("UART #: UART name\n");
1149 for (int i = 0; i < NHW_UARTE_TOTAL_INST; i++) {
1150 printf("%6i: %s\n", i, uart_names[i]);
1151 }
1152 bs_trace_exit(0);
1153 }
1154
nhw_uart_register_cmdline(void)1155 static void nhw_uart_register_cmdline(void) {
1156 static bs_args_struct_t args[] = {
1157 { .is_switch = true,
1158 .option = "uart_list",
1159 .type = 'b',
1160 .call_when_found = uart_list,
1161 .descript = "List available UARTs"
1162 },
1163 ARG_TABLE_ENDMARKER
1164 };
1165
1166 bs_add_extra_dynargs(args);
1167
1168 static bs_args_struct_t args2[2*NHW_UARTE_TOTAL_INST + 1 /* End marker */];
1169 static char descr_tx[] = "Path to a file where the Tx bytes will be logged. Setting this enables the Tx logging for this UART";
1170 static char descr_rx[] = "Path to a file where the Rx bytes will be logged. Setting this enables the Rx logging for this UART";
1171 #define OPTION_LEN (4 + 2 + 11 + 1)
1172 static char options[NHW_UARTE_TOTAL_INST][2][OPTION_LEN];
1173 static char opt_name[]= "path";
1174
1175 for (int i = 0 ; i < NHW_UARTE_TOTAL_INST; i++) {
1176 snprintf(options[i][0], OPTION_LEN, "uart%i_log_txfile", i);
1177 snprintf(options[i][1], OPTION_LEN, "uart%i_log_rxfile", i);
1178
1179 args2[2*i].option = options[i][0];
1180 args2[2*i].name = opt_name;
1181 args2[2*i].type = 's';
1182 args2[2*i].dest = &nhw_uarte_st[i].Tx_log_file_name;
1183 args2[2*i].descript = descr_tx;
1184
1185 args2[2*i + 1].option = options[i][1];
1186 args2[2*i + 1].name = opt_name;
1187 args2[2*i + 1].type = 's';
1188 args2[2*i + 1].dest = &nhw_uarte_st[i].Rx_log_file_name;
1189 args2[2*i + 1].descript = descr_rx;
1190 }
1191
1192 bs_add_extra_dynargs(args2);
1193 }
1194
1195 NSI_TASK(nhw_uart_register_cmdline, PRE_BOOT_1, 199); /* Just before the backends */
1196