This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

app timer event handler never returns to main() while(1) loop to execute code.

I am attempting to use a one shot application timer.  This works fine when I use the event handler to perform a specific task toggle an LED for example.  But I would really like the time to call a set of functions that will execute a sizeable amount of code.  So I have attempted to use the handler to set a flag that will be used in the main loop in with an IF statement to execute this set of functions.  When I do this the event handler is called but I never return to the main while(1) loop to execute the IF statement.  If I add a nrf_delay_us statement inside the while(1) main loop then the code is executed as expected.  What am I missing?  Why does the delay help?  Code is shown below.

#include "nrf.h"
#include "nordic_common.h"
#include "boards.h"
#include "app_timer.h"
#include "nrf_drv_clock.h"
#include "nrf_gpio.h"
#include "nrf_delay.h"

// LED pin
#define LED_Pin1 17

// use a function to calculate the number of tick needed to
// create a delay of 100 millisec and store this value in LED_INTERVAL constant
#define LED_INTERVAL APP_TIMER_TICKS(50)

uint32_t count;
uint8_t timerExpired;
// For each application timer we need to create a handle which points to that instance
// so for evey application timer (Software timer) you create, you need to define a handle
// create a handle and name it as: m_app_timer_id
APP_TIMER_DEF(m_app_timer_id);

// its really important to initialize the clock other wise the app timer will not work
// so make sure you initialize it once in your code and if you are using a soft device
// then you don't need to initialize the clock as the soft device automatically initializes it.
static void lfclk_config(void)
{
// initialize the low power low frequency clock
ret_code_t err_code = nrf_drv_clock_init();
APP_ERROR_CHECK(err_code);

// request the lf clock to not to generate any events on ticks
// One tick = 1 value increment in the counter register
nrf_drv_clock_lfclk_request(NULL);

}


// create a simple handler function which will be called once the timer reaches its
// desired number of ticks value
static void app_timer_handler(void * p_context)
{
// Toggle the LED
timerExpired = true;
app_timer_start(m_app_timer_id, LED_INTERVAL, NULL);
return;
}

// a function to initialize the Application timers
static void timers_init(void)
{
// a variable to hold error value
ret_code_t err_code;

// Initialize the timer
err_code = app_timer_init();
APP_ERROR_CHECK(err_code);

// Create an application timer with the handle, mode and interrupt event handle function
err_code = app_timer_create(&m_app_timer_id, APP_TIMER_MODE_SINGLE_SHOT, app_timer_handler);
APP_ERROR_CHECK(err_code);
timerExpired = false;
}


/**
* @brief Function for application main entry.
*/
int main(void)
{
count = 0;

// initialize the gpio for led
nrf_gpio_cfg_output(LED_Pin1);

// call the function to initialize the clock
lfclk_config();
// initialize the timer by calling this function which is performing all the basic steps
timers_init();

// start the timer so that it can generate events on the desired tick value
uint32_t err_code = app_timer_start(m_app_timer_id, LED_INTERVAL, NULL);

while (true)
{


nrf_delay_us(10);    //CODE in if(timerExpired == true) expression runs with this statement , but does not when this is commented out.
count = count+1;
if(timerExpired == true)
{
timerExpired = false;
nrf_gpio_pin_toggle(LED_Pin1);
}
// Do nothing.
}
}
/** @} */

  • #include "nrf.h"
    #include "nordic_common.h"
    #include "boards.h"
    #include "app_timer.h"
    #include "nrf_drv_clock.h"
    #include "nrf_gpio.h"
    #include "nrf_delay.h"
    
    // LED pin 
    #define LED_Pin1 17
    
    // use a function to calculate the number of tick needed to 
    // create a delay of 100 millisec and store this value in LED_INTERVAL constant
    #define LED_INTERVAL APP_TIMER_TICKS(50)
    
    uint32_t count;
    uint8_t timerExpired;
    // For each application timer we need to create a handle which points to that instance
    // so for evey application timer (Software timer) you create, you need to define a handle
    // create a handle and name it as:  m_app_timer_id 
    APP_TIMER_DEF(m_app_timer_id);
    
    
    
    // its really important to initialize the clock other wise the app timer will not work
    // so make sure you initialize it once in your code and if you are using a soft device
    // then you don't need to initialize the clock as the soft device automatically initializes it.
    static void lfclk_config(void)
    {
    	// initialize the low power low frequency clock
      ret_code_t err_code = nrf_drv_clock_init();
      APP_ERROR_CHECK(err_code);
    
    	// request the lf clock to not to generate any events on ticks
    	// One tick =  1 value increment in the counter register
      nrf_drv_clock_lfclk_request(NULL);
    
    }
    
    
    
    
    
    
    // create a simple handler function which will be called once the timer reaches its 
    // desired number of ticks value
    static void app_timer_handler(void * p_context)
    {
    	// Toggle the LED 
        timerExpired = true;
        app_timer_start(m_app_timer_id, LED_INTERVAL, NULL);
        return;
    }
    
    
    
    // a function to initialize the Application timers
    static void timers_init(void)
    {
    	// a variable to hold error value
        ret_code_t err_code;
    
    	// Initialize the timer 
        err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    
    	// Create an application timer with the handle, mode and interrupt event handle function
        err_code = app_timer_create(&m_app_timer_id, APP_TIMER_MODE_SINGLE_SHOT, app_timer_handler);
        APP_ERROR_CHECK(err_code);
        timerExpired = false;
    }
    
    
    
    
    /**
     * @brief Function for application main entry.
     */
    int main(void)
    {
        count = 0;
    
    // initialize the gpio for led
        nrf_gpio_cfg_output(LED_Pin1);
    
    // call the function to initialize the clock
        lfclk_config();
    // initialize the timer by calling this function which is performing all the basic steps
        timers_init();
    
    // start the timer so that it can generate events on the desired tick value
        uint32_t err_code = app_timer_start(m_app_timer_id, LED_INTERVAL, NULL);
    
    
    
        while (true)
        {
       
        
        nrf_delay_us(10); // if statement below will not execute after event handler
                          // is tripped if this is statement is commented out.
        count = count+1;
        if(timerExpired == true)
          {
            timerExpired = false;
            nrf_gpio_pin_toggle(LED_Pin1);
          }
            // Do nothing.
        }
    }
    /** @} */
    

  • Yes, that was it.  I'm not sure why since the variable is not passed as a parameter.  Thanks for your soltuion.

  • I'm not sure why

    It's a classic case of the variable being modified by separate "threads of execution" - in this case, the timer handler and the main loop.

Related