Reputation: 41
I am developing a new project for the STM32G474 processor using the STM32G474E-EVAL1 board but am having a problem with FDCAN. I have two issues:
I configure FDCAN and use the function HAL_FDCAN_AddMessageToTxFifoQ but the queue quickly fills up and no CAN transmission takes place. I have verified the physical connection and cable termination.
I set up a receive filter to accept all incoming messages and send them to RX FIFO 0, and I activate notifications with HAL_FDCAN_ActivateNotification using the argument FDCAN_IT_RX_FIFO0_NEW_MESSAGE, but I never get a CAN interrupt when messages are sent from the host. I am using a CAN analyzer to verify that the messages are sent.
I am using Classic CAN at 125Kbps.
Here is the STM32CubeMX generated code and the filter I set up:
/**
* @brief FDCAN1 Initialization Function
* @param None
* @retval None
*/
static void MX_FDCAN1_Init(void)
{
/* USER CODE BEGIN FDCAN1_Init 0 */
/* USER CODE END FDCAN1_Init 0 */
/* USER CODE BEGIN FDCAN1_Init 1 */
/* USER CODE END FDCAN1_Init 1 */
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.ClockDivider = FDCAN_CLOCK_DIV1;
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 = 160;
hfdcan1.Init.NominalSyncJumpWidth = 1;
hfdcan1.Init.NominalTimeSeg1 = 2;
hfdcan1.Init.NominalTimeSeg2 = 2;
hfdcan1.Init.DataPrescaler = 1;
hfdcan1.Init.DataSyncJumpWidth = 16;
hfdcan1.Init.DataTimeSeg1 = 15;
hfdcan1.Init.DataTimeSeg2 = 5;
hfdcan1.Init.StdFiltersNbr = 1;
hfdcan1.Init.ExtFiltersNbr = 0;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN FDCAN1_Init 2 */
// Set up filters
FDCAN_FilterTypeDef sFilterConfig;
sFilterConfig.IdType = FDCAN_STANDARD_ID; // vs. Extended ID
sFilterConfig.FilterIndex = 0; // the number of the filter we are using
sFilterConfig.FilterType = FDCAN_FILTER_MASK;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0; // what to do filter match
sFilterConfig.FilterID1 = 0; // filter
sFilterConfig.FilterID2 = 0; // mask: 0=>accept all messages
if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
{
// Filter configuration error
Error_Handler();
}
// There will be no remote messages
if (HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT,
FDCAN_FILTER_REMOTE, FDCAN_FILTER_REMOTE) != HAL_OK)
{
Error_Handler();
}
/* USER CODE END FDCAN1_Init 2 */
}
I subsequently call the following functions:
void canfestival_CAN_Initialize(CO_Data* can_handle)
{
// Set up the transmit header
TxHeader.IdType = FDCAN_STANDARD_ID;
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
TxHeader.DataLength = FDCAN_DLC_BYTES_8;
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE; // Error State Indicator for Tx errors
TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0;
// Start CAN timer for use by CANfestival
if (HAL_TIM_Base_Start_IT(&hCAN_FESTIVAL_TIMER) != HAL_OK)
{
Error_Handler();
}
// Start FDCAN module
if (HAL_FDCAN_Start(&hFDCAN_MODULE) != HAL_OK)
{
Error_Handler();
}
// Set up to interrupt when a new message arrives in the RX Fifo 0
if (HAL_FDCAN_ActivateNotification(&hFDCAN_MODULE, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
{
Error_Handler();
}
}
Issue 1: I use the function HAL_FDCAN_AddMessageToTxFifoQ but the queue quickly fills up and no CAN transmission takes place.
void canxmit_Task(void)
{
Message message;
osStatus_t status;
while(true)
{
// Check to see if the Tx FIFO is full.
if ((hFDCAN_MODULE.Instance->TXFQS & FDCAN_TXFQS_TFQF) != 0)
{
break; // Tx FIFO is full.
}
// Check for any messages in the RTOS queue.
status = osMessageQueueGet(CanXmitQueueHandle, &message, NULL, 0);
if (status == osErrorTimeout)
{
break; // No new messages to send.
}
if (status != osOK)
{
Error_Handler();
}
// Copy message from data structure used by CANfestival into that required for HAL.
TxHeader.Identifier = message.cob_id;
TxHeader.TxFrameType = (message.rtr != 0) ? FDCAN_REMOTE_FRAME : FDCAN_DATA_FRAME;
TxHeader.DataLength = message.len;
for (uint32_t i = 0; i < message.len; i++)
{
TxData[i] = message.data[i];
}
// Add message to CAN Fifo queue for transmission.
if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData) != HAL_OK)
{
Error_Handler();
}
}
}
From debug, I see that HAL_FDCAN_AddMessageTxFifoQ is called 3 times and after this the FDCAN_TXFQS_TFQF bit is permanently set. I don’t see any output on the CAN bus.
Issue 2: I never get a CAN interrupt when messages are sent from the host
Even with host transmitting CAN data, the function: void FDCAN1_IT0_IRQHandler(void) is never called.
I loaded the code on an STM32G474E-EVAL1 board, connected a properly terminated CAN cable to a host, connected a PEAK PCAN-USB analyzer with PCAN-View software, and power up the board. I never see any CAN activity from the code, the 3-deep transmit queue fills up, and I never get any CAN interrupts.
Upvotes: 1
Views: 3230
Reputation: 318
I think you are currently encountering a few issues, but without physical testing it is only speculation. Try to take a look at those:
If I were you I would first test this in a loop-back mode on the MCU itself (maybe even the fancy new external loop-back that comes with FDCAN, which also sends the TX line out, so you can see communication happening). Only when you know that something works I would connect an external device. At that point make sure your timing settings are correct, as this can be a tricky thing to set up (there are bunch of calculators online for this). Also look at PEAK-CAN documentation to find information about the ACK bit behavior. If it doesn't help, try to connect a different listener node e.g. other STM32 MCU with a CAN transceiver. That way you can be sure that you are receiving frames properly.
Upvotes: 2