cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 HAL CAN Receive Interrupt Error

Rui Loureiro
Associate II
Posted on April 03, 2017 at 17:47

I'm trying to get the STM32F4 Discovery board to transmit and receive CAN frames.

I've already got it to work with polling, now I'm trying to get the transmit and receive interrupts working. 

The transmit interrupt works flawlessly, however, the receive interrupt isn't working.

Everytime I try to send a can frame to the STM32F4, it freezes in the

HAL_CAN_RxCpltCallback function, leaving the led on.

Here is the code:

CAN configuration and interrupts priority:

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 */

    __HAL_RCC_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_FREQ_VERY_HIGH;

    GPIO_InitStruct.

Alternate

= GPIO_AF9_CAN1;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

   

/* Peripheral interrupt

init

*/

    HAL_NVIC_SetPriority(

CAN1_TX_IRQn

, 0, 2);

    HAL_NVIC_EnableIRQ(

CAN1_TX_IRQn

);

    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 */

  }

main function:

MX_GPIO_Init();

static

CanTxMsgTypeDef

        TxMessage1;

 

static

CanRxMsgTypeDef

        RxMessage1;

/*##-1- Configure the CAN peripheral #######################################*/

  CanHandle1.

Instance

= CAN1;

  CanHandle1.

pTxMsg

= &TxMessage1;

  CanHandle1.

pRxMsg

= &RxMessage1;

CAN_FilterConfTypeDef

  sFilterConfig1;

 

/*##-1- Configure the CAN peripheral #######################################*/

  CanHandle1.

Init

.

TTCM

=

DISABLE

;

  CanHandle1.

Init

.

ABOM

=

DISABLE

;

  CanHandle1.

Init

.

AWUM

=

DISABLE

;

  CanHandle1.

Init

.

NART

=

DISABLE

;

  CanHandle1.

Init

.

RFLM

=

DISABLE

;

  CanHandle1.

Init

.

TXFP

=

DISABLE

;

  CanHandle1.

Init

.

Mode

= CAN_MODE_NORMAL;

  CanHandle1.

Init

.

SJW

= CAN_SJW_3TQ;

  CanHandle1.

Init

.

BS1

= CAN_BS1_4TQ;

  CanHandle1.

Init

.

BS2

= CAN_BS2_3TQ;

  CanHandle1.

Init

.

Prescaler

= 4;

 

if

(HAL_CAN_Init(&CanHandle1) !=

HAL_OK

)

  {

   

/* Initialization Error */

    Error_Handler();

  }

 

/*##-2- Configure the CAN Filter ###########################################*/

  sFilterConfig1.

FilterNumber

= 1;

  sFilterConfig1.

FilterMode

= CAN_FILTERMODE_IDMASK;

  sFilterConfig1.

FilterScale

= CAN_FILTERSCALE_32BIT;

  sFilterConfig1.

FilterIdHigh

= 0x0000;

  sFilterConfig1.

FilterIdLow

= 0x0000;

  sFilterConfig1.

FilterMaskIdHigh

= 0x0000;

  sFilterConfig1.

FilterMaskIdLow

= 0x0000;

  sFilterConfig1.

FilterFIFOAssignment

= 0;

  sFilterConfig1.

FilterActivation

= 1;

  sFilterConfig1.

BankNumber

= 0;

 

if

(HAL_CAN_ConfigFilter(&CanHandle1, &sFilterConfig1) !=

HAL_OK

)

  {

    Error_Handler();

  }

if

(HAL_CAN_Receive_IT(&CanHandle1, CAN_FIFO0) !=

HAL_OK

)

    {

      Error_Handler();

    }

  i=0;

 

// Infinite loop

 

while

(1)

    {

   

if

(HAL_CAN_Transmit_IT(&CanHandle1) !=

HAL_OK

)

    {

     

/* Transmission Error */

      Error_Handler();

    }

    HAL_Delay(200);

    }

}

Receive interrupt callback:

void

HAL_CAN_RxCpltCallback(

CAN_HandleTypeDef

* CanHandle){

   

HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15,

GPIO_PIN_SET

);

   HAL_Delay(30);

   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_15,

GPIO_PIN_RESET

);

}

Transmit nterrupt callback:

void

HAL_CAN_TxCpltCallback(

CAN_HandleTypeDef

* CanHandle){

   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, 

GPIO_PIN_SET

);

   HAL_Delay(30);

   HAL_GPIO_WritePin(GPIOD, GPIO_PIN_14, 

GPIO_PIN_RESET

);

}

1 REPLY 1
T J
Lead
Posted on April 04, 2017 at 01:25

Hi,

running any blocking code like HAL_Delay, is likely to be your problem.

if you want to see the pulse on the scope, just use a loop bu make sure it is not removed by the compiler.

I just send blocks to the Can Tx systems without interrupts, but I use interrupts on the RX side so that I don't miss any.

I dump the Rx frame into a table of frames with 64 entries, then the foreground just looks to see if the frame buffer is empty.

ie.    if ( ! canRxMsgTableEMPTY){//process Can Rx frame}

I use these to initialise the interrupts

  __HAL_CAN_ENABLE_IT (&hcan, CAN_IT_FMP1);

  __HAL_CAN_ENABLE_IT (&hcan, CAN_IT_FMP0);

the interrupt;

void CEC_CAN_IRQHandler(void)

{

  /* USER CODE BEGIN CEC_CAN_IRQn 0 */

            CAN_IRQFlag = true;   // not needed, just used to show interrupt occurred

            checkCanRxFifos();   // clear the data before HAL sees it

  /* USER CODE END CEC_CAN_IRQn 0 */

  HAL_CAN_IRQHandler(&hcan);      // nothing to process now.

  /* USER CODE BEGIN CEC_CAN_IRQn 1 */

  /* USER CODE END CEC_CAN_IRQn 1 */

}

the Rx function;

void checkCanRxFifos(void){

    

    int readCanBytecount;

    

    char canFifo1FullFlag = CAN->RF1R & CAN_RF1R_FMP1;

    if(canFifo1FullFlag){

        {

            readCanBytecount = (CAN->sFIFOMailBox[1].RDTR &0x0f);    

            

            canFifoBuf.d32[0]             = CAN->sFIFOMailBox[1].RDLR;

            canFifoBuf.d32[1]             = CAN->sFIFOMailBox[1].RDHR;

            canRxMsgID [canRxMsgIN] = CAN->sFIFOMailBox[1].RIR >> 21;

            CAN->RF1R |= CAN_RF1R_RFOM1;                         // release FIFO

            canRxMsgLength [canRxMsgIN] = readCanBytecount;

            canRxMsgBottomWord[canRxMsgIN] = canFifoBuf.d32[0];

            canRxMsgTopWord   [canRxMsgIN] = canFifoBuf.d32[1];

            ++ canRxMsgIN &= 0x3F;    // 64 entries only

            canRxMsgTableEMPTY = false;

            if( canRxMsgIN == canRxMsgOUT) canRxMsgTableFULL = true;

        }

                CAN->IER |= CAN_IER_FMPIE1;                          // (11)        Set FIFO1 message pending IT enable

    }

    char canFifo0FullFlag = CAN->RF0R & CAN_RF0R_FMP0;

    if(canFifo0FullFlag){

        {

            readCanBytecount         = (CAN->sFIFOMailBox[0].RDTR &0x0f);    

            canFifoBuf.d32[0]     =  CAN->sFIFOMailBox[0].RDLR;

            canFifoBuf.d32[1]     =  CAN->sFIFOMailBox[0].RDHR;

            uint32_t canRxmsgID =  CAN->sFIFOMailBox[0].RIR >> 21;

            CAN->RF0R |= CAN_RF0R_RFOM0;                         // release FIFO

            if ( canRxMsgTableFULL){    

                canRxMsgTableOverflow = true;  // now dump new frame...

            }else{

                canRxMsgID [canRxMsgIN] = canRxmsgID;

                canRxMsgLength [canRxMsgIN] = readCanBytecount;

                canRxMsgBottomWord[canRxMsgIN] = canFifoBuf.d32[0];

                canRxMsgTopWord   [canRxMsgIN] = canFifoBuf.d32[1];

                ++ canRxMsgIN &= 0x3F;    // 64 entries only

                canRxMsgTableEMPTY = false;

                if( canRxMsgIN == canRxMsgOUT)

                    canRxMsgTableFULL = true;

            }

           

        }

                        CAN->IER |= CAN_IER_FMPIE0;                          // (11)        Set FIFO1 message pending IT enable

    }

}