解读startup_stm32f407xx.s和STM32F407x_FLASH.ld文件

参考博文:《MCU的内部架构与程序运行原理》部分内容笔记

在VS Code软件中安装插件

在VS Code软件中安装Arm Assembly和LinkerScript插件,可以让startup_stm32f407xx.s和STM32F407ZGTx_FLASH.ld文件的代码进行高亮显示。
在这里插入图片描述

STM32F407x_FLASH.ld

存储区域地址信息的定义

栈段的地址空间位于RAM区域的末尾,且由高地址往低地址生长
_estack代表栈段的首地址,其地址为RAM区域的首地址加上RAM区域的长度,即RAM区域的末地址
_Min_Heap_Size指的是设置的堆的大小,_Min_Stack_Size指的是设置的栈的大小
(可以由自己设置)

/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM);    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */

MEMORY:对存储区域进行设置
定义信息包括区域的首地址ORIGIN、大小LENGTH、读写可执行权限(x可执行,r可读,w可写)
STM32F407系列,存储区域分为1M的FLASH区域和192KB的SRAM区域(包含64KB的CCM data RAM)

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
CCMRAM (xrw)      : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 1024K
}

各个程序段在存储区域的排布

SECTIONS:设置程序中各个段放在指定的地址空间,每个段都按照先后顺序依次在地址空间排布

SECTIONS设置的各个段

——.isr_vector:包含了中断向量表信息,在.s启动文件中定义,放置在FLASH区域的首地址
——.text:代码段,存放程序代码和其他数据,紧跟在.isr_vector段后面
——.rodata:只读数据段,,存放常量数据,紧跟在.text段后面

——.data:初始化数据段,存放已初始化且非零的全局变量,紧跟在.rodata段后面,但在程序运行时被加载到RAM区域的首地址
——.bss:未初始化数据段,存放已初始化为零或者没有初始化的全局变量,紧跟在.data段后面
——.user_heap_stack:位于.bss段后面,工具链自动检查堆栈大小是否溢出RAM区域空间

SECTIONS涉及的变量

——_etext:.text段的末尾地址
——_sdata:.data段的首地址
——_edata:.data段的末尾地址
——_sbss:.bss段的首地址
——_ebss:.bss段的末尾地址
——_sidata:.data段被加载到RAM区域的首地址

/* 定义各个程序段 */
SECTIONS
{
    /* 启动代码 */
    .isr_vector :
    {
        . = ALIGN(4);           /* .代表当前地址 ALIGN(4)代表4字节地址对齐*/
        KEEP(*(.isr_vector))    /* KEEP指示链接器保留指定的段,*代表匹配所有输入段,(.isr_vector)是要匹配的段名 */
        . = ALIGN(4);             
    } >FLASH                    /* >代表存储到哪个区域 */

    /* 程序代码和其他数据 */
    .text :
    {
        . = ALIGN(4); 
        *(.text)                /* 匹配.text段,不使用KEEP链接器指令,可能被优化掉 */
        *(.text*)               /* 匹配.text*段,这里的*代表通配符 */
        *(.glue_7)              /* 匹配.glue_7段,.glue_7段是从ARM模式切换到Thumb模式的代码 */
        *(.glue_7t)             /* 匹配.glue_7t段,.glue_7t段是从Thumb模式切换到ARM模式的代码 */
        *(.eh_frame)            /* 匹配.eh_frame段,.eh_frame段通常包含异常处理所需的信息 */
        
        KEEP(*(.init))          /* 匹配.init段,.init段包含程序初始化代码 */
        KEEP(*(.fini))          /* 匹配.fini段,.fini段包含程序终止代码 */

        . = ALIGN(4);   
        _etext = .;             /* 定义一个全局符号表示.text段的末尾地址 */
    } >FLASH

    /* 常量数据 */
    .rodata :
    {
        . = ALIGN(4);        
        *(.rodata)              /* 匹配.rodata段 */
        *(.rodata*)             /* 匹配.rodata*段 */
        . = ALIGN(4);
    } >FLASH 
}
 _sidata = LOADADDR(.data);      /* _sidata指的是.data段被加载到RAM区域后的首地址 */

    /* 初始化数据 */
    .data :
    {
        . = ALIGN(4);
        _sdata = .;
        *(.data)                    /* 匹配.data段 */
        *(.data*)                   /* 匹配.data*段 */
        . = ALIGN(4);
        _edata = .;
    } >RAM AT> FLASH                /* 表示该段存储在FLASH区域,但运行时被加载到RAM区域,该加载操作是在.s启动文件中执行的 */

    _siccmram = LOADADDR(.ccmram);

    .ccmram :
    {
        . = ALIGN(4);
        _sccmram = .;
        *(.ccmram)
        *(.ccmram*)
        . = ALIGN(4);
        _eccmram = .;
    } >CCMRAM AT> FLASH

    /* 未初始化数据 */
    .bss :
    {
        . = ALIGN(4);
        _sbss = .;
        __bss_start = _sbss;
        *(.bss)
        *(.bss*)
        *(COMMON)
        . = ALIGN(4);
        _ebss = .;
        __bss_end = _ebss;
    } >RAM

    /* 用于检查堆栈大小是否溢出RAM区域空间 */
    .user_heap_stack :
    {
        . = ALIGN(8);
        PROVIDE (end = .);
        provide (_end = .);
        . = . + _Min_Heap_Size;
        . = . + _Min_Stack_Size;
        . = ALIGN(8);
    } >RAM

程序运行的入口

/* Entry Point */
ENTRY(Reset_Handler)

整个文件重点关注的地方

——想要分配的堆栈空间大小(_Min_Heap_Size和_Min_Stack_Size),
对此我的理解是:当设置的_Min_Heap_Size和_Min_Stack_Size的值小于程序代码中使用的堆栈空间大小,编译工具链会报错或警告;所以要合理设置_Min_Heap_Size和_Min_Stack_Size的值;过大也可能会超出RAM的容量
——芯片内部存储空间(MEMORY),不同的芯片型号则需要修改
——可以把.data段加载到CCMRAM区域,但需要修改启动代码关于从FLASH区域加载数据到RAM区域的代码
——修改复位处理函数名称(Reset_Handler,如果你想这么做的话,但还是不要的好!)

startup_stm32f407xx.s

配置汇编环境

;告诉汇编器使用统一的语法规则
.syntax unified
;指定目标处理器为Cortex-M4
.cpu cortex-m4
;指定浮点运算单元为SoftVFP
.fpu softvfp
;指定使用thumb指令集
.thumb

Reset_Handler复位处理函数

——将FLASH区域的.data数据段拷贝到RAM区域
——将RAM区域的.bss数据段清零
——调用时钟系统初始化函数和其他一系列初始化函数
——跳转到用户main函数

/* 创建一个代码段(.text)的子节,名为Reset_Handler */
.section .text.Reset_Handler
/* 声明Reset_Handler为弱符号 */
.weak Reset_Handler
/* 声明Reset_Handler为函数类型 */
.type Reset_Handler, %function
Reset_Handler:
    ldr sp, =_estack        /* 设置堆栈指针 */

/* 将数据段初始化程序从Flash复制到SRAM */
    ldr r0, =_sdata         /* 将_sdata的值存入r0 */
    ldr r1, =_edata         /* 将_edata的值存入r1 */
    ldr r2, =_sidata        /* 将_sidata的值存入r2 */
    movs r3, #0             /* 将立即数0存入r3 */
    b LoopCopyDataInit      /* 跳转到LoopCopyDataInit */

CopyDataInit:
    ldr r4, [r2,r3]         /* (r2的值加上r3的值)对应内存地址存放的值存入r4 */
    str r4, [r0,r3]         /* r4的值存入(r0的值加上r3的值)对应内存地址 */
    adds r3, r3, #4         /* 将r3的值加4存入r3 */

LoopCopyDataInit:   
    adds r4, r0, r3         /* 将r0的值和r3的值相加存入r4 */
    cmp r4, r1              /* 比较r4和r1的值,改变CPSR寄存器的标志位 */
    bcc CopyDataInit        /* 当r4比r1小时,发生跳转 */

    
/* 零填充bss段 */
    ldr r2, =_sbss
    ldr r4, =_ebss
    movs r3, #0
    b LoopFillZerobss

FillZerobss:
    str r3, [r2]
    adds r2, r2, #4

LoopFillZerobss:
    cmp r2, r4
    bcc FillZerobss

/* 调用时钟系统初始化函数 */
bl SystemInit
/* 调用静态构造函数 */
bl __libc_init_array
/* 调用应用程序的入口 */
bl main
/* bl指令将返回地址保存到lr寄存器中,然后跳转到指定的地址执行代码 */
/* bx指令跳转到保存到lr寄存器中的返回地址,继续执行原来的代码 */
bx lr
.size Reset_Handler, .-Reset_Handler

死循环Default_Handler函数

/* 创建一个代码段(.text)的子节Default_Handler,"a"表示该段是可分配的,"x"表示该段是可执行的,%progbits表示该段包含程序代码或数据 */
.section .text.Default_Handler,"ax",%progbits
Default_Handler:
Infinite_Loop:
    b Infinite_Loop
.size Default_Handler, .-Default_Handler

中断向量表以及默认中断处理函数

中断向量表

——中断向量表定义在.isr_vector段,保存着各个异常和外部中断处理函数的首地址

/* 创建一个.isr_vector的段,"a"表示该段是可分配的,%progbits表示该段包含程序代码或数据 */
.section .isr_vector,"a",%progbits
/* 声明ptfVectors为对象类型 */
.type ptfVectors, %object

ptfVectors:
    .word _estack                           
    .word Reset_Handler                         /* Reset */
    .word NMI_Handler                           /* Non maskable interrupt */
    .word HardFault_Handler                     /* All class of fault */
    .word MemManage_Handler                     /* Memory management */
    .word BusFault_Handler                      /* Pre-fetch fault,memory access fault */
    .word UsageFault_Handler                    /* Undefined instruction or illegal state */
    .word 0
    .word 0
    .word 0
    .word 0
    .word SVC_Handler                           /* System service call via SWI instruction */
    .word DebugMon_Handler                      /* Debug Monitor */
    .word 0 
    .word PendSV_Handler                        /* Pendable request for system service */
    .word SysTick_Handler                       /* System tick timer */

    /* 外部中断 */
    .word     WWDG_IRQHandler                   /* Window WatchDog              */                                        
    .word     PVD_IRQHandler                    /* PVD through EXTI Line detection */                        
    .word     TAMP_STAMP_IRQHandler             /* Tamper and TimeStamps through the EXTI line */            
    .word     RTC_WKUP_IRQHandler               /* RTC Wakeup through the EXTI line */                      
    .word     FLASH_IRQHandler                  /* FLASH                        */                                          
    .word     RCC_IRQHandler                    /* RCC                          */                                            
    .word     EXTI0_IRQHandler                  /* EXTI Line0                   */                        
    .word     EXTI1_IRQHandler                  /* EXTI Line1                   */                          
    .word     EXTI2_IRQHandler                  /* EXTI Line2                   */                          
    .word     EXTI3_IRQHandler                  /* EXTI Line3                   */                          
    .word     EXTI4_IRQHandler                  /* EXTI Line4                   */                          
    .word     DMA1_Stream0_IRQHandler           /* DMA1 Stream 0                */                  
    .word     DMA1_Stream1_IRQHandler           /* DMA1 Stream 1                */                   
    .word     DMA1_Stream2_IRQHandler           /* DMA1 Stream 2                */                   
    .word     DMA1_Stream3_IRQHandler           /* DMA1 Stream 3                */                   
    .word     DMA1_Stream4_IRQHandler           /* DMA1 Stream 4                */                   
    .word     DMA1_Stream5_IRQHandler           /* DMA1 Stream 5                */                   
    .word     DMA1_Stream6_IRQHandler           /* DMA1 Stream 6                */                   
    .word     ADC_IRQHandler                    /* ADC1, ADC2 and ADC3s         */                   
    .word     CAN1_TX_IRQHandler                /* CAN1 TX                      */                         
    .word     CAN1_RX0_IRQHandler               /* CAN1 RX0                     */                          
    .word     CAN1_RX1_IRQHandler               /* CAN1 RX1                     */                          
    .word     CAN1_SCE_IRQHandler               /* CAN1 SCE                     */                          
    .word     EXTI9_5_IRQHandler                /* External Line[9:5]s          */                          
    .word     TIM1_BRK_TIM9_IRQHandler          /* TIM1 Break and TIM9          */         
    .word     TIM1_UP_TIM10_IRQHandler          /* TIM1 Update and TIM10        */         
    .word     TIM1_TRG_COM_TIM11_IRQHandler     /* TIM1 Trigger and Commutation and TIM11 */
    .word     TIM1_CC_IRQHandler                /* TIM1 Capture Compare         */                          
    .word     TIM2_IRQHandler                   /* TIM2                         */                   
    .word     TIM3_IRQHandler                   /* TIM3                         */                   
    .word     TIM4_IRQHandler                   /* TIM4                         */                   
    .word     I2C1_EV_IRQHandler                /* I2C1 Event                   */                          
    .word     I2C1_ER_IRQHandler                /* I2C1 Error                   */                          
    .word     I2C2_EV_IRQHandler                /* I2C2 Event                   */                          
    .word     I2C2_ER_IRQHandler                /* I2C2 Error                   */                            
    .word     SPI1_IRQHandler                   /* SPI1                         */                   
    .word     SPI2_IRQHandler                   /* SPI2                         */                   
    .word     USART1_IRQHandler                 /* USART1                       */                   
    .word     USART2_IRQHandler                 /* USART2                       */                   
    .word     USART3_IRQHandler                 /* USART3                       */                   
    .word     EXTI15_10_IRQHandler              /* External Line[15:10]s        */                          
    .word     RTC_Alarm_IRQHandler              /* RTC Alarm (A and B) through EXTI Line */                 
    .word     OTG_FS_WKUP_IRQHandler            /* USB OTG FS Wakeup through EXTI line */                       
    .word     TIM8_BRK_TIM12_IRQHandler         /* TIM8 Break and TIM12         */         
    .word     TIM8_UP_TIM13_IRQHandler          /* TIM8 Update and TIM13        */         
    .word     TIM8_TRG_COM_TIM14_IRQHandler     /* TIM8 Trigger and Commutation and TIM14 */
    .word     TIM8_CC_IRQHandler                /* TIM8 Capture Compare         */                          
    .word     DMA1_Stream7_IRQHandler           /* DMA1 Stream7                 */                          
    .word     FSMC_IRQHandler                   /* FSMC                         */                   
    .word     SDIO_IRQHandler                   /* SDIO                         */                   
    .word     TIM5_IRQHandler                   /* TIM5                         */                   
    .word     SPI3_IRQHandler                   /* SPI3                         */                   
    .word     UART4_IRQHandler                  /* UART4                        */                   
    .word     UART5_IRQHandler                  /* UART5                        */                   
    .word     TIM6_DAC_IRQHandler               /* TIM6 and DAC1&2 underrun errors */                   
    .word     TIM7_IRQHandler                   /* TIM7                         */
    .word     DMA2_Stream0_IRQHandler           /* DMA2 Stream 0                */                   
    .word     DMA2_Stream1_IRQHandler           /* DMA2 Stream 1                */                   
    .word     DMA2_Stream2_IRQHandler           /* DMA2 Stream 2                */                   
    .word     DMA2_Stream3_IRQHandler           /* DMA2 Stream 3                */                   
    .word     DMA2_Stream4_IRQHandler           /* DMA2 Stream 4                */                   
    .word     ETH_IRQHandler                    /* Ethernet                     */                   
    .word     ETH_WKUP_IRQHandler               /* Ethernet Wakeup through EXTI line */                     
    .word     CAN2_TX_IRQHandler                /* CAN2 TX                      */                          
    .word     CAN2_RX0_IRQHandler               /* CAN2 RX0                     */                          
    .word     CAN2_RX1_IRQHandler               /* CAN2 RX1                     */                          
    .word     CAN2_SCE_IRQHandler               /* CAN2 SCE                     */                          
    .word     OTG_FS_IRQHandler                 /* USB OTG FS                   */                   
    .word     DMA2_Stream5_IRQHandler           /* DMA2 Stream 5                */                   
    .word     DMA2_Stream6_IRQHandler           /* DMA2 Stream 6                */                   
    .word     DMA2_Stream7_IRQHandler           /* DMA2 Stream 7                */                   
    .word     USART6_IRQHandler                 /* USART6                       */                    
    .word     I2C3_EV_IRQHandler                /* I2C3 event                   */                          
    .word     I2C3_ER_IRQHandler                /* I2C3 error                   */                          
    .word     OTG_HS_EP1_OUT_IRQHandler         /* USB OTG HS End Point 1 Out   */                   
    .word     OTG_HS_EP1_IN_IRQHandler          /* USB OTG HS End Point 1 In    */                   
    .word     OTG_HS_WKUP_IRQHandler            /* USB OTG HS Wakeup through EXTI */                         
    .word     OTG_HS_IRQHandler                 /* USB OTG HS                   */                   
    .word     DCMI_IRQHandler                   /* DCMI                         */                   
    .word     0                                 /* CRYP crypto                  */                   
    .word     HASH_RNG_IRQHandler               /* Hash and Rng                 */
    .word     FPU_IRQHandler                    /* FPU                          */

异常和外部中断的默认中断处理函数

——用户可以自己定义异常和外部中断的处理函数,若不定义,则执行处理函数时会执行这里的弱函数
——这里的弱函数实际调用的都是Default_Handler,而Default_Handler是一个死循环

 /* .thumb_set symbol,value 用于为value取一个别名 */
    .weak      NMI_Handler
    .thumb_set NMI_Handler,Default_Handler
    
    .weak      HardFault_Handler
    .thumb_set HardFault_Handler,Default_Handler
    
    .weak      MemManage_Handler
    .thumb_set MemManage_Handler,Default_Handler
    
    .weak      BusFault_Handler
    .thumb_set BusFault_Handler,Default_Handler

    .weak      UsageFault_Handler
    .thumb_set UsageFault_Handler,Default_Handler

    .weak      SVC_Handler
    .thumb_set SVC_Handler,Default_Handler

    .weak      DebugMon_Handler
    .thumb_set DebugMon_Handler,Default_Handler

    .weak      PendSV_Handler
    .thumb_set PendSV_Handler,Default_Handler

    .weak      SysTick_Handler
    .thumb_set SysTick_Handler,Default_Handler              
    
    .weak      WWDG_IRQHandler                   
    .thumb_set WWDG_IRQHandler,Default_Handler      
                    
    .weak      PVD_IRQHandler      
    .thumb_set PVD_IRQHandler,Default_Handler
                
    .weak      TAMP_STAMP_IRQHandler            
    .thumb_set TAMP_STAMP_IRQHandler,Default_Handler
                
    .weak      RTC_WKUP_IRQHandler                  
    .thumb_set RTC_WKUP_IRQHandler,Default_Handler
                
    .weak      FLASH_IRQHandler         
    .thumb_set FLASH_IRQHandler,Default_Handler
                    
    .weak      RCC_IRQHandler      
    .thumb_set RCC_IRQHandler,Default_Handler
                    
    .weak      EXTI0_IRQHandler         
    .thumb_set EXTI0_IRQHandler,Default_Handler
                    
    .weak      EXTI1_IRQHandler         
    .thumb_set EXTI1_IRQHandler,Default_Handler
                        
    .weak      EXTI2_IRQHandler         
    .thumb_set EXTI2_IRQHandler,Default_Handler 
                    
    .weak      EXTI3_IRQHandler         
    .thumb_set EXTI3_IRQHandler,Default_Handler
                            
    .weak      EXTI4_IRQHandler         
    .thumb_set EXTI4_IRQHandler,Default_Handler
                    
    .weak      DMA1_Stream0_IRQHandler               
    .thumb_set DMA1_Stream0_IRQHandler,Default_Handler
            
    .weak      DMA1_Stream1_IRQHandler               
    .thumb_set DMA1_Stream1_IRQHandler,Default_Handler
                    
    .weak      DMA1_Stream2_IRQHandler               
    .thumb_set DMA1_Stream2_IRQHandler,Default_Handler
                    
    .weak      DMA1_Stream3_IRQHandler               
    .thumb_set DMA1_Stream3_IRQHandler,Default_Handler 
                    
    .weak      DMA1_Stream4_IRQHandler              
    .thumb_set DMA1_Stream4_IRQHandler,Default_Handler
                    
    .weak      DMA1_Stream5_IRQHandler               
    .thumb_set DMA1_Stream5_IRQHandler,Default_Handler
                    
    .weak      DMA1_Stream6_IRQHandler               
    .thumb_set DMA1_Stream6_IRQHandler,Default_Handler
                    
    .weak      ADC_IRQHandler      
    .thumb_set ADC_IRQHandler,Default_Handler
                
    .weak      CAN1_TX_IRQHandler   
    .thumb_set CAN1_TX_IRQHandler,Default_Handler
                
    .weak      CAN1_RX0_IRQHandler                  
    .thumb_set CAN1_RX0_IRQHandler,Default_Handler
                            
    .weak      CAN1_RX1_IRQHandler                  
    .thumb_set CAN1_RX1_IRQHandler,Default_Handler
                
    .weak      CAN1_SCE_IRQHandler                  
    .thumb_set CAN1_SCE_IRQHandler,Default_Handler
                
    .weak      EXTI9_5_IRQHandler   
    .thumb_set EXTI9_5_IRQHandler,Default_Handler
                
    .weak      TIM1_BRK_TIM9_IRQHandler            
    .thumb_set TIM1_BRK_TIM9_IRQHandler,Default_Handler
                
    .weak      TIM1_UP_TIM10_IRQHandler            
    .thumb_set TIM1_UP_TIM10_IRQHandler,Default_Handler
        
    .weak      TIM1_TRG_COM_TIM11_IRQHandler      
    .thumb_set TIM1_TRG_COM_TIM11_IRQHandler,Default_Handler
        
    .weak      TIM1_CC_IRQHandler   
    .thumb_set TIM1_CC_IRQHandler,Default_Handler
                    
    .weak      TIM2_IRQHandler            
    .thumb_set TIM2_IRQHandler,Default_Handler
                    
    .weak      TIM3_IRQHandler            
    .thumb_set TIM3_IRQHandler,Default_Handler
                    
    .weak      TIM4_IRQHandler            
    .thumb_set TIM4_IRQHandler,Default_Handler
                    
    .weak      I2C1_EV_IRQHandler   
    .thumb_set I2C1_EV_IRQHandler,Default_Handler
                        
    .weak      I2C1_ER_IRQHandler   
    .thumb_set I2C1_ER_IRQHandler,Default_Handler
                        
    .weak      I2C2_EV_IRQHandler   
    .thumb_set I2C2_EV_IRQHandler,Default_Handler
                    
    .weak      I2C2_ER_IRQHandler   
    .thumb_set I2C2_ER_IRQHandler,Default_Handler
                            
    .weak      SPI1_IRQHandler            
    .thumb_set SPI1_IRQHandler,Default_Handler
                            
    .weak      SPI2_IRQHandler            
    .thumb_set SPI2_IRQHandler,Default_Handler
                    
    .weak      USART1_IRQHandler      
    .thumb_set USART1_IRQHandler,Default_Handler
                        
    .weak      USART2_IRQHandler      
    .thumb_set USART2_IRQHandler,Default_Handler
                        
    .weak      USART3_IRQHandler      
    .thumb_set USART3_IRQHandler,Default_Handler
                    
    .weak      EXTI15_10_IRQHandler               
    .thumb_set EXTI15_10_IRQHandler,Default_Handler
                
    .weak      RTC_Alarm_IRQHandler               
    .thumb_set RTC_Alarm_IRQHandler,Default_Handler
                
    .weak      OTG_FS_WKUP_IRQHandler         
    .thumb_set OTG_FS_WKUP_IRQHandler,Default_Handler
                
    .weak      TIM8_BRK_TIM12_IRQHandler         
    .thumb_set TIM8_BRK_TIM12_IRQHandler,Default_Handler
            
    .weak      TIM8_UP_TIM13_IRQHandler            
    .thumb_set TIM8_UP_TIM13_IRQHandler,Default_Handler
            
    .weak      TIM8_TRG_COM_TIM14_IRQHandler      
    .thumb_set TIM8_TRG_COM_TIM14_IRQHandler,Default_Handler
        
    .weak      TIM8_CC_IRQHandler   
    .thumb_set TIM8_CC_IRQHandler,Default_Handler
                    
    .weak      DMA1_Stream7_IRQHandler               
    .thumb_set DMA1_Stream7_IRQHandler,Default_Handler
                        
    .weak      FSMC_IRQHandler            
    .thumb_set FSMC_IRQHandler,Default_Handler
                        
    .weak      SDIO_IRQHandler            
    .thumb_set SDIO_IRQHandler,Default_Handler
                     
   .weak      TIM5_IRQHandler            
   .thumb_set TIM5_IRQHandler,Default_Handler
                     
   .weak      SPI3_IRQHandler            
   .thumb_set SPI3_IRQHandler,Default_Handler
                     
   .weak      UART4_IRQHandler         
   .thumb_set UART4_IRQHandler,Default_Handler
                  
   .weak      UART5_IRQHandler         
   .thumb_set UART5_IRQHandler,Default_Handler
                  
   .weak      TIM6_DAC_IRQHandler                  
   .thumb_set TIM6_DAC_IRQHandler,Default_Handler
               
   .weak      TIM7_IRQHandler            
   .thumb_set TIM7_IRQHandler,Default_Handler
         
   .weak      DMA2_Stream0_IRQHandler               
   .thumb_set DMA2_Stream0_IRQHandler,Default_Handler
               
   .weak      DMA2_Stream1_IRQHandler               
   .thumb_set DMA2_Stream1_IRQHandler,Default_Handler
                  
   .weak      DMA2_Stream2_IRQHandler               
   .thumb_set DMA2_Stream2_IRQHandler,Default_Handler
            
   .weak      DMA2_Stream3_IRQHandler               
   .thumb_set DMA2_Stream3_IRQHandler,Default_Handler
            
   .weak      DMA2_Stream4_IRQHandler               
   .thumb_set DMA2_Stream4_IRQHandler,Default_Handler
            
   .weak      ETH_IRQHandler      
   .thumb_set ETH_IRQHandler,Default_Handler
                  
   .weak      ETH_WKUP_IRQHandler                  
   .thumb_set ETH_WKUP_IRQHandler,Default_Handler
            
   .weak      CAN2_TX_IRQHandler   
   .thumb_set CAN2_TX_IRQHandler,Default_Handler
                           
   .weak      CAN2_RX0_IRQHandler                  
   .thumb_set CAN2_RX0_IRQHandler,Default_Handler
                           
   .weak      CAN2_RX1_IRQHandler                  
   .thumb_set CAN2_RX1_IRQHandler,Default_Handler
                           
   .weak      CAN2_SCE_IRQHandler                  
   .thumb_set CAN2_SCE_IRQHandler,Default_Handler
                           
   .weak      OTG_FS_IRQHandler      
   .thumb_set OTG_FS_IRQHandler,Default_Handler
                     
   .weak      DMA2_Stream5_IRQHandler               
   .thumb_set DMA2_Stream5_IRQHandler,Default_Handler
                  
   .weak      DMA2_Stream6_IRQHandler               
   .thumb_set DMA2_Stream6_IRQHandler,Default_Handler
                  
   .weak      DMA2_Stream7_IRQHandler               
   .thumb_set DMA2_Stream7_IRQHandler,Default_Handler
                  
   .weak      USART6_IRQHandler      
   .thumb_set USART6_IRQHandler,Default_Handler
                        
   .weak      I2C3_EV_IRQHandler   
   .thumb_set I2C3_EV_IRQHandler,Default_Handler
                        
   .weak      I2C3_ER_IRQHandler   
   .thumb_set I2C3_ER_IRQHandler,Default_Handler
                        
   .weak      OTG_HS_EP1_OUT_IRQHandler         
   .thumb_set OTG_HS_EP1_OUT_IRQHandler,Default_Handler
               
   .weak      OTG_HS_EP1_IN_IRQHandler            
   .thumb_set OTG_HS_EP1_IN_IRQHandler,Default_Handler
               
   .weak      OTG_HS_WKUP_IRQHandler         
   .thumb_set OTG_HS_WKUP_IRQHandler,Default_Handler
            
   .weak      OTG_HS_IRQHandler      
   .thumb_set OTG_HS_IRQHandler,Default_Handler
                  
   .weak      DCMI_IRQHandler            
   .thumb_set DCMI_IRQHandler,Default_Handler
                                   
   .weak      HASH_RNG_IRQHandler                  
   .thumb_set HASH_RNG_IRQHandler,Default_Handler   

   .weak      FPU_IRQHandler                  
   .thumb_set FPU_IRQHandler,Default_Handler

整个文件重点关注的地方

——针对不同的芯片型号,汇编环境需要调整
——针对不同的芯片型号,中断向量表和对应中断处理函数也需要修改
——文件中将中断向量表ptfVectors和默认中断处理函数Default_Handler定义为全局符号,使得在C源文件中可见和可用
——在复位处理函数运行过程中还会跳转__libc_init_array这样一个特殊的符号,用于在 C/C++ 程序的初始化阶段执行一系列的函数。在链接过程中,链接器会收集所有带有 attribute((constructor)) 属性的函数,并将它们放入一个特殊的段(通常是 .init_array 段)。然后,在程序启动时,__libc_init_array 会被调用,以执行这些初始化函数。

一些感想

为什么要看这两个文件

下面的图片是用STM32CUBEMX生成的STM32的工程目录,我其实有个想法:构建这样的一个STM32的工程目录,每个文件都经过我的复刻(而不是直接拷贝),我认为这能帮助我更好地理解和学习某款芯片,所以我试着去看每个文件。在这个工程目录下,除了.mxproject和.ioc文件(STM32CUBEMX所需的工程文件,我不打算去看),剩下就是一个.s启动文件、一个.ld链接器脚本、一个Makefile文件和所有的c语言源文件。
请添加图片描述

强烈建议不要去看.s文件、.ld文件和Makefile文件的每个语句!!!!

(如果你是高手,那当我没说!)以我现有的开发经验和这几天的体会来说,看这几个文件确实花费我很大精力,特别是去看每个语句,我感觉我也有些钻牛角尖了,所以建议把这些文件拿去直接使用(.s文件可以看看),若使用Keil开发,也压根不需要接触到.ld文件和Makefile文件是吧?!

看完这两个文件的收获

说实话,我也不敢说我现在彻底理解了整个工程的编译和链接流程,我只是尽力去看懂和理解这个过程完成的一些事情。但是我起码
——写出了这篇博客;
——复刻了startup_stm32f407xx.s和STM32F407ZGTx_FLASH.ld这两个文件,在里面也做了中文注释;
——了解各个程序段在存储区域的排布情况和MCU上电启动执行程序的流程;
——完成了我的想法(构建一个STM32的工程目录)的一部分;
——知道了如何修改设置的堆栈大小和 attribute((constructor)) (这个内容可能有用,但我暂时没用过);
——我或许能构建一个GD32F470ZGT6芯片的工程目录,而使用VS Code和ARM-GCC编译工具链来开发,这个以后再说吧

后续

Makefile文件我还在看,等我觉得看的差不多我就也会写一篇博客分享我的心得和看法;然后后面就是根据数据手册来复刻出固件库,这个我尽力而为。

如果我说的有任何不对的地方,欢迎指正;由衷希望得到大家的建议!

### 回答1: startup_stm32f10x_ld.s是一个汇编语言文件,用于启动STMicroelectronics的STM32F10x微控制器系列中的LD型号。它是一个片上系统(SoC)启动文件,具有以下几个主要功能: 1. 初始化向量表:在启动过程中,处理器将从向量表中获取初始中断服务程序的地址。startup_stm32f10x_ld.s文件包含了该向量表的初始化,通过设置每个中断向量的地址,确保正确的中断服务程序能够在中断发生时执行。 2. 复位处理:当微控制器上电或复位时,startup_stm32f10x_ld.s文件执行一些必要的初始化操作。这包括将堆栈指针设置为正确的值,初始化BSS段中的全局变量为零,以及调用C库的初始化函数。 3. 跳转到主程序:在完成所有必要的初始化后,startup_stm32f10x_ld.s文件将跳转到主程序的入口点。主程序可以是C代码,也可以是汇编语言代码。 此外,startup_stm32f10x_ld.s文件还包含其他一些处理器和外设的特定配置设置,比如时钟设置和中断优先级设置。这些设置将确保在启动和运行期间系统正常工作。 总之,startup_stm32f10x_ld.s文件STM32F10x微控制器LD型号启动过程中的关键文件,它负责初始化向量表、处理复位和跳转到主程序。 ### 回答2: startup_stm32f10x_ld.s是一个汇编语言文件,用于启动STM32F10x系列微控制器。在嵌入式开发中,启动文件是一个必要的组件,它包含了一些特定的指令和配置,用于初始化微控制器的各个部分。 startup_stm32f10x_ld.s文件首先定义了一些符号常量,如堆栈大小、向量表起始地址等。然后,它定义了一个叫reset的函数,这个函数是微控制器上电复位后第一个执行的代码。 在reset函数中,startup_stm32f10x_ld.s文件会执行一系列的初始化操作。首先,它会将寄存器设置为默认值,例如将控制寄存器设置为默认状态、禁用中断等。接着,它会初始化中断向量表,将内核中断向量和外设中断向量连接到相应的中断服务函数。 之后,startup_stm32f10x_ld.s文件会初始化存储器。它会将存储器保护设置为默认状态、配置堆栈指针、初始化静态存储器和堆栈。接着,它会执行一段汇编指令,用于调用主函数。 startup_stm32f10x_ld.s文件的最后一部分是一些中断处理函数。中断处理函数用于处理微控制器发生的各种中断,如时钟中断、串口中断等。这些函数会在相应的中断发生时被自动调用,执行相应的中断处理代码。 总之,startup_stm32f10x_ld.s文件是一个重要的启动文件,它通过初始化和配置微控制器的各个部分,为程序的正常运行提供了基础。 ### 回答3: startup_stm32f10x_ld.s文件STM32F10x系列芯片的启动文件,它在系统上电或复位后被系统加载执行,用于初始化硬件、配置中断向量表和启动主函数。 该文件的主要功能包括以下几个方面: 1. 系统初始化:定义了一些默认的寄存器值,例如将堆栈指针(SP)指向指定的栈顶,并设置处理器工作模式为特权模式。此外,还会调用SystemInit函数,用于初始化系统时钟。 2. 中断向量表配置:定义了所有可能的中断向量,包括硬件中断和软件中断。对于每个中断向量,都指定了相应的中断处理函数的地址,并在启动文件中进行了配置。 3. 异常处理程序:定义了一些异常处理程序,如复位异常、NMI非屏蔽中断异常、硬件错误异常、硬件中断异常等。这些异常处理程序用于异常情况下的处理,例如重启系统、处理硬件错误等。 4. 主函数入口:定义了Reset_Handler函数作为主函数入口点。当系统上电或复位后,将首先执行Reset_Handler函数。在该函数中,会进行一些必要的初始化操作,然后调用main函数启动用户应用程序的执行。 总的来说,startup_stm32f10x_ld.s文件STM32F10x系列芯片的启动文件,负责初始化系统硬件和中断向量表配置,并提供主函数入口点。它为系统启动提供了必要的支持和准备工作。用户可以根据自己的需求对该文件进行定制和修改,以满足特定应用的需求。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值