Hello,
I've created simple delay for my project using systick as it is not used for anything else but once i start raising optimalizations it stops working.
void delay_us(uint32_t us)
{
unsigned long actualSysTick;
unsigned long desiredSysTick;
unsigned long us_delay=us;(void)SYSTICK_CSR;
desiredSysTick=SYSTICK_CURRENT - CORE_1US;
do
{
while((actualSysTick = SYSTICK_CURRENT) > desiredSysTick)
{
if(SYSTICK_CSR & SYSTICK_COUNTFLAG)
{
(void)SYSTICK_CSR;
break;
}
}desiredSysTick = actualSysTick - CORE_1US;
}while(--us_delay);
}
I noticed while debugging that if i set O1 optimalization or highter my program is stuck on do-while because when us_delay hits 0 instead of leaving do-while it jumps to us value again and it's just sits there forever. I heard once that it's best to program on desired optimalization from the start to avoid future problems but seems like compiler is doing some extreme level optimalization and i can't even spot what's wrong.
Solved! Go to Solution.
Brian
It looks like your routine is based on the uTasker code (commented version below):
extern void fnDelayLoop(unsigned long ulDelay_us)
{
    #define CORE_US (CORE_CLOCK/1000000)                                 // the number of core clocks in a us
    register unsigned long ulMatch;
    register unsigned long _ulDelay_us = ulDelay_us;                     // ensure that the compiler puts the variable in a register rather than work with it on the stack
    if (_ulDelay_us == 0) {                                              // minimum delay is 1us
        _ulDelay_us = 1;
    }
    (void)SYSTICK_CSR;                                                   // clear the SysTick reload flag
    ulMatch = ((SYSTICK_CURRENT - CORE_US) & SYSTICK_COUNT_MASK);        // first 1us match value (SysTick counts down)
    do {
        while (SYSTICK_CURRENT > ulMatch) {                              // wait until the us period has expired
            if ((SYSTICK_CSR & SYSTICK_COUNTFLAG) != 0) {                // if we missed a reload (that is, the SysTick was reloaded with its reload value after reaching zero)
                (void)SYSTICK_CSR;                                       // clear the SysTick reload flag
                break;                                                   // assume a single us period expired
            }
        }
        ulMatch -= CORE_US;                                              // set the next 1us match
        ulMatch &= SYSTICK_COUNT_MASK;                                   // respect SysTick 24 bit counter mask
    } while (--_ulDelay_us != 0);                                        // one us period has expired so count down the requested periods until zero
}
I always run with highest optimisation so I suspect that you don't have SYSTICK_CURRENT defined as a volatile register.
Regards
Mark
Brian
It looks like your routine is based on the uTasker code (commented version below):
extern void fnDelayLoop(unsigned long ulDelay_us)
{
    #define CORE_US (CORE_CLOCK/1000000)                                 // the number of core clocks in a us
    register unsigned long ulMatch;
    register unsigned long _ulDelay_us = ulDelay_us;                     // ensure that the compiler puts the variable in a register rather than work with it on the stack
    if (_ulDelay_us == 0) {                                              // minimum delay is 1us
        _ulDelay_us = 1;
    }
    (void)SYSTICK_CSR;                                                   // clear the SysTick reload flag
    ulMatch = ((SYSTICK_CURRENT - CORE_US) & SYSTICK_COUNT_MASK);        // first 1us match value (SysTick counts down)
    do {
        while (SYSTICK_CURRENT > ulMatch) {                              // wait until the us period has expired
            if ((SYSTICK_CSR & SYSTICK_COUNTFLAG) != 0) {                // if we missed a reload (that is, the SysTick was reloaded with its reload value after reaching zero)
                (void)SYSTICK_CSR;                                       // clear the SysTick reload flag
                break;                                                   // assume a single us period expired
            }
        }
        ulMatch -= CORE_US;                                              // set the next 1us match
        ulMatch &= SYSTICK_COUNT_MASK;                                   // respect SysTick 24 bit counter mask
    } while (--_ulDelay_us != 0);                                        // one us period has expired so count down the requested periods until zero
}
I always run with highest optimisation so I suspect that you don't have SYSTICK_CURRENT defined as a volatile register.
Regards
Mark