cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F429 - CAN stop IT stops firing randomly

Just Matt
Associate III
Posted on February 08, 2016 at 21:56

Hi,

I'm using a STM32F429 disco board. I used the CubeMX to gen my HAL. Everything works pretty great, except for after a while my CAN IT stops firing. Here is my code below. In the HAL_CAN_RxCpltCallback, the HandleCanEvent does some slight data manipulation then transmits this info back on the bus. It appears that when the CAN bus is very active is when the IT stops firing and I have to reset the Micro. Why would my Interrupt stop firing? Any thoughts?

void
HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{ 
HAL_GPIO_TogglePin(GPIOG, LD4_Pin); 
// Da activity LED
//Now process crap
canConversionFactory->HandleCanEvent(CanHandle);
/* Receive */
if
(HAL_CAN_Receive_IT(CanHandle, CAN_FIFO0) != HAL_OK)
{
/* Reception Error */
//TODO implement handeling
}
}
void
CAN1_RX0_IRQHandler(
void
)
{
/* USER CODE BEGIN CAN1_RX0_IRQn 0 */
/* USER CODE END CAN1_RX0_IRQn 0 */
HAL_CAN_IRQHandler(&hcan1);
/* USER CODE BEGIN CAN1_RX0_IRQn 1 */
/* USER CODE END CAN1_RX0_IRQn 1 */
}
void
HAL_CAN_MspInit(CAN_HandleTypeDef* hcan)
{
GPIO_InitTypeDef GPIO_InitStruct;
if
(hcan->Instance==CAN1)
{
/* USER CODE BEGIN CAN1_MspInit 0 */
/* USER CODE END CAN1_MspInit 0 */
/* Peripheral clock enable */
CAN1_CLK_ENABLED++;
if
(CAN1_CLK_ENABLED==1){
__CAN1_CLK_ENABLE();
}
/**CAN1 GPIO Configuration 
PB8 ------> CAN1_RX
PB9 ------> CAN1_TX 
*/
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral interrupt init*/
HAL_NVIC_SetPriority(CAN1_RX0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN1_RX0_IRQn);
/* USER CODE BEGIN CAN1_MspInit 1 */
/* USER CODE END CAN1_MspInit 1 */
}
else
if
(hcan->Instance==CAN2)
{
/* USER CODE BEGIN CAN2_MspInit 0 */
/* USER CODE END CAN2_MspInit 0 */
/* Peripheral clock enable */
__CAN2_CLK_ENABLE();
CAN1_CLK_ENABLED++;
if
(CAN1_CLK_ENABLED==1){
__CAN1_CLK_ENABLE();
}
/**CAN2 GPIO Configuration 
PB5 ------> CAN2_RX
PB6 ------> CAN2_TX 
*/
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_CAN2;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral interrupt init*/
HAL_NVIC_SetPriority(CAN2_RX0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(CAN2_RX0_IRQn);
/* USER CODE BEGIN CAN2_MspInit 1 */
/* USER CODE END CAN2_MspInit 1 */
}
}
HAL_StatusTypeDef CanDriver::InitializeCan1(BaudRate baudRate)
{
if
(!hcan1)
return
HAL_ERROR;
if
(!baudRate)
return
HAL_ERROR;
hcan1->Instance = CAN1;
static
CanTxMsgTypeDef TxMessage;
static
CanRxMsgTypeDef RxMessage;
if
(baudRate == 
this
->BITRATE_500k)
{
hcan1->Init.Prescaler = 4;
hcan1->Init.SJW = CAN_SJW_1TQ ;
hcan1->Init.BS1 = CAN_BS1_14TQ ;
hcan1->Init.BS2 = CAN_BS2_6TQ ;
}
else
if
(baudRate == 
this
->BITRATE_250k)
{
//TODO 
}
else
//Assume 500k
{
hcan1->Init.Prescaler = 4;
hcan1->Init.SJW = CAN_SJW_1TQ ; 
// This is for 500k can
hcan1->Init.BS1 = CAN_BS1_14TQ ;
hcan1->Init.BS2 = CAN_BS2_6TQ ;
}
hcan1->Init.TTCM = DISABLE;
hcan1->Init.ABOM = DISABLE;
hcan1->Init.AWUM = DISABLE;
hcan1->Init.NART = DISABLE;
hcan1->Init.RFLM = DISABLE;
hcan1->Init.TXFP = DISABLE;
//Setup the empty Rx/Tx
hcan1->pRxMsg = &RxMessage;
hcan1->pTxMsg = &TxMessage;
HAL_StatusTypeDef can1SetupStatus = HAL_CAN_Init(hcan1);
HAL_StatusTypeDef can1FilterStatus = 
this
->InitializeOpenFilters(CANBUS1);
if
(HAL_CAN_Receive_IT(hcan1, CAN_FIFO0) != HAL_OK) 
// Start listning
{
return
HAL_ERROR;
}
return
can1SetupStatus;
}
HAL_StatusTypeDef CanDriver::InitializeOpenFilters(
int
bus)
{
if
(bus < 1 || bus > 2)
return
HAL_ERROR;
CAN_FilterConfTypeDef sFilterConfig;
/*##-2- Configure the CAN Filter ###########################################*/
sFilterConfig.FilterNumber = 0;
sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK ;
sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT ;
sFilterConfig.FilterIdHigh = 0x0000;
sFilterConfig.FilterIdLow = 0x0000;
sFilterConfig.FilterMaskIdHigh = 0x0000;
sFilterConfig.FilterMaskIdLow = 0x0000;
sFilterConfig.FilterFIFOAssignment = 0;
sFilterConfig.FilterActivation = ENABLE;
sFilterConfig.BankNumber = 14;
if
(bus == CANBUS1)
return
HAL_CAN_ConfigFilter(hcan1, &sFilterConfig);
if
(bus == CANBUS2)
return
HAL_CAN_ConfigFilter(hcan2, &sFilterConfig);
return
HAL_ERROR;
//we should never get here
}

7 REPLIES 7
Posted on February 08, 2016 at 22:27

Why would my Interrupt stop firing? Any thoughts?

Some overflow or error condition. Check if the peripheral status registers are flagging anything.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Just Matt
Associate III
Posted on February 09, 2016 at 17:21

As always, thanks for the reply clive.

I checked CAN_ESR, and nothing is getting set or shown there. I have in the main look a heartbeat sent over the same CAN bus, and it continues to be sent no problem. 

I agree with your assessment it has to be an overflow, but i'm not sure how to get down to debug that exactly.

Any other advice? 🙂

Thanks,

-Matt

Posted on February 09, 2016 at 17:31

The HAL is not my thing, so my advise will be general.

For CAN Rx you need to pay attention to how much is in the FIFO, and making sure you clear everything out. This is especially important in the IRQ handling side, that you check again before you leave, in case it filled up while you were processing the previous packets.

As I recall the peripheral returns the current depth of the FIFO, you should iterate the processing loop until this is zero

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Just Matt
Associate III
Posted on February 10, 2016 at 17:09

Thanks Clive!

I have tried this by checking the fifo for messages and clearing it out before resetting the interrupt. With the following

while
((uint8_t)(CanHandle->Instance->RF0R&(uint32_t)0x03) > 0)
{
HAL_CAN_Receive(CanHandle, 0, 500);
//Now process crap
canConversionFactory->HandleCanEvent(CanHandle); 
}

The problem is that FMPIE0 is getting reset for some reason, and i'm almost certain that it's because the FIFO is overflowing. (FOVR0 and FULL0 are getting set.) Maybe I just can't clear it out fast enough, which doesn't make since with this micro. My bandaid is the following in the main loop until I can figure this out :\

//Canbus poor mans watchdog
if
(hcan1.Instance->IER == 0x00008f00)
hcan1.Instance->IER = 0x00008f02;

Cheers -Matt
Just Matt
Associate III
Posted on February 10, 2016 at 18:14

I just realized in the interrupt that when i check

CanHandle->Instance->RF0R & 0x03

during the CAN_RxCpltCallback that its returning zero, so its not iterating. It doesn't matter if I check it before or after clearing the interrupt. I'm confused why this is, i thought checking this directly would give me the number of messages pending in the FIFO. Any thoughts?
Just Matt
Associate III
Posted on February 15, 2016 at 16:55

For anyone who is experiencing similar problems. The issue is in the HAL somewhere. 

Re-wrote the application in the StdPerph library, and works a treat without issue with 10ms timing. 

#HALFail
MehranMsba
Associate II
Posted on April 07, 2016 at 20:05

I had same problem. I read your last post and I decided to change HAL but I couldn't use standard library in last steps of my project. I traced the problem and found that.

Problem is Lock mechanism in HAL system, If you use RTOS or interrupt base program, HAL can make problem [ST: this versions of HAL doesn't support OS.]

For example, We have a thread to write data in CAN bus and read data with interrupt from bus. Interrupt routine collect data from bus and put into a queue for another thread.

If bus make an interrupt when we executed transmission function, then lock mechanism didn't let receive function work, So interrupt routine do nothing and uncleared interrupt flag generate new interrupt again and again and again!!!. So unlocking never execute from transmission function.

FIFO will overflow after three times of this situation and then CAN controller can't receive data correctly.

Functions that used in interrupt must be fast and have not lock mechanism.

This is problem of  HAL_CAN_IRQHandler and see in HAL_CAN_Receive too.

Also:

ARM CMSIS documentation says: Mutex can not work in Interrupt routine.

[Mutex: have same behavior with lock.]

Good luck.