5.3 协作式多任务操作系统
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Task0程序 入口地址
tnOsCreate(Task0Addr, pucStkTask0)
CPU
TCB填充:包括bp, TCB申请:由于 TCB0的状态字为 堆栈指针,函数入 口地址以及设置任 “删除状态”,所 有将其分配给Task0 务为“就绪状态”
Task0堆栈指针
创建任务的程序实现
tiny_os_51_core.c
任务块结构体 __GtcbTasks[x]
上下文信息 jbTaskContext
上下文信息 jmp_buf [x] bp SP addr15~addr8
ucTaskStat 任务状态字
addr7~addr0
ucTaskStat 即任务状态字,是char型变量,对于V1.0版本的 TinyOS51,它有两个值,如下宏定义所示: #define __TN_TASK_FLG_DEL 0x00 // 任务被删除 #define __TN_TASK_FLG_RDY 0x01 // 任务就绪
设置任务就绪状态 创建任务中不需要创建空闲任务。
创建任务失败
源自文库
结束
创建任务时TCB填充
假设系统最大的任务数为2,系统刚完成初始化,现在要创建Task0,TCB的申请和 填充过程是:
TCB0 bp SP addr15~addr8 addr7~addr0 ucTaskStat xxxxxxxx bp pucStkTask0 xxxxxxxx xxxxxxxx Task0Addr高8位 xxxxxxxx Task0Addr低8位 00000001 00000000 TCB1 xxxxxxxx xxxxxxxx xxxxxxx xxxxxxxx 00000000
TN_OS_TASK_HANDLE tnOsTaskCreate (void (*pfuncTask)(void), idata unsigned char *pucStk) { TN_OS_TASK_HANDLE thRt; for (thRt = 0; thRt < TN_OS_MAX_TASKS; thRt++) { // 搜索是否有空闲的任务控制块 if (__GtcbTask[thRt].uctaskStat == __TN_TASK_FLG_DEL) { setTaskJmp(pfuncTask, pucStk, __GtcbTasks[thRt].jbTaskContext); // 保存上下文信息 __GtcbTasks[thRt].ucTaskStat = __TN_TASK_FLG_RDY; // 任务就绪 return thRt; } } return -1; } // 如果创建任务失败,则返回-1 // 如果创建任务成功,则返回该任务的句柄
目
录
整体规划 任务控制块 内核API 小结
内部变量初始化
TinyOS51开始时没有任务存在,所以必须将所有的任务控制块初始化为一个 “空白表”,即将任务初始化为“删除状态”。
TCB0
bp SP addr15~addr8 addr7~addr0 ucTaskStat 任务状态字 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx 00000000
TinyOS51
tnOsTaskCreate() 任务创建
tnOsSched() tnOsTaskDel() tnOsTaskCreate() tnOsStart() tnOsInit()
作用 初始化TinyOS51 实现任务切换, 创建一个任务, 启动多任务环境, 删除一个任务, 执行下一个任务 内部变量 为任务创建资源 并执行第一个任 释放删除任务的 (内存) 务 资源(内存) 注意 调用此函数之前 必须在任务中调 该函数可在调用 必须在调用其他 可以删除其他任 tnOsInit()函数后 务或自身 用,而且每个任 函数之前调用, 必须创建至少一 并只能调用一次 务都必须周期性 任意时候调用, 个任务,该函数 地调用它 但在调用 不能重复调用, tnOsStart()函数之 且不返回 前必须调用一次
理论最大任务数量少于8个
协作式多任务操作系统运行示例
main.c
static idata unsigned char __GucTaskStk[2][32]; static unsigned char __GucTask0; static unsigned char __GucTask1;
void task0 (void) { ……} void task1 (void) { ……} void main (void) { tnOsInit(); tnOsTaskCreate(task0,__GucTaskStks[0]); tnOsTaskCreate(task1,__GucTaskStks[1]); tnOsStart(); }
TinyOS51
支持的任务 对最大任务数目 支持的任务数量有限 数量无限 没有限制
51单片机idata空间256字节 0xFF
Task3任务堆栈 Task2任务堆栈 Task1任务堆栈
Task0任务堆栈
1 2
单片机片内idata空间有限 任务堆栈占用idata资源
不能继续分配 任务堆栈 0x00
TinyOS51支持的任务数
0x00 0x01
// 任务被删除 // 任务就绪
内部变量初始化程序
tiny_os_51_core.c
static data TN_OS_TASK_HANDLE void thOsInit (void) { TN_OS_TASK_HANDLE
__GthTaskCur;
// 当前任务句柄 // 初始化任务控制块
启动多任务环境
在操作系统中,运行第一个用户任务的过程被称为“启动多任务环境”,也 即运行句柄为0的任务。TinyOS51是通过调用tnOsStart()函数实现的,在内部由 longjmp()函数执行句柄为0的任务。
void tnOsStart (void) { longjmp(__GtcbTasks[0].jbTaskContext); }
pfuncTask:任务函数;pucStk:堆栈位置,堆栈至少 void tnOsStart (void) tnOsSched (void) tnOsInit(void) thTask:任务句柄,如果其值为-1,则删除任务自身 要16字节
thTask:任务句柄,如果其值为-1,则创建任务失败
资源配置
// 分配任务堆 // 任务0测试变量 // 任务1测试变量
// 初始化系统 // 创建任务0 // 创建任务1 // 启动任务
全速运行,在任务函数中设置断点,可以看到2个任务依次执行
目
录
整体规划 任务控制块 内核API 小结
任务的识别和TCB
名字 工号 职称
堆栈指针 返回地址 TCB 任务状态 延时计数
TCB的程序实现
tiny_os_51_core.c
#define __TN_TASK_FLG_DEL #define __TN_TASK_FLG_RDY struct tn_os_tcb { jmp_buf jbTaskContext; // 用于存储上下文信息 // 任务状态字 0x00 0x01 // 任务被删除 // 任务就绪
TCB1
xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx 00000000
TCBn
xxxxxxxx xxxxxxxx
……
xxxxxxx xxxxxxxx xxxxxxxx 00000000
#define __TN_TASK_FLG_DEL #define __TN_TASK_FLG_RDY
unsigned char ucTaskStat; };
typedef
struct
tn_os_tck
TN_OS_TCB;
//TN_OS_TCB类型等效struct tn_os_tcb
static
data
TN_OS_TCB
__GtcbTasks[TN_OS_MAX_TASK]; // 任务控制块的结构体数组
5.3 协作式多任务操作系统
目
录
整体规划 任务控制块 内核API 小结
简介
任务切换的时机完全取决于正在运行的任务;
现代操作系统不再使用,适合于学习范例;
下面介绍 TinyOS51 V1.0版 操作系统。
内核 API
TinyOS51 V1.0是完全用C语言编写的协作式多任务操作系统,它的内核API (Application Interface Program:接口函数)包括5个函数。 tnOsInit() 系统初始化 tnOsStart() 系统启动
调用 setjmp()
是否存在下一 个就绪任务? 是
否
实现系统 空闲任务
通过任务转换实现
保存当前任务TCB
等待当前任务就绪
调用 longjmp()
从下一个就绪任务 TCB恢复上下文
结束
任务切换程序说明1
tiny_os_51_core.c
TCB[2] … TCB[n] TCB结构体 类型数组 数组下标, 俗称句柄 Handle
TCB的构成
TCB的类型是结构体,对于V1.0版本的TinyOS51操作系统,它主要由上下文信 息和任务状态字组成。
jbTaskContext是 jmp_buf 数组类 型变量,而 jmp_buf 数组类 型在<setjmp.h> 中定义
0xFF
Task3任务堆栈 Task2任务堆栈 Task1任务堆栈 Task0任务堆栈
0xFF
Task7任务堆栈
0x00
至少32字节空间 • R0~R7 • 编译器用到的空间 • TinyOS51占用空间 • 用户代码占用空间 0x00
Task1任务堆栈 Task0任务堆栈
实际最大任务数以3~4个最为合适
tnOsTaskDel() 任务删除
名 称 名 称 函数原型 名 称 函数原型 函数原型 输入参数 输入参数 返回值
tnOsSched() 任务切换
tnOsTaskCreate() tnOsTaskDel() TN_OS_TASK_HANDLE tnOsTaskCreate (void( * tnOsSched() tnOsStart() pfuncTask)(void), idata unsigned char *pucStk) tnOsInit() void tnOsTaskDel (TN_OS_TASK_HANDLE thTask)
创建任务
在操作系统中,任何一个程序只有成为了任务才能在内存中运行,使用创建任务 创建与之对应的任务。
开始
如果没有空闲TCB 则不能创建任务
关于空闲任务
是否有空闲 任务控制块
是 保存上下文信息
否
空闲任务是CPU闲置时候运行的任务,TinyOS51为了节省片内 填充TCB的过程 RAM,决定使用调度器来完成空闲任务的工作。
RTOS使用TCB指针识别任务,对于 SDCC编译器来说,指针变量占3个字节空 间,当任务较多时,内存开销大。
pTCB2 … pTCBn
TCB2 …
TCBn
TinyOS51
TCB[1]
TinyOS51使用TCB结构体类型数组 下标来识别任务,类型是无符号char型, 仅占一个字节内存空间,适合内存资源 紧张的51单片机
thTask;
// 操作的任务
for (thTask = 0; thTask < TN_OS_MAX_TASKS; thTask++) { __GtcbTasks[thTask].ucTaskStat = TN_TASK_FLG_DEL; } __GthTaskCur } = 0; // 初始化任务号为0 // 使任务处于删除状态
企业员工
操作系统任务
TCB全称是Task Control Block,即任务控制块,它是一个结构体数据结构, 用于记录各个任务的各种信息,包括任务堆栈指针、任务状态、延时计数、 等待事件指针等。
RTOS和TinyOS51任务识别
RTOS(实时操作系统)
指向TCB 的指针 pTCB1 TCB 结构体变量 TCB1
// 执行0号任务
SP
PC 高8位
Task0 堆栈指针 Task0 入口地址高8位 Task0 入口地址低8位 CPU
Task0
Task1
低8位
Task2
任务切换
任务切换是指保存当前任务的上下文,并恢复需要执行任务的上下文的过程。
任务在宏观上是并发运行的
开始
task0
task1
task0
task1