1 /*
2 * Copyright (c) 2015 - 2025, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of the copyright holder nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include <nrfx.h>
35
36 #if NRFX_CHECK(NRFX_UART_ENABLED)
37
38 #if !NRFX_FEATURE_PRESENT(NRFX_UART, _ENABLED)
39 #error "No enabled UART instances. Check <nrfx_config.h>."
40 #endif
41
42 #include <nrfx_uart.h>
43 #include "prs/nrfx_prs.h"
44 #include <hal/nrf_gpio.h>
45
46 #define NRFX_LOG_MODULE UART
47 #include <nrfx_log.h>
48
49 #define EVT_TO_STR(event) \
50 (event == NRF_UART_EVENT_ERROR ? "NRF_UART_EVENT_ERROR" : \
51 "UNKNOWN EVENT")
52
53
54 #define TX_COUNTER_ABORT_REQ_VALUE UINT32_MAX
55
56 typedef struct
57 {
58 void * p_context;
59 nrfx_uart_event_handler_t handler;
60 uint8_t const * p_tx_buffer;
61 uint8_t * p_rx_buffer;
62 uint8_t * p_rx_secondary_buffer;
63 volatile size_t tx_buffer_length;
64 size_t rx_buffer_length;
65 size_t rx_secondary_buffer_length;
66 volatile size_t tx_counter;
67 volatile size_t rx_counter;
68 volatile bool tx_abort;
69 bool rx_enabled;
70 nrfx_drv_state_t state;
71 bool skip_gpio_cfg : 1;
72 bool skip_psel_cfg : 1;
73 } uart_control_block_t;
74 static uart_control_block_t m_cb[NRFX_UART_ENABLED_COUNT];
75
interrupts_enable(nrfx_uart_t const * p_instance,uint8_t interrupt_priority)76 static void interrupts_enable(nrfx_uart_t const * p_instance,
77 uint8_t interrupt_priority)
78 {
79 nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_TXDRDY);
80 nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_RXTO);
81 nrf_uart_int_enable(p_instance->p_reg, NRF_UART_INT_MASK_TXDRDY |
82 NRF_UART_INT_MASK_RXTO);
83 NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number((void *)p_instance->p_reg),
84 interrupt_priority);
85 NRFX_IRQ_ENABLE(nrfx_get_irq_number((void *)p_instance->p_reg));
86 }
87
interrupts_disable(nrfx_uart_t const * p_instance)88 static void interrupts_disable(nrfx_uart_t const * p_instance)
89 {
90 nrf_uart_int_disable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY |
91 NRF_UART_INT_MASK_TXDRDY |
92 NRF_UART_INT_MASK_ERROR |
93 NRF_UART_INT_MASK_RXTO);
94 NRFX_IRQ_DISABLE(nrfx_get_irq_number((void *)p_instance->p_reg));
95 }
96
uart_configure(nrfx_uart_t const * p_instance,nrfx_uart_config_t const * p_config)97 static void uart_configure(nrfx_uart_t const * p_instance,
98 nrfx_uart_config_t const * p_config)
99 {
100 nrf_uart_baudrate_set(p_instance->p_reg, p_config->baudrate);
101 nrf_uart_configure(p_instance->p_reg, &p_config->hal_cfg);
102
103 if (!p_config->skip_gpio_cfg)
104 {
105 if (p_config->pseltxd != NRF_UART_PSEL_DISCONNECTED)
106 {
107 nrf_gpio_pin_set(p_config->pseltxd);
108 nrf_gpio_cfg_output(p_config->pseltxd);
109 }
110 if (p_config->pselrxd != NRF_UART_PSEL_DISCONNECTED)
111 {
112 nrf_gpio_cfg_input(p_config->pselrxd, NRF_GPIO_PIN_NOPULL);
113 }
114 }
115 if (!p_config->skip_psel_cfg)
116 {
117 nrf_uart_txrx_pins_set(p_instance->p_reg,
118 p_config->pseltxd, p_config->pselrxd);
119 }
120
121 if (p_config->hal_cfg.hwfc == NRF_UART_HWFC_ENABLED)
122 {
123 if (!p_config->skip_gpio_cfg)
124 {
125 if (p_config->pselrts != NRF_UART_PSEL_DISCONNECTED)
126 {
127 nrf_gpio_pin_set(p_config->pselrts);
128 nrf_gpio_cfg_output(p_config->pselrts);
129 }
130 if (p_config->pselcts != NRF_UART_PSEL_DISCONNECTED)
131 {
132 nrf_gpio_cfg_input(p_config->pselcts, NRF_GPIO_PIN_NOPULL);
133 }
134 }
135 if (!p_config->skip_psel_cfg)
136 {
137 nrf_uart_hwfc_pins_set(p_instance->p_reg,
138 p_config->pselrts, p_config->pselcts);
139 }
140 }
141
142 if (m_cb[p_instance->drv_inst_idx].handler)
143 {
144 interrupts_enable(p_instance, p_config->interrupt_priority);
145 }
146 }
147
pins_to_default(nrfx_uart_t const * p_instance)148 static void pins_to_default(nrfx_uart_t const * p_instance)
149 {
150 uart_control_block_t const * p_cb = &m_cb[p_instance->drv_inst_idx];
151
152 /* Reset pins to default states */
153 uint32_t txd;
154 uint32_t rxd;
155 uint32_t rts;
156 uint32_t cts;
157
158 txd = nrf_uart_tx_pin_get(p_instance->p_reg);
159 rxd = nrf_uart_rx_pin_get(p_instance->p_reg);
160 rts = nrf_uart_rts_pin_get(p_instance->p_reg);
161 cts = nrf_uart_cts_pin_get(p_instance->p_reg);
162
163 if (!p_cb->skip_psel_cfg)
164 {
165 nrf_uart_txrx_pins_disconnect(p_instance->p_reg);
166 nrf_uart_hwfc_pins_disconnect(p_instance->p_reg);
167 }
168
169 if (!p_cb->skip_gpio_cfg)
170 {
171 if (txd != NRF_UART_PSEL_DISCONNECTED)
172 {
173 nrf_gpio_cfg_default(txd);
174 }
175 if (rxd != NRF_UART_PSEL_DISCONNECTED)
176 {
177 nrf_gpio_cfg_default(rxd);
178 }
179 if (cts != NRF_UART_PSEL_DISCONNECTED)
180 {
181 nrf_gpio_cfg_default(cts);
182 }
183 if (rts != NRF_UART_PSEL_DISCONNECTED)
184 {
185 nrf_gpio_cfg_default(rts);
186 }
187 }
188 }
189
nrfx_uart_init(nrfx_uart_t const * p_instance,nrfx_uart_config_t const * p_config,nrfx_uart_event_handler_t event_handler)190 nrfx_err_t nrfx_uart_init(nrfx_uart_t const * p_instance,
191 nrfx_uart_config_t const * p_config,
192 nrfx_uart_event_handler_t event_handler)
193 {
194 NRFX_ASSERT(p_config);
195
196 uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
197 nrfx_err_t err_code = NRFX_SUCCESS;
198
199 if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
200 {
201 #if NRFX_API_VER_AT_LEAST(3, 2, 0)
202 err_code = NRFX_ERROR_ALREADY;
203 #else
204 err_code = NRFX_ERROR_INVALID_STATE;
205 #endif
206 NRFX_LOG_WARNING("Function: %s, error code: %s.",
207 __func__,
208 NRFX_LOG_ERROR_STRING_GET(err_code));
209 return err_code;
210 }
211
212 #if NRFX_CHECK(NRFX_PRS_ENABLED)
213 static nrfx_irq_handler_t const irq_handlers[NRFX_UART_ENABLED_COUNT] = {
214 NRFX_INSTANCE_IRQ_HANDLERS_LIST(UART, uart)
215 };
216 if (nrfx_prs_acquire(p_instance->p_reg,
217 irq_handlers[p_instance->drv_inst_idx]) != NRFX_SUCCESS)
218 {
219 err_code = NRFX_ERROR_BUSY;
220 NRFX_LOG_WARNING("Function: %s, error code: %s.",
221 __func__,
222 NRFX_LOG_ERROR_STRING_GET(err_code));
223 return err_code;
224 }
225 #endif // NRFX_CHECK(NRFX_PRS_ENABLED)
226 p_cb->handler = event_handler;
227
228 if (p_config)
229 {
230 p_cb->p_context = p_config->p_context;
231 p_cb->skip_gpio_cfg = p_config->skip_gpio_cfg;
232 p_cb->skip_psel_cfg = p_config->skip_psel_cfg;
233 uart_configure(p_instance, p_config);
234 }
235
236 nrf_uart_enable(p_instance->p_reg);
237 p_cb->rx_buffer_length = 0;
238 p_cb->rx_secondary_buffer_length = 0;
239 p_cb->rx_enabled = false;
240 p_cb->tx_buffer_length = 0;
241 p_cb->state = NRFX_DRV_STATE_INITIALIZED;
242 NRFX_LOG_INFO("Function: %s, error code: %s.",
243 __func__,
244 NRFX_LOG_ERROR_STRING_GET(err_code));
245 return err_code;
246 }
247
nrfx_uart_reconfigure(nrfx_uart_t const * p_instance,nrfx_uart_config_t const * p_config)248 nrfx_err_t nrfx_uart_reconfigure(nrfx_uart_t const * p_instance,
249 nrfx_uart_config_t const * p_config)
250 {
251 NRFX_ASSERT(p_config);
252
253 uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
254
255 if (p_cb->state == NRFX_DRV_STATE_UNINITIALIZED)
256 {
257 return NRFX_ERROR_INVALID_STATE;
258 }
259 if (nrfx_uart_tx_in_progress(p_instance))
260 {
261 return NRFX_ERROR_BUSY;
262 }
263 nrf_uart_disable(p_instance->p_reg);
264 if (p_cb->handler)
265 {
266 p_cb->p_context = p_config->p_context;
267 }
268 uart_configure(p_instance, p_config);
269 nrf_uart_enable(p_instance->p_reg);
270 return NRFX_SUCCESS;
271 }
272
nrfx_uart_uninit(nrfx_uart_t const * p_instance)273 void nrfx_uart_uninit(nrfx_uart_t const * p_instance)
274 {
275 uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
276
277 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
278
279 nrf_uart_disable(p_instance->p_reg);
280
281 if (p_cb->handler)
282 {
283 interrupts_disable(p_instance);
284 }
285
286 pins_to_default(p_instance);
287
288 #if NRFX_CHECK(NRFX_PRS_ENABLED)
289 nrfx_prs_release(p_instance->p_reg);
290 #endif
291
292 p_cb->state = NRFX_DRV_STATE_UNINITIALIZED;
293 p_cb->handler = NULL;
294 NRFX_LOG_INFO("Instance uninitialized: %d.", p_instance->drv_inst_idx);
295 }
296
nrfx_uart_init_check(nrfx_uart_t const * p_instance)297 bool nrfx_uart_init_check(nrfx_uart_t const * p_instance)
298 {
299 uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
300
301 return (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
302 }
303
tx_byte(NRF_UART_Type * p_uart,uart_control_block_t * p_cb)304 static void tx_byte(NRF_UART_Type * p_uart, uart_control_block_t * p_cb)
305 {
306 nrf_uart_event_clear(p_uart, NRF_UART_EVENT_TXDRDY);
307 uint8_t txd = p_cb->p_tx_buffer[p_cb->tx_counter];
308 p_cb->tx_counter++;
309 nrf_uart_txd_set(p_uart, txd);
310 }
311
tx_blocking(NRF_UART_Type * p_uart,uart_control_block_t * p_cb)312 static bool tx_blocking(NRF_UART_Type * p_uart, uart_control_block_t * p_cb)
313 {
314 // Use a local variable to avoid undefined order of accessing two volatile variables
315 // in one statement.
316 size_t const tx_buffer_length = p_cb->tx_buffer_length;
317 while (p_cb->tx_counter < tx_buffer_length)
318 {
319 // Wait until the transmitter is ready to accept a new byte.
320 // Exit immediately if the transfer has been aborted.
321 while (!nrf_uart_event_check(p_uart, NRF_UART_EVENT_TXDRDY))
322 {
323 if (p_cb->tx_abort)
324 {
325 return false;
326 }
327 }
328
329 tx_byte(p_uart, p_cb);
330 }
331
332 return true;
333 }
334
nrfx_uart_tx(nrfx_uart_t const * p_instance,uint8_t const * p_data,size_t length)335 nrfx_err_t nrfx_uart_tx(nrfx_uart_t const * p_instance,
336 uint8_t const * p_data,
337 size_t length)
338 {
339 uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
340
341 NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
342 NRFX_ASSERT(p_data);
343 NRFX_ASSERT(length > 0);
344
345 nrfx_err_t err_code;
346
347 if (nrfx_uart_tx_in_progress(p_instance))
348 {
349 err_code = NRFX_ERROR_BUSY;
350 NRFX_LOG_WARNING("Function: %s, error code: %s.",
351 __func__,
352 NRFX_LOG_ERROR_STRING_GET(err_code));
353 return err_code;
354 }
355 p_cb->tx_buffer_length = length;
356 p_cb->p_tx_buffer = p_data;
357 p_cb->tx_counter = 0;
358 p_cb->tx_abort = false;
359
360 NRFX_LOG_INFO("Transfer tx_len: %d.", p_cb->tx_buffer_length);
361 NRFX_LOG_DEBUG("Tx data:");
362 NRFX_LOG_HEXDUMP_DEBUG(p_cb->p_tx_buffer,
363 p_cb->tx_buffer_length * sizeof(p_cb->p_tx_buffer[0]));
364
365 err_code = NRFX_SUCCESS;
366
367 nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_TXDRDY);
368 nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STARTTX);
369
370 tx_byte(p_instance->p_reg, p_cb);
371
372 if (p_cb->handler == NULL)
373 {
374 if (!tx_blocking(p_instance->p_reg, p_cb))
375 {
376 // The transfer has been aborted.
377 err_code = NRFX_ERROR_FORBIDDEN;
378 }
379 else
380 {
381 // Wait until the last byte is completely transmitted.
382 while (!nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_TXDRDY))
383 {}
384 nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPTX);
385 }
386 p_cb->tx_buffer_length = 0;
387 }
388
389 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
390 return err_code;
391 }
392
nrfx_uart_tx_in_progress(nrfx_uart_t const * p_instance)393 bool nrfx_uart_tx_in_progress(nrfx_uart_t const * p_instance)
394 {
395 NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state != NRFX_DRV_STATE_UNINITIALIZED);
396
397 return (m_cb[p_instance->drv_inst_idx].tx_buffer_length != 0);
398 }
399
rx_enable(nrfx_uart_t const * p_instance)400 static void rx_enable(nrfx_uart_t const * p_instance)
401 {
402 nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_ERROR);
403 nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STARTRX);
404 }
405
rx_byte(NRF_UART_Type * p_uart,uart_control_block_t * p_cb)406 static void rx_byte(NRF_UART_Type * p_uart, uart_control_block_t * p_cb)
407 {
408 if (!p_cb->rx_buffer_length)
409 {
410 nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXDRDY);
411 // Byte received when buffer is not set - data lost.
412 (void) nrf_uart_rxd_get(p_uart);
413 return;
414 }
415 nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXDRDY);
416 p_cb->p_rx_buffer[p_cb->rx_counter] = nrf_uart_rxd_get(p_uart);
417 p_cb->rx_counter++;
418 }
419
nrfx_uart_rx(nrfx_uart_t const * p_instance,uint8_t * p_data,size_t length)420 nrfx_err_t nrfx_uart_rx(nrfx_uart_t const * p_instance,
421 uint8_t * p_data,
422 size_t length)
423 {
424 uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
425
426 NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED);
427 NRFX_ASSERT(p_data);
428 NRFX_ASSERT(length > 0);
429
430 nrfx_err_t err_code;
431
432 bool second_buffer = false;
433
434 if (p_cb->handler)
435 {
436 nrf_uart_int_disable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY |
437 NRF_UART_INT_MASK_ERROR);
438 }
439 if (p_cb->rx_buffer_length != 0)
440 {
441 if (p_cb->rx_secondary_buffer_length != 0)
442 {
443 if (p_cb->handler)
444 {
445 nrf_uart_int_enable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY |
446 NRF_UART_INT_MASK_ERROR);
447 }
448 err_code = NRFX_ERROR_BUSY;
449 NRFX_LOG_WARNING("Function: %s, error code: %s.",
450 __func__,
451 NRFX_LOG_ERROR_STRING_GET(err_code));
452 return err_code;
453 }
454 second_buffer = true;
455 }
456
457 if (!second_buffer)
458 {
459 p_cb->rx_buffer_length = length;
460 p_cb->p_rx_buffer = p_data;
461 p_cb->rx_counter = 0;
462 p_cb->rx_secondary_buffer_length = 0;
463 }
464 else
465 {
466 p_cb->p_rx_secondary_buffer = p_data;
467 p_cb->rx_secondary_buffer_length = length;
468 }
469
470 NRFX_LOG_INFO("Transfer rx_len: %d.", length);
471
472 if ((!p_cb->rx_enabled) && (!second_buffer))
473 {
474 rx_enable(p_instance);
475 }
476
477 if (p_cb->handler == NULL)
478 {
479 nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_RXTO);
480
481 bool rxrdy;
482 bool rxto;
483 bool error;
484 do
485 {
486 do
487 {
488 error = nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_ERROR);
489 rxrdy = nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_RXDRDY);
490 rxto = nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_RXTO);
491 } while ((!rxrdy) && (!rxto) && (!error));
492
493 if (error || rxto)
494 {
495 break;
496 }
497 rx_byte(p_instance->p_reg, p_cb);
498 } while (p_cb->rx_buffer_length > p_cb->rx_counter);
499
500 p_cb->rx_buffer_length = 0;
501 if (error)
502 {
503 err_code = NRFX_ERROR_INTERNAL;
504 NRFX_LOG_WARNING("Function: %s, error code: %s.",
505 __func__,
506 NRFX_LOG_ERROR_STRING_GET(err_code));
507 return err_code;
508 }
509
510 if (rxto)
511 {
512 err_code = NRFX_ERROR_FORBIDDEN;
513 NRFX_LOG_WARNING("Function: %s, error code: %s.",
514 __func__,
515 NRFX_LOG_ERROR_STRING_GET(err_code));
516 return err_code;
517 }
518
519 if (p_cb->rx_enabled)
520 {
521 nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STARTRX);
522 }
523 else
524 {
525 // Skip stopping RX if driver is forced to be enabled.
526 nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPRX);
527 }
528 }
529 else
530 {
531 nrf_uart_int_enable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY |
532 NRF_UART_INT_MASK_ERROR);
533 }
534 err_code = NRFX_SUCCESS;
535 NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
536 return err_code;
537 }
538
nrfx_uart_rx_ready(nrfx_uart_t const * p_instance)539 bool nrfx_uart_rx_ready(nrfx_uart_t const * p_instance)
540 {
541 NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state != NRFX_DRV_STATE_UNINITIALIZED);
542
543 return nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_RXDRDY);
544 }
545
nrfx_uart_rx_enable(nrfx_uart_t const * p_instance)546 void nrfx_uart_rx_enable(nrfx_uart_t const * p_instance)
547 {
548 NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_INITIALIZED);
549
550 if (!m_cb[p_instance->drv_inst_idx].rx_enabled)
551 {
552 rx_enable(p_instance);
553 m_cb[p_instance->drv_inst_idx].rx_enabled = true;
554 }
555 }
556
nrfx_uart_rx_disable(nrfx_uart_t const * p_instance)557 void nrfx_uart_rx_disable(nrfx_uart_t const * p_instance)
558 {
559 NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_INITIALIZED);
560
561 nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPRX);
562 m_cb[p_instance->drv_inst_idx].rx_enabled = false;
563 }
564
nrfx_uart_errorsrc_get(nrfx_uart_t const * p_instance)565 uint32_t nrfx_uart_errorsrc_get(nrfx_uart_t const * p_instance)
566 {
567 NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state != NRFX_DRV_STATE_UNINITIALIZED);
568 /* Function must be used in blocking mode only. */
569 NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].handler == NULL);
570
571 nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_ERROR);
572 return nrf_uart_errorsrc_get_and_clear(p_instance->p_reg);
573 }
574
rx_done_event(uart_control_block_t * p_cb,size_t bytes,uint8_t * p_data)575 static void rx_done_event(uart_control_block_t * p_cb,
576 size_t bytes,
577 uint8_t * p_data)
578 {
579 nrfx_uart_event_t event;
580
581 event.type = NRFX_UART_EVT_RX_DONE;
582 event.data.rxtx.bytes = bytes;
583 event.data.rxtx.p_data = p_data;
584
585 p_cb->handler(&event, p_cb->p_context);
586 }
587
tx_done_event(uart_control_block_t * p_cb,size_t bytes)588 static void tx_done_event(uart_control_block_t * p_cb,
589 size_t bytes)
590 {
591 nrfx_uart_event_t event;
592
593 event.type = NRFX_UART_EVT_TX_DONE;
594 event.data.rxtx.bytes = bytes;
595
596 #if defined(__GNUC__)
597 #pragma GCC diagnostic push
598 #pragma GCC diagnostic ignored "-Wcast-qual"
599 #endif
600 event.data.rxtx.p_data = (uint8_t *)p_cb->p_tx_buffer;
601 #if defined(__GNUC__)
602 #pragma GCC diagnostic pop
603 #endif
604
605 p_cb->tx_buffer_length = 0;
606
607 p_cb->handler(&event, p_cb->p_context);
608 }
609
nrfx_uart_tx_abort(nrfx_uart_t const * p_instance)610 void nrfx_uart_tx_abort(nrfx_uart_t const * p_instance)
611 {
612 uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx];
613
614 NRFX_ASSERT(p_cb->state != NRFX_DRV_STATE_UNINITIALIZED);
615
616 p_cb->tx_abort = true;
617 nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPTX);
618 if (p_cb->handler)
619 {
620 tx_done_event(p_cb, p_cb->tx_counter);
621 }
622
623 NRFX_LOG_INFO("TX transaction aborted.");
624 }
625
nrfx_uart_rx_abort(nrfx_uart_t const * p_instance)626 void nrfx_uart_rx_abort(nrfx_uart_t const * p_instance)
627 {
628 NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state != NRFX_DRV_STATE_UNINITIALIZED);
629
630 nrf_uart_int_disable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY |
631 NRF_UART_INT_MASK_ERROR);
632 nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPRX);
633
634 NRFX_LOG_INFO("RX transaction aborted.");
635 }
636
irq_handler(NRF_UART_Type * p_uart,uart_control_block_t * p_cb)637 static void irq_handler(NRF_UART_Type * p_uart, uart_control_block_t * p_cb)
638 {
639 if (nrf_uart_int_enable_check(p_uart, NRF_UART_INT_MASK_ERROR) &&
640 nrf_uart_event_check(p_uart, NRF_UART_EVENT_ERROR))
641 {
642 nrfx_uart_event_t event;
643 nrf_uart_event_clear(p_uart, NRF_UART_EVENT_ERROR);
644 NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_UART_EVENT_ERROR));
645 nrf_uart_int_disable(p_uart, NRF_UART_INT_MASK_RXDRDY |
646 NRF_UART_INT_MASK_ERROR);
647 if (!p_cb->rx_enabled)
648 {
649 nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STOPRX);
650 }
651 event.type = NRFX_UART_EVT_ERROR;
652 event.data.error.error_mask = nrf_uart_errorsrc_get_and_clear(p_uart);
653 event.data.error.rxtx.bytes = p_cb->rx_buffer_length;
654 event.data.error.rxtx.p_data = p_cb->p_rx_buffer;
655
656 // Abort transfer.
657 p_cb->rx_buffer_length = 0;
658 p_cb->rx_secondary_buffer_length = 0;
659
660 p_cb->handler(&event,p_cb->p_context);
661 }
662 else if (nrf_uart_int_enable_check(p_uart, NRF_UART_INT_MASK_RXDRDY) &&
663 nrf_uart_event_check(p_uart, NRF_UART_EVENT_RXDRDY))
664 {
665 rx_byte(p_uart, p_cb);
666 if (p_cb->rx_buffer_length == p_cb->rx_counter)
667 {
668 if (p_cb->rx_secondary_buffer_length)
669 {
670 uint8_t * p_data = p_cb->p_rx_buffer;
671 size_t rx_counter = p_cb->rx_counter;
672
673 // Switch to secondary buffer.
674 p_cb->rx_buffer_length = p_cb->rx_secondary_buffer_length;
675 p_cb->p_rx_buffer = p_cb->p_rx_secondary_buffer;
676 p_cb->rx_secondary_buffer_length = 0;
677 p_cb->rx_counter = 0;
678 rx_done_event(p_cb, rx_counter, p_data);
679 }
680 else
681 {
682 if (!p_cb->rx_enabled)
683 {
684 nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STOPRX);
685 }
686 nrf_uart_int_disable(p_uart, NRF_UART_INT_MASK_RXDRDY |
687 NRF_UART_INT_MASK_ERROR);
688 p_cb->rx_buffer_length = 0;
689 rx_done_event(p_cb, p_cb->rx_counter, p_cb->p_rx_buffer);
690 }
691 }
692 }
693
694 if (nrf_uart_event_check(p_uart, NRF_UART_EVENT_TXDRDY))
695 {
696 // Use a local variable to avoid undefined order of accessing two volatile variables
697 // in one statement.
698 size_t const tx_buffer_length = p_cb->tx_buffer_length;
699 if (p_cb->tx_counter < tx_buffer_length && !p_cb->tx_abort)
700 {
701 tx_byte(p_uart, p_cb);
702 }
703 else
704 {
705 nrf_uart_event_clear(p_uart, NRF_UART_EVENT_TXDRDY);
706 if (p_cb->tx_buffer_length)
707 {
708 tx_done_event(p_cb, p_cb->tx_buffer_length);
709 }
710 }
711 }
712
713 if (nrf_uart_event_check(p_uart, NRF_UART_EVENT_RXTO))
714 {
715 nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXTO);
716
717 // RXTO event may be triggered as a result of abort call. In th
718 if (p_cb->rx_enabled)
719 {
720 nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STARTRX);
721 }
722 if (p_cb->rx_buffer_length)
723 {
724 p_cb->rx_buffer_length = 0;
725 rx_done_event(p_cb, p_cb->rx_counter, p_cb->p_rx_buffer);
726 }
727 }
728 }
729
730 NRFX_INSTANCE_IRQ_HANDLERS(UART, uart)
731
732 #endif // NRFX_CHECK(NRFX_UART_ENABLED)
733