2014-11-24 09:03 AM
Using STM32Cube_FW_F4_V1.3.0 and a GCC 4.7.4 toolchain I built on Mac OS X, the attached demo (based on Projects/STM32F429I-Discovery/Examples/BSP) toggles one of the LEDs every 250 ms and the other every 500 ms.
SystemClock_Config()
is the same as in the original except for checking the status returns of the HAL calls. I’ve set up a tick callback,volatile
unsigned ticks = 0;
void
HAL_SYSTICK_Callback(
void
)
{
ticks++;
}
and this is checked in the main loop,
while
(1) {
const
unsigned ticks_now = ticks;
if
((ticks_now % 250) == 0) {
BSP_LED_Toggle(LED4);
}
if
((ticks_now % 500) == 0) {
BSP_LED_Toggle(LED3);
}
}
and what happens is that the short-period LED (LED4 here) flickers when the other LED is off and (appears to be) on all the time that the other LED is on.
I can make the LEDs work the way I expected by insertingHAL_Delay(1)
immediately after the firstBSP_LED_Toggle()
,
if
((ticks_now % 250) == 0) {
BSP_LED_Toggle(LED4);
HAL_Delay(1);
}
if
((ticks_now % 500) == 0) {
BSP_LED_Toggle(LED3);
}
The demonstration also works as expected if I remove the
SystemClock_Config()
call but that doesn’t seem like a good way ahead!
2014-11-25 02:48 AM
I thought this might be because of using the non-atomic
GPIOx->ODR ^= GPIO_Pin
inHAL_GPIO_TogglePin()
, so tried usingBSP_LED_On()
,BSP_LED_Off()
with a local variable to tell which one to call (they useHAL_GPIO_WritePin()
, which usesGPIOx->BSRRL
,GPIOx->BSRRH)
.No luck.The reference manual says thatBSRR
is to be used for atomic updates; looks as though it doesn’t quite do that. Which would make using any GPIO problematic. Which I can’t believe.What am I doing wrong?2014-11-25 09:41 AM
What I should have been doing was to set a flag when the
HAL_SYSTICK_Callback()
saw it was time to do a job and then test/clear the flag in the main loop.static
int
t_250 = 0;
static
int
t_500 = 0;
void
HAL_SYSTICK_Callback(
void
)
{
static
unsigned ticks = 0;
ticks++;
if
((ticks % 250) == 0) {
t_250 = !0;
}
if
((ticks % 500) == 0) {
t_500 = !0;
}
}
[...]
while
(1) {
if
(t_500) {
BSP_LED_Toggle(LED3);
t_500 = 0;
}
if
(t_250) {
BSP_LED_Toggle(LED4);
t_250 = 0;
}
}
Mind you,
BSP_LED_Toggle()
, and by extension toggling any GPIO pin, definitely isn’t thread-safe.
2014-11-25 09:50 AM
The reference manual says that
BSRR
is to be used for atomic updates. It can if it's used as a 32-bit register as intended.