原创 STM32启动代码概述

2008-7-23 20:30 17125 12 29 分类: MCU/ 嵌入式

一般嵌入式开发流程就是先建立一个工程,再编写源文件,然后进行编译,把所有的 *.s文件和 *.c文件编译成一个 *.o文件,再对目标文件进行链接和定位,编译成功后会生成一个 *.hex文件和调试文件,接下来要进行调试,如果成功的话,就可以将它固化到 flash 里面去。


启动代码是用来初始化电路以及用来为高级语言写的软件作好运行前准备的一小段汇编语言,是任何处理器上电复位时的程序运行入口点。


比如,刚上电的过程中,PC机会对系统的一个运行频率进行锁定在一个固定的值,这个设计频率的过程就是在汇编源代码中进行的,也就是在启动代码中进行的。与此同时,设置完后,程序开始运行,注意,程序是在内存中运行的。这个时候,就需要把一些源文件从flash里面copy到内存中,又要对它们进行初始化读写,这又有频率的设置。这些都是初始化。


初始化完成后,我们又要设置一些堆栈,要跳到C语言的main函数里面运行。这就需要堆栈。对普通的ARM CPU有这样一个要求:在绝对地址为零的地方要放置一个异常向量表,但并不是所有的ARM CPU都留有这个一个空间,这就需要用到映射的功能。我们可以将其它地方的一些空间映射到绝对地址里面。当发生异常时,ARM核来读取异常中断表的时候,它会使用映射之后的那个表,这个就可以接着往下执行,否则在绝对地址零的地方找不到任何信息,程序就会死掉。这些运行的环境全部建立好后,程序就会跳转到我们的main函数里面。


总之,启动代码,就是对最小系统的初始化。 包括晶振,CPU频率等。


启动代码的最小系统是: 异常向量表的初始化 存储区分配 初始化堆栈 高级语言入口函数调用 – main()函数。


程序的启动过程:


点击看大图


 


 


以下面这个例子为例,编译完后, DEBUG后,我们可以看到,光标指向绝对地址为零的地方,这里存放的就是一个异常向量表。


 


712d47ed-1fe3-4cab-9c0f-c0d60d482658.jpg


 


它对应在 startup.s 里的源文件如下:


 


点击看大图


 


单步运行后,马上跳转到初始化CPU的频率。即初始化锁相环,将其锁在一个固定的频率。具体代码如下:


; Setup PLL


                IF      PLL_SETUP <> 0


                LDR     R0, =PLL_BASE


                MOV     R1, #0xAA


                MOV     R2, #0x55


<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 


;  Configure and Enable PLL


                MOV     R3, #PLLCFG_Val


                STR     R3, [R0, #PLLCFG_OFS]


                MOV     R3, #PLLCON_PLLE


                STR     R3, [R0, #PLLCON_OFS]


                STR     R1, [R0, #PLLFEED_OFS]


                STR     R2, [R0, #PLLFEED_OFS]


 


;  Wait until PLL Locked


PLL_Loop        LDR     R3, [R0, #PLLSTAT_OFS]


                ANDS    R3, R3, #PLLSTAT_PLOCK


                BEQ     PLL_Loop


 


;  Switch to PLL Clock


                MOV     R3, #(PLLCON_PLLE:OR:PLLCON_PLLC)


                STR     R3, [R0, #PLLCON_OFS]


                STR     R1, [R0, #PLLFEED_OFS]


                STR     R2, [R0, #PLLFEED_OFS]


                ENDIF   ; PLL_SETUP


 


然后再初始化每一种模式的堆栈,再进行单步运行的时候,下面我们可以看到,它自动跳转到 main()函数:


; Enter the C code


 


                IMPORT  __main


                LDR     R0, =__main


                BX      R0


 


 


                IF      :DEF:__MICROLIB


 


                EXPORT  __heap_base


                EXPORT  __heap_limit


 


                ELSE


 


这个时候,程序会运行各种 scatterload函数,将我们的堆栈、全局变量等内容拷贝到内存中去。拷贝完后,就正式跳转到我们的 main() 函数中来执行了。


 


点击看大图


 


这就是启动代码执行的全过程,呵呵,平时我们看到以为只是执行main()函数就行了,是不是没有想到在执行 main() 函数后还有这么多学问呢?


 


如果觉得对你有有帮助,请顶一顶,这是对我很大的支持!


 


 

PARTNER CONTENT

文章评论17条评论)

登录后参与讨论

用户1865310 2015-12-18 14:53

分析的很好,学习了,辛苦楼主!

用户377235 2013-10-7 11:47

长见识了!!!!

用户377235 2013-8-13 10:04

初学者的福音。顶

用户377235 2013-6-20 10:45

很感谢!

用户377235 2012-10-25 09:41

学习了。谢谢

用户1444478 2012-7-13 17:29

mark~~学习了,一直以为程序是从main函数开始执行,其实它只是特殊的一个函数,前面还是一些初始化的指令要执行的。

用户506238 2009-2-17 09:29

是 Run to main()吗? 我试过了,不行啊。 就是从LDR R0,=__main开始。 恳请赐教。

daiqiumiao_806246054 2008-9-25 11:14

在options选项里面有一个钩,如果钩上了就默认从main开始.把钩去掉即可.

用户1086080 2008-9-22 21:05

为什么你的启动可以从0x000000000开始debug??我每次都只能从0x080000FC开始??就是从LDR R0,=__main开始,什么设置可以这样?我都试过了,还是没找到,郁闷。。。RVMDK 3.22a,STLINKII 启动代码在操作系统的环境下就很关键了,如果不用操作系统,确实没有太大意义,

用户1086080 2008-9-22 21:04

为什么你的启动可以从0x000000000开始debug??我每次都只能从0x080000FC开始??就是从LDR R0,=__main开始,什么设置可以这样?我都试过了,还是没找到,郁闷。。。RVMDK 3.22a,STLINKII 启动代码在操作系统的环境下就很关键了,如果不用操作系统,确实没有太大意义,
相关推荐阅读
daiqiumiao_806246054 2011-01-06 13:57
linux下yum代理设置
    我们在安装好linux后,经常会使用yum来更新系统,但是系统默认的代理是国外的,国内一般的网络不能访问,这里讲解具体做法,把代理换成国内的。attachment download      ...
daiqiumiao_806246054 2010-12-30 09:48
【转】ORACLE 10g下载地址
Oracle Database 10g Release 2 (10.2.0.1.0) Enterprise/Standard Edition for Microsoft Windows (32-bit...
daiqiumiao_806246054 2010-11-29 11:06
找工作的进来看
如下是我所有的开放性问题回答,希望对大家有帮助!1.      When choosing your first job/employer, what will you consider and wh...
daiqiumiao_806246054 2010-11-29 09:47
中长期规划---螺旋式上升方式修改完善职业之路
一、中长期职业发展的自我准备1、心态上随时做好准备 机会是给有准备的人的------“有准备”是你在做准备的过程中让“别人”认为你“有准备”!别人是包括你现在的老板和别的老板,以及你身边的人!他们对你...
daiqiumiao_806246054 2010-03-17 21:26
移动
分集方式传输损耗和距离关系光纤网络G网...
daiqiumiao_806246054 2010-03-17 09:40
GSM
特点  使用直观  GSM系统有几项重要特点:防盗拷能力佳、网络容量大、手机号码资源丰富、通话清晰、稳定性强不易受干扰、信息灵敏、通话死角少、手机耗电量低。  技术特点  1.频谱效率。由于采用了高效...
EE直播间
更多
我要评论
17
12
关闭 站长推荐上一条 /3 下一条