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 #ifndef NRFX_UART_H__
35 #define NRFX_UART_H__
36 
37 #include <nrfx.h>
38 #include <hal/nrf_uart.h>
39 
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
43 
44 /**
45  * @defgroup nrfx_uart UART driver
46  * @{
47  * @ingroup nrf_uart
48  * @brief   UART peripheral driver.
49  */
50 
51 /** @brief Data structure of the UART driver instance. */
52 typedef struct
53 {
54     NRF_UART_Type * p_reg;        ///< Pointer to a structure with UART registers.
55     uint8_t         drv_inst_idx; ///< Index of the driver instance. For internal use only.
56 } nrfx_uart_t;
57 
58 #ifndef __NRFX_DOXYGEN__
59 enum {
60     /* List all enabled driver instances (in the format NRFX_\<instance_name\>_INST_IDX). */
61     NRFX_INSTANCE_ENUM_LIST(UART)
62     NRFX_UART_ENABLED_COUNT
63 };
64 #endif
65 
66 /** @brief Macro for creating a UART driver instance. */
67 #define NRFX_UART_INSTANCE(id)                               \
68 {                                                            \
69     .p_reg        = NRFX_CONCAT(NRF_, UART, id),             \
70     .drv_inst_idx = NRFX_CONCAT(NRFX_UART, id, _INST_IDX),   \
71 }
72 
73 /** @brief Types of UART driver events. */
74 typedef enum
75 {
76     NRFX_UART_EVT_TX_DONE, ///< Requested TX transfer completed.
77     NRFX_UART_EVT_RX_DONE, ///< Requested RX transfer completed.
78     NRFX_UART_EVT_ERROR,   ///< Error reported by UART peripheral.
79 } nrfx_uart_evt_type_t;
80 
81 /** @brief Structure for the UART configuration. */
82 typedef struct
83 {
84     uint32_t            pseltxd;            ///< TXD pin number.
85     uint32_t            pselrxd;            ///< RXD pin number.
86     uint32_t            pselcts;            ///< CTS pin number.
87     uint32_t            pselrts;            ///< RTS pin number.
88     void *              p_context;          ///< Context passed to interrupt handler.
89     nrf_uart_baudrate_t baudrate;           ///< Baud rate.
90     uint8_t             interrupt_priority; ///< Interrupt priority.
91     nrf_uart_config_t   hal_cfg;            ///< Parity, flow control and stop bits settings.
92     bool                skip_gpio_cfg;      ///< Skip GPIO configuration of pins.
93                                             /**< When set to true, the driver does not modify
94                                              *   any GPIO parameters of the used pins. Those
95                                              *   parameters are supposed to be configured
96                                              *   externally before the driver is initialized. */
97     bool                skip_psel_cfg;      ///< Skip pin selection configuration.
98                                             /**< When set to true, the driver does not modify
99                                              *   pin select registers in the peripheral.
100                                              *   Those registers are supposed to be set up
101                                              *   externally before the driver is initialized.
102                                              *   @note When both GPIO configuration and pin
103                                              *   selection are to be skipped, the structure
104                                              *   fields that specify pins can be omitted,
105                                              *   as they are ignored anyway. */
106 } nrfx_uart_config_t;
107 
108 #if NRF_UART_HAS_STOP_BITS || defined(__NRFX_DOXYGEN__)
109     /** @brief UART additional stop bits configuration. */
110     #define NRFX_UART_DEFAULT_EXTENDED_STOP_CONFIG   \
111         .stop = NRF_UART_STOP_ONE,
112 #else
113     #define NRFX_UART_DEFAULT_EXTENDED_STOP_CONFIG
114 #endif
115 
116 #if NRF_UART_HAS_PARITY_BIT || defined(__NRFX_DOXYGEN__)
117     /**  @brief UART additional parity type configuration. */
118     #define NRFX_UART_DEFAULT_EXTENDED_PARITYTYPE_CONFIG   \
119         .paritytype = NRF_UART_PARITYTYPE_EVEN,
120 #else
121     #define NRFX_UART_DEFAULT_EXTENDED_PARITYTYPE_CONFIG
122 #endif
123 
124 /**
125  * @brief UART driver default configuration.
126  *
127  * This configuration sets up UART with the following options:
128  * - hardware flow control disabled
129  * - no parity bit
130  * - one stop bit
131  * - baudrate: 115200
132  *
133  * @param[in] _pin_tx TX pin.
134  * @param[in] _pin_rx RX pin.
135  */
136 #define NRFX_UART_DEFAULT_CONFIG(_pin_tx, _pin_rx)                                \
137 {                                                                                 \
138     .pseltxd            = _pin_tx,                                                \
139     .pselrxd            = _pin_rx,                                                \
140     .pselcts            = NRF_UART_PSEL_DISCONNECTED,                             \
141     .pselrts            = NRF_UART_PSEL_DISCONNECTED,                             \
142     .p_context          = NULL,                                                   \
143     .baudrate           = NRF_UART_BAUDRATE_115200,                               \
144     .interrupt_priority = NRFX_UART_DEFAULT_CONFIG_IRQ_PRIORITY,                  \
145     .hal_cfg            = {                                                       \
146         .hwfc           = NRF_UART_HWFC_DISABLED,                                 \
147         .parity         = NRF_UART_PARITY_EXCLUDED,                               \
148         NRFX_UART_DEFAULT_EXTENDED_STOP_CONFIG                                    \
149         NRFX_UART_DEFAULT_EXTENDED_PARITYTYPE_CONFIG                              \
150     }                                                                             \
151 }
152 
153 /** @brief Structure for the UART transfer completion event. */
154 typedef struct
155 {
156     uint8_t * p_data; ///< Pointer to memory used for transfer.
157     uint32_t  bytes;  ///< Number of bytes transfered.
158 } nrfx_uart_xfer_evt_t;
159 
160 /** @brief Structure for the UART error event. */
161 typedef struct
162 {
163     nrfx_uart_xfer_evt_t rxtx;       ///< Transfer details, including number of bytes transferred.
164     uint32_t             error_mask; ///< Mask of error flags that generated the event.
165 } nrfx_uart_error_evt_t;
166 
167 /** @brief Structure for the UART event. */
168 typedef struct
169 {
170     nrfx_uart_evt_type_t type; ///< Event type.
171     union
172     {
173         nrfx_uart_xfer_evt_t  rxtx;  ///< Data provided for transfer completion events.
174         nrfx_uart_error_evt_t error; ///< Data provided for error event.
175     } data;                          ///< Union to store event data.
176 } nrfx_uart_event_t;
177 
178 /**
179  * @brief UART interrupt event handler.
180  *
181  * @param[in] p_event   Pointer to event structure. Event is allocated on the stack so it is available
182  *                      only within the context of the event handler.
183  * @param[in] p_context Context passed to the interrupt handler, set on initialization.
184  */
185 typedef void (*nrfx_uart_event_handler_t)(nrfx_uart_event_t const * p_event,
186                                           void *                    p_context);
187 
188 /**
189  * @brief Function for initializing the UART driver.
190  *
191  * This function configures and enables UART. After this function GPIO pins are controlled by UART.
192  *
193  * @param[in] p_instance    Pointer to the driver instance structure.
194  * @param[in] p_config      Pointer to the structure with the initial configuration.
195  * @param[in] event_handler Event handler provided by the user. If not provided, the driver works in
196  *                          blocking mode.
197  *
198  * @retval NRFX_SUCCESS             Initialization is successful.
199  * @retval NRFX_ERROR_ALREADY       The driver is already initialized.
200  * @retval NRFX_ERROR_INVALID_STATE The driver is already initialized.
201  *                                  Deprecated - use @ref NRFX_ERROR_ALREADY instead.
202  * @retval NRFX_ERROR_BUSY          Some other peripheral with the same
203  *                                  instance ID is already in use. This is
204  *                                  possible only if @ref nrfx_prs module
205  *                                  is enabled.
206  */
207 nrfx_err_t nrfx_uart_init(nrfx_uart_t const *        p_instance,
208                           nrfx_uart_config_t const * p_config,
209                           nrfx_uart_event_handler_t  event_handler);
210 
211 /**
212  * @brief Function for reconfiguring the UART driver.
213  *
214  * @param[in] p_instance Pointer to the driver instance structure.
215  * @param[in] p_config   Pointer to the structure with the configuration.
216  *
217  * @retval NRFX_SUCCESS             Reconfiguration was successful.
218  * @retval NRFX_ERROR_BUSY          The driver is during transfer.
219  * @retval NRFX_ERROR_INVALID_STATE The driver is uninitialized.
220  */
221 nrfx_err_t nrfx_uart_reconfigure(nrfx_uart_t const *        p_instance,
222                                  nrfx_uart_config_t const * p_config);
223 
224 /**
225  * @brief Function for uninitializing the UART driver.
226  *
227  * @param[in] p_instance Pointer to the driver instance structure.
228  */
229 void nrfx_uart_uninit(nrfx_uart_t const * p_instance);
230 
231 /**
232  * @brief Function for checking if the UART driver instance is initialized.
233  *
234  * @param[in] p_instance Pointer to the driver instance structure.
235  *
236  * @retval true  Instance is already initialized.
237  * @retval false Instance is not initialized.
238  */
239 bool nrfx_uart_init_check(nrfx_uart_t const * p_instance);
240 
241 /**
242  * @brief Function for getting the address of the specified UART task.
243  *
244  * @param[in] p_instance Pointer to the driver instance structure.
245  * @param[in] task       Task.
246  *
247  * @return Task address.
248  */
249 NRFX_STATIC_INLINE uint32_t nrfx_uart_task_address_get(nrfx_uart_t const * p_instance,
250                                                        nrf_uart_task_t     task);
251 
252 /**
253  * @brief Function for getting the address of the specified UART event.
254  *
255  * @param[in] p_instance Pointer to the driver instance structure.
256  * @param[in] event      Event.
257  *
258  * @return Event address.
259  */
260 NRFX_STATIC_INLINE uint32_t nrfx_uart_event_address_get(nrfx_uart_t const * p_instance,
261                                                         nrf_uart_event_t    event);
262 
263 /**
264  * @brief Function for sending data over UART.
265  *
266  * If an event handler was provided in nrfx_uart_init() call, this function
267  * returns immediately and the handler is called when the transfer is done.
268  * Otherwise, the transfer is performed in blocking mode, that is this function
269  * returns when the transfer is finished. Blocking mode is not using interrupt
270  * so there is no context switching inside the function.
271  *
272  * @param[in] p_instance Pointer to the driver instance structure.
273  * @param[in] p_data     Pointer to data.
274  * @param[in] length     Number of bytes to send.
275  *
276  * @retval NRFX_SUCCESS         Initialization was successful.
277  * @retval NRFX_ERROR_BUSY      Driver is already transferring.
278  * @retval NRFX_ERROR_FORBIDDEN The transfer was aborted from a different context
279  *                              (blocking mode only).
280  */
281 nrfx_err_t nrfx_uart_tx(nrfx_uart_t const * p_instance,
282                         uint8_t const *     p_data,
283                         size_t              length);
284 
285 /**
286  * @brief Function for checking if UART is currently transmitting.
287  *
288  * @param[in] p_instance Pointer to the driver instance structure.
289  *
290  * @retval true  The UART is transmitting.
291  * @retval false The UART is not transmitting.
292  */
293 bool nrfx_uart_tx_in_progress(nrfx_uart_t const * p_instance);
294 
295 /**
296  * @brief Function for aborting any ongoing transmission.
297  * @note @ref NRFX_UART_EVT_TX_DONE event will be generated in non-blocking mode.
298  *       It will contain number of bytes sent until the abort was called. The event
299  *       handler will be called from the function context.
300  *
301  * @param[in] p_instance Pointer to the driver instance structure.
302  */
303 void nrfx_uart_tx_abort(nrfx_uart_t const * p_instance);
304 
305 /**
306  * @brief Function for receiving data over UART.
307  *
308  * If an event handler is provided in the nrfx_uart_init() call, this function
309  * returns immediately and the handler is called when the transfer is done.
310  * Otherwise, the transfer is performed in blocking mode, that is this function
311  * returns when the transfer is finished. Blocking mode is not using interrupt so
312  * there is no context switching inside the function.
313  * The receive buffer pointer is double-buffered in non-blocking mode. The secondary
314  * buffer can be set immediately after starting the transfer and will be filled
315  * when the primary buffer is full. The double-buffering feature allows
316  * receiving data continuously.
317  *
318  * If this function is used without a previous call to @ref nrfx_uart_rx_enable, the reception
319  * will be stopped on error or when the supplied buffer fills up. In both cases,
320  * RX FIFO gets disabled. This means that, in case of error, the bytes that follow are lost.
321  * If this nrfx_uart_rx() function is used with the previous call to @ref nrfx_uart_rx_enable,
322  * the reception is stopped in case of error, but FIFO is still ongoing. The receiver is still
323  * working, so after handling the error, an immediate repeated call to this nrfx_uart_rx()
324  * function with fresh data buffer will re-establish reception. To disable the receiver,
325  * you must call @ref nrfx_uart_rx_disable explicitly.
326  *
327  * @param[in] p_instance Pointer to the driver instance structure.
328  * @param[in] p_data     Pointer to data.
329  * @param[in] length     Number of bytes to receive.
330  *
331  * @retval    NRFX_SUCCESS         Reception is complete (in case of blocking mode) or it is
332  *                                 successfully started (in case of non-blocking mode).
333  * @retval    NRFX_ERROR_BUSY      The driver is already receiving
334  *                                 (and the secondary buffer has already been set
335  *                                 in non-blocking mode).
336  * @retval    NRFX_ERROR_FORBIDDEN The transfer was aborted from a different context
337  *                                 (blocking mode only, also see @ref nrfx_uart_rx_disable).
338  * @retval    NRFX_ERROR_INTERNAL  The UART peripheral reported an error.
339  */
340 nrfx_err_t nrfx_uart_rx(nrfx_uart_t const * p_instance,
341                         uint8_t *           p_data,
342                         size_t              length);
343 
344 /**
345  * @brief Function for testing the receiver state in blocking mode.
346  *
347  * @param[in] p_instance Pointer to the driver instance structure.
348  *
349  * @retval true  The receiver has at least one byte of data to get.
350  * @retval false The receiver is empty.
351  */
352 bool nrfx_uart_rx_ready(nrfx_uart_t const * p_instance);
353 
354 /**
355  * @brief Function for enabling the receiver.
356  *
357  * UART has a 6-byte-long RX FIFO and it is used to store incoming data. If a user does not call the
358  * UART receive function before the FIFO is filled, an overrun error will appear. The receiver must be
359  * explicitly closed by the user @sa nrfx_uart_rx_disable.
360  *
361  * @param[in] p_instance Pointer to the driver instance structure.
362  */
363 void nrfx_uart_rx_enable(nrfx_uart_t const * p_instance);
364 
365 /**
366  * @brief Function for disabling the receiver.
367  *
368  * This function must be called to close the receiver after it has been explicitly enabled by
369  * @sa nrfx_uart_rx_enable.
370  *
371  * @param[in] p_instance Pointer to the driver instance structure.
372  */
373 void nrfx_uart_rx_disable(nrfx_uart_t const * p_instance);
374 
375 /**
376  * @brief Function for aborting any ongoing reception.
377  * @note @ref NRFX_UART_EVT_TX_DONE event will be generated in non-blocking mode.
378  *       It will contain number of bytes received until the abort was called. The event
379  *       handler will be called from the UART interrupt context.
380  *
381  * @param[in] p_instance Pointer to the driver instance structure.
382  */
383 void nrfx_uart_rx_abort(nrfx_uart_t const * p_instance);
384 
385 /**
386  * @brief Function for reading error source mask. Mask contains values from @ref nrf_uart_error_mask_t.
387  * @note Function must be used in blocking mode only. In case of non-blocking mode, an error event is
388  *       generated. Function clears error sources after reading.
389  *
390  * @param[in] p_instance Pointer to the driver instance structure.
391  *
392  * @return Mask of reported errors.
393  */
394 uint32_t nrfx_uart_errorsrc_get(nrfx_uart_t const * p_instance);
395 
396 
397 #ifndef NRFX_DECLARE_ONLY
nrfx_uart_task_address_get(nrfx_uart_t const * p_instance,nrf_uart_task_t task)398 NRFX_STATIC_INLINE uint32_t nrfx_uart_task_address_get(nrfx_uart_t const * p_instance,
399                                                        nrf_uart_task_t     task)
400 {
401     return nrf_uart_task_address_get(p_instance->p_reg, task);
402 }
403 
nrfx_uart_event_address_get(nrfx_uart_t const * p_instance,nrf_uart_event_t event)404 NRFX_STATIC_INLINE uint32_t nrfx_uart_event_address_get(nrfx_uart_t const * p_instance,
405                                                         nrf_uart_event_t    event)
406 {
407     return nrf_uart_event_address_get(p_instance->p_reg, event);
408 }
409 #endif // NRFX_DECLARE_ONLY
410 
411 /**
412  * @brief Macro returning UART interrupt handler.
413  *
414  * param[in] idx UART index.
415  *
416  * @return Interrupt handler.
417  */
418 #define NRFX_UART_INST_HANDLER_GET(idx) NRFX_CONCAT_3(nrfx_uart_, idx, _irq_handler)
419 
420 /** @} */
421 
422 /*
423  * Declare interrupt handlers for all enabled driver instances in the following format:
424  * nrfx_\<periph_name\>_\<idx\>_irq_handler (for example, nrfx_uart_0_irq_handler).
425  *
426  * A specific interrupt handler for the driver instance can be retrieved by using
427  * the NRFX_UART_INST_HANDLER_GET macro.
428  *
429  * Here is a sample of using the NRFX_UART_INST_HANDLER_GET macro to map an interrupt handler
430  * in a Zephyr application:
431  *
432  * IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_UART_INST_GET(\<instance_index\>)), \<priority\>,
433  *             NRFX_UART_INST_HANDLER_GET(\<instance_index\>), 0, 0);
434  */
435 NRFX_INSTANCE_IRQ_HANDLERS_DECLARE(UART, uart)
436 
437 #ifdef __cplusplus
438 }
439 #endif
440 
441 #endif // NRFX_UART_H__
442