购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

2.6.5 MQX系统启动过程:_mqx函数剖析

在main函数中,将MQX初始化参数传入_mqx函数(在“..\MQX\kernel\ mqx.c”文件中),执行_mqx函数启动MQX系统。MQX启动过程大致如下:初始化内核数据区、初始化外设、调度系统初始化与启动。

1.初始化内核数据区

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

(1)创建内核数据区访问指针kernel_data。内核数据区空间是在链接命令文件中定义的,属于BSP的内容,为了提高相对于BSP的独立性,此处创建了一个内核数据区访问指针,并定义了访问接口。

上段程序为访问内核数据区铺平了道路。 今后的程序中,只要将 kernel_data定义为volatile KERNEL_DATA_STRUCT_PTR类型,再使用_GET_KERNEL_DATA(kernel_data)宏函数,随后就可以访问内核数据区了。

(2)填充内核数据区。在系统启动后,会从内核数据区获取系统信息,因此在MQX启动过程中要将为系统设定的初始信息填充到内核数据区中。

(3)启动对中断的支持。若使用中断,则需要为系统中断栈分配存储空间并在内核数据区中登记。当产生嵌套中断时,系统将把嵌套中断的上下文保存在中断栈中。高优先级中断服务例程执行返回后,从中断栈中恢复低优先级中断上下文继续执行。

(4)创建系统空闲任务栈。系统空闲任务是MQX系统自动维护的,非用户创建。当系统空闲任务被中断阻塞时,使用系统栈保存空闲任务的上下文。空闲任务栈的大小为PSP_STACK_START_STRUCT结构体的大小加上PSP_STACK_ INTERRUPT_OVERHEAD(116字节)再加上PSP_STACK_KLOG_OVERHEAD(因为没有启动内核日志,该字段大小为0字节)。

(5)创建就绪任务队列数组。就绪任务队列数组是任务调度系统操纵的主要对象,在系统初始化过程中,根据任务模板列表中用户定义的任务最低优先级(数值最大),创建就绪队列数目,并根据优先级将这些就绪队列高低排序。在就绪任务队列刚被创建时,每个就绪任务队列中仅仅包含一个队列头结构,当有任务进入就绪态后,该任务的任务描述符(任务描述符参考5.1.1节中的任务描述符)就会被挂载到相应优先级的就绪任务队列上。

其中,_psp_init_readyqs函数位于在“..\MQX\psp\sc_irdyq.c”文件中,其源码如下。

(6)创建任务操作信号量。在内核数据区中为创建和删除任务创建轻量级信号量,创建和删除任务时均需对内核数据区进行同步访问,这就需要一个信号量来保证同步访问能够正确进行。

2.初始化外设

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

其中_bsp_enable_card函数的定义位于“..\MQX\bsp\init_bsp.c”文件中,主要内容如下。

(1)初始化MQX的中断系统。为中断系统分配稀疏中断向量(参见3.3.2节稀疏中断向量表的建立)链接表头节点,初始化稀疏中断向量表。

事实上,MQX使用软件的方式对稀疏中断向量表进行分组管理,每组的节点数由配置文件small_ram_config.h中的宏MQX_SPARSE_ISR_SHIFT的定义值决定,默认值一般为3,每组的节点数为2 3 =8。初始化的稀疏中断向量链接表头节点,是MQX专门设计了一个中断服务的数组指针,数组的大小由给定的中断向量数除以8得到的组数决定,每组数组元素指针指向一组链表。当中断事件产生后,MQX的中断处理系统将在中断向量链表中查询相应的服务函数并调用执行。关于MQX中断处理系统的工作机制,将在第3章进行阐述。

(2)初始化系统时间嘀嗒。

在MQX操作系统运行时,还需要一个嘀嗒(Tick)时钟信号,驱动操作系统的时间管理系统工作。K60微控制器基于ARM Cortex-M4处理器,该处理器内部提供了一个SysTick定时器,它是一个可编程的硬件模块,能以固定的频率产生中断。该中断就是所谓的SysTick中断,它所处理的中断处理程序负责更新系统时间,也负责执行需要周期性运行的任务。内核只有在SysTick的帮助下才能计算和管理时间。因为对于SysTick,用户在编程时已经定义了,也就说它的节拍率对于内核来说是已知的,所以内核知道连续两次SysTick中断的时间间隔,这个间隔就称为嘀嗒(有的翻译为节拍)。任何使用ARM Cortex-M4处理器的芯片都可以使用SysTick,选用SysTick作为MQX操作系统的嘀嗒定时器,可以提高MQX在使用ARM Cortex-M4处理器的不同微控制间的可移植性。在3.4节中将对MQX的嘀嗒时间系统进行详细的说明。

此处设定时钟系统主要参数为:处理器内核频率为96 MHz,处理器总线频率为48 MHz,系统嘀嗒的时间间隔为5 ms,也就是每隔5 ms产生一次SysTick定时器中断,一个“嘀嗒”单位时间5 ms。

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

当完成MQX系统运行的准备工作后,调度系统就可以启动了。启动调度系统是MQX启动过程的最后一个环节,当调度系统启动后,整个系统中包含的应用任务将在调度系统的管理下无休止地运行。

(1)设定默认使用的时间片。若配置使用任务的时间片轮转调度机制(参考5.5节任务的调度策略),则需要为该任务指定任务轮转的时间片长度。若未在任务模板中明确指定任务的轮转时间片长度,则使用系统默认的设定的时间片长度,在MQX启动的过程中对系统默认使用的时间片长度进行设定。

默认时间片长度的配置值MQX_DEFAULT_TIME_SLICE在“…\MQX\include”文件夹中的mqx_prv.h文件中定义,代码中默认将时间片设置为10 ms。

(2)创建并启动系统初始化任务。系统初始化任务是MQX系统创建的初始化任务,BSP设备初始化和自动运行任务加入就绪任务队列两项工作。

通过调用“..\MQX\kernal\inittask.c”文件中_mqx_init_task函数完成,在_bsp_init()中完成DMA设备列表初始化、内核I/O子系统初始化、默认UART调试串口初始化、内核串行I/O端口初始化。

设备驱动程序初始化后安装完毕,才能被纳入到MQX的设备管理器的管理体系之下,从而与文件操作建立起关联。在_bsp_init()中完成DMA设备列表初始化、内核I/O子系统初始化、默认UART调试串口初始化、内核串行I/O端口初始化。

在_io_serial_default_init函数中,打开了一个由bsp_config.h中指定的缺省端口(此处为ittye:),在此之后,就可以使用printf等标准I/O操作通过缺省端口进行输出了。如果使用其他驱动,如ADC模块,则同样需要将对应的ADC的驱动安装函数_io_adc_install放在这个位置以达到安装ADC驱动的目的。

(3)创建并启动空闲任务。为便于维护系统中的任务队列,一般情况下,MQX会创建一个空闲任务。当所有应用任务均不再执行,系统仍然运行一个空闲任务,以保证MQX的调度系统保持工作状态。空闲任务在MQX初始化过程中创建。

在创建空闲任务之后,将该任务设定为就绪态。在MQX中的空闲任务(_mqx_idle_task)位于“..\MQX\kernel\idletask.c”文件中,空闲任务实际上是一个永久循环,执行的是一个三层嵌套循环的加法过程,仅仅对4个32位变量增1计数。

(4)启动调度系统。在做好所有启动MQX的准备后,启动调度程序,开始执行多任务的调度,至此,系统开始工作。

启动调度器后,系统的控制权就转移给调度系统了。在调度系统的管理下,根据系统使用的调度策略依次调度各个任务执行,实现系统功能,关于调度将在第5章任务管理与调度中详细介绍。 Sgcejt9WJoqnV5CKgOLxnQu/Z2IWBbVTiAac48Nk939SGrP0YivpwO8xUcqEM9ys

点击中间区域
呼出菜单
上一章
目录
下一章
×