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