Reputation: 677
I am using ST Link debugger on STM32F407 MCU. I have issues relating to data not loading in correct manner in between differnt circular buffers, used to extract bytes from USART. I wanted to see how thread which extracts frames from the serial [4000]
array behaves with added delay.
Below code plays fine with debuger and I can step into each line, and inspect values of the variables.
//This callback is automatically called by the HAL when the DMA transfer is completed
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
// read 50 bytes of raw data to the raw_serial buffer
HAL_UART_Receive_DMA (huart, raw_serial, 50);
//osDelay(10);
//HAL_Delay(10);
// add raw_serial to the serial[4000]
AppendSerial(raw_serial,size);
}
Using either of those delays:
osDelay(10);
HAL_Delay(10);
Causes program execution to get stuck in one of the countdown loops and prevents me from ever reachign a breakpoint located after the wait statment.
Reading this post it seems to me that osDelay
is more apprioprate, when using FreeRTOS.
Only things I can think of causing this is ST Link lacking compatibility or drivers, or inability to include delays from within interrupt triggered callback functions.
Thanks for your help.
Upvotes: 1
Views: 2015
Reputation: 8059
It has nothing to do with ST-Link.
By default, the delay functions work by monitoring a variable that is incremented in a timer interrupt. If that timer interrupt is blocked, then the variable is not incremented, and the delay function would never finish. There are a few ways around this.
Let the timer interrupt preempt the serial interrupt handler
Ensure that the timer interrupt has higher priority than the serial interrupt. By default, HAL sets the timer interrupt to the lowest possible priority (quite stupid idea IMO) in stm32f4xx_hal_conf.h
#define TICK_INT_PRIORITY 0x0FU /*!< tick interrupt priority */
change that to a lower value (higher priority), and set the priority of the UART interrupt to a higher value (lower priority). Now, HAL_Delay()
would work even in the UART interrupt handler.
Make HAL_Delay()
work without interrupts
HAL_Delay()
works by repeatedly calling HAL_GetTick()
until the delay time has elapsed. HAL_GetTick()
should return the time elapsed since startup in milliseconds as a 32 bit unsigned value. You can provide your own HAL_GetTick()
implementation that uses a 32 bit hardware timer to determine the current time.
There are two 32-bit timers, TIM2
and TIM5
, pick one of them. Set the reload value to the APB1 clock frequency divided by 1000 minus 1 (83999 with the default clock settings), start counting upwards. Now HAL_GetTick()
can simply return the timer counter register.
uint32_t HAL_GetTick(void) {
return TIM2->CNT; // or TIM5->CNT
}
Write your own delay function
For example, you can use the cycle counter for short delays, or an empty for
loop to have an approximate delays, start a one-shot timer and wait until completion, etc.
Upvotes: 4
Reputation: 19
You cannot call a delay function from within an interrupt handler. Remember that an interrupt handlers purpose is to execute as quickly as possible so the program can return to normal execution, a delay is incompatible with that concept.
Upvotes: 0