cancel
Showing results for 
Search instead for 
Did you mean: 

H7 CAN hot-plug problem

奥特曼9527
Associate II
void HAL_FDCAN_TxBufferCompleteCallback(FDCAN_HandleTypeDef *hfdcan, uint32_t BufferIndexes)
{
	extern FDCAN_HandleTypeDef hfdcan1;
	if(hfdcan == &hfdcan1)
	{
	//	printf("tx cplt = %d\n",BufferIndexes);
		can_tx_cplt = 1;
	}
}


void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef *hfdcan)
{
    // 错误处理
    //printf("FDCAN Error Callback: ErrorCode=%lu\n", (unsigned long)(hfdcan->ErrorCode));
    uint32_t error;
    error = HAL_FDCAN_GetError(hfdcan);
	if(error == 4)
	{
		can_init();
	}
	printf("FDCAN Error = %d\n",error);
}

void can_send_msg(uint32_t id, uint8_t *data)
{
   can_send_msg_len(id,data,3);
}

#if 1
void can_send_msg_len(uint32_t id, uint8_t *data,uint8_t len)
{
    FDCAN_TxHeaderTypeDef FDCAN_Tx;
    static uint32_t can_tx_time_out_count = 0;
    extern FDCAN_HandleTypeDef hfdcan1;
    uint8_t retry_count = 0;
	bool flag = 0;
    FDCAN_Tx.TxFrameType = FDCAN_DATA_FRAME;
    FDCAN_Tx.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
    FDCAN_Tx.MessageMarker = 0x00;
    FDCAN_Tx.Identifier = id; // 使用输入的ID
    FDCAN_Tx.IdType = FDCAN_STANDARD_ID;
    FDCAN_Tx.FDFormat = FDCAN_CLASSIC_CAN;
    FDCAN_Tx.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
    FDCAN_Tx.DataLength = len;
    FDCAN_Tx.BitRateSwitch = FDCAN_BRS_OFF;
	can_tx_cplt = 0;
    HAL_StatusTypeDef state = HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &FDCAN_Tx, data);    
    if (state != HAL_OK)
    {
        #if (CAN_DEBUG_INFO == 1)
        typedef struct {
            const char *string;
            uint32_t error_val;
        } CAN_ERROR_TYPE;

        const CAN_ERROR_TYPE can_error_string[] = {
            {"HAL_FDCAN_ERROR_NONE",           ((uint32_t)0x00000000U)},
            {"HAL_FDCAN_ERROR_TIMEOUT",        ((uint32_t)0x00000001U)},
            {"HAL_FDCAN_ERROR_NOT_INITIALIZED",((uint32_t)0x00000002U)},
            {"HAL_FDCAN_ERROR_NOT_READY",      ((uint32_t)0x00000004U)},
            {"HAL_FDCAN_ERROR_NOT_STARTED",    ((uint32_t)0x00000008U)},
            {"HAL_FDCAN_ERROR_NOT_SUPPORTED",  ((uint32_t)0x00000010U)},
            {"HAL_FDCAN_ERROR_PARAM",          ((uint32_t)0x00000020U)},
            {"HAL_FDCAN_ERROR_PENDING",        ((uint32_t)0x00000040U)},
            {"HAL_FDCAN_ERROR_RAM_ACCESS",     ((uint32_t)0x00000080U)},
            {"HAL_FDCAN_ERROR_FIFO_EMPTY",     ((uint32_t)0x00000100U)},
            {"HAL_FDCAN_ERROR_FIFO_FULL",      ((uint32_t)0x00000200U)}
        };

        uint8_t index = 0;
        uint32_t error_code = hfdcan1.ErrorCode;

        for (int i = 0; i < sizeof(can_error_string) / sizeof(CAN_ERROR_TYPE); i++) {
            if (error_code & can_error_string[i].error_val) {
                index = i;
                break;
            }
        }

        // 重新初始化和启动CAN
		printf("重新初始化\n");
		__HAL_RCC_FDCAN_FORCE_RESET();
		__HAL_RCC_FDCAN_RELEASE_RESET();
		can_init();
        printf("%s\n", can_error_string[index].string);
        printf("can_error_val = 0x%08x\n", error_code);
        #endif
    }
    else 
    {
	
		uint32_t start_time = HAL_GetTick(); // 获取当前的系统时间
		while ((can_tx_cplt == 0) && ((HAL_GetTick() - start_time) < 10)) // 超时 500ms
		{
			// 等待发送完成
		}
		uint32_t time = HAL_GetTick() - start_time;
		if (time >= 10)
		{
			printf("CAN[0x%0x] Send Time Out = %d\n", id,time);
			can_tx_cplt = 0;
			can_init();
		}
		else
		{
		   //printf("XAN=%d\n",time);
		}
		
	//	can_tx_cplt = 0;
    }
}

I am currently testing the hot plug of CAN. When I unplug the external CAN device, I continue to send data, but the transmission fails. When I reconnect the external CAN device, my code will report an error.

9527_0-1751512654474.png

void MX_FDCAN1_Init(void)
{

  /* USER CODE BEGIN FDCAN1_Init 0 */

  /* USER CODE END FDCAN1_Init 0 */

  /* USER CODE BEGIN FDCAN1_Init 1 */

  /* USER CODE END FDCAN1_Init 1 */
  hfdcan1.Instance = FDCAN1;
  hfdcan1.Init.FrameFormat = FDCAN_FRAME_CLASSIC;
  hfdcan1.Init.Mode = FDCAN_MODE_NORMAL;
  hfdcan1.Init.AutoRetransmission = ENABLE;
  hfdcan1.Init.TransmitPause = DISABLE;
  hfdcan1.Init.ProtocolException = ENABLE;
  hfdcan1.Init.NominalPrescaler = 96;
  hfdcan1.Init.NominalSyncJumpWidth = 1;
  hfdcan1.Init.NominalTimeSeg1 = 7;
  hfdcan1.Init.NominalTimeSeg2 = 2;
  hfdcan1.Init.DataPrescaler = 12;
  hfdcan1.Init.DataSyncJumpWidth = 2;
  hfdcan1.Init.DataTimeSeg1 = 7;
  hfdcan1.Init.DataTimeSeg2 = 2;
  hfdcan1.Init.MessageRAMOffset = 0;
  hfdcan1.Init.StdFiltersNbr = 1;
  hfdcan1.Init.ExtFiltersNbr = 0;
  hfdcan1.Init.RxFifo0ElmtsNbr = 1;
  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 = 1;
  hfdcan1.Init.TxFifoQueueMode = FDCAN_TX_FIFO_OPERATION;
  hfdcan1.Init.TxElmtSize = FDCAN_DATA_BYTES_64;
  if (HAL_FDCAN_Init(&hfdcan1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN FDCAN1_Init 2 */
  FDCAN_FilterTypeDef sFilterConfig;
    /* Configure Rx filter */
  sFilterConfig.IdType = FDCAN_STANDARD_ID;
  sFilterConfig.FilterIndex = 0;
  sFilterConfig.FilterType = FDCAN_FILTER_MASK;
  sFilterConfig.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
  sFilterConfig.FilterID1 = 0x500;	// 基准ID,最小ID
  sFilterConfig.FilterID2 = 0x700;	// 掩码为0x3F,匹配0x5A0到0x5B3范围
  if (HAL_FDCAN_ConfigFilter(&hfdcan1, &sFilterConfig) != HAL_OK)
  {
    /* Filter configuration Error */
    Error_Handler();
  }

  /* Configure global filter to reject all non-matching frames */
  HAL_FDCAN_ConfigGlobalFilter(&hfdcan1, FDCAN_REJECT, FDCAN_REJECT, FDCAN_REJECT_REMOTE, FDCAN_REJECT_REMOTE);
  HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_TX_COMPLETE , FDCAN_TX_BUFFER0);
  if (HAL_FDCAN_Start(&hfdcan1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_FDCAN_ActivateNotification(&hfdcan1, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0) != HAL_OK)
  {
    /* Notification Error */
    Error_Handler();
  }

  /* USER CODE END FDCAN1_Init 2 */

}
void can_init(void)
{
	// 停止外设
	HAL_FDCAN_Stop(&hfdcan1);

	// 复位错误状态
	hfdcan1.State = HAL_FDCAN_STATE_RESET;

	HAL_FDCAN_DeInit(&hfdcan1);
	// 重新初始化并启动
	HAL_FDCAN_Init(&hfdcan1);
	MX_FDCAN1_Init();
	HAL_FDCAN_Start(&hfdcan1);
}
1 REPLY 1
Ozone
Principal

> I am currently testing the hot plug of CAN. When I unplug the external CAN device, I continue to send data, but the transmission fails.

The CAN bus is designed for "static" use cases, hot-plugging is not supported.

> When I reconnect the external CAN device, my code will report an error.

Especially not use cases with just two nodes. Every unacknowledged transmission will cause the error count to go up, eventually causing bus shutdown (error passive , bus-off).