以下内容转载自安富莱电子: http://forum.armfly.com/forum.php

单任务系统
学习多任务系统之前,我们先来回顾下单任务系统的编程框架,即裸机时的编程框架。 裸机编程主要
是采用超级循环(super-loops)系统,又称前后台系统。应用程序是一个无限的循环,循环中调用相应
的函数完成相应的操作,这部分可以看做后台行为,中断服务程序处理异步事件,这部分可以看做是前台
行为。 后台也可以叫做任务级,前台也叫作中断级。

对于前后台系统的编程思路主要有以下两种方式:

轮询方式
对于一些简单的应用,处理器可以查询数据或者消息是否就绪,就绪后进行处理,然后再等待,如此
循环下去。 对于简单的任务,这种方式简单易处理。但大多数情况下,需要处理多个接口数据或者消息,
那就需要多次处理,如下面的流程图所示:

用查询方式处理简单的应用,效果比较好,但是随着工程的复杂,采用查询方式实现的工程就变的很
难维护,同时,由于无法定义查询任务的优先级,这种查询方式会使得重要的接口消息得不到及时响应。
比如程序一直在等待一个非紧急消息就绪,如果这个消息后面还有一个紧急的消息需要处理,那么就会使
得紧急消息长时间得不到执行。

中断方式
对于查询方式无法有效执行紧急任务的情况,采用中断方式就有效的解决了这个问题,下面是中断方
式简单的流程图:

采用中断和查询结合的方式可以解决大部分裸机应用,但随着工程的复杂,裸机方式的缺点就暴露出来了
 必须在中断(ISR)内处理时间关键运算:
 ISR 函数变得非常复杂,并且需要很长执行时间。
 ISR 嵌套可能产生不可预测的执行时间和堆栈需求。
 超级循环和 ISR 之间的数据交换是通过全局共享变量进行的:
 应用程序的程序员必须确保数据一致性。
 超级循环可以与系统计时器轻松同步,但:
 如果系统需要多种不同的周期时间,则会很难实现。
 超过超级循环周期的耗时函数需要做拆分。
 增加软件开销,应用程序难以理解。
 超级循环使得应用程序变得非常复杂,因此难以扩展:
 一个简单的更改就可能产生不可预测的副作用,对这种副作用进行分析非常耗时。
 超级循环 概念的这些缺点可以通过使用实时操作系统 (RTOS) 来解决。

多任务系统
针对这些情况,使用多任务系统就可以解决这些问题了。 下面是一个多任务系统的流程图:

多任务系统或者说 RTOS 的实现,重点就在这个调度器上,而调度器的作用就是使用相关的调度算法来决
定当前需要执行的任务。如上图所画的那样,创建了任务并完成 OS 初始化后,就可以通过调度器来决定
任务 A,任务 B 和任务 C 的运行,从而实现多任务系统。 另外需要初学者注意的是,这里所说的多任务系
统同一时刻只能有一个任务可以运行,只是通过调度器的决策,看起来像所有任务同时运行一样。为了更
好的说明这个问题,再举一个详细的运行例子,运行条件如下:
 使用抢占式调度器。
 1 个空闲任务,优先级最低。
 2 个应用任务,一个高优先级和一个低优先级,优先级都比空闲任务优先级高。
 中断服务程序,含 USB 中断,串口中断和系统滴答定时器中断。
下图 7.2 所示是任务的运行过程,其中横坐标是任务优先级由低到高排列,纵坐标是运行时间,时间
刻度有小到大。

(1) 启动 RTOS,首先执行高优先级任务。
(2) 高优先级任务等待事件标志(os_evt_wait_and)被挂起,低优先级任务得到执行。
(3) 低优先级任务执行的过程中产生 USB 中断,进入 USB 中断服务程序。
(4) 退出 USB 中断复位程序,回到低优先级任务继续执行。
(5) 低优先级任务执行过程中产生串口接收中断,进入串口接收中断服务程序。
(6) 退出串口接收中断复位程序,并发送事件标志设置消息(isr_evt_set),被挂起的高优先
级任务就会重新进入就绪状态,这个时候高优先级任务和低优先级任务都在就绪态,基于优
先级的调度器就会让高优先级的任务先执行,所有此时就会进入高优先级任务。
(7) 高优先级任务由于等待事件标志(os_evt_wait_and)会再次被挂起,低优先级任务开始
继续执行。
(8) 低优先级任务调用函数 os_dly_wait,低优先级任务被挂起,从而空闲任务得到执行。
(9) 空闲任务执行期间发生滴答定时器中断,进入滴答定时器中断服务程序。
(10) 退出滴答定时器中断,由于低优先级任务延时时间到,低优先级任务继续执行。

(11) 低优先级任务再次调用延迟函数 os_dly_wait,低优先级任务被挂起,从而切换到空闲任务。
空闲任务得到执行。
通过上面实例的讲解,大家应该对多任务系统完整的运行过程有了一个全面的认识。 随着教程后面对
调度器,任务切换等知识点的讲解,大家会对这个运行过程有更深刻的理解。
RTX 就是一款支持多任务运行的实时操作系统,具有时间片,抢占式和合作式三种调度方法。 通过
RTX 实时操作系统可以将程序函数分成独立的任务,并为其提供合理的调度方式。 同时 RTX 实时操作系
统为多任务的执行提供了以下重要优势:
 任务调度 - 任务在需要时进行调用,从而确保了更好的程序执行和事件响应。
 多任务 - 任务调度会产生同时执行多个任务的效果。
 确定性的行为 - 在定义的时间内处理事件和中断。
 更短的 ISR - 实现更加确定的中断行为。
 任务间通信 - 管理多个任务之间的数据、内存和硬件资源共享。
 定义的堆栈使用 - 每个任务分配一个堆栈空间,从而实现可预测的内存使用。
 系统管理 - 可以专注于应用程序开发而不是资源管理。

任务设置
RTX 操作系统的配置工作是通过配置文件 RTX_Conf_CM.c 实现。 在 MDK 工程中打开文件
RTX_Conf_CM.c,可以看到如下图 7.4 所示的工程配置向导:

用于任务配置的主要是如下两个参数:
 Number of concurrent running tasks
参数范围 0 – 250
表示同时运行的最大任务数,这个数值一定要大于等于用户实际创建的任务数,空闲任务不包含
在这个里面。比如当前的数值是 6,就表示用户最多可以创建 6 个任务。
 Number of tasks with user-provided stack
参数范围 0 – 250
表示自定义任务堆栈的任务数,如果这个参数定义为 0 的话,表示所有的任务都是使用的配置向
导里面第三个参数 Task statck size 大小。 比如:
Number of concurrent running tasks = 6
Number of tasks with user-provided stack = 0
表示允许用户创建 6 个任务,所有的 6 个任务都是分配第三个参数 Task statck size 大小的任务
堆栈空间。
Number of concurrent running tasks = 6
Number of tasks with user-provided stack = 3
表示允许用户创建 6 个任务,其中 3 个任务是用户自定义任务堆栈大小,另外 3 个任务是用的第
三个参数 Task statck size 大小的任务堆栈空间。

栈溢出检测
如果怕任务栈溢出,那么此功能就非常的有用了,用户只需在 RTX 的配置向导里面使能使用任务栈检测即可: 

RTX 初始化和启动
使用如下 3 个函数可以实现 RTX 的初始化:
 os_sys_init()
 os_sys_init_prio()
 os_sys_init_user()

关于这 3 个函数的讲解及其使用方法可以看参考资料 rlarm.chm 文件 :

函数描述:
函数 os_sys_init_user 用于实现 RTX 操作系统的初始化和启动任务的创建,并且使用这个函数做初始化还
可以自定义任务栈的大小。
 第 1 个参数填启动任务的函数名。
 第 2 个参数是任务的优先级设置,用户可以设置的任务优先级范围是 1-254。 优先级 0 用于空闲任
务,如果用户将这个参数设置为 0 的话,RTX 系统会将其更改为 1。 优先级 255 被保留用于最重要
的任务。
 第 3 个参数是任务栈地址。
 第 4 个参数是任务栈大小。
使用这个函数要注意以下几个问题
1. 必须在 main 函数中调用 os_sys_init_user。
2. 任务栈空间必须 8 字节对齐,可以将任务栈数组定义成 uint64_t 类型即可。 (补充说明,这就是为什么我们定义任务栈的时候要用大小除以8,因为sizeof所求大小需要乘以元素字节,这里定义的正好是uint64_t,八个字节的,这样能保证是八字节对齐的)

3. 优先级 255 代表更重要的任务。
4. 对于 RTX 操作系统来说,优先级参数中数值越小优先级越低,也就是说空闲任务的优先级是最低的,因为它的优先级数值是 0 。

任务创建
使用如下 4 个函数可以实现 RTX 的任务创建:
 os_tsk_create
 os_tsk_create_ex
 os_tsk_create_user
 os_tsk_create_user_ex

ex后缀是extension的缩写,看英文文档就会知道的,表示扩展。

函数描述:
函数 os_tsk_create_use 用于实现 RTX 操作系统的任务创建,并且还可以自定义任务栈的大小。
 第 1 个参数填创建任务的函数名。
 第 2 个参数是任务的优先级设置,用户可以设置的任务优先级范围是 1-254。 优先级 0 用于空闲任
务,如果用户将这个参数设置为 0 的话,RTX 系统会将其更改为 1。 优先级 255 被保留用于更重要
的任务。 如果新创建的任务优先级比当前正在执行任务的优先级高,那么就会立即切换到高优先级
任务去执行。
 第 3 个参数是任务栈地址。
 第 4 个参数是任务栈大小。
 函数的返回值是任务的 ID,使用 ID 号可以区分不同的任务。
使用这个函数要注意以下问题
1. 任务栈空间必须 8 字节对齐,可以将任务栈数组定义成 uint64_t 类型即可。

任务删除
使用如下 2 个函数可以实现 RTX 的任务删除:
 os_tsk_delete
 os_tsk_delete_self

函数描述:
函数 os_tsk_create_use 用于实现 RTX 操作系统的任务删除
 第 1 个参数填要删除任务的 ID。
 如果任务删除成功,函数返回 OS_R_OK,其余所有情况返回 OS_R_NOK,比如所写的任务 ID 不存在。

使用这个函数要注意以下问题:
1. 如果用往此函数里面填的任务 ID 是 0 的话,那么删除的就是当前正在执行的任务,此任务被删除后,
RTX 会切换到任务就绪列表里面下一个要执行的高优先级任务。

空闲任务
几乎所有的小型 RTOS 中都会有一个空闲任务,空闲任务应该属于系统任务,是必须要执行的,用
户程序不能将其关闭。不光小型系统中有空闲任务,大型的系统里面也有的,比如 WIN7,下面的截图就
是 WIN7 中的空闲进程。

空闲任务主要有以下几个作用:
 用户不能让系统一直在执行各个应用任务,这样的话系统利用率就是 100%,系统就会一直的超负荷
运行,所以空闲任务很有必要。
 为了更好的实现低功耗,空闲任务也很有必要,用户可以在空闲任务中实现睡眠,停机等低功耗措施。

代码练兵场:

K1 按键按下,删除任务 AppTaskLED。
K2 按键按下,重新创建任务 AppTaskLED。
不按键的时候,LED和Beep翻转。

int main ( void )
{
Bsp_Init(); /* 创建启动任务 */
os_sys_init_user (AppTaskStart, /* 任务函数 */
, /* 任务优先级 */
&AppTaskStartStk, /* 任务栈 */
sizeof(AppTaskStartStk)); /* 任务栈大小,单位字节数 */
while ( )
{ } }
__task void AppTaskUserIF(void)
{ while()
{
if(key1_flag==)
{
key1_flag=;
printf("K1键按下,删除任务HandleTaskLED\r\n");
if(HandleTaskLED != NULL)
{
if(os_tsk_delete(HandleTaskLED) == OS_R_OK)
{
HandleTaskLED = NULL;
printf("任务AppTaskLED删除成功\r\n");
}
else
{
printf("任务AppTaskLED删除失败\r\n");
}
}
}
if(key2_flag==)
{
key2_flag=;
printf("K2键按下,重新创建任务AppTaskLED\r\n");
if(HandleTaskLED == NULL)
{
HandleTaskLED = os_tsk_create_user(AppTaskLED, /* 任务函数 */
, /* 任务优先级 */
&AppTaskLEDStk, /* 任务栈 */
sizeof(AppTaskLEDStk)); /* 任务栈大小,单位字节数 */
}
}
os_dly_wait();
}
}

输出打印:

可以看到按下K1时,LED灯不再翻转,按下K2后,又开始翻转。

RTX 配置:
RTX 配置向导详情如下:

RTX——第7章 任务管理的更多相关文章

  1. RTX——第13章 事件标志组

    以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 前面的章节我们已经讲解了任务管理和时间管理,从本章节开始讲解任务间的通信和同步机制.首先讲解任务间的通信 ...

  2. RTX——第10章 任务调度-抢占式、时间片和合作式

    以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章教程为大家将介绍 RTX 操作系统支持的任务调度方式,抢占式,时间片和合作式,这部分算是RTX 操作 ...

  3. RTX——第9章 任务运行在特权级或非特权级模式

    以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章教程为大家讲解 RTX 运行模式的一个重要知识点,特权级模式和非特权级模式,有些资料或者书籍将非特权 ...

  4. RTX——第19章 SVC 中断方式调用用户函数(后期补历程)

    以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章节为大家讲解如何采用 SVC 中断方式调用用户函数. 当用户将 RTX 任务设置为工作在非特权级模式 ...

  5. RTX——第18章 内存管理

    以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 内存管理介绍在 ANSI C 中,可以用 malloc()和 free()2 个函数动态的分配内存和释放 ...

  6. RTX——第17章 定时器组

    以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章节为大家讲解 RTX 支持的定时器组,或者叫软件定时器,或者叫用户定时器均可.软件定时器的功能比较简 ...

  7. RTX——第16章 消息邮箱

    以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 前面几个章节主要给大家讲解了任务间的同步和资源共享机制,本章节为大家讲解任务间的通信机制消息邮箱,RTX ...

  8. RTX——第15章 互斥信号量

    以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章节开始讲解 RTX 的另一个重要的资源共享机制---互斥信号量(Mutex,即 Mutual Exc ...

  9. RTX——第14章 信号量

    以下内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章节开始讲解 RTX 的另一个重要的任务间的同步和资源共享机制,信号量. 信号量有3种用途: 1) 表 ...

随机推荐

  1. 〖Linux〗Ubuntu13.10,配置tftp服务器

    前言,配置了好久没有发现老是出问题tftp: server error: (2) Access violation,一般侦测之后... 1. 安装软件包:apt-getsudo apt-get ins ...

  2. python之函数用法any()

    # -*- coding: utf-8 -*- #python 27 #xiaodeng #python之函数用法any() #any() #说明:如果iterable的任何元素不为0.''.Fals ...

  3. lr如何获取当前系统时间戳

    lr如何获取当前系统时间戳 一般使用time函数,获取当前unix时间戳 lr程序如下: int t1; char a[20]; t1=time();//获取当前系统时间 //根据不同情况,将时间存储 ...

  4. 在centos (linux) 搭建 eclipse c++开发分环境

    网上说得很多,很烦,操作了很多,总有错误,但解决方案很简单.步骤就下面几步就OK了 安装gcc .g++ yum install gcc yum install gcc-c++ 安装jdk,配置jdk ...

  5. 从零开始学做微信小程序,看这些就够了!

    随着正式开放公测,微信小程序再次万众瞩目,越来越多的企业和个人涌入到小程序开发的大军中.小程序究竟是什么?适合做小程序的产品有哪些?做小程序需要提前准备什么?如何零基础学做小程序?此文,将列出OSC上 ...

  6. web.xml文件头出错

    原先将web.xml文件头设置为如下格式 <?xml version="1.0" encoding="UTF-8"?><web-app ver ...

  7. 【LeetCode】18. 4Sum (2 solutions)

    4Sum Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d  ...

  8. 数据源与JNDI资源实现JSP数据库连接池实例

    名词解释:JNDI的全称是java命名与目录接口(Java Naming and Directory Interface),是一个应用程序设计的API,为开发人员提供了查找和访问各种命名和目录服务的通 ...

  9. RHCE7 管理II-5管理进程的优先级

    进程的优先级值称为进程的nice值,共有40种不同的取值(用数字-20到19表示) nice值越大,表示进程的优先级越低. 进程的nice值,只允许root用户来设置负的nice:其他用户只允许设置正 ...

  10. ELK系统搭建流程

    ELK系统搭建流程 1. Logstash 1.1 安装 注:安装在需要收集日志的机器上. cd /data/softs sudo wget https://download.elastic.co/l ...