zephyr_02_内核启动
2017-12-11 08:22
211 查看
zephyr是一款轻量级的linux, 中文翻译为”和风, 西风, 轻薄织物”, 推出不到两年的时间, 已从刚开始支持的4,5个到现在支持市面上主流的MCU, 发展速度及其迅速, 最主要是开源, 现在更新到1.9.2, 基于最新版本代码, 汲取网上大牛们的经验, 对系统的启动流程做个简单的记录 (以cortex-cm4为例, 因手头的nrf52840是基于M4核的).
CPU上电复位操作流程
1. 查找向量中断表, 跳转到复位异常函数处理执行
2. 锁中断(NMI和hard Fault除外)
3. 初始化看门狗(条件编译, 可选)
4. 初始化中断栈空间(条件编译, 可选) // 但为什么要初始化为0xaa by Huihh 2017.12.8
5. 将PSP指向栈顶地址
6. 跳转到_PrepC函数, 准备C代码运行环境
7. 根据启动方式, 重定位向量表
8. 将BBS段清0
9. 数据拷贝, 从ROM拷贝到RAM中 (完成之后, C代码环境已准备好)
10. 初始化内核 (调用前必须确保系统已准备好执行C代码的环境, 处理器必须运行在32-bit模式, BSS段已清0)
1. XIP 模式 (eXecute In Place), 在该模式下,CPU直接从Nor Flash上读代码执行 执行速度慢
2. 非XIP模式 在该模式下, 硬件先将代码从Flash上搬移到RAM上后, CPU才能从RAM上访问数据 执行速度快
CPU上电复位操作流程
1. 查找向量中断表, 跳转到复位异常函数处理执行
2. 锁中断(NMI和hard Fault除外)
3. 初始化看门狗(条件编译, 可选)
4. 初始化中断栈空间(条件编译, 可选) // 但为什么要初始化为0xaa by Huihh 2017.12.8
5. 将PSP指向栈顶地址
6. 跳转到_PrepC函数, 准备C代码运行环境
7. 根据启动方式, 重定位向量表
8. 将BBS段清0
9. 数据拷贝, 从ROM拷贝到RAM中 (完成之后, C代码环境已准备好)
10. 初始化内核 (调用前必须确保系统已准备好执行C代码的环境, 处理器必须运行在32-bit模式, BSS段已清0)
1. 向量表
Cortex-M4的异常向量表 . 1-15 //系统异常向量表 . 16-255 //中断向量表, 芯片厂家一般只会实现其中一部分中断
2. 启动源文件(/${ZEPHYR_BASE}/arch/arm/core/cortex_m/vector_table.S)
#include <board.h> #include <toolchain.h> #include <linker/sections.h> #include <drivers/system_timer.h> #include "vector_table.h" _ASM_FILE_PROLOGUE GDATA(_main_stack) //_main_stack 全局符号, 存放在数据段 SECTION_SUBSEC_FUNC(exc_vector_table,_vector_table_section,_vector_table) .word _main_stack + CONFIG_MAIN_STACK_SIZE //0 N/A .word __reset //1 系统上电, 发生复位异常, 既会跳转到 __reset符号处执行 .word __nmi //2 不可屏蔽中断NMI, .word __hard_fault //3 硬中断 .word __mpu_fault //4 MPU fault .word __bus_fault //5 总线 fault .word __usage_fault //6 用法 fault .word __reserved //7 保留 .word __reserved //8 保留 .word __reserved //9 保留 .word __reserved //10 保留 .word __svc //11 SVC 系统调用 .word __debug_monitor //12 调试监视器 .word __reserved //13 保留 .word __pendsv //14 PendSV #if defined(CONFIG_CORTEX_M_SYSTICK) //条件编译, 如果存在systick 则定义, 否则保留 .word _timer_int_handler //15 SysTick #else .word __reserved #endif
3. 上电复位, __reset处理, 为执行C代码准备环境 (/${ZEPHYR_BASE}/arch/arm/core/cortex_m/reset.S)
1. 系统从reset中运行, 处理器处于特权级别的线程模式, 主堆栈(MSP)指向SRAM的有效区域 2. 锁定中断(除NMI和hard Fault外), 默认的NMI异常处理已存在向量表中, boot代码不应该产生hard Fault 3. 使用进程堆栈(PSP)替代主堆栈(MSP), 一旦主堆栈(MSP)用于指向唯一的中断堆栈继续启动, 这在运行C代码时是不可能的 4. 这些步骤完成后, 跳转到_PrepC()函数, 它将完成设置C代码的运行环境 #include <board.h> #include <toolchain.h> #include <linker/sections.h> #include <arch/cpu.h> #include <offsets_short.h> #include "vector_table.h" _ASM_FILE_PROLOGUE GTEXT(__reset) GTEXT(memset) GDATA(_interrupt_stack) SECTION_SUBSEC_FUNC(TEXT,_reset_section,__reset) SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start) //XIP启动, __start 开始启动处的别名 movs.n r0, #_EXC_IRQ_DEFAULT_PRIO //锁中断 msr BASEPRI, r0 #ifdef CONFIG_WDOG_INIT //条件编译 初始化看门狗 bl _WdogInit #endif #ifdef CONFIG_INIT_STACKS //条件编译 初始化堆栈 (初始值为0xaa) //为什么不是0x00 by Huihh 2017.12.8 ldr r0, =_interrupt_stack ldr r1, =0xaa ldr r2, =CONFIG_ISR_STACK_SIZE bl memset //memset参数: Para1: r0, Para2: r1, Para3: r2 #endif ldr r0, =_interrupt_stack //将PSP指向栈顶(栈顶=栈起始地址+栈大小) ldr r1, =CONFIG_ISR_STACK_SIZE adds r0, r0, r1 msr PSP, r0 movs.n r0, #2 msr CONTROL, r0 //配置CONTROL寄存器, 使能进程堆栈寄存器(PSP) b _PrepC //跳转_PrepC 函数, 准备C代码执行环境
4. _PrepC (/${ZEPHYR_BASE}/arch/arm/core/cortex_m/prep_c.c)
启动方式(具体启动方式由SoC设计决定)1. XIP 模式 (eXecute In Place), 在该模式下,CPU直接从Nor Flash上读代码执行 执行速度慢
2. 非XIP模式 在该模式下, 硬件先将代码从Flash上搬移到RAM上后, CPU才能从RAM上访问数据 执行速度快
#include <kernel.h> #include <zephyr/types.h> #include <toolchain.h> #include <linker/linker-defs.h> #include <nano_internal.h> #include <arch/arm/cortex_m/cmsis.h> #include <string.h> #ifdef CONFIG_XIP #define VECTOR_ADDRESS ((uintptr_t)&_image_rom_start + \ CONFIG_TEXT_SECTION_OFFSET) //XIP启动, 向量表地址, 默认为0x00地址 #else #define VECTOR_ADDRESS CONFIG_SRAM_BASE_ADDRESS //非XIP启动, (硬件已搬移代码)向量表地址, 指向SRAM的地址 #endif static inline void relocate_vector_table(void) //重定位向量表地址, 决定从SRAM/Nor Flash启动 { SCB->VTOR = VECTOR_ADDRESS & SCB_VTOR_TBLOFF_Msk; __DSB(); __ISB(); } #ifdef CONFIG_FLOAT static inline void enable_floating_point(void) //浮点单元配置 { /* * Upon reset, the Co-Processor Access Control Register is 0x00000000. * Enable CP10 and CP11 coprocessors to enable floating point. */ SCB->CPACR |= CPACR_CP10_FULL_ACCESS | CPACR_CP11_FULL_ACCESS; /* * Upon reset, the FPU Context Control Register is 0xC0000000 * (both Automatic and Lazy state preservation is enabled). * Disable lazy state preservation so the volatile FP registers are * always saved on exception. */ FPU->FPCCR = FPU_FPCCR_ASPEN_Msk; /* FPU_FPCCR_LSPEN = 0 */ /* * Although automatic state preservation is enabled, the processor * does not automatically save the volatile FP registers until they * have first been touched. Perform a dummy move operation so that * the stack frames are created as expected before any task or fiber * context switching can occur. */ __asm__ volatile( "vmov s0, s0;\n\t" "dsb;\n\t" "isb;\n\t" ); } #else static inline void enable_floating_point(void) { } #endif extern FUNC_NORETURN void _Cstart(void); /** * * @brief Prepare to and run C code * * This routine prepares for the execution of and runs C code. * * @return N/A */ #ifdef CONFIG_BOOT_TIME_MEASUREMENT extern u64_t __start_time_stamp; #endif void _PrepC(void) { relocate_vector_table(); //重定位向量表 enable_floating_point(); //浮点单元(FPU) _bss_zero(); //bss段清0 (实现 /${ZEPHYR_BASE}/kernel/init.c) _data_copy(); //数据拷贝 (实现 /${ZEPHYR_BASE}/kernel/init.c) #ifdef CONFIG_BOOT_TIME_MEASUREMENT __start_time_stamp = 0; #endif _Cstart(); //初始化内核 CODE_UNREACHABLE; }
5. _Cstart() 初始化内核 (/${ZEPHYR_BASE}/kernel/init.c)
相关文章推荐
- Zephyr OS 内核篇:系统启动 - 汇编阶段
- Linux 内核启动分析
- 内核启动参数
- centos系统有多个内核,修改默认启动内核
- 启动内核为什么一定要先启动bootloader
- 内核启动之启动内核——startup_32
- 如何贴加自己的应用程序到WINCE内核中,并且随系统启动而启动!
- 戴文的Linux内核专题:02 源代码
- Beaglebone Black——理论篇beaglebone black启动——从串口获得SPL、U-BOOT,TFTP服务器获得内核,NFS服务器挂载根文件系统
- Linux 第20天: (09月12日) Linux启动和内核管理
- [Spark内核] 第32课:Spark Worker原理和源码剖析解密:Worker工作流程图、Worker启动Driver源码解密、Worker启动Executor源码解密等
- 修改内核启动logo的方法
- Linux芯片级移植与底层驱动(基于3.7.4内核) --SMP多核启动以及CPU热插拔驱动
- UBOOT启动内核过程
- IMX6Solo启动流程-Linux 内核启动 三
- Linux如何在系统启动时自动加载内核模块
- tiny4412平台linux系统内核启动问题
- IMX6Solo启动流程-Linux 内核启动 四
- mini6410基于linux2.6.36内核通过NFS启动根文件系统总结(四制作根文件系统及通过NFS挂载文件系统)
- Hyper-V 环境,CentOS内核冲突,修改内核启动顺序