Beware that this post is related to an SDK in maintenance mode
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

How Do I Re-Initialise a Timer?

Hi, nRF newbie here, forgive me if I'm being dim. I've searched the devzone, can't see obvious answers.

nRF52840, SDK 17.0.2, Nordic SES 5.30a, using nrfx_* drivers

I'm using one of the timers for bitbashing a bespoke serial bus, and want to re-initialise it each time I use it. I'm using nrfx_timer_init(), NRFX_TIMER_DEFAULT_CONFIG, with interrupt handler, and various compare channels set using nrfx_timer_compare().

However when called a second time, nrfx_timer_init() fails with err_code of NRFX_ERROR_INVALID_STATE, because p_cb->state != NRFX_DRV_STATE_UNINITIALIZED
Which of course it won't be, it is already initialised. Why won't nrfx_timer_init() let me re-initialise it?

If I just do nrfx_timer_clear() instead of the re-init, all runs fine, but I would be happier doing a full init to ensure it is configured for the next step.

I tried adding "if (nrfx_timer_is_enabled()) nrfx_timer_uninit();" before nrfx_timer_init(), but both those funcs have
NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
Why are these asserts here?

This is my init code
static void init_sbus_timer(void)
{
   uint32_t err_code = NRF_SUCCESS;
   nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG;
   err_code = nrfx_timer_init(&TIMER_SBUS, &timer_cfg, timsbus_interrupt);
   APP_ERROR_CHECK(err_code);
}

Many thanks

  • Hi,

    Which of course it won't be, it is already initialised. Why won't nrfx_timer_init() let me re-initialise it?

    NRFX_ERROR_INVALID_STATE returned by nrfx_timer_init() means the instance is already initialized. It only allows initializing if the instance must not have already been initialized. That can avoid initializing the using timer by accident. 

        if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
        {
            err_code = NRFX_ERROR_INVALID_STATE;
            NRFX_LOG_WARNING("Function: %s, error code: %s.",
                             __func__,
                             NRFX_LOG_ERROR_STRING_GET(err_code));
            return err_code;
        }
    

    I tried adding "if (nrfx_timer_is_enabled()) nrfx_timer_uninit();" before nrfx_timer_init(), but both those funcs have
    NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED);
    Why are these asserts here?

    nrfx_timer_uninit() doesn't check the value of state itself, but it does call nrfx_timer_disable(). nrfx_timer_disable() and nrfx_timer_is_enabled() do an NRFX_ASSERT(m_cb[p_instance->instance_id].state != NRFX_DRV_STATE_UNINITIALIZED). If you call nrfx_timer_uninit() and nrfx_timer_is_enabled() on an uninitialized driver instance, you will get assert. 

    -Amanda H.

  • Hi Amanda

    Thanks for the reply

    OK, so I have to uninitialise the timer before I reinitialise it...

    But my second question still stands - how do I do that, if I don't know whether it is initialised?

    As I said, I tried "if (nrfx_timer_is_enabled()) nrfx_timer_uninit();" but that gives an assert if it is not initialised.

    As you said, I can't just call nrfx_timer_uninit() as that gives an assert if it is not initialised.

    I need a if(nrfx_timer_is_init()) but that doesn't exist

    Surely I'm not alone in wanting to do this? I normally re-init timers all the time on other platforms (e.g. STM32s). Maybe I should just write my own timer_init()...

    Cheers

  • Hi, 

    Because NRFX_ERROR_INVALID_STATE returned by nrfx_timer_init() means the instance is already initialized, I think you can initiate the time nrfx_timer_init() in the sub-function, and uninitialise and initialise again if it gets the NRFX_ERROR_INVALID_STATE. 

    -Amanda H.

  • Thanks for the reply

    Are you suggesting I do this:-

    static void init_sbus_timer(void)
    {
       uint32_t err_code = NRF_SUCCESS;
       nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG;
       err_code = nrfx_timer_init(&TIMER_SBUS, &timer_cfg, timsbus_interrupt);
       if (err_code == NRFX_ERROR_INVALID_STATE)
       {
          err_code = nrfx_timer_uninit(&TIMER_SBUS);
          APP_ERROR_CHECK(err_code);
          err_code = nrfx_timer_init(&TIMER_SBUS, &timer_cfg, timsbus_interrupt);
       }
       APP_ERROR_CHECK(err_code);
    }
    

    To be honest that seems a little clunky, I might just write my own init routine

Related