MCU启动过程简介

发布于:2025-08-31 ⋅ 阅读:(19) ⋅ 点赞:(0)

第一阶段:芯片内置硬件自动处理 (上电复位后)

这是完全由硬件自动完成的步骤,程序员无法干预,但必须了解。

  1. 上电复位 (Power-On Reset)

    • 当给 MCU 施加电源后,内部的复位电路会保持 MCU 处于复位状态,直到电源电压稳定达到正常工作范围(例如 3.3V 或 5.0V)。这确保了芯片不会在电压不稳时发生误操作。

  2. 时钟初始化

    • 复位释放后,MCU 首先会使用其内部RC振荡器 (Internal RC Oscillator) 作为初始时钟源。这是因为内部RC振荡器起振快,但精度较低。它为后续更复杂的初始化过程提供基本的时钟驱动。

  3. 获取初始堆栈指针 (SP) 和程序计数器 (PC)

    • 这是最关键的一步。CPU 会从中断向量表 (Interrupt Vector Table) 的起始地址(通常是 Flash 存储器的第一个地址,如 0x0000_0000)读取前两个字(Word):

      • 第一个字:加载到主堆栈指针 (MSP) 寄存器。这是系统启动后使用的第一个堆栈,为后续的C语言函数调用提供内存空间。

      • 第二个字:加载到程序计数器 (PC) 寄存器。这个值通常是复位异常处理函数 (Reset_Handler) 的地址。CPU 会跳转到这个函数开始执行代码。


第二阶段:启动文件执行 (Reset_Handler)

从这一步开始,软件开始接管。芯片厂商会提供一个默认的启动文件(Startup File,通常是汇编和C混合编写,如 startup_stm32fxxx.s)。这个文件中的 Reset_Handler 函数负责为运行C语言代码搭建一个完整的环境。

  1. 初始化堆栈指针 (SP)

    • 虽然硬件已经设置了MSP,但一些复杂的系统(如带有RTOS或双堆栈的ARM Cortex-M芯片)可能还会在这里重新设置或初始化堆栈。

  2. 初始化数据段 (.data)

    • 问题:已初始化的全局变量和静态变量(如 int a = 100;)的初始值存储在Flash中,但它们的运行时值需要在可读写的RAM中。

    • 操作:启动代码会将这部分变量的初始值从Flash拷贝到RAM中对应的 .data 区域。

  3. 清零BSS段 (.bss)

    • 问题:未初始化的全局变量和静态变量(如 int b;)默认值应为0,它们被归类在 .bss 段。

    • 操作:启动代码会将整个 .bss 段所在的RAM区域全部清零。这确保了这些变量从0开始。

  4. 初始化标准库 (可选)

    • 如果用户程序使用了标准库函数(如 printfmalloc),这里会调用 SystemInit 等函数来初始化系统时钟(切换到外部晶振、配置PLL提高频率)、初始化内存管理单元等。

  5. 跳转到 main 函数

    • 在所有准备工作完成后,Reset_Handler 会最终跳转到用户的 main() 函数。从此,控制权完全交给了用户的应用程序。


第三阶段:用户主程序 (main())

用户程序开始执行,通常包含以下步骤:

  1. 硬件外设初始化

    • 在 main() 函数中,首先要初始化所需的各种外设,如GPIO(设置输入/输出模式)、UART(配置波特率)、SPI、I2C、ADC等。

    • 配置系统时钟(如果启动文件中没有完全配置的话)。

    • 设置中断优先级和使能中断。

  2. RTOS初始化(如果使用)

    • 对于运行实时操作系统(RTOS)的系统,会在这里创建任务(Task)、队列(Queue)、信号量(Semaphore)等,然后启动调度器(Scheduler)。

  3. 进入主循环 (Main Loop)

    • 最后,程序通常会进入一个无限的 while(1) 循环,在这里不断地执行主要的应用程序逻辑,如读取传感器数据、处理用户输入、控制执行器等。


总结与要点

阶段 执行者 核心任务 是否可编程
第一阶段 硬件 稳定电压、提供基础时钟、读取SP和PC
第二阶段 启动文件 (Reset_Handler) 搭建C语言环境:初始化堆栈、.data段、.bss段 (需修改启动文件)
第三阶段 用户程序 (main()) 初始化外设、创建任务、执行应用逻辑

关键概念:

  • 中断向量表 (IVT):一个存放着所有异常和中断处理函数地址的表格,是硬件和软件连接的桥梁。

  • 启动文件:芯片厂商提供,是项目的重要组成部分,它完成了硬件到软件的关键过渡。理解它对于深入理解嵌入式系统至关重要。

  • 链接脚本 (Linker Script):它定义了内存布局(Flash和RAM的地址范围),并指定了各个段(如 .text.data.bss)在内存中的存放位置。启动文件的操作依赖于链接脚本的定义。

希望这份详细的分解能帮助你彻底理解MCU的启动过程!


网站公告

今日签到

点亮在社区的每一天
去签到