Ejemplo n.º 1
0
/**@brief GPIOTE event handler.
 *
 * @param[in] event_pins_low_to_high   Mask telling which pin(s) generated an event from low->high.
 * @param[in] event_pins_high_to_low   Mask telling which pin(s) generated an event from high->low.
 */
static void gpiote_uart_event_handler(uint32_t event_pins_low_to_high,
                                      uint32_t event_pins_high_to_low)
{
    if ((event_pins_high_to_low & event_pins_low_to_high & m_pin_cts_mask) != 0)
    {
        // We have an indication from GPIOTE that the CTS pin has toggled high->low and low->high.
        // If this occurs, we must read the active pins in the GPIOTE module ourself.
        uint32_t active_pins;
        uint32_t err_code;

        err_code = app_gpiote_pins_state_get(m_gpiote_uid, &active_pins);
        if (err_code != NRF_SUCCESS)
        {
            // Pin reading was not possible, even though an event from GPIOTE was received that the
            // CTS pin toggled. If pin double toggled but status cannot be fetched we silently
            // return and keep the current UART status as-is.
            return;
        }
        event_pins_low_to_high &= active_pins;
        event_pins_high_to_low &= ~active_pins;
    }

    if ((event_pins_high_to_low & m_pin_cts_mask) != 0)
    {
        on_uart_event(ON_CTS_LOW);
    }
    else if ((event_pins_low_to_high & m_pin_cts_mask) != 0)
    {
        on_uart_event(ON_CTS_HIGH);
    }
    else
    {
        // Do nothing, as the CTS pin didn't toggle.
    }
}
Ejemplo n.º 2
0
/**@brief Function for the GPIOTE event handler.
 */
static void gpiote_uart_event_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
    if (nrf_drv_gpiote_in_is_set(pin))
    {
        on_uart_event(ON_CTS_HIGH);
    }
    else
    {
        on_uart_event(ON_CTS_LOW);
    }
}
Ejemplo n.º 3
0
uint32_t app_uart_close(uint16_t app_uart_uid)
{
    if (app_uart_uid < UART_INSTANCE_GPIOTE_BASE)
    {
        on_uart_event(ON_UART_CLOSE);
        return NRF_SUCCESS;
    }

    on_uart_event(ON_UART_CLOSE);

    nrf_drv_gpiote_in_uninit(NRF_UART0->PSELCTS);
    return NRF_SUCCESS;
}
Ejemplo n.º 4
0
/**@brief Function for the UART Interrupt handler.
 *
 * @details UART interrupt handler to process TX Ready when TXD is available, RX Ready when a byte
 *          is received, or in case of error when receiving a byte.
 */
void UART0_IRQHandler(void)
{
    // Handle reception
    if (NRF_UART0->EVENTS_RXDRDY != 0)
    {
        uint32_t err_code;

        // Clear UART RX event flag
        NRF_UART0->EVENTS_RXDRDY = 0;

        // Write received byte to FIFO
        err_code = app_fifo_put(&m_rx_fifo, (uint8_t)NRF_UART0->RXD);
        if (err_code != NRF_SUCCESS)
        {
            app_uart_evt_t app_uart_event;
            app_uart_event.evt_type          = APP_UART_FIFO_ERROR;
            app_uart_event.data.error_code   = err_code;
            m_event_handler(&app_uart_event);
        }
        // Notify that new data is available if this was first byte put in the buffer.
        else if (FIFO_LENGTH(m_rx_fifo) == 1)
        {
            app_uart_evt_t app_uart_event;
            app_uart_event.evt_type = APP_UART_DATA_READY;
            m_event_handler(&app_uart_event);
        }
        else
        {
            // Do nothing, only send event if first byte was added or overflow in FIFO occurred.
        }
    }

    // Handle transmission.
    if (NRF_UART0->EVENTS_TXDRDY != 0)
    {
        // Clear UART TX event flag.
        NRF_UART0->EVENTS_TXDRDY = 0;
        on_uart_event(ON_TX_READY);
    }

    // Handle errors.
    if (NRF_UART0->EVENTS_ERROR != 0)
    {
        uint32_t       error_source;
        app_uart_evt_t app_uart_event;

        // Clear UART ERROR event flag.
        NRF_UART0->EVENTS_ERROR = 0;

        // Clear error source.
        error_source        = NRF_UART0->ERRORSRC;
        NRF_UART0->ERRORSRC = error_source;

        app_uart_event.evt_type                 = APP_UART_COMMUNICATION_ERROR;
        app_uart_event.data.error_communication = error_source;

        m_event_handler(&app_uart_event);
    }
}
Ejemplo n.º 5
0
uint32_t app_uart_put(uint8_t byte)
{
    uint32_t err_code;

    err_code = app_fifo_put(&m_tx_fifo, byte);
    on_uart_event(ON_UART_PUT);
    return err_code;
}
Ejemplo n.º 6
0
uint32_t app_uart_put(uint8_t byte)
{
    uint32_t err_code = NRF_SUCCESS;

    if (m_current_state != UART_READY)
    {
      err_code = NRF_ERROR_NO_MEM;
    }
    else
    {
      m_tx_byte = byte;
      on_uart_event(ON_UART_PUT);
    }

    return err_code;
}
Ejemplo n.º 7
0
/**@brief Function for handling the UART Interrupt.
 *
 * @details UART interrupt handler to process TX Ready when TXD is available, RX Ready when a byte
 *          is received, or in case of error when receiving a byte.
 */
void UART_IRQHandler(void)
{
    // Handle reception
    if ((NRF_UART0->EVENTS_RXDRDY != 0) && (NRF_UART0->INTENSET & UART_INTENSET_RXDRDY_Msk))
    {
        app_uart_evt_t app_uart_event;

        // Clear UART RX event flag
        NRF_UART0->EVENTS_RXDRDY  = 0;
        m_rx_byte                 = (uint8_t)NRF_UART0->RXD;
        app_uart_event.evt_type   = APP_UART_DATA;
        app_uart_event.data.value = m_rx_byte;
        m_event_handler(&app_uart_event);
    }

    // Handle transmission.
    if ((NRF_UART0->EVENTS_TXDRDY != 0) && (NRF_UART0->INTENSET & UART_INTENSET_TXDRDY_Msk))
    {
        // Clear UART TX event flag.
        NRF_UART0->EVENTS_TXDRDY = 0;
        on_uart_event(ON_TX_READY);
    }

    // Handle errors.
    if ((NRF_UART0->EVENTS_ERROR != 0) && (NRF_UART0->INTENSET & UART_INTENSET_ERROR_Msk))
    {
        uint32_t       error_source;
        app_uart_evt_t app_uart_event;

        // Clear UART ERROR event flag.
        NRF_UART0->EVENTS_ERROR = 0;

        // Clear error source.
        error_source        = NRF_UART0->ERRORSRC;
        NRF_UART0->ERRORSRC = error_source;

        app_uart_event.evt_type                 = APP_UART_COMMUNICATION_ERROR;
        app_uart_event.data.error_communication = error_source;

        m_event_handler(&app_uart_event);
    }
}
Ejemplo n.º 8
0
uint32_t app_uart_init(const app_uart_comm_params_t * p_comm_params,
                       app_uart_buffers_t           * p_buffers,
                       app_uart_event_handler_t       event_handler,
                       app_irq_priority_t             irq_priority,
                       uint16_t                     * p_app_uart_uid)
{
    uint32_t err_code;

    m_current_state = UART_OFF;
    m_event_handler = event_handler;
    m_rx_byte       = BYTE_INVALID;


    // Configure RX and TX pins.
    nrf_gpio_pin_set(p_comm_params->tx_pin_no);
    nrf_gpio_cfg_output(p_comm_params->tx_pin_no);
    nrf_gpio_cfg_input(p_comm_params->rx_pin_no, NRF_GPIO_PIN_PULLUP);


    NRF_UART0->PSELTXD = p_comm_params->tx_pin_no;
    NRF_UART0->PSELRXD = p_comm_params->rx_pin_no;

    // Configure baud rate and parity.
    NRF_UART0->BAUDRATE = (p_comm_params->baud_rate << UART_BAUDRATE_BAUDRATE_Pos);

    if (p_comm_params->use_parity)
    {
        NRF_UART0->CONFIG = (UART_CONFIG_PARITY_Included << UART_CONFIG_PARITY_Pos);
    }
    else
    {
        NRF_UART0->CONFIG = (UART_CONFIG_PARITY_Excluded << UART_CONFIG_PARITY_Pos);
    }

    if (p_comm_params->flow_control == APP_UART_FLOW_CONTROL_LOW_POWER)
    {
        if (!nrf_drv_gpiote_is_init())
        {
            err_code = nrf_drv_gpiote_init();
            if (err_code != NRF_SUCCESS)
            {
                return err_code;
            }
        }

        // Configure hardware flow control.
        nrf_drv_gpiote_out_config_t rts_config = GPIOTE_CONFIG_OUT_SIMPLE(true);
        err_code = nrf_drv_gpiote_out_init(p_comm_params->rts_pin_no, &rts_config);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }

        NRF_UART0->PSELCTS = UART_PIN_DISCONNECTED;
        NRF_UART0->PSELRTS = p_comm_params->rts_pin_no;
        NRF_UART0->CONFIG |= (UART_CONFIG_HWFC_Enabled << UART_CONFIG_HWFC_Pos);

        // Setup the gpiote to handle pin events on cts-pin.
        // For the UART we want to detect both low->high and high->low transitions in order to
        // know when to activate/de-activate the TX/RX in the UART.
        // Configure pin.
        nrf_drv_gpiote_in_config_t cts_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
        err_code = nrf_drv_gpiote_in_init(p_comm_params->cts_pin_no, &cts_config, gpiote_uart_event_handler);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }

        nrf_drv_gpiote_in_event_enable(p_comm_params->cts_pin_no, true);

        // UART CTS pin is active when low.
        if (nrf_drv_gpiote_in_is_set(p_comm_params->cts_pin_no))
        {
            on_uart_event(ON_CTS_HIGH);
        }
        else
        {
            on_uart_event(ON_CTS_LOW);
        }
    }
    else if (p_comm_params->flow_control == APP_UART_FLOW_CONTROL_ENABLED)
    {
        uart_standard_flow_control_init(p_comm_params);
        m_current_state = UART_READY;
    }
    else
    {
        uart_no_flow_control_init();
        m_current_state = UART_READY;
    }
    if (*p_app_uart_uid == UART_INSTANCE_ID_INVALID)
    {
        *p_app_uart_uid = m_instance_counter++;
    }

    // Enable UART interrupt
    NRF_UART0->INTENCLR = 0xffffffffUL;
    NRF_UART0->INTENSET = (UART_INTENSET_RXDRDY_Set << UART_INTENSET_RXDRDY_Pos) |
                          (UART_INTENSET_TXDRDY_Set << UART_INTENSET_TXDRDY_Pos) |
                          (UART_INTENSET_ERROR_Set << UART_INTENSET_ERROR_Pos);

    NVIC_ClearPendingIRQ(UART_IRQ);
    NVIC_SetPriority(UART_IRQ, irq_priority);
    NVIC_EnableIRQ(UART_IRQ);

    return NRF_SUCCESS;
}
Ejemplo n.º 9
0
uint32_t app_uart_init(const app_uart_comm_params_t * p_comm_params,
                             app_uart_buffers_t *     p_buffers,
                             app_uart_event_handler_t event_handler,
                             app_irq_priority_t       irq_priority)
{
    uint32_t err_code;
    uint32_t gpiote_high_pins;
    uint32_t gpiote_pin_low_high_mask = 0;
    uint32_t gpiote_pin_high_low_mask = 0;

    m_current_state = UART_OFF;
    m_event_handler = event_handler;

    // Configure buffer RX buffer.
    err_code = app_fifo_init(&m_rx_fifo, p_buffers->rx_buf, p_buffers->rx_buf_size);
    if (err_code != NRF_SUCCESS)
    {
        // Propagate error code.
        return err_code;
    }

    // Configure buffer TX buffer.
    err_code = app_fifo_init(&m_tx_fifo, p_buffers->tx_buf, p_buffers->tx_buf_size);
    if (err_code != NRF_SUCCESS)
    {
        // Propagate error code.
        return err_code;
    }

    // Configure RX and TX pins.
    nrf_gpio_cfg_output(p_comm_params->tx_pin_no);
    nrf_gpio_cfg_input(p_comm_params->rx_pin_no, NRF_GPIO_PIN_NOPULL);

    NRF_UART0->PSELTXD = p_comm_params->tx_pin_no;
    NRF_UART0->PSELRXD = p_comm_params->rx_pin_no;

    // Configure baud rate and parity.
    NRF_UART0->BAUDRATE = (p_comm_params->baud_rate << UART_BAUDRATE_BAUDRATE_Pos);
    if (p_comm_params->use_parity)
    {
        NRF_UART0->CONFIG = (UART_CONFIG_PARITY_Included << UART_CONFIG_PARITY_Pos);
    }
    else
    {
        NRF_UART0->CONFIG = (UART_CONFIG_PARITY_Excluded << UART_CONFIG_PARITY_Pos);
    }

    if (p_comm_params->use_hardware_flow_control)
    {
        // Configure hardware flow control.
        nrf_gpio_cfg_output(p_comm_params->rts_pin_no);
        NRF_GPIO->OUT = 1 << p_comm_params->rts_pin_no;

        NRF_UART0->PSELCTS  = UART_PIN_DISCONNECTED;
        NRF_UART0->PSELRTS  = p_comm_params->rts_pin_no;
        NRF_UART0->CONFIG  |= (UART_CONFIG_HWFC_Enabled << UART_CONFIG_HWFC_Pos);

        // Setup the gpiote to handle pin events on cts-pin.
        // For the UART we want to detect both low->high and high->low transistions in order to
        // know when to activate/deactivate the TX/RX in the UART.
        // Configure pin.
        m_pin_cts_mask = (1 << p_comm_params->cts_pin_no);
        GPIO_PIN_CONFIG(p_comm_params->cts_pin_no,
                        GPIO_PIN_CNF_DIR_Input,
                        GPIO_PIN_CNF_INPUT_Connect,
                        GPIO_PIN_CNF_PULL_Disabled,
                        GPIO_PIN_CNF_DRIVE_S0S1,
                        GPIO_PIN_CNF_SENSE_Low);

        gpiote_pin_low_high_mask = (1 << p_comm_params->cts_pin_no);
        gpiote_pin_high_low_mask = (1 << p_comm_params->cts_pin_no);

        err_code = app_gpiote_user_register(&m_gpiote_uid,
                                            gpiote_pin_low_high_mask,
                                            gpiote_pin_high_low_mask,
                                            gpiote_uart_event_handler);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }

        err_code = app_gpiote_pins_state_get(m_gpiote_uid, &gpiote_high_pins);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }

        err_code = app_gpiote_user_enable(m_gpiote_uid);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }

        // UART CTS pin is active when low.
        if ((gpiote_high_pins & (1 << p_comm_params->cts_pin_no)) == 0)
        {
            on_uart_event(ON_CTS_LOW);
        }
        else
        {
            on_uart_event(ON_CTS_HIGH);
        }
    }
    else
    {
        uart_no_flow_control_init();
        m_current_state = UART_READY;
    }

    // Enable UART interrupt
    NRF_UART0->INTENCLR = 0xffffffffUL;
    NRF_UART0->INTENSET = (UART_INTENSET_RXDRDY_Set << UART_INTENSET_RXDRDY_Pos) |
                          (UART_INTENSET_TXDRDY_Set << UART_INTENSET_TXDRDY_Pos) |
                          (UART_INTENSET_ERROR_Set << UART_INTENSET_ERROR_Pos);

    NVIC_ClearPendingIRQ(UART0_IRQn);
    NVIC_SetPriority(UART0_IRQn, irq_priority);
    NVIC_EnableIRQ(UART0_IRQn);

    return NRF_SUCCESS;
}
Ejemplo n.º 10
0
uint32_t app_uart_close(uint16_t app_uart_uid)
{
    on_uart_event(ON_UART_CLOSE);

    return 0;
}