void UART0_IRQHandler(void) { if (nrf_uart_int_enable_check(NRF_UART0, NRF_UART_INT_MASK_ERROR) && nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_ERROR)) { nrf_uart_event_clear(NRF_UART0, NRF_UART_EVENT_ERROR); } if (nrf_uart_int_enable_check(NRF_UART0, NRF_UART_INT_MASK_RXDRDY) && nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_RXDRDY)) { rt_hw_serial_isr(working_cfg->serial, RT_SERIAL_EVENT_RX_IND); } if (nrf_uart_int_enable_check(NRF_UART0, NRF_UART_INT_MASK_TXDRDY) && nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_TXDRDY)) { rt_hw_serial_isr(working_cfg->serial, RT_SERIAL_EVENT_TX_DONE); } if (nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_RXTO)) { rt_hw_serial_isr(working_cfg->serial, RT_SERIAL_EVENT_RX_TIMEOUT); } }
/** * @brief Output a character in polled mode. * * @param dev UART device struct * @param c Character to send * * @return Sent character */ static unsigned char uart_nrfx_poll_out(struct device *dev, unsigned char c) { /* The UART API dictates that poll_out should wait for the transmitter * to be empty before sending a character. However, without locking, * this introduces a rare yet possible race condition if the thread is * preempted between sending the byte and checking for completion. * Because of this race condition, the while loop has to be placed * after the write to TXD, and we can't wait for an empty transmitter * before writing. This is a trade-off between losing a byte once in a * blue moon against hanging up the whole thread permanently */ /* reset transmitter ready state */ nrf_uart_event_clear(NRF_UART0, NRF_UART_EVENT_TXDRDY); /* send a character */ nrf_uart_txd_set(NRF_UART0, (u8_t)c); /* Wait for transmitter to be ready */ while (!nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_TXDRDY)) { } return c; }
/** * Interrupt handler of UART0 peripherial. */ void UARTE0_UART0_IRQHandler(void) { // Check if any error has been detected. if (nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_ERROR)) { // Clear error event and ignore erronous byte in RXD register. nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_ERROR); nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_RXDRDY); } else if (nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_RXDRDY)) { // Clear RXDRDY event. nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_RXDRDY); // Read byte from the UART buffer. uint8_t byte = nrf_uart_rxd_get(UART_INSTANCE); if (!isRxBufferFull()) { sReceiveBuffer[sReceiveHead] = byte; sReceiveHead = (sReceiveHead + 1) % UART_RX_BUFFER_SIZE; otSysEventSignalPending(); } } if (nrf_uart_event_check(UART_INSTANCE, NRF_UART_EVENT_TXDRDY)) { // Clear TXDRDY event. nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_TXDRDY); // Send any more bytes if available or call application about TX done. if (sTransmitLength) { nrf_uart_txd_set(UART_INSTANCE, *sTransmitBuffer++); sTransmitLength--; } else { sTransmitDone = true; nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_STOPTX); otSysEventSignalPending(); } } }
nrfx_err_t nrfx_uart_tx(nrfx_uart_t const * p_instance, uint8_t const * p_data, size_t length) { uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; NRFX_ASSERT(p_cb->state == NRFX_DRV_STATE_INITIALIZED); NRFX_ASSERT(p_data); NRFX_ASSERT(length > 0); nrfx_err_t err_code; if (nrfx_uart_tx_in_progress(p_instance)) { err_code = NRFX_ERROR_BUSY; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } p_cb->tx_buffer_length = length; p_cb->p_tx_buffer = p_data; p_cb->tx_counter = 0; p_cb->tx_abort = false; NRFX_LOG_INFO("Transfer tx_len: %d.", p_cb->tx_buffer_length); NRFX_LOG_DEBUG("Tx data:"); NRFX_LOG_HEXDUMP_DEBUG(p_cb->p_tx_buffer, p_cb->tx_buffer_length * sizeof(p_cb->p_tx_buffer[0])); err_code = NRFX_SUCCESS; nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_TXDRDY); nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STARTTX); tx_byte(p_instance->p_reg, p_cb); if (p_cb->handler == NULL) { if (!tx_blocking(p_instance->p_reg, p_cb)) { // The transfer has been aborted. err_code = NRFX_ERROR_FORBIDDEN; } else { // Wait until the last byte is completely transmitted. while (!nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_TXDRDY)) {} nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPTX); } p_cb->tx_buffer_length = 0; } NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; }
/** Console I/O function */ static int uart_nrfx_err_check(struct device *dev) { u32_t error = 0; if (nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_ERROR)) { /* register bitfields maps to the defines in uart.h */ error = nrf_uart_errorsrc_get_and_clear(NRF_UART0); } return error; }
static int uart_nrfx_poll_in(struct device *dev, unsigned char *c) { if (!nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_RXDRDY)) { return -1; } /* Clear the interrupt */ nrf_uart_event_clear(NRF_UART0, NRF_UART_EVENT_RXDRDY); /* got a character */ *c = nrf_uart_rxd_get(NRF_UART0); return 0; }
/** Interrupt driven FIFO read function */ static int uart_nrfx_fifo_read(struct device *dev, u8_t *rx_data, const int size) { u8_t num_rx = 0; while ((size - num_rx > 0) && nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_RXDRDY)) { /* Clear the interrupt */ nrf_uart_event_clear(NRF_UART0, NRF_UART_EVENT_RXDRDY); /* Receive a character */ rx_data[num_rx++] = (u8_t)nrf_uart_rxd_get(NRF_UART0); } return num_rx; }
/** Interrupt driven FIFO fill function */ static int uart_nrfx_fifo_fill(struct device *dev, const u8_t *tx_data, int len) { u8_t num_tx = 0; while ((len - num_tx > 0) && nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_TXDRDY)) { /* Clear the interrupt */ nrf_uart_event_clear(NRF_UART0, NRF_UART_EVENT_TXDRDY); /* Send a character */ nrf_uart_txd_set(NRF_UART0, (u8_t)tx_data[num_tx++]); } return (int)num_tx; }
static bool tx_blocking(NRF_UART_Type * p_uart, uart_control_block_t * p_cb) { while (p_cb->tx_counter < p_cb->tx_buffer_length) { // Wait until the transmitter is ready to accept a new byte. // Exit immediately if the transfer has been aborted. while (!nrf_uart_event_check(p_uart, NRF_UART_EVENT_TXDRDY)) { if (p_cb->tx_abort) { return false; } } tx_byte(p_uart, p_cb); } return true; }
static int _uart_getc(struct rt_serial_device *serial) { int ch = -1; UART_CFG_T *instance = working_cfg; RT_ASSERT(serial != RT_NULL); if (serial->parent.user_data != RT_NULL) { instance = (UART_CFG_T*)serial->parent.user_data; } if (nrf_uart_event_check(instance->uart.reg.p_uart, NRF_UART_EVENT_RXDRDY)) { nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_RXDRDY); ch = (int)(nrf_uart_rxd_get(instance->uart.reg.p_uart)); } return ch; }
static int _uart_putc(struct rt_serial_device *serial, char c) { UART_CFG_T *instance = working_cfg; RT_ASSERT(serial != RT_NULL); if (serial->parent.user_data != RT_NULL) { instance = (UART_CFG_T*)serial->parent.user_data; } nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_TXDRDY); nrf_uart_task_trigger(instance->uart.reg.p_uart, NRF_UART_TASK_STARTTX); nrf_uart_txd_set(instance->uart.reg.p_uart, (uint8_t)c); while (!nrf_uart_event_check(instance->uart.reg.p_uart, NRF_UART_EVENT_TXDRDY)) { } return 1; }
static void uart_irq_handler(NRF_UART_Type * p_uart, uart_control_block_t * p_cb) { if (nrf_uart_int_enable_check(p_uart, NRF_UART_INT_MASK_ERROR) && nrf_uart_event_check(p_uart, NRF_UART_EVENT_ERROR)) { nrfx_uart_event_t event; nrf_uart_event_clear(p_uart, NRF_UART_EVENT_ERROR); NRFX_LOG_DEBUG("Event: %s.", EVT_TO_STR(NRF_UART_EVENT_ERROR)); nrf_uart_int_disable(p_uart, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR); if (!p_cb->rx_enabled) { nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STOPRX); } event.type = NRFX_UART_EVT_ERROR; event.data.error.error_mask = nrf_uart_errorsrc_get_and_clear(p_uart); event.data.error.rxtx.bytes = p_cb->rx_buffer_length; event.data.error.rxtx.p_data = p_cb->p_rx_buffer; // Abort transfer. p_cb->rx_buffer_length = 0; p_cb->rx_secondary_buffer_length = 0; p_cb->handler(&event,p_cb->p_context); } else if (nrf_uart_int_enable_check(p_uart, NRF_UART_INT_MASK_RXDRDY) && nrf_uart_event_check(p_uart, NRF_UART_EVENT_RXDRDY)) { rx_byte(p_uart, p_cb); if (p_cb->rx_buffer_length == p_cb->rx_counter) { if (p_cb->rx_secondary_buffer_length) { uint8_t * p_data = p_cb->p_rx_buffer; size_t rx_counter = p_cb->rx_counter; // Switch to secondary buffer. p_cb->rx_buffer_length = p_cb->rx_secondary_buffer_length; p_cb->p_rx_buffer = p_cb->p_rx_secondary_buffer; p_cb->rx_secondary_buffer_length = 0; p_cb->rx_counter = 0; rx_done_event(p_cb, rx_counter, p_data); } else { if (!p_cb->rx_enabled) { nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STOPRX); } nrf_uart_int_disable(p_uart, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR); p_cb->rx_buffer_length = 0; rx_done_event(p_cb, p_cb->rx_counter, p_cb->p_rx_buffer); } } } if (nrf_uart_event_check(p_uart, NRF_UART_EVENT_TXDRDY)) { if (p_cb->tx_counter < p_cb->tx_buffer_length && !p_cb->tx_abort) { tx_byte(p_uart, p_cb); } else { nrf_uart_event_clear(p_uart, NRF_UART_EVENT_TXDRDY); if (p_cb->tx_buffer_length) { tx_done_event(p_cb, p_cb->tx_buffer_length); } } } if (nrf_uart_event_check(p_uart, NRF_UART_EVENT_RXTO)) { nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXTO); // RXTO event may be triggered as a result of abort call. In th if (p_cb->rx_enabled) { nrf_uart_task_trigger(p_uart, NRF_UART_TASK_STARTRX); } if (p_cb->rx_buffer_length) { p_cb->rx_buffer_length = 0; rx_done_event(p_cb, p_cb->rx_counter, p_cb->p_rx_buffer); } } }
bool nrfx_uart_rx_ready(nrfx_uart_t const * p_instance) { return nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_RXDRDY); }
nrfx_err_t nrfx_uart_rx(nrfx_uart_t const * p_instance, uint8_t * p_data, size_t length) { uart_control_block_t * p_cb = &m_cb[p_instance->drv_inst_idx]; NRFX_ASSERT(m_cb[p_instance->drv_inst_idx].state == NRFX_DRV_STATE_INITIALIZED); NRFX_ASSERT(p_data); NRFX_ASSERT(length > 0); nrfx_err_t err_code; bool second_buffer = false; if (p_cb->handler) { nrf_uart_int_disable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR); } if (p_cb->rx_buffer_length != 0) { if (p_cb->rx_secondary_buffer_length != 0) { if (p_cb->handler) { nrf_uart_int_enable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR); } err_code = NRFX_ERROR_BUSY; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } second_buffer = true; } if (!second_buffer) { p_cb->rx_buffer_length = length; p_cb->p_rx_buffer = p_data; p_cb->rx_counter = 0; p_cb->rx_secondary_buffer_length = 0; } else { p_cb->p_rx_secondary_buffer = p_data; p_cb->rx_secondary_buffer_length = length; } NRFX_LOG_INFO("Transfer rx_len: %d.", length); if ((!p_cb->rx_enabled) && (!second_buffer)) { rx_enable(p_instance); } if (p_cb->handler == NULL) { nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_RXTO); bool rxrdy; bool rxto; bool error; do { do { error = nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_ERROR); rxrdy = nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_RXDRDY); rxto = nrf_uart_event_check(p_instance->p_reg, NRF_UART_EVENT_RXTO); } while ((!rxrdy) && (!rxto) && (!error)); if (error || rxto) { break; } rx_byte(p_instance->p_reg, p_cb); } while (p_cb->rx_buffer_length > p_cb->rx_counter); p_cb->rx_buffer_length = 0; if (error) { err_code = NRFX_ERROR_INTERNAL; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } if (rxto) { err_code = NRFX_ERROR_FORBIDDEN; NRFX_LOG_WARNING("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; } if (p_cb->rx_enabled) { nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STARTRX); } else { // Skip stopping RX if driver is forced to be enabled. nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STOPRX); } } else { nrf_uart_int_enable(p_instance->p_reg, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR); } err_code = NRFX_SUCCESS; NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code)); return err_code; }
/** Interrupt driven receiver ready function */ static int uart_nrfx_irq_rx_ready(struct device *dev) { return nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_RXDRDY); }
/** Interrupt driven transfer empty function */ static int uart_nrfx_irq_tx_complete(struct device *dev) { return !nrf_uart_event_check(NRF_UART0, NRF_UART_EVENT_TXDRDY); }