2025-08-19 7:57 PM - last edited on 2025-08-21 2:00 AM by mƎALLEm
Hello @D.Botelho @mƎALLEm
I had an issue of ThreadX and FDCAN transmit as below.
I use the stm32g474 and config a threadx and fdcan with stm32cubemx, so far it works well.
but when i add some fdcan transmit code, it comes strangely.
the code as below
void appThread2(ULONG thread_input)
{
while(1)
{
if(fdcan1_RXFlag == 1)
{
fdcan1_RXFlag = 0; // Clear the receive flag
for(int i = 0; i < 8; i++)
{
fdcan1TxData[i] = fdcan1RxData[i]+1; // Copy received data to transmit buffer
}
my_FDCAN1_Transmit(fdcan1TxData); // Echo back the received data
printf("FDCAN1 Received data: ");
for (int i = 0; i < 8; i++)
{
printf("%02X ", fdcan1RxData[i]);
}
printf("\r\n");
}
// // 发送 0x12
fdcan1TxHeader.Identifier=0x012;
fdcan1TxData[0] = (dis_sensor_data1.dis1 >> 0) & 0xff;
fdcan1TxData[1] = (dis_sensor_data1.dis1 >> 8) & 0xff;
fdcan1TxData[2] = (dis_sensor_data1.dis2 >> 0) & 0xff;
fdcan1TxData[3] = (dis_sensor_data1.dis2 >> 8) & 0xff;
fdcan1TxData[4] = (dis_sensor_data1.dis3 >> 0) & 0xff;
fdcan1TxData[5] = (dis_sensor_data1.dis3 >> 8) & 0xff;
fdcan1TxData[6] = (dis_sensor_data1.dis4 >> 0) & 0xff;
fdcan1TxData[7] = (dis_sensor_data1.dis4 >> 8) & 0xff;
my_FDCAN1_Transmit(fdcan1TxData);
// // 发送 0x13
fdcan1TxHeader.Identifier=0x013;
fdcan1TxData[0] = (dis_sensor_data2.dis1 >> 0) & 0xff;
fdcan1TxData[1] = (dis_sensor_data2.dis1 >> 8) & 0xff;
fdcan1TxData[2] = (dis_sensor_data2.dis2 >> 0) & 0xff;
fdcan1TxData[3] = (dis_sensor_data2.dis2 >> 8) & 0xff;
fdcan1TxData[4] = (dis_sensor_data2.dis3 >> 0) & 0xff;
fdcan1TxData[5] = (dis_sensor_data2.dis3 >> 8) & 0xff;
fdcan1TxData[6] = (dis_sensor_data2.dis4 >> 0) & 0xff;
fdcan1TxData[7] = (dis_sensor_data2.dis4 >> 8) & 0xff;
my_FDCAN1_Transmit(fdcan1TxData);
// // 发送 0x14
fdcan1TxHeader.Identifier=0x014;
fdcan1TxData[0] = sbusHandle.isExist; // 遥控器工作状态
fdcan1TxData[1] = sys_status; // 系统状态
fdcan1TxData[2] = (encoder_data1.counter >> 0) & 0xff;
fdcan1TxData[3] = (encoder_data1.counter >> 8) & 0xff;
fdcan1TxData[4] = (encoder_data2.counter >> 0) & 0xff;
fdcan1TxData[5] = (encoder_data2.counter >> 8) & 0xff;
fdcan1TxData[6] = encoder_data1.direction;
fdcan1TxData[7] = encoder_data1.direction;
my_FDCAN1_Transmit(fdcan1TxData);
// 发送 0x15
fdcan1TxHeader.Identifier=0x015;
fdcan1TxData[0] = RS485_RXData[0]+0x0A;
fdcan1TxData[1] = RS485_RXData[1];
fdcan1TxData[2] = RS485_RXData[2];
fdcan1TxData[3] = RS485_RXData[3];
fdcan1TxData[4] = RS485_RXData[4];
fdcan1TxData[5] = RS485_RXData[5];
fdcan1TxData[6] = RS485_RXData[6];
fdcan1TxData[7] = RS485_RXData[7];
my_FDCAN1_Transmit(fdcan1TxData);
tx_thread_sleep(20); // Sleep for 20 ticks
}
}
I use a thread to send can message with a peroid of 20ms.
the CAN message ID is 0x12, 0x13, 0x14, 0x15.
as the code above, when i compiled the code and programming to mcu, just after 1s, the system stack and Error_Handler() called. when I comment out 0x15 CAN transimt, only transmit 0x12, 0x13, 0x14, it works well.
why?
I have increased the thread_stack of appThread2, but it seems the issue still exists.
how should i do to fix this issue?
Thanks,
dqsh06
2025-08-20 12:55 PM
You forgot to show code for my_FDCAN1_Transmit
2025-08-20 5:50 PM
OK, the code of my_FDCAN1_Transmit is as below:
void my_FDCAN1_Transmit(uint8_t *TxData)
{
// 发送数据
if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &fdcan1TxHeader, TxData) != HAL_OK)
{
// usb_printf("HAL_FDCAN_AddMessageToTxFifoQ failed\r\n");
printf("HAL_FDCAN_AddMessageToTxFifoQ failed\r\n");
Error_Handler();
}
}
and just as your minds, the function
why call HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &fdcan1TxHeader, TxData) failed for ID 0x15?
Thanks.
2025-08-20 6:15 PM - edited 2025-08-20 6:17 PM
Because you're trying to send 5 CAN messages (your reply message and 4 other CAN messages) back to back and your Tx only has 3 mailboxes. The mailboxes are getting full quickly, so you get HAL_ERROR.
Create a queue buffer to hold your CAN messages and when you call HAL_FDCAN_AddMessageToTxFifoQ and it returns HAL_OK, then you increment your queue pointer. When you get HAL_FDCAN_TxFifoEmptyCallback, you can send the next message in the queue. To get HAL_FDCAN_TxFifoEmptyCallback, you need to activate the notification
if (HAL_FDCAN_ActivateNotification(msg->hfdcan, FDCAN_FLAG_RX_FIFO0_NEW_MESSAGE | FDCAN_IT_TX_FIFO_EMPTY, 0) != HAL_OK)
{
Error_Handler();
}
2025-08-21 12:58 AM
Hello @Karl Yamashita ,
Thanks for your reply, but it is too difficult for me, can i just add a delay after 3 transmit to wait the transmit mailbox has space? as below
// 发送 0x12
fdcan1TxHeader.Identifier=0x012;
fdcan1TxData[0] = (dis_sensor_data1.dis1 >> 0) & 0xff;
fdcan1TxData[1] = (dis_sensor_data1.dis1 >> 8) & 0xff;
fdcan1TxData[2] = (dis_sensor_data1.dis2 >> 0) & 0xff;
fdcan1TxData[3] = (dis_sensor_data1.dis2 >> 8) & 0xff;
fdcan1TxData[4] = (dis_sensor_data1.dis3 >> 0) & 0xff;
fdcan1TxData[5] = (dis_sensor_data1.dis3 >> 8) & 0xff;
fdcan1TxData[6] = (dis_sensor_data1.dis4 >> 0) & 0xff;
fdcan1TxData[7] = (dis_sensor_data1.dis4 >> 8) & 0xff;
my_FDCAN1_Transmit(fdcan1TxData);
// 发送 0x13
fdcan1TxHeader.Identifier=0x013;
fdcan1TxData[0] = (dis_sensor_data2.dis1 >> 0) & 0xff;
fdcan1TxData[1] = (dis_sensor_data2.dis1 >> 8) & 0xff;
fdcan1TxData[2] = (dis_sensor_data2.dis2 >> 0) & 0xff;
fdcan1TxData[3] = (dis_sensor_data2.dis2 >> 8) & 0xff;
fdcan1TxData[4] = (dis_sensor_data2.dis3 >> 0) & 0xff;
fdcan1TxData[5] = (dis_sensor_data2.dis3 >> 8) & 0xff;
fdcan1TxData[6] = (dis_sensor_data2.dis4 >> 0) & 0xff;
fdcan1TxData[7] = (dis_sensor_data2.dis4 >> 8) & 0xff;
my_FDCAN1_Transmit(fdcan1TxData);
tx_thread_sleep(1);
// 发送 0x14
fdcan1TxHeader.Identifier=0x014;
fdcan1TxData[0] = sbusHandle.isExist; // 遥控器工作状态
fdcan1TxData[1] = sys_status; // 系统状态
fdcan1TxData[2] = (encoder_data1.counter >> 0) & 0xff;
fdcan1TxData[3] = (encoder_data1.counter >> 8) & 0xff;
fdcan1TxData[4] = (encoder_data2.counter >> 0) & 0xff;
fdcan1TxData[5] = (encoder_data2.counter >> 8) & 0xff;
fdcan1TxData[6] = encoder_data1.direction;
fdcan1TxData[7] = encoder_data2.direction;
my_FDCAN1_Transmit(fdcan1TxData);
// 发送 0x15
fdcan1TxHeader.Identifier=0x015;
fdcan1TxData[0] = RS485_RXData[0]+0x0A;
fdcan1TxData[1] = RS485_RXData[1];
fdcan1TxData[2] = RS485_RXData[2];
fdcan1TxData[3] = RS485_RXData[3];
fdcan1TxData[4] = RS485_RXData[4];
fdcan1TxData[5] = RS485_RXData[5];
fdcan1TxData[6] = RS485_RXData[6];
fdcan1TxData[7] = RS485_RXData[7];
my_FDCAN1_Transmit(fdcan1TxData);
tx_thread_sleep(20);
How do you think just add a tx_thread_sleep(1) to wait?
Thanks.
2025-08-21 2:38 AM
Hello @dqsh06
Please refer to example below: