Skip to main content
Graduate
August 20, 2025
Question

issue of ThreadX and FDCAN function

  • August 20, 2025
  • 2 replies
  • 839 views

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

    This topic has been closed for replies.

    2 replies

    Graduate II
    August 20, 2025

    You forgot to show code for my_FDCAN1_Transmit

    dqsh06Author
    Graduate
    August 21, 2025

    @Karl Yamashita ,

    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 

    HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &fdcan1TxHeader, TxData)
    returns HAL_ERROR when call my_FDCAN1_Transmit() for ID 0x15.
    because i got a printf of 
    "HAL_FDCAN_AddMessageToTxFifoQ failed"
    and Error_Handler() called.

     why call HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &fdcan1TxHeader, TxData) failed for ID 0x15?

     

    Thanks.

    Graduate II
    August 21, 2025

    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();
    	}

     

    Technical Moderator
    August 21, 2025
    dqsh06Author
    Graduate
    August 22, 2025

    Hello @Saket_Om ,

     

    I can send and receive FDCAN messages already, I said it is difficult for me is as below




    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. 

    i dont know how to get a queue buffer and let it works well. not for FDCAN config.

    I have checked your link, but i found it no new information for me.

    could you teach me how to get a queue buffer and let it works well for this situation?

     

    Thanks.

    Explorer
    August 22, 2025

    >...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

    The CAN bus is not synchronous, you cannot send a message directly, but only add it to the queue.
    It will only be sent once the CAN peripheral acquires the bus the next time (or the current transmission by the same node is finished).

    Thus you have to wait for the AddMessage call until there is free space.
    You could implement an additional, memory-based queue you operate based upon CAN interrupts. This is what we use in my company, either implemented by ourselves or within a commercial CAN stack.