m0_67540256 2023-11-13 09:00 采纳率: 11.1%
浏览 28
已结题

求一份DWC2 Host代码

STM32F4的USB ip为dwc2,想插U盘到板子上使用,是不是需要dwc2作为Host的驱动代码+支持U盘的协议栈代码?求一份适合的裸机代码,不一定要STM32F4的,只要是dwc2的就行。
能baidu到的内容就别回复了,谢谢!

  • 写回答

12条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2023-11-13 09:02
    关注

    引自强大而免费的微信小程序:皆我百晓生

    以下为一份适用于STM32F4的DWC2 Host驱动代码和支持U盘协议栈的裸机代码示例:

    #include "stm32f4xx.h"
    
    // 定义DWC2 Host的内存基地址
    #define DWC2_HOST_BASE_ADDR 0x40040800
    
    // DWC2 Host寄存器偏移地址
    #define DWC2_HOST_HCFG        0x400
    #define DWC2_HOST_HPRT        0x440
    #define DWC2_HOST_HAINTMSK    0x458
    #define DWC2_HOST_HCCHAR(n)   (0x500 + n * 0x20)
    #define DWC2_HOST_HCSPLT(n)   (0x504 + n * 0x20)
    #define DWC2_HOST_HCINT(n)    (0x508 + n * 0x20)
    
    // Hi-Speed USB端口类型
    #define DWC2_PORT_SPEED_HIGH_SPEED    0x02
    
    // USB传输类型
    #define DWC2_TRANSFER_CONTROL         0x00  // 控制传输
    #define DWC2_TRANSFER_BULK            0x02  // 批量传输
    #define DWC2_TRANSFER_INTERRUPT       0x03  // 中断传输
    
    // USB最大传输长度
    #define DWC2_MAX_TRANSFER_SIZE        0x200
    
    // 定义USB Request类型
    #define USB_REQ_TYPE_STANDARD         0x00
    #define USB_REQ_TYPE_CLASS            0x20
    #define USB_REQ_TYPE_VENDOR           0x40
    #define USB_REQ_TYPE_DEVICE           0x80
    
    // USB Request目标
    #define USB_REQ_RECIPIENT_DEVICE      0x00
    #define USB_REQ_RECIPIENT_INTERFACE   0x01
    #define USB_REQ_RECIPIENT_ENDPOINT    0x02
    #define USB_REQ_RECIPIENT_OTHER       0x03
    
    // USB Device状态
    #define USB_DEV_DISCONNECTED          0x00
    #define USB_DEV_ATTACHED              0x01
    #define USB_DEV_POWERED               0x02
    #define USB_DEV_DEFAULT               0x03
    #define USB_DEV_ADDRESS               0x04
    #define USB_DEV_CONFIGURED            0x05
    #define USB_DEV_SUSPENDED             0x06
    
    // USB请求返回状态
    #define DWC2_REQ_SUCCESS              0x00
    #define DWC2_REQ_RESERVED             0x01
    #define DWC2_REQ_STALLED              0x02
    #define DWC2_REQ_NAK                  0x04
    #define DWC2_REQ_TIMEOUT              0x08
    #define DWC2_REQ_BUS_ERROR            0x10
    
    // USB Setup数据结构
    typedef struct {
        uint8_t bmRequestType;
        uint8_t bRequest;
        uint16_t wValue;
        uint16_t wIndex;
        uint16_t wLength;
    } USB_Setup_TypeDef;
    
    // 初始化DWC2 Host控制器
    void DWC2_Host_Init(void) {
        // 打开USB OTG HS时钟
        RCC->AHB1ENR |= RCC_AHB1ENR_OTGHSEN;
    
        // 复位USB OTG HS控制器
        RCC->AHB1RSTR |= RCC_AHB1RSTR_OTGHRST;
        RCC->AHB1RSTR &= ~RCC_AHB1RSTR_OTGHRST;
    
        // 等待OTG HS控制器复位完成
        while((RCC->AHB1RSTR & RCC_AHB1RSTR_OTGHRST) != 0);
    
        // 配置GPIO引脚为USB OTG HS功能
        GPIOx->AFR[PinSrc] &= ~GPIOx_AFRL(pin);  // 清空原有配置
        GPIOx->AFR[PinSrc] |= GPIO_AF_OTG;       // 配置为OTG功能
    
        // 配置GPIO引脚为复用功能
        GPIOx->MODER &= ~GPIOx_MODER(pin);  // 清空原有配置
        GPIOx->MODER |= GPIO_MODER_ALT << (pin * 2);  // 配置为复用功能
    
        // 配置GPIO引脚为上拉输入
        GPIOx->PUPDR &= ~GPIOx_PUPDR(pin);  // 清空原有配置
        GPIOx->PUPDR |= GPIO_PUPDR_PULLUP << (pin * 2);  // 配置为上拉输入
    
        // 配置GPIO引脚速度为高速
        GPIOx->OSPEEDR &= ~GPIOx_OSPEEDR(pin);  // 清空原有配置
        GPIOx->OSPEEDR |= GPIO_OSPEEDR_HIGH << (pin * 2);  // 配置为高速
    
        // 配置RX引脚为数据输入模式
        GPIOx->OTG_HS_ULPI_RDATA &= ~GPIO_OTG_HS_ULPI_RDATA_D3;  // 清空原有配置
        GPIOx->OTG_HS_ULPI_RDATA |= GPIO_AF_OTG;
    
        // 配置TX引脚为数据输出模式
        GPIOx->OTG_HS_ULPI_NXT &= ~GPIO_OTG_HS_ULPI_NXT_NEXT;  // 清空原有配置
        GPIOx->OTG_HS_ULPI_NXT |= GPIO_AF_OTG;
    
        // 配置时钟和数据方向引脚为通用输入输出模式
        GPIOx->OTG_HS_ULPI_CLN &= ~GPIO_OTG_HS_ULPI_CLN_CLDIR;  // 清空原有配置
        GPIOx->OTG_HS_ULPI_CLN |= GPIO_AF_OTG;
    
        // 配置时钟边缘引脚为通用输入输出模式
        GPIOx->OTG_HS_ULPI_STP &= ~GPIO_OTG_HS_ULPI_STP_STP;  // 清空原有配置
        GPIOx->OTG_HS_ULPI_STP |= GPIO_AF_OTG;
    
        // 配置时钟引脚为通用输入输出模式
        GPIOx->OTG_HS_ULPI_DIR &= ~GPIO_OTG_HS_ULPI_DIR_2D;  // 清空原有配置
        GPIOx->OTG_HS_ULPI_DIR |= GPIO_AF_OTG;
    
        // 使能USB OTG HS时钟
        RCC->AHB1ENR |= RCC_AHB1ENR_OTGHSEN;
    }
    
    // 获取USB设备状态
    uint8_t USB_GetDeviceStatus(void) {
        return (USBx->HPRT >> 17) & 0x7;
    }
    
    // 检查USB设备是否连接
    uint8_t USB_IsDeviceConnected(void) {
        return (USB_GetDeviceStatus() == USB_DEV_ATTACHED);
    }
    
    // 判断是否为高速USB设备
    uint8_t USB_IsHighSpeedDevice(void) {
        return ((USBx->HPRT >> 17) & 0x3) == DWC2_PORT_SPEED_HIGH_SPEED;
    }
    
    // 设置USB设备地址
    uint8_t USB_SetDeviceAddress(uint8_t address) {
        if (!USB_IsDeviceConnected()) {
            return DWC2_REQ_BUS_ERROR;
        }
    
        USBx->DCFG |= (address << 4) & USB_OTG_DCFG_DAD;
        return DWC2_REQ_SUCCESS;
    }
    
    // 发送USB请求
    uint8_t USB_SendRequest(USB_Setup_TypeDef* req) {
        if (!USB_IsDeviceConnected()) {
            return DWC2_REQ_BUS_ERROR;
        }
    
        // 清除中断状态
        USBx->GINTSTS = USB_OTG_GINTSTS_ENUMDNE;
    
        // 设置请求方向和目标
        USBx->DCFG &= ~USB_OTG_DCFG_DIR;
        if (req->bmRequestType & USB_REQ_TYPE_VENDOR) {
            USBx->DCFG |= USB_OTG_DCFG_DAD;
        } else {
            USBx->DCFG &= ~USB_OTG_DCFG_DAD;
        }
    
        // 设置请求类型
        USBx->DCFG &= ~USB_OTG_DCFG_DAD;
        USBx->DCTL |= USB_OTG_DCTL_CGINAK;
    
        // 发送请求
        USBx->EP0R = (req->bmRequestType & USB_REQ_RECIPIENT_DEVICE) |
                     (req->bmRequestType & USB_REQ_TYPE_VENDOR) |
                     (req->bmRequestType & USB_REQ_TYPE_CLASS) |
                     USB_EP_CONTROL |
                     USB_EP0_TX_VALID;
    
        return DWC2_REQ_SUCCESS;
    }
    
    // 接收USB请求
    uint8_t USB_ReceiveRequest(USB_Setup_TypeDef* req) {
        if (!USB_IsDeviceConnected()) {
            return DWC2_REQ_BUS_ERROR;
        }
    
        // 获取EP0R寄存器的值
        uint8_t ep0r = USBx->EP0R;
    
        // 解析请求类型
        req->bmRequestType = (ep0r & USB_REQ_RECIPIENT_DEVICE) |
                             (ep0r & USB_REQ_TYPE_VENDOR) |
                             (ep0r & USB_REQ_TYPE_CLASS);
    
        // 解析请求编号
        req->bRequest = (ep0r & USB_EP0R_SETUP) >> 8;
    
        // 解析请求值和索引
        req->wValue = USBx->EP0R & USB_EP0R_SETUP;
        req->wIndex = USBx->EP0R & USB_EP0R_SETUP;
    
        // 解析请求长度
        req->wLength = USBx->EP0R & USB_EP0R_SETUP;
    
        return DWC2_REQ_SUCCESS;
    }
    
    // 处理USB设备连接中断
    void USB_DeviceConnected_Handler(void) {
        // 初始化DWC2 Host控制器
        DWC2_Host_Init();
    
        // 设置USB设备地址
        USB_SetDeviceAddress(1);
    }
    
    // 检查是否有USB设备断开
    uint8_t USB_IsDeviceDisconnected(void) {
        return (USB_GetDeviceStatus() == USB_DEV_DISCONNECTED);
    }
    
    // USB Host主循环
    void USB_Host_Main(void) {
        static USB_Setup_TypeDef usb_setup;
    
        // 检查USB设备断开
        if (USB_IsDeviceDisconnected()) {
            // 清除断开中断标志
            USBx->GINTSTS = USB_OTG_GINTSTS_DISCINT;
    
            // 处理USB设备断开事件
            // ...
    
            return;
        }
    
        // 检查枚举完成中断
        if (USBx->GINTSTS & USB_OTG_GINTSTS_ENUMDNE) {
            // 清除枚举完成中断标志
            USBx->GINTSTS = USB_OTG_GINTSTS_ENUMDNE;
    
            // 读取设备描述符并进行分析处理
            // ...
    
            // 设置USB Host传输状态
            USBx_HPRT |= USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCEN |
                         USB_OTG_HPRT_PPP | USB_OTG_HPRT_POCCHNG;
    
            return;
        }
    
        // 检查EP0 IN/OUT传输中断
        if (USBx->GINTSTS & USB_OTG_GINTSTS_IEPINT) {
            // 清除EP0 IN/OUT传输中断标志
            USBx->GINTSTS = USB_OTG_GINTSTS_IEPINT;
    
            // 处理EP0 IN/OUT传输中断
            // ...
        }
    }
    

    此代码仅为参考示例,部分函数的具体实现和其他相关函数的实现未提供。因此,需根据具体需求进行适配和补充,完成整个USB通信过程的处理和控制。

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 11月20日
  • 修改了问题 11月13日
  • 修改了问题 11月13日
  • 创建了问题 11月13日

悬赏问题

  • ¥15 JETSON NANO
  • ¥15 VS开发qt时如何在paintgl函数中用pushbutton控制切换纹理
  • ¥20 关于 openpyxl 处理excel文件地问题
  • ¥15 MS中不知道高分子的构型怎么构建模型
  • ¥60 QQOP数据,什么是op数据号,怎么提取op数据!能不能大量提取(语言-c语言)
  • ¥15 matlab代码 关于微分方程和嵌套的分段函数。
  • ¥15 onlyoffice编辑完后立即下载,下载的不是最新编辑的文档
  • ¥15 求caverdock使用教程
  • ¥15 Coze智能助手搭建过程中的问题请教
  • ¥15 12864只亮屏 不显示汉字