关键字: STM32H5, Classic USB, CDC
1.问题发生的背景
细心的用户可能会发现,使用到我们最新的 STM32CubeMX 6.9.1 对 STM32H5 的
USB 外设进行配置的时候,只能用 USBX,而以前的 Classic USB 库不能选择了。
由于 USBx 是基于 Threadx OS 的,客户更多的希望是裸机版本的,所以在这儿给大
家提供一个移植的方法。
2.问题的分析
虽然在 STM32CubeMX 6.9.1 上不能使用经典的 Classic USB 驱动了,但是实际上在
github 上,仍能发现一些可用的资源供参考:
GitHub - STMicroelectronics/stm32h5-classic-coremw-apps: Provide a set of applications for STM32H5xx series based on the STM32 Classic Core Middleware
libraries
GitHub - STMicroelectronics/stm32u5-classic-coremw-apps: Provide a set of applications for STM32U5xx series based on the STM32 Classic Core Middleware
libraries.
下载这两个链接,发现 H5 例程里面仅仅有 Classic USB driver 的 HID 例程,并没有
CDC 的, 但这对于我们想要移植来说, 已经足够了。
3.Classic USBD CDC 驱动的移植
3.1 .解压缩编译验证原始工程
对原始的 H5 例程进行编译,发现报如下错误:
根据错误的说明,查看会发现下载的示例工程里面 :
驱动相关文件夹……\stm32h5-classic-coremw-apps-main\Drivers 里内容是空的;
解决方法:建议将最新版本的 STM32CubeH5 lib 里面的 Drivers 全部拷贝即可(含有
BSP、CMSIS、STM3H5xx_HAL_Driver);
库文件 STM32_USB_Device_Library 也为空,建议从 github 上下载:
GitHub - STMicroelectronics/stm32_mw_usb_device: Provides the USB Device library part of the STM32Cube MCU Component "middleware" for all STM32xx
series.
解压后, 再复制 stm32_mw_usb_device-master 内的 Core,Class 的文件夹到
\stm32h5-classic-coremw-apps-
main\Middlewares\ST\STM32_USB_Device_Library,编译通过, 无错误。
下载工程到到 NUCLEO H563 运行,通过设备管理器能找到相应的 HID 设备,测试按一
下 USER BUTTON 按键,则鼠标也会跟着横向移动一步.
3.2 .屏蔽掉 USB PD 相关的操作
基于此, 我们准备开始新建 CDC 的例程
细心的朋友,通过上述的列表结构,我们可以比较清楚的看到需要调整的文件: usb_device.c、 usbd_desc.c、usbd_conf.c, usbd_hid.c 及其相应的头文件,另外比较显眼的是使用到的 USB PD 的库;这个库与 USB 库没有耦合关系,主要是因为我们相关开发板上 USB 接口使用的 Type C,为了符合目前 USB 标准的相关协议规定,需要添加 PD 功能,如果客户不打算通过相关 USB
标准,则这个 PD 功能可以移除.
为了更简便的在 H5 上移植 USB Device 外设,我们将 PD 功能相关的库去除(如上图红色框
框),并屏蔽 User Code 部分关于 USBPD 的处理并解决编译错误.
Main 函数可以简化为如下:
在 USBPD 的相关初始化操作里, 和 USB 相关的就是其调用 USBD_Start 函数,由于移除了
USB PD,所以我们需要添加 USBD_Start 函数, 如下图:
这时候, 编译下载程序,仍然能正确的操作 HID 类及演示 User Button 功能;
3.3 .实现 USB CDC 的枚举
即使目前使用的是 HID 类,但是不同 USB 类, 对应枚举的实现其实是一样的,所以,
第一步:将 usbd_hid.c 移除, 项目工程中加入\stm32_mw_usb_device-
master\Class\CDC\Src 中的 usbd_cdc.c,
并修改相应头文件名称和路径, 解决编译问题;
另外, 由于移除了 usbd_hid.c 文件,所以在应用层也需要并屏蔽掉 HID 相关的应用层操作; 主
要比如 HAL_GPIO_EXTI_Rising_Callback(),
然后编译,会遇到下面 3 个错误:
对于第一个错误 ,USBD_ClassTypeDef USBD_HID 修改为 USBD_ClassTypeDef
USBD_CDC ,用 USBD_CDC 替换对应的 USBD_HID 解决 USBD_HID 的未定义的问题;
对于第二个错误,修改 PMA ,因为 CDC 类和 HID 使用到 USB 端点资源的不同, 所以修改如
下:
对于第三个错误,将下面代码
替换如下即可:
解决好这些错误,我们再运行,会发现:
右击显示错误是:
其实我们清楚, 移植到这一步, 肯定还是有问题的,至少我们CDC 类的描述符还没有修改过
来。
第二步 :修改 usbd_desc.c 文件,对于这些标准的 USBD Class ,可以在我们之前 Classic USB
例程中寻找一个,在这里用上面提到的 U5 的示例;
……\stm32u5-classic-coremw-apps-main\Projects\NUCLEO-U575ZI-
Q\Applications\USB_Device\CDC_Standalone\USB_Device\App 直接替换掉之前 HID 的
usbd_desc.c 和对应头文件,
编译并出现:
解决方法就是将下图中的 HID_Desc 修改为对应的名称, 这儿用到的是 CDC_Desc;
此时再编译,发现设备管理器已经能够识别出端口了,
但是停下程序, 发现程序进入了 hardfault ;
程序显示在 init physical interface 时出现问题, 此时我们回过头,会发现我们并没有注册 USB
接口:
解决方法,将: C:\TEMP\stm32h5-classic-coremw-apps-
main\Middlewares\ST\STM32_USB_Device_Library\Class\CDC
usbd_cdc if template.c 和对应头文件添加入项目工程, 并添加注册接口 interface 的函数。
解决编译错误, 然后运行,就会发现 hardfault 问题解决了;
但是好事多磨 ,运行后,会发现能枚举成功,但是 USB CDC 的驱动安装不成功, 会出现黄色小
感叹号,
常规的, 我们解决这个感叹号的问题:首先 IAR 编译其对应的 MCU 的脚本文件 icf 文件中的 heap 改大些,保险一点 0x1000 (有些 USB 类如 Audio 可能需要更大),发现没有起作用。
经调试对比,在如下函数内添加如下代码,并解决编译问题后,即可正确安装驱动。
4.验证 USBD CDC 通信
简单的验证 64 个字节之内的发送与接收,修改函数如下:
测试如下 :
当然,这儿仅仅是一个简单的移植,验证 CDC 通信,对于实际的项目中的通信逻辑,发送包
长, 可以对照之前的 Classic USBD CDC 例程自行根据需要添加修改即可!