完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
本文以STM32F429的启动文件为例去做介绍,其他系列芯片甚至其他厂家芯片的启动文件也类似,至少我见过的是这样的。 启动文件的作用: 1.初始化SP。 2.初始化PC 等于复位中断函数,上电首先执行复位中断函数。 3.用中断地址初始化中断向量表。 4.配置系统时钟 5.跳转到C库函数的_main()函数,_main()函数会调用main函数。运行用户编写的应用程序。 下面开始按照文件内容由上至下介绍启动文件。 Stack_Size EQU 0x00000400 AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size __initial_sp 初始化栈,为什么要有栈?栈用于局部变量,函数调用,函数形参的开销。这个大家可以做实验验证,搞一个递归。看他调用到多少层崩溃,然后将栈改大,观察可调用的层数是不是变大了? EQU:类似C语言中的define宏定义。 Stack_Size EQU 0x00000400 表示Stack_Size的大小是0x400 AREA :告诉汇编器汇编一个新的代码段或数据段 AREA STACK, NOINIT, READWRITE, ALIGN=3 汇编一段内存空间名字叫STACK,不初始化,可读可写,8字节对齐 SPACE:用于分配一定大小的内存空间,单位为字节。 Stack_Mem SPACE Stack_Size 分配 Stack_Size大小的内存空间名字叫Stack_Mem, 标号__initial_sp紧挨着SPACE语句之后放置,表示栈的结束地址,即栈顶地址,因为STM32的栈是向下生长的,所以初始化以后栈指针要指向栈的末尾地址(高地址)。 Heap_Size EQU 0x00000200 AREA HEAP, NOINIT, READWRITE, ALIGN=3 __heap_base Heap_Mem SPACE Heap_Size __heap_limit 初始化堆,为什么要有堆?堆用于动态内存的分配。大家可以做一个实验,用malloc函数申请内存,将堆空间改大,测试可以申请到的空间是否变大? 前两行和初始化栈部分代码一样的意义。 __heap_base放置在SPACE之前表示堆的起始地址。 Heap_Mem SPACE Heap_Size 分配Heap_Size大小的空间名字叫Heap_Mem __heap_limit放置在SPACE之后表示堆的结束地址。 PRESERVE8 THUMB PRESERVE8:指定当前文件的堆栈按照8字节对齐。 THUMB:表示后面的指令为THUMB指令。 AREA RESET, DATA, READONLY;汇编一个数据段 名字是REST 只读 EXPORT __Vectors ;表示向量表的起始地址 EXPORT __Vectors_End ;表示向量表的结束地址 EXPORT __Vectors_Size ;后续用来表示向量表的大小 再看中断向量表 __Vectors DCD __initial_sp ; Top of Stack 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 FMC_IRQHandler ; FMC 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 CRYP_IRQHandler ; CRYP crypto DCD HASH_RNG_IRQHandler ; Hash and Rng DCD FPU_IRQHandler ; FPU DCD UART7_IRQHandler ; UART7 DCD UART8_IRQHandler ; UART8 DCD SPI4_IRQHandler ; SPI4 DCD SPI5_IRQHandler ; SPI5 DCD SPI6_IRQHandler ; SPI6 DCD SAI1_IRQHandler ; SAI1 DCD LTDC_IRQHandler ; LTDC DCD LTDC_ER_IRQHandler ; LTDC error DCD DMA2D_IRQHandler ; DMA2D __Vectors_End 中断向量表映射到0地址,也就是说中断向量表从flash起始地址处开始存储。 DCD 分配以字为单位的空间,并要求初始化他们,在向量表中,DCD分配了一堆内存,并且以ESR的入口地址初始化它们。 说白了,中断向量表实际上是一个32位的整形数组,一个元素对应一个中断/异常,数组存放在FLASH的起始地址。数组元素的值就是中断/异常服务函数的入口地址。那我们在MDK中debug一下,观察以下是不是这样子。 发现并不一样,其实是一样的。最低位表示的不是地址是处理器的状态。CM4指令至少是半字对齐的,所以最低位总是0,这时候,最低位用来标记处理器是ARM状态还是Thumb状态。cortex-M3权威指南有如下解释。 下面是复位中断函数 ; Reset handler 复位中断函数 Reset_Handler PROC ;PROC表示子程序的开始 EXPORT Reset_Handler [WEAK] IMPORT SystemInit IMPORT __main LDR R0, =SystemInit BLX R0 LDR R0, =__main;__main是C库函数 想要使用__main这个C库函数 必须勾选微库选项 BX R0 ENDP 在复位中断函数中都做了哪些事? 将SystemInit函数的地址加载到R0中,执行SystemInit函数 将__main函数的地址加载到R0中,执行__main函数。 __main函数是标准C库函数,__main函数会调用main函数。 ;初始化堆和栈,文件开始只是开辟了堆和栈 并没有初始化 此处初始化堆和栈 此部分代码由C库__main调用 ;******************************************************************************* IF :DEF:__MICROLIB ; 如果定义了微库 执行这一部分 EXPORT __initial_sp EXPORT __heap_base EXPORT __heap_limit ELSE ; 如果没定义微库执行这一部分 IMPORT __use_two_region_memory EXPORT __user_initial_stackheap 最后就是初始化栈了。 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1618 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1545 浏览 1 评论
979 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1597 浏览 2 评论
1864浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
645浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
516浏览 3评论
532浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
505浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 18:35 , Processed in 0.730284 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号