2016-02-08 12:56 PM
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
}
2016-02-08 01:27 PM
Why would my Interrupt stop firing? Any thoughts?
Some overflow or error condition. Check if the peripheral status registers are flagging anything.2016-02-09 08:21 AM
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,-Matt2016-02-09 08:31 AM
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 zero2016-02-10 08:09 AM
Thanks Clive!
I have tried this by checking the fifo for messages and clearing it out before resetting the interrupt. With the followingwhile
((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
2016-02-10 09:14 AM
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?
2016-02-15 07:55 AM
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. #HALFail2016-04-07 11:05 AM
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.