/* * Copyright (c) 2018 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ /** * @brief Driver for Nordic Semiconductor nRF UARTE */ #include #include #include #include #include #include #include LOG_MODULE_REGISTER(uart_nrfx_uarte, LOG_LEVEL_ERR); /* Generalize PPI or DPPI channel management */ #if defined(CONFIG_HAS_HW_NRF_PPI) #include #define gppi_channel_t nrf_ppi_channel_t #define gppi_channel_alloc nrfx_ppi_channel_alloc #define gppi_channel_enable nrfx_ppi_channel_enable #elif defined(CONFIG_HAS_HW_NRF_DPPIC) #include #define gppi_channel_t u8_t #define gppi_channel_alloc nrfx_dppi_channel_alloc #define gppi_channel_enable nrfx_dppi_channel_enable #else #error "No PPI or DPPI" #endif #if (defined(CONFIG_UART_0_NRF_UARTE) && \ defined(CONFIG_UART_0_INTERRUPT_DRIVEN)) || \ (defined(CONFIG_UART_1_NRF_UARTE) && \ defined(CONFIG_UART_1_INTERRUPT_DRIVEN)) || \ (defined(CONFIG_UART_2_NRF_UARTE) && \ defined(CONFIG_UART_2_INTERRUPT_DRIVEN)) || \ (defined(CONFIG_UART_3_NRF_UARTE) && \ defined(CONFIG_UART_3_INTERRUPT_DRIVEN)) #define UARTE_INTERRUPT_DRIVEN 1 #endif /* * RX timeout is divided into time slabs, this define tells how many divisions * should be made. More divisions - higher timeout accuracy and processor usage. */ #define RX_TIMEOUT_DIV 5 #ifdef CONFIG_UART_ASYNC_API struct uarte_async_cb { uart_callback_t user_callback; void *user_data; /* tx_buf has to be volatile it is used as busy flag in uart_tx and * uart_poll_out. If both tx_buf and tx_size is set then there is * currently ongoing asynchronous transmission. If only tx_size * is bigger than 0 and tx_buf is NULL, then there is ongoing * transmission by uart_poll_out */ const u8_t *volatile tx_buf; size_t tx_size; struct k_timer tx_timeout_timer; u8_t *rx_buf; size_t rx_offset; u8_t *rx_next_buf; u32_t rx_total_byte_cnt; /* Total number of bytes received */ u32_t rx_total_user_byte_cnt; /* Total number of bytes passed to user */ s32_t rx_timeout; /* Timeout set by user */ s32_t rx_timeout_slab; /* rx_timeout divided by RX_TIMEOUT_DIV */ s32_t rx_timeout_left; /* Current time left until user callback */ struct k_timer rx_timeout_timer; union { gppi_channel_t ppi; u32_t cnt; } rx_cnt; bool rx_enabled; bool hw_rx_counting; /* Flag to ensure that RX timeout won't be executed during ENDRX ISR */ volatile bool is_in_irq; }; #endif #ifdef UARTE_INTERRUPT_DRIVEN struct uarte_nrfx_int_driven { uart_irq_callback_user_data_t cb; /**< Callback function pointer */ void *cb_data; /**< Callback function arg */ u8_t *tx_buffer; u16_t tx_buff_size; volatile bool disable_tx_irq; }; #endif /* Device data structure */ struct uarte_nrfx_data { struct uart_config uart_config; #ifdef UARTE_INTERRUPT_DRIVEN struct uarte_nrfx_int_driven *int_driven; #endif #ifdef CONFIG_UART_ASYNC_API struct uarte_async_cb *async; #endif atomic_val_t poll_out_lock; #ifdef CONFIG_DEVICE_POWER_MANAGEMENT u32_t pm_state; #endif u8_t rx_data; }; /** * @brief Structure for UARTE configuration. */ struct uarte_nrfx_config { NRF_UARTE_Type *uarte_regs; /* Instance address */ bool rts_cts_pins_set; bool gpio_mgmt; #ifdef CONFIG_UART_ASYNC_API nrfx_timer_t timer; #endif }; struct uarte_init_config { u32_t pseltxd; /* TXD pin number */ u32_t pselrxd; /* RXD pin number */ u32_t pselcts; /* CTS pin number */ u32_t pselrts; /* RTS pin number */ }; static inline struct uarte_nrfx_data *get_dev_data(struct device *dev) { return dev->driver_data; } static inline const struct uarte_nrfx_config *get_dev_config(struct device *dev) { return dev->config->config_info; } static inline NRF_UARTE_Type *get_uarte_instance(struct device *dev) { const struct uarte_nrfx_config *config = get_dev_config(dev); return config->uarte_regs; } #ifdef UARTE_INTERRUPT_DRIVEN /** * @brief Interrupt service routine. * * This simply calls the callback function, if one exists. * * @param arg Argument to ISR. * * @return N/A */ static void uarte_nrfx_isr_int(void *arg) { struct device *dev = arg; struct uarte_nrfx_data *data = get_dev_data(dev); NRF_UARTE_Type *uarte = get_uarte_instance(dev); if (data->int_driven->disable_tx_irq && nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX)) { nrf_uarte_int_disable(uarte, NRF_UARTE_INT_ENDTX_MASK); /* If there is nothing to send, driver will save an energy * when TX is stopped. */ nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPTX); data->int_driven->disable_tx_irq = false; return; } if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ERROR)) { nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ERROR); } if (data->int_driven->cb) { data->int_driven->cb(data->int_driven->cb_data); } } #endif /* UARTE_INTERRUPT_DRIVEN */ /** * @brief Set the baud rate * * This routine set the given baud rate for the UARTE. * * @param dev UARTE device struct * @param baudrate Baud rate * * @return 0 on success or error code */ static int baudrate_set(struct device *dev, u32_t baudrate) { nrf_uarte_baudrate_t nrf_baudrate; /* calculated baudrate divisor */ NRF_UARTE_Type *uarte = get_uarte_instance(dev); switch (baudrate) { case 300: /* value not supported by Nordic HAL */ nrf_baudrate = 0x00014000; break; case 600: /* value not supported by Nordic HAL */ nrf_baudrate = 0x00027000; break; case 1200: nrf_baudrate = NRF_UARTE_BAUDRATE_1200; break; case 2400: nrf_baudrate = NRF_UARTE_BAUDRATE_2400; break; case 4800: nrf_baudrate = NRF_UARTE_BAUDRATE_4800; break; case 9600: nrf_baudrate = NRF_UARTE_BAUDRATE_9600; break; case 14400: nrf_baudrate = NRF_UARTE_BAUDRATE_14400; break; case 19200: nrf_baudrate = NRF_UARTE_BAUDRATE_19200; break; case 28800: nrf_baudrate = NRF_UARTE_BAUDRATE_28800; break; case 31250: nrf_baudrate = NRF_UARTE_BAUDRATE_31250; break; case 38400: nrf_baudrate = NRF_UARTE_BAUDRATE_38400; break; case 56000: nrf_baudrate = NRF_UARTE_BAUDRATE_56000; break; case 57600: nrf_baudrate = NRF_UARTE_BAUDRATE_57600; break; case 76800: nrf_baudrate = NRF_UARTE_BAUDRATE_76800; break; case 115200: nrf_baudrate = NRF_UARTE_BAUDRATE_115200; break; case 230400: nrf_baudrate = NRF_UARTE_BAUDRATE_230400; break; case 250000: nrf_baudrate = NRF_UARTE_BAUDRATE_250000; break; case 460800: nrf_baudrate = NRF_UARTE_BAUDRATE_460800; break; case 921600: nrf_baudrate = NRF_UARTE_BAUDRATE_921600; break; case 1000000: nrf_baudrate = NRF_UARTE_BAUDRATE_1000000; break; default: return -EINVAL; } nrf_uarte_baudrate_set(uarte, nrf_baudrate); return 0; } static int uarte_nrfx_configure(struct device *dev, const struct uart_config *cfg) { nrf_uarte_config_t uarte_cfg; #if defined(UARTE_CONFIG_STOP_Msk) switch (cfg->stop_bits) { case UART_CFG_STOP_BITS_1: uarte_cfg.stop = NRF_UARTE_STOP_ONE; break; case UART_CFG_STOP_BITS_2: uarte_cfg.stop = NRF_UARTE_STOP_TWO; break; default: return -ENOTSUP; } #else if (cfg->stop_bits != UART_CFG_STOP_BITS_1) { return -ENOTSUP; } #endif if (cfg->data_bits != UART_CFG_DATA_BITS_8) { return -ENOTSUP; } switch (cfg->flow_ctrl) { case UART_CFG_FLOW_CTRL_NONE: uarte_cfg.hwfc = NRF_UARTE_HWFC_DISABLED; break; case UART_CFG_FLOW_CTRL_RTS_CTS: if (get_dev_config(dev)->rts_cts_pins_set) { uarte_cfg.hwfc = NRF_UARTE_HWFC_ENABLED; } else { return -ENOTSUP; } break; default: return -ENOTSUP; } #if defined(UARTE_CONFIG_PARITYTYPE_Msk) uarte_cfg.paritytype = NRF_UARTE_PARITYTYPE_EVEN; #endif switch (cfg->parity) { case UART_CFG_PARITY_NONE: uarte_cfg.parity = NRF_UARTE_PARITY_EXCLUDED; break; case UART_CFG_PARITY_EVEN: uarte_cfg.parity = NRF_UARTE_PARITY_INCLUDED; break; #if defined(UARTE_CONFIG_PARITYTYPE_Msk) case UART_CFG_PARITY_ODD: uarte_cfg.parity = NRF_UARTE_PARITY_INCLUDED; uarte_cfg.paritytype = NRF_UARTE_PARITYTYPE_ODD; break; #endif default: return -ENOTSUP; } if (baudrate_set(dev, cfg->baudrate) != 0) { return -ENOTSUP; } nrf_uarte_configure(get_uarte_instance(dev), &uarte_cfg); get_dev_data(dev)->uart_config = *cfg; return 0; } static int uarte_nrfx_config_get(struct device *dev, struct uart_config *cfg) { *cfg = get_dev_data(dev)->uart_config; return 0; } static int uarte_nrfx_err_check(struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); /* register bitfields maps to the defines in uart.h */ return nrf_uarte_errorsrc_get_and_clear(uarte); } #ifdef CONFIG_UART_ASYNC_API static inline bool hw_rx_counting_enabled(struct uarte_nrfx_data *data) { if (IS_ENABLED(CONFIG_UARTE_NRF_HW_ASYNC)) { return data->async->hw_rx_counting; } else { return false; } } static void timer_handler(nrf_timer_event_t event_type, void *p_context) { } static void rx_timeout(struct k_timer *timer); static void tx_timeout(struct k_timer *timer); static int uarte_nrfx_rx_counting_init(struct device *dev) { struct uarte_nrfx_data *data = get_dev_data(dev); const struct uarte_nrfx_config *cfg = get_dev_config(dev); NRF_UARTE_Type *uarte = get_uarte_instance(dev); int ret; if (hw_rx_counting_enabled(data)) { nrfx_timer_config_t tmr_config = NRFX_TIMER_DEFAULT_CONFIG; tmr_config.mode = NRF_TIMER_MODE_COUNTER; tmr_config.bit_width = NRF_TIMER_BIT_WIDTH_32; ret = nrfx_timer_init(&cfg->timer, &tmr_config, timer_handler); if (ret != NRFX_SUCCESS) { LOG_ERR("Timer already initialized, " "switching to software byte counting."); data->async->hw_rx_counting = false; } else { nrfx_timer_enable(&cfg->timer); nrfx_timer_clear(&cfg->timer); } } if (hw_rx_counting_enabled(data)) { ret = gppi_channel_alloc(&data->async->rx_cnt.ppi); if (ret != NRFX_SUCCESS) { LOG_ERR("Failed to allocate PPI Channel, " "switching to software byte counting."); data->async->hw_rx_counting = false; nrfx_timer_uninit(&cfg->timer); } } if (hw_rx_counting_enabled(data)) { #if CONFIG_HAS_HW_NRF_PPI ret = nrfx_ppi_channel_assign( data->async->rx_cnt.ppi, nrf_uarte_event_address_get(uarte, NRF_UARTE_EVENT_RXDRDY), nrfx_timer_task_address_get(&cfg->timer, NRF_TIMER_TASK_COUNT)); if (ret != NRFX_SUCCESS) { return -EIO; } #else nrf_uarte_publish_set(uarte, NRF_UARTE_EVENT_RXDRDY, data->async->rx_cnt.ppi); nrf_timer_subscribe_set(cfg->timer.p_reg, NRF_TIMER_TASK_COUNT, data->async->rx_cnt.ppi); #endif ret = gppi_channel_enable(data->async->rx_cnt.ppi); if (ret != NRFX_SUCCESS) { return -EIO; } } else { nrf_uarte_int_enable(uarte, NRF_UARTE_INT_RXDRDY_MASK); } return 0; } static int uarte_nrfx_init(struct device *dev) { struct uarte_nrfx_data *data = get_dev_data(dev); NRF_UARTE_Type *uarte = get_uarte_instance(dev); int ret = uarte_nrfx_rx_counting_init(dev); if (ret != 0) { return ret; } nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDRX_MASK | NRF_UARTE_INT_RXSTARTED_MASK | NRF_UARTE_INT_ERROR_MASK | NRF_UARTE_INT_RXTO_MASK); nrf_uarte_enable(uarte); k_timer_init(&data->async->rx_timeout_timer, rx_timeout, NULL); k_timer_user_data_set(&data->async->rx_timeout_timer, dev); k_timer_init(&data->async->tx_timeout_timer, tx_timeout, NULL); k_timer_user_data_set(&data->async->tx_timeout_timer, dev); return 0; } static int uarte_nrfx_tx(struct device *dev, const u8_t *buf, size_t len, s32_t timeout) { struct uarte_nrfx_data *data = get_dev_data(dev); NRF_UARTE_Type *uarte = get_uarte_instance(dev); if (!nrfx_is_in_ram(buf)) { return -ENOTSUP; } if (atomic_cas((atomic_t *) &data->async->tx_size, (atomic_val_t) 0, (atomic_val_t) len) == false) { return -EBUSY; } data->async->tx_buf = buf; nrf_uarte_tx_buffer_set(uarte, buf, len); nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDTX); nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_TXSTOPPED); nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDTX_MASK | NRF_UARTE_INT_TXSTOPPED_MASK); nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTTX); if (data->uart_config.flow_ctrl == UART_CFG_FLOW_CTRL_RTS_CTS && timeout != K_FOREVER) { k_timer_start(&data->async->tx_timeout_timer, timeout, K_NO_WAIT); } return 0; } static int uarte_nrfx_tx_abort(struct device *dev) { struct uarte_nrfx_data *data = get_dev_data(dev); NRF_UARTE_Type *uarte = get_uarte_instance(dev); if (data->async->tx_buf == NULL) { return -EFAULT; } k_timer_stop(&data->async->tx_timeout_timer); nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPTX); return 0; } static int uarte_nrfx_rx_enable(struct device *dev, u8_t *buf, size_t len, s32_t timeout) { struct uarte_nrfx_data *data = get_dev_data(dev); const struct uarte_nrfx_config *cfg = get_dev_config(dev); NRF_UARTE_Type *uarte = get_uarte_instance(dev); if (nrf_uarte_rx_pin_get(uarte) == NRF_UARTE_PSEL_DISCONNECTED) { __ASSERT(false, "TX only UARTE instance"); return -ENOTSUP; } if (hw_rx_counting_enabled(data)) { nrfx_timer_clear(&cfg->timer); } else { data->async->rx_cnt.cnt = 0; } data->async->rx_total_byte_cnt = 0; data->async->rx_total_user_byte_cnt = 0; data->async->rx_timeout = timeout; data->async->rx_timeout_slab = MAX(timeout / RX_TIMEOUT_DIV, NRFX_CEIL_DIV(1000, CONFIG_SYS_CLOCK_TICKS_PER_SEC)); data->async->rx_buf = buf; data->async->rx_offset = 0; nrf_uarte_rx_buffer_set(uarte, buf, len); nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDRX); nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXSTARTED); data->async->rx_enabled = true; nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTRX); return 0; } static int uarte_nrfx_rx_buf_rsp(struct device *dev, u8_t *buf, size_t len) { struct uarte_nrfx_data *data = get_dev_data(dev); NRF_UARTE_Type *uarte = get_uarte_instance(dev); if (data->async->rx_next_buf == NULL) { data->async->rx_next_buf = buf; nrf_uarte_rx_buffer_set(uarte, buf, len); } else { return -EBUSY; } return 0; } static int uarte_nrfx_callback_set(struct device *dev, uart_callback_t callback, void *user_data) { struct uarte_nrfx_data *data = get_dev_data(dev); data->async->user_callback = callback; data->async->user_data = user_data; return 0; } static int uarte_nrfx_rx_disable(struct device *dev) { struct uarte_nrfx_data *data = get_dev_data(dev); NRF_UARTE_Type *uarte = get_uarte_instance(dev); if (data->async->rx_buf == NULL) { return -EFAULT; } k_timer_stop(&data->async->rx_timeout_timer); data->async->rx_enabled = false; nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPRX); return 0; } static void tx_timeout(struct k_timer *timer) { struct device *dev = k_timer_user_data_get(timer); (void) uarte_nrfx_tx_abort(dev); } static void user_callback(struct device *dev, struct uart_event *evt) { struct uarte_nrfx_data *data = get_dev_data(dev); if (data->async->user_callback) { data->async->user_callback(evt, data->async->user_data); } } /** * Whole timeout is divided by RX_TIMEOUT_DIV into smaller units, rx_timeout * is executed periodically every rx_timeout_slab ms. If between executions * data was received, then we start counting down time from start, if not, then * we subtract rx_timeout_slab from rx_timeout_left. * If rx_timeout_left is less than rx_timeout_slab it means that receiving has * timed out and we should tell user about that. */ static void rx_timeout(struct k_timer *timer) { struct device *dev = k_timer_user_data_get(timer); struct uarte_nrfx_data *data = get_dev_data(dev); const struct uarte_nrfx_config *cfg = get_dev_config(dev); u32_t read; if (data->async->is_in_irq) { return; } /* Disable ENDRX ISR, in case ENDRX event is generated, it will be * handled after rx_timeout routine is complete. */ nrf_uarte_int_disable(get_uarte_instance(dev), NRF_UARTE_INT_ENDRX_MASK); if (hw_rx_counting_enabled(data)) { read = nrfx_timer_capture(&cfg->timer, 0); } else { read = data->async->rx_cnt.cnt; } /* Check if data was received since last function call */ if (read != data->async->rx_total_byte_cnt) { data->async->rx_total_byte_cnt = read; data->async->rx_timeout_left = data->async->rx_timeout; } /* Check if there is data that was not sent to user yet */ s32_t len = data->async->rx_total_byte_cnt - data->async->rx_total_user_byte_cnt; if (len > 0) { if (data->async->rx_timeout_left < data->async->rx_timeout_slab) { /* rx_timeout ms elapsed since last receiving */ struct uart_event evt = { .type = UART_RX_RDY, .data.rx.buf = data->async->rx_buf, .data.rx.len = len, .data.rx.offset = data->async->rx_offset }; data->async->rx_offset += len; data->async->rx_total_user_byte_cnt = data->async->rx_total_byte_cnt; user_callback(dev, &evt); } else { data->async->rx_timeout_left -= data->async->rx_timeout_slab; } } nrf_uarte_int_enable(get_uarte_instance(dev), NRF_UARTE_INT_ENDRX_MASK); } #define UARTE_ERROR_FROM_MASK(mask) \ ((mask) & NRF_UARTE_ERROR_OVERRUN_MASK ? UART_ERROR_OVERRUN \ : (mask) & NRF_UARTE_ERROR_PARITY_MASK ? UART_ERROR_PARITY \ : (mask) & NRF_UARTE_ERROR_FRAMING_MASK ? UART_ERROR_FRAMING \ : (mask) & NRF_UARTE_ERROR_BREAK_MASK ? UART_BREAK \ : 0) static void error_isr(struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); u32_t err = nrf_uarte_errorsrc_get_and_clear(uarte); struct uart_event evt = { .type = UART_RX_STOPPED, .data.rx_stop.reason = UARTE_ERROR_FROM_MASK(err), }; user_callback(dev, &evt); (void) uarte_nrfx_rx_disable(dev); } static void rxstarted_isr(struct device *dev) { struct uarte_nrfx_data *data = get_dev_data(dev); struct uart_event evt = { .type = UART_RX_BUF_REQUEST, }; user_callback(dev, &evt); if (data->async->rx_timeout != K_FOREVER) { data->async->rx_timeout_left = data->async->rx_timeout; k_timer_start(&data->async->rx_timeout_timer, data->async->rx_timeout_slab, data->async->rx_timeout_slab); } } static void endrx_isr(struct device *dev) { struct uarte_nrfx_data *data = get_dev_data(dev); NRF_UARTE_Type *uarte = get_uarte_instance(dev); if (!data->async->rx_enabled) { if (data->async->rx_buf == NULL) { /* This condition can occur only after triggering * FLUSHRX task. */ struct uart_event evt = { .type = UART_RX_DISABLED, }; user_callback(dev, &evt); } return; } data->async->is_in_irq = true; if (data->async->rx_next_buf) { nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTRX); } k_timer_stop(&data->async->rx_timeout_timer); size_t rx_len = nrf_uarte_rx_amount_get(uarte) - data->async->rx_offset; data->async->rx_total_user_byte_cnt += rx_len; if (!hw_rx_counting_enabled(data)) { /* Prevent too low value of rx_cnt.cnt which may occur due to * latencies in handling of the RXRDY interrupt. Because whole * buffer was filled we can be sure that rx_total_user_byte_cnt * is current total number of received bytes. */ data->async->rx_cnt.cnt = data->async->rx_total_user_byte_cnt; } struct uart_event evt = { .type = UART_RX_RDY, .data.rx.buf = data->async->rx_buf, .data.rx.len = rx_len, .data.rx.offset = data->async->rx_offset, }; user_callback(dev, &evt); evt.type = UART_RX_BUF_RELEASED; evt.data.rx_buf.buf = data->async->rx_buf; user_callback(dev, &evt); if (data->async->rx_next_buf) { data->async->rx_buf = data->async->rx_next_buf; data->async->rx_next_buf = NULL; data->async->rx_offset = 0; } else { data->async->rx_buf = NULL; evt.type = UART_RX_DISABLED; user_callback(dev, &evt); } data->async->is_in_irq = false; } /* This handler is called when the reception is interrupted, in contrary to * finishing the reception after filling all provided buffers, in which case * the events UART_RX_BUF_RELEASED and UART_RX_DISABLED are reported * from endrx_isr. */ static void rxto_isr(struct device *dev) { struct uarte_nrfx_data *data = get_dev_data(dev); struct uart_event evt = { .type = UART_RX_BUF_RELEASED, .data.rx_buf.buf = data->async->rx_buf, }; user_callback(dev, &evt); data->async->rx_buf = NULL; if (data->async->rx_next_buf) { evt.type = UART_RX_BUF_RELEASED; evt.data.rx_buf.buf = data->async->rx_next_buf; user_callback(dev, &evt); data->async->rx_next_buf = NULL; } /* Flushing RX fifo requires buffer bigger than 4 bytes to empty fifo */ static u8_t flush_buf[5]; nrf_uarte_rx_buffer_set(get_uarte_instance(dev), flush_buf, 5); /* Final part of handling RXTO event is in ENDRX interrupt handler. * ENDRX is generated as a result of FLUSHRX task. */ nrf_uarte_task_trigger(get_uarte_instance(dev), NRF_UARTE_TASK_FLUSHRX); } static void txstopped_isr(struct device *dev) { struct uarte_nrfx_data *data = get_dev_data(dev); if (!data->async->tx_buf) { return; } size_t amount = nrf_uarte_tx_amount_get(get_uarte_instance(dev)); struct uart_event evt = { .data.tx.buf = data->async->tx_buf, .data.tx.len = amount, }; if (amount == data->async->tx_size) { evt.type = UART_TX_DONE; } else { evt.type = UART_TX_ABORTED; } data->async->tx_buf = NULL; data->async->tx_size = 0; nrf_uarte_int_disable(get_uarte_instance(dev), NRF_UARTE_INT_TXSTOPPED_MASK); user_callback(dev, &evt); } static void endtx_isr(struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); struct uarte_nrfx_data *data = get_dev_data(dev); nrf_uarte_int_disable(uarte, NRF_UARTE_INT_ENDTX_MASK); nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPTX); k_timer_stop(&data->async->tx_timeout_timer); } static void uarte_nrfx_isr_async(struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); struct uarte_nrfx_data *data = get_dev_data(dev); if (!hw_rx_counting_enabled(data) && nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_RXDRDY)) { nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXDRDY); data->async->rx_cnt.cnt++; return; } if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ERROR)) { nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ERROR); error_isr(dev); } if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_RXSTARTED)) { nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXSTARTED); rxstarted_isr(dev); } if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDRX)) { nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDRX); endrx_isr(dev); } if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_RXTO)) { nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXTO); rxto_isr(dev); } if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX) && nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDTX_MASK)) { nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDTX); endtx_isr(dev); } if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_TXSTOPPED) && nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_TXSTOPPED_MASK)) { nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_TXSTOPPED); txstopped_isr(dev); } } #endif /* CONFIG_UART_ASYNC_API */ /** * @brief Poll the device for input. * * @param dev UARTE device struct * @param c Pointer to character * * @return 0 if a character arrived, -1 if the input buffer is empty. */ static int uarte_nrfx_poll_in(struct device *dev, unsigned char *c) { const struct uarte_nrfx_data *data = get_dev_data(dev); NRF_UARTE_Type *uarte = get_uarte_instance(dev); #ifdef CONFIG_UART_ASYNC_API if (data->async) { return -ENOTSUP; } #endif if (!nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDRX)) { return -1; } *c = data->rx_data; /* clear the interrupt */ nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDRX); nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTRX); return 0; } /** * @brief Output a character in polled mode. * * @param dev UARTE device struct * @param c Character to send */ static void uarte_nrfx_poll_out(struct device *dev, unsigned char c) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); struct uarte_nrfx_data *data = get_dev_data(dev); atomic_t *lock; #ifdef CONFIG_UART_ASYNC_API if (data->async) { while (data->async->tx_buf) { /* If there is ongoing transmission, and we are in * isr, then call uarte interrupt routine, otherwise * busy wait until transmission is finished. */ if (k_is_in_isr()) { uarte_nrfx_isr_async(dev); } } /* Use tx_size as lock, this way uarte_nrfx_tx will * return -EBUSY during poll_out. */ lock = &data->async->tx_size; } else #endif lock = &data->poll_out_lock; if (!k_is_in_isr()) { u8_t safety_cnt = 100; while (atomic_cas((atomic_t *) lock, (atomic_val_t) 0, (atomic_val_t) 1) == false) { /* k_sleep allows other threads to execute and finish * their transactions. */ k_sleep(1); if (--safety_cnt == 0) { return; } } } else { *lock = 1; } /* reset transmitter ready state */ nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDTX); /* send a character */ nrf_uarte_tx_buffer_set(uarte, &c, 1); nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTTX); /* Wait for transmitter to be ready */ int res; NRFX_WAIT_FOR(nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX), 1000, 1, res); /* Deactivate the transmitter so that it does not needlessly * consume power. */ nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPTX); /* Release the lock. */ *lock = 0; } #ifdef UARTE_INTERRUPT_DRIVEN /** Interrupt driven FIFO fill function */ static int uarte_nrfx_fifo_fill(struct device *dev, const u8_t *tx_data, int len) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); struct uarte_nrfx_data *data = get_dev_data(dev); if (!nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX)) { return 0; } if (len > data->int_driven->tx_buff_size) { len = data->int_driven->tx_buff_size; } nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDTX); /* Copy data to RAM buffer for EasyDMA transfer */ for (int i = 0; i < len; i++) { data->int_driven->tx_buffer[i] = tx_data[i]; } nrf_uarte_tx_buffer_set(uarte, data->int_driven->tx_buffer, len); nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTTX); return len; } /** Interrupt driven FIFO read function */ static int uarte_nrfx_fifo_read(struct device *dev, u8_t *rx_data, const int size) { int num_rx = 0; NRF_UARTE_Type *uarte = get_uarte_instance(dev); const struct uarte_nrfx_data *data = get_dev_data(dev); if (nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDRX)) { /* Clear the interrupt */ nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDRX); /* Receive a character */ rx_data[num_rx++] = (u8_t)data->rx_data; nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTRX); } return num_rx; } /** Interrupt driven transfer enabling function */ static void uarte_nrfx_irq_tx_enable(struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); struct uarte_nrfx_data *data = get_dev_data(dev); data->int_driven->disable_tx_irq = false; nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDTX_MASK); } /** Interrupt driven transfer disabling function */ static void uarte_nrfx_irq_tx_disable(struct device *dev) { struct uarte_nrfx_data *data = get_dev_data(dev); /* TX IRQ will be disabled after current transmission is finished */ data->int_driven->disable_tx_irq = true; } /** Interrupt driven transfer ready function */ static int uarte_nrfx_irq_tx_ready_complete(struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); /* ENDTX flag is always on so that ISR is called when we enable TX IRQ. * Because of that we have to explicitly check if ENDTX interrupt is * enabled, otherwise this function would always return true no matter * what would be the source of interrupt. */ return nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDTX) && nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDTX_MASK); } static int uarte_nrfx_irq_rx_ready(struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); return nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_ENDRX); } /** Interrupt driven receiver enabling function */ static void uarte_nrfx_irq_rx_enable(struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ENDRX_MASK); } /** Interrupt driven receiver disabling function */ static void uarte_nrfx_irq_rx_disable(struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); nrf_uarte_int_disable(uarte, NRF_UARTE_INT_ENDRX_MASK); } /** Interrupt driven error enabling function */ static void uarte_nrfx_irq_err_enable(struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); nrf_uarte_int_enable(uarte, NRF_UARTE_INT_ERROR_MASK); } /** Interrupt driven error disabling function */ static void uarte_nrfx_irq_err_disable(struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); nrf_uarte_int_disable(uarte, NRF_UARTE_INT_ERROR_MASK); } /** Interrupt driven pending status function */ static int uarte_nrfx_irq_is_pending(struct device *dev) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); return ((nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDTX_MASK) && uarte_nrfx_irq_tx_ready_complete(dev)) || (nrf_uarte_int_enable_check(uarte, NRF_UARTE_INT_ENDRX_MASK) && uarte_nrfx_irq_rx_ready(dev))); } /** Interrupt driven interrupt update function */ static int uarte_nrfx_irq_update(struct device *dev) { return 1; } /** Set the callback function */ static void uarte_nrfx_irq_callback_set(struct device *dev, uart_irq_callback_user_data_t cb, void *cb_data) { struct uarte_nrfx_data *data = get_dev_data(dev); data->int_driven->cb = cb; data->int_driven->cb_data = cb_data; } #endif /* UARTE_INTERRUPT_DRIVEN */ static const struct uart_driver_api uart_nrfx_uarte_driver_api = { .poll_in = uarte_nrfx_poll_in, .poll_out = uarte_nrfx_poll_out, .err_check = uarte_nrfx_err_check, .configure = uarte_nrfx_configure, .config_get = uarte_nrfx_config_get, #ifdef CONFIG_UART_ASYNC_API .callback_set = uarte_nrfx_callback_set, .tx = uarte_nrfx_tx, .tx_abort = uarte_nrfx_tx_abort, .rx_enable = uarte_nrfx_rx_enable, .rx_buf_rsp = uarte_nrfx_rx_buf_rsp, .rx_disable = uarte_nrfx_rx_disable, #endif /* CONFIG_UART_ASYNC_API */ #ifdef UARTE_INTERRUPT_DRIVEN .fifo_fill = uarte_nrfx_fifo_fill, .fifo_read = uarte_nrfx_fifo_read, .irq_tx_enable = uarte_nrfx_irq_tx_enable, .irq_tx_disable = uarte_nrfx_irq_tx_disable, .irq_tx_ready = uarte_nrfx_irq_tx_ready_complete, .irq_rx_enable = uarte_nrfx_irq_rx_enable, .irq_rx_disable = uarte_nrfx_irq_rx_disable, .irq_tx_complete = uarte_nrfx_irq_tx_ready_complete, .irq_rx_ready = uarte_nrfx_irq_rx_ready, .irq_err_enable = uarte_nrfx_irq_err_enable, .irq_err_disable = uarte_nrfx_irq_err_disable, .irq_is_pending = uarte_nrfx_irq_is_pending, .irq_update = uarte_nrfx_irq_update, .irq_callback_set = uarte_nrfx_irq_callback_set, #endif /* UARTE_INTERRUPT_DRIVEN */ }; static int uarte_instance_init(struct device *dev, const struct uarte_init_config *config, u8_t interrupts_active) { int err; NRF_UARTE_Type *uarte = get_uarte_instance(dev); struct uarte_nrfx_data *data = get_dev_data(dev); nrf_gpio_pin_write(config->pseltxd, 1); nrf_gpio_cfg_output(config->pseltxd); if (config->pselrxd != NRF_UARTE_PSEL_DISCONNECTED) { nrf_gpio_cfg_input(config->pselrxd, NRF_GPIO_PIN_NOPULL); } nrf_uarte_txrx_pins_set(uarte, config->pseltxd, config->pselrxd); if (config->pselcts != NRF_UARTE_PSEL_DISCONNECTED && config->pselrts != NRF_UARTE_PSEL_DISCONNECTED) { nrf_gpio_pin_write(config->pselrts, 1); nrf_gpio_cfg_output(config->pselrts); nrf_gpio_cfg_input(config->pselcts, NRF_GPIO_PIN_NOPULL); nrf_uarte_hwfc_pins_set(uarte, config->pselrts, config->pselcts); } err = uarte_nrfx_configure(dev, &get_dev_data(dev)->uart_config); if (err) { return err; } #ifdef CONFIG_DEVICE_POWER_MANAGEMENT data->pm_state = DEVICE_PM_ACTIVE_STATE; #endif #ifdef CONFIG_UART_ASYNC_API if (data->async) { return uarte_nrfx_init(dev); } #endif /* Enable receiver and transmitter */ nrf_uarte_enable(uarte); if (config->pselrxd != NRF_UARTE_PSEL_DISCONNECTED) { nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_ENDRX); nrf_uarte_rx_buffer_set(uarte, &data->rx_data, 1); nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTRX); } #ifdef UARTE_INTERRUPT_DRIVEN if (interrupts_active) { /* Set ENDTX event by requesting fake (zero-length) transfer. * Pointer to RAM variable (data->tx_buffer) is set because * otherwise such operation may result in HardFault or RAM * corruption. */ nrf_uarte_tx_buffer_set(uarte, data->int_driven->tx_buffer, 0); nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTTX); /* switch off transmitter to save an energy */ nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPTX); } #endif return 0; } #ifdef CONFIG_DEVICE_POWER_MANAGEMENT static void uarte_nrfx_pins_enable(struct device *dev, bool enable) { if (!get_dev_config(dev)->gpio_mgmt) { return; } NRF_UARTE_Type *uarte = get_uarte_instance(dev); u32_t tx_pin = nrf_uarte_tx_pin_get(uarte); u32_t rx_pin = nrf_uarte_rx_pin_get(uarte); u32_t cts_pin = nrf_uarte_cts_pin_get(uarte); u32_t rts_pin = nrf_uarte_rts_pin_get(uarte); if (enable) { nrf_gpio_pin_write(tx_pin, 1); nrf_gpio_cfg_output(tx_pin); if (rx_pin != NRF_UARTE_PSEL_DISCONNECTED) { nrf_gpio_cfg_input(rx_pin, NRF_GPIO_PIN_NOPULL); } if (get_dev_config(dev)->rts_cts_pins_set) { nrf_gpio_pin_write(rts_pin, 1); nrf_gpio_cfg_output(rts_pin); nrf_gpio_cfg_input(cts_pin, NRF_GPIO_PIN_NOPULL); } } else { nrf_gpio_cfg_default(tx_pin); if (rx_pin != NRF_UARTE_PSEL_DISCONNECTED) { nrf_gpio_cfg_default(rx_pin); } if (get_dev_config(dev)->rts_cts_pins_set) { nrf_gpio_cfg_default(cts_pin); nrf_gpio_cfg_default(rts_pin); } } } static void uarte_nrfx_set_power_state(struct device *dev, u32_t new_state) { NRF_UARTE_Type *uarte = get_uarte_instance(dev); struct uarte_nrfx_data *data = get_dev_data(dev); if (new_state == DEVICE_PM_ACTIVE_STATE) { uarte_nrfx_pins_enable(dev, true); nrf_uarte_enable(uarte); #ifdef CONFIG_UART_ASYNC_API if (hw_rx_counting_enabled(get_dev_data(dev))) { nrfx_timer_enable(&get_dev_config(dev)->timer); } if (get_dev_data(dev)->async) { return; } #endif if (nrf_uarte_rx_pin_get(uarte) != NRF_UARTE_PSEL_DISCONNECTED) { nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STARTRX); } } else { __ASSERT_NO_MSG(new_state == DEVICE_PM_LOW_POWER_STATE || new_state == DEVICE_PM_SUSPEND_STATE || new_state == DEVICE_PM_OFF_STATE); /* if pm is already not active, driver will stay indefinitely * in while loop waiting for event NRF_UARTE_EVENT_RXTO */ if (data->pm_state != DEVICE_PM_ACTIVE_STATE) { return; } /* Disabling UART requires stopping RX, but stop RX event is * only sent after each RX if async UART API is used. */ #ifdef CONFIG_UART_ASYNC_API if (hw_rx_counting_enabled(get_dev_data(dev))) { nrfx_timer_disable(&get_dev_config(dev)->timer); } if (get_dev_data(dev)->async) { nrf_uarte_disable(uarte); uarte_nrfx_pins_enable(dev, false); return; } #endif nrf_uarte_task_trigger(uarte, NRF_UARTE_TASK_STOPRX); while (!nrf_uarte_event_check(uarte, NRF_UARTE_EVENT_RXTO)) { /* Busy wait for event to register */ } nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_RXTO); nrf_uarte_disable(uarte); uarte_nrfx_pins_enable(dev, false); } } static int uarte_nrfx_pm_control(struct device *dev, u32_t ctrl_command, void *context, device_pm_cb cb, void *arg) { struct uarte_nrfx_data *data = get_dev_data(dev); if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { u32_t new_state = *((const u32_t *)context); if (new_state != data->pm_state) { uarte_nrfx_set_power_state(dev, new_state); data->pm_state = new_state; } } else { __ASSERT_NO_MSG(ctrl_command == DEVICE_PM_GET_POWER_STATE); *((u32_t *)context) = data->pm_state; } if (cb) { cb(dev, 0, context, arg); } return 0; } #endif /* CONFIG_DEVICE_POWER_MANAGEMENT */ #define UART_NRF_UARTE_DEVICE(idx) \ DEVICE_DECLARE(uart_nrfx_uarte##idx); \ UARTE_INT_DRIVEN(idx); \ UARTE_ASYNC(idx); \ static struct uarte_nrfx_data uarte_##idx##_data = { \ UARTE_CONFIG(idx), \ IF_ENABLED(CONFIG_UART_##idx##_ASYNC, \ (.async = &uarte##idx##_async,)) \ IF_ENABLED(CONFIG_UART_##idx##_INTERRUPT_DRIVEN, \ (.int_driven = &uarte##idx##_int_driven,)) \ }; \ static const struct uarte_nrfx_config uarte_##idx##z_config = { \ .uarte_regs = (NRF_UARTE_Type *) \ DT_NORDIC_NRF_UARTE_UART_##idx##_BASE_ADDRESS, \ .rts_cts_pins_set = IS_ENABLED(UARTE_##idx##_CONFIG_RTS_CTS), \ .gpio_mgmt = IS_ENABLED(CONFIG_UART_##idx##_GPIO_MANAGEMENT), \ IF_ENABLED(CONFIG_UART_##idx##_NRF_HW_ASYNC, \ (.timer = NRFX_TIMER_INSTANCE( \ CONFIG_UART_##idx##_NRF_HW_ASYNC_TIMER),)) \ }; \ static int uarte_##idx##_init(struct device *dev) \ { \ const struct uarte_init_config init_config = { \ .pseltxd = DT_NORDIC_NRF_UARTE_UART_##idx##_TX_PIN, \ .pselrxd = DT_NORDIC_NRF_UARTE_UART_##idx##_RX_PIN, \ UARTE_NRF_RTS_CTS_PINS(idx), \ }; \ IF_ENABLED(CONFIG_UART_##idx##_INTERRUPT_DRIVEN, \ (IRQ_CONNECT( \ NRFX_IRQ_NUMBER_GET(NRF_UARTE##idx), \ DT_NORDIC_NRF_UARTE_UART_##idx##_IRQ_0_PRIORITY, \ uarte_nrfx_isr_int, \ DEVICE_GET(uart_nrfx_uarte##idx), \ 0); \ irq_enable(DT_NORDIC_NRF_UARTE_UART_##idx##_IRQ_0);)) \ IF_ENABLED(CONFIG_UART_##idx##_ASYNC, \ (IRQ_CONNECT( \ NRFX_IRQ_NUMBER_GET(NRF_UARTE##idx), \ DT_NORDIC_NRF_UARTE_UART_##idx##_IRQ_0_PRIORITY, \ uarte_nrfx_isr_async, \ DEVICE_GET(uart_nrfx_uarte##idx), \ 0); \ irq_enable(DT_NORDIC_NRF_UARTE_UART_##idx##_IRQ_0);)) \ return uarte_instance_init( \ dev, \ &init_config, \ IS_ENABLED(CONFIG_UART_##idx##_INTERRUPT_DRIVEN)); \ } \ DEVICE_DEFINE(uart_nrfx_uarte##idx, \ DT_NORDIC_NRF_UARTE_UART_##idx##_LABEL, \ uarte_##idx##_init, \ uarte_nrfx_pm_control, \ &uarte_##idx##_data, \ &uarte_##idx##z_config, \ PRE_KERNEL_1, \ CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ &uart_nrfx_uarte_driver_api) #define UARTE_CONFIG(idx) \ .uart_config = { \ .baudrate = DT_NORDIC_NRF_UARTE_UART_##idx##_CURRENT_SPEED, \ .data_bits = UART_CFG_DATA_BITS_8, \ .stop_bits = UART_CFG_STOP_BITS_1, \ .parity = IS_ENABLED(CONFIG_UART_##idx##_NRF_PARITY_BIT) \ ? UART_CFG_PARITY_EVEN \ : UART_CFG_PARITY_NONE, \ .flow_ctrl = IS_ENABLED(CONFIG_UART_##idx##_NRF_FLOW_CONTROL) \ ? UART_CFG_FLOW_CTRL_RTS_CTS \ : UART_CFG_FLOW_CTRL_NONE, \ } #define UARTE_NRF_RTS_CTS_PINS(idx) \ .pselcts = COND_CODE_1(UARTE_##idx##_CONFIG_RTS_CTS, \ (DT_NORDIC_NRF_UARTE_UART_##idx##_CTS_PIN), \ (NRF_UARTE_PSEL_DISCONNECTED)), \ .pselrts = COND_CODE_1(UARTE_##idx##_CONFIG_RTS_CTS, \ (DT_NORDIC_NRF_UARTE_UART_##idx##_RTS_PIN), \ (NRF_UARTE_PSEL_DISCONNECTED)) #define UARTE_ASYNC(idx) \ IF_ENABLED(CONFIG_UART_##idx##_ASYNC, \ (struct uarte_async_cb uarte##idx##_async = { \ .hw_rx_counting = \ IS_ENABLED(CONFIG_UART_##idx##_NRF_HW_ASYNC), \ })) #define UARTE_INT_DRIVEN(idx) \ IF_ENABLED(CONFIG_UART_##idx##_INTERRUPT_DRIVEN, \ (static u8_t uarte##idx##_tx_buffer[\ MIN(CONFIG_UART_##idx##_NRF_TX_BUFFER_SIZE, \ BIT_MASK(UARTE##idx##_EASYDMA_MAXCNT_SIZE))]; \ static struct uarte_nrfx_int_driven \ uarte##idx##_int_driven = { \ .tx_buffer = uarte##idx##_tx_buffer, \ .tx_buff_size = sizeof(uarte##idx##_tx_buffer),\ };)) #ifdef CONFIG_UART_0_NRF_UARTE #if defined(DT_NORDIC_NRF_UARTE_UART_0_RTS_PIN) && \ defined(DT_NORDIC_NRF_UARTE_UART_0_CTS_PIN) #define UARTE_0_CONFIG_RTS_CTS 1 #endif #if !defined(DT_NORDIC_NRF_UARTE_UART_0_RX_PIN) #define DT_NORDIC_NRF_UARTE_UART_0_RX_PIN NRF_UARTE_PSEL_DISCONNECTED #endif UART_NRF_UARTE_DEVICE(0); #endif /* CONFIG_UART_0_NRF_UARTE */ #ifdef CONFIG_UART_1_NRF_UARTE #if defined(DT_NORDIC_NRF_UARTE_UART_1_RTS_PIN) && \ defined(DT_NORDIC_NRF_UARTE_UART_1_CTS_PIN) #define UARTE_1_CONFIG_RTS_CTS 1 #endif #if !defined(DT_NORDIC_NRF_UARTE_UART_1_RX_PIN) #define DT_NORDIC_NRF_UARTE_UART_1_RX_PIN NRF_UARTE_PSEL_DISCONNECTED #endif UART_NRF_UARTE_DEVICE(1); #endif /* CONFIG_UART_1_NRF_UARTE */ #ifdef CONFIG_UART_2_NRF_UARTE #if defined(DT_NORDIC_NRF_UARTE_UART_2_RTS_PIN) && \ defined(DT_NORDIC_NRF_UARTE_UART_2_CTS_PIN) #define UARTE_2_CONFIG_RTS_CTS 1 #endif #if !defined(DT_NORDIC_NRF_UARTE_UART_2_RX_PIN) #define DT_NORDIC_NRF_UARTE_UART_2_RX_PIN NRF_UARTE_PSEL_DISCONNECTED #endif UART_NRF_UARTE_DEVICE(2); #endif /* CONFIG_UART_2_NRF_UARTE */ #ifdef CONFIG_UART_3_NRF_UARTE #if defined(DT_NORDIC_NRF_UARTE_UART_3_RTS_PIN) && \ defined(DT_NORDIC_NRF_UARTE_UART_3_CTS_PIN) #define UARTE_3_CONFIG_RTS_CTS 1 #endif #if !defined(DT_NORDIC_NRF_UARTE_UART_3_RX_PIN) #define DT_NORDIC_NRF_UARTE_UART_3_RX_PIN NRF_UARTE_PSEL_DISCONNECTED #endif UART_NRF_UARTE_DEVICE(3); #endif /* CONFIG_UART_3_NRF_UARTE */