Arman Safikhani
Arman Safikhani

Reputation: 945

STM32F1xx CAN2 receive interrupt not being called

I've successfully established CAN communication with CAN1 of two STM32F105vC(s)(Which has two CANs), and I can send and receive CAN frames.

But when I change my code to use CAN2, it works, I mean it acknowledges the received CAN frames but the receive interrupt is not being called at all.

I thought it's filter configuration, I changed the BankNumber multipletimes (tried 0, 1, 14, 20), no luck.

Here is my configurations:

Initilizing:

init_HAL_CAN(CAN2);

if(HAL_CAN_Receive_IT(canHandle, CAN_FIFO0) != HAL_OK)
{
    /* Reception Error */
    Error_Handler();
}

Receive callback:

void HAL_CAN_RxCpltCallback(CAN_HandleTypeDef* CanHandle)
{
    LED_DBG_TOGGLE();

    // other 
    // stuff 
    // here
    //...

    /* Receive */
    if(HAL_CAN_Receive_IT(CanHandle, CAN_FIFO0) != HAL_OK)
    {
        /* Reception Error */
        Error_Handler();
    }
}

Init function:

void init_HAL_CAN(CAN_TypeDef* _CANInstance)
{
    CAN_FilterConfTypeDef sFilterConfig;
    static CanTxMsgTypeDef TxMessage;
    static CanRxMsgTypeDef RxMessage;

    /*##-1- Configure the CAN peripheral #######################################*/
    canHandle->Instance = _CANInstance;
    canHandle->pTxMsg = &TxMessage;
    canHandle->pRxMsg = &RxMessage;
    canHandle->Init.TTCM = DISABLE; //Non time trigger communication mode //
    canHandle->Init.ABOM = DISABLE;  //The software automatically Bus-off management     //
    canHandle->Init.AWUM = DISABLE; //Sleep mode wake by software (clear CAN-> MCR SLEEP) (automatic wake-up mode)//
    canHandle->Init.NART = DISABLE;  //Disable automatic transfer message (non-automatic retransmission mode)//
    canHandle->Init.RFLM = DISABLE; //The message is not locked, the new cover the old // 
    canHandle->Init.TXFP = DISABLE; // Priority is determined by the message identifier //

    canHandle->Init.Mode = CAN_MODE_NORMAL;
    canHandle->Init.SJW = CAN_SJW_1TQ;
    canHandle->Init.BS1 = CAN_BS1_2TQ;
    canHandle->Init.BS2 = CAN_BS2_1TQ;
    canHandle->Init.Prescaler = 7;

    if(HAL_CAN_Init(canHandle) != HAL_OK)
    {
        /* Initialization Error */
        Error_Handler();
        return false;
    }

    /*##-2- Configure the CAN Filter ###########################################*/
    CAN_FilterConfTypeDef sFilterConfig;
    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 = 20;

    if (HAL_CAN_ConfigFilter(canHandle, &sFilterConfig) != HAL_OK)
    {
        /* Filter configuration Error */
        Error_Handler();
        return false;
    }

}

IRQHandler (placed in stm32f1xx_it.c):

void CAN2_RX0_IRQHandler(void)
{
    HAL_CAN_IRQHandler(canHandle);
}

MspInit function (placed in stm32f1xx_hal_msp.c) :

void HAL_CAN_MspInit(CAN_HandleTypeDef *hcan)
{
    GPIO_InitTypeDef   GPIO_InitStruct;

    /*##-1- Enable peripherals and GPIO Clocks #################################*/
    /* CAN1 Periph clock enable */
    CANx1_CLK_ENABLE(); // Need to enable CAN1 clock too.
    CANx2_CLK_ENABLE();
    /* Enable GPIO clock ****************************************/
    CANx2_GPIO_CLK_ENABLE();
    /* CAN2 needs no remapping *******/

    /*##-2- Configure peripheral GPIO ##########################################*/
    /* CAN1 TX GPIO pin configuration */
    GPIO_InitStruct.Pin = CANx2_TX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Pull = GPIO_PULLUP;

    HAL_GPIO_Init(CANx2_TX_GPIO_PORT, &GPIO_InitStruct);

    /* CAN1 RX GPIO pin configuration */
    GPIO_InitStruct.Pin = CANx2_RX_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Pull = GPIO_PULLUP;

    HAL_GPIO_Init(CANx2_RX_GPIO_PORT, &GPIO_InitStruct);

    /*##-3- Configure the NVIC #################################################*/
    /* NVIC configuration for CAN2 Reception complete interrupt */

    HAL_NVIC_SetPriority(CAN2_RX0_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(CAN2_RX0_IRQn);

}

I should mention again, that following codes works perfectly with CAN1 (of course with changing CAN2 to CAN1, etc).

And it's clear that the CAN controller is working because the other board that is transmitting CAN frames, receives the acknowledges (and does not get any transmitting error or timeout), the only problem here is Receive Interrupts, why?

Upvotes: 1

Views: 6953

Answers (2)

FoxVK
FoxVK

Reputation: 77

You must perform settings of all filters through hcan1. Even for Can2.

In connectivity line devices, the registers from offset 0x200 to 31C are present only in CAN1.

...and on offset 0x200 begins filter settings...

Upvotes: 0

Marcin Gajewski
Marcin Gajewski

Reputation: 61

I had similar issue and what help was reference manual:

CAN2SB[5:0]: CAN2 start bank

These bits are set and cleared by software. They define the start bank for the CAN2 interface (Slave) in the range 0 to 27.

Note: When CAN2SB[5:0] = 28d, all the filters to CAN1 can be used.

When CAN2SB[5:0] is set to 0, no filters are assigned to CAN1 sFilterConfig.BankNumber = 20;

Please change sFilterConfig.BankNumber = 20;

to

sFilterConfig.BankNumber = 0x2d;

Upvotes: 3

Related Questions