本帖最后由 wangqy_ic 于 2022-2-15 13:13 编辑
#申请原创#
@21小跑堂
Zephyr-RTOS 简介
Zephyr Project 是托管于 Linux 基金会的一个嵌入式相关项目。主要的目标是提供一个供小型嵌入式系统使用的实时操作系统系统(Zephyr-RTOS),以及相关的工具软件(west 等)。
官网:https://www.zephyrproject.org/
官方介绍:
The Zephyr OS is based on a small-footprint kernel designed for use on resource-constrained and embedded systems: from simple embedded environmental sensors and LED wearables to sophisticated embedded controllers, smart watches, and IoT wireless applications.
Zephyr-RTOS 的开发,类似 Linux 系统/应用程序的开发,包括 KConfig ,Devicetree 等工具。
Zephyr-RTOS 的特性有:- 多种内核服务:多任务,动态内存管理,线程同步,电源管理等
- 多种调度算法:协作式和抢占式调度,时间片,最早截止日期优先等
- 高度可配置
- 支持多种处理器架构:ARM,ARM64,RISC-V,Xtensa,X86……
- 内存保护
- 编译期间定义资源(这个不好翻译,作用是可以有效缩小固件尺寸)
- 设备驱动模型
- 支持 Devicetree
- 原生的网络协议栈,支持多种网络协议
- BLE 5.0
- 原生支持 Linux, macOS, Windows 开发
- VFS 支持(LittleFS 和 FATFS)
- 强大的日志系统
- 功能完善的 Shell
- NVS 支持
- 兼容 POSIX
这么多的特性,全用上的话,固件尺寸当然也不会太小……
缘起
据我了解,这个操作系统目前在国内使用也不是很广泛,相对于 FreeRTOS,RT-Thread 等更是知者甚少。
我大概是在 2018 年接触到这个系统,对于它非常接近 Linux 系统的开发方式,觉得非常有意思,就一直保持着兴趣。
2021 年起,我逐渐在工作中引入了这个系统,并且成功使用在 STM32 的系统上运行一直非常稳定。灵活的配置方式,也非常便于切换到新的硬件系统。
去年底,因为项目需要我们打算切入国产 MCU。经过评估,我们选择了国民技术的 MCU。对于国内的 MCU,Zephyr 目前官方支持的只有兆易创新(gigadevice)和乐鑫科技(espressif)的一部分热门 MCU。看到 21IC 和国民技术在搞活动,也也就有了这个移植项目。
国民技术简介
官网:https://www.nationstech.com/
官方介绍
国民技术股份有限公司于2000年源于国家“909”集成电路专项工程成立,2010年创业板上市(股票代码:300077),是中国安全芯片、通用MCU领军企业,国家级**技术企业,拥有国内首个企业独立安全芯片攻防技术实验室,博士后科研工作站。总部位于深圳,在北京、上海、武汉、西安、香港、新加坡等地设有分支机构。主营产品包括:安全芯片、通用MCU、可信计算芯片、智能卡芯片、非接读写芯片、蓝牙芯片、RCC创新产品等,广泛应用于网络安全认证、电子银行、电子证照、移动支付与移动安全、物联网、工业联网及工业控制、智能家电及智能家庭物联网终端、消费电子、电机驱动、电池及能源管理、智能表计、医疗电子、汽车电子、安防、生物识别、通讯、传感器、机器自动化等应用方向。
移植目标
我在活动中申请拿到的开发板是 N32G45XVL-STB,MCU 是 N32G457VEL7,所以移植的目标是 N32G4567 系列。
移植过程介绍
准备工作
开发 Zephyr-RTOS 至少需要:CMake,Ninja,Python,Git以及编译套件(我使用的是 GNU ARMEmbedded)。具体安装方法,可以参考官方的说明:https://docs.zephyrproject.org/latest/getting_started/index.html,也可以参考我自己整理的简要说明:https://www.yuque.com/quincy/zephyr/gyq03s。
确保开发环境正常,就可以正式的移植工作。
一些说明
在我看来,Zephyr-RTOS 的灵活性有一个重要的体现 Out-of-tree-development:在 Zephyr-RTOS 主干代码外进行开发。大白话就是移植和开发的工作完全独立于Zephyr-RTOS 的官方代码,不会影响和干扰官方代码。
我的移植工作就是基于这种特性,而不需要在 Zephyr-RTOS 的代码中开新的分支,也不会存在代码合并等一系列麻烦事。
代码目录介绍
代码已经在 Gitee 上的仓库:https://gitee.com/quincyzh/zephyr-rtos-for-n32-mcu欢迎点赞。另外有个彩蛋,我实际使用的是 N32WB031 系列芯片,所以代码仓库也包含 N32WB031 系列芯片的移植。这个是不是可以奖励双倍 @21小跑堂 2本文只是介绍 N32G4567 的移植。
代码目录结构:
- boards :开发板代码
- CMakeLists.txt :CMake 配置文件
- drivers :适配 Zephyr 驱动代码
- dts :Devicetree 支持
- hal_library :国民技术提供的代码库
- include :头文件目录
- Kconfig :KConfig 配置文件
- modules :Zephyr 构建配置
- README.md :README 文件
- soc :N32 SOC 移植代码
- zephyr :Zephyr 构建配置
移植说明
主要步骤:
- 创建代码目录
- SOC 相关代码
- 驱动相关代码
- 开发板相关代码
- 测试
1. 创建代码目录
按 “代码目录介绍” 一节介绍,建立目录及相关文件。各个文件的目录,后续会说明。
2. SOC 相关代码
SOc 目录的详细结构如下:
- ├─soc
- │ └─arm
- │ └─nationstech_n32
- │ ├─common
- │ ├─n32g4
- │ └─n32wb03
这个目录结构是按 Zephyr 要求建立,不能随意调整,否则不能编译。
soc/arm/nationstech_n32/n32g4目录及其内容就是对应 N32G4567 这个 MCU,内容有:
- CMakeLists.txt
- Kconfig.defconfig.n32g457x
- Kconfig.defconfig.series
- Kconfig.series
- Kconfig.soc
- linker.ld
- soc.c
- soc.h
Kconfig 一系列文件,是 KConfig 配置文件,目的是向 KConfig 系统提供与 N32G4567 相关的配置项目.
CMakeLists.txt 是 CMake 配置文件,决定那些文件参与构建.
linker.ld 是链接说明,这个文件是从 Zephyr 代码库复制而来,基本上每个架构的 MCU 都差不多。
soc.c soc.h 是 MCU 最基本的初始化代码,这里主要是初始化基本的时钟系统。soc.c 的主要代码:
- static intn32g0_init(const struct device *arg)
- {
- uint32_t key;
- ARG_UNUSED(arg);
- key = irq_lock();
- SystemInit();
- NMI_INIT();
- irq_unlock(key);
- SystemCoreClockUpdate();
- return 0;
- }
这个目录内容正确的话,会在配置期间看到以下两个的效果。
一是在 Soc/CPU/Configuration Selection 目录下可以看到 N32G4 Series MCU:
二是在 Hardware Configuration → N32G4 MCU Selection 目录下可以看到类似内容:
需要注意的是:这些选项默认是隐藏的,要按键盘 "A" 才会显示。
file:///C:/Users/Zoro/AppData/Local/Temp/msohtmlclip1/01/clip_image003.png
其他的驱动适配,结构基本相当,不再赘述。具体可参见代码仓库:https://gitee.com/quincyzh/zephyr-rtos-for-n32-mcu。需要注意的点是,每种驱动的 api 结构定义是不一样的,可参考 Zephyr 的 driver 文件在的各种平台的实现。
3. 驱动相关代码
目前已经实现驱动 clock_ctrl, pinmux, GPIO, Uart 这四个驱动。这里已 clock_ctrl 为例,说明移植的步骤。
创建文件夹 drivers\clock_control,创建3个文件:
- drivers\clock_control\clock_control_n32.c
- drivers\clock_control\CMakeLists.txt
- drivers\clock_control\Kconfig
- drivers\CMakeLists.txt
drivers\clock_control\clock_control_n32.c 文件是适配 Zephyr 系统的驱动框架,主要代码:
- static const struct clock_control_driver_api n32_cc_api = {
- .on = n32_cc_on,
- .off = n32_cc_off,
- .get_rate = n32_cc_get_subsys_rate,
- };
- static int n32_cc_init(const struct device *dev)
- {
- return 0;
- }
- DEVICE_DT_DEFINE(DT_NODELABEL(rcc),
- &n32_cc_init,
- NULL,
- NULL, NULL,
- PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
- &n32_cc_api);
- n32_cc_api 这个结构体是填充相关的操作 api 函数指针;
- n32_cc_init 函数是时钟初始化
- DEVICE_DT_DEFINE 这个宏,是向系统注册 clock_ctrl 设备。
系统启动期间,这些内容是这样使用的:
1. 依据优先级,DEVICE_DT_DEFINE 宏里的 PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY。
2. 调用设备注册的初始化函数,也就是 n32_cc_init。
3. 使用相关 API 时,就会调用 n32_cc_api 结构体的那些函数(指针)。例如 获取某个子系统的时钟频率就是这样调用:clock_control_get_rate(cc_dev, subsys, &rate); 这个函数最终会调用 n32_cc_get_subsys_rate。
drivers\clock_control\CMakeLists.txt 文件是 CMake 配置文件,决定构建内容:
- zephyr_library_amend()
- zephyr_library_sources_ifdef(CONFIG_CLOCK_CTRL_N32 clock_control_n32.c)
zephyr_library_amend 函数会把这个目录下的代码,链接至驱动相关代码块。
drivers\clock_control\Kconfig 是KConfig 配置文件。
- menuconfig CLOCK_CTRL_N32
- bool "CLOCK_CTRL Driver for N32 family of MCUs"
- depends on SOC_FAMILY_N32
- select USE_NS_STD_LIB_RCC
- help
- Enable CLOCK_CTRL driver for N32 MCUs
这个会增加一个配置目录,让用户选择是否启用该配置。实际的效果是在配置界面中 Modules → Nationstech N32 Porting 目录下,看到如下,空格键切换是否启用:
其他的驱动适配,结构基本相当,不再赘述。具体可参见代码仓库:https://gitee.com/quincyzh/zephyr-rtos-for-n32-mcu 。需要注意的点是,每种驱动的 api 结构定义是不一样的,可参考 Zephyr 的 driver 文件在的各种平台的实现。
4. 开发板相关代码
boards\arm\n32g45xvl_stb目录就是 N32G45XVL-STB这个开发板的配置说明:
- board.cmake
- Kconfig.board
- Kconfig.defconfig
- n32g45xvl_stb.dts
- n32g45xvl_stb.yaml
- n32g45xvl_stb_defconfig
boards\arm\n32g45xvl_stb\board.cmake文件配置
Kconfig 系列文件是增加板级 KConfig 配置选项。选项可以在配置界面 BoardSelection 目录下看到。
boards\arm\n32g45xvl_stb\n32g45xvl_stb.dts文件是设备树(Devicetree)描述文件:
|