This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

FreeRTOS with libuarte: incompatibility between app_timer and app_timer_freertos?

Hello,

I intend to use libuarte under FreeRTOS together with the SoftDevice (SDK 17.1.0). An app_timer is used for the RX timeout. I think there might be an incompatibility problem between app_timer and app_timer_freertos.

My application initializes the libuarte as follows:

NRF_LIBUARTE_ASYNC_DEFINE( xLibUarteCOM0, 0, 1, NRF_LIBUARTE_PERIPHERAL_NOT_USED, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 255, 3 );
xErrCode = nrf_libuarte_async_init( ( nrf_libuarte_async_t * )&xLibUarteCOM0, &nrf_libuarte_async_config, pvUartEvtHandler, ( void * )pxLibUarte );

The macro NRF_LIBUARTE_ASYNC_DEFINE creates xLibUarteCOM0 as follows:

static const nrf_libuarte_async_t xLibUarteCOM0 = 
{ 
	.p_rx_pool = &xLibUarteCOM0_rx_pool, 
	.p_rx_queue = &xLibUarteCOM0_rxdata_queue, 
	.p_rtc = 0, 
	.p_timer = 0, 
	.p_app_timer = &xLibUarteCOM0_app_timer, 
	.p_app_timer_ctrl_blk = &xLibUarteCOM0_app_timer_ctrl_blk, 
	.p_libuarte = &xLibUarteCOM0_libuarte, 
	.p_ctrl_blk = &xLibUarteCOM0ctrl_blk, 
	.rx_buf_size = 255, 
}; 

with p_app_timer_t being a pointer to (a pointer to) a variable of type app_timer_t:

static const app_timer_id_t xLibUarteCOM0_app_timer = &xLibUarteCOM0_app_timer_data; 

typedef struct
{
	nrf_sortlist_item_t         list_item;     /**< Token used by sortlist. */
	uint64_t                    end_val;       /**< RTC counter value when timer expires or @ref APP_TIMER_IDLE_VAL. */
	uint32_t                    repeat_period; /**< Repeat period (0 if single shot mode). */
	app_timer_timeout_handler_t handler;       /**< User handler. */
	void *                      p_context;     /**< User context. */
	NRF_LOG_INSTANCE_PTR_DECLARE(p_log)        /**< Pointer to instance of the logger object (Conditionally compiled). */
} app_timer_t;

The structure is then initialized by the macro as:

static app_timer_t xLibUarteCOM0_app_timer_data = 
{ 
	.end_val = 0xFFFFFFFFFFFFFFFFULL, 
}; 

In the FreeRTOS version of app_timer_create() called from nrf_libuarte_async_init(), xLibUarteCOM0_app_timer_data gets overlaid by a different structure. It is recasted to app_timer_info_t:

app_timer_info_t * pinfo = (app_timer_info_t*)(*p_timer_id);

/**@brief This structure keeps information about osTimer.*/
typedef struct
{
	void                      * argument;
	TimerHandle_t               osHandle;
	app_timer_timeout_handler_t func;
	/**
	 * This member is to make sure that timer function is only called if timer is running.
	 * FreeRTOS may have timer running even after stop function is called,
	 * because it processes commands in Timer task and stopping function only puts command into the queue. */
	bool                        active;
	bool                        single_shot;
}app_timer_info_t;

Without further initialization of the structure, app_timer_create() then checks the value of pinfo->active and fails with NRF_ERROR_INVALID_STATE if true.

The pinfo->active variable, however, is part of the pre-initialized 64-bit end_val and has the value 0xff which evaluates to true (!= 0). Hence, the initialization fails.

A possible work-around (although not very clean) is to initialize end_val with 0:

app_timer_t *p_xLibUarteCOM0_app_timer_data = *xLibUarteCOM0.p_app_timer;
p_xLibUarteCOM0_app_timer_data->end_val = 0x0ULL;

Does my analysis sound corrected or is there a another issue somewhere?

Thanks,

Norbert

Parents
  • Hi,

    You cannot use app_timer as it is as app_timer uses RTC1 which is the already used by freertos to keep its internal timers uptodate. If you want to use app_timer and app_timer_freertos together, you need to change the freertos to use the different timer. This is easy to achieve if you change the external\freertos\portable\CMSIS\nrf51\portmacro_cmsis.h from

    #define portNRF_RTC_REG        NRF_RTC1
    to 
    #define portNRF_RTC_REG        NRF_RTC2
    and also change
    #define portNRF_RTC_IRQn       RTC1_IRQn 
    to
    #define portNRF_RTC_IRQn       RTC2_IRQn
  • Hi Susheel,

    Sorry, I am a bit confused. By telling libuarte to use app_timer, I thought it really uses the FreeRTOS version of it (app_timer_freertos) which is clocked by the FreeRTOS systick.

    At least that is what I am trying to achieve. If it is not correct what I am doing, then how do I configure libuarte to use app_timer_freertos? NRF_LIBUARTE_ASYNC_DEFINE only proposes TIMER (HW), RTC (HW) or app_timer.

    Thanks

  • Since Freertos is using RTC1 by default, you can give NRF_CLI_LIBUARTE_TIMEOUT_RTC_INSTANCE as 2 inside NRF_LIBUARTE_ASYNC_DEFINE. I haven't tried the freertos libuarte myself, but if the libuarte has done all this correct with taking this RTC instance as a configurable thing, then it should work.

Reply
  • Since Freertos is using RTC1 by default, you can give NRF_CLI_LIBUARTE_TIMEOUT_RTC_INSTANCE as 2 inside NRF_LIBUARTE_ASYNC_DEFINE. I haven't tried the freertos libuarte myself, but if the libuarte has done all this correct with taking this RTC instance as a configurable thing, then it should work.

Children
No Data
Related