NXP i.MX RT1060移植TinyUSB:快速扩展大量USB Class示例

描述

前言

 

为啥是TinyUSB?给强大的RT配个轻巧的USB栈!

USB这个让我们方便快捷的接口,几乎无处不在。在嵌入式世界里,尤其是用上了像NXP i.MX RT这样性能强劲的跨界MCU,我们自然希望它能轻松驾驭USB通信。官方所提供的示例只涵盖了USB基础类,对于诸如ECM、NCM等特定类的开发而言,若要从头开始构建,有可能会拖延客户项目的推进。

 

 

这时候,TinyUSB闪亮登场!

 

 

想象一下,一个开源(MIT 协议)、轻量级、跨平台、示例友好的USB协议栈,是不是有点小激动?

 

 

选择TinyUSB的几大优势:

 

  • 轻巧高效:资源占用小,对内存和 Flash 都很友好。对于性能本就充裕的RT系列,更是能跑得飞起

  • 功能全面:支持常见的设备类(CDC, MSC, HID, MIDI, Vendor等)和主机功能,甚至复杂的复合设备也不在话下。你想让你的RT板子变成U盘、虚拟串口、键盘鼠标?TinyUSB都能帮你搞定

  • 易于移植:清晰的架构设计和OSAL,无论是裸机还是RTOS环境,移植起来都相对顺畅

  • 社区活跃 & 开源免费:MIT协议方便客户使用。同时提供了大量的例程,即使是初学者也可以通过这个项目入门USB开发

所以,如果你想在你的NXP RT项目加上USB功能,或者学习一些特定class的开发,TinyUSB是一个值得尝试的选择。本文就将手把手带你,在熟悉的MCUXpresso IDE环境下,完成TinyUSB的移植,让你的RT开发板通过USB与世界自由沟通!

一、准备事项:装备检查

 

动手之前,确保你的“武器库”齐全:

 

 

  • 硬件平台:一块NXPi.MX RT开发板,本文以RT1060-EVK为例,和能把它“安排”明白的调试器(JLink或LinkServer都行)。

     

  • 软件工具

     

  • MCUXpresso IDE: NXP 的官方 IDE,我们的主战场(版本越新越好)

  • Git: 版本控制神器,管理代码和子模块的必备佳品

  • Make: 构建工具,跑 TinyUSB 自带脚本会用到

  • Python: 同样是跑脚本用

开辟工作目录并获取TinyUSB源码。创建项目文件夹,然后用 Git 初始化,拉取TinyUSB库。

mkdir //TinyUSB_Porting
 cd  /c/TinyUSB_Porting
 git init

 

 

把TinyUSB官方仓库加进来,用子模块的方式,既能保持项目整洁,又能方便地到最新版。

 

 

git submodule add  https://github.com/hathach/tinyusb.git tinyusb

 

 

搞定!Tinyusb文件夹里现在就是协议栈的源码和各种示例了。

恩智浦

 

二、小试牛刀:命令行下的“热身运动

 

在直接跳进IDE的“大坑”之前,咱们先在命令行下跑个官方示例,确保TinyUSB和 NXP的底层驱动能跑通,能避免很多不必要的麻烦。

 

 

步骤1: 选个入门示例开动

 

TinyUSB 的examples/device 目录下有很多好玩的示例。我们就选 cdc_msc 这个经典的“二合一”设备(虚拟串口 + U盘)开刀。

 

 

cd  tinyusb/examples/device/cdc_msc

 

 

步骤2:TinyUSB获取NXP的依赖项

TinyUSB支持很多芯片和开发板,对于NXP RT,它提供了脚本来自动下载 MCUXpresso SDK的相关驱动。

 

 

# 告诉 Make 我们用的是 RT1060EVK 板子
 make BOARD=mimxrt1060_evk get-deps

 

 

这条命令会运行 tinyusb/tools/get_deps.py imxrt 脚本,把NXP RT系列需要的驱动文件从GitHub上扒下来,放到 inyusbhwmcu xpmcux-sdk目录。

!!友情提示:NXP 的 Kinetis、LPC、MCX等系列需要用不同的参数去拉取各自的依赖包,别搞混了,对于同一个系列的MCU,只需要拉取一次就可以了。

 

 

步骤3: 编译!看看会不会“炸”

 

 

是时候检验成果了。用Make命令编译这个示例:

 

 

# 参数解释:
 #  BOARD=mimxrt1060_evk     - 目标板
 #  DEBUG=1                  - 打开调试信息,方便看日志
 #  LOG=2                    - 日志输出级别
 #  LOGGER=rtt            - 默认使用UART打印日志,也指定用 RTT 或者SWO
 #  PORT=1                - 多个USB Controller时可选
 #  SPEED=full               - USB 全速模式 (也可以试试 high 高速)
 make BOARD=mimxrt1060_evk DEBUG=1 LOG=2 LOGGER=rtt PORT=1 SPEED=full all

 

 

如果终端没有喷出一堆错误,并且在 _build/mimxrt1060_evk目录下看到了 .elf, .bin这些熟悉的身影,那么恭喜你,第一阶段胜利!

 

恩智浦

步骤4: 下载!是骡子是马拉出来遛遛

 

 

把编译好的固件烧录到你的RT板子上,插上USB线(连接到板子的 USB Device 端口)。如果你的电脑成功识别出一个U盘,那就稳了!这证明TinyUSB和NXP底层驱动这对“CP”在你这块板子上是能正常工作的。

 

 

三、主战场:MCUXpresso IDE集成

 

热身完毕,该进入主战场——MCUXpresso IDE了。我们要把TinyUSB“塞”进一个标准的IDE工程里。

 

 

步骤1: 建立“根据地” (创建基础工程)

 

在 IDE 里,为你的 RT MCU创建一个新的工程。你可以从 hello_world 这种简单的 SDK 示例开始,或者干脆创建一个只包含必要驱动的空工程。确保这个基础工程能独立编译、下载、运行。

 

 

步骤2: 给 TinyUSB 安个“家” (添加源码文件夹)

 

为了不让项目结构乱成一锅粥,我们在 IDE 里给 TinyUSB 单独创建一个“家”(源文件夹)。

 

1.右键项目-> New -> Source Folder。

 

2.取个名字,比如tinyusb。

 

 

步骤3: 搬运 TinyUSB 的“家当” (复制核心文件)

 

把之前 Git 下载的 tinyusb/src目录下的核心文件复制到刚创建的 tinyusb 文件夹里。注意只选择需要的device端代码即可。主要包括:

 

  • src/common: 通用工具函数

  • src/device: USB 设备协议栈核心代码

  • src/class: 你需要用到的 USB 功能类驱动(比如cdc, msc)

  • src/osal: 操作系统抽象层

  • src/portable/nxp/chipidea/ci_hs和nxp/ehci: NXP RT 芯片上USB 控制器的底层驱动

  • src/tusb.c, src/tusb.h:TinyUSB 的主入口和核心头文件

  • src/tusb_option.h: 默认编译选项

    恩智浦

步骤4: 把“说明书”和“应用代码”也拿过来 (复制配置和示例文件)

cdc_msc 示例能跑起来,还需要几个关键的配置文件和应用层代码。把它们从 examples/device/cdc_msc/src/ 复制到 IDE 项目的主源码目录(通常叫source 或src):

 

 

  • main.c: 示例的主函数(替换掉hello_world.c)

  • msc_disk.c / .h: U盘功能的底层存储接口(你需要实现它来读写你的存储器)

  • tusb_config.h: TinyUSB的配置文件。所有功能的开关、参数都在这里调

  • usb_descriptors.c / .h:USB设备的“身份证”——各种描述符。电脑就是靠这些信息来认识设备
步骤5: 板级支持包 (BSP) 文件别落下

 

示例代码会调用TinyUSB重写的板级初始化函数。检查下 examples/device/cdc_msc/src/ 和 hw/bsp 目录下类似 board_api.h family.c 这样的文件,有的话也一并复制到你项目的board 或bsp目录。

 

 

步骤6: 给编译器“指路” (配置 IncludePaths)

 

现在文件都搬过来了,但编译器还不知道去哪找头文件。我们需要在 IDE 里配置包含路径:

 

 

  • 右键项目-> Properties -> C/C++ Build -> Settings -> Tool Settings -> MCUC Compiler -> Includes

     

  • 点击"Add...",把下面这些路径加进去(根据实际项目结构可能需要微调)

     

恩智浦

步骤7: 配置 PreprocessorDefines

 

TinyUSB 用宏定义来识别目标平台和开关功能。我们需要告诉它现在是在为谁工作:

 

 

  • 右键项目-> Properties -> C/C++ Build -> Settings -> Tool Settings -> MCUC Compiler -> Preprocessor。

     

     

  • 点击"Add...",添加以下宏定义:

     

  • CFG_TUSB_MCU=OPT_MCU_MIMXRT1XXX: 关键!这就是告诉 TinyUSB:“现在需要跑在 NXP RT 芯片上!”

  • 按需添加其他调试宏,比如 CFG_TUSB_DEBUG=2

恩智浦

步骤8: 配置“硬件接口” (Pin Mux 和 Clock)

 

 

别忘了硬件!它们负责开发板上的各种PINMUX,直接使用TinyUSB中:tinyusbhwspimxrtoardsmimxrt1060_evk下提供的配置替换即可!

 

恩智浦

步骤9: 扫清“障碍” (处理冲突与缺失)

 

集成路上总会有些小坎坷:

 

  • SDK 组件缺失: 从hello_world工程开始移植TinyUSB可能会缺少相关组件,比如OCOTP,可以通过MCUXpressoIDE中的管理工具很方便的添加它们。

     

  • family.c和board_api.h的“戏份”: 这些文件通常负责板级的初始化(比如 board_init())。确保它们已经正确移植好!

     

     

4. TinyUSB配置文件和Class文件

 

  • tusb_config.h (协议栈的“控制面板”):

     

     

  • 这个文件用于TinyUSB的基础配置。虽然有些配置(如MCU类型 CFG_TUSB_MCU)可能通过编译器 -D参数传入,但大部分基础和类相关的配置都在这里完成。

     

  • usb_descriptors.c / .h (设备的“身份证”和“说明书”):

     

  • 这里定义了所有USB 描述符:设备描述符、配置描述符、接口描述符、端点描述符、字符串描述符等等。

     

  • class文件夹:参考cdc/msc,其他类型的示例移植方法也是类似的。

     

     

五、胜利收官:总结展望

 

恭喜!如果你一路跟着走到这里,并且成功让你的NXP RT开发板在电脑上被识别为一个 USB disk 设备,那么你已经掌握了在MCUXpresso IDE环境下移植TinyUSB 的核心技巧。

 

 

恩智浦

恩智浦

现在,RTMCU已经插上了TinyUSB的“翅膀”,可以更自由地翱翔在USB的世界里了。以此为起点,我们可以探索TinyUSB 支持的其他USB Class (HID, MIDI, 网卡等)、将TinyUSB集成到你的实际项目中,实现更复杂的USB功能或者host端协议栈!这些就留给感兴趣的小伙伴来尝试了!

[参考链接]:

  1. https://github.com/hathach‍/tinyusb

  2. https://docs.tinyusb.org/en/stable/r‍eference/getting_started.html

作者:Gavin Jia  

恩智浦MCU加油站

恩智浦半导体NXP Semiconductors N.V.(纳斯达克股票代码:NXPI)是汽车、工业物联网、移动设备和通信基础设施市场值得信赖的合作伙伴,致力于提供创新解决方案。

 

 


打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分