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