Wio Terminal 运行 RT-Thread 系统
Wio Terminal 是 Seeed Studio 设计的一款开发套件。它基于 SAMD51 的微控制器,运行速度为 120MHz(最高可达 200MHz),拥有 4MB 外部闪存和 192KB RAM,具有 Realtek RTL8720DN 支持的无线连接,同时支持蓝牙和 Wi-Fi 功能,是物联网项目的一个不错选择。并且它使用 Arduino IDE 就可以进行开发,新手也可以非常容易上手。
但是,基于 Arduino 的开发也有一些缺点,比如无法调试、无法使用多线程编程、不利于理解底层代码深入学习嵌入式开发、难以进行系统优化等等。于是,我在想能不能在 Wio Terminal 上运行 RT-Thread 操作系统?使用 RT-Thread 强大的软件生态进行开发呢?
说干就干!经过两个周末的折腾,我终于实现了将 RT-Thread 移植到 Wio Terminal 上。那么,本文就来介绍我是如何实现这个目标的。
背景知识
开始之前,我们先来了解一些相关概念,以便顺利完成本次实验。
SAM 系列芯片
Microchip ATSAM 系列芯片在各种工业、消费类和汽车领域有广泛应用。Arduino 开发板常用的芯片就是 Atmel 公司生产的 AVR 和 SAM 系列微控制器。而我们这里用到的 Wio Terminal,它的主控制器是 ATSAMD51P19A-U。
我们先来看看这个 SAM 芯片家族,下面是数据手册提供的说明。其中,ATSAMD51P19 就表示核心是 Cortex-M4F(不含 CAN 和 Ethernet 外设)、Flash 容量 512 KB,管脚共 120/128 个(具体和封装有关)。
Atmel START
Atmel START 是一款可对 SAM 和 AVR 微控制器项目进行直观的图形配置的在线工具,作用类似于 ST 的 STM32CubeMX 工具。由于 Atmel START 以 SaaS 形式提供服务,所以我觉得更加方便。
Atmel START 基于最新一代的高级软件框架 ASF4。使用 Atmel START,你可以选择和配置软件组件、驱动程序和中间件,以及专门根据你的应用程序需求定制的完整示例项目。
通过图形引脚复用和时钟配置,你可以轻松地将软件和驱动程序与你使用的硬件布局相匹配。配置阶段还会检查软件组件之间的依赖关系、冲突和硬件约束。如果发生冲突,Atmel START 会自动建议适合你特定设置的解决方案。
ASF4
ASF4 全称 Advanced Software Framework Version 4,它是 Microchip 提供的一套外设驱动程序、中间件和软件应用程序等软件组件的集合。该框架支持 Microchip 的 SAM 系列微控制器。
Microchip Studio
Atmel Studio 是 Atmel(现在是 Microchip) 公司推出的一款集成开发环境(IDE),专门用于嵌入式系统的开发。提供了丰富的工具和功能,以支持 Atmel 微控制器的编程、调试和部署。Atmel Studio 支持多种编译器,包括 GCC 和 IAR 编译器,可用于生成最优化的代码。支持多种编程语言,包括 C、C++ 和汇编语言。开发者可以根据自己的需求选择最合适的编程语言来编写他们的应用程序。
由于 Atmel 被 Microchip 收购了,所以 Atmel Studio 也更名为 Microchip Studio。它整合了 Atmel Studio 的功能,并扩展支持了更多 Microchip 微控制器系列,包括 PIC 系列等。
我们这里使用最新的 Microchip Studio 7.0,你可以在这里下载。
Atmel ICE Programmer
Atmel-ICE 是 Microchip 新推出的功能强大的调试编程工具,适用于 Atmel ARM Cortex-M 的 SAM 和 AVR 系列芯片。
Atmel-ICE 支持的软件:
- 支持 MIcrochip Studio 6.2 以上版本
- 支持 ICC8AVR 以上版本
- 支持烧录 ICCAVR、CVAVR、IAR 等生成的 HEX 文件
本次实验将使用 MIcrochip Studio + Atmel-ICE 来完成 RT-Thread 固件烧录。
搭建工程
下载源代码
我已经完成 RT-Thread 的移植了,你可以从我的 GitHub 分支拉取移植好的 rt-thread 工程,这样就能快速启动你的 Wio Terminal。
git clone -b microchip https://github.com/luhuadong/rt-thread.git
国内的小伙伴也可以从 Gitee 下载,这样会更快一点。
git clone -b microchip https://gitee.com/luhuadong/rt-thread.git
Wio Terminal 对应的 BSP 位于 bsp/microchip/samd51-seeed-wio-terminal
目录。
编译 BSP
目前仅提供在 Windows 下通过 Env 工具编译。使用 Env 工具打开 samd51-seeed-wio-terminal 目录,输入 scons
即可编译该 BSP 工程。
因为我已经事先配置好工程了,因此你不需要执行 menuconfig
配置即可编辑。当然,你也可以执行 menuconfig
命令对该 BSP 工程进行重新配置,添加你想要的组件或软件包。
创建工程
打开 Microchip Studio, 依次选择 File -> Open -> Open Object File For Debugging,打开工程配置窗口。
选择刚刚编译好的 rt-thread-samd51.elf 文件,设置项目名称,以及工程目录,如下图所示。
点击 Next,选择对应芯片型号 ATSAMD51P19A,如下图所示。
点击 Finish 完成 Microchip Studio 工程配置。
烧录调试
硬件改造
Wio Terminal 默认只提供了 USB 接口通过 Arduino IDE 开发,通过查阅 Wio Terminal 电路图,我们发现 PCB 上有预留 SWD 调试接口。
一种方式是以 Grove 接口提供,对应 Wio Terminal 正面左侧的 I2C Grove 接口。不过需要在 PCB 上 R33 和 R34 位置焊接 0Ω 电阻可以使用。
另一种方式是以测试 触点提供的接口,如下图左侧所示。
在实验过程中,我尝试通过电烙铁和热风枪的方式将两颗 0Ω 电阻焊接上去,因为使用的是 0402 尺寸电阻,所以对没有硬件经验的同学操作起来有一定难度。
首先,拆开 Wio Terminal 外壳。提示:Wio Terminal 的两颗螺丝隐藏在背面左上角和右下角的两个垫片下。
拆开后取出 PCB 板,找到 R33 和 R34 焊盘位置,将两颗 0Ω 电阻摆放好。
由于位置刁钻,建议使用热风枪调至 300 ℃ 左右慢慢将其焊接好。另一个方法是先把 Grove 座子焊下来,腾出空间用电烙铁将 0402 电阻焊上。提示:焊接完一定要检查是否虚焊。
如果你觉得 0402 电阻难度太大,也可以尝试直接用导线将测试触点引出来。需要注意的是,由于测试触点不是专用的焊盘,表面没有涂锡,因此操作的时候要特别小心,不要焊太久,否则很容易像我这样把铜片都焊掉了 (⊙﹏⊙)b
后来我找到了一种专用于烧录的“顶针夹具”,应该是最方便的了,不需要焊接,直接夹上就可以用了!不过,大家注意要选择 2.0mm 的,而不是 2.54mm 的。
连接 Atmel ICE
解决了硬件问题,接下来就可以连接 Atmel ICE 啦。这里用到的是 SWD(Serial Wire Debug)接口,需要连接四根线,SWDIO、SWCLK 以及 VCC 和 GND,分别是对应 2、4、1、3 端口。
连接好 Atmel ICE 之后,点击 Microchip Studio 菜单栏中的 Tools -> Device Programming,打开 Device Programming 窗口。
此时,你可以在 Interface settings 选项卡中,Tool 下拉框选择 Atmel-ICE 调试器,点击 Apply 按钮。如果连接正常,点击右侧的 Read 按钮,可以读取设备签名信息和电压值。
擦除 Bootloader
想要将 RT-Thread 固件写入 Wio Terminal,还有一个非常关键的地方 —— 擦除设备原先的 Bootloader 程序。
点击左侧 Fuses 选项卡,然后找到 NVM 控制寄存器 USER_WORD_0_NVMCTRL_BOOTPORT
配置项,可以看到当前设置为 16 KB。也就是说,Flash 的前 16 KB 被用于存放 Bootloader 程序了。
我们需要将其改为 0 KB,然后点击 Program 按钮保存修改。这样,Bootloader 占用的 Flash 空间就不再受保护。
接着,在 Memories 选项卡中,选择 Erash Chip,点击 Erase now,擦除整片 Flash。
等待擦除完毕,你就可以写入新的固件啦!
烧录程序
回到 Microchip Studio 主界面,在工具栏点击“小锤子”按钮,如下图 ① 所示。选择 Tool 选项卡,设置调试器为 Atmel-ICE,接口为 SWD,保存配置。
然后点击工具栏中“绿色小三角”按钮,如下图 ④ 所示,将固件 rt-thread-samd51.elf 下载到 Wio Terminal,并进入调试模式。
在实验过程中,我们发现第一次烧录可能会出现“Launch Failed”错误导致无法烧录成功。解决方法是拉下 Wio Terminal 左侧的 Reset 开关,然后松开,立即点击“小三角”按钮(或者 F5 键)。
如果失败了,多尝试几遍,并检查连线是否正常。多点耐心,一定会成功的。
运行测试
当固件烧录成功后,就会进入调试模式。你可以在工程代码中打上一些断点,检查 RT-Thread 程序是否正常运行。
在这个 BSP 中,我们配置了一个 LED 设备、一个 UART 串口设备,以及一个 USB CDC 设备。在 RT-Thread 程序中,我们启动一个线程用于循环控制 LED 灯亮灭。因此,当 main 函数运行起来后,你会看到 Wio Terminal 板载的蓝色 LED 灯开始闪烁。
该 BSP 默认配置 uart0 为 RT-Thread 的 Finsh 控制台,uart0 对应的引脚在 Wio Terminal 背面 40 pin 接口上,如下图所示。
使用 USB 转 TTL 串口模块连接该串口,打开任意一款串口终端工具,配置串口参数为 115200 N 8 1。当 RT-Thread 固件启动后,可以在终端上看到熟悉的打印,这意味着 RT-Thread 系统已经在 Wio Terminal 上跑起来了。
现在,你可以尝试输入 RT-Thread 内置的命令,查看系统信息。例如 ps
命令查看系统当前有多少个任务。
Atmel START 配置
首先,你需要使用 Atmel START 在线工具生成一套基于 ASF4 框架的工程示例代码。配置流程大致如下,首先创建一个特定芯片型号的工程,然后配置时钟、管脚、驱动、中间件等,最后根据配置生成并导出代码。
创建工程
使用浏览器打开 Atmel START 网页 https://start.atmel.com,点击“CREATE NEW PROJECT”创建一个新的工程。控制器选择 ATSAMD51P19A,封装选择 TFBGA120。
时钟配置
选择左侧的 CLOCKS 选项卡,开始配置时钟。这里以内部晶振作为时钟源为例,配置完成后如下图所示,最终生成 48MHz 的时钟给到 CPU。
具体来说,勾选时钟发生器 0 和 1,generator 1 选择 32kHz 内部晶振(OSCULP32K)作为时钟源,并作为 DFLL48M 数控频率锁定环的输入,然后 generator 0 选择 DFLL48M 作为时钟源,并输出到 CPU。
当然,Wio Terminal 本身是提供外部晶振的,可以配置更高的时钟频率,你可以自行探索。
串口配置
切换到 DASHBOARD 选项卡,点击 Add software component 添加串口驱动。搜索 stdio
关键字,添加 STDIO Redirect 组件。
此时会增加 STDIO_REDIRECT_0 和 TARGET_IO 两个模块,这里的 TARGET_IO 对应的就是 UART 外设。不过,由于 STDIO Redirect 依赖导致 TARGET_IO 无法设置为异步模式,所以这里需要把 STDIO_REDIRECT_0 组件删除,只留下 TARGET_IO 驱动,如下图所示。
现在,点击 TARGET_IO,开始配置串口。查阅 Wio Terminal 的电路图,可以找到有哪些串口供我们使用,这里以背面 40 pin 引脚中的 UART 串口为例,其对应关系如下:
- TXD - TXD0/GPIO14 - A13 - PB26/I12/SERCOM2.0+4.1/TCC1.3
- RXD - RXD0/GPIO15 - B12 - PB27/I13/SERCOM2.1+4.0/TCC1.3
因此,Driver 选择 HAL:Driver:USART_Async
,Mode 选择 UART
,Instance 选择 SERCOM2
。RX 引脚为 PB27
,TX 引脚为 PB26
。
另外,还可以修改串口参数,例如波特率为 115200、8 位数据位、1 位停止位、无奇偶校验位。
这样,串口就配置好了。
LED 配置
Wio Terminal 上有一个 USER LED,我们把它配置起来,后续在 RT-Thread 中实现点灯操作。查阅电路图,这颗 LED 的管脚对应关系为:
- USER_LED - PA15/I15/SERCOM2+4.3/TC3.1+TCC2.1+1.3
切换到 PINMUX 选项卡,在右边找到 PA15 管脚,添加 User label 信息为 LED0,Pin mode 为 Digital output 即可。
生成工程
配置完成后,将项目名称修改为“Wio-Terminal”。下图是我制作好的 BSP 对应的配置树,这里还配置了一个 USB CDC 设备,用于实现 USB 虚拟串口。不过本次实验暂时没有用到,所以这里就不展开了。
点击右上方的“EXPORT PROJECT”导出工程,勾选需要导出的 IDE 工程,然后点击“DOWNLOAD PACK”即可打包生成一个 Wio-Terminal.atzip 文件。
实际上,你现在就可以用 Microchip Studio 打开 Wio-Terminal.atzip 文件,编译并通过 Atmel-ICE 将固件下载到 Wio Terminal 中。不过,我们的目标是要在 Wio-Terminal 上面跑 RT-Thread 操作系统,所以还需要继续下去!
RT-Thread BSP 移植
好,下面开始移植 RT-Thread。受篇幅限制,这里只着重介绍一些关键点,具体可参照代码学习和分析。
搭建 BSP 工程
通常来说,将一个操作系统移植到一个新平台上,最简单快捷的方法就是找一个和目标平台最接近的 BSP 作为参考。好在 RT-Thread 的 bsp/microchip 目录里面有一些现场的 BSP。由于没有 SAMD51 系列的,因此我们选择了 SAME54 作为参考。
将 same54 文件夹拷贝一份,命名为 samd51-seeed-wio-terminal,并切换到该文件夹下,接下来我们将在这里进行修改。
首先,解压缩前面生成的 Wio-Terminal.atzip 文件(可以将其后缀修改 zip 再解压)。删除 samd51-seeed-wio-terminal/bsp 目录下除 SConscript 文件外的所有文件,并将解压出来的文件全部拷贝到该目录下,如下图所示。
修改 SConscript
接下来,修改 samd51-seeed-wio-terminal/bsp 目录下的 SConscript 文件。我们知道,RT-Thread 使用 scons 作为构建工具,SConscript 文件是 scons 构建系统的一部分,其作用是描述项目中每个目录的构建规则以及它们之间的依赖关系。
简单来说,就是要在这个 SConscript 文件里指定需要添加 Atmel START 生成的 Wio-Terminal 工程中的哪些 .c 和 .h 文件。例如:
src = Glob('hal/src/*.c')
src += Glob('hal/utils/src/*.c')
src += Glob('hpl/core/*.c')
src += Glob('hpl/gclk/*.c')
src += Glob('hpl/mclk/*.c')
src += Glob('hpl/osc32kctrl/*.c')
src += Glob('hpl/oscctrl/*.c')
src += Glob('hpl/pm/*.c')
src += Glob('hpl/port/*.c')
src += Glob('hpl/ramecc/*.c')
src += Glob('hpl/sercom/*.c')
src += [cwd + '/atmel_start.c']
src += [cwd + '/driver_init.c']
修改 rtconfig.py
接着,修改 samd51-seeed-wio-terminal 工程根目录下的 rtconfig.py 文件,它的作用是让该 BSP 更好地支持多种编译器,以及方便地调整编译参数。
这里需要修改 DEVICE_SERIES
和 DEVICE_TYPE
等参数,如下所示。
DEVICE_SERIES = 'SAMD51'
DEVICE_TYPE = '__SAMD51P19A__'
DEVICE_PART = 'samd51'
并将链接脚本修改为 bsp/samd51a/gcc/gcc/samd51p19a_flash.ld。
if PLATFORM == 'gcc':
# toolchains
...
LFLAGS = DEVICE + \
' -Wl,--gc-sections,-Map=rt-thread-' + \
DEVICE_PART + \
'.map,-cref,-u,Reset_Handler -T bsp/samd51a/gcc/gcc/samd51p19a_flash.ld'