How can I implement UART RX PPI with GPIO?

Hi, I use nRF52840, with SDK 15.3.0

I would like to toggle LED every time receive 1 byte to UART.

So I wrote down the code.

static void ppi_init()
{
uint32_t err_code;

uint32_t uart_event_addr;
uint32_t gpio_task_addr;

nrf_ppi_channel_t ppi_channel_uart_gpio_toggle;

err_code = nrf_drv_ppi_init();
if((err_code != 0) && (err_code != NRF_ERROR_MODULE_ALREADY_INITIALIZED))
{
APP_ERROR_CHECK(err_code);
}

nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(false);

err_code = nrf_drv_gpiote_out_init(LED_pin, &config);
APP_ERROR_CHECK(err_code);

err_code = nrf_drv_ppi_channel_alloc(&ppi_channel_uart_gpio_toggle);
APP_ERROR_CHECK(err_code);

uart_event_addr = nrfx_uart_event_address_get(&uart1_inst, NRF_UART_TASK_STARTRX);
gpio_task_addr = nrfx_gpiote_out_task_addr_get(LED_pin);

err_code = nrfx_ppi_channel_assign(ppi_channel_uart_gpio_toggle, uart_event_addr, gpio_task_addr);
APP_ERROR_CHECK(err_code);

err_code = nrf_drv_ppi_channel_enable(ppi_channel_uart_gpio_toggle);
APP_ERROR_CHECK(err_code);

nrf_drv_gpiote_out_task_enable(LED_pin);

}

Thanks in advance!

Parents Reply Children
  • Hello,

    Here the related UART code initial part, IRQ handler, main

    void UART_dataHandler(void)
    {
        static uint8_t databuff;
        printf("%x\r\n", databuff);
    }
    
    void UART_idleHandler(void)
    {
    }
    /*    UART ISR    */
    void UART_IRQ_handler(const nrfx_uart_event_t * p_event, void * p_context)
    {
        switch(p_event -> type)
        {
            case NRFX_UART_EVT_RX_DONE:
                UART_dataHandler();
                break;
            case NRFX_UART_EVT_TX_DONE:
                break;
            case NRFX_UART_EVT_ERROR:
                NRF_LOG_INFO("INVALID_IRQ\r\n");
                UART_idleHandler();
                break;
        }
    }
    
    void uart1_init(void)
    {
        uint32_t err_code;
    
        nrfx_uart_config_t uart1_config = {TX_PIN,
                                           RX_PIN,
                                           CTS_PIN,
                                           RTS_PIN,
                                           NULL,
                                           NRF_UART_HWFC_DISABLED,
                                           NRF_UART_PARITY_EXCLUDED,
                                           UART_BR_115200,
                                           6};
    
        nrfx_uart_init(&uart1_inst, &uart1_config, UART_IRQ_handler);
        nrf_uart_int_enable(NRF_UART0, NRF_UART_INT_MASK_ERROR | NRF_UART_INT_MASK_RXDRDY);
        nrf_uart_event_clear(NRF_UART0, NRF_UART_EVENT_ERROR | NRF_UART_EVENT_RXDRDY);
        //nrf_uart_task_trigger(NRF_UART0, NRF_UART_TASK_STARTRX);
    }
    
    static void ppi_init()
    {
            uint32_t err_code;
    
            uint32_t uart_event_addr;
            uint32_t gpio_task_addr;
            
            nrf_ppi_channel_t ppi_channel_uart_gpio_toggle;
    
            err_code = nrf_drv_ppi_init();
            if((err_code != 0) && (err_code != NRF_ERROR_MODULE_ALREADY_INITIALIZED))
            {
                APP_ERROR_CHECK(err_code);
            }
    
            nrf_drv_gpiote_out_config_t config = GPIOTE_CONFIG_OUT_TASK_TOGGLE(true);
    
            err_code = nrfx_gpiote_out_init(LED_1, &config);
            APP_ERROR_CHECK(err_code);
    
            err_code = nrfx_ppi_channel_alloc(&ppi_channel_uart_gpio_toggle);
            APP_ERROR_CHECK(err_code);
    
            uart_event_addr = nrfx_uart_event_address_get(&uart1_inst, NRF_UART_EVENT_RXDRDY);
            gpio_task_addr = nrfx_gpiote_out_task_addr_get(LED_1);
            
            err_code = nrfx_ppi_channel_assign(ppi_channel_uart_gpio_toggle, uart_event_addr, gpio_task_addr);
            APP_ERROR_CHECK(err_code);
    
            err_code = nrfx_ppi_channel_enable(ppi_channel_uart_gpio_toggle);
            APP_ERROR_CHECK(err_code);
    
            nrfx_gpiote_out_task_enable(LED_1);
    }
    
    int main(void)
    {
        uart1_init();
        
        ppi_init();
        nrfx_uart_rx_enable(&uart1_inst);
        
        while(1)
        {}
    }

  • Hello,

    I see the problem now. To enable reception you have to provide the driver with a application buffer to hold store the received bytes. You also have to repeat this after receiving the NRFX_UART_EVT_RX_DONE event.

    Like this:

    static uint8_t m_rx_buffer[1];
    
    void UART_dataHandler(void)
    {
        ...
        nrfx_uart_rx(&uart1_inst, m_rx_buffer, sizeof(m_rx_buffer));
    }
    
    int main(void)
    {
        uart1_init();
        
        ppi_init();
        nrfx_uart_rx(&uart1_inst, m_rx_buffer, sizeof(m_rx_buffer));
        
        while(1)
        {}
    }

    You may also refer to the app_uart library implementation used by ble_app_uart to see how the driver APIs are used there.

Related