예제 #1
0
파일: uart.c 프로젝트: nodish/openthread
otError otPlatUartEnable(void)
{
    otError error = OT_ERROR_NONE;

    otEXPECT_ACTION(sUartEnabled == false, error = OT_ERROR_ALREADY);

    // Set up TX and RX pins.
    nrf_gpio_pin_set(UART_PIN_TX);
    nrf_gpio_cfg_output(UART_PIN_TX);
    nrf_gpio_cfg_input(UART_PIN_RX, NRF_GPIO_PIN_NOPULL);
    nrf_uart_txrx_pins_set(UART_INSTANCE, UART_PIN_TX, UART_PIN_RX);

#if (UART_HWFC == NRF_UART_HWFC_ENABLED)
    // Set up CTS and RTS pins.
    nrf_gpio_cfg_input(UART_PIN_CTS, NRF_GPIO_PIN_NOPULL);
    nrf_gpio_pin_set(UART_PIN_RTS);
    nrf_gpio_cfg_output(UART_PIN_RTS);
    nrf_uart_hwfc_pins_set(UART_INSTANCE, UART_PIN_RTS, UART_PIN_CTS);
#endif

    // Configure baudrate.
    nrf_uart_baudrate_set(UART_INSTANCE, UART_BAUDRATE);

    // Configure parity and hardware flow control.
    nrf_uart_configure(UART_INSTANCE, UART_PARITY, UART_HWFC);

    // Clear UART specific events.
    nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_TXDRDY);
    nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_ERROR);
    nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_RXDRDY);

    // Enable interrupts for TX.
    nrf_uart_int_enable(UART_INSTANCE, NRF_UART_INT_MASK_TXDRDY);

    // Enable interrupts for RX.
    nrf_uart_int_enable(UART_INSTANCE, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR);

    // Configure NVIC to handle UART interrupts.
    NVIC_SetPriority(UART_IRQN, UART_IRQ_PRIORITY);
    NVIC_ClearPendingIRQ(UART_IRQN);
    NVIC_EnableIRQ(UART_IRQN);

    // Start HFCLK
    nrf_drv_clock_hfclk_request(NULL);

    while (!nrf_drv_clock_hfclk_is_running())
    {
    }

    // Enable UART instance, and start RX on it.
    nrf_uart_enable(UART_INSTANCE);
    nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_STARTRX);

    sUartEnabled = true;

exit:
    return error;
}
예제 #2
0
static void interrupts_enable(nrfx_uart_t const * p_instance,
                              uint8_t             interrupt_priority)
{
    nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_TXDRDY);
    nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_RXTO);
    nrf_uart_int_enable(p_instance->p_reg, NRF_UART_INT_MASK_TXDRDY |
                                           NRF_UART_INT_MASK_RXTO);
    NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number((void *)p_instance->p_reg),
                          interrupt_priority);
    NRFX_IRQ_ENABLE(nrfx_get_irq_number((void *)p_instance->p_reg));
}
예제 #3
0
static void rx_byte(NRF_UART_Type * p_uart, uart_control_block_t * p_cb)
{
    if (!p_cb->rx_buffer_length)
    {
        nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXDRDY);
        // Byte received when buffer is not set - data lost.
        (void) nrf_uart_rxd_get(p_uart);
        return;
    }
    nrf_uart_event_clear(p_uart, NRF_UART_EVENT_RXDRDY);
    p_cb->p_rx_buffer[p_cb->rx_counter] = nrf_uart_rxd_get(p_uart);
    p_cb->rx_counter++;
}
예제 #4
0
static void tx_byte(NRF_UART_Type * p_uart, uart_control_block_t * p_cb)
{
    nrf_uart_event_clear(p_uart, NRF_UART_EVENT_TXDRDY);
    uint8_t txd = p_cb->p_tx_buffer[p_cb->tx_counter];
    p_cb->tx_counter++;
    nrf_uart_txd_set(p_uart, txd);
}
예제 #5
0
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);
    }
}
예제 #6
0
/**
 * @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;
}
예제 #7
0
파일: uart.c 프로젝트: nodish/openthread
/**
 * 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();
        }
    }
}
예제 #8
0
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;
}
예제 #9
0
파일: uart.c 프로젝트: mtornblad/openthread
void nrf5UartInit(void)
{
    // Set up TX and RX pins.
    nrf_gpio_pin_set(UART_PIN_TX);
    nrf_gpio_cfg_output(UART_PIN_TX);
    nrf_gpio_cfg_input(UART_PIN_RX, NRF_GPIO_PIN_NOPULL);
    nrf_uart_txrx_pins_set(UART_INSTANCE, UART_PIN_TX, UART_PIN_RX);

#if (UART_HWFC == NRF_UART_HWFC_ENABLED)
    // Set up CTS and RTS pins.
    nrf_gpio_cfg_input(UART_PIN_CTS, NRF_GPIO_PIN_NOPULL);
    nrf_gpio_pin_set(UART_PIN_RTS);
    nrf_gpio_cfg_output(UART_PIN_RTS);
    nrf_uart_hwfc_pins_set(UART_INSTANCE, UART_PIN_RTS, UART_PIN_CTS);
#endif

    // Configure baudrate.
    nrf_uart_baudrate_set(UART_INSTANCE, UART_BAUDRATE);

    // Configure parity and hardware flow control.
    nrf_uart_configure(UART_INSTANCE, UART_PARITY, UART_HWFC);

    // Clear UART specific events.
    nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_TXDRDY);
    nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_ERROR);
    nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_RXDRDY);

    // Enable interrupts for TX.
    nrf_uart_int_enable(UART_INSTANCE, NRF_UART_INT_MASK_TXDRDY);

    // Enable interrupts for RX.
    nrf_uart_int_enable(UART_INSTANCE, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_ERROR);

    // Configure NVIC to handle UART interrupts.
    NVIC_SetPriority(UART_IRQN, UART_IRQ_PRIORITY);
    NVIC_ClearPendingIRQ(UART_IRQN);
    NVIC_EnableIRQ(UART_IRQN);
}
예제 #10
0
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;
}
예제 #11
0
/** 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;
}
예제 #12
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;
}
예제 #13
0
파일: uart.c 프로젝트: nodish/openthread
otError otPlatUartSend(const uint8_t *aBuf, uint16_t aBufLength)
{
    otError error = OT_ERROR_NONE;

    otEXPECT_ACTION(sTransmitBuffer == NULL, error = OT_ERROR_BUSY);

    // Set up transmit buffer and its size without counting first triggered byte.
    sTransmitBuffer = aBuf;
    sTransmitLength = aBufLength - 1;

    // Initiate Transmission process.
    nrf_uart_event_clear(UART_INSTANCE, NRF_UART_EVENT_TXDRDY);
    nrf_uart_txd_set(UART_INSTANCE, *sTransmitBuffer++);
    nrf_uart_task_trigger(UART_INSTANCE, NRF_UART_TASK_STARTTX);

exit:
    return error;
}
예제 #14
0
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;
}
예제 #15
0
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;
}
예제 #16
0
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;
}
예제 #17
0
static void rx_enable(nrfx_uart_t const * p_instance)
{
    nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_ERROR);
    nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_RXDRDY);
    nrf_uart_task_trigger(p_instance->p_reg, NRF_UART_TASK_STARTRX);
}
예제 #18
0
static rt_err_t _uart_cfg(struct rt_serial_device *serial, struct serial_configure *cfg)
{
    nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG;
    UART_CFG_T *instance = &uart0;

    RT_ASSERT(serial != RT_NULL);
    RT_ASSERT(cfg != RT_NULL);

    if (serial->parent.user_data != RT_NULL)
    {
        instance = (UART_CFG_T*)serial->parent.user_data;
    }

    nrf_uart_disable(instance->uart.reg.p_uart);

    switch (cfg->baud_rate)
    {
    case 115200:
        config.baudrate = NRF_UART_BAUDRATE_115200;
        break;

    case 9600:
        config.baudrate = NRF_UART_BAUDRATE_9600;
        break;

    default:
        config.baudrate = NRF_UART_BAUDRATE_115200;
        break;
    }

    if (cfg->parity == PARITY_NONE)
    {
        config.parity = NRF_UART_PARITY_EXCLUDED;
    }
    else
    {
        config.parity = NRF_UART_PARITY_INCLUDED;
    }

    config.hwfc = NRF_UART_HWFC_DISABLED;
    config.interrupt_priority = APP_IRQ_PRIORITY_LOWEST;
    config.pselcts = 0;
    config.pselrts = 0;
    config.pselrxd = instance->rx_pin;
    config.pseltxd = instance->tx_pin;

    nrf_gpio_pin_set(config.pseltxd);
    nrf_gpio_cfg_output(config.pseltxd);
    nrf_gpio_pin_clear(config.pseltxd);
    nrf_gpio_cfg_input(config.pselrxd, NRF_GPIO_PIN_NOPULL);
    nrf_uart_baudrate_set(instance->uart.reg.p_uart, config.baudrate);
    nrf_uart_configure(instance->uart.reg.p_uart, config.parity, config.hwfc);
    nrf_uart_txrx_pins_set(instance->uart.reg.p_uart, config.pseltxd, config.pselrxd);

    if (config.hwfc == NRF_UART_HWFC_ENABLED)
    {
        nrf_uart_hwfc_pins_set(instance->uart.reg.p_uart, config.pselrts, config.pselcts);
    }

    nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_TXDRDY);
    nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_RXDRDY);
    nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_RXTO);
    nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_ERROR);

    nrf_uart_int_enable(instance->uart.reg.p_uart, NRF_UART_INT_MASK_RXDRDY | NRF_UART_INT_MASK_RXTO | NRF_UART_INT_MASK_ERROR);
    nrf_drv_common_irq_enable(nrf_drv_get_IRQn((void *)instance->uart.reg.p_uart), config.interrupt_priority);
    nrf_uart_enable(instance->uart.reg.p_uart);
    // nrf_uart_task_trigger(instance->uart.reg.p_uart, NRF_UART_TASK_STARTRX);
    working_cfg = instance;
    return RT_EOK;
}
예제 #19
0
uint32_t nrfx_uart_errorsrc_get(nrfx_uart_t const * p_instance)
{
    nrf_uart_event_clear(p_instance->p_reg, NRF_UART_EVENT_ERROR);
    return nrf_uart_errorsrc_get_and_clear(p_instance->p_reg);
}
예제 #20
0
/**
 * @brief Initialize UART channel
 *
 * This routine is called to reset the chip in a quiescent state.
 * It is assumed that this function is called only once per UART.
 *
 * @param dev UART device struct
 *
 * @return 0 on success
 */
static int uart_nrfx_init(struct device *dev)
{
	struct device *gpio_dev;
	int err;

	gpio_dev = device_get_binding(CONFIG_GPIO_NRF5_P0_DEV_NAME);

	__ASSERT(gpio_dev,
		 "UART init failed. Cannot find %s",
		 CONFIG_GPIO_NRF5_P0_DEV_NAME);

	/* Setting default height state of the TX PIN to avoid glitches
	 * on the line during peripheral activation/deactivation.
	 */
	gpio_pin_write(gpio_dev, CONFIG_UART_0_NRF_TX_PIN, 1);
	gpio_pin_configure(gpio_dev,
			   CONFIG_UART_0_NRF_TX_PIN,
			   GPIO_DIR_OUT);
	gpio_pin_configure(gpio_dev,
			   CONFIG_UART_0_NRF_RX_PIN,
			   GPIO_DIR_IN);

	nrf_uart_txrx_pins_set(NRF_UART0,
			       CONFIG_UART_0_NRF_TX_PIN,
			       CONFIG_UART_0_NRF_RX_PIN);

#ifdef CONFIG_UART_0_NRF_FLOW_CONTROL
	/* Setting default height state of the RTS PIN to avoid glitches
	 * on the line during peripheral activation/deactivation.
	 */
	gpio_pin_write(gpio_dev, CONFIG_UART_0_NRF_RTS_PIN, 1);
	gpio_pin_configure(gpio_dev,
			   CONFIG_UART_0_NRF_RTS_PIN,
			   GPIO_DIR_OUT);
	gpio_pin_configure(gpio_dev,
			   CONFIG_UART_0_NRF_CTS_PIN,
			   GPIO_DIR_IN);
	nrf_uart_hwfc_pins_set(NRF_UART0,
			       CONFIG_UART_0_NRF_RTS_PIN,
			       CONFIG_UART_0_NRF_CTS_PIN);
#endif /* CONFIG_UART_0_NRF_FLOW_CONTROL */

	nrf_uart_configure(NRF_UART0,
#ifdef CONFIG_UART_0_NRF_PARITY_BIT
			   NRF_UART_PARITY_INCLUDED,
#else
			   NRF_UART_PARITY_EXCLUDED,
#endif /* CONFIG_UART_0_NRF_PARITY_BIT */
#ifdef CONFIG_UART_0_NRF_FLOW_CONTROL
			   NRF_UART_HWFC_ENABLED);
#else
			   NRF_UART_HWFC_DISABLED);
#endif /* CONFIG_UART_0_NRF_PARITY_BIT */

	/* Set baud rate */
	err = baudrate_set(dev, CONFIG_UART_0_BAUD_RATE);
	if (err) {
		return err;
	}

	/* Enable receiver and transmitter */
	nrf_uart_enable(NRF_UART0);

	nrf_uart_event_clear(NRF_UART0, NRF_UART_EVENT_TXDRDY);
	nrf_uart_event_clear(NRF_UART0, NRF_UART_EVENT_RXDRDY);

	nrf_uart_task_trigger(NRF_UART0, NRF_UART_TASK_STARTTX);
	nrf_uart_task_trigger(NRF_UART0, NRF_UART_TASK_STARTRX);

#ifdef CONFIG_UART_INTERRUPT_DRIVEN

	IRQ_CONNECT(NRFX_IRQ_NUMBER_GET(NRF_UART0),
		    CONFIG_UART_0_IRQ_PRI,
		    uart_nrfx_isr,
		    DEVICE_GET(uart_nrfx_uart0),
		    0);
	irq_enable(NRFX_IRQ_NUMBER_GET(NRF_UART0));
#endif

	return 0;
}
예제 #21
0
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);
        }
    }
}
예제 #22
0
static rt_err_t _uart_ctrl(struct rt_serial_device *serial, int cmd, void *arg)
{
    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;
    }

    switch (cmd)
    {
        /* disable interrupt */
    case RT_DEVICE_CTRL_CLR_INT:
        nrf_uart_task_trigger(instance->uart.reg.p_uart, NRF_UART_TASK_STOPRX);
        nrf_uart_int_disable(instance->uart.reg.p_uart, NRF_UART_INT_MASK_RXDRDY
                                                | NRF_UART_INT_MASK_RXTO
                                                | NRF_UART_INT_MASK_ERROR);
        nrf_drv_common_irq_disable(nrf_drv_get_IRQn((void *)instance->uart.reg.p_uart));
        break;

        /* enable interrupt */
    case RT_DEVICE_CTRL_SET_INT:
        nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_RXDRDY);
        nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_RXTO);
        nrf_uart_event_clear(instance->uart.reg.p_uart, NRF_UART_EVENT_ERROR);
        /* Enable RX interrupt. */
        nrf_uart_int_enable(instance->uart.reg.p_uart, NRF_UART_INT_MASK_RXDRDY
                                                | NRF_UART_INT_MASK_RXTO
                                                | NRF_UART_INT_MASK_ERROR);
        nrf_drv_common_irq_enable(nrf_drv_get_IRQn((void *)instance->uart.reg.p_uart), APP_IRQ_PRIORITY_LOWEST);
        nrf_uart_task_trigger(instance->uart.reg.p_uart, NRF_UART_TASK_STARTRX);
        break;

    case RT_DEVICE_CTRL_CUSTOM:
        if ((rt_uint32_t)(arg) == UART_CONFIG_BAUD_RATE_9600)
        {
            instance->serial->config.baud_rate = 9600;
            nrf_uart_baudrate_set(instance->uart.reg.p_uart, NRF_UART_BAUDRATE_9600);
        }
        else if ((rt_uint32_t)(arg) == UART_CONFIG_BAUD_RATE_115200)
        {
            instance->serial->config.baud_rate = 115200;
            nrf_uart_baudrate_set(instance->uart.reg.p_uart, NRF_UART_BAUDRATE_115200);
        }

        // _uart_cfg(instance->serial, &(instance->serial->config));
        // nrf_uart_task_trigger(instance->uart.reg.p_uart, NRF_UART_TASK_STARTRX);
        break;

    case RT_DEVICE_CTRL_PIN:
        if (working_cfg != instance)
        {
            _uart_cfg(instance->serial, &(instance->serial->config));
        }
        break;

    case RT_DEVICE_POWERSAVE:
        nrf_uart_disable(instance->uart.reg.p_uart);
        nrf_uart_txrx_pins_disconnect(instance->uart.reg.p_uart);
        nrf_gpio_pin_clear(instance->rx_pin);
        nrf_gpio_cfg_output(instance->rx_pin);
        nrf_gpio_pin_clear(instance->tx_pin);
        nrf_gpio_cfg_output(instance->tx_pin);
        break;

    case RT_DEVICE_WAKEUP:
        _uart_cfg(instance->serial, &(instance->serial->config));
        break;

    default:
        return RT_ERROR;
    }

    return RT_EOK;
}