文章目录
Zephyr 简介
Zephyr OS 基于专为资源受限和嵌入式系统设计的小型内核:从简单的嵌入式环境传感器和 LED可穿戴设备到复杂的嵌入式控制器、智能手表和物联网无线应用。
Zephyr 内核支持多种架构,包括:
- ARCv2(EM 和 HS)和 ARCv3(HS6X)
- ARMv6-M、ARMv7-M 和 ARMv8-M (Cortex-M)
- ARMv7-A 和 ARMv8-A(Cortex-A,32 位和 64 位)
- ARMv7-R、ARMv8-R(Cortex-R,32 位和 64 位)
- 英特尔 x86(32 位和 64 位)
- MIPS(MIPS32 第 1 版规范)
- NIOS II 第 2 代
- RISC-V(32 位和 64 位)
- SPARC V8
- Tensilica Xtensa®
内核服务套件
Zephyr 提供了许多熟悉的开发服务:
- 用于协作、基于优先级、非抢占和抢占线程的多线程服务,具有可选的循环时间片。包括 POSIX pthreads 兼容的 API 支持。
- 用于中断处理程序的编译时注册的中断服务。
- 用于动态分配和释放固定大小或可变大小内存块的内存分配服务。
- 二进制信号量、计数信号量和互斥信号量的线程间同步服务。
- 用于基本消息队列、增强消息队列和字节流的线程间数据传递服务。
- 电源管理服务,例如 tickless idle 和高级空闲基础设施。
多种调度算法
Zephyr 提供了一套全面的线程调度选择:
- 协作和抢占式调度
- 最早截止日期优先 (EDF)
- 实现“中断下半部”或“tasklet”行为的元 IRQ 调度
- 时间片:在具有相同优先级的可抢占线程之间启用时间片
- 多种排队策略:
- 简单的链表就绪队列
- 红/黑树就绪队列-
- 传统多队列就绪队列
高度可配置以实现灵活性
允许应用程序只包含它需要的功能,并指定它们的数量和大小。
跨架构
支持具有不同 CPU 架构和开发人员工具的各种受支持的板。贡献增加了对越来越多的 SoC、平台和驱动程序的支持。
内存保护
在 x86、ARC 和 ARM 架构、用户空间和内存域上实现可配置的特定于架构的堆栈溢出保护、内核对象和设备驱动程序权限跟踪以及线程隔离和线程级内存保护。
对于没有 MMU/MPU 和内存受限设备的平台,支持将特定于应用程序的代码与自定义内核相结合,以创建在系统硬件上加载和执行的整体映像。应用程序代码和内核代码都在一个共享地址空间中执行。
编译时资源定义
允许在编译时定义系统资源,从而减少代码大小并提高资源受限系统的性能。
优化的设备驱动程序模型
为配置作为平台/系统一部分的驱动程序提供一致的设备模型,并为初始化配置到系统中的所有驱动程序提供一致的模型,并允许跨具有通用设备/IP 块的平台重用驱动程序
设备树支持
使用设备树来描述硬件。来自 devicetree 的信息用于创建应用程序映像。
支持多种协议的原生网络堆栈
网络支持功能齐全并经过优化,包括 LwM2M 和 BSD 套接字兼容支持。还提供 OpenThread 支持(在 Nordic 芯片组上)一种网状网络,旨在安全可靠地连接家庭中的数百种产品。
蓝牙低功耗 5.0 支持
蓝牙 5.0 兼容 (ESR10) 和蓝牙低功耗控制器支持(LE 链路层)。包括蓝牙网状网络和蓝牙认证就绪蓝牙控制器。
本机 Linux、macOS 和 Windows 开发
命令行 CMake 构建环境在流行的开发人员操作系统系统上运行。本机 POSIX 端口,让您可以在 Linux 和其他操作系统上构建和运行 Zephyr 作为本机应用程序,以帮助开发和测试。
支持 LittleFS 和 FATFS 的虚拟文件系统接口
LittleFS 和 FATFS 支持、用于内存受限应用程序的 FCB(闪存循环缓冲区)以及用于日志记录和配置的文件系统增强功能。
强大的多后端日志框架
支持日志过滤、对象转储、恐慌模式、多个后端(内存、网络、文件系统、控制台……)以及与 shell 子系统的集成。
用户友好且功能齐全的 Shell 界面
一个多实例 shell 子系统,具有用户友好的功能,例如自动完成、通配符、着色、元键(箭头、退格键、ctrl+u 等)和历史记录。支持静态命令和动态子命令。
非易失性存储的设置
设置子系统为模块提供了一种方法来存储持久的每设备配置和运行时状态。设置项存储为键值对字符串。
非易失性存储 (NVS)
NVS 允许存储二进制 blob、字符串、整数、长整数以及它们的任意组合。
本机 POSIX 端口
支持将 Zephyr 作为 Linux 应用程序运行,支持各种子系统和网络。
Zephyr 目录结构
为了深入了解Zephyr的工作机制,我们清晰的了解Zephyr中的各个目录功能。
arch
- arch目录中存放了针对不同架构的移植文件,里面主要是针对不同的CPU进行适配,例如arch/arm/core中存放了针对arm32位芯片的移植,包含mmu,中断,系统时钟,mpu等,有了这些接口,操作系统内核便能正常运行。
- 这些功能通常由Zephyr开发者或者芯片原厂完成,大部分情况下我们是不需要改动的。
soc
- soc目录下存放了针对不同芯片的外设配置和部分功能初始化,例如引脚数量描述,芯片型号,中断数量,总线速率等,可配置的资源为芯片上集成的各种外设,如果选中其中一个SOC,该芯片所属的内核也就确定了。
- 此处配置的资源属于外设,在编译前体现为通过选项决定驱动源文件是否会被编译,在预处理时通过配置选项进行条件编译。同一家的芯片在同种外设功能设计时可能会考虑向后兼容,但是随着时间的推移,为了增加和改进一些新特性,寄存器上也可能存在较大差异,驱动文件中会根据芯片所属系列进行条件编译,驱动需要较强稳定性,一般只会由芯片原厂进行适配。
boards
- boards目录中存放了不同开发板的配置文件,开发板属于SOC的子集,当我们选中一个开发板时,也就会自动确认其SOC的型号
- 除此之外其中还包含了板子的设备树文件,设备树用于描述板上可用资源,这些资源既包括板载的片内外设,也包括与片内外设相连接的外部设备,需要根据硬件设计来进行配置。
- 这部分工作灵活多变,通常就是我们自身来完成,所有的改动都是建立在前面两个目录的基础上进行。
dts
- 该目录下存放了不同架构和不同SOC的设备树文件,以stm32f1为例,该芯片的内核为cortex-m3,属于armv7-m架构,因此会被stm32f1.dtsi引用。
- 除此之外,bindings目录下存放了设备树各个节点的绑定文件,文件的命名通常为"vender,device.yaml",在配置阶段,构建系统会尝试将设备树中的每个节点与bindings中的绑定文件相匹配,如果验证匹配匹配成功,将使用该绑定文件输出对应的宏。
- 构建系统通常会在如下目录中dts/bindings的子目录下查找绑定文件
- zephyr源码仓库
- 你的应用程序目录
- 你的boards目录
- 任何shield目录
- CMake 变量 DTS_ROOT 指定目录
- 在构建设置中定义了dts_root的任何模块
drivers
由芯片厂商适配的驱动程序,其中会使用到soc和board目录下的配置参数,用于条件编译。
doc
参考文档。
kernel
该目录为Zephyr内核源码,包含IPC通讯机制,内存管理,任务调度等。
include
包含了驱动,内核,组件,设备树等模块的头文件。
lib
包含了标准C库,C++库,POSIX接口,以及系统中的一些通用库。
modules
一些第三方的开源库,例如fatfs,canopennode等。
cmake
Zephyr使用CMake作为构建系统,构建过程可分为两个主要阶段:配置阶段(由 CMake 驱动)和构建阶段(由 Make 或 Ninja 驱动)。
- 配置阶段
- 当用户调用CMake生成构建系统时,指定源应用程序目录和板目标,配置阶段开始。
- CMake 首先处理CMakeLists.txt应用程序目录中的文件,该文件引用CMakeLists.txtZephyr 顶级目录中的文件,后者又引用CMakeLists.txt整个构建树中的文件(直接和间接)。它的主要输出是一组 Makefile 或 Ninja 文件来驱动构建过程。
- 但 CMake 脚本也会进行一些自己的处理,设备树预处理和Kconfig的配置工作。
- 构建阶段
- 预构建
- 初次二进制文件
- 最终二进制文件
- 编译后处理
samples
包含各个功能模块的使用示例。
scripts
编译,调试等过程中可以使用的脚本。
subsys
系统中的各种子系统,例如文件系统,控制台,CAN总线,modbus
tests
测试相关,一般不会用到。