2015-04-15 01:27 PM
If you use HAL_CAN_Receive_IT for receive and send messages at same time you can get race condition. Typical callback looks like:
void
HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle) {
if
((CanHandle->pRxMsg->StdId == 0x321) && (CanHandle->pRxMsg->IDE == CAN_ID_STD) && (CanHandle->pRxMsg->DLC == 2)) {
if
(CanHandle->pRxMsg->Data[0]) {
LED_GREEN_ON();
}
else
{
LED_GREEN_OFF();
}
}
/* Receive */
if
(HAL_CAN_Receive_IT(CanHandle, CAN_FIFO0) != HAL_OK) {
/* Reception Error */
Error_Handler(1, 20);
}
}
If interrupt occurs when HAL_CAN_Transmit (or other) is called,
HAL_CAN_Receive_IT
will return HAL_BUSY because can handle is locked. I can reproduce this error in 100% if loopback mode is used.
I attach sample code to reproduce this. my_main() must be called inside generated main.c
#cubemx #bug #bxcan #stm32f2
2015-04-15 01:53 PM
This bug is very critical for me. It make CAN part of cubemx useless :(.
2015-04-16 01:19 AM
// ideally, we should be able to call HAL_CAN_Receive_IT() here to set up for another
// receive but the API is flawed because that function will fail if HAL_CAN_Transmit*()
// had already locked the handle when the receive interrupt occurred - so we do what
// HAL_CAN_Receive_IT() would do
if(hcan->State == HAL_CAN_STATE_BUSY_TX)
hcan->State = HAL_CAN_STATE_BUSY_TX_RX;
else {
hcan->State = HAL_CAN_STATE_BUSY_RX;
/* Set CAN error code to none */
hcan->ErrorCode = HAL_CAN_ERROR_NONE;
/* Enable Error warning Interrupt */
__HAL_CAN_ENABLE_IT(hcan, CAN_IT_EWG);
/* Enable Error passive Interrupt */
__HAL_CAN_ENABLE_IT(hcan, CAN_IT_EPV);
/* Enable Bus-off Interrupt */
__HAL_CAN_ENABLE_IT(hcan, CAN_IT_BOF);
/* Enable Last error code Interrupt */
__HAL_CAN_ENABLE_IT(hcan, CAN_IT_LEC);
/* Enable Error Interrupt */
__HAL_CAN_ENABLE_IT(hcan, CAN_IT_ERR);
}
// Enable FIFO 0 message pending Interrupt
__HAL_CAN_ENABLE_IT(hcan, CAN_IT_FMP0);
2015-04-16 04:07 AM
Many thnx!
This code fix problem!2015-04-17 12:29 AM
In fact I believe you still have a race condition in the modified code.
Let' s assume you have a transmit under interrupt in progress when calling the modified receive_It. If you happen to get and ''end of transmission flag'' the hcan->State will be modified. In both (original and modified) version of receive_It you have the following sequence: if(hcan->State == HAL_CAN_STATE_BUSY_TX) { /* Change CAN state */ hcan->State = HAL_CAN_STATE_BUSY_TX_RX; } else { /* Change CAN state */ hcan->State = HAL_CAN_STATE_BUSY_RX; } In case the previously mentionned interrupt happens after readind state for the ''if'' statement, but before writng the new value, then the state will be corrupted. This is a very short time window but it may (and so it will one day or the other) happen. I already mentionned that issue on the forum (for the UART Hal) but did not get any answer. Gerard2015-04-17 07:00 AM
2015-09-18 03:17 PM
September 18th, 2015.
I can confirm that this bug still exists in the latest F4 library (1.8.0).The workaround for HAL_CAN_Receive_IT, as shown at the top of the discussion does work and should be a good clue to the ST development team.Andrei from The Great White North