Skip to main content
Visitor II
April 25, 2016
Question

Questions surrounding __HAL_LOCK

  • April 25, 2016
  • 15 replies
  • 12416 views
Posted on April 26, 2016 at 00:12

I’m an engineer at Fluke, and we’re using an STM32F4xx seriesmicrocontroller (together with its HAL drivers) as the basis for a newproduct. The HAL contains a “locking�? mechanism, where eachsubsystem—I²C, USB, UART, and so on—has a “locking object�?. My team hasbeen working on the assumption that this mechanism’s goal is to providesome mutual exclusion for memory-mapped hardware registers and relatedstate so that, for example, an interrupt doesn’t modify the same hardware state being manipulated in the main “thread�? of exectution.

What’s confused us, however, is how this is done. The driver code found in stm32f4xx_hal_def.h defines the locking mechanism as follows:[1]

typedef
enum
{
HAL_UNLOCKED = 0x00U,
HAL_LOCKED = 0x01U
} HAL_LockTypeDef;
#if (USE_RTOS == 1)
/* Reserved for future use */
#error ''USE_RTOS should be 0 in the current HAL release''
#else
#define __HAL_LOCK(__HANDLE__) \
do
{ \
if
((__HANDLE__)->Lock == HAL_LOCKED) \
{ \
return
HAL_BUSY; \
} \
else
\
{ \
(__HANDLE__)->Lock = HAL_LOCKED; \
} \
}
while
(0)
#define __HAL_UNLOCK(__HANDLE__) \
do
{ \
(__HANDLE__)->Lock = HAL_UNLOCKED; \
}
while
(0)
#endif /* USE_RTOS */

In summary, “locking�? consists of setting a flag, or returning an error(indicating the system is busy) when the flag is already set.“Unlocking�? consists of unconditionally clearing the flag. What throws us is the immediate return of HAL_BUSY in the case ofcontention. If a HAL lock is providing mutual exclusion between the mainthread and an interrupt handler, what should be done if the interrupt isthe second caller of __HAL_LOCK and gets HAL_BUSY? An interrupt cannotpause its execution and start again when the lock is no longercontended, like a userspace thread could in a multitasking OS. (The bestone can do is have the interrupt schedule the work for some later time,but this is not always feasible.) Additionally, many read-modify-write sequences (such as ORing bits) are performed on hardware registers without any additional protection besides these ''locks''. What is to keep an interrupt (or, if one is running an RTOS, another task) from executing in the middle of one of these sequences? Based on these observations, we tried redefining __HAL_LOCK and__HAL_UNLOCK to be a global “interrupt lock�?, i.e., the former disablesinterrupts and the latter re-enables them. For cases where several callsto these functions nest (whether intentionally or unintentionally), wekeep track of a nesting count. Unfortunately this doesn’t work well withthe I²C driver, since it contains several code paths where, on atimeout, __HAL_UNLOCK is called twice for a single call to __HAL_LOCK,unbalancing our nesting count to disastrous effect. How is the __HAL_LOCK/__HAL_UNLOCK system meant to work? It would seemwe’re not using it according to its design goals. [1] All code is taken from STM32CubeF4, version 1.0 #hal #stm32f4
    This topic has been closed for replies.

    15 replies

    Graduate
    January 15, 2018
    Posted on January 15, 2018 at 16:33

    So, generally speaking, fixing __HAL_LOCK with a more robust code would not solve the weaknesses of HAL drivers.

    You're wrong it actually does ! The assembly code is somewhat a mutex implementation. It's not because you could not test it that is does not work.

    I can send my sources that do proves it works.

    Things could be different with an RTOS (e.g. FreeRTOS), but then you have RTOS' locks, so __HAL_LOCK/UNLOCK could be rewritten using RTOS locks instead of assembly code.

    And what do you think RTOS locks implementation actually are ?

    You can't just say 'disabling IT' resolve issues, as it may creates other pb, think of that :

    func1()

       disable IT

        call func2 (fun2 also disables and enables IT).

      /** YOU are doomed here !!!*/

    enable IT

    Visitor II
    January 16, 2018
    Posted on January 16, 2018 at 11:08

     ,

     ,

    Hello I agree disabling interrupts is bad practice.

    But in my particular case (CAN Tx / CAN Irq issue), after inspecting the

    CAN HAL drivers source code, I found buggy read-modify-writes on status

    data in interrupt code, that are shared with the APIs. Moreover, interrupt

    code does not call __HAL_LOCK/UNLOCK at all.

    So, modifying __HAL_LOCK/UNLOCK to become a real and strong mutex (as your

    fix, for example) would not help in this case.

    Regards,

    --Vito.

    2018-01-15 16:34 GMT+01:00 Selso LIBERADO <,st-microelectronics@jiveon.com>,:

    STMicroelectronics Community

    <,https://community.st.com/?et=watches.email.thread>,

    Re: Questions surrounding __HAL_LOCK

    reply from Selso LIBERADO

    <,

    in STM32 MCUs Forum - View the full discussion

    <,https://community.st.com/message/181294-re-questions-surrounding-hallock?commentID=181294&,et=watches.email.thread ♯ comment-181294>,

    Visitor II
    November 14, 2018

    Checked latest version of HAL libs (STM32Cube_FW_L1_V1.8.0 and STM32Cube_FW_F4_V1.21.0). Still not fixed after more then two years. Perhaps a community "fork" of these libs would at least receive fixes...

    Super User
    November 14, 2018

    ​Oh no, please. Forks IMHO is a terrible variant. ST should put these libraries on GitHub, along with other their stuff already there, and accept patches and pull requests. And use branches as needed. If Microsoft can do this, they can too. This would enable community to contribute efficiently. But ST should rule the whole project and avoid forks. </IMHO>

    -- pa

    Visitor II
    December 6, 2018

    @SFran.16​  I actually started such a thing, but as we are migrating to the LL-Hal this becomes less important for us: https://github.com/redheads/STM32Cube_FW_F3

    Explorer
    February 20, 2020

    Old thread and I expect I'm repeating what's already been said...

    The HAL lock mechanism is to protect only against incorrect implementation.

    An application with more than one producer process, should implement a single thread to arbitrate, queue and forward their output, without _ever_ hitting a lock.

    Developers want a leaner/faster HAL too.

    ST, please add a means to disable locks and argument checking.

    In Cube perhaps it'd be configured in the HAL Settings pane in Project Manager.

    It's macro, e.g. HAL_DISABLE_CHECKS, default 0 (checks are on), would be added to stm32h7xx_hal_conf.h.