2018-10-17 02:23 PM
The CubeMX HAL library is considered and claimed to be "thread safe". One can select FreeRTOS on the CubeMX and generate a code.
I am questioning whether the HAL is indeed 100% safe for using with RTOS. The HAL allows read/write to specific bits in the STM32 registers through pointers, e.g.
*((volatile uint32_t*)0x820000) &= value;
I think this code is not safe and should be protected by some RTOS synchronization means. Am I mistaken?
Thank you in advance!
2018-12-06 05:11 AM
Hi @Community member ,
Do you have any example of HAL/LL driver where such code is used:
*((volatile uint32_t*)0x820000) &= value;
Thanks,
-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.
2018-12-06 05:45 AM
Hi Amel,
I don't remember the original example, maybe I just used the absolute address for the question simplicity. Here is a similar exam:
/**
* @brief Starts the TIM Base generation in interrupt mode.
* @param htim : TIM handle
* @retval HAL status
*/
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)
{
/* Check the parameters */
assert_param(IS_TIM_INSTANCE(htim->Instance));
/* Enable the TIM Update interrupt */
__HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);
/* Enable the Peripheral */
__HAL_TIM_ENABLE(htim);
/* Return function status */
return HAL_OK;
}
Here __HAL_TIM_ENABLE_IT seems to me as not an atomic instruction that read/write from/to HW register and it is not protected.
HOWEVER, I changed my mind. I think now that HAL is not necessarily supposed to be Thread Safe. It should be a "Driver" that needs to speak with the HAL and provide HAL protection with various RTOS means, like, semaphore, mutex and etc., so this is how I justified this behavior.
On the other hand, in some other cases I do see an attempt to protect global registers from non-atomic access from concurrent threads/different contexts, e.g.
HAL_StatusTypeDef HAL_TIM_Base_Stop(TIM_HandleTypeDef *htim)
{
/* Check the parameters */
assert_param(IS_TIM_INSTANCE(htim->Instance));
/* Set the TIM state */
htim->State= HAL_TIM_STATE_BUSY;
/* Disable the Peripheral */
__HAL_TIM_DISABLE(htim);
/* Change the TIM state*/
htim->State= HAL_TIM_STATE_READY;
/* Return function status */
return HAL_OK;
}
Here __HAL_TIM_DISABLE(htim); is kind of "protected" by writing BUSY before the macro is called and then READY . So I don't understand why in my 1st example ST didn't use the same approach like in the 2nd one?
2018-12-10 08:54 AM
Hi Yevpator,
HAL drivers are developed in a way that should allow the abstraction of the processing.
This is based on the implementation of all possible scenarii for a given peripheral based on a state machine.
Some APIs cannot be executed while the state isn't yet ready, like HAL_TIM_Base_Start_DMA.
That is why such "protection" is added in the implementation of HAL_TIM_Base_Stop.
If you use the LL driver, the implementation is different; it is up to you to protect your code and the defined states of HAL driver are no more used.
-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.