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