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