基于ARM CortexTM-M4的MQX-RTOS启动流程剖析*

2015-12-23 08:49张建王宜怀
自动化与信息工程 2015年4期
关键词:堆栈内核指针

张建 王宜怀



基于ARM CortexTM-M4的MQX-RTOS启动流程剖析*

张建1,2王宜怀1,2

(1.苏州大学计算机科学与技术学院 2.软件新技术与产业化协同创新中心)

结合ARM Cortex-M4的地址映射、工程链接文件intflash.ld分析Kinetis MK60DN512ZVLQ10芯片的地址空间的分配情况,剖析芯片从加电复位跳转到驻留在ROM开始地址的中断向量表处执行,依次完成系统堆栈指针、进程堆栈指针、切换堆栈指针等设置,最后调用MQX初始化函数完成MQX-RTOS的启动,在对启动过程的代码进行合理裁剪的基础上,给出较详细的注释,为研究其他RTOS的启动提供一定的借鉴。

MQX系统;RTOS;ARM Cortex-M4芯片;启动流程

0 引言

MQX(message queue executive)是一种广泛应用于工业控制、医疗电子、家用电器等领域的嵌入式实时操作系统(embedded real time operation system,RTOS),相对其他的嵌入式实时操作系统,其内核精简、实时性较高,具有技术支持、开发工具成熟、外设驱动丰富等特点而备受开发人员欢迎。RTOS的启动过程具有复杂性高和启动时间短的特点,深入剖析MQX-RTOS的启动流程,对提高软件开发、编写高效的软件代码有很大的帮助[1]。

以苏州大学飞思卡尔嵌入式实验中心发布的AMQXFW工程框架,结合ARM Cortex-M4的地址映射、工程链接文件intflash.ld分析Kinetis MK60DN512ZVLQ10芯片地址空间的分配情况[2]。剖析芯片从加电复位跳转到驻留在ROM开始地址(地址为0x0000_0000)的中断向量表处执行,依次设置系统堆栈指针、进程堆栈指针、切换堆栈指针、关看门狗、端口时钟门控、系统时钟、初始化全局变量,调用MQX初始化函数完成MQX-RTOS启动的复杂过程,对启动过程的代码进行合理的裁剪并给出剖析的注释,可深入理解MQX-RTOS的启动过程[3]。

1 存储器空间地址映射

存储器空间地址映像是芯片的“地图”,规定了芯片上所有设备的地址范围,不同芯片组的存储器空间地址映像也不相同。ARM Cortex-M4的K60系列的存储器空间地址映像对照如表1所示,MK60DN512ZVLQ10芯片没有FlexNVM和FlexRAM,其存储器空间地址映像对照如表2所示。

表1 K60系列芯片的存储器空间地址映像

表2 MK60DN512ZVLQ10芯片的存储器空间地址映像

ARM Cortex-M4的K60系列ROM地址范围为0x0000_0000~0x0FFF_FFFF,共计256MB的ROM区域,该区域主要存放中断向量表、操作系统代码和常量等内容。Kinetis MK60DN512ZVLQ10芯片只配置512 kB的Flash,其地址只使用了起始的512 kB地址空间,即0x0000_0000~0x0008_0000,该区域主要存放中断向量表、Flash模块配置信息、MQX-RTOS操作系统代码和常量等内容。K60系列的RAM地址范围为0x1800_0000~0x200F_FFFF,共计129 MB的RAM区域,主要存放运行时的中断向量表、支持操作系统运行的代码、常变量、静态变量、全局变量和堆栈等内容。Kinetis MK60DN512ZVLQ10芯片只配置了128 kB的SRAM,其地址只使用了SRAM_L末尾的64 kB和SRAM_U起始的64 kB空间,地址范围为0x1FFF_0000~0x0x2000_FFFF[4]。

Flash和SRAM存储空间的分配,在AMQXFW工程的链接文件intflash.ld中定义如下:

MEMORY

{

/* 异常中断向量表 */

vectorrom (RX): ORIGIN = 0x00000000, LENGTH = 0x00000400

/* Flash模块配置 */

cfmprotrom (R): ORIGIN = 0x00000400, LENGTH = 0x00000020

/* 代码和常量 */

rom (RX): ORIGIN = 0x00000420, LENGTH = 0x0007FBE0

/* SRAM */

ram (RW): ORIGIN = 0x1FFF0000, LENGTH = 0x00020000

/* 内核数据区结束处 */

end_of_kd (RW): ORIGIN = 0x2000FFF0, LENGTH = 0x00000000

/* 启动堆栈 */

bstack (RW): ORIGIN = 0x2000FA00, LENGTH = 0x00000200

/* 启动堆栈结束处 */

end_bstack (RW): ORIGIN = 0x2000FC00, LENGTH = 0x00000000

}

由intflash.ld文件的定义,MK60DN512ZVLQ10的ROM、RAM的地址映射分别如图1和图2所示;512 kB的ROM主要分为1 kB的中断向量表+32 B的Flash配置+(511 kB-32 B)的代码和常量区,其中1 kB的中断向量共包含256个中断项,每个中断占4个字节[5]。

图1 MK60DN512ZVLQ10 ROM地址空间映射

图2 MK60DN512ZVLQ10 RAM地址空间映射

128 kB的RAM由编译器根据MQX系统预定义的常量进行有条件地编译使用。一般来说,RAM主要有中断向量表、数据段、BSS段和内核数据等,其中内核数据区约从0x1FFF_0330开始,到0x2000_ FFFF结束,约为127 kB,不同的工程编译出来的内核数据区大小也不尽相同。

MK60DN512ZVLQ10芯片的启动可分为芯片启动和MQX-RTOS系统启动2个阶段,启动流程如图3所示。

2 芯片启动阶段

MK60DN512ZVLQ10芯片加电复位跳转到驻留在ROM开始地址的中断向量表处执行,依次设置系统堆栈指针、进程堆栈指针、切换堆栈指针、关看门狗、端口时钟门控、系统时钟、初始化全局变量[6]。

图3 MQX-RTOS启动流程

2.1引导

芯片上电,ARM Cortex-M4处理器架构的芯片将寄存器清0,同时自动执行0x0000_0000地址处的指令。对存储映射区域进行解析,位于0x0000_0000为ROM区域的中断向量表内容。引导程序从中断向量表中取第一个表项(地址为:0x0000_0000)的内容作为系统栈指针,即主堆栈指针(main stack pointer,MSP);从中断向量表中取第二个表项(地址为:0x0000_0004)的内容作为系统启动函数的地址,并放入程序计数器(Program Counter,PC)中,接着进入执行PC指向处的指令,进入__boot函数的执行。ROM起始的1 kB放置的256个中断,每个中断占4个字节,以下代码为前2个中断[7]。

/* 第1个中断项

* 中断系统栈指针,值在intflash.ld文件中定义,其值和end_bstack相同

* end_bstack=0x2000_FC00*/

(vector_entry)__BOOT_STACK_ADDRESS,

/* 第2个中断项

* 启动函数指针宏定义为__boot

* __boot为boot.s中的标号 */

BOOT_START,

...

2.2__boot启动

__boot启动代码在boot.s文件中,采用汇编语言编写加快启动速度。__boot主要设置了启动过程中禁中断、切换堆栈,并跳转到startup.c的__thumb_startup处运行。__boot代码如下。

__boot:

// 禁中断清除挂起标志

ldr r0, =NVIC_ICER0

ldr r1, =NVIC_ICPR0

ldr r2, =0xFFFFFFFF

mov r3, #8

// 循环设置8个禁中断清除挂起标志寄存器

_boot_loop:

cbz r3, _boot_loop_end

str r2, [r0], #4 /* NVIC_ICERx - 清除IRQ使能 */

str r2, [r1], #4 /* NVIC_ICPRx - 清除挂起IRQ标志 */

sub r3, r3, #1

b _boot_loop

_boot_loop_end:

// 用主堆栈指针值设置进程堆栈指针的值

mrs r0, MSP

msr PSP, r0

// 切换到PSP CONTROL[1]为1使用PSP 为0使用MSP

mrs r0, CONTROL

orr r0, r0, #2

msr CONTROL, r0

isb #15

// 跳转到startup.c的__thumb_startup处执行

.extern __thumb_startup

b __thumb_startup

2.3__thumb_startup函数

__thumb_startup函数在startup.c文件中,主要完成看门狗、端口时钟门控、系统时钟等设置,初始化全局变量,调用main函数,进入main函数运行。__thumb_startup函数代码如下:

//设置看门狗

wdog_disable1();

//设置端口时钟门控

gpio_io_init();

//初始化全局变量

zero_fill_bss();

//拷贝ROM至RAM,本文件中SUPPORT_ROM_TO_RAM定义为1

#if SUPPORT_ROM_TO_RAM

if (__S_romp != 0L)/* __S_romp 在intflash.ld中定义 */

__copy_rom_sections_to_ram();

#endif

//设置系统时钟

SystemClockSetup(ClockSource_EX50M,CoreClock_96M);

//进入主程序Main

exit(main(0, argv));

3 MQX-RTOS系统启动阶段

MQX-RTOS系统启动阶段主要是通过main函数调用_mqx函数完成MQX-RTOS系统的启动。

3.1 main函数

main函数在main.c文件中,主要根据定义的MQX初始化常量调用_mqx函数完成MQX-RTOS系统的启动。main函数代码如下:

//MQX初始化结构体常量MQX_init_struct,在mqx_init.c文件中赋值

extern const MQX_INITIALIZATION_STRUCT MQX_init_struct;

//调用_mqx,启动MQX-RTOS系统

_mqx( (MQX_INITIALIZATION_STRUCT_PTR) &MQX_init_struct );[8]

3.2_mqx函数

_mqx函数主要完成MQX-RTOS系统的启动,具体步骤如下:

1) 初始化内核数据区

内核数据区是负责记录MQX系统运行状态及资源使用情况的存储区,在开始正常工作之前,要为内核数据区指定合适的初始值。

初始化内核数据区依次执行:创建内核数据区访问指针→填充内核数据区→启动对中断的支持→创建系统空闲任务栈→创建就绪任务队列数组→创建任务操作信号量。

2) 初始化外设

MQX操作系统的运行需要硬件平台的支持,因此在系统启动过程中,需对硬件平台进行初始化设定。

初始化外设依次执行:初始化MQX中断系统→初始化系统时间滴答→初始化IO子系统。

3) 调度系统初始化与启动

启动调度系统是MQX启动过程的最后一个环节,成功启动调度系统后,整个系统中包含的应用任务将在调度系统的管理下有序地运行。

调度系统初始化与启动依次执行:设置缺省使用的时间片→创建并启动空闲任务→创建自启动应用任务→启动调度系统。

启动调度系统成功后,标志着RTOS系统成功启动,用户开发的程序可通过调度系统来运行。

4 结语

MQX-RTOS系统启动过程包括芯片启动和MQX系统启动2个阶段。MQX-RTOS系统成功启动调度系统后,由调度系统合理有序地调度各个任务、中断运行。本文主要结合苏州大学飞思卡尔嵌入式实验中心发布的AMQXFW工程框架进行深入剖析,对主要的启动代码进行分析,为从事RTOS系统的启动研究提供了研究基础,同时为基于MQX系统应用程序开发提供一定的借鉴。

参考文献

[1] 王宜怀,朱仕浪,姚望舒.嵌入式实时操作系统MQX应用开发技术—ARM Cortex-M微处理器[M].北京:电子工业出版社,2014.

[2] 朱仕浪,王宜怀,冯德旺.MQX实时操作系统构件化工程框架研究[J].武汉理工大学学报,2013,35(10):135-140.

[3] 蒋建武,王宜怀.基于ARM Cortex-M4的MQX中断机制深度剖析[J].电子技术与软件工程,2014(22):214-217,233.

[4] Freescale. MQX User Guide Rev.12[M]. 2014.

[5] 王宜怀,吴瑾,蒋银珍.嵌入式系统原理与实践——ARM Cortex-M4 Kinetis微控制器[M].北京:电子工业出版社, 2012.3.

[6] Freescale.K60 Sub-Family Reference Manual Rev.6[M]. 2011.

[7] Freescale. Freescale MQX RTOS Reference Manual Rev.16 [M]. 2014.

[8] Freescale. Cortex-MTM System Design Kit Technical Reference Manual Revision r0p0[M]. 2011.

[9] Giovani Gracioli, Sebastian Fischmeister. Tracing and recording interrupts in embedded software[J]. Journal of Systems Architecture,2012,58(9): 372-385.

[10] 董荣胜,古天龙.计算机科学与技术方法论[M].北京:人民邮电出版社,2002.

[11] Enkhbaatar Tumenjargal, Luubaatar Badarch, Hyeokjae Kwon, et al. Embedded software and hardware implementation system for a human machine interface based on ISOAgLib[J]. Journal of Zhejiang University-Science C (Computers & Electronics), 2013,14(3):155-166.

The Analysis of Starting Process of MQX-RTOS Based on ARM CortexTM-M4

Zhang Jian1,2Wang Yihuai1,2

(1.School of Computer Science & Technology, Soochow University, Suzhou 2.Collaborative Innovation Center of Novel Software Technology and Industrialization)

Based on ARM Cortex-M4’s address mapping and the project link file “intflash.ld”, this paper analyzes the address space distribution statement of Kinetis MK60DN512ZVLQ10 chip, and the starting process of the chip, which first jumps to the interrupt vector table at the beginning of the ROM address after power on reset, and then sets the system stack pointer, process stack pointer, switches stack pointer, and finally calls the MQX initialization function to complete the MQX-RTOS starting process. In the basis of reasonable tailoring the start-up code, this paper gives more detailed annotations, which provide certain reference for the further study of other RTOS.

MQX System; RTOS; ARM Cortex-M4 Chip; Booting Process

张建,男,1980年生,讲师/硕士,主要研究方向:MIS系统开发、嵌入式系统应用。E-mail: zhangjian2012@suda.edu.cn

王宜怀(通信作者),男,1962年生,教授/博士、博导,主要研究方向:嵌入式系统、传感网与智能控制技术。E-mail: Yihuaiw@suda.edu.cn

国家自然科学基金资助项目(61070169:无线网传感器网络中紧急事件信息发布的可靠性研究)

猜你喜欢
堆栈内核指针
基于行为监测的嵌入式操作系统堆栈溢出测试*
多内核操作系统综述①
强化『高新』内核 打造农业『硅谷』
活化非遗文化 承启设计内核
垂悬指针检测与防御方法*
微软发布新Edge浏览器预览版下载换装Chrome内核
为什么表的指针都按照顺时针方向转动
基于堆栈自编码降维的武器装备体系效能预测
浅析C语言指针
一种用于分析MCS-51目标码堆栈深度的方法