说起来RTOS第一印象就是单片机程序、ARMM核、微控制器低频运行处理程序甚至其不能算一个真正的OS。但是随着时代发展这些单片机程序在有限的硬件机制下非常接近像Linux这种的巨无霸OS了例如其有线程、中断、内存管理、IPC、驱动、网络协议栈、shell、提供POSIX接口等可以说其已经是一个缩小版的OS了甚至在A核也可以运行简单修改下添加一点用户空间支持等特性就可以。在嵌入式领域中定制化的软硬件并且没有界面展示的时候并不需要ARM A核这种高级的CPUM核是一个更好的选择其便宜小省电可靠性高偏向专用控制但是频率低功能进行了阉割。在其上运行的RTOS也有对应的特点地址空间只有一个就像Linux的内核一样共享地址空间没有高级的硬件相关MMU功能无虚拟地址没有文件系统、UI界面等复杂服务各种服务例如进程调度等是一个简单实现版本之前介绍过一个典型的RTOS freeRTOSFreeRTOS入门-概念介绍。其实RTOS的定义就是实时操作系统例如Linux修改下具有实时特性也可以叫RTOS了。本文讲的zephyr RTOS就是一个类似freeRTOS的操作系统可以等价平替下面介绍下其特点先直接上代码https://github.com/zephyrproject-rtos/zephyr1. Zephyr介绍1.1 Zephyr简介Zephyr最初是由Wind River公司开发的一个微内核在2016年的时候成为Linux基金会维护的一个项目发展至今已经成为了一个功能齐全的嵌入式OS。平台现在支持ARM、RISC-V、X86、Xtensa等等处理器平台拥有原生的BLE协议栈、完整的Net协议栈包括TCP/IP与应用层协议为嵌入式应用的开发提供了有力的支持。Zephyr它不仅仅维护了一个RTOS内核还维护一些编译链、libc、 IDE插件、HEL层驱动等几乎每一个模块都有相关的文档。正是因为拥有详细的文档Zephyr才能源源不断的吸引人来进行尝试与开发以至于系统不断的被完善进入开源项目的一个良性循环。Linux基金会维护所以看Zephyr就很Linux里Linux气的比如make menuconfig支持、DTS支持等可以说把Linux一些优秀的通用特性吸引进来了做到了很多代码跟Linux同步妥妥的Linux小弟。好处就是我们去抄代码的时候不是移植代码的时候Zephyr就是一个很好的调研对象其完全开源嘛Wind River公司大名鼎鼎的VxWorks实时操作系统就是Wind River公司开发的其在实时操作系统领域早期可谓独领风骚特别在军工中它以其良好的可靠性和实时性被广泛地应用在通信、军事、航空、航天等高精尖技术及实时性要求极高的领域中如卫星通讯、军事演习、弹道制导、飞机导航等。在美国的 F-16、FA-18战斗机、B-2 隐形轰炸机和爱国者导弹上甚至连1997年4月在火星表面登陆的火星探测器、2008年5月登陆的凤凰号和2012年8月登陆的好奇号也都使用到了VxWorks。VxWorks不开源这里的Zephyr可以说是出身在一流家族中其实时特性应该很值得借鉴。1.2 特性介绍Zephyr OS 基于小占用内核设计用于资源受限的嵌入式系统从简单的嵌入式环境传感器和 LED 可穿戴设备到复杂的嵌入式控制器、智能手表和物联网无线应用。其中Zephyr OS为Zephyr提供的核心代码包含了Kernel/HAL内核调度低级的体系结构和板级支援各种RTOS内核对象电源管理框架低级的硬件接口抽象OS服务及底层接口设备管理及底层驱动API文件系统Logging系统Debugging系统及IPC加密服务平台相关的特殊驱动网络协议栈应用服务高层级的应用API标准化的数据模型高层级网络协议接口对于Zephyr应用开发者需要熟知应用服务和OS服务了解底层接口及Kernel/HAL特性。Zephy也提供构建系统及开发环境和Zephyr OS一起构成了Zephyr ProjectZephyr Project包含了Zephyr的SDK构建工具CI及开发环境BootloaderMCUboot附加的中间件Zephyr除了核心代码之外还引入了其它优秀的开源项目做为其功能组成部分另外还有不同的项目也将Zephyr作为其组成部分这些内容在一起构成了完整的Zephyr生态。Zephyr生态有如下内容第三方模块或库例如lvglfatfsmcumgropenthreadopenampopencan等等。第三方支持Zephyr的项目例如Jerryscript ,Micropython , Iotivity , SwiftIO等。SOC供应商HalZephyr将不同芯片的Hal作为外部模块引入到Zephyr中通过Zephyr驱动的整合让应用可以通过统一的驱动接口控制不同芯片的片上设备。例如nxpsttinordicsilabs等等。Kernel涵盖以下内容提供Kernel service例如thread同步数据传递中断管理时间管理内存管理等进行任务调度电源管理平台相关的特殊驱动例如Radios传感器加密硬件Flash等OS服务涵盖以下内容设备驱动实现提供统一的底层驱动接口设备管理网络L2实现及接口抽象网络层和传输层协议栈(TCP/IP)socket接口应用服务涵盖以下内容网络应用协议及高层级接口例如HTTPcoapmqtttlsdtls等提供标准化的数据模型目前尚未在Zephyr的目录树中找到该部分内容提供智能物件对象例如基于lwm2m的IPSOZephyr的硬件层次结构被抽象出6层架构(Architecutre)指令架构体系例如ARMRISC-Vx86等CPU内核(CPU core)架构中特定的CPU例如ARM中有Cortex-M0,M3,M4,M7等芯片族(Soc family)具有相似特性的SoC例如Cortex-M7中有STMicro STM32NXP i.MX芯片系列(SoC series)一小部分紧密关联的SoC例如i.MX中有i.MX RT 系列i.MX 8系列等芯片级(SoC)电路板上的SoC例如i.MX RT系列中有RT1050,RT1060等芯片板级(Board)PCB上特定的SoC和一些外设相连构成有特定功能的电路板。例如Zephyr支援的mimxrt1050_evkmm_swiftio开发板使用了rt1052芯片。Zephyr 内核支持多种架构包括ARCv2 (EM and HS) and ARCv3 (HS6X)ARMv6-M, ARMv7-M, and ARMv8-M (Cortex-M)ARMv7-A and ARMv8-A (Cortex-A, 32- and 64-bit)ARMv7-R, ARMv8-R (Cortex-R, 32- and 64-bit)Intel x86 (32- and 64-bit)MIPS (MIPS32 Release 1 specification)NIOS II Gen 2RISC-V (32- and 64-bit)SPARC V8Tensilica Xtensa广泛的内核服务套件Zephyr 提供了许多熟悉的开发服务用于协作、基于优先级、非抢占式和抢占式线程的多线程服务具有可选的循环时间切片。包括 POSIX pthreads 兼容 API 支持。中断服务用于中断处理程序的编译时注册。用于动态分配和释放固定大小或可变大小内存块的内存分配服务。用于二进制信号量、计数信号量和互斥信号量的线程间同步服务。用于基本消息队列、增强消息队列和字节流的线程间数据传递服务。Zephyr 提供了一套全面的线程调度选择协作和抢占式调度最早截止日期优先 (EDF)元 IRQ 调度实现“中断下半部分”或“tasklet”行为时间切片在同等优先级的可抢占线程之间启用时间切片多种排队策略简单链表就绪队列红/黑树就绪队列传统多队列就绪队列高度可配置/模块化以实现灵活性允许应用程序仅根据需要合并其所需的功能并指定其数量和大小。跨架构支持具有不同 CPU 架构和开发工具的各种受支持的主板。贡献增加了对越来越多 SoC、平台和驱动程序的支持。内存保护在 x86、ARC 和 ARM 架构、用户空间和内存域上实现可配置的特定于架构的堆栈溢出保护、内核对象和设备驱动程序权限跟踪以及具有线程级内存保护的线程隔离。对于没有 MMU/MPU 和内存受限设备的平台支持将特定于应用程序的代码与自定义内核相结合以创建在系统硬件上加载和执行的整体映像。应用程序代码和内核代码都在单个共享地址空间中执行。编译时资源定义允许在编译时定义系统资源从而减少代码大小并提高资源有限系统的性能。优化的设备驱动模型提供用于配置属于平台/系统的驱动程序的一致设备模型以及用于初始化配置到系统中的所有驱动程序的一致模型并允许跨具有公共设备/IP 块的平台重用驱动程序。设备树支持使用devicetree来描述硬件。来自 devicetree 的信息用于创建应用程序映像。支持多种协议的本机网络堆栈网络支持功能齐全且经过优化包括 LwM2M 和 BSD 套接字兼容支持。还提供 OpenThread 支持在 Nordic 芯片组上 - 一个网状网络旨在安全可靠地连接家庭周围的数百个产品。低功耗蓝牙 5.0 支持符合蓝牙 5.0 标准 (ESR10) 和蓝牙低功耗控制器支持LE 链路层。包括蓝牙网状网络和蓝牙资格就绪的蓝牙控制器。网格支持中继、朋友节点、低功耗节点 (LPN) 和 GATT 代理功能支持两种配置承载PB-ADV 和 PB-GATT高度可配置适合具有至少 16k RAM 的设备具有所有可能的 LE 角色的通用访问配置文件 (GAP)通用属性配置文件 (GATT)配对支持包括蓝牙 4.2 的安全连接功能干净的 HCI 驱动程序抽象原始 HCI 接口将 Zephyr 作为控制器运行而不是完整的主机堆栈经多个流行控制器验证高度可配置本机 Linux、macOS 和 Windows 开发命令行 CMake 构建环境在流行的开发人员操作系统上运行。本机端口 ( native_sim ) 允许您在 Linux 上构建和运行 Zephyr 作为本机应用程序从而帮助开发和测试。支持 ext2、FatFs 和 LittleFS 的虚拟文件系统接口ext2、LittleFS 和 FatFS 支持FCB闪存循环缓冲区适用于内存受限的应用程序。强大的多后端日志框架支持日志过滤、对象转储、恐慌模式、多个后端内存、网络、文件系统、控制台……以及与 shell 子系统的集成。用户友好且功能齐全的 Shell 界面多实例 shell 子系统具有用户友好的功能例如自动完成、通配符、着色、元键箭头、退格键、ctrlu 等和历史记录。支持静态命令和动态子命令。非易失性存储上的设置设置子系统为模块提供了一种存储持久的每设备配置和运行时状态的方法。设置项存储为键值对字符串。非易失性存储 (NVS)NVS 允许存储二进制 blob、字符串、整数、长整型以及这些的任意组合。本机端口Native sim允许将 Zephyr 作为 Linux 应用程序运行并支持各种子系统和网络。2. 环境搭建和代码下载编译参考https://docs.zephyrproject.org/latest/develop/getting_started/index.htmlhttps://blog.csdn.net/shenhuxi_yu/article/details/1032299多种编译工具编译参考https://liao-xingyu.gitee.io/p/zephyr-%E7%89%A9%E8%81%94%E7%BD%91%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F%E7%BC%96%E8%AF%91%E4%B8%8E%E8%BF%90%E8%A1%8C/按照本指南进行操作在 Ubuntu、macOS 或 Windows 上设置命令行 Zephyr 开发环境其他 Linux 发行版的说明在 安装 Linux 主机依赖项中讨论获取源代码构建、刷新并运行示例应用程序具体不赘述了提下如果在qemu下运行参考如下在QEMU中运行应用程序在 Linux 和 macOS 上当面向 x86 或 ARM Cortex-M3 架构时您可以使用QEMU在主机系统上通过仿真运行 Zephyr 应用程序。QEMU 包含在 Zephyr SDK 安装中。例如您可以使用 x86 仿真板配置 ( ) 构建并运行Hello Worldqemu_x86示例其中# From the root of the zephyr repositorywest build-bqemu_x86 samples/hello_world west build-trun要退出 QEMU请键入然后键入。Ctrl-ax用于qemu_cortex_m3针对模拟的 Arm Cortex-M3 示例。3. Zephyr的内核特性3.1 构建ephyr的构建系统主要有三个部分cmake、kconfig、devicetreecmake 在前期驱动kconfig和devicetree需生成必要的头文件后期用来生成像ninja或makefile等编译脚本kconfig平台的区分以及代码的裁剪应用开发中主要体现在驱动的开关如下图显示在驱动的实现里面定义了wifi的kconfig宏用户在使用的时候可以在prj.config文件去打开这个宏这个驱动就会被打开。devicetree配置硬件参数信息比如像WIFI的模块可以配置SPI引脚以及速率还可以配置跟他相关的同步引脚。3.2 设备驱动模型Zephyr几乎为所有的外设驱动都提供了统一的API接口芯片原厂基于API接口提供自己的实现用户在使用外设的时候可以直接使用Zephyr提供的外设接口来进行应用开发。Zephyr的设备驱动是在同一个地方统一初始化的比如像这个SPI的驱动它的宏函数就等效于这一段代码代码的含义就是注册了一个函数。这个函数会在main函数前运行运行等级为application级别。驱动的等级会比application高等级越高就会越先执行。设备驱动一定会在main函数前初始化完毕。3.3 线程调度和通信Zephyr 在线程调度方面的功能更加强大、灵活可以更好地满足不同场景下的需求。而 FreeRTOS 则更加简单、易于使用适合对资源需求较为简单的嵌入式应用场景Zephyr 与 FreeRTOS 线程通信对比Zephyr提供了管道、消息队列和信号量等多种线程通信机制而FreeRTOS提供了二值信号量、互斥量和队列等线程通信机制。可以看出Zephyr提供的线程通信机制更加多样化。3.4 内存管理Zephyr在内存管理上具备一些比起其他RTOS更加先进机制如下Memory Heaps提供了基于堆的动态内存分配和释放机制Memory Slabs提供了预分配一定数量内存块的机制并能够快速分配和释放内存块避免了堆内存管理的 开销以及内存碎片的产生Memory Blocks Allocator提供了固定大小内存块的动态分配和释放机制适用于需要频繁分配、释放同一大小内存块 的场景3.5 组件生态越来越多的第三方组件库已经加入或者被移植进了ZephyrProject中,第三方组件管理与接入流程也日趋成熟这为开发者节省了大量常用组件的移植与适配工作。4. Zephyr启动流程这里我们以cortex_m为例只讲下启动流程其他代码流程分析参考https://blog.csdn.net/qq_36115224/category_12279396.html4.1 程序入口include/zephyr/arch/arm/cortex_m/scripts/linker.ld中定义了ENTRY程序入口ENTRY(CONFIG_KERNEL_ENTRY)这个宏的定义在Kconfig.zephyr中config KERNEL_ENTRY stringKernel entry symboldefault__starthelpCode entry symbol, to besetat linking phase.__start是程序的入口但是这是gcc的规则Cortex-M系列处理器是通过中断向量表来确定程序入口 Cortex-M系列处理器是通过中断向量表来确定程序入口。在 Cortex-M 系列 MCU 中如果设置为从 flash 启动flash 前1K 用于存放中断向量表其中第一个字为程序栈顶指针用于初始化栈顶第二个字为复位向量即 ResetHandler 的地址作为程序跳转地址从而跳转到程序中运行详细说明可参考异常模型, 该机制为Cortex-M 系列 MCU 中独有与此相对的不同的芯片在系统启动时对可执行程序都有一定的格式要求需要在程序的头部添加符合操作规范的头。中断向量表中reset的处理地址定义在arch/arm/core/cortex_m/reset.S中SECTION_SUBSEC_FUNC(TEXT,_reset_section,z_arm_reset)4.2 汇编初始化在arch/arm/core/cortex_m/reset.S中SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start)#if defined(CONFIG_DEBUG_THREAD_INFO)/* Clear z_sys_post_kernel flagforRTOS aware debuggers */ movs.n r0,#0ldr r1,z_sys_post_kernel strb r0,[r1]#endif /* CONFIG_DEBUG_THREAD_INFO */#if defined(CONFIG_INIT_ARCH_HW_AT_BOOT)/* 复位CONTROL寄存器在特权模式和非特权模式均使用MSP * 当切换栈指针之后必须使用ISB指令刷新流水线 * 以保证在ISB之后执行的指令都使用新的栈 */ movs.n r0,#0msr CONTROL, r0 isb#if defined(CONFIG_CPU_CORTEX_M_HAS_SPLIM)/* 堆栈限制寄存器分别限制 MSP 和 PSP 寄存器可以下降的程度此处设置为0 */ movs.n r0,#0msr MSPLIM, r0 msr PSPLIM, r0#endif /* CONFIG_CPU_CORTEX_M_HAS_SPLIM */#endif /* CONFIG_INIT_ARCH_HW_AT_BOOT */#if defined(CONFIG_PM_S2RAM)/* 低功耗相关初始化 */ bl arch_pm_s2ram_resume#endif /* CONFIG_PM_S2RAM */#if defined(CONFIG_PLATFORM_SPECIFIC_INIT)/* 针对内存cachejtag时钟中断的一些特殊配置 */ bl z_arm_platform_init#endif#if defined(CONFIG_INIT_ARCH_HW_AT_BOOT)#if defined(CONFIG_CPU_HAS_ARM_MPU)/* 操作系统未运行之前使用平坦内存模型所有内存均不受保护 * 为避免在初始化过程中触发读写保护进入异常一定要关闭MPU */ movs.n r0,#0ldr r1,_SCS_MPU_CTRL str r0,[r1]dsb#endif /* CONFIG_CPU_HAS_ARM_MPU *//* ARM32使用满递减栈栈顶指针初始时刻指向高地址 * 将MSP指向 z_main_stack 的末尾以便后续进行函数调用 */ ldr r0,z_main_stack CONFIG_MAIN_STACK_SIZE msr msp, r0 /* 清除MPU配置关闭所有中断清除被挂起的中断重置Cache配置等 */ bl z_arm_init_arch_hw_at_boot#endif /* CONFIG_INIT_ARCH_HW_AT_BOOT *//* 屏蔽中断 */#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)cpsid i#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)movs.n r0,#_EXC_IRQ_DEFAULT_PRIOmsr BASEPRI, r0#else#error Unknown ARM architecture#endif#ifdef CONFIG_WDOG_INIT/* 开启看门狗 */ bl z_arm_watchdog_init#endif#ifdef CONFIG_INIT_STACKS/* 将栈全部设置为0xaa可用于监测剩余栈容量 */ ldr r0,z_interrupt_stacks ldr r1,0xaa ldr r2,CONFIG_ISR_STACK_SIZE MPU_GUARD_ALIGN_AND_SIZE bl z_early_memset#endif/* 初始化PSP将CONTROL的SPSEL位设置为1在特权模式下使用MSP非特权模式下使用PSP * 后续操作将使用 z_interrupt_stacks 作为栈进行初始化 */ ldr r0,z_interrupt_stacks ldr r1,CONFIG_ISR_STACK_SIZE MPU_GUARD_ALIGN_AND_SIZE adds r0, r0, r1 msr PSP, r0 mrs r0, CONTROL movs r1,#2orrs r0, r1 /* CONTROL_SPSEL_Msk */ msr CONTROL, r0 isb bl z_prep_c4.3 C语言初始化z_prep_c函数的定义在arch/arm/core/cortex_m/prep_c.c中void z_arm_prep_c(void){relocate_vector_table();#if defined(CONFIG_CPU_HAS_FPU)z_arm_floating_point_init();#endifz_bss_zero();z_data_copy();#if ((defined(CONFIG_ARMV7_R) || defined(CONFIG_ARMV7_A)) defined(CONFIG_INIT_STACKS))z_arm_init_stacks();#endifz_arm_interrupt_init();z_cstart();CODE_UNREACHABLE;}对于不同的平台还需要增加额外的操作例如浮点寄存器的初始化中断向量表的重定向在系统启动之前还运行了一段芯片内置程序这段程序将中断向量表的位置设置为 0x00000000当程序从boot跳转到指定存储器运行之后首先需要立即关闭中断避免中断产生并跳转到错误的中断响应函数中重设中断向量表偏移位置之后再重新开启中断。初始化内核开启任务调度FUNC_NO_STACK_PROTECTOR FUNC_NORETURN void z_cstart(void){/* 代码覆盖率测试相关 */ gcov_static_init();/* 调用初始化级别为 INIT_LEVEL_EARLY 的函数进行初始化 */ z_sys_init_run_level(INIT_LEVEL_EARLY);/* z_arm_interrupt_stack_setup 初始化MSP * z_arm_exc_setup 初始化PENDSV、SysTick等中断的优先级其中PENDSV优先级为最低 * z_arm_fault_init 初始化 Fault 中断。 * z_arm_cpu_idle_init 初始化 idle 线程 * z_arm_clear_faults 清除所有故障标志 * z_arm_mpu_init 初始化MPU * z_arm_mmu_init 初始化MMU */ arch_kernel_init();/* 日志初始化 */ LOG_CORE_INIT();#if defined(CONFIG_MULTITHREADING)/* Note: The z_ready_thread()callinprepare_multithreading()requires * a dummy thread evenifCONFIG_ARCH_HAS_CUSTOM_SWAP_TO_MAINy */ struct k_thread dummy_thread;z_dummy_thread_init(dummy_thread);#endif/* 初始化驱动中的静态节点 */ z_device_state_init();/* 其他的硬件初始化 */ z_sys_init_run_level(INIT_LEVEL_PRE_KERNEL_1);z_sys_init_run_level(INIT_LEVEL_PRE_KERNEL_2);#ifdef CONFIG_STACK_CANARIES/* CONFIG_STACK_CANARIES 用于开启堆栈金丝雀功能这是一种安全特性有助于监测堆栈溢出 * 当启动该功能时系统启动时会生成一个随机数并保存在 __stack_chk_guard 中 * 在函数返回之前会检查该值确保它没有被缓冲区溢出所覆盖。 */ uintptr_t stack_guard;z_early_boot_rand_get((uint8_t*)stack_guard,sizeof(stack_guard));__stack_chk_guardstack_guard;__stack_chk_guard8;#endif /* CONFIG_STACK_CANARIES */#ifdef CONFIG_TIMING_FUNCTIONS_NEED_AT_BOOT/* timing_init 函数用于初始化系统计时器 */ timing_init();timing_start();#endif#ifdef CONFIG_MULTITHREADING/* CONFIG_MULTITHREADING为y时使用多线程否则只会有一个 main 线程 * 默认情况下都启用多线程通过将 main 线程添加到就绪队列中然后开启任务调度 */ switch_to_main_thread(prepare_multithreading());#else#ifdef ARCH_SWITCH_TO_MAIN_NO_MULTITHREADING/* Custom ARCH-specific routine to switch to main()*inthecaseof no multi-threading. */ ARCH_SWITCH_TO_MAIN_NO_MULTITHREADING(bg_thread_main, NULL, NULL, NULL);#elsebg_thread_main(NULL, NULL, NULL);/* LCOV_EXCL_START * Weve already dumped coverage data at this point. */ irq_lock(); while (true) { } /* LCOV_EXCL_STOP */ #endif #endif /* CONFIG_MULTITHREADING */ /* * Compiler cant tell that the above routines wontreturnand issues * a warning unless we explicitly tell it that control never gets this * far. */ CODE_UNREACHABLE;/* LCOV_EXCL_LINE */}在进入 z_cstart 之后首先调用平台相关的内核初始化函数然后使用模块自动初始化机制根据不同优先级调用相关初始化函数 需要注意的是同一优先级的模块之间不应该存在依赖关系被依赖的模块应该先初始化。在调度器启动之前会调用优先级为 INIT_LEVEL_PRE_KERNEL_1 和 INIT_LEVEL_PRE_KERNEL_2 的初始化函数此时调度器还未运行因此这些函数中不应该使用操作系统提供的功能。在初始化完成之后通过将main线程添加到就绪队列中并开启调度器main 线程从 bg_thread_main 函数开始运行。4.4 main线程bg_thread_main的定义在kernel/init.c中static void bg_thread_main(void *unused1, void *unused2, void *unused3){ARG_UNUSED(unused1);ARG_UNUSED(unused2);ARG_UNUSED(unused3);#ifdef CONFIG_MMU/* Invoked here such that backing store or eviction algorithms may * initialize kernel objects, and that all POST_KERNEL and later tasks * may perform memory management tasks(exceptforz_phys_map()which* is allowed at anytime)*/ z_mem_manage_init();#endif /* CONFIG_MMU */z_sys_post_kerneltrue;/* 调用优先级为INIT_LEVEL_POST_KERNEL的初始化函数 * 此时内核已经开始运行可以使用操作系统API */ z_sys_init_run_level(INIT_LEVEL_POST_KERNEL);#if CONFIG_STACK_POINTER_RANDOMz_stack_adjust_initialized1;#endif/* 从控制台输出系统启动标识 */ boot_banner();#if defined(CONFIG_CPP)/* 初始化CPP运行环境 */ void z_cpp_init_static(void);z_cpp_init_static();#endif/* 调用优先级为 INIT_LEVEL_APPLICATION 的初始化函数 */ z_sys_init_run_level(INIT_LEVEL_APPLICATION);/* Zephyr支持静态创建线程线程对应的信息在编译时确定 * 随代码一起被编译到程序中系统启动之后从对应地址将线程的信息从flash中读出 * 创建并初始化线程并将其添加到就绪队列中等待操作系统调度。 */ z_init_static_threads();#ifdef CONFIG_KERNEL_COHERENCE__ASSERT_NO_MSG(arch_mem_coherent(_kernel));#endif#ifdef CONFIG_SMPif(!IS_ENABLED(CONFIG_SMP_BOOT_DELAY)){z_smp_init();}z_sys_init_run_level(INIT_LEVEL_SMP);#endif#ifdef CONFIG_MMUz_mem_manage_boot_finish();#endif /* CONFIG_MMU */#ifdef CONFIG_CPP_MAINextern int main(void);#elseextern void main(void);#endif/* 跳转到main函数 */(void)main();/* Mark nonessential since main()has nomorework todo*/ z_main_thread.base.user_options~K_ESSENTIAL;#ifdef CONFIG_COVERAGE_DUMP/* Dump coverage data once the main()has exited. */ gcov_coverage_dump();#endif}其中包含几个系统运行的重要的操作配置MMU如果存在 调用优先级为 INIT_LEVEL_POST_KERNEL 的初始化函数 CPP运行环境的初始化 调用优先级为 INIT_LEVEL_APPLICATION 的初始化函数 创建通过宏静态创建的线程并添加到就绪队列。初始化对称多核处理如果存在多个处理器并启用了多核调度。在这些准备工作完成后跳转到用户编写的main函数中如果main函数执行并返回最终会返回到 z_thread_entry 被销毁。学习方法看官网https://docs.zephyrproject.org/latest/introduction/index.htmlbilibili看视频https://search.bilibili.com/all?keywordZephyrfrom_sourcewebtop_searchspm_id_from333.788search_source5CSDN、知乎等资料也挺多可以自己去搜索参考资料Zephyr 入门看这篇就够了(含FreeRTOS对比)https://blog.csdn.net/qq_36115224/article/details/130077367https://lgl88911.github.io/2020/11/29/Zephyr-%E6%A1%86%E6%9E%B6%E7%BB%93%E6%9E%84%E7%AE%80%E4%BB%8B/后记Zephyr RTOS整体上网上资料很多大家可以自己去搜索学习也说明这个RTOS是比较流行的各种硬件也对这个Zephyr进行了支持里面有很多功能非常的丰富如果自己项目的RTOS缺失的功能可以去上面进行移植。一个典型就是gcov代码覆盖率测试模块一般的RTOS是不支持的就可以移植。对于OS在国内可能很神秘但是在欧美特别是高校里面各种定制版本或者学术版本的OS层出不穷已经算是人人都能造OS了一样这些小众的OS不一定流行起来但是也各有特点特别是一些特定场景下小众OS也许能获得更高的效率和效果开源OS界也是天下文章一大抄。“啥都懂一点啥都不精通干啥都能干干啥啥不是专业入门劝退堪称程序员杂家”。个人文章汇总https://thatway1989.github.io