??在前面的文章《ARM 之 Cortex-M/R 内核启动过程 / 程序启动流程(基于ARMCC)》中已经介绍过了 Cortex-M/R 内核相关内容。这里基于 IAR 的启动流程与之前的并没有太大区别,因为这是 Cortex-M/R 内核规定好的。无论是 ARMCC 还是 IAR 都需要遵循内核的规定。区别主要在于初始化的个函数接口不同!
??相比于 《ARM 之 Cortex-M/R 内核启动过程 / 程序启动流程(基于ARMCC)》 IAR 关于这方面的介绍就少多了,不像 ARM 提供了各种文档来详细介绍各个方面!如果想要更深入了解这一部分,建议去 ARM 官 看看其文档。
??本位主要的内容,来自于 IAR 的官方文档《IAR C/C++ Development Guide Compiling and Linking》,在翻译了部分功能的基础上添加了一些自己的理解!
启动流程
嵌入式应用程序的执行,分为三个阶段:
- 初始化阶段
- 执行阶段
- 退出阶段
初始化阶段
??在系统启动期间,进入 函数之前执行初始化序列。 初始化序列处理目标硬件和 C/C++ 运行环境所需的初始化。初始化是在应用程序(CPU 复位)启动但是进入用户的 函数之前来执行的。初始化阶段可以简单地分为:
-
硬件初始化,通常至少初始化堆栈指针。
??硬件初始化通常在系统启动代码 中执行,如果需要,还可以通过用户提供的额外的低级接口()来执行用户自己的代码。 它可能包括重置/启动其余硬件,设置 CPU 等,以准备软件 C/C++ 系统初始化。
- Return from the main function
- Call the exit function.
- Call functions registered to be executed when the application ends. This includes C++ destructors for static and global variables, and functions registered with the standard function atexit. See also Setting up the atexit limit, page 110.
- Close all open files
- Call
- When is reached, stop the system.
??因为 C 标准声明这两个方法应该是等价的,所以如果函数返回,系统启动代码会调用 函数。传递给函数的参数是的返回值。
默认退出函数用C语言编写。它调用一个小的汇编程序函数_exit,它将:
??应用程序也可以通过调用 abort,_Exit 或 quick_exit 函数退出。中止函数只是调用来暂停系统,并且不执行任何类型的清理。The _Exit function is equivalent to the abort function, except for the fact that _Exit takes an argument for passing exit status information.函数等同于 abort 函数,事实上,接受一个参数来传递退出状态信息。The quick_exit function is equivalent to the _Exit function, except that it calls each function passed to at_quick_exit before calling __exit. quick_exit函数等同于函数,只是它在调用之前会刁艳红每个传递给的函数。
??如果您希望应用程序在退出时执行任何额外操作,例如重置系统(如果使用是不够的),您可以编写自己的函数实现。
启动相关函数
??在基于 ARM 的启动流程中,我们介绍了各启动相关的函数全部位于 ARM 编译套件的库文件中。IAR 则直接提供了相关函数的源代码,源码使用汇编语言编写!
??处理启动和终止的代码位于源文件,,中,这些文件位于 或 目录中(针对 Cortex-M的 thumb 指令)和位于目录中的。其中,下面的文件如下图所示:
从上面的汇编代码可以看出, 跳转到了一个叫做的符 处,代码如下:
0x80034c8: 0xb510 PUSH {R4, LR} 0x80034ca: 0x4907 LDR.N R1, [PC, #0x1c] ; 0x8 (8) 0x80034cc: 0x4479 ADD R1, R1, PC 0x80034ce: 0x3118 ADDS R1, R1, #24 ; 0x18 0x80034d0: 0x4c06 LDR.N R4, [PC, #0x18] ; 0x24 (36) 0x80034d2: 0x447c ADD R4, R4, PC 0x80034d4: 0x3416 ADDS R4, R4, #22 ; 0x16 0x80034d6: 0xe004 B.N 0x80034e2 0x80034d8: 0x680a LDR R2, [R1] 0x80034da: 0x1d08 ADDS R0, R1, #4 0x80034dc: 0x4411 ADD R1, R1, R2 0x80034de: 0x4788 BLX R1 0x80034e0: 0x4601 MOV R1, R0 0x80034e2: 0x42a1 CMP R1, R4 0x80034e4: 0xd1f8 BNE.N 0x80034d8 0x80034e6: 0xbd10 POP {R4, PC} 0x80034e8: 0x00000008 DC32 0x8 (8) 0x80034ec: 0x00000024 DC32 0x24 (36)Region$$Table$$Base: 0x80034f0: 0xffffdc57 DC32 0xffffdc57 (-9129) 0x80034f4: 0x0000085c DC32 0x85c (2140) 0x80034f8: 0x20000588 DC32 Uart1Info 0x80034fc: 0x00000000 DC32 0x0 (0) 0x8003500: 0xffffdadf DC32 0xffffdadf (-9505) 0x8003504: 0x000001b8 DC32 0x1b8 (440) 0x8003508: 0x0000010c DC32 0x10c (268) 0x800350c: 0x20000000 DC32 UpGradeCtrl/span>main:Region$$Table$$Limit:__cmain: 0x8003510: 0xf000 0xf80d BL __low_level_init ; 0x800352e 0x8003514: 0x2800 CMP R0, #0 0x8003516: 0xd001 BEQ.N _call_main ; 0x800351c 0x8003518: 0xf7ff 0xffd6 BL __iar_data_init3 ; 0x80034c8_call_main: 0x800351c: 0xf3af 0x8000 NOP.W 0x8003520: 0x2000 MOVS R0, #0 0x8003522: 0xf3af 0x8000 NOP.W 0x8003526: 0xf7ff 0xff2b BL main ; 0x8003380_main: 0x800352a: 0xf000 0xf802 BL exit ; 0x8003532__low_level_init: 0x800352e: 0x2001 MOVS R0, #1 0x8003530: 0x4770 BX LRexit: 0x8003532: 0xf000 0xb801 B.W _exit ; 0x8003538 0x8003536: 0x0000 MOVS R0, R0_exit: 0x8003538: 0x4607 MOV R7, R0 0x800353a: 0x4638 MOV R0, R7 0x800353c: 0xf000 0xf802 BL __exit ; 0x8003544 0x8003540: 0xe7fb B.N 0x800353a 0x8003542: 0x0000 MOVS R0, R0__exit: 0x8003544: 0xb580 PUSH {R7, LR} 0x8003546: 0xf3af 0x8000 NOP声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!