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

how is APP_timer running? like a thread?

hi, i was just wondering whether the app_timer works like a function or like a thread.

e.g. lets say i got my mainloop

while(1) { start_timer(...); //DO SOMETHING }

and my timer function

void dummy_timer_handler(...) { //DO SOMETHING ELSE }

when the timer expires and the handler function is called, is my main loop paused? or does it run in parallel?

  • It is interrupt based. By default, as soon as the timer expires, the main loop pauses on the next instruction and the handler is run. When the handler returns, the main loop resumes where it left off.

    If you want it to behave more like a thread where you tell an OS when it is safe to run the handler, you can somewhat fake it by using the APP scheduler version of APP timer (also in the Nordic SDK). The main loop will still pause momentarily at timeout, but it just sends a message to the scheduler that you want the timeout function to be run later. It will run the next time you call the app_sched_execute() function. This requires you to build app_timer_appsh.c and app_scheduler.c. Both of their header files will need to be included, and you will have to initialize the scheduler and tell the app timer that you want it to use the scheduler. Quick example code (not guaranteed to work as is, but should be close) (I recommend making max buffered messages at least OP_QUEUE_SIZE or larger, and making max scheduler message size needs to be at minimum sizeof(app_timer_event_t)):

    #include <stdint.h>
    #include "app_scheduler.h"
    #include "app_timer.h"
    #include "app_timer_appsh.h"
    
    #define OP_QUEUE_SIZE 6
    
    void main(void)
    {
      static uint32_t APP_TIMER_BUF[CEIL_DIV(APP_TIMER_BUF_SIZE(OP_QUEUE_SIZE),
                                                   sizeof(uint32_t))];
      APP_SCHED_INIT(/*Insert max scheduler message size here*/, /*Insert max buffered messages here*/);
      (void)app_timer_init((APP_TIMER_PRESCALER), OP_QUEUE_SIZE, APP_TIMER_BUF, app_timer_evt_schedule);
      
      // Add app timer create here, no different from normal
      
      while(1) {
        app_sched_execute(); // Timer timeout handler functions called here, when appropriate
        
        /* Do stuff here */
        /* Start timer on conditions whenever in here */
      }
    }
    
  • Thank you that cleared that up.

    Why im asking is because im using a timer to shut my system off after a long button press. But in the timer function when i use my SPI functions it is not run through properly. the program gets stuck at the SPI functions because my mainloop also uses them to communicate with an ADC and i think there exists a conflict.

    example: while(1) { if adc_data_rdy SPI2ADC(...); }

    timer_handle() { SPI2ADC(SHUTDOWN); SYSTEM_OFF; }

    as i see it i cannot wait for the usual SPI communication to be over because the timer is not a thread. so i have to program it differently.

  • Good to know you've cleared that up. Just an FYI, on this site it's usually better to leave a comment under the answer for clarity that you're responding to that answer chain, as there can be multiple answers from different users. If you're satisfied you can hit the accept answer button to close out the question.

    Also note that in the code as how you've written it, if you turn the system back on later it'll be from the end of the interrupt, so you could start at any random place in the main loop on wakeup. It is probably better to use something like setting a volatile flag in the interrupt so you can control where you sleep in the main loop.

  • Hey,

    thank your for your advice. i was looking for an "accept answer" button was unable to find it. i will look thoroughly once more!

    i solved it as you stated in your post, with a flag that is checked in my mainloop!

    edit: ah the arrow, okay! Thanks again.

Related