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:

Fullscreen
1
2
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 );
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

The macro NRF_LIBUARTE_ASYNC_DEFINE creates xLibUarteCOM0 as follows:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
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,
};
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
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;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

The structure is then initialized by the macro as:

Fullscreen
1
2
3
4
static app_timer_t xLibUarteCOM0_app_timer_data =
{
.end_val = 0xFFFFFFFFFFFFFFFFULL,
};
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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:

Fullscreen
1
2
app_timer_t *p_xLibUarteCOM0_app_timer_data = *xLibUarteCOM0.p_app_timer;
p_xLibUarteCOM0_app_timer_data->end_val = 0x0ULL;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

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

Thanks,

Norbert