iar stm32_欲练此功必先自宫之STM32汇编启动,放慢是为了更好的前行

2023-10-21 08:40

本文主要是介绍iar stm32_欲练此功必先自宫之STM32汇编启动,放慢是为了更好的前行,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在上一篇文章《假美猴王之三极管与MOS管,谁是悟空,谁又是六耳猕猴》中我们讲到了真假美猴王之三极管与MOS管的区别。今天来探讨一下武功秘籍的修炼,据说秘籍第一页就写道:欲练此功,必先自宫。意思就是说明一个道理,任何人要想成仙成佛,练就一身超神的本领,那么是要付出的代价并做好准备工作的。

而今天我们的要探讨的主角STM32处理器也不例外,别看它运行起来玉树临风,似乎无所不能,启动初期也要先苦练一番本领才行。那么这一部分都做了哪些工作呢?

STM32这款处理器使用的是的ARM的Cortex-M3内核,Cortex-M3内核有个特点就是在地址0x00000000存放的是全局的栈地址。紧接着从地址0x00000004执行(因为STM32是32位的处理器,一条指令正好对应4个字节),也就是从这个地址取出中断向量表的地址,跳转执行中断处理函数。

b3f6990a32b785204399ac1ed4095d7e.png

M3内核复位后程序执行过程

在前面文章《敢问路在何方,STM32迈出的第一步,却注定了它非凡的一生》中我们有介绍通过BOOT0和BOOT1引脚高低电平的不同组合,对应者三种不同的启动方式,同样也就对应着三种地址的映射: Flash system memory就是将0x00000000映射到了0x08000000;System memory就是将0x00000000映射到了0x1FFF0000;SRAM就是将0x00000000映射到了0x20000000。选择了哪种启动方式就会把0地址映射到对应物理地址。同样该区的物理地址最前面存放的就是栈地址和中断向量表。

        DATA__vector_table        DCD     sfe(CSTACK)        DCD     Reset_Handler             ; Reset Handler        DCD     NMI_Handler               ; NMI Handler        DCD     HardFault_Handler         ; Hard Fault Handler        DCD     0                         ; Reserved        DCD     0                         ; Reserved        DCD     0                         ; Reserved        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 detect                DCD     RTC_IRQHandler                 ; RTC through EXTI Line                DCD     FLASH_IRQHandler               ; FLASH                DCD     RCC_CRS_IRQHandler             ; RCC_CRS                DCD     EXTI0_1_IRQHandler             ; EXTI Line 0 and 1                DCD     EXTI2_3_IRQHandler             ; EXTI Line 2 and 3                DCD     EXTI4_15_IRQHandler            ; EXTI Line 4 to 15                DCD     TSC_IRQHandler                 ; TSC                DCD     DMA1_Channel1_IRQHandler       ; DMA1 Channel 1                DCD     DMA1_Channel2_3_IRQHandler     ; DMA1 Channel 2 and Channel 3                DCD     DMA1_Channel4_5_6_7_IRQHandler ; DMA1 Channel 4, Channel 5, Channel 6 and Channel 7                DCD     ADC1_COMP_IRQHandler           ; ADC1, COMP1 and COMP2                 DCD     LPTIM1_IRQHandler              ; LPTIM1                DCD     0                              ; Reserved                DCD     TIM2_IRQHandler                ; TIM2                DCD     0                              ; Reserved                DCD     TIM6_DAC_IRQHandler            ; TIM6 and DAC                DCD     0                              ; Reserved                DCD     0                              ; Reserved                DCD     TIM21_IRQHandler                ; TIM21                DCD     0                              ; Reserved                DCD     TIM22_IRQHandler               ; TIM22                DCD     I2C1_IRQHandler                ; I2C1                DCD     I2C2_IRQHandler                ; I2C2                DCD     SPI1_IRQHandler                ; SPI1                DCD     SPI2_IRQHandler                ; SPI2                DCD     USART1_IRQHandler              ; USART1                DCD     USART2_IRQHandler              ; USART2                DCD     RNG_LPUART1_IRQHandler         ; RNG and LPUART1                DCD     LCD_IRQHandler                 ; LCD                DCD     USB_IRQHandler                 ; USB

而中断处理函数的第一个就是复位中断处理函数Reset_Handler:

        THUMB        PUBWEAK Reset_Handler        SECTION .text:CODE:NOROOT:REORDER(2)Reset_Handler        LDR     R0, =SystemInit        BLX     R0        LDR     R0, =__iar_program_start        BX      R0                PUBWEAK NMI_Handler        SECTION .text:CODE:NOROOT:REORDER(1)

我们看下默认的复位中断处理函数里边都做了什么事情,首先将SystemInit函数的首地址存放到R0寄存器里边,然后跳转到R0寄存器的地址,即去执行IAR本身库文件中的SystemInit函数进行相关初始化。然后将__iar_program_start函数的首地址存放到R0寄存器里边,然后跳转到R0寄存器的地址,即去执行__iar_program_start函数。

那么__iar_program_start这个函数在哪里呢?没错,你在整个汇编文件中都没有找到!这个文件在IAR的安装目录里边,具体的路径是C:Program Files (x86)IAR SystemsEmbedded Workbench 7.2armsrclibhumb,我是将IAR装在C:Program Files (x86)目录下的,大家根据自己情况查找。在thumb目录下有个cstartup_M.s文件,文件代码如下:

        MODULE  ?cstartup        PUBLIC  __iar_program_start        EXTERN  __cmain        EXTERN  __vector_table        EXTWEAK __iar_init_core        EXTWEAK __iar_init_vfp        SECTION .text:CODE:REORDER(1)        THUMB__iar_program_start:        FUNCALL __iar_program_start, __iar_init_core        BL      __iar_init_core        FUNCALL __iar_program_start, __iar_init_vfp        BL      __iar_init_vfp        FUNCALL __iar_program_start, __cmain        BL      __cmain        REQUIRE __vector_table        END

__iar_program_start中分别调用了__iar_init_core,__iar_init_vfp和__cmain三个函数。前面两个函数式弱函数,在工程中没有定义,大家可以根据实际情况重写这两个函数。最后一个函数__cmain也在同目录下的cmain.s中定义:

        THUMB__cmain:?main:; Initialize segments.; __segment_init and __low_level_init are assumed to use the same; instruction set and to be reachable by BL from the ICODE segment; (it is safest to link them in segment ICODE).          FUNCALL __cmain, __low_level_init        bl      __low_level_init        cmp     r0,#0        beq     ?l1          FUNCALL __cmain, __iar_data_init3        bl      __iar_data_init3?l1:        REQUIRE ?l3        SECTION .text:CODE:NOROOT(2)        PUBLIC  _main        PUBLIC _call_main        THUMB__iar_init$$done:                 ; Copy initialization is done?l3:_call_main:        MOVS    r0,#0             ;  No parameters          FUNCALL __cmain, __iar_argc_argv        BL      __iar_argc_argv   ; Maybe setup command line          FUNCALL __cmain, main        BL      main_main:          FUNCALL __cmain, exit        BL      exit        END

其实最后就是进行了一个底层的初始化,然后就永久的跳转到main.c文件中的main函数了。至此,汇编部分代码结束,开始执行大家在main中编写的代码。

喜欢就在文末点个“关注”或者 “转发”,这样可以让更多的人学习哦!!!

有问题评论一起交流学习进步! 感谢!

更多优质文章请点击我的头像,选择“文章”标签!

这篇关于iar stm32_欲练此功必先自宫之STM32汇编启动,放慢是为了更好的前行的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/253243

相关文章

Redis在windows环境下如何启动

《Redis在windows环境下如何启动》:本文主要介绍Redis在windows环境下如何启动的实现方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Redis在Windows环境下启动1.在redis的安装目录下2.输入·redis-server.exe

解决SpringBoot启动报错:Failed to load property source from location 'classpath:/application.yml'

《解决SpringBoot启动报错:Failedtoloadpropertysourcefromlocationclasspath:/application.yml问题》这篇文章主要介绍... 目录在启动SpringBoot项目时报如下错误原因可能是1.yml中语法错误2.yml文件格式是GBK总结在启动S

SpringBoot启动报错的11个高频问题排查与解决终极指南

《SpringBoot启动报错的11个高频问题排查与解决终极指南》这篇文章主要为大家详细介绍了SpringBoot启动报错的11个高频问题的排查与解决,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一... 目录1. 依赖冲突:NoSuchMethodError 的终极解法2. Bean注入失败:No qu

一文带你了解SpringBoot中启动参数的各种用法

《一文带你了解SpringBoot中启动参数的各种用法》在使用SpringBoot开发应用时,我们通常需要根据不同的环境或特定需求调整启动参数,那么,SpringBoot提供了哪些方式来配置这些启动参... 目录一、启动参数的常见传递方式二、通过命令行参数传递启动参数三、使用 application.pro

SpringBoot项目启动报错"找不到或无法加载主类"的解决方法

《SpringBoot项目启动报错找不到或无法加载主类的解决方法》在使用IntelliJIDEA开发基于SpringBoot框架的Java程序时,可能会出现找不到或无法加载主类com.example.... 目录一、问题描述二、排查过程三、解决方案一、问题描述在使用 IntelliJ IDEA 开发基于

SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法

《SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法》本文主要介绍了SpringBoot项目启动错误:找不到或无法加载主类的几种解决方法,具有一定的参考价值,感兴趣的可以了解一下... 目录方法1:更改IDE配置方法2:在Eclipse中清理项目方法3:使用Maven命令行在开发Sprin

Nginx启动失败:端口80被占用问题的解决方案

《Nginx启动失败:端口80被占用问题的解决方案》在Linux服务器上部署Nginx时,可能会遇到Nginx启动失败的情况,尤其是错误提示bind()to0.0.0.0:80failed,这种问题通... 目录引言问题描述问题分析解决方案1. 检查占用端口 80 的进程使用 netstat 命令使用 ss

Android里面的Service种类以及启动方式

《Android里面的Service种类以及启动方式》Android中的Service分为前台服务和后台服务,前台服务需要亮身份牌并显示通知,后台服务则有启动方式选择,包括startService和b... 目录一句话总结:一、Service 的两种类型:1. 前台服务(必须亮身份牌)2. 后台服务(偷偷干

Windows设置nginx启动端口的方法

《Windows设置nginx启动端口的方法》在服务器配置与开发过程中,nginx作为一款高效的HTTP和反向代理服务器,被广泛应用,而在Windows系统中,合理设置nginx的启动端口,是确保其正... 目录一、为什么要设置 nginx 启动端口二、设置步骤三、常见问题及解决一、为什么要设置 nginx

springboot启动流程过程

《springboot启动流程过程》SpringBoot简化了Spring框架的使用,通过创建`SpringApplication`对象,判断应用类型并设置初始化器和监听器,在`run`方法中,读取配... 目录springboot启动流程springboot程序启动入口1.创建SpringApplicat