Skip to main content
Graduate II
January 25, 2025
Question

FDCAN1 error in STM32G431 with interrupt vectors.

  • January 25, 2025
  • 1 reply
  • 1275 views


The conclusion is that setting filters and interrupts on FIFO0 leads to exception handling
FDCAN1_IT1_IRQHandler.
The reason for this behavior is an error in the file. startup_stm32g431cbtx.s

ERROR

..
.word ADC1_2_IRQHandler
.word USB_HP_IRQHandler
.word USB_LP_IRQHandler
.wordh FDCAN1_IT0_IRQHandler
.word FDCAN1_IT1_IRQHandler
.word EXTI9_5_IRQHandler
.word TIM1_BRK_TIM15_IRQHandler

 

..

 

This is how it should be

...

.word ADC1_2_IRQHandler
.word USB_HP_IRQHandler
.word USB_LP_IRQHandler
.word FDCAN1_IT1_IRQHandler
.word FDCAN1_IT0_IRQHandler
.word EXTI9_5_IRQHandler
.word TIM1_BRK_TIM15_IRQHandler

...

 

 

 

As an example, the code that I use is for testing so that there are no questions).

void CAN_Config(void) {

 FDCAN_GlobalTypeDef *CAN = FDCAN1;
 uint32_t *filterRAM = (uint32_t *)RAMBaseFDCAN1;

 // Включение тактирования для CAN
 RCC->APB1ENR1 |= RCC_APB1ENR1_FDCANEN;

 RCC->CCIPR &= ~RCC_CCIPR_FDCANSEL;
 // PLL "Q" for FDCAN
 RCC->CCIPR |= (0x1 << RCC_CCIPR_FDCANSEL_Pos); 



 // Init FDCAN module
 CAN->CCCR |= FDCAN_CCCR_INIT;
 while (!(CAN->CCCR & FDCAN_CCCR_INIT));
 CAN->CCCR |= FDCAN_CCCR_CCE; 

/*
 Baudrate	NSJW	NBRP	NTSEG1	NTSEG2	FDCAN_NBTP (uint32)
 125000		1		640		543		95		0x21F5F
 250000		1		320		271		47		0x10F2F
 500000		2		160		67		12		0x08617
 800000		1		100		84		14		0x0540E
 1000000		1		80		67		11		0x0430B
*/

 // Set the nominal bit timing register
 CAN->NBTP = (1 << FDCAN_NBTP_NSJW_Pos) |
 		(1 << FDCAN_NBTP_NBRP_Pos) |
		(66 << FDCAN_NBTP_NTSEG1_Pos)|
		(11 << FDCAN_NBTP_NTSEG2_Pos);

 // Clear message RAM
 for(uint8_t i=0;i< 212;i++){filterRAM[i] = 0;};

 /* FDCAN global filter configuration register (FDCAN_RXGFC)
 	 Address offset: 0x0080
 	 Reset value: 0x0000 0000
 */
 //CAN->RXGFC = STDfilter_n(2)|EXTfilter_n(0)|ANFS_Reject_rx|ANFE_Reject_rx;
 CAN->RXGFC = (2<<16)|(2<<4)|(2 << 2);//

 // ID filters 100 and 80
 // filterRAM[0] = STDfilterID_DUAL | STDfilterRxFIFO0 | STDfilterID1(0x100) | STDfilterID2(0x80); 
 filterRAM[0] = (1 << 30) | (1 << 27) | (0x100 << 16) | 80; 

 // Включить прерывания в FDCAN FIFO

 CAN->IE |= 3; // FDCAN_IE_RF0NE_| RF0FE
 CAN->ILS |= 1; // RXFIFO0: RX FIFO bit grouping the following interruption
 CAN->ILE |= 3; // Enable IT0

 // Normal MODE
 CAN->CCCR &= ~FDCAN_CCCR_INIT; // Выход из режима инициализации
 while (CAN->CCCR & FDCAN_CCCR_INIT);

 NVIC_EnableIRQ(FDCAN1_IT0_IRQn);;
 NVIC_EnableIRQ(FDCAN1_IT1_IRQn);
 
 }

 

 

 

It took me several hours to understand that someone had screwed up.(

 

RM0440 
Sometimes it blows my mind too))

Знімок екрана з 2025-01-25 18-53-54.png

 

 

 

    This topic has been closed for replies.

    1 reply

    Technical Moderator
    January 28, 2025

    Hello,

    I didn't understand how you arrived to the conclusion that the IRQ vector table needs to be in this order:

    FDCAN1_IT1_IRQHandler
    FDCAN1_IT0_IRQHandler

    Instead of :

    FDCAN1_IT0_IRQHandler
    FDCAN1_IT1_IRQHandler

    According to the reference manual RM0440 / Table 97. STM32G4 series vector table ,the implemented order is correct:

    SofLit_0-1738077936326.png

    I invite you to use the HAL to confirm your observation instead of playing with the direct access to the registers.

    OleksiiAuthor
    Graduate II
    January 28, 2025

    I will answer your question)


    Following the logic RM0440


    FDCAN interrupt enable register (FDCAN_IE)

    Bit 5 RF1LE: Rx FIFO 1 message lost interrupt enable
    0: Interrupt disabled
    1: Interrupt enabled
    Bit 4 RF1FE: Rx FIFO 1 full interrupt enable
    0: Interrupt disabled
    1: Interrupt enabled
    Bit 3 RF1NE: Rx FIFO 1 new message interrupt enable
    0: Interrupt disabled
    1: Interrupt enabled
    Bit 2 RF0LE: Rx FIFO 0 message lost interrupt enable
    0: Interrupt disabled
    1: Interrupt enabled
    Bit 1 RF0FE: Rx FIFO 0 full interrupt enable
    0: Interrupt disabled
    1: Interrupt enabled
    Bit 0 RF0NE: Rx FIFO 0 new message interrupt enable
    0: Interrupt disabled
    1: Interrupt enabled

    FDCAN interrupt line select register (FDCAN_ILS)
    Bit 1 RXFIFO1: RX FIFO bit grouping the following interruption
    RF1LL: Rx FIFO 1 message lost interrupt line
    RF1FL: Rx FIFO 1 full interrupt line
    RF1NL: Rx FIFO 1 new message interrupt line

    Bit 0 RXFIFO0: RX FIFO bit grouping the following interruption
    RF0LL: Rx FIFO 0 message lost interrupt line
    RF0FL: Rx FIFO 0 full interrupt line
    RF0NL: Rx FIFO 0 new message interrupt line

     

    What do you expect to see in the register FDCAN_ILE ?

    bit0 is the enable interrupt for FIFO0
    bit1 - is the enable interrupt for FIFO1.


    But what do we see)
    An inconvenient crutch with an attempt to justify it.

    FDCAN interrupt line enable register (FDCAN_ILE)

    Bit 1 EINT1: Enable interrupt line 1
    0: Interrupt line fdcan_intr0_it disabled
    1: Interrupt line fdcan_intr0_it enabled

    Bit 0 EINT0: Enable interrupt line 0
    0: Interrupt line fdcan_intr1_it disabled
    1: Interrupt line fdcan_intr1_it enabled

     

    The solution is to simply make changes to the vector table.

    As for HAL - due to its multi-level abstraction, of course this error can be corrected..

    But don't suggest this to me, it's a lot of extra text and extra code.)


    Registers are much simpler and better.
    As a result, the firmware is much smaller.

    There is no need to create an entire structure to write one value to a register))