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

相关文章

nginx启动命令和默认配置文件的使用

《nginx启动命令和默认配置文件的使用》:本文主要介绍nginx启动命令和默认配置文件的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录常见命令nginx.conf配置文件location匹配规则图片服务器总结常见命令# 默认配置文件启动./nginx

Nexus安装和启动的实现教程

《Nexus安装和启动的实现教程》:本文主要介绍Nexus安装和启动的实现教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、Nexus下载二、Nexus安装和启动三、关闭Nexus总结一、Nexus下载官方下载链接:DownloadWindows系统根

Java中实现线程的创建和启动的方法

《Java中实现线程的创建和启动的方法》在Java中,实现线程的创建和启动是两个不同但紧密相关的概念,理解为什么要启动线程(调用start()方法)而非直接调用run()方法,是掌握多线程编程的关键,... 目录1. 线程的生命周期2. start() vs run() 的本质区别3. 为什么必须通过 st

Oracle修改端口号之后无法启动的解决方案

《Oracle修改端口号之后无法启动的解决方案》Oracle数据库更改端口后出现监听器无法启动的问题确实较为常见,但并非必然发生,这一问题通常源于​​配置错误或环境冲突​​,而非端口修改本身,以下是系... 目录一、问题根源分析​​​二、保姆级解决方案​​​​步骤1:修正监听器配置文件 (listener.

MySQL版本问题导致项目无法启动问题的解决方案

《MySQL版本问题导致项目无法启动问题的解决方案》本文记录了一次因MySQL版本不一致导致项目启动失败的经历,详细解析了连接错误的原因,并提供了两种解决方案:调整连接字符串禁用SSL或统一MySQL... 目录本地项目启动报错报错原因:解决方案第一个:第二种:容器启动mysql的坑两种修改时区的方法:本地

MySQL启动报错:InnoDB表空间丢失问题及解决方法

《MySQL启动报错:InnoDB表空间丢失问题及解决方法》在启动MySQL时,遇到了InnoDB:Tablespace5975wasnotfound,该错误表明MySQL在启动过程中无法找到指定的s... 目录mysql 启动报错:InnoDB 表空间丢失问题及解决方法错误分析解决方案1. 启用 inno

无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案

《无法启动此程序因为计算机丢失api-ms-win-core-path-l1-1-0.dll修复方案》:本文主要介绍了无法启动此程序,详细内容请阅读本文,希望能对你有所帮助... 在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是"api-ms-win-core-path-l1-1-0.dll丢失

解决tomcat启动时报Junit相关错误java.lang.ClassNotFoundException: org.junit.Test问题

《解决tomcat启动时报Junit相关错误java.lang.ClassNotFoundException:org.junit.Test问题》:本文主要介绍解决tomcat启动时报Junit相... 目录tomcat启动时报Junit相关错误Java.lang.ClassNotFoundException

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