cancel
Showing results for 
Search instead for 
Did you mean: 

FDCAN1 error in STM32G431 with interrupt vectors.

Oleksii
Associate III


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

 

 

 

2 REPLIES 2
SofLit
ST Employee

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.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
PS:
1 - This is NOT an online support (https://ols.st.com) but a collaborative space.
2 - Please be polite in your reply. Otherwise, it will be reported as inappropriate and you will be permanently blacklisted from my help.

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))