2025-01-25 08:55 AM - last edited on 2025-01-28 08:02 AM by SofLit
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-28 07:27 AM - edited 2025-01-28 07:46 AM
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:
I invite you to use the HAL to confirm your observation instead of playing with the direct access to the registers.
2025-01-28 10:54 AM
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))