2024-07-17 12:22 AM - last edited on 2024-07-17 03:56 AM by SofLit
Hi,
i need help with a strange behaviour of the FDCAN RX interrupt. I have 2 controllers which communicate with each other over CAN bus (Classic CAN). The first (my problem mcu) sends a command message and the second answers with 3 messages. The problem is, that on the first MCU the RX interrupt is only called twice and the third message stucks in the fifo until I send a new message.
I have made some debug output which shows my problem a little bit clearer:
106 CAN TX: 0E 07 00
107 CAN RX: 01 0A 02 FF FF FF FF FF
108 CAN RX: 02 08 00 00 01 0E 00 EB
FIFO: 1
1118 CAN TX: 0E 07 00
1119 CAN RX: 03 08 FF FF FF FF FF FF
1120 CAN RX: 01 0A 02 FF FF FF FF FF
FIFO: 2
2130 CAN TX: 0E 07 00
2131 CAN RX: 02 08 00 00 01 0A 00 F8
2132 CAN RX: 03 FA FF FF FF FF FF FF
FIFO: 3
3142 CAN TX: 0E 07 00
3143 CAN RX: 01 0A 02 FF FF FF FF FF
3144 CAN RX: 02 08 00 00 01 0C 00 FB
FIFO: 4
4154 CAN TX: 0E 07 00
4155 CAN RX: 03 FB FF FF FF FF FF FF
4156 CAN RX: 01 0A 02 FF FF FF FF FF
FIFO: 5
5166 CAN TX: 0E 07 00
5167 CAN RX: 02 08 00 00 01 0E 00 FC
5168 CAN RX: 03 FC FF FF FF FF FF FF
The number at the beginning of the lines are the timestamps.
The first byte in the RX messages is the id of the message counting from 1 to 3.
The CAN Rx... messages are printed out in the IRQ.
The data in the messages is correct, so the bit timing matches on both mcu sides.
As you can see, if I send a message the RX interrupt is only called twice and the third response message stays in the FIFO until I send another message.
I have verified that the second controller is sending its 3 messages within a few milliseconds (Debug message outputs and logic analyser for the CAN bus). So the problem is not on that side.
My intializing code looks like:
GPIO_InitTypeDef GPIO_InitStruct = {0};
// Peripheral clock enable
__HAL_RCC_FDCAN_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**FDCAN1 GPIO Configuration
PA11 ------> FDCAN1_RX
PA12 ------> FDCAN1_TX
*/
GPIO_InitStruct.Pin = GPIO_PIN_11|GPIO_PIN_12;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
can->Instance = FDCAN1;
can->Init.FrameFormat = FDCAN_FRAME_CLASSIC;
can->Init.Mode = FDCAN_MODE_NORMAL;
can->Init.AutoRetransmission = ENABLE;
can->Init.TransmitPause = DISABLE;
can->Init.ProtocolException = ENABLE;
can->Init.NominalPrescaler = 4;
can->Init.NominalSyncJumpWidth = 5;
can->Init.NominalTimeSeg1 = 14;
can->Init.NominalTimeSeg2 = 5;
can->Init.MessageRAMOffset = 0;
can->Init.StdFiltersNbr = 0;
can->Init.ExtFiltersNbr = 0;
can->Init.RxFifo0ElmtsNbr = 6;
can->Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
can->Init.RxFifo1ElmtsNbr = 0;
can->Init.RxBuffersNbr = 0;
can->Init.TxEventsNbr = 0;
can->Init.TxBuffersNbr =0;
can->Init.TxFifoQueueElmtsNbr = 1;
can->Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
can->Init.TxElmtSize = FDCAN_DATA_BYTES_8;
if (HAL_FDCAN_Init(can) != HAL_OK) {
return RESULT_INIT;
}
HAL_FDCAN_ActivateNotification(can, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
// Enable interrupts
HAL_NVIC_EnableIRQ(FDCAN1_IT0_IRQn);
if(HAL_FDCAN_Start(can) != HAL_OK) {
return RESULT_INIT;
}
The RX interrupt handler:
void FDCAN1_IT0_IRQHandler() {
HAL_FDCAN_IRQHandler(can);
}
/**
* \brief Receive callback from HAL. Takes the received CAN packet and puts it in the protocol stack
* \param hcan Pointer to the CAN handle typedef
*/
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef* hcan, uint32_t RxFifo0ITs) {
HAL_StatusTypeDef result;
FDCAN_RxHeaderTypeDef header;
tCANFrame rxF;
result = HAL_FDCAN_GetRxMessage(hcan, FDCAN_RX_FIFO0, &header, rxF.data);
rxF.msgId = header.Identifier;
rxF.size = ((header.DataLength>>16)>8)?8:(header.DataLength>>16);
logd("%d CAN RX: ", HAL_GetTick());
for(uint8_t i=0; i<rxF.size; i++) {
logd("%02X ", rxF.data[i]);
}
lognl("");
}
And the test loop where I send the messages to the second controller:
FDCAN_TxHeaderTypeDef header;
uint8_t data[3];
data[0] = 0x0E;
data[1] = 0x07;
data[2] = 0x00;
header.IdType = FDCAN_EXTENDED_ID;
header.Identifier = 0x11C;
header.DataLength = FDCAN_DLC_BYTES_3;
header.TxFrameType = FDCAN_DATA_FRAME;
header.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
header.BitRateSwitch = FDCAN_BRS_OFF;
header.FDFormat = FDCAN_CLASSIC_CAN;
header.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
header.MessageMarker = 0;
while(1) {
uint32_t mailbox;
// Check if TX queue is full
if((can->Instance->TXFQS&FDCAN_TXFQS_TFQF)) {
break;
}
logd("%d CAN TX: ", HAL_GetTick());
for(uint8_t i=0; i<3; i++) {
logd("%02X ", data[i]);
}
lognl("");
HAL_FDCAN_AddMessageToTxFifoQ(can, &header, data);
// Wait some time until interrupts could be handled
HAL_Delay(10);
// Show remaining message count from FIFO
lognl("FIFO: %d", HAL_FDCAN_GetRxFifoFillLevel(can, FDCAN_RX_FIFO0));
HAL_Delay(1000);
}
Maybe someone have a hint what's wrong with my code?
Solved! Go to Solution.
2024-07-17 04:53 AM - edited 2024-09-24 05:04 AM
You set the number of filters to 0. You need to set it to at least 1.
can->Init.StdFiltersNbr = 0;
can->Init.ExtFiltersNbr = 0;
What if you increase this delay from the transmit side?
// Wait some time until interrupts could be handled
HAL_Delay(10)
let's say 100ms.
2024-07-17 03:55 AM
Hello,
Avoid using printf in the interrupts (in the callbacks).
2024-07-17 04:48 AM
Even if I do not have any outputs in the interrupt, the problem exists.
2024-07-17 04:53 AM - edited 2024-09-24 05:04 AM
You set the number of filters to 0. You need to set it to at least 1.
can->Init.StdFiltersNbr = 0;
can->Init.ExtFiltersNbr = 0;
What if you increase this delay from the transmit side?
// Wait some time until interrupts could be handled
HAL_Delay(10)
let's say 100ms.
2024-12-11 03:09 AM - edited 2024-12-11 03:10 AM
Hi bro Are you using the stm32h743zit6 board CAN
if your using CAN
can u send the working code because i have code that is not working i have message can u check once
#include"STM32H743.h"
/* CAN Handle */
FDCAN_HandleTypeDef hfdcan1;
/* Function to Initialize CAN Peripheral */
void CAN_Init(void)
{
/*CAN GPIO Configuration (PB12 as RX, PB13 as TX)*/
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOB_CLK_ENABLE(); // Enable clock for GPIOB
// Configure PB12 and PB13 for CAN (RX and TX)
GPIO_InitStruct.Pin = GPIO_PIN_12 | GPIO_PIN_13; // Combine pins
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; // Alternate function push-pull
GPIO_InitStruct.Pull = GPIO_NOPULL; // No pull-up or pull-down resistors
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF9_FDCAN1; // Alternate function for FDCAN1
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = DISABLE;
hfdcan1.Init.TransmitPause = DISABLE;
hfdcan1.Init.ProtocolException = DISABLE;
hfdcan1.Init.NominalPrescaler = 161;
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 7;
hfdcan1.Init.NominalTimeSeg2 = 6;
hfdcan1.Init.DataPrescaler = 1;
hfdcan1.Init.DataSyncJumpWidth = 1;
hfdcan1.Init.DataTimeSeg1 = 1;
hfdcan1.Init.DataTimeSeg2 = 1;
hfdcan1.Init.MessageRAMOffset = 0;
hfdcan1.Init.StdFiltersNbr = 1;
hfdcan1.Init.ExtFiltersNbr = 0;
hfdcan1.Init.RxFifo0ElmtsNbr = 8;
hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxFifo1ElmtsNbr = 0;
hfdcan1.Init.RxFifo1ElmtSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.RxBuffersNbr = 0;
hfdcan1.Init.RxBufferSize = FDCAN_DATA_BYTES_8;
hfdcan1.Init.TxEventsNbr = 0;
hfdcan1.Init.TxBuffersNbr = 0;
hfdcan1.Init.TxFifoQueueElmtsNbr = 8;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
while (1) { }
}
HAL_FDCAN_ConfigMessageRam(&hfdcan1);
/* Message RAM Configuration */
FDCAN1->SIDFC = (0x0000 << 2) | 16; // 11-bit filters: start at 0x0000, 16 elements
FDCAN1->XIDFC = (0x0010 << 2) | 8; // 29-bit filters: start at 0x0010, 8 elements
FDCAN1->RXF0C = (0x0020 << 2) | 32; // Rx FIFO 0: start at 0x0020, 32 elements
FDCAN1->TXBC = (0x0260 << 2) | 8; // Tx buffers: start at 0x0260, 8 elements
if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
{
while (1) { } // Start Error
}
}
/* Function to Transmit Data via CAN */
HAL_StatusTypeDef CAN_TransmitData(uint32_t id, uint8_t* data, uint8_t length)
{
FDCAN_TxHeaderTypeDef txHeader;
txHeader.Identifier = id;
txHeader.IdType = FDCAN_STANDARD_ID;
txHeader.TxFrameType = FDCAN_DATA_FRAME;
txHeader.DataLength = (length << 16);
txHeader.BitRateSwitch = FDCAN_BRS_OFF;
txHeader.FDFormat = FDCAN_CLASSIC_CAN;
if (data == NULL || length > 8)
{
return HAL_ERROR; // Debug here
}
return HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &txHeader, data);
}
/* Function to Receive Data from CAN */
HAL_StatusTypeDef CAN_ReceiveData(uint32_t* id, uint8_t* data, uint8_t* length)
{
FDCAN_RxHeaderTypeDef rxHeader;
uint32_t fifoIndex = 0;
if (HAL_FDCAN_GetRxMessage(&hfdcan1, fifoIndex, &rxHeader, data) != HAL_OK)
{
return HAL_ERROR; // Failed to receive the message
}
*id = rxHeader.Identifier;
*length = rxHeader.DataLength;
return HAL_OK;
}
2024-12-11 03:11 AM
Hello @bhargav23 ,
This thread has been closed. Please keep the discussion in this thread.