nRF5 SDK is not maintained anymore
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Receiving for UART with FreeRTOS

Hello,

I have implemented a somewhat working RX algorithm for receiving data over UART but I'm looking for a good way to make it more robust. I haven't found any good answers to this in either the forum or the infocenter and I get a little bit confused regrading the driver setup.

My implementation:

  • Custom board using nRF52840
  • Using the nRF5 SDK v15.0.0.
  • Using FreeRTOS, built from the "ble_app_hrs_freertos"-example. (At the moment without BLE stack initialization.)
  • Implemented FreeRTOS task for handling UART communication.
  • Have a module connected over UART that use AT-commands.

Assumptions:

  • As it is AT-commands I always know the ending of the message, though I don't know the length as the reply to one command can be different.
    • An example is reading the ID which gives 24 bytes as answer. If there is a failure, the answer is simply "+ERR=x".
    • There is a response to every TX, thus I want to have RX after TX.

So far I have tried mostly with the "Serial port library" and I have tried using blocking-mode similar to:

uint32_t received_bytes = 0;
err = nrf_serial_write(&serial_uart, tx_tmp, tx_size, NULL, NRF_SERIAL_MAX_TIMEOUT);
err = nrf_serial_read(&serial_uart, rx_tmp, 50, &received_bytes, 100);

This does however only work for the first message. The second time I try with nrf_serial_read() I get an error as the handle for the timer is not null, somewhere around line 136 in app_timer_freertos.c (DUH, it is already created). For experimentation I changed to the following in app_timer_create() function in app_timer_freertos.c and now it works (even though I know it is a VERY ugly solution):

    if (pinfo->osHandle == NULL)
    {
        /* New timer is created */
        memset(pinfo, 0, sizeof(app_timer_info_t));

        if (mode == APP_TIMER_MODE_SINGLE_SHOT)
            timer_mode = pdFALSE;
        else
            timer_mode = pdTRUE;

        pinfo->func = timeout_handler;
        pinfo->osHandle = xTimerCreate(" ", 1000, timer_mode, pinfo, app_timer_callback);

        if (pinfo->osHandle == NULL)
            err_code = NRF_ERROR_NULL;
    }
    else
    {
        xTimerReset(pinfo->osHandle, 100);
        /* Timer cannot be reinitialized using FreeRTOS API */
        //return NRF_ERROR_INVALID_STATE;
    }

So is this a bug or am I using it totally wrong? Is the approach of using software timers good, or should I change to some other method?

Regards

Robert

Parents Reply
  • Hi,

    Since the original issue is still unresolved and if you think your issue matches the exact same description, then we can continue our discussion here.

    There were issues with nrf_serial working with freeRTOS that was mentioned in the known issues list for SDK15.x (check item 40. in the known issues list)

    I see that this was fixed in later SDKs internally but the module was removed for public in latest.

    The problem was that nrf_serial was trying to create too many timers which was turning out to be problematic with FreeRTOS.

    Can you please try to replace the components\libraries\serial\nrf_serial.c file with the attached one and see if it helps.

    Sorry for multiple edits, there is some issue with uploading this file

Children
Related