- RTEMS 是一个开放源代码的实时操作系统,适用于嵌入式系统。而 FreeBSD 是一个功能强大且稳定的操作系统,广泛应用于各种网络和服务器环境,RTEMS-libbsd 是一个使 RTEMS 能够利用 FreeBSD 网络栈、文件系统和驱动程序的库。通过 RTEMS-libbsd,我们可以体验 FreeBSD-Style 的 RTOS
- 目前飞腾派已经提供了 RTEMS-libbsd 的支持,可以运行网络、PCIe、NVMe、XHCI(USB 3.0)、SDMMC 等一系列来自 FreeBSD 12.2 的驱动
Phytium-RTEMS-SDK: 本项目发布了 Phytium 系列 CPU 的 RTEMS 源代码,参考例程以及配置构建工具 (gitee.com)
# 系统环境准备
- 飞腾派(Phytium 开发板)
- 电源适配器
- 串口线和串口上位机
- MicroSD 卡
- XHCI PCIe 卡
- USB 3.x Hub, USB 2.x Hub
- 键盘、鼠标、U 盘
- NVMe 硬盘
- 网线
- 具体可以参考 examples/rtems-libbsd/README.md · Phytium嵌入式软件/Phytium-RTEMS-SDK - 码云 - 开源中国 (gitee.com)
# 软件环境
- RTEMS 最新版本 rtems: RTEMS is a real-time executive in use by embedded systems applications around the world and beyond (gitee.com)
- RTEMS LibBSD 最新版本rtems-libbsd: FreeBSD on RTEMS - Networking, USB, Filesystems, Media (gitee.com)
- RTEMS SDK Phytium-RTEMS-SDK: 本项目发布了 Phytium 系列 CPU 的 RTEMS 源代码,参考例程以及配置构建工具 (gitee.com)
- 通过 RTEMS SDK ,可以轻松地搭建 RTEMS 开发环境,制作 RTEMS 交叉编译工具,编译 RTEMS 镜像
# 具体方法
# 配置 RTEMS 开发环境 (Ubuntu/Debian x64)
- 本文介绍 Ubuntu 21.04 (x64)、WSL 1/2 Ubuntu/Debain 环境下,通过交叉编译构建 RTEMS 镜像的方法
## 1. 安装环境依赖
- 安装 GCC 编译链,注意 python3.6-dev 根据主机的上的 Python 版本定,如果是 python 3.11 就用 python3.11-dev
```
python --version
sudo apt-get update
sudo apt-get build-dep binutils gcc g++ gdb unzip git python3.8-dev
```
- apt-get build-dep 需要将 /etc/apt/sources.list 的 deb-src 打开
- 有些系统 python --version 没有效果,需要额外创建 python 软链接
```
sudo ln -s /usr/bin/python3 /usr/bin/python
```
## 2. 获取 SDK 源码
- 下载 Phytium RTEMS SDK 源码
```
git clone https://gitee.com/phytium_embedded/phytium-rtems-sdk.git ./phytium-rtems-sdk
```
- 源码构建 AARCH64 用的交叉编译工具,构建前会下载 gcc,gdb 等一系列源码包到 ./rtems/rtems-source-builder/rtems 目录下,可能会由于网络问题下载较慢,可以下载源码包 [toolchain_sources.tar.xz, 提取码:RTTL](https://pan.baidu.com/s/1V09uR2UAx3j_B0dc3Ht9tg),放置在 SDK 根目录下,运行 ./install.py 时将工具链解压到 ./rtems/rtems-source-builder/rtems 目录下,节省下载时间
- 运行 install.py,拉取 RTEMS,RTEMS LibBSD 和 RTEMS Source Builder 源码,需要的拉取的源码较多,可能需要等待一段时间
```
$ cd phytium-rtems-sdk
$ ./install.py
```
- 拉取完成后会显示
```
Success!!! Phytium RTEMS SDK is Install at /xxx/phytium-rtems-sdk
```
## 3. 构建交叉编译链
- 输入下面的命令开始构建编译链,整个过程可能需要较长的时间(通常会大于 1 小时,具体速度和编译主机的性能有关)
```
$ make aarch64_rtems_toolchain
```
> 注意 WSL1 中不要将 SDK 放到 /mnt/d 等 Windows 挂载盘目录下
- 编译成功后交叉工具链在 toolchain 目录下,后面构建的 BSP 静态库也会被安装在这个目录下
## 4. 构建目标平台 BSP
- 在交叉编译工具的基础上,进一步构建目标平台的 BSP,生成一系列静态库,后面应用程序会链接这些静态库
> 在 SDK 根目录下编译所有目标平台的 BSP,每个平台都会对应一组独立的静态库
```
$ make all
```
> 编译指定目标平台的 BSP
```
$ make e2000d_demo_aarch64_all
$ make phytium_pi_aarch64_all
$ make d2000_test_aarch64_all
$ make ft2004_dsk_aarch64_all
```
## 5. 构建应用程序镜像
- 完成目标平台 BSP 的构建后,最后编译应用代码,和 BSP 静态库进行链接,生成可以在开发板上运行的镜像文件
- 首先在 SDK 根目录下选择当前生效的 BSP,如选择 Phytium PI
```
$ source tools/env_phytium_pi_aarch64.sh
```
- 然后,选择应用程序进行编译,对于 RTEMS 内核应用
```
$ cd examples/rtems
$ make clean image
```
- 编译完成后,会生成 o-optimize 目录和一系列目标文件,其中
```
rtems.exe 应用程序镜像
rtems.asm 应用程序反汇编文件
rtems.map 应用程序镜像分析文件
```
- 对于 RTEMS LibBSD 应用
```
$ cd examples/rtems-libbsd
$ make clean image
```
- 编译完成后,会生成 o-optimize 目录和一系列目标文件,其中
```
rtems_libbsd.exe 应用程序镜像
rtems_libbsd.asm 应用程序反汇编文件
rtems_libbsd.map 应用程序镜像分析文件
```
- 默认用 make image 会将镜像拷贝到 /mnt/d/tftpboot 目录,可以在应用工程的 makefile 中修改 USR_BOOT_DIR 变量的值指定为其它目录
- 然后确保开发板可以访问主机的 tftp 服务,将镜像上传到开发板上
- 如果是加载 bin 文件,启动之前需要刷新一下 dcache
```
setenv ipaddr 192.168.4.20
setenv serverip 192.168.4.30
setenv gatewayip 192.168.4.1
tftpboot 0x80100000 rtems.bin;dcache flush; go 0x80100000;
```
- 如果是加载 elf 文件(RTEMS 编译输出中以 *.exe 结尾)
> 注意必须 RTEMS 镜像中有多个 section,只能用 bootelf -s 启动,不能用 bootelf -p
```
setenv ipaddr 192.168.4.20
setenv serverip 192.168.4.30
setenv gatewayip 192.168.4.1
tftpboot 0xd0100000 rtems.exe; bootelf -s 0xd0100000;
```
## 6. 使用 RTEMS 自带的镜像
- RTEMS 内核中也提供了大量的现成应用程序,在构建 BSP 的过程中会构建成镜像,用户可以通过下面的方法,方便地将这些镜像拷贝到 /mnt/d/tftpboot 目录下,然后加载启动
- 首先需要参考步骤 5 选择生效的 BSP,然后拷贝镜像
> 注意 source toos/env_xxx.sh 后只在当前 Shell 端生效,不要切换控制台 Shell
### 6.1 RTEMS 内核测试套件
- 对于 RTEMS 内核测试套件中的镜像
```
copy_image hello.exe testsuite
```
- 查看 RTEMS 内核测试套件中所有的镜像
```
list_images testsuite
```
### 6.2 RTEMS LibBSD 测试套件
- 对于 RTEMS LibBSD 测试套件中的镜像
```
copy_image media01.exe bsdtestsuite
```
- 查看 RTEMS LibBSD 测试套件中所有的镜像
```
list_images bsdtestsuite
```
### 6.3 RTEMS Examples 测试套件
- 查看 RTEMS Examples 中所有的镜像
```
list_images examples
```
- 对于 RTEMS Examples 中的镜像
```
copy_image both_hello.exe examples
```
## 7. 更新 SDK 版本
- RTEMS-SDK 中有多个组件是通过脚本拉取的,更新 SDK 版本前,需要先删除这些组件
```
$ ./uninstall.py
```
- 然后使用 `git fetch` 或者 `git pull` 更新分支
# RTEMS LibBSD 系统测试
## 1. 例程介绍
><font size="1">介绍例程的用途,使用场景,相关基本概念,描述用户可以使用例程完成哪些工作</font><br />
本例程示范了 RTEMS LibBSD 基本功能的使用:
- 此例程已在 E2000 D/Q Demo 板上完成测试
- 此例程已在 Phytium PI 上完成测试
- 此例程已在 FT2004 DSK 上完成测试
- 此例程已在 D2000 TEST 上完成测试
## 2. 如何使用例程
><font size="1">描述开发平台准备,使用例程配置,构建和下载镜像的过程</font><br />
本例程需要以下硬件,
- E2000D/Q Demo/ Phytium PI/ FT2004 DSK/ D2000 TEST板
- 串口线和串口上位机
- MicroSD 卡
- XHCI PCIe 卡
- USB 3.x Hub, USB 2.x Hub
- 键盘、鼠标、U 盘
- NVMe 硬盘
- 网线
### 2.1 硬件配置方法
><font size="1">哪些硬件平台是支持的,需要哪些外设,例程与开发板哪些IO口相关等(建议附录开发板照片,展示哪些IO口被引出)</font><br />
#### 2.1.1 E2000D/Q Demo
- 如图所示连接硬件
![E2000 D/Q Demo](./figs/e2000dq_demo.png)
- 其中,
- - 1. 通过 UART 1 串口连接控制台
- - 2. 通过 XMAC 0 连接网线对端
- - 3. 通过 PCIe 通道连接 NVMe 硬盘
- - 4. 通过 PCIe 通道连接 XHCI 扩展卡,连接 USB 2.x U 盘
- - 5. 通过 SD 0 连接 eMMC
- - 6. 通过 SD 1 连接 MicroSD 卡
- - 7. 通过 XHCI 0 (支持 3.x 速率) 连接 USB 3.x Hub,再连接 USB 3.x U 盘
- - 8. 通过 XHCI 1 (支持 2.x 速率) 连接 USB 2.x Hub, 再连接键盘鼠标
- 实际测试过程中,连接以上全部的外设或者只连接其中部分的外设都可以进行相应的测试
#### 2.1.2 Phytium PI
![Phytium PI](./figs/phytiumpi.png)
- 其中,
- - 1. 通过 UART 1 串口连接控制台
- - 2. 通过 XMAC 0 连接网线对端
- - 3. 通过 SD 0 连接 MicroSD 卡
- - 4. 通过 XHCI 0 (支持 3.x 速率) 连接 USB 3.x Hub,再连接 USB 3.x U 盘、键盘、鼠标
- 实际测试过程中,连接以上全部的外设或者只连接其中部分的外设都可以进行相应的测试
#### 2.1.3 FT2004 DSK
![FT2004 DSK](./figs/ft2004.png)
- 其中,
- - 1. 通过 UART 1 串口连接控制台
- - 2. 通过 GMAC 0 连接网线对端
- - 3. 通过 PCIe 通道连接 XHCI 扩展卡,连接 USB 2.x U 盘
- 实际测试过程中,连接以上全部的外设或者只连接其中部分的外设都可以进行相应的测试
#### 2.1.4 D2000 TEST
- 其中,
- - 1. 通过 UART 1 串口连接控制台
- - 2. 通过 GMAC 0 连接网线对端
- - 3. 通过 PCIe 通道连接 XHCI 扩展卡,连接 USB 2.x U 盘
- 实际测试过程中,连接以上全部的外设或者只连接其中部分的外设都可以进行相应的测试
### 2.2 SDK配置方法
><font size="1">依赖哪些驱动、库和第三方组件,如何完成配置(列出需要使能的关键配置项)</font><br />
#### 2.1.1 E2000D Demo
- 在 SDK 根目录编译 E2000D Demo 的 BSP 和 LibBSD
```
make e2000d_demo_aarch64_bsp
make e2000d_demo_aarch64_libbsd
```
#### 2.1.2 E2000Q Demo
- 在 SDK 根目录编译 E2000Q Demo 的 BSP 和 LibBSD
```
make e2000q_demo_aarch64_bsp
make e2000q_demo_aarch64_libbsd
```
#### 2.1.3 Phytium PI
- 在 SDK 根目录编译 Phytium PI 的 BSP 和 LibBSD
```
make phytium_pi_aarch64_bsp
make phytium_pi_aarch64_libbsd
```
#### 2.1.4 FT2004 DSK
- 在 SDK 根目录编译 FT2004 DSK 的 BSP 和 LibBSD
```
make ft2004_dsk_aarch64_bsp
make ft2004_dsk_aarch64_libbsd
```
#### 2.1.5 D2000 TEST
- 在 SDK 根目录编译 D2000 TEST 的 BSP 和 LibBSD
```
make d2000_test_aarch64_bsp
make d2000_test_aarch64_libbsd
```
### 2.3 构建和下载
><font size="1">描述构建、烧录下载镜像的过程,列出相关的命令</font><br />
- 选择目标平台的类型
> 对于 E2000D Demo,在 SDK 根目录下输入
```
source tools/env_e2000d_demo_aarch64.sh
```
> 对于 E2000Q Demo,在 SDK 根目录下输入
```
source tools/env_e2000q_demo_aarch64.sh
```
> 对于 Phytium PI,在 SDK 根目录下输入
```
source tools/env_phytium_pi_aarch64.sh
```
> 对于 FT2004 DSK,在 SDK 根目录下输入
```
source tools/env_ft2004_dsk_aarch64.sh
```
> 对于 D2000 TEST,在 SDK 根目录下输入
```
source tools/env_d2000_test_aarch64.sh
```
![选择目标平台 BSP](./figs/select_target_bsp.png)
- 随后在当前 Shell 终端下进入例程,编译镜像
> 注意 source tools 目录脚本选择目标平台只对当前 Shell 终端有效
```
cd examples/rtems-libbsd
make clean image
```
- 默认编译生成的镜像会放置在 /mnt/d/tftpboot 目录下,可以通过 makefile 中的 USR_BOOT_DIR 修改镜像放置的目录
- BSP 和 LibBSD 没有修改的情况下,如果只修改本例程的代码,只需要编译本例程即可
![构建镜像](./figs/build_apps.png)
- 通过 tftpboot 将编译生成的镜像上传到开发板上
- 如果是加载 elf 镜像 (编译输出的 *.exe 文件)
```
setenv ipaddr 192.168.4.20
setenv serverip 192.168.4.30
setenv gatewayip 192.168.4.1
tftpboot 0xd0100000 rtems.exe
bootelf -s 0xd0100000
```
![加载 ELF](./figs/load_exe.png)
![启动 ELF](./figs/bootelf.png)
- 如果是加载 bin 镜像
```
setenv ipaddr 192.168.4.20
setenv serverip 192.168.4.30
setenv gatewayip 192.168.4.1
tftpboot 0x80100000 rtems.bin
dcache flush
go 0x80100000
```
> 部分固件可能没有命令 `dcache flush`,可以先尝试不 flush dcache 启动,如果启动失败的话需要联系 FAE 更换支持命令 `dcache flush`的固件
### 2.4 输出与实验现象
><font size="1">描述输入输出情况,列出存在哪些输出,对应的输出是什么(建议附录相关现象图片)</font><br />
#### 2.4.1 E2000D/Q Demo
##### Micro SD
- 启动过程中应该可以看到 SD 1 控制器的初始化信息
![初始化 SD1](./figs/init_sd1.png)
- SD 1 卡槽如果连接了 MicroSD 卡应该可以看到识别到卡的信息,形成设备实例 /dev/mmcsd-1,如果 MicroSD 卡上存在 FAT32 文件系统,可以看到 media listener 自动挂载文件系统到 /media/mmcsd-1 目录的过程
![识别 MicroSD 卡](./figs/detect_microsd.png)
##### eMMC
- 启动过程中应该可以看到 SD 0 控制器的初始化信息
![初始化 SD0](./figs/init_sd0.png)
- SD 0 板载连接的 eMMC 应该也可以识别,形成设备实例 /dev/mmcsd-0,如果 eMMC 上存在 FAT32 文件系统,可以看到 media listener 自动挂载文件系统到 /media/mmcsd-0 目录的过程
![识别 eMMC 卡](./figs/detect_emmc.png)
##### XMAC
- 启动过程中应该可以看到 XMAC 0 控制器和 PHY 的初始化信息
![初始化 XMAC0](./figs/init_xmac0.png)
- 随后一段时间,可以看到链路配置的信息,以及 23 号端口上启动 Telnet 服务的提示
![配置 IP 和服务](./figs/config_ip.png)
- 之后可以在串口终端查看网口的配置,默认地,开发板 ip 是 192.168.4.20,对端的 ip 是 192.168.4.30,相关的默认配置可以通过 configs/netconf 中对应平台的配置文件修改,也可以通过 ifconfig 命令手动修改
![IP 配置](./figs/ifconfig.png)
- 首先可以尝试从开发板侧 ping 对端主机
```
ping -c 20 192.168.4.30
```
![Ping PC](./figs/ping_pc.png)
- 然后可以从对端主机 ping 开发板
```
ping 192.168.4.20
```
![Ping 开发板](./figs/ping_board.png)
- 确认开发板和对端主机联通后,可以通过 23 号端口 telnet 登录开发板,进入 TLNT 控制台
```
telnet 192.168.4.20 23
```
![Telnent 连接](./figs/telnet.png)
![Telnent 连接信息](./figs/telnent_session.png)
- 可以通过 ifconfig 手动修改 IP 地址,
```
ifconfig cgem0 192.168.4.10 netmask 255.255.255.0 up
```
![重新配置 ip](./figs/recofig_ip.png)
##### XHCI (平台)
- 启动后应该可以看到 XHCI 0 和 XHCI 1 控制器的初始化信息
![初始化 XHCI](./figs/init_xhci.png)
- 随后可以看到 XHCI roothub 的初始化
![初始化 XHCI Roohub](./figs/init_xhci_rh.png)
- 之后开始枚举 USB 设备,首先依次是外扩的 USB Hub,以及上来连接的键盘鼠标和U盘,可以看到 /dev/ukbd0 是键盘,/dev/ums0 是鼠标,/dev/umass-sim-0 是 U 盘
![枚举 USB 设备](./figs/usb_devices.png)
![各类 USB 设备](./figs/all_devices.png)
- 如果 U 盘上有 FAT32 文件系统,会自动挂载到 /dev/umass-sim-0 目录下
![U 盘挂载](./figs/usbdisk.png)
- 随后可以用连接的 USB 键盘进行输入
![USB 键盘](./figs/usbkeyboard.png)
- 通过 USB 鼠标进行输入
![USB 鼠标](./figs/usbmouse.png)
##### XHCI(PCIe)
- 启动过程中可以看到 PCI XHCI 控制器初始化
##### NVMe (PCIe)
- 启动过程中可以看到 NVMe 盘的识别,对应设备 /dev/nvd0
![初始化 NVMe](./figs/init_nvme.png)
- 如果 NVMe 盘存在 FAT32 文件系统,可以看到自动挂载到 /media/nvd0 目录的信息
![挂载 NVMe](./figs/mount_nvme.png)
- 通过 df 命令可以查看各个块设备的容量的使用情况
```
df -h
```
![查看各个块设备的容量](./figs/df.png)
- 退出 RTEMS 系统可以通过 reset 命令完成,重启后回到 Uboot 界面
```
reset
```
#### 2.4.2 PhytiumPI
##### Micro SD
- Phytium PI 中 Micro SD 连接在 SD 0 控制器上,默认会放置固件,可以在固件后面,偏移量大于 64MB 的位置预留分区制作一个 FAT32 文件系统给 RTEMS 使用
- 启动后可以看到 SD 0 控制器和 Micro SD 卡的识别信息
![SD](./figs/phytiumpi_sd.png)
![SD](./figs/phytiumpi_sd2.png)
- 由于 FAT32 文件系统是在分区中,对应的块设备会识别为 /dev/mmcsd-0-0,自动挂载目录为 /media/mmcsd-0-0
![DF](./figs/phytiumpi_df.png)
##### XMAC
- Phytium PI 的两个网口,XMAC 0 和 XMAC 1 都引出可以使用,初始化时可以看到对应信息
![XMAC 初始化](./figs/phytiumpi_init_xmac.png)
- 两个网口对应 cgem0 和 cgem1 设备实例
![XMAC 配置](./figs/phytiumpi_ifconfig.png)
##### XHCI (平台)
- Phytium PI 只引出了 XHCI 0,在板子正面靠近网口的插槽,可以通过 Hub 同时使用键盘、鼠标和 U 盘,具体的使用方法和 E2000 D/Q Demo 中的介绍一致
![XHCI](./figs/phytiumpi_xhci.png)
#### 2.4.3 FT2004 DSK
##### XHCI(PCIe)
- 启动过程中可以看到 PCI XHCI 控制器初始化
![pcie_xhci](./figs/ft2004_pcie_xhci.png)
#### 2.4.4 D2000 TEST
##### XHCI(PCIe)
- 启动过程中可以看到 PCI XHCI 控制器初始化
![pcie_xhci](./figs/d2000_pcie_xhci.png)
## 3. 如何解决问题
><font size="1">主要记录使用例程中可能会遇到的问题,给出相应的解决方案</font><br />
## 4. 修改历史记录
><font size="1">记录例程的重大修改记录,标明修改发生的版本号 </font><br />