garfield

【原创】初始化并开始运行MQX

0
阅读(2373)

MQX 开始于_mqx()函数,该函数以 MQX 初始化结构为参数。基于这一结构中的参数,MQX完成如下任务:

(1).载入并初始化 MQX 经常使用的数据,包括默认内存池,就绪队列,中断堆栈和任务栈;

(2).初始化硬件(如芯片选择);

(3).开启定时器;

(4).设置默认的时间片值;

(5).生成空闲任务,当没有其它任务就绪时将被激活;

(6).生成由任务模板列表定义为自启动的任务;

(7).开始调度多任务。

1.MQX初始化结构

MQX 初始化结构中定义应用程序和目标硬件的参数如下:

typedef struct mqx_initialization_struct

{

_mqx_uint PROCESSOR_NUMBER;

pointer START_OF_KERNEL_MEMORY;

pointer END_OF_KERNEL_MEMORY;

_mqx_uint INTERRUPT_STACK_SIZE;

TASK_TEMPLATE_STRUCT_PTR TASK_TEMPLATE_LIST;

_mqx_uint MQX_HARDWARE_INTERRUPT_LEVEL_MAX;

_mqx_uint MAX_MSGPOOLS;

_mqx_uint MAX_MSGQS;

char _PTR_ IO_CHANNEL;

char _PTR_ IO_OPEN_MODE;

_mqx_uint RESERVED[2];

} MQX_INITIALIZATION_STRUCT, _PTR_ MQX_INITIALIZATION_STRUCT_PTR;

如需查看每个域的描述,参见 MQX的手册。

1.1 默认MQX初始化结构

你可以为 MQX 初始化结构定义自己的初始值,或者使用由每个 BSP 提供的默认值。该默认值被称为 MQX_init_struct 而且保存在相应的 BSP 目录下的 mqx_init.c 文件中。该文件已经被编译并连接到 MQX。

注意:对于任务相关的调试工具来说,MQX 初始化结构必须命名为 MQX_init_struct。

本章中的例子将使用如下 MQX_init_struct:

MQX_INITIALIZATION_STRUCT MQX_init_struct =

{

/* PROCESSOR_NUMBER */ BSP_DEFAULT_PROCESSOR_NUMBER,

/* START_OF_KERNEL_MEMORY */ BSP_DEFAULT_START_OF_KERNEL_MEMORY,

/* END_OF_KERNEL_MEMORY */ BSP_DEFAULT_END_OF_KERNEL_MEMORY,

/* INTERRUPT_STACK_SIZE */ BSP_DEFAULT_INTERRUPT_STACK_SIZE,

/* TASK_TEMPLATE_LIST */ (pointer)MQX_template_list,

/* MQX_HARDWARE_INTERRUPT_LEVEL_MAX*/

BSP_DEFAULT_MQX_HARDWARE_INTERRUPT_LEVEL_MAX,

/* MAX_MSGPOOLS */ BSP_DEFAULT_MAX_MSGPOOLS,

/* MAX_MSGQS */ BSP_DEFAULT_MAX_MSGQS,

/* IO_CHANNEL */ BSP_DEFAULT_IO_CHANNEL,

/* IO_OPEN_MODE */ BSP_DEFAULT_IO_OPEN_MODE

};

注:初始化 RESERVED 域的元素值为 0

1.2 任务模板列表

任务模板列表(TASK_TEMPLATE_STRUCT)定义了一组初始化模板,基于该模板可以在处理器上生成任务。

初始化时,MQX 生成每个任务的一个实例,任务模板将其定义为一个自启动任务。同样,当应用程序运行时,它能按任务模板生成其它任务,该模板由任务模板定义或应用程序动态定义。任务模板队列的结尾是一个填入全 0 的任务模板。

typedef struct task_template_struct

{

_mqx_uint TASK_TEMPLATE_INDEX;

void _CODE_PTR_ TASK_ADDRESS)(uint_32);

_mem_size TASK_STACKSIZE;

_mqx_uint TASK_PRIORITY;

char _PTR_ TASK_NAME;

_mqx_uint TASK_ATTRIBUTES;

uint_32 CREATION_PARAMETER;

_mqx_uint DEFAULT_TIME_SLICE;

} TASK_TEMPLATE_STRUCT, _PTR_ TASK_TEMPLATE_STRUCT_PTR;

如需查看每个域的描述,请参见 MQX 手册。

1.2.1 指定任务优先级

注意:如果指定某个任务优先级为 0,则该任务运行时屏蔽了所有中断。当你在任务模板列表中指定任务优先级,请注意:

MQX 为每个优先级生成一个就绪队列直至最低的优先级(最大的数值)

当一个应用程序运行时,它不能生成一个优先级低于任务模板列表中的最低优先级(较大的数值)的任务。

1.2.2 指定任务属性

你可以为一个任务指定如下属性的任意组合:

(1).自启动——当 MQX 开始运行时,它生成任务的一个实例;

(2).DSP——MQX 保存 DSP 协处理器寄存器作为任务现场的一部分;

(3).浮点——MQX 保存浮点寄存器作为任务现场的一部分;

(4).时间片——MQX 为任务使用轮循调度(默认是 FIFO 调度)。

1.2.3 默认任务模板列表

你可以初始化自己的任务模板列表,也可以使用默认的列表 MQX_template_list。

1.2.4 举例:一个任务模板列表

TASK_TEMPLATE_STRUCT MQX_template_list[] =

{

{ MAIN_TASK, world_task, 0x2000, 5, "world_task",

MQX_AUTO_START_TASK, 0L, 0},

{ HELLO, hello_task, 0x2000, 5, "hello_task",

MQX_TIME_SLICE_TASK, 0L, 100},

{ FLOAT, float_task, 0x2000, 5, "Float_task",

MQX_AUTO_START_TASK | MQX_FLOATING_POINT_TASK, 0L, 0},

{ 0, 0, 0, 0, 0, 0, 0L, 0 }

};

在这个例子中,world_task 是一个自启动任务,因此在初始化时 MQX 生成一个参数为 0 的任务实例。应用程序定义任务模板索引(MAIN_TASK)。该任务优先级为 5。World_task()函数是任务的入口,栈的大小是 0x2000 个寻址单元。

任务 hello_task 是一个时间片任务,如果使用默认的实时编译配置选项,其时间片数值为 100毫秒。

Float_task 任务既是一个浮点任务,也是一个自启动任务。

1.2.5 实例:创建一个自启动任务

创建一个简单任务,其功能为输出“Hello World”并终止,程序编写如下:

/* hello.c */

#include

#include

/* Task IDs */

#define HELLO_TASK 5

extern void hello_task(uint_32);

TASK_TEMPLATE_STRUCT MQX_template_list[] =

{

{ HELLO_TASK, hello_task, 500, 5, "hello",

MQX_AUTO_START_TASK, 0L, 0},

{ 0, 0, 0, 0, 0,

0, 0L, 0}

};

void hello_task(uint_32 initial_data)

{

printf("\n Hello World \n");

_mqx_exit(0);

}

1.2.5.1 编译程序并连接到MQX

(1).进入如下目录:mqx\examples\hello

(2).参考 MQX 发布版本的说明文档,获得创建和运行程序的指令。

(3).按照说明文档的指令运行该应用程序。

在输出设备上将会有如下显示:

Hello World

Baidu
map