cancel
Showing results for 
Search instead for 
Did you mean: 

CubeMX HAL - Is Thread Safe?

Yevpator
Associate III

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!​

3 REPLIES 3
Amel NASRI
ST Employee

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.

Yevpator
Associate III

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?

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.