第 7 章 移植 μC/OS-II 到 ARM7

72
南南南南南南南南南南 南7南 南南 μC/OS-II 南 ARM7 RTOSARM

description

第 7 章 移植 μC/OS-II 到 ARM7. RTOS ARM. 第 7 章 目录. 1. μC/OS-II 简介 2. 移植规划 3. 移植 μC/OS-II 4. 移植代码应用到 LPC2000. 第 7 章 目录. 1. μC/OS-II 简介 2. 移植规划 3. 移植 μC/OS-II 4. 移植代码应用到 LPC2000. 7.1 μC/OS-II 简介. 概述. - PowerPoint PPT Presentation

Transcript of 第 7 章 移植 μC/OS-II 到 ARM7

Page 1: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

第 7 章 移植 μC/OS-II 到 ARM7

RTOSARM

Page 2: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

第 7 章 目录

1. μC/OS-II 简介2. 移植规划3. 移植 μC/OS-II4. 移植代码应用到 LPC2000

Page 3: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

第 7 章 目录

1. μC/OS-II 简介2. 移植规划3. 移植 μC/OS-II4. 移植代码应用到 LPC2000

Page 4: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

7.1 μC/OS-II 简介• 概述

μC/OS-II 读做“ micro C O S 2” ,意为“微控制器操作系统版本 2” 。 μC/OS-II 是源码公开的著名实时内核,可用于各类 8 位、 16 位和 32 位单片机或 DSP 。从 μC/OS 算起,该内核已有 10 多年应用史,在诸多领域得到广泛应用。 μC/OS-II 是一个完整的、可移植、可固化、可剪裁的占先式实时多任务内核。 μC/OS-II 使用 ANSI C语言编写,包含一小部分汇编代码,使之可以供不同架构的微处理器使用。至今,从 8 位到 64 位, μC/OS-II 已在超过 40 种不同架构的微处理器上运行。

Page 5: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

µC/OS-II的各种商业应用 全世界有数百种产品

在应用医疗器械移动电话路由器工业控制GPS 导航系统智能仪器

更多…

Page 6: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• μC/OS-II 特点●提供源代码:购买作者撰写的《嵌入式实时操作系统 μC/OS-II 》一书即可获得 μC/OS-II V2.52 版本的所有源代码,购买此书的其它版本可以获得相应版本的全部源代码。●可移植性( portable ): μC/OS-II 的源代码绝大部分是使用移植性很强的 ANSI C 写的,将与微处理器硬件相关的汇编语言使用量压缩到最低的限度,以使 μC/OS-II 便于移植到其它微处理器上。目前,μC/OS-II 已经被移植到多种不同架构的微处理器上。●可固化 (ROMmable) :只要具备合适的软硬件工具,就可以将 μC/OS-II 嵌入到产品中成为产品的一部分。●可剪裁 (scalable) : μC/OS-II 使用条件编译实现可剪裁,用户程序可以只编译自己需要的( μC/OS-II 的)功能,而不编译不要需要的功能,以减少 μC/OS-II 对代码空间和数据空间的占用。●可剥夺 (preemptive) : μC/OS-II 是完全可剥夺型的实时内核, μC/OS-II 总是运行就绪条件下优先级最高的任务。

Page 7: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• μC/OS-II 特点●多任务: μC/OS-II 可以管理 64 个任务,然而, μC/OS-II 的作者建议用户保留 8 个给 μC/OS-II 。这样,留给用户的应用程序最多可有56 个任务。●可确定性:绝大多数 μC/OS-II 的函数调用和服务的执行时间具有确定性,也就是说,用户总是能知道 μC/OS-II 的函数调用与服务执行了多长时间。●任务栈: μC/OS-II 的每个任务都有自己单独的栈,使用 μC/OS-II的占空间校验函数,可确定每个任务到底需要多少栈空间。●系统服务: μC/OS-II 提供很多系统服务,例如信号量、互斥信号量、时间标志、消息邮箱、消息队列、块大小固定的内存的申请与释放及时间管理函数等。●中断管理:中断可以使正在执行的任务暂时挂起,如果优先级更高的任务被中断唤醒,则高优先级的任务在中断嵌套全部退出后立即执行,中断嵌套层数可达 255层。

Page 8: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• μC/OS-II 特点●稳定性与可靠性: μC/OS-II 是 μC/OS 的升级版, μC/OS 自 1992年以来已经有数百个商业应用。 μC/OS-II 与 μC/OS 的内核是一样的,只是提供了更多的功能。 2000 年 7月, μC/OS-II 在一个航空项目中得到了美国联邦航空管理局对商用飞机的、符合 RTCA DO – 178B 标准的认证。这表明,该操作系统的质量得到了认证,可以在任何应用中使用。

作者及其著作

Page 9: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

第 7 章 目录

1. μC/OS-II 简介2. 移植规划3. 移植 μC/OS-II4. 移植代码应用到 LPC2000

Page 10: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

7.2 移植规划• 概述

所谓“移植”,就是使一个实时内核能在其它的微处理器或微控制器上运行。 尽管大部分 μC/OS-II 的代码是用 C 语言编写的,但是在编写与处理器硬件相关的代码时还是不得不使用汇编语言。移植的主要工作就是编写这些与处理器硬件相关的代码。 在移植前针对所使用的微处理器进行规划,主要有以下几个方面的考虑:编译器的选择、任务模式的选择和支持的指令集。

Page 11: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• μC/OS-II 移植

应用程序(用户代码)

μC/OS-II(与处理器无关代码)

OS_CORE.cOS_FLAG.c

...

μC/OS-II配置(与应用无关)

OS_CFG.HINCLUDES.H

μC/OS-II 移植(与处理器相关代码)

CPU 定时器

硬件

软件

——μC/OS-II 硬件软件体系结构

用于产生系统时钟

移植时需要编写的代码

Page 12: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

7.2 移植规划• 编译器的选择

目前,针对 ARM 处理器核的 C 语言编译器有很多,如 SDT 、 ADS 、 IAR 、 TASKING 和 GCC 等。据了解,目前在国内最流行的是 ADS 、 SDT 和 GCC 。SDT 和 ADS均为 ARM 公司自己开发, ADS 为 SDT的升级版,以后 ARM 公司不再支持 SDT ,所以不会选择 SDT 。 GCC虽然支持广泛,很多开发套件使用它作为编译器,但是与 ADS比较其编译效率较低,这对充分发挥芯片性能很不利,所以最终使用 ADS 编译程序和调试。

Page 13: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

7.2 移植规划• 任务模式的取舍

ARM7 处理器核具有用户、系统、管理、中止、未定义、中断和快中断七种模式,其中除用户模式外其它均为特权模式。其中管理、中止、未定义、中断和快中断模式与相应异常相联系,任务使用这些模式不太适合。而系统模式除了是特权模式外,其它与用户模式一样,因而可选为任务使用的模式只有用户模式和系统模式。为了尽量减少任务代码错误对整个程序的影响,缺省的任务模式定为用户模式,可选为系统模式,同时提供接口使任务可以在这两种模式间切换。

Page 14: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

7.2 移植规划• 支持的指令集

带 T变量的 ARM7 处理器核具有两个指令集(可以参考第 3 章 ):标准 32 位 ARM指令集和 16 位 Thumb指令集,两种指令集有不同的应用范围。为了最大限度地支持芯片的特性,任务应当可以使用任意一个指令集并可以自由切换,而且不同的任务应当可以使用不同的指令集,这次移植的代码已经实现了这一点。

Page 15: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

第 7 章 目录

1. μC/OS-II 简介2. 移植规划3. 移植 μC/OS-II4. 移植代码应用到 LPC2000

Page 16: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

7.3 移植 μC/OS-II

• 概述 要移植一个操作系统到一个特定的 CPU体系结构上并不是一件很容易的事情,它对移植者有以下要求:

1. 对目标体系结构要有很深了解;2. 对 OS原理要有较深入的了解;3. 对所使用的编译器要有较深入的了解;4. 对需要移植的操作系统要有相当的了解;5. 对具体使用的芯片也要一定的了解。

Page 17: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

要移植一个操作系统到一个特定的 CPU体系结构上并不是一件很容易的事情,它对移植者有以下要求:

1. 对目标体系结构要有很深了解;

2. 对 OS原理要有较深入的了解;

3. 对所使用的编译器要有较深入的了解;

4. 对需要移植的操作系统要有相当的了解;

5. 对具体使用的芯片也要一定的了解。

• 概述

参考ARM公司的《 ARM体系结构》文档

参考《嵌入式实时操作系统 μC/OS-II 》一书

参考ADS软件自带的编译器和连接器手册

参考《嵌入式实时操作系统 μC/OS-II 》一书

参考具体芯片的数据手册和使用手册因为第 4 点的影响是全局性的,它决定移植代码的框架和功能。

所以重点介绍第 4 点。

Page 18: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 概述 根据 μC/OS-II 的要求,移植 μC/OS-II 到一个新的体系结构上需要提供 2 个或 3 个文件:

OS_CPU.H ( C 语言头文件) OS_CPU_C.C ( C 程序源文件) OS_CPU_A.ASM (汇编程序源文件)

其中 OS_CPU_A.ASM 在某些情况下不需要,但极其罕见。不需要 OS_CPU_A.ASM 的必须满足以下苛刻条件,而同时满足这些条件的微控制器几乎没有: 1. 可以直接使用 C 语言开关中断; 2. 可以直接使用 C 语言编写中断服务程序; 3. 可以直接使用 C 语言操作堆栈指针; 4. 可以直接使用 C 语言保存 CPU 的所有寄存器。

——移植需要编写的文件

Page 19: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 概述移植内容 类型 所属文件 描述

BOOLEAN、 INT8U、 INT8S、…

数据类型 OS_CPU.H 与编译器无关的数据类型

OS_STK 数据类型 OS_CPU.H 堆栈的数据类型OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()

宏 OS_CPU.H 开关中断的代码

OS_STK_GROWTH 常量 OS_CPU.H 定义堆栈的增长方向OS_TASK_SW 函数 OS_CPU.H 任务切换时执行的代码OSTaskStkInit() 函数 OS_CPU_C.C 任务堆栈初始化函数OSInitHookBegin()、 OSInitHookEnd()、…

函数 OS_CPU_C.CμC/OS-II在执行某些操作时调用的用户函数,一般为空

OSStartHighRdy() 函数 *OS_CPU_A.ASM进入多任务环境时运行优先

级最高的任务,OSIntCtxSw() 函数 *OS_CPU_A.ASM 中断退出时的任务切换函数OSTickISR() 中断服务程序 *OS_CPU_A.ASM 时钟节拍中断服务程序

实际上,还有一个文件很重要,它就是 IRQ.INC ,它定义了一个汇编宏,它是 μC/OS-II for ARM7通用的中断服务程序的汇编与 C 函数接口代码。时钟节拍中断服务程序也没有移植,因为其与芯片和应用都强烈相关,需要用户自己编写,不过可以通过 IRQ.INC 简化用户代码的编写。

——移植代码包括的内容

Page 20: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 关于头文件 includes.h 和 config.h

μC/OS-II 要求所有 .C文件的都要包含都文件 includes.h ,这样使得用户项目中的每个 .C文件不用分别去考虑它实际上需要哪些头文件。使用 INCLUDES.H 的缺点是它可能会包含一些实际不相关的头文件,这意味着每个文件的编译时间可能会增加,但却增强了代码的可移植性。 在本移植中另外增加了一个头文件 config.h ,我们要求所有用户程序必须包含 config.h ,在 config.h 中包含 includes.h 和特定的头文件和配置项。而 μC/OS-II 的系统文件依然只是包含 includes.h ,即 μC/OS-II 的系统文件完全不必改动。所有的配置改变包括头文件的增减均在 config.h 中进行,而 includes.h 定下来后不必改动( μC/OS-II 的系统文件需要包含的东西是固定的)。这样,μC/OS-II 的系统文件需要编译的次数大大减少,编译时间随之减少。

congfig.h

UCOS 内核文件

Includes.h

用户程序

Page 21: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 OS_CPU.H

μCOS-II 不使用 C 语言中的 short 、 int 、 long 等数据类型的定义,因为它们与处理器类型有关,隐含着不可移植性。代之以移植性强的整数数据类型,这样,既直观又可移植,不过这就成了必须移植的代码。根据 ADS 编译器的特性,这些代码如程序清单 7.1 所示。

typedef unsigned char BOOLEAN; typedef unsigned char INT8U;typedef signed char INT8S;typedef unsigned short INT16U;typedef signed short INT16S;typedef unsigned int INT32U;typedef signed int INT32S;typedef float FP32;typedef double FP64;typedef INT32U OS_STK;

——不依赖于编译的数据类型

Page 22: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 OS_CPU.H

μCOS-II 运行时,处理器可能处于的状态如下图所示:

——使用软中断 SWI 作底层接口

Thumb指令集ARM指令集

用户模式

系统模式

用户任务使用的处理器模式

ARM7 内核具有的指令集

ARM指令用户模式

ARM指令系统模式

Thumb指令系统模式

Thumb指令用户模式

Page 23: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 OS_CPU.H

为了使底层接口函数与处理器状态无关,同时在任务调用相应的函数不需要知道函数位置,本移植使用软中断指令 SWI 作为底层接口,使用不同的功能号区分不同的函数。软中断功能号分配如下表所示,未列出的为保留功能。

——使用软中断 SWI 作底层接口

功能号 接口函数 简介0x00 void OS_TASK_SW(void) 任务级任务切换函数0x01 _OSStartHighRdy(void) 运行优先级最高的任务 ,由 OSStartHighRdy产

生0x02 void

OS_ENTER_CRITICAL(void)关中断

0x03 Void OS_EXIT_CRITICAL(void) 开中断0x80 Void ChangeToSYSMode(void) 任务切换到系统模式0x81 Void ChangeToUSRMode(void) 任务切换到用户模式0x82 Void TaskIsARM(INT8U prio) 任务代码是 ARM代码0x83 Void TaskIsTHUMB(INT8U prio) 任务代码是 THUMB代码

Page 24: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 OS_CPU.H

用软中断作为操作系统的底层接口就需要在 C 语言中使用SWI指令。在 ADS 中,有一个关键字 __swi ,用它声明一个不存在的函数,则调用这个函数就在调用这个函数的地方插入一条 SWI指令,并且可以指定功能号。同时,这个函数也可以有参数和返回值,其传递规则与一般函数一样。

——使用软中断 SWI 作底层接口

/* 任务级任务切换函数 */__swi(0x00) void OS_TASK_SW(void);

/* 运行优先级最高的任务 */__swi(0x01) void _OSStartHighRdy(void);

/* 关中断 */__swi(0x02) void OS_ENTER_CRITICAL(void);

/* 开中断 */__swi(0x03) void OS_EXIT_CRITICAL(void);

/* 任务切换到系统模式 */__swi(0x80) void ChangeToSYSMode(void);

/* 任务切换到用户模式 */__swi(0x81) void ChangeToUSRMode(void);

/* 任务代码是 ARM 代码 */__swi(0x82) void TaskIsARM(INT8U prio);

/* 任务代码是 THUMB 代码 */__swi(0x83) void TaskIsTHUMB(INT8U prio);

程序中调用软中断时使用的函数名

软件中断号

该调用不返回参数

Page 25: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 OS_CPU.H

μCOS-II 使用结构常量 OS_STK_GROWTH 中指定堆栈的生长方式:

置 OS_STK_GROWTH 为 0表示堆栈从下往上长。置 OS_STK_GROWTH 为 1表示堆栈从上往下长。

虽然 ARM 处理器核对于两种方式均支持,但 ADS 的 C语言编译器仅支持一种方式,即从上往下长,并且必须是满递减堆栈,所以 OS_STK_GROWTH 的值为 1 。

#define OS_STK_GROWTH 1

——堆栈生长方式

Page 26: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_c.c

该函数用于初始化任务堆栈,使任务的堆栈看起来就像刚发生中断一样。即任务被执行时,就像从中断返回一样。 在编写此函数之前,必须先确定任务的堆栈结构。而任务的堆栈结构是与 CPU 的体系结构、编译器有密切的关联。本移植的堆栈结构如下图所示。

——OSTaskStkInit( )

任务入栈的其它数据

LRR12R11R10R9R8...

栈底

任务环境开始

SP

PC

R2R1R0

OSEnterSum空闲空间

Page 27: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_c.c——OSTaskStkInit( )

OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt){ OS_STK *stk; opt = opt; stk = ptos; *stk = (OS_STK) task; *--stk = (OS_STK) task; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = (unsigned int) pdata; *--stk = (USER_USING_MODE|0x00); *--stk = 0; return (stk);}

入栈的数据

Page 28: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_c.c——OSTaskStkInit( )

OS_STK *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt){ OS_STK *stk; opt = opt; stk = ptos; *stk = (OS_STK) task; *--stk = (OS_STK) task; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = 0; *--stk = (unsigned int) pdata; *--stk = (USER_USING_MODE|0x00); *--stk = 0; return (stk);}

该数据比较特别,它用于保存该任务关中断的次数,它在调用 OS_ENTER_CRITICAL( ) 时加 1 ,在调用 OS_EXIT_CRITICAL( ) 时减 1 。 这样每个任务都可以独立控制本任务的中断允许状态,而不会影响其它任务的中断允许状态。因此关中断和开中断就可以嵌套。

Page 29: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_c.c——软件中断异常服务程序

前面介绍过,操作系统与硬件相关的底层函数使用软件中断作为接口,如下表所示。移植代码中一个重要的工作就是为这些软件中断编写服务程序。

功能号 接口函数 简介0x00 void OS_TASK_SW(void) 任务级任务切换函数0x01 _OSStartHighRdy(void) 运行优先级最高的任务 ,由 OSStartHighRdy产

生0x02 void

OS_ENTER_CRITICAL(void)关中断

0x03 Void OS_EXIT_CRITICAL(void) 开中断0x80 Void ChangeToSYSMode(void) 任务切换到系统模式0x81 Void ChangeToUSRMode(void) 任务切换到用户模式0x82 Void TaskIsARM(INT8U prio) 任务代码是 ARM代码0x83 Void TaskIsTHUMB(INT8U prio) 任务代码是 THUMB代码

Page 30: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_c.c——软件中断异常服务程序

功能号 简介0x00 任务级任务切换函数0x01 运行优先级最高的任务 ,由

OSStartHighRdy产生0x02 关中断0x03 开中断0x80 任务切换到系统模式0x81 任务切换到用户模式0x82 任务代码是 ARM代码0x83 任务代码是 THUMB代码

void SWI_Exception(int SWI_Num, int *Regs){ OS_TCB *ptcb; switch(SWI_Num) { case 0x02: // 关中断 ...

case 0x03: // 开中断 ...

case 0x80: // 任务切换到系统模式 ...

case 0x81: // 任务切换到用户模式 ...

case 0x82: // 任务代码是 ARM 代码 ...

case 0x83: // 任务代码是 Thumb 代码 ...

default: }}

这两个软件中断使用汇编代码完成

Page 31: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_c.c——软件中断异常服务程序

功能号 简介0x00 任务级任务切换函数0x01 运行优先级最高的任务 ,由

OSStartHighRdy产生0x02 关中断0x03 开中断0x80 任务切换到系统模式0x81 任务切换到用户模式0x82 任务代码是 ARM代码0x83 任务代码是 THUMB代码

μC/OS-II的启动多任务环境的函数叫做 OSStart(),用户在调用 OSStart()之前,必须已经建立了一个或更多任务。 OSStart()最终调用函数OSStartHighRdy()运行多任务启动前优先级最高的任务。

void OSStartHighRdy(void) { _OSStartHighRdy(); }

该函数在 Os_cpu_a.s 文件中实现。

Page 32: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_c.c——软件中断异常服务程序

功能号 简介0x00 任务级任务切换函数0x01 运行优先级最高的任务 ,由

OSStartHighRdy产生0x02 关中断0x03 开中断0x80 任务切换到系统模式0x81 任务切换到用户模式0x82 任务代码是 ARM代码0x83 任务代码是 THUMB代码

关中断和开中断是为了保护临界段代码。这些代码与处理器有关,是需要移植的代码。在 ARM处理器核中关中断和开中断时通过改变程序状态寄存器 CPSR中的相应控制位实现。由于使用了软件中断,程序状态寄存器 CPSR保存到程序状态保存寄存器 SPSR中,软件中断退出时会将SPSR恢复到 CPSR中,所以程序只要改变程序状态保存寄存器 SPSR中的相应的控制位就可以了。

Page 33: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_c.c——软件中断异常服务程序

功能号 简介0x00 任务级任务切换函数0x01 运行优先级最高的任务 ,由

OSStartHighRdy产生0x02 关中断0x03 开中断0x80 任务切换到系统模式0x81 任务切换到用户模式0x82 任务代码是 ARM代码0x83 任务代码是 THUMB代码

void SWI_Exception(int SWI_Num, int *Regs){

... case 0x02: // 关中断 __asm

{ MRS R0,SPSR ORR R0,R0,#NoInt MSR SPSR_c,R0 } OsEnterSum++; break;

case 0x03: // 开中断 if (--OsEnterSum == 0) { __asm { MRS R0,SPSR BIC R0,R0,#NoInt MSR SPSR_c,R0 } } break; ...

每关闭一次中断,中断关闭计数器加 1

每调用一次开中断函数,该计数器减 1,为 0时允许打开中断

关闭中断

打开中断

Page 34: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_c.c——软件中断异常服务程序

功能号 简介0x00 任务级任务切换函数0x01 运行优先级最高的任务 ,由

OSStartHighRdy产生0x02 关中断0x03 开中断0x80 任务切换到系统模式0x81 任务切换到用户模式0x82 任务代码是 ARM代码0x83 任务代码是 THUMB代码

它们可以在任何情况下使用。它们改变程序状态保留寄存器 SPSR的相应位段,而程序状态保留寄存器会在软件中断退出时复制到程序状态寄存器 CPSR,任务的处理器模式就改变了。

Page 35: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_c.c——软件中断异常服务程序

功能号 简介0x00 任务级任务切换函数0x01 运行优先级最高的任务 ,由

OSStartHighRdy产生0x02 关中断0x03 开中断0x80 任务切换到系统模式0x81 任务切换到用户模式0x82 任务代码是 ARM代码0x83 任务代码是 THUMB代码

void SWI_Exception(int SWI_Num, int *Regs){

... case 0x80: // 任务切换到系统模式 __asm { MRS R0,SPSR BIC R0,R0,#0x1f ORR R0,R0,#SYS32Mode MSR SPSR_c,R0 } break;

case 0x81: // 任务切换到用户模式 __asm { MRS R0,SPSR BIC R0,R0,#0x1f ORR R0,R0,#USR32Mode MSR SPSR_c,R0 }

break; ...

使用内嵌汇编将处理器模式切换到用户模式

使用内嵌汇编将处理器模式切换到系统模式

Page 36: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_c.c——软件中断异常服务程序

功能号 简介0x00 任务级任务切换函数0x01 运行优先级最高的任务 ,由

OSStartHighRdy产生0x02 关中断0x03 开中断0x80 任务切换到系统模式0x81 任务切换到用户模式0x82 任务代码是 ARM代码0x83 任务代码是 THUMB代码

任务可以使用 ARM的两种指令集的任意一种运行,但是任务建立时默认的只是一种指令集。如果任务使用的第一条指令与默认的指令集不同,则程序运行错误。所以增加两个函数 TaskIsARM()和 TaskIsTHUMB()用于改变任务建立时默认的指令集。 它们都有唯一的参数:需要改变的任务的优先级,值得注意的是,这两个函数必须在相应的任务建立后但还没有运行时调用。

Page 37: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_c.c——软件中断异常服务程序

功能号 简介0x00 任务级任务切换函数0x01 运行优先级最高的任务 ,由

OSStartHighRdy产生0x02 关中断0x03 开中断0x80 任务切换到系统模式0x81 任务切换到用户模式0x82 任务代码是 ARM代码0x83 任务代码是 THUMB代码

... case 0x82: // 任务代码是 ARM 代码 if (Regs[0] <= OS_LOWEST_PRIO) { ptcb = OSTCBPrioTbl[Regs[0]]; if (ptcb != NULL) { ptcb -> OSTCBStkPtr[1] &= ~(1 << 5); } } break;

case 0x83: // 任务代码是 Thumb 代码 if (Regs[0] <= OS_LOWEST_PRIO) { ptcb = OSTCBPrioTbl[Regs[0]]; if (ptcb != NULL) { ptcb -> OSTCBStkPtr[1] |= (1 << 5); } } break; ...

被设置的任务号一定不能大于最低优先级任务

获取指定任务的任务控制块的地址

修改任务堆栈中 CPSR 的值,在任务重新运行时,切换到

ARM指令方式

修改任务堆栈中 CPSR 的值,在任务重新运行时,切换到 T

humb指令方式

Page 38: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_c.c——软件中断异常服务程序

功能号 简介0x00 任务级任务切换函数0x01 运行优先级最高的任务 ,由

OSStartHighRdy产生0x02 关中断0x03 开中断0x80 任务切换到系统模式0x81 任务切换到用户模式0x82 任务代码是 ARM代码0x83 任务代码是 THUMB代码

注意: 这两个函数必须在相应的任务建立后但还没有运行时调用。 如果在低优先级的任务中创建高优先级的任务就十分危险了。此时,解决的方法有三种:(1) 高优先级任务使用默认的指令集;(2)改变函数 OSTaskCreateHook() 使任务默认不是处于就绪状态,建立任务后调用函数 OSTaskResume()来使任务进入就绪状态;(3) 建立任务时禁止任务切换,调用函数 TaskIsARM() 或 TaskIsTHUMB()后再允许任务切换。

Page 39: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_c.c

在 Os_cpu_c.c文件中还有许多钩子函数,它们在某个特定的系统动作时被调用,允许执行函数中的用户代码。这些函数默认是空函数,用户根据实际情况添加相关代码。它们分别如下表所示。

——…Hook( ) 函数

函数名 被执行条件OSInitHookBegin( ) 在开始执行 OSInit( ) 函数时被执行OSInitHookEnd( ) 在 OSInit() 函数结束时被执行

OSTaskCreateHook( ) 在任务建立时被调用OSTaskDelHook( ) 在任务删除时被调用OSTaskSwHook( ) 在进行任务切换时被调用OSTaskStatHook( ) 被统计任务调用,每秒执行一次

OSTCBInitHook( )在建立所有的 TCB后,由 OSTCBInit 函数调用

OSTimeTickHook( ) 每个时钟节拍产生后被调用OSTaskIdleHook( ) 由空闲任务调用

Page 40: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

7.3 移植 μC/OS-II

• 编写 Os_cpu_a.s

在 Os_cpu_a.s文件中有软件中断的汇编接口程序、任务切换程序、 OS启动时运行就绪最高优先级任务的程序。

Page 41: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_a.s

在调用软中断之后,处理器切换到 ARM指令和管理模式下工作。在执行软件中断服务函数之前,要提取中断号和其它入口参数,这些通过软件中断接口程序完成。

——软件中断汇编接口

SoftwareInterrupt LDR SP, StackSvc STMFD SP!, {R0-R3, R12, LR} MOV R1, SP

MRS R3, SPSR TST R3, #T_bit LDRNEH R0, [LR,#-2] BICNE R0, R0, #0xff00 LDREQ R0, [LR,#-4] BICEQ R0, R0, #0xFF000000 CMP R0, #1 LDRLO PC, =OSIntCtxSw LDREQ PC, =__OSStartHighRdy BL SWI_Exception LDMFD SP!, {R0-R3, R12, PC}^

保护被中断的现场将要用到的寄存器压栈

判断中断前的指令集类型

从产生软件中断的指令中提取

中断号

ARM

Thumb

根据不同的中断号执行不同的程序

返回被中断的任务

中断号 执行程序0 进行任务切换

1启动多任务环境,运行就绪的最高优先级

任务其它 软件中断服务函数

Page 42: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_a.s

μCOS-II 是抢占式实时操作系统,得到运行的始终是就绪条件下最高优先级的任务。当处于运行状态的任务因为某种脱离就绪态,或者有其它更高优先级的任务进入就绪态,那么操作系统内核就要运行别的就绪任务,这时需要进行任务切换。

任务切换可能发生的情况有两种: 1.当前运行的任务主动交出 CPU 控制权,通常发生在等待某个事件或是调用系统延时。调用函数 OS_TASK_SW( ); 2.发生中断,使更高优先级的任务进入就绪状态,内核剥夺当前任务的运行资格。即发生在中断退出时。调用函数 OSIntCtxSw( ) 。

——任务切换代码

Page 43: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_a.s

虽然 OS_TASK_SW( ) 和 OSIntCtxSw( ) 的执行条件不同,但是它们的功能相同,只要稍作处理就可以它们共用一段任务切换代码。这些处理就是保证在执行任务切换前两者的任务现场是一致的。共同执行的任务切换代码是“ OSIntCtxSw” 其中 OS_TASK_SW( ) 是通过软件中断 0 完成的,通过前面的分析,可以知道执行任务切换时的现场环境如下所示,同时 R3 中保存着 SPSR ,它是任务中断前 CPSR 的备份。

——任务切换代码

任务入栈的其它数据

LR

R12

R3

R2

R1

R0

空闲空间

栈底

任务环境开始

SP

Page 44: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_a.s——OSIntCtxSw

保存当前任务的寄存器组及其它

修改当前任务的 TCB堆栈指针

用将要运行任务的优先级和 TCB指针更新 OSPrioHighRdy

和 OSTCBCur

恢复新任务的寄存器组及其它

运行新任务

流程图

Page 45: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_a.s——OSIntCtxSw

保存当前任务的寄存器组及其它

修改当前任务的 TCB堆栈指针

用将要运行任务的优先级和 TCB指针更新 OSPrioHighRdy

和 OSTCBCur

恢复新任务的寄存器组及其它

运行新任务

流程图OSIntCtxSw ; 下面为保存任务环境 LDR R2, [SP, #20] ; 获取 PC LDR R12, [SP, #16] ; 获取 R12 MRS R0, CPSR ; 保存 LR,PC 及 R4-R12 MSR CPSR_c, #(NoInt | SYS32Mode) MOV R1, LR STMFD SP!, {R1-R2} STMFD SP!, {R4-R12} ; 获取 R0-R3 ,并出栈 R12 和 PC寄存器 MSR CPSR_c, R0 LDMFD SP!, {R4-R7} ADD SP, SP, #8 ; 保存 R0-R3 MSR CPSR_c, #(NoInt | SYS32Mode) STMFD SP!, {R4-R7} ; 获取 OsEnterSum ,并保存 CPSR,OsEnterSum LDR R1, =OsEnterSum LDR R2, [R1] STMFD SP!, {R2, R3} ...

PCLRR12R11R10R9

R7

R5R4R3R2R1R0

R6

R8

CPSROSEnterSum

切换至系统模式获取任务运行时的各寄存

器并将它们压栈

恢复之前的模式读出压栈的数据

任务环境保存结束后的栈结构

Page 46: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_a.s——OSIntCtxSw

修改当前任务的 TCB堆栈指针

用将要运行任务的优先级和 TCB指针更新 OSPrioHighRdy

和 OSTCBCur

保存当前任务的寄存器组及其它

恢复新任务的寄存器组及其它

运行新任务

Page 47: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

OSIntCtxSw ...

; 保存当前任务堆栈指针到当前任务的 TCB LDR R1, =OSTCBCur LDR R1, [R1] STR SP, [R1]

BL STaskSwHook ; 调用钩子函数 ;OSPrioCur <= OSPrioHighRdy LDR R4, =OSPrioCur LDR R5, =OSPrioHighRdy LDRB R6, [R5] STRB R6, [R4] ;OSTCBCur <= OSTCBHighRdy LDR R6, =OSTCBHighRdy LDR R6, [R6] LDR R4, =OSTCBCur STR R6, [R4] ...

• 编写 Os_cpu_a.s——OSIntCtxSw

用即将运行任务的 TCB指针更新OSTCBCur变量

用即将运行任务的优先级更新 OS

PrioCur变量

Page 48: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写 Os_cpu_a.s——OSIntCtxSw

恢复新任务的寄存器组及其它

运行新任务

保存当前任务的寄存器组及其它

修改当前任务的 TCB堆栈指针

用将要运行任务的优先级和 TCB指针更新 OSPrioHighRdy

和 OSTCBCur

Page 49: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

OSIntCtxSw ...OSIntCtxSw_1 ; 从 R6指向 TCB中获取新任务堆栈指针 LDR R4, [R6] ; 调整堆栈指针 ;17寄存器 CPSR,OsEnterSum,R0-R12,LR,SP ADD SP, R4, #68 LDR LR, [SP, #-8]

;进入管理模式,恢复任务的各寄存器和变量 MSR CPSR_c, #(NoInt | SVC32Mode) MOV SP, R4 ;设置堆栈指针 ; 获取 CPSR和 OsEnterSum LDMFD SP!, {R4, R5} ;恢复新任务的 OsEnterSum LDR R3, =OsEnterSum STR R4, [R3] ;恢复 CPSR MSR SPSR_cxsf, R5

;运行新任务 LDMFD SP!, {R0-R12, LR, PC }^

• 编写 Os_cpu_a.s——OSIntCtxSw

恢复新任务的各寄存器

运行新任务

这段代码还被 __OSStartHighRdy

函数调用,用于启动最高优先级的就

绪任务

Page 50: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

__OSStartHighRdy MSR CPSR_c, #(NoInt | SYS32Mode) ;告诉 uC/OS-II自身已经运行 LDR R4, =OSRunning MOV R5, #1 STRB R5, [R4] ;调用钩子函数 BL OSTaskSwHook

LDR R6, =OSTCBHighRdy ;取得新任务的 TCB指针 LDR R6, [R6] B OSIntCtxSw_1

• 编写 Os_cpu_a.s——OSStartHighRdy

μC/OS-II 的多任务环境由函数 OSStart( ) 启动。用户在调用该函数之前,必须已经建立了一个或更多任务。 OSStart()最终调用函数 OSStartHighRdy( ) 运行多任务启动前优先级最高的任务,而它最终是调用 __OSStartHighRdy 实现的,其代码如下所示:

Page 51: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

Os_cpu_a.s文件

• 编写 Os_cpu_a.s

通过前面的分析,我们可以画出下面这张结构图:

中断退出时任务切换

xxx_Handler

任务级任务切换

OS_TASK_SW()

启动多任务

OSStartHighRdy()

OSIntCtxSw _OSStartHighRdy

OSIntCtxSw_1

Page 52: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

7.3 移植 μC/OS-II

• 关于中断及时钟节拍

在本移植中, IRQ 是受 μC/OS-II 管理的中断,而对于 FIQ 不做处理,这是为了提高 FIQ 的响应速度。由于各种 ARM芯片的中断系统不一样,各个用户的目标板也不一样,对于中断和时钟节拍是需要进一步移植的代码。为此编写了一个汇编宏,它是 μC/OS-II for ARM7通用的中断服务程序的汇编与 C 函数接口代码。 注:在不受管理的中断服务程序中不能调用任何系统函数。

Page 53: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 关于中断及时钟节拍流程图

保存当前任务的寄存器组

中断嵌套数加 1

切换到系统模式执行中断服务程序

关中断执行 OSIntExit( )

切换到 IRQ模式判断是否需要进行

任务切换

切换任务或返回

Page 54: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 关于中断及时钟节拍流程图

保存当前任务的寄存器组

中断嵌套数加 1

切换到系统模式执行中断服务程序

关中断执行 OSIntExit( )

切换到 IRQ模式判断是否需要进行

任务切换

切换任务或返回

Page 55: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

MACRO$IRQ_Label HANDLER $IRQ_Exception_Function

EXPORT $IRQ_Label ; 输出的标号 IMPORT $IRQ_Exception_Function ; 引用的外部标号

$IRQ_Label SUB LR, LR, #4 ; 计算返回地址 STMFD SP!, {R0-R3, R12, LR} ; 保存任务环境 MRS R3, SPSR ; 保存状态 ; 保存用户状态的 R3,SP,LR, 不能回写 STMFD SP, {R3, SP, LR}^

LDR R2, =OSIntNesting LDRB R1, [R2] ADD R1, R1, #1 STRB R1, [R2]

SUB SP, SP, #4*3 ; 切换到系统模式 MSR CPSR_c, #(NoInt | SYS32Mode) CMP R1, #1 LDREQ SP, =StackUsr ...

• 关于中断及时钟节拍

中断嵌套层数加1

切换到系统模式,如果是第一次中断还要设置

堆栈指针

压栈保存被中断任务的运行环境

Page 56: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 关于中断及时钟节拍流程图

保存当前任务的寄存器组

中断嵌套数加 1

切换到系统模式执行中断服务程序

关中断执行 OSIntExit( )

切换到 IRQ模式判断是否需要进行

任务切换

切换任务或返回

中断服务程序( ISR )

在 ISR中可以打开中断实现中断嵌套

Page 57: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

MACRO$IRQ_Label HANDLER $IRQ_Exception_Function

EXPORT $IRQ_Label ; 输出的标号 IMPORT $IRQ_Exception_Function ; 引用的外部标号

$IRQ_Label ... BL $IRQ_Exception_Function ; 切换到系统模式 MSR CPSR_c, #(NoInt | SYS32Mode) ; OsEnterSum, 使 OSIntExit退出时中断关闭 LDR R2, =OsEnterSum MOV R1, #1 STR R1, [R2]

BL OSIntExit ; 因为中断服务程序要退出,所以 OsEnterSum=0 LDR R2, =OsEnterSum MOV R1, #0 STR R1, [R2] ; 切换回 irq模式,并恢复用户状态的 R3,SP,LR MSR CPSR_c, #(NoInt | IRQ32Mode) LDMFD SP, {R3, SP, LR}^ ; 注意不能回写 ...

• 关于中断及时钟节拍

关闭中断执行中断服务程序 (ISR)

使 OSEnterSum为 1,防止在 OSIntExit函数

中打开中断

通知系统,中断退出

使 OSEnterSum为 0,运行中断打开

恢复任务的 R3、 SP和 LR

Page 58: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 关于中断及时钟节拍流程图

保存当前任务的寄存器组

中断嵌套数加 1

切换到系统模式执行中断服务程序

关中断执行 OSIntExit( )

切换到 IRQ模式判断是否需要进行

任务切换

切换任务或返回

Page 59: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

MACRO$IRQ_Label HANDLER $IRQ_Exception_Function

EXPORT $IRQ_Label ; 输出的标号 IMPORT $IRQ_Exception_Function ; 引用的外部标号

$IRQ_Label ... LDR R0, =OSTCBHighRdy LDR R0, [R0] LDR R1, =OSTCBCur LDR R1, [R1] CMP R0, R1

ADD SP, SP, #4*3 MSR SPSR_cxsf, R3 ; 不进行任务切换 LDMEQFD SP!, {R0-R3, R12, PC}^ ; 进行任务切换 LDR PC, =OSIntCtxSw

MEND

• 关于中断及时钟节拍

比较当前任务是否为就绪的最高优先级任务,

如果不是则进行切换

设置堆栈指针和恢复 SPSR

进行任务切换或者恢复执行被中断任务

Page 60: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 关于中断及时钟节拍流程图

保存当前任务的寄存器组

中断嵌套数加 1

切换到系统模式执行中断服务程序

关中断执行 OSIntExit( )

切换到 IRQ模式判断是否需要进行

任务切换

切换任务或返回

中断服务程序( ISR )

在 ISR中可以打开中断实现中断嵌套

Page 61: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

void ISR(void){ OS_ENTER_CRITICAL() 或直接给变量 OsEnterSum赋 1; 清除中断源 ; 通知中断控制器中断结束: 开中断: OS_EXIT_CRITICAL(); 用户处理程序 ;}

• 中断服务程序的编写 因为中断发生时肯定是允许中断的,所以如果用户在清除中断源之前调用 μC/OS-II 的系统服务函数就很可能会造成芯片的中断系统工作异常而使程序工作异常。因此在函数开始处关闭中断,或者直接给变量 OSEnterSum赋 1 。如果用户程序没有这种情况,则不需要这个操作。在执行 OS_EXIT_CRITICAL( )后,中断重新打开,如果在接下来的用户处理程序中发生中断,就可以实现中断嵌套。

Page 62: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

第 7 章 目录

1. μC/OS-II 简介2. 移植规划3. 移植 μC/OS-II4. 移植代码应用到 LPC2000

Page 63: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

7.4 移植代码应用到 LPC2000

• 概述 在具体的项目中应用移植代码时,还需要做一些工作,这是因为:

1.各种基于 ARM7 处理器核的芯片的硬件结构不尽相同,所以需要编写部分启动代码(参看第 5章)。另外中断服务程序的编写方法也各不相同;2.因为各个项目对资源的要求不一样,所以尽管使用同一系列的芯片,其时钟节拍中断也可能使用不同的中断实现。

Page 64: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

7.4 移植代码应用到 LPC2000

• 概述 将 μC/OS-II 移植到 LPC2000 时,需要完成的工作主要有以下几个部分:

编写或获取启动代码; 挂接 SWI 软件中断; 中断及时钟节拍中断; 编写应用程序。

注:其中“启动代码”已经在第 5章中讲述。

Page 65: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

Reset LDR PC,ResetAddr LDR PC,UndefinedAddr LDR PC,SWI_Addr LDR PC,PrefetchAddr LDR PC,DataAbortAddr DCD 0xb9205f80 LDR PC,[PC, #-0xff0] LDR PC,FIQ_Addr

ResetAddr DCD ResetInitUndefinedAddr DCD UndefinedSWI_Addr DCD SoftwareInterruptPrefetchAddr DCD PrefetchAbortDataAbortAddr DCD DataAbortnouse DCD 0IRQ_Addr DCD IRQ_HandlerFIQ_Addr DCD FIQ_Handler

• 挂接 SWI 软件中断

将软中断异常处理程序挂接到内核是通过修改启动代码中的异常向量表实现, 代码如下所示:

发生软件中断时跳转到软件中断服务函数

Page 66: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

1.增加汇编接口的支持 方法是在文件中 IRQ.S 适当位置添加如下所示的代码,其中 xxx替换为自己需要的字符串。这样,汇编接口就完成了。

xxx_Handler HANDLER xxx_Exception

• 中断及时钟节拍中断

编写中断服务程序代码比较简单,按照 7.3.6 小节( )编写 C 语言处理函数即可。关键在于把程序与芯片的相关中断源挂接,使芯片在产生相应的中断后会调用相应的处理程序。 这需要做以下两个方面的工作:

周立功单片机

void ISR(void){

OS_ENTER_CRITICAL()或直接给变量OsEnterSum赋1;清除中断源;通知中断控制器中断结束:开中断: OS_EXIT_CRITICAL();用户处理程序;

}

• 中断服务程序的编写

因为中断发生时肯定是允许中断的,所以如果用户在清除中断源之前调用μ C/OS-II的系统服务函数就很可能会造成芯片的中断系统工作异常而使程序工作异常。因此在函数开始处关闭中断,或者直接给变量OSEnterSum赋1。如果用户程序没有这种情况,则不需要这个操作。在执行OS_EXIT_CRITICAL( )后,中断重新打开,如果在接下来的用户处理程序中发生中断,就可以实现中断嵌套。

2.初始化向量中断控制器 // 中断外设初始化 ; VICVectAddrX = (uint32) xxx_Handler ; VICVectCntlX = (0x20 | Y); VICIntEnable = 1 << Y;

每个中断都有自己的汇编接口代码

将汇编接口代码的入口设置

到向量中断

Page 67: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写应用程序 移植 μC/OS-II 是为了在自己的系统使用 μC/OS-II 。要在自己的系统中使用 μC/OS-II 编写自己的应用程序就必须遵守 μC/OS-II的编程规范。主要包括主函数和用户任务,它们的关系如下。

Main函数

初始化操作系统,并建立空闲任务创建根任务或更多

的任务

启动多任务环境

根任务

目标板初始化(启动系统时钟)

创建其它的任务

执行任务循环

任务 1执行特定操作执行任务循环

任务 n执行特定操作执行任务循环

. . .

Page 68: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写应用程序 移植 μC/OS-II 是为了在自己的系统使用 μC/OS-II 。要在自己的系统中使用 μC/OS-II 编写自己的应用程序就必须遵守 μC/OS-II的编程规范。主要包括主函数和用户任务,它们的关系如下。

Main函数

初始化操作系统,并建立空闲任务创建根任务或更多

的任务

启动多任务环境

根任务

目标板初始化(启动系统时钟)

创建其它的任务

执行任务循环

任务 1执行特定操作执行任务循环

任务 n执行特定操作执行任务循环

. . .多任务共享系统资源,分时执行

多任务共享系统资源,分时执行

多任务共享系统资源,分时执行

多任务共享系统资源,分时执行

Page 69: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写应用程序

Main函数

初始化操作系统,并建立空闲任务创建根任务或更多

的任务

启动多任务环境

移植 μC/OS-II 是为了在自己的系统使用 μC/OS-II 。要在自己的系统中使用 μC/OS-II 编写自己的应用程序就必须遵守 μC/OS-II的编程规范。主要包括主函数和用户任务,它们的关系如下。

根任务

目标板初始化(启动系统时钟)

创建其它的任务

执行任务循环

任务 1执行特定操作执行任务循环

任务 n执行特定操作执行任务循环

. . .多任务共享系统资源,分时执行

多任务共享系统资源,分时执行

多任务共享系统资源,分时执行

多任务共享系统资源,分时执行

Main函数

初始化操作系统,并建立空闲任务创建根任务或更多

的任务

启动多任务环境

#include "config.h"OS_STK TaskStartStk[TASK_STK_SIZE];OS_STK TaskStk[TASK_STK_SIZE];

int main (void){ OSInit(); OSTaskCreate(Task1, (void *)0, &TaskStartStk[TASK_STK_SIZE - 1], 0); OSStart(); return 0;}

定义任务的堆栈

Page 70: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写应用程序

根任务

目标板初始化(启动系统时钟)

创建其它的任务

执行任务循环

void Task1(void *pdata){ pdata = pdata; /* 避免编译警告 */ TargetInit(); /* 目标板初始化 */ for (;;) { OSTimeDly(OS_TICKS_PER_SEC / 50); if (GetKey() != KEY1) { continue; } OSTimeDly(OS_TICKS_PER_SEC / 50); if (GetKey() != KEY1) { continue; }

OSTaskCreate(Task2, (void *)0, &TaskStk[TASK_STK_SIZE - 1], 10); while (GetKey() != 0) { OSTimeDly(OS_TICKS_PER_SEC / 50); } }}

任务 1执行特定操作执行任务循环

将该任务放在循环中创建,是因为该任务执行

一次后会自行删除

Page 71: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院

• 编写应用程序

任务 1执行特定操作执行任务循环

根任务

目标板初始化(启动系统时钟)

创建其它的任务

执行任务循环

void Task1(void *pdata){ pdata = pdata; /* 避免编译警告 */ TargetInit(); /* 目标板初始化 */ for (;;) { OSTimeDly(OS_TICKS_PER_SEC / 50); if (GetKey() != KEY1) { continue; } OSTimeDly(OS_TICKS_PER_SEC / 50); if (GetKey() != KEY1) { continue; }

OSTaskCreate(Task2, (void *)0, &TaskStk[TASK_STK_SIZE - 1], 10); while (GetKey() != 0) { OSTimeDly(OS_TICKS_PER_SEC / 50); } }}

将该任务放在循环中创建,是因为该任务执行

一次后会自行删除

任务 1执行特定操作执行任务循环

// 任务功能:鸣叫两声,然后删除自己

void Task2(void *pdata){ pdata = pdata; /* 避免编译警告 */

BeeMoo(); /* 使蜂鸣器鸣叫 */ /* 延时 */ OSTimeDly(OS_TICKS_PER_SEC / 8); BeeNoMoo(); /* 使蜂鸣器停止鸣叫 */

OSTimeDly(OS_TICKS_PER_SEC / 4); BeeMoo(); /* 延时 */ OSTimeDly(OS_TICKS_PER_SEC / 8); BeeNoMoo(); /* 使蜂鸣器停止鸣叫 */

OSTaskDel(OS_PRIO_SELF); /* 删除自己 */}

Page 72: 第 7 章  移植 μC/OS-II 到 ARM7

南京林业大学信息学院