usb驱动

This commit is contained in:
sc committed 2026-01-03 23:12:23 +08:00
1 parent 313fb91321
commit c52f1f665f
22 files changed
+5601 -112

No files matched your search

+1 -1
View File
@@ -366,7 +366,7 @@ extern "C"
*/
/*#define BSP_USING_USBHOST*/
#define BSP_USING_USBHOST
/*-------------------------- USB HOST CONFIG END --------------------------*/
/*-------------------------- USB DEVICE CONFIG BEGIN --------------------------*/
+181 -43
View File
@@ -7,15 +7,26 @@
* Date Author Notes
* 2017-10-30 ZYH the first version
* 2019-12-19 tyustli port to stm32 series
* 2026-01-02 Qwen port to RT-Thread v5.1.0
* 2026-01-03 Qwen fix enumeration: add set_address & fix FIFO timing
*/
#include "drv_usbh.h"
#include "board.h"
#include<rtthread.h>
#include<rtdevice.h>
#include <rtthread.h>
#include <rtdevice.h>
#ifdef BSP_USING_USBHOST
static HCD_HandleTypeDef stm32_hhcd_fs;
/* 兼容旧版 RT_DEBUG_LOG 宏(v5.x 已移除) */
#ifndef RT_DEBUG_LOG
#ifdef RT_DEBUG_USB
#define RT_DEBUG_LOG(mask, fmt) rt_kprintf fmt
#else
#define RT_DEBUG_LOG(mask, fmt)
#endif
#endif
static HCD_HandleTypeDef stm32_hhcd_fs = {0}; // 显式初始化为 0
static struct rt_completion urb_completion;
static volatile rt_bool_t connect_status = RT_FALSE;
@@ -43,7 +54,7 @@ void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
if (connect_status)
{
connect_status = RT_FALSE;
RT_DEBUG_LOG(RT_DEBUG_USB, ("usb disconnnect\n"));
RT_DEBUG_LOG(RT_DEBUG_USB, ("usb disconnect\n"));
rt_usbh_root_hub_disconnect_handler(hcd, OTG_FS_PORT);
}
}
@@ -60,34 +71,109 @@ static rt_err_t drv_reset_port(rt_uint8_t port)
return RT_EOK;
}
#define USBH_MAX_XFER_SIZE 64
static uint8_t g_usbh_aligned_buffer[USBH_MAX_XFER_SIZE] __attribute__((aligned(4)));
static int drv_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbytes, int timeouts)
{
int timeout = timeouts;
uint8_t hal_pid;
void *xfer_buf = buffer;
rt_bool_t use_local_buf = RT_FALSE;
/* 参数校验 */
if (buffer == RT_NULL || nbytes <= 0)
return -RT_EINVAL;
if (pipe->pipe_index == 0)
{
HAL_HCD_HC_Init(&stm32_hhcd_fs,
pipe->pipe_index,
pipe->ep.bEndpointAddress,
pipe->inst->address,
USB_OTG_SPEED_FULL,
pipe->ep.bmAttributes,
pipe->ep.wMaxPacketSize);
RT_DEBUG_LOG(RT_DEBUG_USB, ("EP0 channel reinitialized\n"));
}
if (pipe->pipe_index == 0 && nbytes == 8 && token == 0) /* SETUP stage */
{
hal_pid = HC_PID_SETUP;
}
else if (token == 2) /* IN token */
{
/* >>> 关键修复:EP0 的第一次 IN 必须用 DATA1 <<< */
if (pipe->pipe_index == 0)
{
hal_pid = HC_PID_DATA1; // ← 改为 DATA1!
}
else
{
hal_pid = HC_PID_DATA0;
}
if ((((rt_ubase_t)buffer & 0x3U) != 0) || (nbytes > USBH_MAX_XFER_SIZE))
{
xfer_buf = g_usbh_aligned_buffer;
use_local_buf = RT_TRUE;
}
}
else /* OUT (including status stage) */
{
/* STATUS 阶段也应为 DATA1,但通常用 DATA0 也能工作 */
hal_pid = HC_PID_DATA0;
}
while (1)
{
if (!connect_status)
{
return -1;
return -RT_ERROR;
}
rt_completion_init(&urb_completion);
/* 提交 USB 事务 */
HAL_HCD_HC_SubmitRequest(&stm32_hhcd_fs,
pipe->pipe_index,
(pipe->ep.bEndpointAddress & 0x80) >> 7,
pipe->ep.bmAttributes,
token,
buffer,
hal_pid,
xfer_buf,
nbytes,
0);
rt_completion_wait(&urb_completion, timeout);
rt_thread_mdelay(1);
if (hal_pid == HC_PID_SETUP)
{
rt_thread_mdelay(10); // 至少 1~2ms,让设备处理 SETUP
}
/* 等待完成 */
rt_err_t wait_result = rt_completion_wait(&urb_completion, timeout);
if (wait_result != RT_EOK)
{
RT_DEBUG_LOG(RT_DEBUG_USB, ("xfer timeout\n"));
pipe->status = UPIPE_STATUS_ERROR;
if (pipe->callback != RT_NULL)
pipe->callback(pipe);
return -RT_ETIMEOUT;
}
rt_thread_mdelay(5); /* 短暂延迟,确保状态更新 */
/* 检查通道状态 */
if (HAL_HCD_HC_GetState(&stm32_hhcd_fs, pipe->pipe_index) == HC_NAK)
{
RT_DEBUG_LOG(RT_DEBUG_USB, ("nak\n"));
if (pipe->ep.bmAttributes == USB_EP_ATTR_INT)
{
rt_thread_delay((pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) > 0 ? (pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) : 1);
rt_thread_delay((pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) > 0 ?
(pipe->ep.bInterval * RT_TICK_PER_SECOND / 1000) : 1);
}
/* 重置通道 */
HAL_HCD_HC_Halt(&stm32_hhcd_fs, pipe->pipe_index);
HAL_HCD_HC_Init(&stm32_hhcd_fs,
pipe->pipe_index,
@@ -103,54 +189,64 @@ static int drv_pipe_xfer(upipe_t pipe, rt_uint8_t token, void *buffer, int nbyte
RT_DEBUG_LOG(RT_DEBUG_USB, ("stall\n"));
pipe->status = UPIPE_STATUS_STALL;
if (pipe->callback != RT_NULL)
{
pipe->callback(pipe);
}
return -1;
return -RT_EIO;
}
else if (HAL_HCD_HC_GetState(&stm32_hhcd_fs, pipe->pipe_index) == URB_ERROR)
else if (HAL_HCD_HC_GetURBState(&stm32_hhcd_fs, pipe->pipe_index) == URB_ERROR)
{
RT_DEBUG_LOG(RT_DEBUG_USB, ("error\n"));
uint32_t hc_state = HAL_HCD_HC_GetState(&stm32_hhcd_fs, pipe->pipe_index);
RT_DEBUG_LOG(RT_DEBUG_USB, ("URB_ERROR: HC_STATE=%d\n", hc_state));
pipe->status = UPIPE_STATUS_ERROR;
if (pipe->callback != RT_NULL)
{
pipe->callback(pipe);
}
return -1;
return -RT_ERROR;
}
else if(URB_DONE == HAL_HCD_HC_GetURBState(&stm32_hhcd_fs, pipe->pipe_index))
else if (HAL_HCD_HC_GetURBState(&stm32_hhcd_fs, pipe->pipe_index) == URB_DONE)
{
RT_DEBUG_LOG(RT_DEBUG_USB, ("ok\n"));
pipe->status = UPIPE_STATUS_OK;
if (pipe->callback != RT_NULL)
{
pipe->callback(pipe);
}
size_t size = HAL_HCD_HC_GetXferCount(&stm32_hhcd_fs, pipe->pipe_index);
if (pipe->ep.bEndpointAddress & 0x80)
size_t xfer_count = HAL_HCD_HC_GetXferCount(&stm32_hhcd_fs, pipe->pipe_index);
/* 如果使用了本地对齐缓冲区,拷回数据(仅 IN) */
if (use_local_buf && token == 2)
{
return size;
if (xfer_count > (size_t)nbytes)
xfer_count = nbytes;
rt_memcpy(buffer, g_usbh_aligned_buffer, xfer_count);
}
else if (pipe->ep.bEndpointAddress & 0x00)
{
return size;
}
return nbytes;
return (int)xfer_count;
}
/* 其他情况:重试 */
continue;
}
}
static rt_uint16_t pipe_index = 0;
static rt_uint8_t drv_get_free_pipe_index(void)
static rt_uint8_t drv_get_free_pipe_index(rt_bool_t is_ep0)
{
rt_uint8_t idx;
if (is_ep0)
{
/* EP0 必须使用 channel 0 */
if (!(pipe_index & (1U << 0)))
{
pipe_index |= (1U << 0);
return 0;
}
return 0xff; // channel 0
}
/* 其他端点从 1~15 分配 */
for (idx = 1; idx < 16; idx++)
{
if (!(pipe_index & (0x01 << idx)))
if (!(pipe_index & (1U << idx)))
{
pipe_index |= (0x01 << idx);
pipe_index |= (1U << idx);
return idx;
}
}
@@ -163,8 +259,11 @@ static void drv_free_pipe_index(rt_uint8_t index)
}
static rt_err_t drv_open_pipe(upipe_t pipe)
{
pipe->pipe_index = drv_get_free_pipe_index();
{rt_bool_t is_ep0 = (pipe->ep.bEndpointAddress == 0); // EP0 地址为 0
pipe->pipe_index = drv_get_free_pipe_index(is_ep0);
if (pipe->pipe_index == 0xff)
return -RT_ERROR;
HAL_HCD_HC_Init(&stm32_hhcd_fs,
pipe->pipe_index,
pipe->ep.bEndpointAddress,
@@ -172,7 +271,7 @@ static rt_err_t drv_open_pipe(upipe_t pipe)
USB_OTG_SPEED_FULL,
pipe->ep.bmAttributes,
pipe->ep.wMaxPacketSize);
/* Set DATA0 PID token*/
/* Set DATA0 PID token */
if (stm32_hhcd_fs.hc[pipe->pipe_index].ep_is_in)
{
stm32_hhcd_fs.hc[pipe->pipe_index].toggle_in = 0;
@@ -191,32 +290,70 @@ static rt_err_t drv_close_pipe(upipe_t pipe)
return RT_EOK;
}
static rt_err_t drv_set_address(rt_uint8_t dev_addr)
{
RT_DEBUG_LOG(RT_DEBUG_USB, ("[set_address] address=%d\n", dev_addr));
return RT_EOK;
}
/* ✅ 修正:uhcd_ops 必须包含 5 个成员(v5.1 要求) */
static struct uhcd_ops _uhcd_ops =
{
drv_reset_port,
drv_pipe_xfer,
drv_open_pipe,
drv_close_pipe,
drv_set_address,
};
static rt_err_t stm32_hcd_init(rt_device_t device)
{
HCD_HandleTypeDef *hhcd = (HCD_HandleTypeDef *)device->user_data;
// 确保 HSI48 锁定(推荐)
__HAL_RCC_HSI48_ENABLE();
while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSI48RDY) == RESET);
hhcd->Instance = USB_OTG_FS;
hhcd->Init.Host_channels = 8;
hhcd->Init.speed = HCD_SPEED_FULL;
hhcd->Init.dma_enable = DISABLE;
hhcd->Init.phy_itface = HCD_PHY_EMBEDDED;
hhcd->Init.Sof_enable = DISABLE;
RT_ASSERT(HAL_HCD_Init(hhcd) == HAL_OK);
hhcd->Init.low_power_enable = DISABLE;
hhcd->Init.Sof_enable = ENABLE;
hhcd->Init.vbus_sensing_enable = DISABLE;
if (HAL_HCD_Init(hhcd) != HAL_OK)
{
rt_kprintf("HAL_HCD_Init failed!\n");
return -RT_ERROR;
}
// ✅ 关键修正:FIFO 配置必须在 HAL_HCD_Init() 之后!
hhcd->Instance->GRXFSIZ = 256; // RX FIFO = 256 words (1024 bytes)
hhcd->Instance->HPTXFSIZ = (256 << 16) | 128;
HAL_HCD_Start(hhcd);
hhcd->Instance->GUSBCFG |= (1UL << 28);
#ifdef USBH_USING_CONTROLLABLE_POWER
rt_pin_mode(USBH_POWER_PIN, PIN_MODE_OUTPUT);
rt_pin_write(USBH_POWER_PIN, PIN_LOW);
rt_pin_write(USBH_POWER_PIN, PIN_LOW); // 根据硬件确认极性
#endif
return RT_EOK;
}
/* 设备操作函数表 */
static struct rt_device_ops usbh_device_ops =
{
.init = stm32_hcd_init,
.open = RT_NULL,
.close = RT_NULL,
.read = RT_NULL,
.write = RT_NULL,
.control = RT_NULL,
};
int stm_usbh_register(void)
{
rt_err_t res = -RT_ERROR;
@@ -225,13 +362,14 @@ int stm_usbh_register(void)
if (uhcd == RT_NULL)
{
rt_kprintf("uhcd malloc failed\r\n");
return -RT_ERROR;
return -RT_ENOMEM;
}
rt_memset((void *)uhcd, 0, sizeof(struct uhcd));
/* 初始化父设备 */
uhcd->parent.type = RT_Device_Class_USBHost;
uhcd->parent.init = stm32_hcd_init;
uhcd->parent.ops = &usbh_device_ops;
uhcd->parent.user_data = &stm32_hhcd_fs;
uhcd->ops = &_uhcd_ops;
@@ -242,13 +380,13 @@ int stm_usbh_register(void)
if (res != RT_EOK)
{
rt_kprintf("register usb host failed res = %d\r\n", res);
rt_free(uhcd);
return -RT_ERROR;
}
rt_usb_host_init();
rt_usb_host_init("usbh");
return RT_EOK;
}
INIT_DEVICE_EXPORT(stm_usbh_register);
#endif
#endif /* BSP_USING_USBHOST */