2021-07-27 05:08 AM
Hej Folks :D
I am currently sending a bunch of data with my STM32H7 via FDCAN in standard format with a standard ID. At about. 1Mbit / s. I'm doing that by pushing at 100Hz quickly 4 64-bit CAN messages into the TxFiFo.
I receive the data with my RaspberryPi and the PiCan and also use their default candump function. Unfortunately, I notice that when I expect the STM32H7 4000 CAN messages to send, only ~ 3996 messages arrive. (The 3996 value likes to change.)
Also i checked the HAL_FDCAN_AddMessageToTxFifoQ Function is called 4000 times.
If I insert a Hal_delay (1) when filling into the TxFiFo, I ALWAYS get the expected 4000 messages.
Does anyone know why?
Unfortunately, the HAL_FDCAN_AddMessageToTxFifoQ does not display an error. Actually only when the FiFo is running at full capacity ..
Does the STM send the CAN messages from the FiFo too quickly? Can, should I change that? Or does anyone have an idea why this could be?
For context here a the FDCAN Init:
/* FDCAN1 init function */
void MX_FDCAN1_Init(void)
{
/*
Bit time parameter | Nominal
---------------------------|--------------
fdcan_ker_ck | 20 MHz
Time_quantum (tq) | 50 ns
Synchronization_segment | 1 tq
Propagation_segment | 3 tq
Phase_segment_1 | 8 tq
Phase_segment_2 | 8 tq
Synchronization_Jump_width | 8 tq
Bit_length | 20 tq = 1 µs
Bit_rate | 1.0 MBit/s
*/
if((CANBaudRate < 125000) | (CANBaudRate > 1e6)) Error_Handler_Msg(INADMISSIBLE_BAUDRATE);
hfdcan1.Instance = FDCAN1;
hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan1.Init.AutoRetransmission = ENABLE;
hfdcan1.Init.TransmitPause = ENABLE;
hfdcan1.Init.ProtocolException = ENABLE;
/* Nominal Time Quanta */
hfdcan1.Init.NominalPrescaler = round(1e6/CANBaudRate);
hfdcan1.Init.NominalSyncJumpWidth = 8;
hfdcan1.Init.NominalTimeSeg1 = 11;
hfdcan1.Init.NominalTimeSeg2 = 8;
/* 1 UNUSED */
hfdcan1.Init.DataPrescaler = 1;
hfdcan1.Init.DataSyncJumpWidth = 4;
hfdcan1.Init.DataTimeSeg1 = 5;
hfdcan1.Init.DataTimeSeg2 = 4;
/* 1 UNUSED */
hfdcan1.Init.MessageRAMOffset = 0;
hfdcan1.Init.StdFiltersNbr = 1;
hfdcan1.Init.ExtFiltersNbr = 0;
hfdcan1.Init.RxFifo0ElmtsNbr = 2;
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 = 32;
hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_8;
if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
{
Error_Handler();
}
HAL_StatusTypeDef Error;
FDCAN_FilterTypeDef sFilterConfig;
/* Configure Rx filter */
sFilterConfig.IdType = FDCAN_STANDARD_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_RANGE;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = 0x00;
sFilterConfig.FilterID2 = 0x7FF;
Error = HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig);
if(Error != HAL_OK) Error_Handler();
sFilterConfig.IdType = FDCAN_EXTENDED_ID;
sFilterConfig.FilterIndex = 0;
sFilterConfig.FilterType = FDCAN_FILTER_RANGE;
sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
sFilterConfig.FilterID1 = 0x00;
sFilterConfig.FilterID2 = 0x1FFFFFFF;
Error = HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig);
if(Error != HAL_OK) Error_Handler();
/* Configure global filter to reject all non-matching frames */
Error = HAL_FDCAN_ConfigGlobalFilter(&hfdcan1,
FDCAN_ACCEPT_IN_RX_FIFO0, FDCAN_ACCEPT_IN_RX_FIFO0,
FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE);
if(Error != HAL_OK) Error_Handler();
/* Configure Rx FIFO 0 watermark to 1 */
Error = HAL_FDCAN_ConfigFifoWatermark(&hfdcan1, FDCAN_CFG_RX_FIFO0, 1);
if(Error != HAL_OK) Error_Handler();
/* Activate Rx FIFO 0 watermark notification */
Error = HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_WATERMARK, 0);
if(Error != HAL_OK) Error_Handler();
}
And my CAN send Function:
void can_send(ht_can_t *entry_can){
FDCAN_TxHeaderTypeDef TxHeader;
TxHeader.Identifier = entry_can->key;
if(entry_can->extID){
TxHeader.IdType = FDCAN_EXTENDED_ID;
}else{
TxHeader.IdType = FDCAN_STANDARD_ID;
}
TxHeader.TxFrameType = FDCAN_DATA_FRAME;
TxHeader.DataLength = (uint32_t)entry_can->size << 16;
TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxHeader.MessageMarker = 0;
/*Sende Nachricht und vermerke ggf. Fehler*/
HAL_StatusTypeDef err = HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, entry_can->msg);
if(err != HAL_OK){
cnt_error++;
#ifndef UNITTEST
HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET);
#endif
char err_buffer[128];
sprintf(err_buffer, "Gescheitert CAN-Botschaft zu senden ID: %ld\r\n", entry_can->key);
if(!strstr(error_data_msg, err_buffer)){
strcat(error_data_msg, err_buffer);
}
}
}
I'm also calling the main
HAL_FDCAN_EnableISOMode(&hfdcan1);
HAL_FDCAN_Start(&hfdcan1);
Thank you for reading this far.
If I have to describe something in more detail, just say it.
Unfortunately I am not that good at describing problems and unfortunately my English is not the best either. So thank you for any consideration.
2021-07-28 09:27 AM
So I checked with an osciloscope if the STM32 was sending all CAN messages. (He does)
I notice that the next CAN message is sent almost immediately after the IFS.
Do I have a chance to artificially enlarge the IFS?
2021-08-05 07:57 AM
Apparently not. I have to do it without the luxury of a FIFO and send timed CAN messages.