STM32H7 CAN FD Frame Reception and Transmission Issues

The STM32H7 microcontroller’s CAN FD (Flexible Data-Rate Controller Area Network) module is a powerful peripheral designed for high-speed communication in automotive and industrial applications. However, improper configuration or subtle hardware-software interactions can lead to communication failures, error flags, and unreliable data transmission. The core issue manifests as follows:

When attempting to receive CAN FD frames, the system enters an error handling state, and the CAN analyzer software reports numerous errors. Transmission from the STM32H7 to the CAN bus results in data frames being flagged with "other error" indicators. The system appears to transmit data only once before failing, suggesting potential issues with the CAN FD initialization, interrupt handling, or message filtering configuration.

The CAN FD protocol extends the classical CAN protocol by allowing higher data rates (up to 8 Mbps) and larger payloads (up to 64 bytes). The STM32H7 implements this through its FDCAN peripheral, which requires careful configuration of several key parameters:

  • Nominal bit timing parameters for arbitration phase
  • Data bit timing parameters for data phase
  • Message RAM allocation and filtering
  • Interrupt handling and error management
  • Clock synchronization and prescaler settings

Understanding these components is crucial for diagnosing and resolving the communication issues.

Improper FDCAN Initialization and Interrupt Configuration

The root causes of CAN FD communication failures in STM32H7 systems typically stem from several interrelated factors:

  1. Clock Configuration Issues
    The FDCAN peripheral requires precise clock synchronization. Incorrect PLL configuration or improper peripheral clock source selection can lead to timing errors in CAN frame handling. The STM32H7’s complex clock tree must be configured to provide the correct frequency to the FDCAN peripheral.

  2. Message RAM Allocation
    The FDCAN peripheral uses dedicated Message RAM for storing received messages, transmit events, and filter configurations. Insufficient or improperly configured Message RAM allocation can cause message loss or corruption.

  3. Bit Timing Parameters
    CAN FD operates with two distinct bit rates: the nominal bit rate for the arbitration phase and the data bit rate for the data phase. Incorrect configuration of these parameters, including synchronization jump width and sample point placement, can lead to bit errors.

  4. Interrupt Handling
    The FDCAN peripheral relies on interrupts for efficient message handling. Improper interrupt configuration or missing interrupt service routines can result in missed messages or error conditions.

  5. Filter Configuration
    The FDCAN peripheral’s filter system must be properly configured to accept relevant messages. Incorrect filter settings can cause valid messages to be rejected or invalid messages to be accepted.

  6. Error Handling
    The FDCAN peripheral provides extensive error detection capabilities. Improper error handling configuration can lead to unnecessary error flags or failure to detect actual errors.

  7. Hardware Interface
    The physical layer interface, including transceiver configuration and termination resistors, must be properly implemented to ensure reliable communication.

Comprehensive FDCAN Configuration and Debugging Procedure

To resolve the CAN FD communication issues, follow this detailed troubleshooting and configuration procedure:

1. Clock Configuration Verification
Verify the clock configuration using the following steps:

  • Confirm the PLL configuration provides the correct frequency to the FDCAN peripheral
  • Check the FDCAN clock source selection in RCC registers
  • Verify the peripheral clock enable bit is set

2. FDCAN Initialization Sequence
Implement a robust initialization sequence:

static void MX_FDCAN1_Init(void)
{
    FDCAN_FilterTypeDef sFilterConfig;
    
    hfdcan1.Instance = FDCAN1;
    hfdcan1.Init.FrameFormat = FDCAN_FRAME_FD_BRS;
    hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
    hfdcan1.Init.AutoRetransmission = ENABLE;
    hfdcan1.Init.TransmitPause = DISABLE;
    hfdcan1.Init.ProtocolException = DISABLE;
    
    // Nominal bit timing configuration
    hfdcan1.Init.NominalPrescaler = 5;
    hfdcan1.Init.NominalSyncJumpWidth = 8;
    hfdcan1.Init.NominalTimeSeg1 = 31;
    hfdcan1.Init.NominalTimeSeg2 = 8;
    
    // Data bit timing configuration
    hfdcan1.Init.DataPrescaler = 2;
    hfdcan1.Init.DataSyncJumpWidth = 4;
    hfdcan1.Init.DataTimeSeg1 = 15;
    hfdcan1.Init.DataTimeSeg2 = 4;
    
    // Message RAM configuration
    hfdcan1.Init.MessageRAMOffset = 0;
    hfdcan1.Init.StdFiltersNbr = 1;
    hfdcan1.Init.ExtFiltersNbr = 0;
    hfdcan1.Init.RxFifo0ElmtsNbr = 3;
    hfdcan1.Init.RxFifo0ElmtSize = FDCAN_DATA_BYTES_64;
    hfdcan1.Init.TxBuffersNbr = 1;
    hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_64;
    
    if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
    {
        Error_Handler();
    }
    
    // Configure filter
    sFilterConfig.IdType = FDCAN_STANDARD_ID;
    sFilterConfig.FilterIndex = 0;
    sFilterConfig.FilterType = FDCAN_FILTER_MASK;
    sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
    sFilterConfig.FilterID1 = 0x321;
    sFilterConfig.FilterID2 = 0x7FF;
    
    if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
    {
        Error_Handler();
    }
    
    // Start FDCAN module
    if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
    {
        Error_Handler();
    }
    
    // Activate notifications
    if (HAL_FDCAN_ActivateNotification(&hfdcan1, 
        FDCAN_IT_RX_FIFO0_NEW_MESSAGE | 
        FDCAN_IT_ERROR_WARNING | 
        FDCAN_IT_ERROR_PASSIVE | 
        FDCAN_IT_BUS_OFF, 0) != HAL_OK)
    {
        Error_Handler();
    }
}

3. Interrupt Handling Implementation
Implement a comprehensive interrupt handler:

void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef *hfdcan, uint32_t RxFifo0ITs)
{
    if((RxFifo0ITs & FDCAN_IT_RX_FIFO0_NEW_MESSAGE) != RESET)
    {
        if (HAL_FDCAN_GetRxMessage(hfdcan, FDCAN_RX_FIFO0, &RxHeader, RxData) != HAL_OK)
        {
            Error_Handler();
        }
        
        // Process received message
        ProcessCANMessage(RxHeader, RxData);
        
        // Reactivate notification
        if (HAL_FDCAN_ActivateNotification(hfdcan, 
            FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
        {
            Error_Handler();
        }
    }
}

4. Error Handling and Recovery
Implement robust error handling:

void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t ErrorStatusITs)
{
    if(ErrorStatusITs & FDCAN_IT_ERROR_WARNING)
    {
        // Handle error warning state
    }
    
    if(ErrorStatusITs & FDCAN_IT_ERROR_PASSIVE)
    {
        // Handle error passive state
    }
    
    if(ErrorStatusITs & FDCAN_IT_BUS_OFF)
    {
        // Handle bus off state
        HAL_FDCAN_Stop(hfdcan);
        HAL_Delay(100);
        HAL_FDCAN_Start(hfdcan);
    }
}

5. Transmission Implementation
Implement proper transmission handling:

HAL_StatusTypeDef SendCANMessage(uint32_t id, uint8_t* data, uint8_t length)
{
    FDCAN_TxHeaderTypeDef TxHeader;
    
    TxHeader.Identifier = id;
    TxHeader.IdType = FDCAN_STANDARD_ID;
    TxHeader.TxFrameType = FDCAN_DATA_FRAME;
    TxHeader.DataLength = length;
    TxHeader.ErrorStateIndicator = FDCAN_ESI_PASSIVE;
    TxHeader.BitRateSwitch = FDCAN_BRS_ON;
    TxHeader.FDFormat = FDCAN_FD_CAN;
    TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
    TxHeader.MessageMarker = 0;
    
    return HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, data);
}

6. Debugging and Monitoring
Implement debugging features:

void PrintCANStatus(void)
{
    uint32_t status = hfdcan1.Instance->PSR;
    
    printf("CAN Status:\n");
    printf("  Last Error Code: %lu\n", (status & FDCAN_PSR_LEC) >> FDCAN_PSR_LEC_Pos);
    printf("  Activity: %s\n", (status & FDCAN_PSR_ACT) ? "Active" : "Inactive");
    printf("  Error Passive: %s\n", (status & FDCAN_PSR_EP) ? "Yes" : "No");
    printf("  Warning Status: %s\n", (status & FDCAN_PSR_EW) ? "Yes" : "No");
    printf("  Bus Off: %s\n", (status & FDCAN_PSR_BO) ? "Yes" : "No");
}

7. Physical Layer Verification
Verify the physical layer implementation:

  • Check transceiver power supply
  • Verify termination resistor value (typically 120Ω)
  • Ensure proper CAN_H and CAN_L signal levels
  • Check for signal integrity issues

By following this comprehensive guide and implementing the provided solutions, you should be able to resolve the CAN FD communication issues on the STM32H7 microcontroller. Remember to verify each configuration step and monitor the system status using the provided debugging tools.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *