完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一.概述
在系统上电时需要先执行一段引导程序,也称bootloader程序,来完成对系统运行环境的初始化工作。就和 PC 上的 BIOS程序一样,bootloader 就相当于 BIOS。 基于ARM架构的处理器其内核启动流程大同小异,本文就基于cortex-M4内核的MCU以及基于cortex-A7内核的MPU,对其启动流程做简要分析。 二.cortex-M4内核启动流程 在我们进行单片机编程的时候,通常没有考虑过自己写bootloader程序,直接编写main函数就能运行。那是因为半导体厂商给我们写好了bootloader,通常不需要我们修改。以STM32F4系列MCU为例,可以看到在我们的工程中存在startup_stm32f40_41xxx.s这个文件,这个文件是使用汇编写的,也就是bootloader程序。 在单片机上电时,首先指向的就是startup_stm32f40_41xxx.s这个文件,因为在这个文件中完成了对系统的初始化工作。下面具体看看做了哪些事情。在这个文件上方给出了这样一段描述: This module performs: ;* - Set the initial SP //初始化SP指针 ;* - Set the initial PC == Reset_Handler //设置PC指针指向Reset_Handler ;* - Set the vector table entries with the exceptions ISR address //设置中断向量表 ;* - Configure the system clock and the external SRAM mounted on //调用SystemInit函数进行系统初始化,包括时钟、偏移地址等,且执行SystemInit函数后跳转回来 ;* STM324xG-EVAL board to be used as data memory (optional, ;* to be enabled by user) ;* - Branches to __main in the C library (which eventually //最终跳转到main函数执行,且不再跳转回来,因此汇编初始化只执行一次,一旦跳出就不会回来。 ;* calls main()). ;* After Reset the CortexM4 processor is in Thread mode, ;* priority is Privileged, and the Stack is set to Main. 从上面的描述中可以大概看出初始化工作做了哪些事情:包括堆栈初始化、SP初始化、PC初始化、系统时钟初始化并最终跳转到main函数。 1.在代码最开始进行定义中断向量表 __Vectors DCD __initial_sp ; Top of Stack //初始化SP指针指向栈顶,栈顶地址:0X08000000 DCD Reset_Handler ; Reset Handler //复位中断向量(中断向量表起始地址):0X08000004 DCD NMI_Handler ; NMI Handler //非可屏蔽中断向量:0X08000008 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 .................. .................. .................. 2.编写中断服务函数(重点分析Reset_Handler复位中断函数) ; Reset handler Reset_Handler PROC //执行Reset_Handler中断服务函数 EXPORT Reset_Handler [WEAK] IMPORT SystemInit //输入SystemInit IMPORT __main //输入__main LDR R0, =SystemInit //将SystemInit函数的地址放在R0寄存器中 BLX R0 //跳转到SystemInit函数执行,并将返回地址放在LR寄存器中,执行完返回!!! LDR R0, =__main //将main函数的地址放在R0寄存器中 BX R0 //跳转到main函数执行,并且不会返回!!! ENDP 可以看出,在Reset handler中断服务函数中主要完成了两件事: (1)调用SystemInit进行系统初始化 (2)跳转到mian处执行并不再跳回(因为BX R0并未保存返回地址至LR) 3.分析SystemInit()函数 SystemInit()系统初始化函数主要做了一下几件事情: (1)设置是否开启FPU (2)进行系统时钟初始化配置 (3)设置中断向量表偏移地址(ARM处理器默认中断向量表地址为:0x00000000,这里FLASH起始地址是0x08000000,因此设置偏移地址为0x08000000) 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 System clock source, PLL Multiplier and Divider factors, AHB/APBx prescalers and Flash settings ----------------------------------*/ SetSysClock(); /* 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 } 4. 启动过程总结 <1>初始化堆栈、SP指针、令PC指向Reset_Handler(也就是最先执行复位中断服务函数) <2>定义中断向量表(后面在中断发送时会根据中断向量表找到中断服务函数的入口地址) <3>由于最开始PC指针指向了Reset_Handler中断,因此先执行Reset_Handler中断服务函数(进行初始化工作:包括初始化时钟,FPU,设置VTOR中断向量表偏移地址等) <4>在Reset_Handler服务函数中SystemInit执行完返回并跳转到mian函数(采用BX跳转,不会返回了),进入用户程序执行,至此,系统启动,boot程序作用终结。 <5>通常main函数是while死循环执行的方式,那么当中断来的时候怎样执行呢?别忘了我们在bootloader程序的一开始就定义了中断向量表,将各中断都注册了(包括外部中断和内部中断),并且有系统或用户实现其中断服务函数。当有中断来临时系统会自动跳转到中断向量表,并根据中断号查找中断向量表获得中断服务子程序的入口地址,并跳转指向,中断指向完成后跳回main函数继续指向。 三.cortex-A7内核启动流程 通常ARM的A系列处理器会基于linux系统做开发,由专门的bootloader程序做引导。常用的例如U-BOOT。这里我们不分析U-BOOT,只是按照上面的MCU裸机开发的方式分析cortex-A7内核启动流程。具体过程和上面大同小异。 1.定义中断向量表 _start: //此处为定义中断向量表,后面需写其执行部分 ldr pc, =Reset_Handler /* 复位中断 */ ldr pc, =Undefined_Handler /* 未定义中断 */ ldr pc, =SVC_Handler /* SVC(Supervisor)中断 */ ldr pc, =PrefAbort_Handler /* 预取终止中断 */ ldr pc, =DataAbort_Handler /* 数据终止中断 */ ldr pc, =NotUsed_Handler /* 未使用中断 */ ldr pc, =IRQ_Handler /* IRQ中断 */ ldr pc, =FIQ_Handler /* FIQ(快速中断)未定义中断 */ 可以看出Cortex-A中断向量表有8个中断,比上面的M4内核中断少了很多,而且我们常见的中断都没有了,这是为什么?这是因为Cortex-A内核有9种运行模式,其中断系统也更加复杂,因此中间又封装了一层,将所有中断分为了以上几类,我们常用的一些中断都在IRQ_Handler这一大类里面。在上面的表中我们重点关注Reset_Handler和IRQ_Handler。因为Reset_Handler完成了系统初始化,IRQ_Handler是用户级中断。 2.Reset_Handler中断服务函数 /******编写复位中断服务函数Reset_Handler,内容如下:*******/ Reset_Handler: /*1)关闭I,D Cache和MMU。 CP15寄存器: MRC将CP15协处理器中的寄存器数据读到ARM寄存器中。 MRC就是读CP15寄存器,MCR就是写CP15寄存器,MCR指令格式如下:*/ MCR{cond} p15, |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1617 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1543 浏览 1 评论
977 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1595 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
644浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
515浏览 3评论
531浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
504浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 05:57 , Processed in 0.655809 second(s), Total 46, Slave 39 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号