cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 F7 HAL CAN bug

Paolo Chiantore
Associate II
Posted on March 21, 2017 at 15:31

We are using HAL CAN drivers for STM32 F7 (stm32f7xx_hal_can.c).

During CAN tx/rx stress tests we experienced an issue resulting in CAN receive hang.

The issue is due to a race condition on hcan->State variable between HAL_CAN_Transmit_IT  and CAN_Receive_IT.

The issue arises in the following conditions:

  1. hcan->State  is

    HAL_CAN_STATE_BUSY_RX

  2. HAL_CAN_Transmit_IT is called and enters condition 

    if

    (hcan->

    State

    ==

    HAL_CAN_STATE_BUSY_RX

    )

  3. right after this, CAN_Transmit_IT is preempeted  by a CAN receive interrupt
  4. Within the CAN receive interrupt handler CAN_Receive_IT is called
  5. CAN_Receive_IT  sets 

    hcan->

    State

    =

    HAL_CAN_STATE_READY

  6. HAL_CAN_Transmit_IT resumes execution after the if at point2 and sets 

    hcan->

    State

    =

    HAL_CAN_STATE_BUSY_TX_RX

The final result is that when exiting HAL_CAN_Transmit_IT hcan->State is

HAL_CAN_STATE_BUSY_TX_RX

while it should have been

HAL_CAN_STATE_BUSY_TX

. From now on every attempt of further receptions with HAL_CAN_Receive_IT will fail.

Has someone experienced this issue before?

Are there avilable solutions to this HAL bug from ST?

13 REPLIES 13
Posted on May 18, 2017 at 20:49

They also have more rx-tx states and better handling of them , though to me it still seems like band-aid code, just a bit better one

Posted on May 22, 2017 at 11:20

I still haven't had a chance to test this new version of the HAL driver, but I can't see how these few extra states will make a difference to this problem, and they seem to be handled in more or less the same way still. As

Synter.Indrek

‌ suggests, a critical section somewhere might help (although the __HAL_LOCK macro is meant to do this to some effect from what I can tell - at least stop the HAL state writes being interrupted.). For my project I've just disabled interrupts around the HAL CAN TX call, although this isn't a good solution in general, but it works in my case.

Posted on May 22, 2017 at 11:31

I've just realised that the CAN_Receive_IT function doesn't use the __HAL_LOCK macro, which is what's causing the issue. Tricky though, as this function does need to release the CAN state from being busy no matter what. Seems like the way to go is put some critical section around writes to the state variable.

Posted on June 15, 2017 at 12:14

I've done it in a much simpler way

No need to lock/unlock anything

My application guarantees fixed rate of incoming messages

I tuned sheduler to launch specific task slightly more often than the said rate

The task merely does the following

if (__HAL_CAN_MSG_PENDING(&hcan, CAN_FIFO0) != 0U)

{

if ( (((&hcan)->Instance->sFIFOMailBox[CAN_FIFO0].RDTR) & 0x0FU) == _VALID_LENGTH)

{

UpdTimeout(&stRx_TO);

DoAllTheseThings(((&hcan)->Instance->sFIFOMailBox[CAN_FIFO0].RDLR), ((&hcan)->Instance->sFIFOMailBox[CAN_FIFO0].RDHR));

}

__HAL_CAN_FIFO_RELEASE(&hcan, CAN_FIFO0);

}