GD32F4系列微控制器上电启动流程

根据提供的《GD32F4xx用户手册》及相关文档,GD32F470系列微控制器(基于ARM Cortex-M4内核)的上电启动过程是硬件和软件协同工作的结果。以下是详细的启动步骤,直到执行用户程序的main函数。

核心启动流程概览

整个过程可以分为三个阶段:

  1. 硬件复位与内核启动:芯片上电,硬件逻辑将CPU从复位状态释放,内核从固定的存储地址开始执行预置代码。
  2. 启动程序(Bootloader / 启动文件)执行:这通常由固化在芯片内部或用户编写的汇编启动代码完成,负责初始化最基本的系统环境。
  3. C运行时环境建立与跳转 :初始化C语言的运行环境(如堆栈、全局变量),最后跳转到用户编写的main函数。

详细步骤分解

第一阶段:硬件复位与内核启动
  1. 上电复位

    • 当给芯片提供稳定的电源(VDD/VDDA)后,内部的上电复位(POR) 电路会产生一个复位信号,将芯片(除备份域外)的所有逻辑复位到初始状态。
    • 如果使能了欠压复位(BOR),电源电压需高于设定的阈值,才会释放复位信号。
  2. 引导配置(Boot Configuration)

    • 在复位信号释放后的第四个系统时钟(CK_SYS)上升沿,芯片会锁存 BOOT0BOOT1 引脚的电平状态。这两个引脚决定了CPU从哪个存储空间开始取指(引导源)。根据手册 表1-3. 引导模式
      • BOOT0=0:从主FLASH存储器 启动(地址 0x0800 0000)。这是最常见的用户程序运行模式。
      • BOOT0=1, BOOT1=0:从系统存储器 (Bootloader)启动(地址 0x1FFF 0000)。
      • BOOT0=1, BOOT1=1:从片上SRAM 启动(地址 0x2000 0000)。
  3. 映射与取向量

    • 根据选择的引导模式,相应的存储空间会被映射到引导存储空间 (即从 0x0000 0000 开始的地址空间)。例如,当选择从主FLASH启动时,FLASH的起始地址 0x0800 0000 被映射到 0x0000 0000
    • Cortex-M4内核0x0000 0000 地址读取数据,并将其作为栈顶指针(MSP) 的初始值。
    • 紧接着,内核从 0x0000 0004 地址读取数据,并将其作为复位向量,即复位后要执行的第一条指令的地址。
第二阶段:启动程序执行
  1. 跳转到复位处理函数

    • CPU跳转到复位向量指向的代码地址,这个地址通常是启动文件(startup_gd32f470.s)中的Reset_Handler函数入口。
  2. Reset_Handler执行

    这个函数是启动程序的核心,主要执行以下操作:

    • 系统时钟初始化 :调用SystemInit函数。该函数配置时钟控制单元(RCU),将系统时钟从默认的内部16MRC振荡器(IRC16M) 切换到用户配置的时钟源(如外部高速晶体振荡器(HXTAL)锁相环(PLL)),最终设置到最高频率(例如200MHz)。这一步在手册第4章"复位和时钟单元(RCU)"中有详细说明。
    • 中断向量表重定位 :如果程序在SRAM中运行或需要重定位中断向量表,SystemInit或后续代码会配置中断向量表偏移量寄存器(VTOR),将其指向正确的位置。
    • 初始化静态数据
      • 已初始化的全局变量和静态变量.data段)从FLASH复制到SRAM中。
      • 未初始化的全局变量和静态变量.bss段)所在的SRAM区域清零。
    • 初始化堆和栈 :为C语言的运行库设置堆栈指针(SP),并可能初始化堆内存(用于malloc等动态内存分配)。
第三阶段:进入用户程序
  1. 跳转到__main

    • Reset_Handler函数的最后一步通常是跳转到C库的入口函数__main(注意,不是用户写的main)。
  2. C库初始化

    • __main函数负责完成C运行时环境的最后设置,例如初始化C库函数所需的资源。
  3. 执行用户main函数

    • C库初始化完成后,最终会调用用户程序中的main函数。至此,用户程序开始执行。

总结图示

关键点总结

  • 启动文件 :整个过程的核心是启动文件(通常由芯片厂商提供),它包含了Reset_HandlerSystemInit函数的汇编/C实现。
  • 向量表 :存储在FLASH起始位置(0x0800_0000)的向量表是程序正确运行的基石。第一个字是栈顶地址,第二个字是Reset_Handler的地址。
  • SystemInit :在进入用户main函数之前,一个稳定且高效的时钟配置是必需的。SystemInit函数正是为此而设。你可以在system_gd32f4xx.c文件中找到它并进行配置。
  • 用户入口点 :尽管启动过程复杂,但最终目标就是可靠地跳转到你编写的main函数,开始应用程序的逻辑。
相关推荐
azwsm3 小时前
驱动第一阶段——启动流程
单片机·嵌入式硬件
单片机杂货铺5 小时前
基于单片机的自动开窗器设计
stm32·嵌入式硬件·51单片机·硬件工程
天天爱吃肉82186 小时前
商用车多体动力学实战笔记|第6篇:动力传动系统(发动机、变速箱、分动器、TCS、LSD限滑差速)
大数据·人工智能·笔记·python·嵌入式硬件·汽车
lhbweilai7 小时前
STM32 I2C(hal库)
stm32·单片机·嵌入式硬件
单片机杂货铺10 小时前
基于STM32的智能市政清洁小车系统设计
stm32·单片机·嵌入式硬件·物联网·硬件工程
单片机杂货铺10 小时前
基于STM32的智能书房系统的设计
stm32·单片机·嵌入式硬件·51单片机·硬件工程
&Hello Code11 小时前
3.解决STM32工程混乱:一套可复用六层架构,GPIO 、LED 实战演示
stm32·嵌入式硬件·架构
普科PRBTEK11 小时前
电流探头的常见应用场景
单片机·嵌入式硬件
qq_4017004112 小时前
3个常用的单片机实现隔离控制大电流负载例子
单片机·嵌入式硬件
weixin_4568083812 小时前
【沁恒蓝牙开发】BLE常见错误码与解析
c语言·单片机·嵌入式硬件