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