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

Using serial port with free RTOS - receive issues

Hello,

I would like to use the serial port library with free RTOS. I read several threads that timeouts do not work when using free RTOS. So I tried to use the lib without it.

I always try to read one byte (in an own task). It works in general but every other byte I get wrong (something between 0xE0 and 0xFF). I use a serial terminal to send some keyboard keys.

I am using SDK Version 15.3 with the PCA10056.

NRF_SERIAL_DRV_UART_CONFIG_DEF(m_uarte0_drv_config,
                      RX_PIN_NUMBER,ARDUINO_SCL_PIN,
                      RTS_PIN_NUMBER, CTS_PIN_NUMBER,
                      NRF_UART_HWFC_DISABLED, NRF_UART_PARITY_EXCLUDED,
                      NRF_UART_BAUDRATE_38400,
                      UART_DEFAULT_CONFIG_IRQ_PRIORITY);

#define SERIAL_FIFO_TX_SIZE 128
#define SERIAL_FIFO_RX_SIZE 128

NRF_SERIAL_QUEUES_DEF(serial0_queues, SERIAL_FIFO_TX_SIZE, SERIAL_FIFO_RX_SIZE);


#define SERIAL_BUFF_TX_SIZE 1
#define SERIAL_BUFF_RX_SIZE 1

NRF_SERIAL_BUFFERS_DEF(serial0_buffs, SERIAL_BUFF_TX_SIZE, SERIAL_BUFF_RX_SIZE);



NRF_SERIAL_CONFIG_DEF(serial0_config, NRF_SERIAL_MODE_DMA,
                      &serial0_queues, &serial0_buffs, NULL, NULL);


NRF_SERIAL_UART_DEF(serial0_uarte, 0);


// Task method
void UART_Read_E10_Task()
{
  char c;
  ret_code_t ret;

  while(true)
  {
    ret = nrf_serial_read(&serial0_uarte, &c, sizeof(c), NULL,0);
    if (ret == NRF_SUCCESS)
    {
   
    NRF_LOG_DEBUG("READ E10 %c %i %i",c,c)   
    }
  }
}

Does anyone know what I am doing wrong? Or does anyone have the same problem?

The best would be a working example using both UARTs with free RTOS...

Thanks,

Andreas

Parents Reply Children
  • Hi! Yes, I am asking this again, because it did not work out. I did as I was told in the other issue and use none blocking read (seems that sdk does not work with blocking mode). But there I get this issue, that every other received byte is trash. I am not getting anywhere on myself. So I thought maybe someone can help or has a working example...

    EDIT: I added a event handler and I get  "NRF_SERIAL_EVENT_DRV_ERR" events. Why?

    EDIT 2: I got the bllinky free rtos sample to use UART. When I set a timeout (e. g. 5000 ms) it gets the bytes but the timeout does never expire. When bytes are receveived, they are right. When I use timeout of 0 the method returns imemdiatly but sometimes with wrong bytes. Here's the code:

    /**
     * Copyright (c) 2015 - 2019, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    /** @file
     * @defgroup blinky_example_main main.c
     * @{
     * @ingroup blinky_example_freertos
     *
     * @brief Blinky FreeRTOS Example Application main file.
     *
     * This file contains the source code for a sample application using FreeRTOS to blink LEDs.
     *
     */
    
    #include <stdbool.h>
    #include <stdint.h>
    
    #include "FreeRTOS.h"
    #include "task.h"
    #include "timers.h"
    #include "bsp.h"
    #include "nordic_common.h"
    #include "nrf_drv_clock.h"
    #include "sdk_errors.h"
    #include "app_error.h"
    #include "nrf_serial.h"
    
    #if LEDS_NUMBER <= 2
    #error "Board is not equipped with enough amount of LEDs"
    #endif
    
    #define TASK_DELAY        200           /**< Task delay. Delays a LED0 task for 200 ms */
    #define TIMER_PERIOD      1000          /**< Timer period. LED1 timer will expire after 1000 ms */
    
    TaskHandle_t  led_toggle_task_handle;   /**< Reference to LED0 toggling FreeRTOS task. */
    TimerHandle_t led_toggle_timer_handle;  /**< Reference to LED1 toggling FreeRTOS timer. */
    
    NRF_SERIAL_DRV_UART_CONFIG_DEF(m_uarte0_drv_config,
                          RX_PIN_NUMBER, TX_PIN_NUMBER,
                         //   NRF_GPIO_PIN_MAP(0,22),NRF_GPIO_PIN_MAP(0,24),                    
                          RTS_PIN_NUMBER, CTS_PIN_NUMBER,
                          NRF_UART_HWFC_DISABLED, NRF_UART_PARITY_EXCLUDED,
                          NRF_UART_BAUDRATE_38400,
                          UART_DEFAULT_CONFIG_IRQ_PRIORITY);
    
    
    #define SERIAL_FIFO_TX_SIZE 32
    #define SERIAL_FIFO_RX_SIZE 32
    
    NRF_SERIAL_QUEUES_DEF(serial0_queues, SERIAL_FIFO_TX_SIZE, SERIAL_FIFO_RX_SIZE);
    
    #define SERIAL_BUFF_TX_SIZE 1
    #define SERIAL_BUFF_RX_SIZE 1
    
    NRF_SERIAL_BUFFERS_DEF(serial0_buffs, SERIAL_BUFF_TX_SIZE, SERIAL_BUFF_RX_SIZE);
    
    NRF_SERIAL_CONFIG_DEF(serial0_config, NRF_SERIAL_MODE_DMA,
                          &serial0_queues, &serial0_buffs, NULL, NULL);
    NRF_SERIAL_UART_DEF(serial0_uarte, 0);
    
    
    /**@brief LED0 task entry function.
     *
     * @param[in] pvParameter   Pointer that will be used as the parameter for the task.
     */
    static void led_toggle_task_function (void * pvParameter)
    {
     ret_code_t ret;
        UNUSED_PARAMETER(pvParameter);
    
       ret = nrf_serial_init(&serial0_uarte, &m_uarte0_drv_config, &serial0_config);
        APP_ERROR_CHECK(ret);
    
    
        static char tx_message[] = "Hello nrf_serial!\n\r";
    
        ret = nrf_serial_write(&serial0_uarte,
                               tx_message,
                               strlen(tx_message),
                               NULL,
                               NRF_SERIAL_MAX_TIMEOUT);
        (void)nrf_serial_flush(&serial0_uarte, 0);
    
    char c = 'a';
        while (true)
        {
            bsp_board_led_invert(BSP_BOARD_LED_0);
    
            ret = nrf_serial_read(&serial0_uarte, &c, sizeof(c), NULL, 5000);
            if (ret != NRF_SUCCESS)
            {
                continue;
            }
            (void)nrf_serial_write(&serial0_uarte, &c, sizeof(c), NULL, 0);
            (void)nrf_serial_flush(&serial0_uarte, 0);
    
          
    
    
            /* Tasks must be implemented to never return... */
        }
    }
    
    /**@brief The function to call when the LED1 FreeRTOS timer expires.
     *
     * @param[in] pvParameter   Pointer that will be used as the parameter for the timer.
     */
    static void led_toggle_timer_callback (void * pvParameter)
    {
        UNUSED_PARAMETER(pvParameter);
        bsp_board_led_invert(BSP_BOARD_LED_1);
    }
    
    int main(void)
    {
        ret_code_t err_code;
    
    
    
        /* Initialize clock driver for better time accuracy in FREERTOS */
        err_code = nrf_drv_clock_init();
        APP_ERROR_CHECK(err_code);
    
    
       // Initializ
        //nrf_drv_clock_lfclk_request(NULL);
        
        
    
        /* Configure LED-pins as outputs */
        bsp_board_init(BSP_INIT_LEDS);
    
        /* Create task for LED0 blinking with priority set to 2 */
        UNUSED_VARIABLE(xTaskCreate(led_toggle_task_function, "LED0", configMINIMAL_STACK_SIZE + 200, NULL, 2, &led_toggle_task_handle));
    
        /* Start timer for LED1 blinking */
        led_toggle_timer_handle = xTimerCreate( "LED1", TIMER_PERIOD, pdTRUE, NULL, led_toggle_timer_callback);
        UNUSED_VARIABLE(xTimerStart(led_toggle_timer_handle, 0));
    
        /* Activate deep sleep mode */
        SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
    
        /* Start FreeRTOS scheduler. */
        vTaskStartScheduler();
    
        while (true)
        {
            /* FreeRTOS should not be here... FreeRTOS goes back to the start of stack
             * in vTaskStartScheduler function. */
        }
    }
    
    /**
     *@}
     **/
    

  • Hi,

    I don't have an explanation for this right now. However, the NRF_SERIAL_EVENT_DRV_ERR is caused by an error in / error detected by the driver. Can you try to track down this error in the driver? Perhaps start with a breakpoint around the calls to nrf_uarte_errorsrc_get_and_clear() on line 477 and 545 in nrfx_uarte.c in SDK 15.3. Is that relevant? If so, what is the value of the ERRORSRC?

  • I think we should focus on the timeout first. In "nrf_serial_read" method of "nrf_serial.c" the timeout never expires:

     do
        {
            size_t rcnt = serial_rx(p_serial, p_buff, left);
            left -= rcnt;
            p_buff += rcnt;
            if (!left)
            {
                break;
            }
    
            if (tout_ctx.expired) // NEVER EXPIRES
            {
                if (p_serial->p_ctx->p_config->mode != NRF_SERIAL_MODE_POLLING)
                {
                    nrf_drv_uart_rx_abort(&p_serial->instance);
                }
                break;
            }
    
            sleep_handler(p_serial);
        } while (1);

  • Hi,

    I don't have any idea, to be honest. Can you upload a completed project so that I can test on a PCA10056 on my side? Please provide instructions on how to test to reproduce the issue.

  • Hi,

    Thank you for your support. 

    Attached is the example I am talking about. I am using SES with PCA10056. If you run the example you should see that the first call to "nrf_serial_read "does not timeout untill a byte is sent  (I tested with a serial terminal, baud rate 38400).. after the first byte is read the method does return with an error...

    blinky_freertos - Sample.7z

Related