This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Using the Scheduler (8051 OSAL system to nRF51822)

Hi all,

I just had some general questions regarding events and timers on the nRF51822. I'm coming from a Ti CC2540 8051 which used an OSAL system. This made it quite easy to create events and sub-tasks, and handlers for each event and task. This allowed one class to trigger an event handler in another class quite easily. I'm trying to figure out how to perform equivalent custom event/task handling on the nRF51822. Case in point:

I used the Button Handler to catch button presses/releases. I use this to trigger timers in a Button_Timer.c class which monitor how long a button has been press. While pressed, the duration triggers different LED's to turn on (i.e. if 2sec has elasped, turn on Red led. After 3secs turn off LED, after 5secs trigger a buzzer...etc). I know I can do this by simply using app_timers, but I'd rather avoid using many many timers to handle tasks.

I can't seem to find any example code where the application creates its own events and at certain trigger points pushes them to the scheduler to execute via app_sched_event_put. I may be looking at this all wrong with how the Scheduler is supposed to work, so any advise on the matter is greatly appreciated. Thank you

Parents
  • Hi. Scheduler in nRF51822 is used to queue the non-real-time operation and release the interruption resources quickly. It is equivalent to the traditional flag setting/resetting in the IRQ processing. For instance, a traditional IRQ processing is like

    void xxx_IRQHandler(void)
    {
        ....
        xxx_flag = true;
        ....
    }
    
    int main(void)
    {
        for(;;)
        {
        	....
            if (xxx_flag == true) { /* Process interruption here */ }
            ....
        }
    }
    

    The alternative version using scheduler is

    void xxx_IRQHandler(void)
    {
        ....
        err_code = app_sched_event_put(..., xxx_func);
        ....
    }
    
    void xxx_func(void *p_event_data, uint16_t event_size)
    {
        /* Process interruption here */
    }
    
    int main(void)
    {
        ....
        for (;;)
        {
            err_code = sd_app_evt_wait();
            APP_ERROR_CHECK(err_code);
            app_sched_execute();
        }
    }
    

    The queued operation may be executed at anytime. For your application, if you need instant response occurred at the exact time, scheduler may be not a good solution. What you can do is first register a button event using app_button,

    static void button_evt_handler(uint8_t pin_no, uint8_t button_action)
    {
        ....
        if (pin_no == BUTTON_PIN_NO && button_action == APP_BUTTON_PUSH)
        {
            button_pushed = true;
            count = 0;
        } else if (pin_no == BUTTON_PIN_NO && button_action == APP_BUTTON_RELEASE)
        {
            button_pushed = false;
            count = 0;
        }
        ....
    }
    

    Then register an app_timer triggered every 1s,

    void timer_timeout_handler(void *p_context)
    {
        ....
        if (button_pushed == true)
        {
            count ++;
            switch(count)
            {
                case 2: /* Turn on Red LED */
                case 3: /* Turn off LED */
                case 5: /* Trigger a buzzer */
                ....
             }
         }
         ....
    }
    

    That should be fine. BTW, no matter how many app_timer instance you registered, there's only one hardware timer used. (In fact, nRF51822 has only two RTCs, and another is occupied if you're using the SoftDevice.) app_timer can respond to the RTC interruption, and distribute tasks among different app_timer instances. So don't worry about how many "timers" you're using. Particularly, when you initialize the app_timer using

    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, true);
    

    The last parameter of true means scheduler is enabled. All your app_timer event handler will be automatically queued and executed by the scheduler.

Reply
  • Hi. Scheduler in nRF51822 is used to queue the non-real-time operation and release the interruption resources quickly. It is equivalent to the traditional flag setting/resetting in the IRQ processing. For instance, a traditional IRQ processing is like

    void xxx_IRQHandler(void)
    {
        ....
        xxx_flag = true;
        ....
    }
    
    int main(void)
    {
        for(;;)
        {
        	....
            if (xxx_flag == true) { /* Process interruption here */ }
            ....
        }
    }
    

    The alternative version using scheduler is

    void xxx_IRQHandler(void)
    {
        ....
        err_code = app_sched_event_put(..., xxx_func);
        ....
    }
    
    void xxx_func(void *p_event_data, uint16_t event_size)
    {
        /* Process interruption here */
    }
    
    int main(void)
    {
        ....
        for (;;)
        {
            err_code = sd_app_evt_wait();
            APP_ERROR_CHECK(err_code);
            app_sched_execute();
        }
    }
    

    The queued operation may be executed at anytime. For your application, if you need instant response occurred at the exact time, scheduler may be not a good solution. What you can do is first register a button event using app_button,

    static void button_evt_handler(uint8_t pin_no, uint8_t button_action)
    {
        ....
        if (pin_no == BUTTON_PIN_NO && button_action == APP_BUTTON_PUSH)
        {
            button_pushed = true;
            count = 0;
        } else if (pin_no == BUTTON_PIN_NO && button_action == APP_BUTTON_RELEASE)
        {
            button_pushed = false;
            count = 0;
        }
        ....
    }
    

    Then register an app_timer triggered every 1s,

    void timer_timeout_handler(void *p_context)
    {
        ....
        if (button_pushed == true)
        {
            count ++;
            switch(count)
            {
                case 2: /* Turn on Red LED */
                case 3: /* Turn off LED */
                case 5: /* Trigger a buzzer */
                ....
             }
         }
         ....
    }
    

    That should be fine. BTW, no matter how many app_timer instance you registered, there's only one hardware timer used. (In fact, nRF51822 has only two RTCs, and another is occupied if you're using the SoftDevice.) app_timer can respond to the RTC interruption, and distribute tasks among different app_timer instances. So don't worry about how many "timers" you're using. Particularly, when you initialize the app_timer using

    APP_TIMER_INIT(APP_TIMER_PRESCALER, APP_TIMER_MAX_TIMERS, APP_TIMER_OP_QUEUE_SIZE, true);
    

    The last parameter of true means scheduler is enabled. All your app_timer event handler will be automatically queued and executed by the scheduler.

Children
No Data
Related