2026-01-19 2:21 AM
I have a simple function with loop that checks RX pin state for 10ms, and if there was high level - breaks loop and exits. it works ok with -O0, but is broken with -Os or -O1 (-O2) or -Og - it loops forever.
Here's code:
uint8_t isModemOn() {
uint32_t expire = uwTick + 10;
while (expire - uwTick < 11) { // check RXD pin level, if low for 10ms - consider modem is off
if (LL_GPIO_ReadInputPort(GPIOA) & LL_GPIO_PIN_10) {
return 1;
}
}
return 0;
}and how it's appears in listing
080003dc <isModemOn>:
* @PAram GPIOx GPIO Port
* @retval Input data register value of port
*/
__STATIC_INLINE uint32_t LL_GPIO_ReadInputPort(GPIO_TypeDef *GPIOx)
{
return (uint32_t)(READ_REG(GPIOx->IDR));
80003dc: 21a0 movs r1, #160 @ 0xa0
//#pragma GCC optimize ("O0") // Error in -Os optimization
uint8_t isModemOn() {
uint32_t expire = uwTick + 10;
while (expire - uwTick < 11) { // check RXD pin level, if low for 10ms - consider modem is off
if (LL_GPIO_ReadInputPort(GPIOA) & LL_GPIO_PIN_10) {
80003de: 2380 movs r3, #128 @ 0x80
80003e0: 05c9 lsls r1, r1, #23
80003e2: 00db lsls r3, r3, #3
80003e4: 690a ldr r2, [r1, #16]
80003e6: 421a tst r2, r3
80003e8: d0fc beq.n 80003e4 <isModemOn+0x8>
return 1;
}
}
return 0;
}
80003ea: 2001 movs r0, #1
80003ec: 4770 bx lr
...I didn't work too much with ARM assembler, but it looks like it calculates expire variable dynamically in the loop, or even dropped it's check at all. I tried to change conditions (while..if) but it doesn't help.
I'll try to find workaround by code refactoring, but I hope it'll be fixed in future releases.
Solved! Go to Solution.
2026-01-19 2:52 AM
Hm, I forgot to declare uwTick as volatile. with volatile all is OK...
2026-01-19 2:44 AM
You haven't shown your definition of uwTick - is it the standard HAL one?
If not, is it volatile, and how is it updated ?
2026-01-19 2:52 AM
Hm, I forgot to declare uwTick as volatile. with volatile all is OK...