EmbDev.net

Forum: ARM programming with GCC/GNU tools STM32 HAL Delay too slow


von Philipp (Guest)


Rate this post
useful
not useful
Hi,

I recently started with an STM32F103C8T6 on a bluepill board. I am using 
SW4STM32 on Windows 10.

When writing a program that blinks an LED on PC13 with the standard
peripheral library and implementing my own SysTick_Handler and Delay 
functions, the LED blinks in the correct intervals.

This is the relevant code:
1
// Main without GPIO Initialization and APB2ENR code
2
int main(void)
3
{
4
  SystemInit();
5
  SysTick_Config(SystemCoreClock / 1000);
6
}
7
8
// My own SysTick_Handler
9
void SysTick_Handler(void) {
10
  static uint32_t millis = 0;
11
  millis++;
12
  if (millis % 1000 == 0) {
13
    flipPin();
14
  }
15
}


When I tried porting this code to a project using the Cube HAL libraries 
provided by SW4STM32 and using HAL_Delay for delay, the LED blinks ~18x 
slower. I tried following other guides on writing HAL applications, 
however I could not find any examples about clock configuration.

The relevant HAL code:
1
// Main without GPIO Initialization and APB2ENR code
2
int main(void) {
3
  HAL_Init();
4
  SysTick_Config(SystemCoreClock / 1000);
5
  ...
6
  for (;;) {
7
    HAL_Delay(1000);
8
    flipPin();
9
  }
10
}

While the STD code blinks the LED in precise 1000ms intervals, the HAL 
code takes ~18000ms for each loop. I have looked at the HAL_Init code, 
switched HAL_Init and SysTick_Config and tested flipPin, but could not 
find any hints to what might cause this behaviour.

 In case anybody knows what I am doing wrong, please let me know. Thank 
you

von Philipp (Guest)


Rate this post
useful
not useful
I can't edit the post, but one important detail: The main function in 
STD also has a loop in the form of
1
for(;;);

von Philipp (Guest)


Rate this post
useful
not useful
Ok, kind of embarassing, I read the code but I skipped the comments. It 
says right on line 175 of "stm32f1xx_hal.c":
1
  /* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */

So after configuring the PLL and SysClock with
1
RCC_PLLInitTypeDef pll;
2
pll.PLLMUL = RCC_PLL_MUL9;
3
pll.PLLSource = RCC_PLLSOURCE_HSE;
4
pll.PLLState = RCC_PLL_ON;
5
6
RCC_OscInitTypeDef osc;
7
osc.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
8
osc.HSEState = RCC_HSE_ON;
9
osc.OscillatorType = RCC_OSCILLATORTYPE_HSE;
10
osc.PLL = pll;
11
12
HAL_RCC_OscConfig(&osc);
13
14
RCC_ClkInitTypeDef clock;
15
clock.ClockType = RCC_CLOCKTYPE_SYSCLK;
16
clock.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
17
18
HAL_RCC_ClockConfig(&clock, FLASH_LATENCY_2);

I feel like an idiot, but I will leave this here, so others can find a 
solution.

von W.S. (Guest)


Rate this post
useful
not useful
Philipp wrote:
> I feel like an idiot, but I will leave this here, so others can find a
> solution.

Why do you fiddle around with this obfuscating HAL?

Just be a man and build your own firmware. I give you a hint, how to do:
https://www.mikrocontroller.net/attachment/316790/STM32F103C8T6.ZIP

Just have a look into it - and use what you want if you are interested.
btw: the binary in this archive should also work on a blue-pill board.

W.S.

von STM Code Warrior (Guest)


Rate this post
useful
not useful
Philipp wrote:
> In case anybody knows what I am doing wrong, please let me know. Thank
> you

Perhaps you did not do the clock initializiation in the
HAL version correctly.

von Sebastian E. (Guest)


Rate this post
useful
not useful
SystemCoreClock might still contain the initial clock value (HSI).
Double-check whether the clock configuration updates SystemCoreClock or 
call SystemCoreClockUpdate before using SystemCoreClock .

von Heinz M. (subi)


Rate this post
useful
not useful
Try to NOT use HAL_Delay.
With HAL_Delay the µC does nothing, but consume energy. I only use it 
for start up, while waiting for some external peripherie to start up.

Never put a HAL_Delay in the Systick or Timer Interrupt!
While HAL_Delay the µC can do nothing else. If the next systick 
interrupt comes meanwhile you have a problem. If some other interrupt 
comes the HAL_Delay timing is added to the time the other interrupt 
takes. Thats why it only should be used while start up or in the main 
loop.

Use a timer or the systick and put a counter inside. By 1 ms timer, 
count until 1000 and then flip the LED on. Like you have done in your 
own systick. Now the µC only needs ~ 1% of the calculating power like 
with HAL_Delay. Now you can use different variables to get different 
timings out of one timer. With HAL_Delay absolutly not possible.

: Edited by User
von Kala C. (Company: Elxis) (kalacanel)


Rate this post
useful
not useful
Hi...If you really need to disable all interrupts you'd need to poll on 
a timer or on CPU cycle counter.
If however you can tolerate SysTick (and possibly other) interrupts you 
may want to arrange your interrupt priorities so that instead of 
disabling all interrupts with __disable_irq() you disable only the ones 
with a priority level lower than a given threshold with __set_BASEPRI().

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.