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

APP_TIMER timeout handler not triggered with optimization level -O3

I am using APP_TIMER to turn ON and OFF pwm. PWM is used to drive a buzzer. PWM is turned ON and OFF in the APP_TIMER timeout handler.

It is observed that after starting the APP_TIMER, PWM is turned ON and OFF few times (i.e the timeout handler is called successfully) and then there is a delay during which the PWM either remains ON or OFF for sometime before the cycle resumes again. During the delay timeout handler is not triggered.

Interestingly this issue is seen only when compiler optimization level is set to -O3 or -O1. Everything works fine if compiler optimization level is set to -O0.

Are there any recommended compiler options that work for the SDK or am I missing something?

Firmware includes Boot loader + Application + SoftDevice (s130) and uses SDK12. The project is build using VisualGDB.
Tried using both the timer modes i.e. using the APP_TIMER in single shot & repeated mode but got the same results.

Any help is appreciated. Thanks

APP_PWM_INSTANCE(PWM_BUZZER,1);                   // Create the instance "PWM_BUZZER" using TIMER1.
APP_TIMER_DEF(m_timer_id);

/* Initialize PWM amd APP_TIMER*/
void init()
{
    ret_code_t err_code;


    /* PWM period is set to 250 us */
    app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_1CH(m_pwm.period, BUZZER);

    /* Switch the polarity of the second channel. */
    pwm1_cfg.pin_polarity[0] = APP_PWM_POLARITY_ACTIVE_HIGH;

    /* Initialize PWM. */
    err_code = app_pwm_init(&PWM_BUZZER,&pwm1_cfg,NULL);
    APP_ERROR_CHECK(err_code);

    /* Create app timer */
    err_code = app_timer_create(&m_timer_id,
                                APP_TIMER_MODE_SINGLE_SHOT,
                                buzzer_timeout_handler);
    APP_ERROR_CHECK(err_code);
}

void start_buzzer(uint8_t beep_count)
{
    uint32_t err_code;
    uint32_t timeout_ticks;

    app_pwm_enable(&PWM_BUZZER);

    m_pwm.beep_count = beep_count;
    app_pwm_channel_duty_set(&PWM_BUZZER, 0, m_pwm.duty_cycle);  //duty cycle = 50%
    
    timeout_ticks = APP_TIMER_TICKS(m_pwm.on_time_ms, APP_TIMER_PRESCALER);  //On time = 62ms
    err_code = app_timer_start(m_timer_id, timeout_ticks, NULL);
    APP_ERROR_CHECK(err_code);
}


static void buzzer_timeout_handler()
{
    app_pwm_duty_t duty_cycle=0;
    uint32_t err_code;
    uint32_t timeout_ticks;

    app_timer_stop(m_timer_id);
    duty_cycle = app_pwm_channel_duty_get(&PWM_BUZZER,0);
    
    if(0 != duty_cycle)
    {
        /*buzzer is ON make it OFF*/
        app_pwm_channel_duty_set(&PWM_BUZZER, 0, 0);  /*set duty cycle to 0 to make it off*/
        
        timeout_ticks = APP_TIMER_TICKS(m_pwm.off_time_ms, APP_TIMER_PRESCALER); //OFF time = 62ms
        err_code = app_timer_start(m_timer_id, timeout_ticks, NULL);
        APP_ERROR_CHECK(err_code);
    }
    else
    {
        /*buzer is OFF make it ON if beep_count != 0*/
        m_pwm.beep_count--;
        if(m_pwm.beep_count)
        {
            app_pwm_channel_duty_set(&PWM_BUZZER, 0, m_pwm.duty_cycle );
            
            timeout_ticks = APP_TIMER_TICKS(m_pwm.on_time_ms, APP_TIMER_PRESCALER); //ON time = 62ms
            err_code = app_timer_start(m_timer_id, timeout_ticks, NULL);
            APP_ERROR_CHECK(err_code);
        }
        else
        {
            /*Stop buzzer*/
            app_pwm_disable(&PWM_BUZZER);
            nrf_gpio_pin_write(BUZZER,0);
            m_pwm.busy = false;
        }
    }
}

/* Alternate timeout handler keeping timer mode APP_TIMER_MODE_REPEATED 
This also gives the same result. */
static void buzzer_timeout_handler()
{
    app_pwm_duty_t duty_cycle=0;
    uint32_t err_code;
    uint32_t timeout_ticks;


    duty_cycle = app_pwm_channel_duty_get(&PWM_BUZZER,0);
    
    if(0 != duty_cycle)
    {
        /*buzzer is ON make it OFF*/
        app_pwm_channel_duty_set(&PWM_BUZZER, 0, 0);  /*set duty cycle to 0 to make it off*/     

    }
    else
    {
        /*buzer is OFF make it ON if beep_count != 0*/
        m_pwm.beep_count--;
        if(m_pwm.beep_count)
        {
            app_pwm_channel_duty_set(&PWM_BUZZER, 0, m_pwm.duty_cycle );            
        }
        else
        {
            /*Stop buzzer*/
			app_timer_stop(m_timer_id);
            app_pwm_disable(&PWM_BUZZER);
            nrf_gpio_pin_write(BUZZER,0);
            m_pwm.busy = false;
        }
    }
}

Related