AnsweredAssumed Answered

leaving CAN intialization mode fails (MSR->INAK not reset)

Question asked by Sebastian Ulrich on Apr 25, 2017
Latest reply on Sep 27, 2017 by Sebastian Ulrich

Hi.

 

I’ve tried to migrate our existing STM32F4 CAN driver to the STM32F302R8 controller. We use the NUCLEO-F302R8 boards for testing. Our driver uses the functionality of the Standard Peripherals Library to configure the CAN peripheral.

 

After building and debugging the adapted code, the CAN receive interrupt routine (and the CAN error interrupt routine as well) were never entered. After further debugging the CAN initialization turned out to be done not correctly.

 

The exact part of the code is inside the “CAN_Init” Standard Peripherals library function of the file “stm32f30x_can.c” just after trying to leave the initialization mode. The write operation to the MCR register is executed correctly, as far as I can see it in the debuggers register table. While waiting for the hardware to set the “INAK” bit in the MSR register, a timeout occurs. (The “wait_ack” variable reaches the value 0xFF FFFF, specified as “INAK_TIMEOUT”). These Instructions are located at line 276ff in the version of the file on my hands. A test with the new HAL configured via STM32CubeMX got stuck at the same instruction.

 

The existing CAN driver is already working on the STM32F407VG controller. Therefore, I think I can exclude the library (or its structure) as an error reason. I only changed some identifiers, due to differences in the header files between the two controllers. Of course, I’ve done a recalculation of the bit timing values to setup the baud rate correctly.

 

Can someone help me with this issue?

Thanks in advance.

 

For better comprehension, I included the source code of the CAN intialization routine.

 

void LibRS_CAN_Init(LibRS_CAN_Init_t* RS_CAN_InitStruct)
{
     // Initialize the FIFO ring buffers
     if (RS_CAN_InitStruct->CANx == CAN1)
     {
          LibRS_CAN_TxBufferInit(&CAN1_TxBuffer);
#ifdef CAN_BUFFERED_RX
          LibRS_CAN_RxBufferInit( &CAN1_RxBuffer);
#endif
     }
#if !defined(STM32F3R8)
     if (RS_CAN_InitStruct->CANx == CAN2)
     {
          LibRS_CAN_TxBufferInit(&CAN2_TxBuffer);
#ifdef CAN_BUFFERED_RX
          LibRS_CAN_RxBufferInit( &CAN2_RxBuffer);
#endif
     }
#endif

     GPIO_InitTypeDef GPIO_InitStructure;
     CAN_InitTypeDef CAN_InitStructure;
     uint16_t prescaler;

     // APB1_CLOCK in K / TIME_QUANTS * BIT_RATE
     prescaler = 42000 / (21 * RS_CAN_InitStruct->Baudrate);

#if !defined(STM32F3R8)
     // Init Clock for CAN
     RCC_AHB1PeriphClockCmd(RCC_GetGPIOClock(RS_CAN_InitStruct->RxPort), ENABLE);
     RCC_AHB1PeriphClockCmd(RCC_GetGPIOClock(RS_CAN_InitStruct->TxPort), ENABLE);
#else // only AHB bus on STM32F302R8
     RCC_AHBPeriphClockCmd(RCC_GetGPIOClock(RS_CAN_InitStruct->RxPort), ENABLE);
     RCC_AHBPeriphClockCmd(RCC_GetGPIOClock(RS_CAN_InitStruct->TxPort), ENABLE);
#endif

     // Activate Clock and map CAN
     if (RS_CAN_InitStruct->CANx == CAN1)
     {
          RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1, ENABLE);

#if !defined(STM32F3R8)
          GPIO_PinAFConfig(RS_CAN_InitStruct->RxPort, GPIO_GetPinSource(RS_CAN_InitStruct->RxPin), GPIO_AF_CAN1);
          GPIO_PinAFConfig(RS_CAN_InitStruct->TxPort, GPIO_GetPinSource(RS_CAN_InitStruct->TxPin), GPIO_AF_CAN1);
#else
          // different definitions for alternate functions on STM32F302R8
          GPIO_PinAFConfig(RS_CAN_InitStruct->RxPort, GPIO_GetPinSource(RS_CAN_InitStruct->RxPin), GPIO_AF_7);
          GPIO_PinAFConfig(RS_CAN_InitStruct->TxPort, GPIO_GetPinSource(RS_CAN_InitStruct->TxPin), GPIO_AF_7);
#endif
     }
#if !defined(STM32F3R8) // CAN2 not available on STM32F302R8
     if(RS_CAN_InitStruct->CANx == CAN2)
     {
          RCC_APB1PeriphClockCmd((RCC_APB1Periph_CAN1 | RCC_APB1Periph_CAN2), ENABLE);

          GPIO_PinAFConfig(RS_CAN_InitStruct->RxPort, GPIO_GetPinSource(RS_CAN_InitStruct->RxPin), GPIO_AF_CAN2);
          GPIO_PinAFConfig(RS_CAN_InitStruct->TxPort, GPIO_GetPinSource(RS_CAN_InitStruct->TxPin), GPIO_AF_CAN2);
     }
#endif

     // Init GPIOs for CAN
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
     GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
     GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

     GPIO_InitStructure.GPIO_Pin = RS_CAN_InitStruct->RxPin;
     GPIO_Init(RS_CAN_InitStruct->RxPort, &GPIO_InitStructure);
     GPIO_InitStructure.GPIO_Pin = RS_CAN_InitStruct->TxPin;
     GPIO_Init(RS_CAN_InitStruct->TxPort, &GPIO_InitStructure);

     CAN_DeInit(RS_CAN_InitStruct->CANx);

#if !defined(STM32F3R8)
     CAN_InitStructure.CAN_Prescaler = prescaler; //Prescaler: 1..1024
     CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;//Synchronisation Jump Width: shorten or lengthen bit for resynchronisation CAN1WJ_1tq..CAN1WJ_4tq
     CAN_InitStructure.CAN_BS1 = CAN_BS1_14tq;//Time Quantum BS1: CAN_BS1_1tq..CAN_BS16tq
     CAN_InitStructure.CAN_BS2 = CAN_BS2_6tq;//Time Quantum BS2: CAN_BS1_1tq..CAN_BS8tq
#else
     // same as above
     CAN_InitStructure.CAN_Prescaler = 9; // 500kbit/s and 1Mbit/s possible
     CAN_InitStructure.CAN_SJW = CAN_SJW_1tq;
     if (RS_CAN_InitStruct->Baudrate == CAN_BR_1M)
     {
          CAN_InitStructure.CAN_BS1 = CAN_BS1_8tq;
          CAN_InitStructure.CAN_BS2 = CAN_BS2_3tq;
     }
     else // 500kbit/s default
     {
          CAN_InitStructure.CAN_BS1 = CAN_BS1_5tq;
          CAN_InitStructure.CAN_BS2 = CAN_BS2_2tq;
     }
#endif
     CAN_InitStructure.CAN_Mode = CAN_Mode_Normal; //Mode: everything but normal is for debugging only
     CAN_InitStructure.CAN_TTCM = DISABLE; //Time Triggered Communication Mode: save times for TX/RX
     CAN_InitStructure.CAN_ABOM = RS_CAN_InitStruct->CAN_ABOM; //Automatic-Bus-Off Management: 255 transmit-errors cause bus of, if enable, can switches back on again after receiving 128x11 recessive bits
     CAN_InitStructure.CAN_AWUM = DISABLE; //Automatic Wakeup-Mode
     CAN_InitStructure.CAN_NART = RS_CAN_InitStruct->CAN_NART; //No automatic Retransmission
     CAN_InitStructure.CAN_RFLM = DISABLE; //Receive FIFO locked mode: in Case of overflow delete or hold old message
     CAN_InitStructure.CAN_TXFP = DISABLE; //Transmit FIFO Priority
     CAN_Init(RS_CAN_InitStruct->CANx, &CAN_InitStructure);

     // Filter Init: Alle IDs empfangen
     CAN_FilterInitTypeDef CAN_FilterInitStructure;
     CAN_FilterInitStructure.CAN_FilterMode = CAN_FilterMode_IdMask;
     CAN_FilterInitStructure.CAN_FilterScale = CAN_FilterScale_32bit;
     CAN_FilterInitStructure.CAN_FilterIdHigh = 0x0000;
     CAN_FilterInitStructure.CAN_FilterIdLow = 0x0000;
     CAN_FilterInitStructure.CAN_FilterMaskIdHigh = 0x0000;
     CAN_FilterInitStructure.CAN_FilterMaskIdLow = 0x0000;
     CAN_FilterInitStructure.CAN_FilterFIFOAssignment = 0;
     CAN_FilterInitStructure.CAN_FilterActivation = ENABLE;

     CAN_FilterInitStructure.CAN_FilterNumber = RS_CAN_InitStruct->FilterNumber;
     CAN_FilterInit(&CAN_FilterInitStructure);

     NVIC_InitTypeDef NVIC_InitStructure;
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0;
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

     if (RS_CAN_InitStruct->CANx == CAN1)
     {
          NVIC_InitStructure.NVIC_IRQChannel = CAN1_SCE_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =
                    RS_CAN_InitStruct->CAN_SceIrqPriority;
          NVIC_Init(&NVIC_InitStructure);
          NVIC_InitStructure.NVIC_IRQChannel = CAN1_RX0_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =
                    RS_CAN_InitStruct->CAN_Rx0IrqPriority;
          NVIC_Init(&NVIC_InitStructure);
          NVIC_InitStructure.NVIC_IRQChannel = CAN1_TX_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =
                    RS_CAN_InitStruct->CAN_TxIrqPriority;
          NVIC_Init(&NVIC_InitStructure);

          //CAN Receive Interrupt config, FIFO 0 is used
          CAN_ITConfig(CAN1, CAN_IT_FMP0, ENABLE);
          //CAN transmit interrupt config
          CAN_ITConfig(CAN1, CAN_IT_TME, DISABLE);
          //CAN error management interrupt config
          CAN_ITConfig(CAN1, CAN_IT_ERR, ENABLE);
          CAN_ITConfig(CAN1, CAN_IT_EWG, ENABLE);      //Error warning Interrupt
          CAN_ITConfig(CAN1, CAN_IT_EPV, ENABLE);      //Error passive Interrupt
          CAN_ITConfig(CAN1, CAN_IT_BOF, ENABLE);      //Bus-off Interrupt
     }
#if !defined(STM32F3R8) // CAN2 not available on STM32F302R8
     if (RS_CAN_InitStruct->CANx == CAN2)
     {
          NVIC_InitStructure.NVIC_IRQChannel = CAN2_RX0_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = RS_CAN_InitStruct->CAN_Rx0IrqPriority;
          NVIC_Init(&NVIC_InitStructure);
          NVIC_InitStructure.NVIC_IRQChannel = CAN2_TX_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = RS_CAN_InitStruct->CAN_TxIrqPriority;
          NVIC_Init(&NVIC_InitStructure);
          NVIC_InitStructure.NVIC_IRQChannel = CAN2_SCE_IRQn;
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = RS_CAN_InitStruct->CAN_SceIrqPriority;
          NVIC_Init(&NVIC_InitStructure);

          CAN_ITConfig(CAN2, CAN_IT_FMP0, ENABLE);
          CAN_ITConfig(CAN2, CAN_IT_TME, DISABLE);
          CAN_ITConfig(CAN2, CAN_IT_ERR, ENABLE);
          CAN_ITConfig(CAN2, CAN_IT_EWG, ENABLE);      //Error warning Interrupt
          CAN_ITConfig(CAN2, CAN_IT_EPV, ENABLE);//Error passive Interrupt
          CAN_ITConfig(CAN2, CAN_IT_BOF, ENABLE);//Bus-off Interrupt
     }
#endif
}

 

Outcomes