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

app_timer with scheduler

I want to use nested app_timer instances:  I am gathering data on a repeating app_timer (app_timer_1) which fires say every 10ms.  One of my sensors providing the data requires some time delay between requesting the data and it being ready, so I want to use a second app_timer (app_timer_2) to provide a low-power delay function. The delay can be of the order of 5ms.

Since app_timer_2 is being stated from app_timer_1 it isnt running because they have the same interrupt priority but timer_2 is running in the context of timer_1.  I believe the way to get around this is to use the scheduler.  However despite spending some time searching I cant find any examples of how to do this.  Documentation seems a bit sparse, and in places confusing.

For example, app_timer use in scheduler example here: https://devzone.nordicsemi.com/tutorials/b/software-development-kit/posts/scheduler-tutorial uses deprecated functions: app_timer_appsh no longer exists (I am using SDK 14.2).

Any help much appreciated!

  • Hey Barnaby,

    It sounds like you need to start app_timer_2 from app_timer_1s event handler. You do not need to use the scheduler at all. 

    Cheers,

    Håkon.

  • Hey Hakon,

    That is what I am doing, but app_timer_2 event never fires.  Reading around it, I though that was because it is running in context of app_timer_1, and since they have same priority it will never work.  Did I get it wrong?

    I can try making a simple example to see if problem is elsewhere.

    Thanks again!

    Barney

  • App timer is non blocking, but you need to exit app_timer_1s event handler before the 5ms is up. If app_timer_2 is still not firing then there something wrong in they way you initialize the app_timer_2. Do you have som sample code to show me?

  • Hi Hakon,

    Sorry for the delayed response.  

    Here is example code that demonstrates my problem.  I am running a function using timer_1, but in this function I need to implement a delay for which I am using timer_2.  Timer_2 delay causes code to hang as the event of timer 2 never gets called:

    static void power_manage(void){
        uint32_t err_code = sd_app_evt_wait();
        APP_ERROR_CHECK(err_code);
    }
    
    // Main timer object
    APP_TIMER_DEF(timer_1);
    //Timer function for low power delay:
    APP_TIMER_DEF(timer_2);
    
    /* 
     * Low power delay function stuff:
     */
    static bool lp_delay_flag = false; /**< Flag to indicate le delay is running. */
    
     static void lp_delay_evt(void * p_context){
        lp_delay_flag = false;
    }
     
    static void lp_delay_ms(int ms_delay)
    {
        uint32_t err_code;
    		uint32_t tick_count = APP_TIMER_TICKS(ms_delay);
        lp_delay_flag = true;
        err_code = app_timer_start(timer_1, tick_count, NULL);
        APP_ERROR_CHECK(err_code);
        while(lp_delay_flag)
        {
            power_manage();
        }   
    }
    
    static ret_code_t lp_delay_timer_init()
    {
    	ret_code_t err_code = app_timer_create(&timer_2, APP_TIMER_MODE_SINGLE_SHOT, lp_delay_evt);
    	return err_code;
    }
    
    
    /* 
     * Main timer function stuff:
     */
    
    void timer_1_handler(void * p_context)
    {
    	NRF_LOG_INFO("Timer_1_Handler start.");
    	NRF_LOG_FLUSH();
    	// Aim of following is to create a delay using minimal power. 
    	// PROGRAM HANGS ON THIS NEXT LINE - CALLBACK EVENT NEVER CALLED
    	lp_delay_ms(TIMER_2_DELAY_MS);
    	
    	NRF_LOG_INFO("Timer_1_Handler end.");
    	NRF_LOG_FLUSH();
    }
    
     void main_timer_init()
    {
      ret_code_t err_code;
    	
    	err_code = app_timer_create(&timer_1, APP_TIMER_MODE_REPEATED, timer_1_handler);
    	APP_ERROR_CHECK(err_code);
    
    	err_code = app_timer_start(timer_1, APP_TIMER_TICKS(TIMER_1_DELAY_MS), NULL);
    	APP_ERROR_CHECK(err_code);
    }
    
    
    /* 
     * Initial setup functions:
     */
    
    static void lfclk_request(void)
    {
        uint32_t err_code = nrf_drv_clock_init();
        APP_ERROR_CHECK(err_code);
        nrf_drv_clock_lfclk_request(NULL);
    }
    
    static void utils_setup(void)
    {
    		ret_code_t err_code = NRF_LOG_INIT(NULL);
    		APP_ERROR_CHECK(err_code);
    
    		err_code = app_timer_init();
    		APP_ERROR_CHECK(err_code);
    
    		err_code = nrf_pwr_mgmt_init();
    		APP_ERROR_CHECK(err_code);
    
    		NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    
    int main(void)
    {
    	//Initialise logging, clock etc.
    	utils_setup();
    	//Start low frequency clock:
    	lfclk_request();
    	//Initialise delay timer:
    	lp_delay_timer_init();
    	//Initialise and start main timer:
    	main_timer_init();
    	
    	while (true)
    	{
    		nrf_pwr_mgmt_run();
    	}
    }

  • Why do you start another delay after the first one, can't you just use one? 

Related