STM32的启动流程分析 和 一些底层控制的原理

阅读引言: 阅读本文之后, 你将对单片机, 甚至是嵌入式系统, 或者是传统的PC机系统的启动流程有一个大致的了解, 本文更加偏向于单片机的启动流程分析。

目录

一、基础知识

1.STM32系列的微控制器(mcu)使用的计算机体系结构

2.嵌入式系统的存储器

3.CPU是如何控制外设的

二、点亮LED的几种办法

1.使用汇编指令读写指定的地址

2.使用C语言读写指定的地址​​​​​​​

3.其它方法

三、STM32的启动流程

1.引导加载程序(Boot Loard)

2.STM32G431RBT6的启动流程分析

3.stm32启动代码详解



一、基础知识


1.STM32系列的微控制器(mcu)使用的计算机体系结构

        STM32微控制器使用的是哈佛结构。哈佛结构是指指令存储器和数据存储器分开的计算机存储器结构。在STM32微控制器中,指令存储器通常是闪存,而数据存储器通常是SRAM。这种结构可以提高系统的运行效率,并且可以同时访问指令和数据,提高系统的响应速度。

2.嵌入式系统的存储器

        存储装置是计算机不可或缺的组件,用于存储程序代码和数据,它赋予计算机记忆功能。存储装置通常分为主存和外部存储器。主存是电路板上的半导体存储器,而外部存储器包括硬盘、光盘、U盘、闪存卡等。 嵌入式系统的存储器系统与通用计算机系统的设计方法有所不同,嵌入式微处理器芯片上集成了一定数量的存储器,成为构成嵌入式系统硬件的主要组成部分。 存储器性能的一些指标包括易失性、只读性、位容量、速度、功耗、可靠性和价格等因素。嵌入式存储器根据掉电信息的保留情况分为ROM和RAM两类, 大致画了一个思维导图, 总结了一下。

引出这些的目的就是需要知道stm32的程序, 也就是指令是存放在flash中的, 而程序在运行期间的数据是存放在SRAM中的, 关于ROM和RAM大家可以把ROM想象成电脑的硬盘, RAM比喻成内存, 运行程序的地方。

3.CPU是如何控制外设的

  • CPU的组成

CPU由以下几部分组成:

1. 控制单元(Control Unit):负责指令的解码和执行,协调各个部件的工作,控制数据的流动。

2. 运算单元(Arithmetic Logic Unit,ALU):负责执行算术和逻辑运算,例如加法、减法、乘法、与、或等操作。

3. 寄存器(Register):用来存放指令、数据和中间结果,包括程序计数器(Program Counter),指令寄存器(Instruction Register),累加器(Accumulator)等。

4. 时钟(Clock):用来同步各个部件的工作,控制指令和数据的传输和处理速度。

5. 数据总线(Data Bus):用于传输数据,连接CPU和其他设备或存储器。

6. 地址总线(Address Bus):用于传输地址信号,指示数据在存储器中的位置。

7. 控制总线(Control Bus):用于传输控制信号,控制各个部件的工作。

以上是CPU的主要组成部分,它们协同工作,使得计算机能够执行各种指令和处理数据。

其实在嵌入式系统中我们熟知的ARM只是为cpu的架构设计提供方案的公司, 或说是一种技术,准确来说我们见到的ST公司生产的芯片都是基于ARM的内核, 然后自己添加了一些硬件控制器在一块芯片里面, 专业术语叫做SOC。

        好了, 言归正传, 只是铺垫得差不多了, 该说说cpu是如何控制外设的了, 比如, cpu控制LED灯的亮灭。这里得提到一个知识点, 指令。

        什么是指令, 其定义是CPU能够识别并执行的机器码, 也就是一些0101的二进制数据, 我们写的代码, 给到交叉编译器编译之后得到的.hex或者.bin文件本质就是机器码, 现在知道为什么cpu能够执行我们写的程序了把, 是编译器的功能, 选择和cpu适配的编译器, 编译出的指令cpu就能识别并执行。、

        cpu执行指令一般分为三个步骤、取值、译码、执行。这些都是由抓门的cpu指令的, 比如通过该cpu的取指的指令给到cpu执行,cpu通过地址总线去内存的指定位置取出指令给到cpu内部的硬件电路去执行。

        编不下去, 直接给大伙看两个汇编指令, LDR, STR, 一个是cpu去指定的地址加载数据到cpu内部, 一个是cpu往指定的地址写数据, 那么, cpu控制LED灯点亮, 大家是不是已经想到答案了, cpu之所以能够控制硬件, 就是其能够通过总线去读写存储器的指定位置。


二、点亮LED的几种办法


1.使用汇编指令读写指定的地址

去芯片厂家提供的地址映射表可以查到对用外设的地址, LTR, STR, MOV,这些指令往控制LED的寄存器的指定的那一个位写值, 即可控制LED

LDR R1, [R2]
STR R1, [R2]

2.使用C语言读写指定的地址

假设你知道了控制LED的gpio的数据寄存器的地址, 哪就可以这样干。

#define LED_DATA (0X48000000)void led_on(void)
{*(volatile unsigned int *)0x4800000 = *(volatile unsigned int *)0x4800000 | 1 << i
}
 * 二.C语言访问存储器* 	1.读存储器* 		data = *ADDR* 	2.写存储器* 	 	*ADDR = data*/

3.其它方法

各个芯片厂家提供的SDK, 其本质就是我上面说的那个, 将地址转换位C语言中的指针, 封装成宏, 结构体等等, 提供接口, 提升开发效率。


三、STM32的启动流程


1.引导加载程序(Boot Loard)

        是芯片厂家固化在IROM(内部存储器)的一段代码, 可以和windows中的BIOS对比学, 作用是引导cpu执行程序的, 初始化软硬件, 接着该段程序会去读boot引脚的电平状态, 确定程序的入口地址在哪

2.STM32G431RBT6的启动流程分析

        上面我们说, cpu之说一能控制硬件, 是因为其有读写存储器的能力, stm32是一个32位的单片机, 那是不是其能够寻址的范围就是0-4G, 这些空间内的存储器都是cpu能够访问到的,芯片厂家会对ARM架构的cpu给出的地址映射范围加上自己的外设。所谓的存储器映射其实就是给存储器分配地址的过程。

图解:

跳到flash之后, 开头的前两条指令一般都是固定的, 第一条指令, 赋值cpu内部MSP寄存器的值, 指定主栈的地址, 第二条指令是Reset_Handler这个函数的入口地址, 将这个函数的地址值给CPU内部的PC寄存器, 这样cpu就会去Reset_Handler函数对用的地址空间内取指执行了。

3.stm32启动代码详解

给大家写写注释!

;*******************************************************************************
;* @File Name          : startup_stm32g431xx.s
;* @Author             : MCD Application Team
;* @Brief              : Vector table for MDK-ARM toolchain
;*******************************************************************************
;* Description        : STM32G431xx Mainstream devices vector table for
;*                      MDK-ARM toolchain.
;*                      This module performs:
;*                      - Set the initial SP
;*                      - Set the initial PC == Reset_Handler
;*                      - Set the vector table entries with the exceptions ISR address
;*                      - Branches to __main in the C library (which eventually
;*                        calls main()).
;*                      After Reset the Cortex-M4 processor is in Thread mode,
;*                      priority is Privileged, and the Stack is set to Main.
;********************************************************************************
;* @attention
;*
;* Copyright (c) 2019 STMicroelectronics.
;* All rights reserved.
;*
;* This software is licensed under terms that can be found in the LICENSE file
;* in the root directory of this software component.
;* If no LICENSE file comes with this software, it is provided AS-IS.
;
;*******************************************************************************
;* <<< Use Configuration Wizard in Context Menu >>>
;
; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>@EQU指令,类似C语言的宏
Stack_Size		EQU     0x400          @定义了一个内存区域,名字STACK,后面是一些属性,没有初始化、可读可写、按照2^3对齐,提高访问效率AREA    STACK, NOINIT, READWRITE, ALIGN=3@用于分配一个连续的地址空间
Stack_Mem       SPACE   Stack_Size
__initial_sp    @该空间的其实地址, 也就是栈的起始地址; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>@和上面栈的定义类似, 如果没有用到malloc relloc calloc类似的函数,可以删除
Heap_Size      EQU     0x200AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit@伪指令, 告诉编译器按照8字节对齐PRESERVE8@使用的是thumb指令THUMB; Vector Table Mapped to Address 0 at Reset@开辟一段空间, 名字讲座reset,存放指令的,只能读AREA    RESET, DATA, READONLY@export,导出的意思,让别的.c和.s文件能够使用这个符号EXPORT  __Vectors EXPORT  __Vectors_EndEXPORT  __Vectors_Size@一个标号,用来占位置的
@DCD,声明一个4个字节的变量
@看第一条和第二条指令, 就是msp的值和即将要执行的代码
__Vectors       DCD     __initial_sp               ; Top of StackDCD     Reset_Handler              ; Reset HandlerDCD     NMI_Handler                ; NMI HandlerDCD     HardFault_Handler          ; Hard Fault HandlerDCD     MemManage_Handler          ; MPU Fault HandlerDCD     BusFault_Handler           ; Bus Fault HandlerDCD     UsageFault_Handler         ; Usage Fault HandlerDCD     0                          ; ReservedDCD     0                          ; ReservedDCD     0                          ; ReservedDCD     0                          ; ReservedDCD     SVC_Handler                ; SVCall HandlerDCD     DebugMon_Handler           ; Debug Monitor HandlerDCD     0                          ; ReservedDCD     PendSV_Handler             ; PendSV HandlerDCD     SysTick_Handler            ; SysTick Handler; External InterruptsDCD     WWDG_IRQHandler                   ; Window WatchDogDCD     PVD_PVM_IRQHandler                ; PVD/PVM1/PVM2/PVM3/PVM4 through EXTI Line detectionDCD     RTC_TAMP_LSECSS_IRQHandler        ; RTC, TAMP and RCC LSE_CSS through the EXTI lineDCD     RTC_WKUP_IRQHandler               ; RTC Wakeup through the EXTI lineDCD     FLASH_IRQHandler                  ; FLASHDCD     RCC_IRQHandler                    ; RCCDCD     EXTI0_IRQHandler                  ; EXTI Line0DCD     EXTI1_IRQHandler                  ; EXTI Line1DCD     EXTI2_IRQHandler                  ; EXTI Line2DCD     EXTI3_IRQHandler                  ; EXTI Line3DCD     EXTI4_IRQHandler                  ; EXTI Line4DCD     DMA1_Channel1_IRQHandler          ; DMA1 Channel 1DCD     DMA1_Channel2_IRQHandler          ; DMA1 Channel 2DCD     DMA1_Channel3_IRQHandler          ; DMA1 Channel 3DCD     DMA1_Channel4_IRQHandler          ; DMA1 Channel 4DCD     DMA1_Channel5_IRQHandler          ; DMA1 Channel 5DCD     DMA1_Channel6_IRQHandler          ; DMA1 Channel 6DCD     0                                 ; ReservedDCD     ADC1_2_IRQHandler                 ; ADC1 and ADC2DCD     USB_HP_IRQHandler                 ; USB Device High PriorityDCD     USB_LP_IRQHandler                 ; USB Device Low PriorityDCD     FDCAN1_IT0_IRQHandler             ; FDCAN1 interrupt line 0DCD     FDCAN1_IT1_IRQHandler             ; FDCAN1 interrupt line 1DCD     EXTI9_5_IRQHandler                ; External Line[9:5]sDCD     TIM1_BRK_TIM15_IRQHandler         ; TIM1 Break, Transition error, Index error and TIM15DCD     TIM1_UP_TIM16_IRQHandler          ; TIM1 Update and TIM16DCD     TIM1_TRG_COM_TIM17_IRQHandler     ; TIM1 Trigger, Commutation, Direction change, Index and TIM17DCD     TIM1_CC_IRQHandler                ; TIM1 Capture CompareDCD     TIM2_IRQHandler                   ; TIM2DCD     TIM3_IRQHandler                   ; TIM3DCD     TIM4_IRQHandler                   ; TIM4DCD     I2C1_EV_IRQHandler                ; I2C1 EventDCD     I2C1_ER_IRQHandler                ; I2C1 ErrorDCD     I2C2_EV_IRQHandler                ; I2C2 EventDCD     I2C2_ER_IRQHandler                ; I2C2 ErrorDCD     SPI1_IRQHandler                   ; SPI1DCD     SPI2_IRQHandler                   ; SPI2DCD     USART1_IRQHandler                 ; USART1DCD     USART2_IRQHandler                 ; USART2DCD     USART3_IRQHandler                 ; USART3DCD     EXTI15_10_IRQHandler              ; External Line[15:10]DCD     RTC_Alarm_IRQHandler              ; RTC Alarm (A and B) through EXTI LineDCD     USBWakeUp_IRQHandler              ; USB Wakeup through EXTI lineDCD     TIM8_BRK_IRQHandler               ; TIM8 Break, Transition error and Index error InterruptDCD     TIM8_UP_IRQHandler                ; TIM8 Update InterruptDCD     TIM8_TRG_COM_IRQHandler           ; TIM8 Trigger, Commutation, Direction change and Index InterruptDCD     TIM8_CC_IRQHandler                ; TIM8 Capture Compare InterruptDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     LPTIM1_IRQHandler                 ; LP TIM1 interruptDCD     0                                 ; ReservedDCD     SPI3_IRQHandler                   ; SPI3DCD     UART4_IRQHandler                  ; UART4DCD     0                                 ; ReservedDCD     TIM6_DAC_IRQHandler               ; TIM6 and DAC1&3 underrun errorsDCD     TIM7_IRQHandler                   ; TIM7DCD     DMA2_Channel1_IRQHandler          ; DMA2 Channel 1DCD     DMA2_Channel2_IRQHandler          ; DMA2 Channel 2DCD     DMA2_Channel3_IRQHandler          ; DMA2 Channel 3DCD     DMA2_Channel4_IRQHandler          ; DMA2 Channel 4DCD     DMA2_Channel5_IRQHandler          ; DMA2 Channel 5DCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     UCPD1_IRQHandler                  ; UCPD1DCD     COMP1_2_3_IRQHandler              ; COMP1, COMP2 and COMP3DCD     COMP4_IRQHandler                  ; COMP4DCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     CRS_IRQHandler                    ; CRS InterruptDCD     SAI1_IRQHandler                   ; Serial Audio Interface 1 global interruptDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     FPU_IRQHandler                    ; FPUDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     RNG_IRQHandler                    ; RNG global interruptDCD     LPUART1_IRQHandler                ; LP UART 1 interruptDCD     I2C3_EV_IRQHandler                ; I2C3 EventDCD     I2C3_ER_IRQHandler                ; I2C3 ErrorDCD     DMAMUX_OVR_IRQHandler             ; DMAMUX overrun global interruptDCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     DMA2_Channel6_IRQHandler          ; DMA2 Channel 6DCD     0                                 ; ReservedDCD     0                                 ; ReservedDCD     CORDIC_IRQHandler                 ; CORDICDCD     FMAC_IRQHandler                   ; FMAC__Vectors_End@计算出向量表的大小
__Vectors_Size  EQU  __Vectors_End - __VectorsAREA    |.text|, CODE, READONLY@复位函数的入口
Reset_Handler    PROC       @proc, 可以看作是C语言中的{ , endp可以看作是}EXPORT  Reset_Handler             [WEAK]IMPORT  SystemInit   @导入别的文件中的这个符号IMPORT  __main       @导入编译器生成的__main函数, 具体作用后面说@将SystemInit函数的地址加载到R0寄存器LDR     R0, =SystemInit@跳转到R0中的地址出执行, 保存返回地址, 以便执行完SystemInit函数后返回到下一条指令执行BLX     R0@加载__main的地址到R0寄存器LDR     R0, =__main@跳转到R0寄存器中的地址执行,不返回BX      R0ENDP; Dummy Exception Handlers (infinite loops which can be modified)@下面就是各个异常的默认处理, 都是 [WEAK]虚符号, 当出现强符号的时候会覆盖掉它
NMI_Handler     PROCEXPORT  NMI_Handler                [WEAK]B       .ENDP
HardFault_Handler\PROCEXPORT  HardFault_Handler          [WEAK]B       .ENDP
MemManage_Handler\PROCEXPORT  MemManage_Handler          [WEAK]B       .ENDP
BusFault_Handler\PROCEXPORT  BusFault_Handler           [WEAK]B       .ENDP
UsageFault_Handler\PROCEXPORT  UsageFault_Handler         [WEAK]B       .ENDP
SVC_Handler     PROCEXPORT  SVC_Handler                [WEAK]B       .ENDP
DebugMon_Handler\PROCEXPORT  DebugMon_Handler           [WEAK]B       .ENDP
PendSV_Handler  PROCEXPORT  PendSV_Handler             [WEAK]B       .ENDP
SysTick_Handler PROCEXPORT  SysTick_Handler            [WEAK]B       .ENDPDefault_Handler PROCEXPORT     WWDG_IRQHandler                   [WEAK]EXPORT     PVD_PVM_IRQHandler                [WEAK]EXPORT     RTC_TAMP_LSECSS_IRQHandler        [WEAK]EXPORT     RTC_WKUP_IRQHandler               [WEAK]EXPORT     FLASH_IRQHandler                  [WEAK]EXPORT     RCC_IRQHandler                    [WEAK]EXPORT     EXTI0_IRQHandler                  [WEAK]EXPORT     EXTI1_IRQHandler                  [WEAK]EXPORT     EXTI2_IRQHandler                  [WEAK]EXPORT     EXTI3_IRQHandler                  [WEAK]EXPORT     EXTI4_IRQHandler                  [WEAK]EXPORT     DMA1_Channel1_IRQHandler          [WEAK]EXPORT     DMA1_Channel2_IRQHandler          [WEAK]EXPORT     DMA1_Channel3_IRQHandler          [WEAK]EXPORT     DMA1_Channel4_IRQHandler          [WEAK]EXPORT     DMA1_Channel5_IRQHandler          [WEAK]EXPORT     DMA1_Channel6_IRQHandler          [WEAK]EXPORT     ADC1_2_IRQHandler                 [WEAK]EXPORT     USB_HP_IRQHandler                 [WEAK]EXPORT     USB_LP_IRQHandler                 [WEAK]EXPORT     FDCAN1_IT0_IRQHandler             [WEAK]EXPORT     FDCAN1_IT1_IRQHandler             [WEAK]EXPORT     EXTI9_5_IRQHandler                [WEAK]EXPORT     TIM1_BRK_TIM15_IRQHandler         [WEAK]EXPORT     TIM1_UP_TIM16_IRQHandler          [WEAK]EXPORT     TIM1_TRG_COM_TIM17_IRQHandler     [WEAK]EXPORT     TIM1_CC_IRQHandler                [WEAK]EXPORT     TIM2_IRQHandler                   [WEAK]EXPORT     TIM3_IRQHandler                   [WEAK]EXPORT     TIM4_IRQHandler                   [WEAK]EXPORT     I2C1_EV_IRQHandler                [WEAK]EXPORT     I2C1_ER_IRQHandler                [WEAK]EXPORT     I2C2_EV_IRQHandler                [WEAK]EXPORT     I2C2_ER_IRQHandler                [WEAK]EXPORT     SPI1_IRQHandler                   [WEAK]EXPORT     SPI2_IRQHandler                   [WEAK]EXPORT     USART1_IRQHandler                 [WEAK]EXPORT     USART2_IRQHandler                 [WEAK]EXPORT     USART3_IRQHandler                 [WEAK]EXPORT     EXTI15_10_IRQHandler              [WEAK]EXPORT     RTC_Alarm_IRQHandler              [WEAK]EXPORT     USBWakeUp_IRQHandler              [WEAK]EXPORT     TIM8_BRK_IRQHandler               [WEAK]EXPORT     TIM8_UP_IRQHandler                [WEAK]EXPORT     TIM8_TRG_COM_IRQHandler           [WEAK]EXPORT     TIM8_CC_IRQHandler                [WEAK]EXPORT     LPTIM1_IRQHandler                 [WEAK]EXPORT     SPI3_IRQHandler                   [WEAK]EXPORT     UART4_IRQHandler                  [WEAK]EXPORT     TIM6_DAC_IRQHandler               [WEAK]EXPORT     TIM7_IRQHandler                   [WEAK]EXPORT     DMA2_Channel1_IRQHandler          [WEAK]EXPORT     DMA2_Channel2_IRQHandler          [WEAK]EXPORT     DMA2_Channel3_IRQHandler          [WEAK]EXPORT     DMA2_Channel4_IRQHandler          [WEAK]EXPORT     DMA2_Channel5_IRQHandler          [WEAK]EXPORT     UCPD1_IRQHandler                  [WEAK]EXPORT     COMP1_2_3_IRQHandler              [WEAK]EXPORT     COMP4_IRQHandler                  [WEAK]EXPORT     CRS_IRQHandler                    [WEAK]EXPORT     SAI1_IRQHandler                   [WEAK]EXPORT     FPU_IRQHandler                    [WEAK]EXPORT     RNG_IRQHandler                    [WEAK]EXPORT     LPUART1_IRQHandler                [WEAK]EXPORT     I2C3_EV_IRQHandler                [WEAK]EXPORT     I2C3_ER_IRQHandler                [WEAK]EXPORT     DMAMUX_OVR_IRQHandler             [WEAK]EXPORT     DMA2_Channel6_IRQHandler          [WEAK]EXPORT     CORDIC_IRQHandler                 [WEAK]EXPORT     FMAC_IRQHandler                   [WEAK]WWDG_IRQHandler
PVD_PVM_IRQHandler
RTC_TAMP_LSECSS_IRQHandler
RTC_WKUP_IRQHandler
FLASH_IRQHandler
RCC_IRQHandler
EXTI0_IRQHandler
EXTI1_IRQHandler
EXTI2_IRQHandler
EXTI3_IRQHandler
EXTI4_IRQHandler
DMA1_Channel1_IRQHandler
DMA1_Channel2_IRQHandler
DMA1_Channel3_IRQHandler
DMA1_Channel4_IRQHandler
DMA1_Channel5_IRQHandler
DMA1_Channel6_IRQHandler
ADC1_2_IRQHandler
USB_HP_IRQHandler
USB_LP_IRQHandler
FDCAN1_IT0_IRQHandler
FDCAN1_IT1_IRQHandler
EXTI9_5_IRQHandler
TIM1_BRK_TIM15_IRQHandler
TIM1_UP_TIM16_IRQHandler
TIM1_TRG_COM_TIM17_IRQHandler
TIM1_CC_IRQHandler
TIM2_IRQHandler
TIM3_IRQHandler
TIM4_IRQHandler
I2C1_EV_IRQHandler
I2C1_ER_IRQHandler
I2C2_EV_IRQHandler
I2C2_ER_IRQHandler
SPI1_IRQHandler
SPI2_IRQHandler
USART1_IRQHandler
USART2_IRQHandler
USART3_IRQHandler
EXTI15_10_IRQHandler
RTC_Alarm_IRQHandler
USBWakeUp_IRQHandler
TIM8_BRK_IRQHandler
TIM8_UP_IRQHandler
TIM8_TRG_COM_IRQHandler
TIM8_CC_IRQHandler
LPTIM1_IRQHandler
SPI3_IRQHandler
UART4_IRQHandler
TIM6_DAC_IRQHandler
TIM7_IRQHandler
DMA2_Channel1_IRQHandler
DMA2_Channel2_IRQHandler
DMA2_Channel3_IRQHandler
DMA2_Channel4_IRQHandler
DMA2_Channel5_IRQHandler
UCPD1_IRQHandler
COMP1_2_3_IRQHandler
COMP4_IRQHandler
CRS_IRQHandler
SAI1_IRQHandler
FPU_IRQHandler
RNG_IRQHandler
LPUART1_IRQHandler
I2C3_EV_IRQHandler
I2C3_ER_IRQHandler
DMAMUX_OVR_IRQHandler
DMA2_Channel6_IRQHandler
CORDIC_IRQHandler
FMAC_IRQHandlerB       .ENDPALIGN;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************IF      :DEF:__MICROLIBEXPORT  __initial_spEXPORT  __heap_baseEXPORT  __heap_limitELSEIMPORT  __use_two_region_memoryEXPORT  __user_initial_stackheap__user_initial_stackheapLDR     R0, =  Heap_MemLDR     R1, =(Stack_Mem + Stack_Size)LDR     R2, = (Heap_Mem +  Heap_Size)LDR     R3, = Stack_MemBX      LRALIGNENDIFEND

  • 编译器的__main函数干了那些事

在 STM32 的启动代码中,`__main` 是一个由编译器生成的函数,它是程序的入口点。`__main` 函数在启动代码中被调用,在处理器初始化和启动期间执行一些必要的任务,然后进入主程序。

`__main` 函数通常会执行以下几个重要的任务:

1. 设置堆栈指针(Stack Pointer,SP):在启动代码中,首先会设置堆栈指针,即将 SP 寄存器设置为存放堆栈顶端地址的值。通过这个设置,程序可以正确使用堆栈来保存临时变量、函数调用的返回地址等。

2. 初始化数据段:启动代码将会负责把程序的初始化数据段(.data 段)从 ROM 复制到 RAM。这包括全局变量和静态变量的初始值。这样,程序在执行时就可以使用这些变量了。 3. 清零未初始化数据段:启动代码也会负责把程序的未初始化数据段(.bss 段)清零,以确保所有未初始化的全局变量和静态变量都被初始化为 0 值。

4. 初始化系统时钟和外设:启动代码可能会进行一些初始化工作,如配置系统时钟和外设的寄存器。这些初始化工作可能包括配置时钟源、设置时钟分频器、配置中断向量表等。

5. 调用 C/C++ 运行时库的初始化函数:如果使用了 C/C++ 运行时库,启动代码会在主程序执行之前调用一些运行时库的初始化函数,以确保所需的运行环境被正确设置。

6. 调用主程序(`main` 函数):启动代码结束之前,会最后调用主程序函数 `main`,开始执行主要的应用逻辑。 总的来说,`__main` 函数在 STM32 启动代码中负责执行一系列的初始化工作,以确保系统正确地启动并进入主程序。这些初始化工作包括设置堆栈指针、初始化数据段、清零未初始化数据段、初始化系统时钟和外设等。

然后,`__main` 函数会调用主程序函数 `main`,将控制权转交给主程序,开始执行应用逻辑。

够了够了, 再多就撑爆了, 希望大家有收获, 不懂异常向量表的作用的可以去翻翻我老久之前写的文章http://t.csdnimg.cn/Ac0ws

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/731794.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自研cloud框架专题–web模块(三)

项目特点一:框架集成 1.引入核心依赖2.配置相关功能 二:功能介绍 1.swagger支持并提供swagger快速配置2.knife增强swagger支持3.全局请求参数校验(Validation)支持4.字段脱敏支持5.默认jackson序列化6.xss,cors支持7.访问日志支持8.全局异常处理,统一返回结果9.系统关键及常用信…

数据结构之deque双端队列

一、概念&#xff1a; 众所周知&#xff0c;数据结构是用来存储数据&#xff0c;deque也不例外&#xff0c;他是集结了队列和栈的性质而成的结构&#xff0c;他几乎拥有所有数据结构能有的操作&#xff0c;看似已经大杀四方&#xff0c;可实际情况如何呢&#xff0c;那就带者这…

Day 8.TCP包头和HTTP

TCP包头 1.序号&#xff1a;发送端发送数据包的编号 2.确认号&#xff1a;已经确认接收到的数据的编号&#xff08;只有当ACK为1时、确认号才有用&#xff09;&#xff1b; TCP为什么安全可靠 1.在通信前建立三次握手 SYP SYPACK ACK 2.在通信过程中通过序列号和确认号和…

前端javascript的DOM对象操作技巧,全场景解析

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属的专栏&#xff1a;前端泛海 景天的主页&#xff1a;景天科技苑 文章目录 1.js的DOM介绍2.节点元素层级关系3.通过js修改&#xff0c;清空节点…

【棘手问题】Spring JPA一级缓存导致获取不到数据库表中的最新数据,对象地址不发生改变

【棘手问题】Spring JPA一级缓存导致获取不到数据库表中的最新数据&#xff0c;对象地址不发生改变 一、问题背景二、解决步骤2.1 debug2.2 原因分析2.2.1 数据步骤2.2.2 大模型解释2.2.3 解释举例2.2.4 关键函数 2.3 解决方案 三、Spring JPA一级缓存 一、问题背景 项目的数据…

STM32 通过Modbus协议更改内部Flash(模仿EEPROM)的运行参数

main.c测试 uint8_t uart1RxBuf[64]{0};uint8_t Adc1ConvEnd0; uint8_t Adc2ConvEnd0;int main(void) {/* USER CODE BEGIN 1 *//* USER CODE END 1 *//* MCU Configuration--------------------------------------------------------*//* Reset of all peripherals, Initial…

C++ 智能指针深度剖析

文章目录 1. 前言2. 为什么需要智能指针&#xff1f;3. 内存泄漏3.1 内存泄漏的概念及危害3.2 内存泄漏的分类3.3 如何检测内存泄漏3.4 如何避免内存泄漏 4. 智能指针的使用及原理4.1 RAII思想4.2 智能指针的原理4.3 C智能指针发展历史4.4 std::auto_ptr4.5 std::unique_ptr4.6…

掌握MySQL,看完这篇文章就够了!

1. MySQL MySQL是一种广泛使用的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;由瑞典的MySQL AB公司开发&#xff0c;目前属于甲骨文公司&#xff08;Oracle Corporation&#xff09;。 MySQL使用结构化查询语言&#xff08;SQL&#xff09;进行数据库管理…

C++的面向诗篇:类的叙事与对象的旋律

个人主页&#xff1a;日刷百题 系列专栏&#xff1a;〖C/C小游戏〗〖Linux〗〖数据结构〗 〖C语言〗 &#x1f30e;欢迎各位→点赞&#x1f44d;收藏⭐️留言&#x1f4dd; ​ ​ 一、面向对象的定义 学习C语言时&#xff0c;我们就经常听说C语言是面向过程的&#xff0c;…

[nlp入门论文精读] | Transformer

写在前面 最近工作从CV转向了NLP&#xff0c;于是空余时间便跟着哔哩哔哩李沐老师的视频学习。其实研一NLP课程讲论文的时候&#xff0c;我们小组就选择了经典的Attention和Bert&#xff0c;但还有很多细节并不完全理解&#xff0c;实际使用时也很困惑。 因此这个系列就来记…

红队专题-开源漏扫-巡风xunfeng源码剖析与应用

开源漏扫-巡风xunfeng 介绍主体两部分:网络资产识别引擎,漏洞检测引擎。代码赏析插件编写JSON标示符Python脚本此外系统内嵌了辅助验证功能文件结构功能 模块添加IP三. 进行扫描在这里插入图片描述 ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/de587a6f6f694…

ai写作一键生成文章速度快

ai写作是一种基于人工智能技术的自动写作工具&#xff0c;它可以根据用户提供的主题或关键词&#xff0c;快速一键生成文章。与传统的手动写作相比&#xff0c;ai写作的速度更快&#xff0c;效率更高。下面小编就带大家一起来见识下ai写作一键生成文章的速度是如何之快&#xf…

【CSP试题回顾】202012-1-期末预测之安全指数

CSP-202012-1-期末预测之安全指数 解题代码 #include <iostream> #include <algorithm> using namespace std;int n, sum;int main() {cin >> n;for (int i 0; i < n; i){int w, s;cin >> w >> s;sum w * s;}sum max(sum, 0);cout <&…

Electron-builder打包安装包——编译篇

突然有一天想打包个桌面程序&#xff0c;没有打包过&#xff0c;经过九牛二虎之力终于打包出来&#xff0c;在此感谢那些热于分享的前辈&#xff01; 本篇只讲打包运行和出现的问题 一、准备工作&#xff1a;提前下载相关资源包&#xff0c;否则在国内环境下可能因为网络问题…

ECharts 简要介绍及简单实例代码

ECharts 是一个使用 JavaScript 实现的开源可视化库&#xff0c;涵盖各行业图表&#xff0c;满足各种需求。 ECharts 提供了丰富的图表类型和交互能力&#xff0c;使用户能够通过简单的配置生成各种各样的图表&#xff0c;包括但不限于折线图、柱状图、散点图、饼图、雷达图、…

Lwip之TCP服务端示例记录(1对多)

前言 实现多个客户端同时连接初步代码结构已经实现完成(通过轮训的方式) // // Created by shchl on 2024/3/8. // #if 1#include <string.h> #include "lwip/api.h" #include "FreeRTOS.h" #include "task.h" #include "usart.h&…

群辉docker安装sql server

安装步骤 开启群辉 SSH&#xff0c;通过 SSH 工具连接到群辉&#xff0c;运行下面的命令拉取mssql 2019 镜像 sudo docker pull mcr.microsoft.com/mssql/server:2019-latest然后在 docker 中就可以看到该镜像&#xff1a; 在群晖 docker 共享文件夹中创建 mssql2009 文件夹 …

Qt插件之输入法插件的构建和使用(二)

文章目录 主键盘搭建Google开源引擎音节分割工具类参考项目下载搭建好各个基础控件之后,就可以开发输入法的主界面和引擎了,这也是输入法的核心。 主键盘搭建 输入法的主界面本质上是一个QStackedWidget容器,将各个类型的输入键盘插入到容器中,然后根据业务需要切换不同的…

金现代产品方案部部长王宁,将出席“ISIG-低代码/零代码技术与应用发展峰会”

3月16日&#xff0c;第四届「ISIG中国产业智能大会」将在上海中庚聚龙酒店拉开序幕。本届大会由苏州市金融科技协会指导&#xff0c;企智未来科技&#xff08;LowCode低码时代、RPA中国、AIGC开放社区&#xff09;主办。大会旨在聚合每一位产业成员的力量&#xff0c;深入探索低…

生产管理MES系统在卫浴企业中的应用

在卫浴企业的制造过程中&#xff0c;实现透明车间管理是一个旨在提升效率、质量和可视性的重要目标。MES系统可以在卫浴企业中帮助打造透明车间&#xff0c;提升生产管理的效率和可视性。具体能实现哪些管理呢&#xff1f; 实时监控生产状态&#xff1a; MES系统可以实时监控车…