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

app_scheduler and app_timer

I've searched and the majority of answers seem to be years old. 

I have an existing app_timer event handler that works perfectly, blinking LEDs. 

I will soon have another that needs to do some I/O and thus needs not to be running out of an ISR. 

I enabled  APP_SCHEDULER_ENABLED and APP_TIMER_CONFIG_USE_SCHEDULER

I put the following code into my "init"

#define SCHED_QUEUE_SIZE                    16        
#define SCHED_MAX_EVENT_DATA_SIZE           192       

   APP_SCHED_INIT(APP_TIMER_SCHED_EVENT_DATA_SIZE, SCHED_QUEUE_SIZE);

    ret = app_timer_init();
    APP_ERROR_CHECK(ret);

and in my "main loop" I put this to make sure that things got called every 50 milliseconds or so.

   do
           {
             /*
             ** read from the input stream.
             */
             serial_ret_code = nrf_serial_read(&serial0_uart, &c, 1, NULL, 50);
             if (NRF_SUCCESS != serial_ret_code)
             {
                app_sched_execute();

                continue;
             }
             else
             {
                app_sched_execute();

                break;
             }

           } while (true);


A couple of things happen.

First, the event handler never gets called (again, this works fine without the app_scheduler) and second I get this in my debugger:


Stopped by vector catch

In the Call Stack window it shows me at address 0x8C4 - somewhere in the softdevice


Parents
  • Well I have a beginning of an understanding. nrf_serial_read uses app_timer and so *it* is not timing out and returning to me.

    I basically stole my UART code from the SDK, and for its "sleep_function" it really was putting the processor to sleep, 

    By telling it to wait for an interrupt of any sort, and then running the app_scheduler things seem to be working. 

    I'm unsure if this is a "good" way to solve the problem, though.

    Perhaps an alternate solution would be to use one of the hardware timers and have it run call app_sched_execute() on a periodic basis. Every 100 milliseconds or so. None of my app_timer events need to be services more often than every 250 milliseconds. But no - that won't work because the hardware timer callback is in ISR space rather than userland. For now, leaving the __SWI(); and app_sched_execute together in the sleep function of the nrf_serial abstraction will work for me, and I'll need to find a way to insert app_sched_execute into any other long-ish loops I end up running when I (today) start using the softdevice for BLE. 

    Or is there a "better" way to do this? 

    Below is my change to the sleep handler to support app_scheduler

    uint32_t sleep_handler_count = 0;
    
    static void sleep_handler(void)
    {
       sleep_handler_count++;
    
    #ifdef _USE_EXAMPLE_SLEEP_HANDLER_
       /*
       ** this shuts things down by allowing the processor to go into
       ** low power mode.
       */
       __WFE();
       __SEV();
       __WFE();
    #else
       /*
       ** wait for an interrupt of any sort, and
       ** run the app_scheduler
       */
       __WFI();
       app_sched_execute();
    #endif
    }
    
    
    
Reply
  • Well I have a beginning of an understanding. nrf_serial_read uses app_timer and so *it* is not timing out and returning to me.

    I basically stole my UART code from the SDK, and for its "sleep_function" it really was putting the processor to sleep, 

    By telling it to wait for an interrupt of any sort, and then running the app_scheduler things seem to be working. 

    I'm unsure if this is a "good" way to solve the problem, though.

    Perhaps an alternate solution would be to use one of the hardware timers and have it run call app_sched_execute() on a periodic basis. Every 100 milliseconds or so. None of my app_timer events need to be services more often than every 250 milliseconds. But no - that won't work because the hardware timer callback is in ISR space rather than userland. For now, leaving the __SWI(); and app_sched_execute together in the sleep function of the nrf_serial abstraction will work for me, and I'll need to find a way to insert app_sched_execute into any other long-ish loops I end up running when I (today) start using the softdevice for BLE. 

    Or is there a "better" way to do this? 

    Below is my change to the sleep handler to support app_scheduler

    uint32_t sleep_handler_count = 0;
    
    static void sleep_handler(void)
    {
       sleep_handler_count++;
    
    #ifdef _USE_EXAMPLE_SLEEP_HANDLER_
       /*
       ** this shuts things down by allowing the processor to go into
       ** low power mode.
       */
       __WFE();
       __SEV();
       __WFE();
    #else
       /*
       ** wait for an interrupt of any sort, and
       ** run the app_scheduler
       */
       __WFI();
       app_sched_execute();
    #endif
    }
    
    
    
Children
No Data
Related