AnsweredAssumed Answered

1MHz timer in one pulse mode - no interrupt in case of small auto-reload value

Question asked by belomutskiy.andrey on May 7, 2014
Latest reply on May 8, 2014 by Clive One
I am trying to build a scheduler on top of a 1MHz tim5 32 bit timer operating in one pulse mode:
void initMicrosecondTimer(void) {
    RCC ->APB1ENR |= RCC_APB1ENR_TIM5EN;   // Enable TIM5 clock
    nvicEnableVector(HW_TIMER_IRQ, CORTEX_PRIORITY_MASK(HW_TIMER_PRIORITY));
    TIM->DIER |= TIM_DIER_UIE;   // Enable interrupt on update event
    TIM->CR1 |= TIM_CR1_OPM; // one pulse mode: count down ARR and stop
    TIM->CR1 &= ~TIM_CR1_ARPE; /* ARR register is NOT buffered, allows to update timer's period on-fly. */

    TIM->PSC = 84 - 1;   // 168MHz / 2 / 84 = 1MHz, each tick is a microsecond
}

/**
 * sets the alarm to the specified number of microseconds from now.
 * This function should be invoked under kernel lock which would disable interrupts.
 */
void setHardwareUsTimer(int timeUs) {
    TIM->ARR = timeUs - 1;
    TIM->EGR |= TIM_EGR_UG; // generate an update event to reload timer's counter value
    TIM->CR1 |= TIM_CR1_CEN; // restart timer

    lastSetTimerTime = getTimeNowUs();
    isTimerPending = TRUE;
    timerRestartCounter++;
}

Full file: https://sourceforge.net/p/rusefi/code/HEAD/tree/trunk/firmware/hw_layer/microsecond_timer.c
Problem: while everything works as expected in case of timeUs parameter above 300, I am not getting the expected callback for smaller timeUs parameter values like 5 or 11. Just for clarity: I am not even trying to constantly invoke 5us, 5us, 5us, 5us - even a single 5us between 300us invocations fails.

Currently I am trying relatively low #define HW_TIMER_PRIORITY 12 but I was still expecting the callback to happen eventually?

Please advice how can I get the callback to happen, even if it would be a bit late.

Outcomes