完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
2个回答
|
|
前言
因为在做有关STM32F407ZET6的项目,其中一项内容是通过IAP来对STM32进行在线升级,那么首先需要对STM32的启动流程需要做到详细了解。 硬件及调试配置说明: 使用芯片:STM32F407ZET6 调试软件:IAR6.3.0 软件库:STM32的HAL库,版本V1.3.0 启动文件:startup_stm32f407xx.s,版本V1.2.1 必须说明: 因为本人使用的IAR开发平台,因此程序中的指令都是IAR指令集(关于IAR指令,参见《EWARM_AssemblerReference.ENU.pdf》文档),因此会发现很多汇编指令会和在别的地方看到的不一样,但是基本指令的功能基本类似,比如IAR中的SECTION指令和标准ARM指令集中的AREA指令。而且,同类型的文件在扩展名上也可能不同,比如对于“分散加载文件”,IAR扩展名为.icf,但是keil扩展名是.scf,而且编辑命令也不同。 (一)启动文件 我们需要了解:一般的,工程文件件中会包含很多的C文件以及必要的S文件(汇编文件)。用户在使用IDE(集成开发平台)对工程进行一键式处理时,经预处理->编译->汇编->链接后生成可执行文件。其中,每一个S或C文件在经过汇编器“汇编”后都会生成对应的目标文件(.o或.obj或类似格式文件),然后由链接器对各个目标文件进行链接,决定各个目标文件在最终可执行文件(bin或hex或类似格式文件)里的位置。 我们只需要知道:startup_stm32f407xx.s文件成成的目标文件在最终可执行文件中是第一个被执行的! (我想:不同的源文件(C或S)之间是通过函数调用或参数引用而相互关联起来的。即使是main函数,也是被startup_stm32f407xx.s中汇编代码所调用的,而且此段汇编代码前不再存在其他代码,因此汇编程序应该在最前面执行;同时,通过在线调试,可以看到可执行文件的反汇编文件,其中startup_stm32f407xx.s程序确实是在最前面) STM32F4和STM32F1的启动文件略不相同,但是基本内容是一样的。启动文件的工作按顺序依次分为以下几项: - Set the initial SP - Set the initial PC == _iar_program_start, - Set the vector table entries with the exceptions ISR address. - Branches to main in the C library (which eventually calls main()). (1)设置堆栈 (2)初始化PC指针 (3)设置向量表 (4)跳转到main函数 下面进行分段是分析: 第一段说明: MODULE ?cstartup ;; Forward declaration of sections. SECTION CSTACK:DATA:NOROOT(3) SECTION .intvec:CODE:NOROOT(2) EXTERN __iar_program_start EXTERN SystemInit PUBLIC __vector_table 【1】MODULE 控制指令是用来标记 modules 源码的开始和结束,后边的 ?cstartup 是模块的名字,此文档的最后的 END 表明模块的结束 【2】SECTION 指令是声明段,一个段不能同时包含 public symbol 和 pubweak symbol ,模块只有在相同的名字的模块没有被链接进来的时候才会被链接进来。 语法格式:SECTION section:type [flag] [(align)] align,是用于指定地址对齐到 2^align,他的取值是 0 到 30 flag,取值NOROOT、ROOT、REORDER、NOREORDER,默认是ROOT,NOROOT表示如果这个段中的符号没有被引用,将会被连接器舍弃,即可被优化。ROOT表示不可被优化。REORDER表示开始一个新的名字是 section 的段(section),NOREORDER表示开始一个新的名字为 section 的片段(fragment),多个片段组成一个段(section) type,memory 的类型,取值是 CODE、CONST、DATA section,段的名字 【3】EXTERN 用导入(引用)其他模块的 symbol(符号) 【4】PUBLIC 导出 symbol(符号) 第二段: DATA __vector_table DCD sfe(CSTACK) DCD Reset_Handler ; Reset Handler DCD NMI_Handler ; NMI Handler DCD HardFault_Handler ; Hard Fault Handler DCD MemManage_Handler ; MPU Fault Handler DCD BusFault_Handler ; Bus Fault Handler DCD UsageFault_Handler ; Usage Fault Handler DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD 0 ; Reserved DCD SVC_Handler ; SVCall Handler DCD DebugMon_Handler ; Debug Monitor Handler DCD 0 ; Reserved DCD PendSV_Handler ; PendSV Handler DCD SysTick_Handler ; SysTick Handler ; External Interrupts DCD WWDG_IRQHandler ; Window WatchDog DCD PVD_IRQHandler ; PVD through EXTI Line detection DCD TAMP_STAMP_IRQHandler ; Tamper and TimeStamps through the EXTI line DCD RTC_WKUP_IRQHandler ; RTC Wakeup through the EXTI line DCD FLASH_IRQHandler ; FLASH DCD RCC_IRQHandler ; RCC DCD EXTI0_IRQHandler ; EXTI Line0 DCD EXTI1_IRQHandler ; EXTI Line1 DCD EXTI2_IRQHandler ; EXTI Line2 DCD EXTI3_IRQHandler ; EXTI Line3 DCD EXTI4_IRQHandler ; EXTI Line4 DCD DMA1_Stream0_IRQHandler ; DMA1 Stream 0 DCD DMA1_Stream1_IRQHandler ; DMA1 Stream 1 DCD DMA1_Stream2_IRQHandler ; DMA1 Stream 2 DCD DMA1_Stream3_IRQHandler ; DMA1 Stream 3 DCD DMA1_Stream4_IRQHandler ; DMA1 Stream 4 DCD DMA1_Stream5_IRQHandler ; DMA1 Stream 5 DCD DMA1_Stream6_IRQHandler ; DMA1 Stream 6 DCD ADC_IRQHandler ; ADC1, ADC2 and ADC3s DCD CAN1_TX_IRQHandler ; CAN1 TX DCD CAN1_RX0_IRQHandler ; CAN1 RX0 DCD CAN1_RX1_IRQHandler ; CAN1 RX1 DCD CAN1_SCE_IRQHandler ; CAN1 SCE DCD EXTI9_5_IRQHandler ; External Line[9:5]s DCD TIM1_BRK_TIM9_IRQHandler ; TIM1 Break and TIM9 DCD TIM1_UP_TIM10_IRQHandler ; TIM1 Update and TIM10 DCD TIM1_TRG_COM_TIM11_IRQHandler ; TIM1 Trigger and Commutation and TIM11 DCD TIM1_CC_IRQHandler ; TIM1 Capture Compare DCD TIM2_IRQHandler ; TIM2 DCD TIM3_IRQHandler ; TIM3 DCD TIM4_IRQHandler ; TIM4 DCD I2C1_EV_IRQHandler ; I2C1 Event DCD I2C1_ER_IRQHandler ; I2C1 Error DCD I2C2_EV_IRQHandler ; I2C2 Event DCD I2C2_ER_IRQHandler ; I2C2 Error DCD SPI1_IRQHandler ; SPI1 DCD SPI2_IRQHandler ; SPI2 DCD USART1_IRQHandler ; USART1 DCD USART2_IRQHandler ; USART2 DCD USART3_IRQHandler ; USART3 DCD EXTI15_10_IRQHandler ; External Line[15:10]s DCD RTC_Alarm_IRQHandler ; RTC Alarm (A and B) through EXTI Line DCD OTG_FS_WKUP_IRQHandler ; USB OTG FS Wakeup through EXTI line DCD TIM8_BRK_TIM12_IRQHandler ; TIM8 Break and TIM12 DCD TIM8_UP_TIM13_IRQHandler ; TIM8 Update and TIM13 DCD TIM8_TRG_COM_TIM14_IRQHandler ; TIM8 Trigger and Commutation and TIM14 DCD TIM8_CC_IRQHandler ; TIM8 Capture Compare DCD DMA1_Stream7_IRQHandler ; DMA1 Stream7 DCD FSMC_IRQHandler ; FSMC DCD SDIO_IRQHandler ; SDIO DCD TIM5_IRQHandler ; TIM5 DCD SPI3_IRQHandler ; SPI3 DCD UART4_IRQHandler ; UART4 DCD UART5_IRQHandler ; UART5 DCD TIM6_DAC_IRQHandler ; TIM6 and DAC1&2 underrun errors DCD TIM7_IRQHandler ; TIM7 DCD DMA2_Stream0_IRQHandler ; DMA2 Stream 0 DCD DMA2_Stream1_IRQHandler ; DMA2 Stream 1 DCD DMA2_Stream2_IRQHandler ; DMA2 Stream 2 DCD DMA2_Stream3_IRQHandler ; DMA2 Stream 3 DCD DMA2_Stream4_IRQHandler ; DMA2 Stream 4 DCD ETH_IRQHandler ; Ethernet DCD ETH_WKUP_IRQHandler ; Ethernet Wakeup through EXTI line DCD CAN2_TX_IRQHandler ; CAN2 TX DCD CAN2_RX0_IRQHandler ; CAN2 RX0 DCD CAN2_RX1_IRQHandler ; CAN2 RX1 DCD CAN2_SCE_IRQHandler ; CAN2 SCE DCD OTG_FS_IRQHandler ; USB OTG FS DCD DMA2_Stream5_IRQHandler ; DMA2 Stream 5 DCD DMA2_Stream6_IRQHandler ; DMA2 Stream 6 DCD DMA2_Stream7_IRQHandler ; DMA2 Stream 7 DCD USART6_IRQHandler ; USART6 DCD I2C3_EV_IRQHandler ; I2C3 event DCD I2C3_ER_IRQHandler ; I2C3 error DCD OTG_HS_EP1_OUT_IRQHandler ; USB OTG HS End Point 1 Out DCD OTG_HS_EP1_IN_IRQHandler ; USB OTG HS End Point 1 In DCD OTG_HS_WKUP_IRQHandler ; USB OTG HS Wakeup through EXTI DCD OTG_HS_IRQHandler ; USB OTG HS DCD DCMI_IRQHandler ; DCMI DCD 0 ; Reserved DCD HASH_RNG_IRQHandler ; Hash and RNG DCD FPU_IRQHandler ; FPU ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; 【1】DATA 表示下边中的标签是 32 位的标签,THUMB 表示下边的标签是 16 位的标签,所谓的标签是 地址的别名,不占用代码空间,给编译器看的 【2】 DCD 是数据定义或者 重定位指令,为的是定义一个值,或者保留 memory,DCD 别名是 DC32,用于声明一个 32 位的常量,这部分是中断向量表的内容,需要注意的是,他们的顺序不能改变,此部分会放到 flash 的最开始部分,当系统启动的时候会加载前另个地址,第一个地址是 c 程序的栈的栈顶地址,第二个地址是向量表的开始地址,中断发生时会根据向量表的首地址和偏移量来找到程序的入口 【3】sfe 指令作用是返回栈的结尾,因为栈的增长方向是反方向的 第三段:中断处理函数 ;; Default interrupt handlers. ;; THUMB PUBWEAK Reset_Handler SECTION .text:CODE:REORDER:NOROOT(2) Reset_Handler LDR R0, =SystemInit BLX R0 LDR R0, =__iar_program_start BX R0 PUBWEAK NMI_Handler SECTION .text:CODE:REORDER:NOROOT(1) NMI_Handler B NMI_Handler PUBWEAK HardFault_Handler SECTION .text:CODE:REORDER:NOROOT(1) HardFault_Handler B HardFault_Handler PUBWEAK MemManage_Handler SECTION .text:CODE:REORDER:NOROOT(1) MemManage_Handler B MemManage_Handler PUBWEAK BusFault_Handler SECTION .text:CODE:REORDER:NOROOT(1) BusFault_Handler B BusFault_Handler PUBWEAK UsageFault_Handler SECTION .text:CODE:REORDER:NOROOT(1) UsageFault_Handler B UsageFault_Handler PUBWEAK SVC_Handler SECTION .text:CODE:REORDER:NOROOT(1) SVC_Handler B SVC_Handler PUBWEAK DebugMon_Handler SECTION .text:CODE:REORDER:NOROOT(1) DebugMon_Handler B DebugMon_Handler PUBWEAK PendSV_Handler SECTION .text:CODE:REORDER:NOROOT(1) PendSV_Handler B PendSV_Handler PUBWEAK SysTick_Handler SECTION .text:CODE:REORDER:NOROOT(1) SysTick_Handler B SysTick_Handler PUBWEAK WWDG_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) WWDG_IRQHandler B WWDG_IRQHandler PUBWEAK PVD_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) PVD_IRQHandler B PVD_IRQHandler PUBWEAK TAMP_STAMP_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) TAMP_STAMP_IRQHandler B TAMP_STAMP_IRQHandler PUBWEAK RTC_WKUP_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) RTC_WKUP_IRQHandler B RTC_WKUP_IRQHandler PUBWEAK FLASH_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) FLASH_IRQHandler B FLASH_IRQHandler PUBWEAK RCC_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) RCC_IRQHandler B RCC_IRQHandler PUBWEAK EXTI0_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) EXTI0_IRQHandler B EXTI0_IRQHandler PUBWEAK EXTI1_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) EXTI1_IRQHandler B EXTI1_IRQHandler PUBWEAK EXTI2_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) EXTI2_IRQHandler B EXTI2_IRQHandler PUBWEAK EXTI3_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) EXTI3_IRQHandler B EXTI3_IRQHandler PUBWEAK EXTI4_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) EXTI4_IRQHandler B EXTI4_IRQHandler PUBWEAK DMA1_Stream0_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream0_IRQHandler B DMA1_Stream0_IRQHandler PUBWEAK DMA1_Stream1_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream1_IRQHandler B DMA1_Stream1_IRQHandler PUBWEAK DMA1_Stream2_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream2_IRQHandler B DMA1_Stream2_IRQHandler PUBWEAK DMA1_Stream3_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream3_IRQHandler B DMA1_Stream3_IRQHandler PUBWEAK DMA1_Stream4_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream4_IRQHandler B DMA1_Stream4_IRQHandler PUBWEAK DMA1_Stream5_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream5_IRQHandler B DMA1_Stream5_IRQHandler PUBWEAK DMA1_Stream6_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream6_IRQHandler B DMA1_Stream6_IRQHandler PUBWEAK ADC_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) ADC_IRQHandler B ADC_IRQHandler PUBWEAK CAN1_TX_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) CAN1_TX_IRQHandler B CAN1_TX_IRQHandler PUBWEAK CAN1_RX0_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) CAN1_RX0_IRQHandler B CAN1_RX0_IRQHandler PUBWEAK CAN1_RX1_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) CAN1_RX1_IRQHandler B CAN1_RX1_IRQHandler PUBWEAK CAN1_SCE_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) CAN1_SCE_IRQHandler B CAN1_SCE_IRQHandler PUBWEAK EXTI9_5_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) EXTI9_5_IRQHandler B EXTI9_5_IRQHandler PUBWEAK TIM1_BRK_TIM9_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) TIM1_BRK_TIM9_IRQHandler B TIM1_BRK_TIM9_IRQHandler PUBWEAK TIM1_UP_TIM10_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) TIM1_UP_TIM10_IRQHandler B TIM1_UP_TIM10_IRQHandler PUBWEAK TIM1_TRG_COM_TIM11_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) TIM1_TRG_COM_TIM11_IRQHandler B TIM1_TRG_COM_TIM11_IRQHandler PUBWEAK TIM1_CC_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) TIM1_CC_IRQHandler B TIM1_CC_IRQHandler PUBWEAK TIM2_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) TIM2_IRQHandler B TIM2_IRQHandler PUBWEAK TIM3_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) TIM3_IRQHandler B TIM3_IRQHandler PUBWEAK TIM4_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) TIM4_IRQHandler B TIM4_IRQHandler PUBWEAK I2C1_EV_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) I2C1_EV_IRQHandler B I2C1_EV_IRQHandler PUBWEAK I2C1_ER_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) I2C1_ER_IRQHandler B I2C1_ER_IRQHandler PUBWEAK I2C2_EV_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) I2C2_EV_IRQHandler B I2C2_EV_IRQHandler PUBWEAK I2C2_ER_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) I2C2_ER_IRQHandler B I2C2_ER_IRQHandler PUBWEAK SPI1_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) SPI1_IRQHandler B SPI1_IRQHandler PUBWEAK SPI2_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) SPI2_IRQHandler B SPI2_IRQHandler PUBWEAK USART1_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) USART1_IRQHandler B USART1_IRQHandler PUBWEAK USART2_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) USART2_IRQHandler B USART2_IRQHandler PUBWEAK USART3_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) USART3_IRQHandler B USART3_IRQHandler PUBWEAK EXTI15_10_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) EXTI15_10_IRQHandler B EXTI15_10_IRQHandler PUBWEAK RTC_Alarm_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) RTC_Alarm_IRQHandler B RTC_Alarm_IRQHandler PUBWEAK OTG_FS_WKUP_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) OTG_FS_WKUP_IRQHandler B OTG_FS_WKUP_IRQHandler PUBWEAK TIM8_BRK_TIM12_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) TIM8_BRK_TIM12_IRQHandler B TIM8_BRK_TIM12_IRQHandler PUBWEAK TIM8_UP_TIM13_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) TIM8_UP_TIM13_IRQHandler B TIM8_UP_TIM13_IRQHandler PUBWEAK TIM8_TRG_COM_TIM14_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) TIM8_TRG_COM_TIM14_IRQHandler B TIM8_TRG_COM_TIM14_IRQHandler PUBWEAK TIM8_CC_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) TIM8_CC_IRQHandler B TIM8_CC_IRQHandler PUBWEAK DMA1_Stream7_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA1_Stream7_IRQHandler B DMA1_Stream7_IRQHandler PUBWEAK FSMC_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) FSMC_IRQHandler B FSMC_IRQHandler PUBWEAK SDIO_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) SDIO_IRQHandler B SDIO_IRQHandler PUBWEAK TIM5_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) TIM5_IRQHandler B TIM5_IRQHandler PUBWEAK SPI3_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) SPI3_IRQHandler B SPI3_IRQHandler PUBWEAK UART4_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) UART4_IRQHandler B UART4_IRQHandler PUBWEAK UART5_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) UART5_IRQHandler B UART5_IRQHandler PUBWEAK TIM6_DAC_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) TIM6_DAC_IRQHandler B TIM6_DAC_IRQHandler PUBWEAK TIM7_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) TIM7_IRQHandler B TIM7_IRQHandler PUBWEAK DMA2_Stream0_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream0_IRQHandler B DMA2_Stream0_IRQHandler PUBWEAK DMA2_Stream1_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream1_IRQHandler B DMA2_Stream1_IRQHandler PUBWEAK DMA2_Stream2_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream2_IRQHandler B DMA2_Stream2_IRQHandler PUBWEAK DMA2_Stream3_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream3_IRQHandler B DMA2_Stream3_IRQHandler PUBWEAK DMA2_Stream4_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream4_IRQHandler B DMA2_Stream4_IRQHandler PUBWEAK ETH_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) ETH_IRQHandler B ETH_IRQHandler PUBWEAK ETH_WKUP_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) ETH_WKUP_IRQHandler B ETH_WKUP_IRQHandler PUBWEAK CAN2_TX_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) CAN2_TX_IRQHandler B CAN2_TX_IRQHandler PUBWEAK CAN2_RX0_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) CAN2_RX0_IRQHandler B CAN2_RX0_IRQHandler PUBWEAK CAN2_RX1_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) CAN2_RX1_IRQHandler B CAN2_RX1_IRQHandler PUBWEAK CAN2_SCE_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) CAN2_SCE_IRQHandler B CAN2_SCE_IRQHandler PUBWEAK OTG_FS_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) OTG_FS_IRQHandler B OTG_FS_IRQHandler PUBWEAK DMA2_Stream5_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream5_IRQHandler B DMA2_Stream5_IRQHandler PUBWEAK DMA2_Stream6_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream6_IRQHandler B DMA2_Stream6_IRQHandler PUBWEAK DMA2_Stream7_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DMA2_Stream7_IRQHandler B DMA2_Stream7_IRQHandler PUBWEAK USART6_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) USART6_IRQHandler B USART6_IRQHandler PUBWEAK I2C3_EV_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) I2C3_EV_IRQHandler B I2C3_EV_IRQHandler PUBWEAK I2C3_ER_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) I2C3_ER_IRQHandler B I2C3_ER_IRQHandler PUBWEAK OTG_HS_EP1_OUT_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) OTG_HS_EP1_OUT_IRQHandler B OTG_HS_EP1_OUT_IRQHandler PUBWEAK OTG_HS_EP1_IN_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) OTG_HS_EP1_IN_IRQHandler B OTG_HS_EP1_IN_IRQHandler PUBWEAK OTG_HS_WKUP_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) OTG_HS_WKUP_IRQHandler B OTG_HS_WKUP_IRQHandler PUBWEAK OTG_HS_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) OTG_HS_IRQHandler B OTG_HS_IRQHandler PUBWEAK DCMI_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) DCMI_IRQHandler B DCMI_IRQHandler PUBWEAK HASH_RNG_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) HASH_RNG_IRQHandler B HASH_RNG_IRQHandler PUBWEAK FPU_IRQHandler SECTION .text:CODE:REORDER:NOROOT(1) FPU_IRQHandler B FPU_IRQHandler END |
|
|
|
【1】THUMB 表明下边是 thumb 指令
【2】Reset_Handler:复位操作后,mcu执行的中断处理函数 R0 = SystemInit BLX R0 跳转到 SystemInit 函数(stm32的第一个函数),并将处理器切换到 thumb 态 R0 = __iar_program_start BX R0 跳转到 __iar_program_start 函数,状态也是切换到 thumb 状态 注意:此处BLX 和BX 的用法与区别不过多介绍; 【3】SystemInit函数(大同小异),功能:完成芯片正常运行所需的必备功能项的配置 //#define VECT_TAB_SRAM //RAM或Flash2RAM中运行 #define VECT_TAB_OFFSET 0x0 //!< Vector Table base offset field. //This value must be a multiple of 0x200. void SystemInit(void) { /* FPU settings ------------------------------------------------------------*/ #if (__FPU_PRESENT == 1) && (__FPU_USED == 1) SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */ #endif /* Reset the RCC clock configuration to the default reset state ------------*/ /* Set HSION bit */ RCC->CR |= (uint32_t)0x00000001; /* Reset CFGR register */ RCC->CFGR = 0x00000000; /* Reset HSEON, CSSON and PLLON bits */ RCC->CR &= (uint32_t)0xFEF6FFFF; /* Reset PLLCFGR register */ RCC->PLLCFGR = 0x24003010; /* Reset HSEBYP bit */ RCC->CR &= (uint32_t)0xFFFBFFFF; /* Disable all interrupts */ RCC->CIR = 0x00000000; #if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM) SystemInit_ExtMemCtl(); #endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */ /* Configure the Vector Table location add offset address ------------------*/ #ifdef VECT_TAB_SRAM SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */ #else SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */ #endif } 【3.1】FPU浮点数运算设置,stm32f4系列支持浮点数运算; 【3.2】配置复位和时钟相关的寄存器:RCC结构体变量包含所有的寄存器成员; 【3.3】外部SRAM配置(一般没有使用外部SRAM); 【3.4】Vector向量表重定位(非常重要):配置中断向量表的基地址和偏移量 (1)当在RAM中调试代码时,需要将向量的基地址修改为RAM1的起始地址;这种情况不用这种模式; (2)一般我们配置的是NAND FLASH启动模式,应该将向量的基地址修改为FLASH的起始地址; (3)地址偏移量:当我们的工程文件是stm32上电第一个程序时,应设置VECT_TAB_OFFSET=0;如果在此工程文件前,还有另外的执行程序PRO(比如用于IAP在线升级的bootloader程序),那么需要根据PRO程序的大小来设置VECT_TAB_OFFSET的大小,同时需要注意VECT_TAB_OFFSET的值必须是0x200的2*n(n=1,2,3...)倍数;(此段内容后续 会详细介绍) 【4】此处的 __iar_program_start 在程序中找不到是因为它已经被封装到了 IAR 自带的C库启动代码中了,当我们编译的时候,在项目属性的 linker,library中勾选了 Automatic runtime library ,就告诉了编译器用库中的 __iar_program_start ,具体实现了什么,我们可以查看 IAR 工具为我们提供的源码,具体路径在 IAR 安装目录下的 armsrclibthumb ,我们可以看到有的文件分别的提供了 汇编代码和 c 代码。 查看cstartup_M.c,里面定义了__iar_program_start函数 void __iar_program_start( void ) { __iar_init_core(); __iar_init_vfp(); __cmain(); } 其中: 【4.1】此段的程序中前两个函数是弱函数,在工程共没有定义 【4.2】__cmain 函数作用是初始化段和底层硬件,最后调用main 至此,库文件中的启动文件先分析到这里 (二)启动流程总结: (1)一般我们配置STM32从flash启动,启动流程如下: 【1.1】MCU上电后从0x0800 0000处读取栈顶地址并保存——>MCU从0x0800 0004处读取中断向量表的起始地址——>根据MCU系统设定的中断偏移量来计算出复位中断向量(起始地址+0),其内容=Reset_Handler,即复位中断处理程序入口地址——>跳转到复位中断处理程序入口处(通过设置PC指针,MCU自动完成,我们不需要管); 【1.2】复位中断函数: R0 = SystemInit BLX R0 跳转到 SystemInit 函数(stm32的第一个函数),并将处理器切换到 thumb 态 R0 = __iar_program_start BX R0 跳转到 __iar_program_start 函数,状态也是切换到 thumb 状态 最后的跳转函数时main函数,即进入用户程序 【1.3】main循环: 需要注意:用户main程序一般内部是一个while(1)死循环(否则,main函数执行完成后,MCU会跳进Hard Fault硬件错误处) 当发生xx中断时:MCU保存现场——>MCU从0x0800 0004处读取中断向量表的起始地址——>根据中断偏移量来计算出xx中断向量,然后取出xx中断处理程序入口地址 【1.4】MCU跳转到xx中断处理程序入口地址处,开始执行中断处理函数。 【1.5】xx中断处理程序完成后,MCU恢复现场,继续执行。 (2)STM32的启动模式简述: 上面讲解的是STM32从flash启动(用户APP程序是从0x08000000开始),实际上STM32支持多种启动模式,这里进行简单介绍: 【2.1】STM32的启动模式由芯片的启动引脚BOOT0和BOOT1决定:MCU在上电时会读取BOOT0和BOOT1引脚的电平状态并锁存,系统根据电平状态来从选择启动方式(注意:这里说的启动是指正常的上电,当我们采用jlink/jtag进行程序烧写或调试时,MCU会会忽略引脚状态)。下面是官方使用指南的说明: 【2.2】STM32三种启动模式对应的物理存储介质均是芯片内置的,它们是: a. 主闪存存储器 = 芯片内置的Flash。 b. 系统存储器 = 芯片内部一块特定的区域,芯片出厂时在这个区域预置了一段Bootloader,就是通常说的ISP程序。这个区域的内容在芯片出厂后用户无法进行读写操作。 c. SRAM = 芯片内置的RAM区,具有掉电丢失性。 补充解释:我们知道MCU上电是从0x0000 0000开始执行代码,但是我们发现STM32三种启动模式对应的物理存储介质均不在0x0000 0000处(也不可能同时在),而且地址不连续。这就是,“根据启动引脚,映射到Flash、系统存储区或SRAM”这句话的奇妙,可以理解成一下2点: A 根据不同的启动模式, 对应到各种启动模式的不同物理存储介质将被映像到第0块(启动存储区); B 即使被映像到启动存储区,仍然可以在它原先的存储器空间内访问相关的存储器。(未验证,值得去探究!!) A 就是:逻辑上讲MCU上电是从0x0000 0000开始执行代码,但是实际上PC指针是从实际对应的物理存储介质处开始执行。 比如我们从flash启动,通过IAR或KEIL在线调试,会发现MCU运行时的PC指针是从0x0800 0000开始的。 B就是:因为经过系统映射,那么对映射区的读写 = 对实际物理介质区的读写 比如:在00/01启动模式下,仍可读写执行0x08xxxxxx中的数据和代码, 并和读写执行0x00xxxxxx是一回事;在11启动模式下,仍可读写执行0x20xxxxxx 并和读写执行0x00xxxxxx是一回事 【2.3】三种启动方式对比: a. 主闪存存储器:最常用的方式,程序掉电不丢失,因此当我们确定工程完全达到使用要求后,一般是将文件烧写到flash中。 b. 系统存储器启动:这种模式启动的程序功能是由厂家设置的。一般来说,这种启动方式用的比较少。一般来说,我们选用这种启动模式时,是为了从串口(或是其他类似方式)下载程序,因为在厂家提供的BootLoader中,提供了串口下载程序的固件,可以通过这个BootLoader将程序下载到系统的Flash中。但是这个下载方式需要以下步骤: Step1: 将BOOT0设置为1,BOOT1设置为0,然后按下复位键,这样才能从系统存储器启动BootLoader Step2: 最后在BootLoader的帮助下,通过串口下载程序到Flash中 Step3: 程序下载完成后,又有需要将BOOT0设置为GND,手动复位,这样,STM32才可以从Flash中启动 可以看到,利用这种模式下载程序的流程稍显繁琐,但是可以通过普通串口代替专用烧写接口,不需要使用专用烧写工具。 c. 内置SRAM:因为SRAM掉电数据丢失,因此这个模式一般用于程序调试,而且SRAM的可擦除次数要远高于flash比如:当代码仅修改了局部内容,可以考虑从这个模式启动代码(也就是STM32的内存中),用于快速的程序调试,等程序调试完成后,再将程序下载到Flash中。(还有,一般的,程序在RAM执行速度要比flash快一些) (3)工程源文件与可执行文件的联系之“分散加载文件” 我们在使用ARM集成开发工具对工程进行开发时,基本流程如下: 源文件经预处理->编译->汇编->链接生成目标文件,生产目标文件之前,我们基本上都可以不用深入研究;目标文件经过连接器连接,生成可执行文件。这里我们需要关注一个问题:不同的目标文件是按照什么规则连接在一起的呢? 所依靠的文件即是:分散加载脚本, 【3.1】简单介绍:对于分散加载的概念,在《ARM体系结构与编程》书中第11章有明确介绍。 分散加载文件(即scatter file,IAR工程中其后缀为.scf)是一个文本文件,通过编写一个分散加载文件来指定ARM连接器在生成映像文件时如何分配RO,RW,ZI等数据的存放地址。如果不用SCATTER文件指定,那么ARM连接器会按照默认的方式来生成映像文件,一般情况下我们是不需要使用分散加载文件的。 什么时候使用scatter file: 1、存在复杂的地址映射:例如代码和数据需要分开存放在多个区域。 2、存在多个存储器类型:包含Flash, ROM, SDRAM,快速SRAM。我们根据代码与数据的特性把他们发在不同的存储器中,比如中断处理部分放在快速SRAM内部来提高响应速度,而把不常用到的代 码放到速度比较慢的Flash内。 3、函数的地址固定定位:可以利用Scatter file实现把某个函数放在固定地址,而不管其应用程序是否已经改变或重新编译。 4、利用符号确定堆和堆栈。 5、内存映射的IO:利用scatter file可以实现把某个数据段放在精确的地址处。因此对于嵌入式系统来说scatter file是必不可少的,因为嵌入式系统采用了ROM, RAM和内存映射的IO。 【3.2】IAR中的stm32F407的.scf文件的一般格式如下: /*###ICF### Section handled by ICF editor, don't touch! ****/ /*-Editor annotation file-*/ /* IcfEditorFile="$TOOLKIT_DIR$configideIcfEditorcortex_v1_0.xml" */ /*-Specials-*/ define symbol __ICFEDIT_intvec_start__ = 0x08000000;/*中断向量表开始地址*/ /*-Memory Regions-*/ /*定义内部FLASH地址 */--/*定义内部RAM地址 */ define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;/*闪存起始地址*/ define symbol __ICFEDIT_region_ROM_end__ = 0x0800FFFF;/*闪存结束地址---flash大小64k*/ define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;/*SRAM起始地址*/ define symbol __ICFEDIT_region_RAM_end__ = 0x20004FFF;/*SRAM结束地址---SRAM大小20k*/ /*-Sizes-*//* 栈和堆大小*/ define symbol __ICFEDIT_size_cstack__ = 0x800; /*栈大小*/ define symbol __ICFEDIT_size_heap__ = 0x800;/*堆大小*/ /**** End of ICF editor section. ###ICF###*/ define memory mem with size = 4G; define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__]; define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__]; define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };//CSTACK块属性(8字节对齐、大小__ICFEDIT_size_cstack__) define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { }; /* 下列语句定义所定义地址空间内可完成的操作类型*/ initialize by copy { readwrite }; do not initialize { section .noinit }; place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec }; //__ICFEDIT_intvec_start__赋值给.intvec标识符 place in ROM_region { readonly }; place in RAM_region { readwrite, block CSTACK, block HEAP }; 后续关于分散加载文件会有更加详细的说明; (三) 由于自身能力有限,本文章存在相关表述问题,希望大家能够批评指正,相互交流,共同进步! |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1865 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1656 浏览 1 评论
1131 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
755 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1713 浏览 2 评论
1961浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
777浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
606浏览 3评论
624浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
588浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2025-1-8 20:06 , Processed in 0.915704 second(s), Total 78, Slave 62 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号