2024-10-18 06:28 AM - last edited on 2024-10-20 10:30 AM by Tesla DeLorean
Hello,
I am using STM32G0B1, i have implemented the FDCAN communication but the issue i am facing with the cycle time
i have set the cycle time for 500ms i.e. every 400ms CAN messages will be transmitted.
every thing works good until i am not receiving the CAN message in my callback function but when i send the CAN messages the cycle time for message increases to 1000ms 1500ms and come back to 400ms this happens often.
cycle time when not receiving CAN message (refer below image ID 7A1, 7A2)
cycle time when receiving CAN message (refer below image ID 7A1, 7A2)
below are my code for CAN
void MX_FDCAN2_Init(void)
{
/* USER CODE BEGIN FDCAN2_Init 0 */
/* USER CODE END FDCAN2_Init 0 */
/* USER CODE BEGIN FDCAN2_Init 1 */
/* USER CODE END FDCAN2_Init 1 */
hfdcan2.Instance = FDCAN2;
hfdcan2.Init.ClockDivider = FDCAN_CLOCK_DIV1;
hfdcan2.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
hfdcan2.Init.Mode = FDCAN_MODE_NORMAL;
hfdcan2.Init.AutoRetransmission = DISABLE;
hfdcan2.Init.TransmitPause = DISABLE;
hfdcan2.Init.ProtocolException = DISABLE;
hfdcan2.Init.NominalPrescaler = 32;
hfdcan2.Init.NominalSyncJumpWidth = 1;
hfdcan2.Init.NominalTimeSeg1 = 5;
hfdcan2.Init.NominalTimeSeg2 = 2;
hfdcan2.Init.DataPrescaler = 16;
hfdcan2.Init.DataSyncJumpWidth = 1;
hfdcan2.Init.DataTimeSeg1 = 13;
hfdcan2.Init.DataTimeSeg2 = 2;
hfdcan2.Init.StdFiltersNbr = 27;
hfdcan2.Init.ExtFiltersNbr = 0;
hfdcan2.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
if (HAL_FDCAN_Init(&hfdcan2) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN FDCAN2_Init 2 */
/* USER CODE END FDCAN2_Init 2 */
}
callback function
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
if (hfdcan == &hfdcan2)
{
FDCAN_RxHeaderTypeDef RxHeader;
uint8_t RxData[8];
HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader, RxData);
if (RxHeader.Identifier == FDCANID_OTA_COMM_RX_6FA)
{
if (RxData[1] == CHIMERA_ID)
{
transmitter = RxData[0];
if (RxData[2] == FUPFG_REQUEST)
{
if (RxData[3] == RECEIVE_CONF)
{
uptype = COTA;
upgrade_state = UPGRADE_INIT;
}
else if (RxData[3] == PERFORM_UPGRADE)
{
set_complete_flag(1);
}
else if (RxData[3] == PAUSE_UPGRADE)
{
set_pause_flag(1);
}
else if (RxData[3] == RESUME_UPGRADE)
{
upgrade_state = UPGRADE_RESUME;
}
else if (RxData[3] == RECEIVE_BIN)
{
uptype = FOTA;
upgrade_state = UPGRADE_INIT;
}
}
}
}
else if (RxHeader.Identifier == FDCANID_FRM_UP_RX_3FE)
{
CAN_TP_Receive_interrupt(TransmitFlowControl, FDCANID_FRM_UP_RX_3FE, (uint8_t *)RxData, RxHeader.DataLength, &firmware_up_recv_shim, &firmware_up_recv_message, &firmware_up_recv_handle, &canTpinterrupt_flag);
}
else if (RxHeader.Identifier == FDCANID_DBG_RX_301)
{
if (RxData[0] == 0x01)
{
debug_State = DEBUG_ENABLE;
chimera.ADBMode = DEBUG_ENABLE;
}
else if (RxData[0] == 0x00)
{
debug_State = DEBUG_DISABLE;
chimera.ADBMode = DEBUG_DISABLE;
}
chimera.developerMode = RxData[1];
}
// RPAS DATA (CAN ID will remain same)
else if (RxHeader.Identifier == FDCANID_RPAS_RX_4A0)
{
chimera.rpas.buzzerAlarmFrequency = (RxData[0] >> 0) & 0x07; // bits 2-0
chimera.rpas.buzzerAlarmMode = (RxData[0] >> 3) & 0x07; // bits 5-3
chimera.rpas.distanceS1 = RxData[1]; // byte 1 right sensor
chimera.rpas.distanceS2 = RxData[2]; // byte 2 center sensor
chimera.rpas.distanceS3 = RxData[3]; // byte 3 not used
chimera.rpas.distanceS4 = RxData[4]; // byte 4 left sensor
chimera.rpas.errorS1 = (RxData[5] >> 0) & 0x01; // bit 40
chimera.rpas.errorS2 = (RxData[5] >> 1) & 0x01; // bit 41
chimera.rpas.errorS3 = (RxData[5] >> 2) & 0x01; // bit 42
chimera.rpas.errorS4 = (RxData[5] >> 3) & 0x01; // bit 43
}
else if (RxHeader.Identifier == FDCANID_VCU_RX_602)
{
chimera.SOC = (((uint16_t)(RxData[0] << 8)) | RxData[1]) * 0.1;
chimera.vehicleMode = (uint8_t)(RxData[6] | RxData[7]); // Vehicle mode (0 = ignition off, 1 = charging, 2 = discharging(ignition on), 3 = charging complete)
}
else if (RxHeader.Identifier == FDCANID_VCU_RX_603)
{
chimera.odometer = (((uint32_t)(RxData[2] << 24)) |
((uint32_t)(RxData[3] << 16)) |
((uint16_t)(RxData[4] << 8)) |
RxData[5]) *
0.01;
}
else if (RxHeader.Identifier == FDCANID_VCU_RX_607)
{
if(RxData[0] == 0x11)
{
chimera.vehicleStatus[0] = 0x00; // Neutral
}
else if(RxData[0] == 0x12)
{
chimera.vehicleStatus[0] = 0x02; // Drive -> Eco Mode
}
else if(RxData[0] == 0x14)
{
chimera.vehicleStatus[0] = 0x04; // Reverse
}
else if(RxData[0] == 0x22)
{
chimera.vehicleStatus[0] = 0x06; // Thunder
}
else if(RxData[0] == 0x42)
{
chimera.vehicleStatus[0] = 0x08; // Rhyno
}
chimera.vehicleSpeed = RxData[1];
}
else if (RxHeader.Identifier == FDCANID_VCU_RX_608)
{
chimera.throttleData.throttlePercentage = RxData[0];
chimera.throttleData.throttleVolt = RxData[1] * 0.1;
chimera.brakeData.brakePercentage = RxData[2];
chimera.brakeData.brakeVolt = RxData[3] * 0.1;
chimera.NVAfeedback = RxData[4];
}
else if (RxHeader.Identifier == FDCANID_VCU_RX_6F4)
{
memcpy(chimera.VIN, RxData, 8);
// chimera.VIN[0] = RxData[0];
// chimera.VIN[1] = RxData[1];
// chimera.VIN[2] = RxData[2];
// chimera.VIN[3] = RxData[3];
// chimera.VIN[4] = RxData[4];
// chimera.VIN[5] = RxData[5];
// chimera.VIN[6] = RxData[6];
// chimera.VIN[7] = RxData[7];
}
else if (RxHeader.Identifier == FDCANID_VCU_RX_6F5)
{
memcpy(chimera.VIN + 8, RxData, 8);
// chimera.VIN[8] = RxData[0];
// chimera.VIN[9] = RxData[1];
// chimera.VIN[10] = RxData[2];
// chimera.VIN[11] = RxData[3];
// chimera.VIN[12] = RxData[4];
// chimera.VIN[13] = RxData[5];
// chimera.VIN[14] = RxData[6];
// chimera.VIN[15] = RxData[7];
}
else if (RxHeader.Identifier == FDCANID_VCU_RX_6F6)
{
memcpy(chimera.VIN + 16, RxData, 1);
// chimera.VIN[16] = RxData[0];
}
}
}
For transmission of CAN id i am using while loop having 400ms HAL delay.
Regards
Bhupender Singh
Solved! Go to Solution.
2024-10-21 01:35 AM
@bhupender-singh wrote:
case 1:
When i am sending message only and not receiving and message cycle time is constant
case 1:
When i am sending message and receiving and message at same time the cycle time is fluctuate.
This is what I have a doubt about.
This is a normal behavior. The callback is a code executed in an interrupt context and this delays the execution of the transmit in main(). So you need to simplify your code in the Callback keep just the buffer receive and all the treatment needs to be moved to the main. The interrupt code needs to be as light as possible.
For transmit try to use a Timer and send frames from the interrupt (same case: code needs to be as light as possible).
2024-10-18 06:40 AM
Hello,
@bhupender-singh wrote:
i have set the cycle time for 500ms i.e. every 400ms CAN messages will be transmitted.
How? where the rest of time 100ms goes?
@bhupender-singh wrote:
every thing works good until i am not receiving the CAN message in my callback function but when i send the CAN messages the cycle time for message increases to 1000ms 1500ms and come back to 400ms this happens often.
The problem is not clear. The issue is on send or on receive frame? please elaborate.
You can probe the Tx pin and see what happens on the bus and if that cycle time is 500ms.
@bhupender-singh wrote:
For transmission of CAN id i am using while loop having 400ms HAL delay.
Need to share that part of code.
2024-10-18 06:55 AM
How? where the rest of time 100ms goes?
Ans: my mistake it is 400ms not 500ms
while loop code
while (1)
{
/* send status to stark that chimera is ready to recieve VIN*/
send_version(); // here i am sending
/* Logic for enabling and disabling the ADB mode through CAN*/
if (debug_State == DEBUG_ENABLE)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_RESET);
}
else if (debug_State == DEBUG_DISABLE)
{
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_12, GPIO_PIN_SET);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET);
}
HAL_Delay(400);
}
}
2024-10-18 07:19 AM
Sorry I don't see nothing as FDCAN transmit in the while loop.
You need to share your implementation of send_version();
2024-10-18 07:32 AM
this function I'm calling inside send_version();
void Transmit_on_CAN(uint32_t U32_transmitCANid, TypeofCANID U8_idType, uint8_t *U8_dataarr, uint8_t U8_DLC)
{
FDCAN_TxHeaderTypeDef TxMsg;
if (U8_idType == E)
{
TxMsg.IdType = FDCAN_EXTENDED_ID;
}
else if (U8_idType == S)
{
TxMsg.IdType = FDCAN_STANDARD_ID;
}
TxMsg.TxFrameType = FDCAN_DATA_FRAME;
TxMsg.Identifier = U32_transmitCANid;
TxMsg.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
TxMsg.BitRateSwitch = FDCAN_BRS_OFF;
TxMsg.FDFormat = FDCAN_CLASSIC_CAN;
TxMsg.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
TxMsg.MessageMarker = 0;
switch (U8_DLC)
{
case 0:
TxMsg.DataLength = FDCAN_DLC_BYTES_0; /*!< 0 bytes data field */
break;
case 1:
TxMsg.DataLength = FDCAN_DLC_BYTES_1; /*!< 1 bytes data field */
break;
case 2:
TxMsg.DataLength = FDCAN_DLC_BYTES_2; /*!< 2 bytes data field */
break;
case 3:
TxMsg.DataLength = FDCAN_DLC_BYTES_3; /*!< 3 bytes data field */
break;
case 4:
TxMsg.DataLength = FDCAN_DLC_BYTES_4; /*!< 4 bytes data field */
break;
case 5:
TxMsg.DataLength = FDCAN_DLC_BYTES_5; /*!< 5 bytes data field */
break;
case 6:
TxMsg.DataLength = FDCAN_DLC_BYTES_6; /*!< 6 bytes data field */
break;
case 7:
TxMsg.DataLength = FDCAN_DLC_BYTES_7; /*!< 7 bytes data field */
break;
case 8:
TxMsg.DataLength = FDCAN_DLC_BYTES_8; /*!< 8 bytes data field */
break;
default:
TxMsg.DataLength = FDCAN_DLC_BYTES_0; /*!< 0 bytes data field */
break;
}
if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan2, &TxMsg, U8_dataarr) != HAL_OK)
{
Error_Handler();
}
}
2024-10-18 07:36 AM
Ok I don't see an issue in sending.
But need to answer that question:
@bhupender-singh wrote:
every thing works good until i am not receiving the CAN message in my callback function but when i send the CAN messages the cycle time for message increases to 1000ms 1500ms and come back to 400ms this happens often.
The problem is not clear. The issue is on send or on receive frame? please elaborate.
You can probe the Tx pin and see what happens on the bus and if that cycle time is 500ms.
2024-10-18 12:29 PM
Got this from reference manual
Transceiver delay compensation
During the data phase of a FDCAN transmission only one node is transmitting, all others are
receivers. The length of the bus line has no impact. When transmitting via pin FDCAN_TX
the protocol controller receives the transmitted data from its local CAN transceiver via pin
FDCAN_RX. The received data is delayed by the CAN transceiver loop delay. In case this
Table 203. DLC coding in FDCAN
DLC 9 10 11 12 13 14 15
Number of data bytes 12 16 20 24 32 48 64
RM0444 Rev 5 1205/1390
RM0444 FD controller area network (FDCAN)
1261
delay is greater than TSEG1 (time segment before sample point), a bit error is detected.
Without transceiver delay compensation, the bit rate in the data phase of a FDCAN frame is
limited by the transceivers loop delay.
The FDCAN implements a delay compensation mechanism to compensate the CAN
transceiver loop delay, thereby enabling transmission with higher bit rates during the
FDCAN data phase independent of the delay of a specific CAN transceiver.
link reference manual page number - 1204
2024-10-18 01:55 PM
Forget about Transceiver delay compensation. This is not the issue. As you are transmitting and receiving correctly the frames.
Need to simplify your code and debug step by step.
But still you didn't answer my previous question.
2024-10-19 12:32 AM
The problem is not clear. The issue is on send or on receive frame? please elaborate.
ANS: the issue is in sending the frame
case 1:
When i am sending message only and not receiving and message cycle time is constant
case 1:
When i am sending message and receiving and message at same time the cycle time is fluctuate.
2024-10-20 10:18 AM - edited 2024-10-20 10:19 AM
Hey Soflit,
last night i was debugging the code and found that the issue with CAN callback function. when receiving only one CAN ID it works properly but when multiple CAN IDs are coming at same time some CAN ids are missed.
Can you guide me on this, how would i ensure that my all CAN ID are received and no CAN ID should be missed.