cancel
Showing results for 
Search instead for 
Did you mean: 

Bug Report: CAN HAL Drivers in STM32CubeF4

lars
Associate II
Posted on September 02, 2014 at 12:33

Hi,

I have discovered several unfortunate behaviors of the HAL CAN module in the Cube package according to how I would like to use it. Please read through them and let me know your input.

1. HAL_CAN_Transmit for polled CAN transmission waits until the CAN BUS message has been clocked to the BUS instead of just checking the HW tx buffers, putting it to the HW buffer, returning OK and moving on. This means it takes 500+ microseconds to send just a single CAN message at 250Kbit where the CPU is just wasted in a spin lock. I don't really see why you would need this functionality but fair enough. My complaint is that you cannot use the HAL_CAN_Transmit to skip this timeout functionality of waiting for the message to be clocked to the bus. If you give a timeout parameter of zero, then the function will return HAL_TIMEOUT even though it was put to the HW buffer just fine and will be transmitted shortly. Suggested change: if the timeout parameter is zero, skip all the timeout functionality, put the message to the HW buffer if one is free and return HAL_OK. I am aware that this will also have an impact on the HAL CAN modules internal State variable but that shouldn't matter for the polled functionality (and the internal state variable really shouldn't be used). Alternatively a HAL_CAN_Transmit_NonBlocking function could be made with this functionality. Any input?

2. It seems the HAL_CAN_Transmit_IT function does not use the three CAN HW buffers since it will never pass the condition in the start of the function if there is a transmission in progress.:

if((tmp == HAL_CAN_STATE_READY) || (tmp == HAL_CAN_STATE_BUSY_RX))

This means the function will never be able to put a second CAN message in the HW buffer if the HW buffer already has a single CAN message in it causing performance issues? I can see how the HAL CAN state variable can be nice for debugging purposes etc, but really don't think this sw CAN state should be used in the behavior of the HAL CAN drivers - we should instead use the CAN control registers - e.g. do we have a free slot in the HW CAN buffer then put the CAN message in it and return OK, without depending on the CAN state software variable. Unless I have misread the code it really seems to me that using HAL_CAN_Transmit_IT we only use one third of our available HW CAN buffers. Any Input?

3. General missing HAL_UNLOCK calls lots of places in the HAL CAN module in the case of bus errors. (Already reported as far as I can see)

I have fixed all the above bugs in my own git repo of the cube package but I'm sure someone else will appreciate the above fixes went into the next cube package as well.

Thanks,

Lars

#bug #timeout #can #stm32cubef4
11 REPLIES 11
lars
Associate II
Posted on September 02, 2014 at 14:20

Also the HAL_UNLOCK calls in HAL_CAN_Init makes no sense and looks like copy-paste errors since we never use the HAL_LOCK in that function.

Posted on September 03, 2014 at 12:13

Hi,

Thanks for the feedbacks, Lars. 

Please find below the approprite inputs for each point:

1. It is not sufficient to check the HW TX buffers for successful transmission, in fact RQCP and TXOK must be also checked please see below the underlined line taken from Reference Manual.

The check of the previous bits is done in __HAL_CAN_TRANSMIT_STATUS() within the stm32f4xx_hal_can.h file.

0690X00000605XoQAI.png

2. We understand that this is a limitation that some of you are experiencing, especially with COM IPs with FIFO, resulting the inability to launch many IT transmissions at the same time despite a FIFO is present to stock transmitted messages. We?ll pass it along to our STM32Cube team.

3. This point is already reported and answred [DEAD LINK /public/STe2ecommunities/mcu/Lists/STM32Java/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/STM32Java/CAN-Bus%20Problems&currentviews=2]here.

Hope that this answers your questions.

Thanks for your participation!

Regards.
rm239955
Associate II
Posted on January 26, 2015 at 09:26

Hallo

Even I have found some bugs in STM32  Cube F4 of HAL CAN Module.

After Initalizing the filters and FIFo's for CAN2 module ,the CAN2 Receiver doesn't respond to the proper IDs and it always gets set to the HAL_Lock mechanism.

Though the transmitter bug has been fixed now,but the receiver still has some which is to be cleared

schauhan112
Associate II
Posted on January 29, 2015 at 17:50

Hi,

Can anyone confirm if the issues with CAN driver mentioned in this post have been fixed in the latest version of STM32Cube F4 (version 1.4 dated 12/26/2014). 

Lars,

Can you post the fixed up version of CAN driver so others may also benefit. 

Thanks.

Posted on March 26, 2015 at 18:37

Hi,

latest version of STM32CubeF4 (V1.5.0 / 13-March-2015) doesn't include any fix in CAN drivers, and all issues with CAN_Transmit_IT still here ..

Lars, can you share the fixed up version of CAN driver ?

Thank you.

lars
Associate II
Posted on March 30, 2015 at 14:22

Hi, I hope you (aka ''ABCD'') have figured out the CAN1/CAN2 filtering by now, but in case others can benefit:

I ran into similar problems when configuring the filter settings using the ST HAL for the second CAN-bus until I noticed the CANHandle parameter for HAL_CAN_ConfigFilter is not used in the HAL. You have to set up the filter bank split yourself between CAN1 and CAN2 - the two CAN busses are not independent of each other. E.g:

    CAN_FilterConfTypeDef sFilterConfig;

    sFilterConfig.FilterIdHigh = 0x0000;

    sFilterConfig.FilterIdLow = 0x0000;

    sFilterConfig.FilterMaskIdHigh = 0x0000;

    sFilterConfig.FilterMaskIdLow = 0x0000;

    sFilterConfig.FilterActivation = ENABLE;

    sFilterConfig.BankNumber = 14;

    // Set up CAN1 for hw CAN fifo0 and filter number0

    sFilterConfig.FilterNumber = 0;

    sFilterConfig.FilterFIFOAssignment = 0;

    // Note I have removed the unused CANHandle parameter from the ST Hal layer since it only confuses and is not used

    assert( HAL_CAN_ConfigFilter( &sFilterConfig ) == HAL_OK );

    // The filter bank split between CAN1/CAN2 is 14, so we set up filter 15 for CAN2 and connect it to FIFO1

    sFilterConfig.FilterNumber = 15;

    sFilterConfig.FilterFIFOAssignment = 1;

    assert( HAL_CAN_ConfigFilter( &sFilterConfig ) == HAL_OK );

To avoid future confusion, I removed the CANHandle parameter from the filter call.

lars
Associate II
Posted on March 30, 2015 at 14:28

Sorry for the late reply, I have not checked this forum lately and didn't get any notifications.

I am unsure how to best contribute my changes - can any ST representative tell me the preferred approach? A git patch etc? Am I allowed to distribute my changes?

Regarding the bad hw buffer utilization with interrupt based CAN communication - then I have not made any fixes regarding this since I instead used it polled. (but have made changes to HAL_CAN_Transmit to avoid unnecessary spinlocks).

mario239955_st
Associate II
Posted on March 31, 2015 at 11:00

Hello everyone,

is for many days that I try to run the bus can, I use eclipse with FreeRTOS and hal driver. Please, who I share an example ??

 my main is:

int main(void)

{

HAL_Init();

BSP_LED_Init(LED3);

BSP_LED_Init(LED4);

BSP_PB_Init(BUTTON_KEY, BUTTON_MODE_GPIO);

SystemClock_Config();

/* Initialize all configured peripherals */

GPIO_Init();

CAN1_Init(&canTxHandle);

CAN2_Init(&canRxHandle);

/* Infinite loop */

BSP_LED_Off(LED3);

BSP_LED_Off(LED4);

/*##-3- Start the Transmission process #####################################*/

canTxHandle.pTxMsg = &TxMessage;

canTxHandle.pTxMsg->ExtId = 0x04214006;

canTxHandle.pTxMsg->RTR = CAN_RTR_DATA;

canTxHandle.pTxMsg->IDE = CAN_ID_EXT;

canTxHandle.pTxMsg->DLC = 8;

canTxHandle.pTxMsg->Data[0] = 0xaa; /* 100 km/h for the bits corresponding to ''speed'' */

canTxHandle.pTxMsg->Data[1] = 0xaa;

for(;;){

while (HAL_CAN_GetState(&canTxHandle) != HAL_CAN_STATE_READY) {

BSP_LED_On(LED4);

//osDelay(500);

HAL_Delay(500);

BSP_LED_Off(LED4);

}

while (HAL_CAN_GetState(&canTxHandle) == HAL_CAN_STATE_READY) {

HAL_CAN_Transmit(&canTxHandle,500);

BSP_LED_On(LED3);

//osDelay(500);

HAL_Delay(500);

BSP_LED_Off(LED3);

}

}

/* We should never get here as control is now taken by the scheduler */

while (1)

{}

}

But, the bus can not transmit because HAL_CAN_Transmit return HAL_CAN_STATE_TIMEOUT.

Whats is the problem??? :(

vromanov
Associate II
Posted on March 31, 2015 at 22:17

maybe you forget to wakeup CAN?

static bool init_can_device(CAN_HandleTypeDef* hcan, const char* name) {

    HAL_StatusTypeDef status;

    if ((status = HAL_CAN_WakeUp(hcan)) != HAL_OK) {

        DPRINTF(''%s can't wakeup. Status=%d, Can State=%d error-code=%'' PRIu32 ''\r\n'', name, status, hcan->State, hcan->ErrorCode);

        return false;

    }

}