STM32H5移植USBX+FreeRTOS发送异常:每3次仅成功1次排查咨询
问题排查与解决方案
核心问题定位
- USBX系统任务调度频率不足:
StartDefaultTask中每1秒才调用1次ux_system_tasks_run(),而USBX的STANDALONE模式需要高频调用该函数处理USB事务(包括发送缓冲区调度、端点状态处理等)。发送请求提交后,若ux_system_tasks_run()未及时执行,USBX无法完成实际传输,后续请求会因缓冲区被占用而失败。 - 发送函数未处理缓冲区忙状态:
ux_device_class_cdc_acm_write_with_callback返回失败通常是因为CDC发送缓冲区已满,代码直接返回-1,无重试机制。
具体修复步骤
1. 提升USBX系统任务调度频率
修改StartDefaultTask增加调用频率,或单独创建高优先级USBX专属任务:
方案1:修改原有任务
void StartDefaultTask(void *argument) { /* USER CODE BEGIN defaultTask */ /* Infinite loop */ for(;;) { /*==============LED===========================*/ HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_SET); vTaskDelay(500); HAL_GPIO_WritePin(GPIOC, GPIO_PIN_12, GPIO_PIN_RESET); vTaskDelay(500); // 循环调用多次,确保USBX事务被及时处理 for(int i=0; i<10; i++){ ux_system_tasks_run(); taskYIELD(); // 主动让出CPU,避免阻塞其他任务 } } /* USER CODE END defaultTask */ }
方案2:创建独立USBX任务(推荐)
void USBXSystemTask(void *argument) { for(;;) { ux_system_tasks_run(); vTaskDelay(1); // 短延迟保证高频调度,同时不占用过多CPU } } // 在main函数中添加任务创建代码 // xTaskCreate(USBXSystemTask, "USBXTask", 128, NULL, configMAX_PRIORITIES-1, NULL);
2. 给发送函数添加重试机制
修改ux_device_cdc_acm_send,在超时时间内重试发送:
int ux_device_cdc_acm_send(uint8_t *datas, uint32_t len, uint32_t timeout) { uint32_t start_tick = HAL_GetTick(); if (!cdc_acm) { return -1; } do { if (UX_SUCCESS == ux_device_class_cdc_acm_write_with_callback(cdc_acm, datas, len)) { return 0; } vTaskDelay(1); // 短延迟后重试,避免死循环占用CPU } while ((HAL_GetTick() - start_tick) < timeout); return -1; // 超时失败 }
3. 检查USBX CDC缓冲区配置
在STM32CubeMX中,确认USB CDC发送缓冲区大小是否足够,若缓冲区过小会导致频繁发送失败,可适当增大(如从默认64字节调整为256字节)。
验证要点
- 观察串口助手是否每秒收到连续编号的数据
- 调试查看
ux_device_cdc_acm_send返回值,确认大部分请求成功 - 确保USBX系统任务优先级高于发送任务,保证USB事务优先处理
内容的提问来源于stack exchange,提问作者li junhao
相关产品推荐
相关产品推荐

