cancel
Showing results for 
Search instead for 
Did you mean: 

HAL geniuses, how does this work?

Posted on June 16, 2017 at 23:56

From the STM32F412G-DISCO demo

uint32_t HAL_GetTick(void)

{

return (DWT->CYCCNT / (HAL_RCC_GetHCLKFreq() / 1000)) ;

}

How exactly does this wrap properly within the 32-bit number space? Answer: IT DOESN'T

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
12 REPLIES 12
Posted on June 22, 2017 at 11:59

When something is really badly broken it becomes quite hard to even have a meaningful discussion about it. In my experience all time representations must be signed to make time calculations work at all.

Amel NASRI
ST Employee
Posted on June 23, 2017 at 12:09

Hi

,

We deeply reviewed all your comments and here our feedback:

First to precise: the points you raised in this discussion are valid for F412G demo, some BSP examples and some applications based on the usage of the Touch screen calibration module.

They are not valid for the Cube HAL and Middleware drivers.

We recognize that the following statement should not be used:

uint32_t HAL_GetTick(void){ return (DWT->CYCCNT / (HAL_RCC_GetHCLKFreq() / 1000)) ;}�?�?�?�?�?�?�?�?

In coming Cube firmware package versions, this implementation will be replaced by the usage of a time base based on the TIMERs or the native time base GetTick() (declared as a weak function in the hal.c file). Your proposal to use the following implementation is correct :

uint32_t HAL_GetTick(void){ return(DWT->CYCCNT);}�?�?�?�?�?�?�?�?

But this is not recommended as there is a high risk of multi rollover condition as the DWT->CYCCNT overflow occurs every almost 86 seconds at 50MHz.

As DWT is not available on M0/M0+ cores, it is decided to remove the implementation of GetTick based on the DWT and replace it by TIMER or native time base as previously said in the next releases of the demos.

The default HAL_Delay implementation used for the Cube today is the following :

__weak void HAL_Delay(__IO uint32_t Delay){ uint32_t tickstart = HAL_GetTick(); uint32_t wait = Delay; /* Add a period to guarantee minimum wait */ if (wait < HAL_MAX_DELAY) { wait++; } while((HAL_GetTick() - tickstart) < wait) { }}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

So the minimum 1 ms is ensured.

All the timeout and delay used in the Cube drivers are based on the HAL_GetTick() using the following comparison:

HAL_GetTick() - tickstart) < __TIME__�?

The GetTick() is always returning the uwTick (uint32_t) which is incremented by a Time base ISR occurring each 1ms, and this is completely valid for 32-bit number space.

However, the following statement is used in a special case (touch screen calibration after the Reset, so

the TimeStart is often 0 or 1 ms

:(

if ((HAL_GetTick() - 100) > TimeStart)

Even if there is no issue in this particular case, I agree with you that this has to be updated to avoid confusion.

Please note also that such statement is not used by the HAL drivers neither the applications. Finally, I would like to highlight that the time-base functions implemented in the Cube drivers are all weak, so you have always the possibility to over-write them when needed.

Hope this reply covers all the technical discussed points, and thanks for your insights.

-Amel

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Posted on June 29, 2017 at 17:39

st.mcu

‌ good to know that ST is thoughtfully developing the HAL.