This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Stuck application when implementing UART

Hi,

I have PCA10028 board, and I'm trying to implement UART send/receive. I've searched for the problem here but could not find a solution for it.

My uart init function is(most of the code is copy/paste):

static void uart_init(void)
{
    uint32_t				err_code;
		
		app_uart_comm_params_t params;
    memset(&params, 0, sizeof(params));
    
    params.baud_rate = UART_BAUDRATE_BAUDRATE_Baud115200;
    params.tx_pin_no = TX_PIN_NUMBER;
    params.rx_pin_no = RX_PIN_NUMBER;
    params.use_parity = false;
    params.flow_control = APP_UART_FLOW_CONTROL_DISABLED;
    
    static uint8_t rx_buffer[UART_RX_BUFFER_SIZE];
    static uint8_t tx_buffer[UART_TX_BUFFER_SIZE];
    app_uart_buffers_t buffers;
    buffers.rx_buf = rx_buffer;
    buffers.rx_buf_size = UART_RX_BUFFER_SIZE;
    buffers.tx_buf = tx_buffer;
    buffers.tx_buf_size = UART_TX_BUFFER_SIZE;
    
    err_code = app_uart_init(&params, &buffers, uart_event_handle, APP_IRQ_PRIORITY_LOW, NULL);
    APP_ERROR_CHECK(err_code);
}

This is event handler:

void uart_event_handle(app_uart_evt_t * p_event)
{
    static uint8_t data_array[BLE_MAX_DATA_LEN];
    static uint8_t index = 0;
    uint32_t       err_code;

    switch (p_event->evt_type)
    {
        case APP_UART_DATA_READY:
            UNUSED_VARIABLE(app_uart_get(&data_array[index]));
            index++;

            if ((data_array[index - 1] == '\n') || (index >= (BLE_MAX_DATA_LEN)))
            {
								// TODO: Check sending of data here
                //err_code = ble_nus_string_send(&m_nus, data_array, index);
                if (err_code != NRF_ERROR_INVALID_STATE)
                {
                    APP_ERROR_CHECK(err_code);
                }
                
                index = 0;
            }
            break;

        case APP_UART_COMMUNICATION_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_communication);
            break;

        case APP_UART_FIFO_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_code);
            break;

        default:
            break;
    }
}

And this is my write function:

void app_uart_put_string(const char* s)
{
    uint8_t len = strlen(s);
    for (uint8_t i = 0; i < len; i++)
    {
	while (app_uart_put(s[i]) != NRF_SUCCESS);
        //err_code = app_uart_put(s[i]);
        //APP_ERROR_CHECK(err_code);
    }
}

When this is used: err_code = app_uart_put(s[i]); APP_ERROR_CHECK(err_code); and while (app_uart_put(s[i]) != NRF_SUCCESS) is omitted, this function sends continuously bytes which are not in the char* s. If I send 1 byte it sends it normally and I can see it on the terminal, but when I try to send 2 bytes it sends gibberish continuously.

So I've searched for solution and found: while (app_uart_put(s[i]) != NRF_SUCCESS).

Unfortunately, I've used it and now my PCA board is stuck. I can't flash the new code, can't debug, can't erase with nrfjprog --eraseall and can't erase it in nRFgo Studio. It's not recognized at all.

1.) How can I "unstuck" my board? 2.) Is there an implementation of UART which works? I need a simple sending and receiving of bytes over UART, at higer speeds (baud 115200 or above). I've also found fifo implementation but can't get it to send or receive. I use S110.

Thank you!

Regards, Mladen

Parents
  • Hi,

    When you run this code:

    for (uint8_t i = 0; i < len; i++)
    {
        err_code = app_uart_put(s[i]);
        APP_ERROR_CHECK(err_code);
    }
    

    app_uart_put() will return the error code NRF_ERROR_NO_MEM after you have transmitted your first byte. I.e. you are putting bytes in the buffer too fast and the UART doesn't have the time to process all of them. When err_code is then passed on to APP_ERROR_CHECK() you will end up in the function app_error_handler() defined in app_error.c. Finally, since you (probably) didn't have DEBUG defined in your project the error handler will do a system reset of your chip. This is why it looked like the UART was spewing out an endless stream of bytes, while in reality it transmitted just one byte, but then the code was reset and this continued in an endless loop.

    This code works however:

    for (uint8_t i = 0; i < len; i++)
    {
        while (app_uart_put(s[i]) != NRF_SUCCESS);
    }
    

    because this code puts a byte in the TX buffer and waits for the byte to be transmitted before it loads the buffer with another byte. The code is not ideal, however, since it will wait literally forever and block your code if something goes wrong in app_uart_put().

    Your solution should be to use the app_uart_fifo.c driver instead of the simpler app_uart.c driver. Then you can use the first code and the driver will handle the buffer issue.

    EDIT There is an example in "your_SDK_folder\examples\peripheral\uart" using the fifo drivers. To use it in your own project you will need to add the following .c-files to your project driver and library folder:

    image description

    Just right click on e.g. nRF_Drivers and click "Add existing files...", navigate to "your_SDK_folder\components\drivers_nrf\uart", and add the file you need. Make sure to delete app_uart.c from the library folder if it is present. You should use app_uart.c or app_uart_fifo.c.

  • Can you please tell me where can I find this driver? I mean, is there an example with app_uart_fifo driver which sends and receives multiple bytes?

    Thank you!

    Edit: Awesome! This helps a lot!

Reply Children
No Data
Related