ARM 之 Cortex-M/R 内核启动过程 / 程序启动流程(基于IAR)

2019-05-08 16:15:07 来源:互联网
标签:
ARM   Cortex-M   IAR

这里基于 IAR 的启动流程与之前的并没有太大区别,因为这是 Cortex-M/R 内核规定好的。无论是 ARMCC 还是 IAR 都需要遵循内核的规定。区别主要在于初始化的个函数接口不同!

 

相比于 《ARM 之 Cortex-M/R 内核启动过程 / 程序启动流程(基于ARMCC)》 IAR 关于这方面的介绍就少多了,不像 ARM 提供了各种文档来详细介绍各个方面!如果想要更深入了解这一部分,建议去 ARM 官网看看其文档。


以下所有内容,来自于官方文档《IAR C/C++ Development Guide Compiling and Linking》,进行了一些翻译添加了一些自己的理解!

 

启动流程

嵌入式应用程序的执行,分为三个阶段:

 

初始化阶段

执行阶段

退出阶段

初始化阶段

 

在系统启动期间,在进入main()函数之前执行初始化序列。 此序列执行目标硬件和C / C ++环境所需的初始化。初始化是在应用程序(CPU复位)启动但是进入用户的main()函数之前来执行的。初始化阶段可以简单地分为:

 

硬件初始化,通常至少初始化堆栈指针。

 

硬件初始化通常在系统启动代码cstartup.s中执行,如果需要,还可以通过您提供的额外低级例程执行。 它可能包括重置/启动其余硬件,设置CPU等,以准备软件C / C++系统初始化。

 

 

When the CPU is reset it will start executing at the program entry label __iar_program_start in the system startup code.

 

The stack pointer is initialized to the end of the CSTACK block

 

For Arm7/9/11, Cortex-A, and Cortex-R devices, exception stack pointers are initialized to the end of each corresponding section

 

The function __low_level_init is called if you defined it, giving the application a chance to perform early initializations.

 

C/C++软件系统初始化

 

通常,这包括确保在调用main函数之前,每个全局(静态链接)的C / C ++符号都会收到其正确的初始化值。

 

 

Static and global variables are initialized. That is, zero-initialized variables are cleared and the values of other initialized variables are copied from ROM to RAM memory. This step is skipped if __low_level_init returns zero. 静态和全局变量已初始化。 也就是说,清零初始化为零的变量,并将其他初始化变量的值从ROM复制到RAM存储器。 如果 __low_level_init 返回零,则跳过此步骤。

 

In Standard C, all static variables—variables that are allocated at a fixed memory address—must be initialized by the runtime system to a known value at application startup. This value is either an explicit value assigned to the variable, or if no value is given, it is cleared to zero. In the compiler, there are exceptions to this rule, for example variables declared __no_init, which are not initialized at all.在标准C中,所有静态变量 - 在固定内存地址分配的变量 - 必须由运行时系统初始化为应用程序启动时的已知值。 此值是分配给变量的显式值,或者如果没有给出值,则将其清零。 在编译器中,此规则有例外,例如声明为__no_init的变量,它们根本没有初始化。

 

The compiler generates a specific type of section for each type of variable initialization:编译器为每种类型的变量初始化生成特定类型的节:

 

 

Static C++ objects are constructed 构造静态c++对象

 

The main function is called, which starts the application. 调用主函数,启动应用程序。

 

应用程序初始化

这完全取决于您的应用程序。 它可以包括设置RTOS内核并启动RTOS驱动的应用程序的初始任务。 对于裸机应用程序,它可以包括设置各种中断,初始化通信,初始化设备等。

 

对于基于ROM / flash的系统,常量和函数已经放在ROM中。 放置在RAM中的所有符号必须在调用main函数之前初始化。 链接器已将可用RAM划分为变量,堆栈,堆等的不同区域。

 

以下序列说明简要概述了初始化的不同阶段。

 

1.当应用程序启动时,系统启动代码首先执行硬件初始化,例如初始化栈顶指针以指向预定义堆栈区域的末尾:

 

 

2.然后,清除应该零初始化的存储器,换句话说,用零填充:

 

 

通常,这些数据指的是那些初始化为零的数据; 例如,变量声明为int i = 0;

 

3.对于已经初始化的数据,例如,声明的数据int i = 6;,初始化器从ROM复制到RAM:

 

 

4.最终,main()函数被调用:

 

 

执行阶段

The software of an embedded application is typically implemented as a loop which is either interrupt-driven or uses polling for controlling external interaction or internal events. For an interrupt-driven system, the interrupts are typically initialized at the beginning of the main function.嵌入式应用程序的软件通常实现为循环,该循环可以是中断驱动的,也可以使用轮询来控制外部交互或内部事件。 对于中断驱动的系统,中断通常在主函数的开头初始化。

 

In a system with real-time behavior and where responsiveness is critical, a multi-task system might be required. This means that your application software should be complemented with a real-time operating system. In this case, the RTOS and the different tasks must also be initialized at the beginning of the main function. 在具有实时行为且响应性至关重要的系统中,可能需要多任务系统。 这意味着您的应用程序软件应该配备实时操作系统。 在这种情况下,还必须在main函数的开头初始化RTOS和不同的任务。

 

退出阶段

通常,嵌入式应用程序的执行永远不会结束。 如果推出了,则必须定义正确的结束行为。

 

要以受控方式终止应用程序,请调用标准C库函数之一 exit,_Exit,quick_exit 或 abort,或从main 返回。 如果从main 返回,则自动执行 exit 函数,这意味着调用静态和全局变量的 C++ 析构函数(仅限C ++)并关闭所有打开的文件。

 

当然,如果程序逻辑不正确,应用程序可能会以不受控制的异常方式终止 - 系统崩溃。

 

 

应用程序可以通过两种不同方式正常终止:

 

Return from the main function

 

Call the exit function.

 

因为 C 标准声明这两个方法应该是等价的,所以如果main()函数返回,系统启动代码会调用exit() 函数。传递给exit()函数的参数是main()的返回值。

 

默认退出函数用C语言编写。它调用一个小的汇编程序函数_exit,它将:

 

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 __exit

 

When __exit is reached, stop the system.

 

应用程序也可以通过调用 abort,_Exit 或 quick_exit 函数退出。中止函数只是调用__exit来暂停系统,并且不执行任何类型的清理。The _Exit function is equivalent to the abort function, except for the fact that _Exit takes an argument for passing exit status information._Exit函数等同于 abort 函数,事实上,_Exit接受一个参数来传递退出状态信息。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函数等同于__Exit函数,只是它在调用__exit之前会刁艳红每个传递给_quick_exit的函数。

 

如果您希望应用程序在退出时执行任何额外操作,例如重置系统(如果使用atexit是不够的),您可以编写自己的__exit(int)函数实现。

 

启动相关函数

在基于 ARM 的启动流程中,我们介绍了各启动相关的函数全部位于 ARM 编译套件的库文件中。IAR 则直接提供了相关函数的源代码,源码使用汇编语言编写!

 

处理启动和终止的代码位于源文件cstartup.s,cmain.s,cexit.s中,这些文件位于arm\src\lib\arm 或 arm\src\lib\thumb目录中(针对 Cortex-M的 thumb 指令)和位于arm\src\lib\runtime目录中的low_level_init.c。其中,arm\src\lib\arm下面的文件如下图所示:

 

 

关于 Thumb 指令的这里我们暂不说明

 

前面我们已经分析过,第一个需要调用的函数是__iar_program_start,该函数就位于cstartup.s这个文件中!

 

启动示例分析

下面我们以STM32F373CB片子为例,看看其在 IAR 中调试时的汇编代码。直接进调试模式,注意:需要将 设置 -> 调试器 -> Run to main 去掉,如下图:

 

 

然后 直接进入调试模式,首先看看终端向量表部分:

 

 

符合前面文章介绍的 Cortex-M/R内核的规定!接着我们看到的就是复位中断的服务函数

 

 

从上面的汇编代码可以看出,__iar_program_start 跳转到了一个叫做?main的符号处,代码如下:

 

 

里面有详细的函数调用关系!

 

启动文件

目前,多数 MCU 厂商都提供一个启动文件。当然,编程者也可以自己编写启动文件,具体编写要求ARM的网站上都有相关文档进行说明。下面分析一下 STM32 启动文件startup_stm32f37x.s,具体看里面的注释。

 

由于代码过长,感兴趣的朋友可以去原文查看(https://blog.csdn.net/ZCShouCSDN/article/details/89815785)

 
关注与非网微信 ( ee-focus )
限量版产业观察、行业动态、技术大餐每日推荐
享受快时代的精品慢阅读
 

 

继续阅读
ARM 为何也对华为采取禁运措施?如此现状华为又将采取怎样的措施?

日前,BBC透露,英国芯片设计公司ARM已告知员工,必须暂停和华为的业务往来。ARM要员工停止和华为及其子公司的“所有有效合同、支持权利和任何待定合作”,以遵守最近的美国贸易禁令。在一份公司备忘录中,该公司称其设计包含“美国原产技术”,虽然ARM不是美国的公司,也会受到特朗普政府禁令的影响。

遭美国打压,台积电为何选择继续供货华为?
遭美国打压,台积电为何选择继续供货华为?

“无惧老美!”台湾晶圆代工龙头台积电一周来二度表态对华为出货不变,岛内《中时电子报》对此作出解读,并称台积电力挺华为。

华为的胜算在哪里?
华为的胜算在哪里?

从目前给华为断供的公司看来,美国政府从软件、硬件以及终端设备三方面对华为展开了“封锁”。面对越来越多的公司向华为断供,华为能坚持到最后吗?

华为遭遇各种“打压”,这是场迟早要打的阵地战?

从目前已知的消息来看,Google暂停与华为的商业合作(禁令延迟90天实施)、英国两大主流通讯运营商EE和Vodafone相继宣布“暂停”开售华为5G手机、微软在线商店下架华为MateBook X Pro。

除美国之外,日本、英国也采取措施抵制华为,华为是否能抗住压力?

ARM公司在一份声明中表示,正在“遵守美国政府制定的所有最新规定”,ARM发言人拒绝就其与华为的合同目前的状况提供更多的信息。

更多资讯
物联网操作系统爆发期已至?国产供应商RT-Thread看好哪些市场
物联网操作系统爆发期已至?国产供应商RT-Thread看好哪些市场

“如今在RTOS方面,特别是物联网存在很多碎片化的应用,需要有操作系统来把整个碎片化的系统做很好的梳理,能够把底层和应用层做很好的架构建设,这是我的理解。”近日,在谈及意法半导体生态圈内,活跃于物联网操作系统领域的合作伙伴RT-Thread时,意法半导体微控制器事业部中国区高级经理曹锦东如是说。

华为操作系统的生态能做起来吗?
华为操作系统的生态能做起来吗?

前几天,美国商务部的工业和安全局(BIS)把华为公司加入其Entity List(实体清单)。华为面临着美国供应商“断供”的巨大压力。

Android真的是开源免费的项目吗?谷歌禁止华为完全推翻了这个言论

路透社的独家消息称,Google已经暂停与华为在Android领域的合作。报道称,华为下一代安卓智能手机也将不能使用包括Play Store、Gmail和YouTube等应用程序服务。

担心政府侵犯隐私,ACLU向亚马逊施压禁止向政府出售面部识别软件

针对亚马逊向美国执法部门出售面部识别技术的做法,美国公民自由联盟(American Civil Liberties Union)正在向亚马逊施加压力。

中国操作系统二十年

发生了什么?究竟又是什么影响了国产操作系统的发展?可能是技术、可能是人才、也可能是时机,迄今为止,仍然无一定论。

电路方案