uCos-iii 学习笔记开篇
2016-03-16 08:39
330 查看
uCos-iii 学习笔记开篇
uCos-iii是一个可裁剪,可固化,可剥夺的多任务内核,没有任务数目的限制,其源代码开放,支持时间片轮转调度,系统API使用简单,易作为通用操作系统来进行学习,本章主要对前后台系统及实时内核的结构及调度进行总结。
1.1、前后台系统
简单的小系统通常设计成前后台结构,这个系统包括一个主循环和若干个中断服务程序,应用程序是一个主循环,循环中调用相关的函数完成相应的操作(后台),中断服务程序用于处理系统的异步事件(前台),前台也称作中断级,后台是任务级。前后台系统的缺点在于任务级响应延时,一些时间要求较高的操作通常会放在中断中进行处理,这会导致中断的执行时间变长,中断程序即使快速的生成了特定的数据,后台程序也需要运行到特定的代码处才能进行处理。
![](https://img-blog.csdn.net/20160316083729858?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图1-1 前后台系统
1.2、实时内核
实时系统通常把系统划分为多个任务,每个任务仅负责实现某一功能,每个任务都是一段简单的程序,通常是一个死循环,CPU在任一时刻只能执行一个任务,但每个任务都认为自己在独自使用整个CPU。实时内核的作用是尽最大效率的利用CPU资源,决定什么时候停止任务,什么时候进行任务切换。
![](https://img-blog.csdn.net/20160316083753217?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图1-2可剥夺型多任务内核
二、任务调度
用习惯了前后台系统刚刚使用实时操作系统时总是感觉不适应,不适应的原因很简单,对操作系统的工作方式不是很清楚,不清楚内核到底帮我们做了哪些工作,借助ucos-iii操作系统把通用操作系统的任务调度流程进行总结,明白了操作系统的调度方式,也就基本掌握了操作系统的使用,剩下的就是一些系统API的调用。
任务通常是一个循环,当任务挂起或有高优先级任务需要执行时会进行任务切换,任务切换首先调用OS_TASK_SW宏,这里只进行地址赋值,接着通过CPU_INT_EN宏跳转到OS_CPU_PendSVHandler汇编代码处执行上下文的切换操作,首先将当前的CPU寄存器做入栈操作,然后将堆栈指针指向高优先级任务的入口地址,再进行出栈操作,将栈中保存的CPU寄存器值还原到CPU寄存器中,这样高优先级任务就得到正确执行,执行结束后根据需要进行相关调度,详细流程参见代码注释及流程图。
2.1、代码片段
OS_CPU_PendSVHandler
CPSID I ;关闭中断
MRS R0,PSP ;保存任务堆栈地址到R0寄存器PSP
->R0
STMFD R0!, {R4-R11} ; 保存R4-R11到R0指向的存储单元中,地址自动+1
MOV32 R5,OSTCBCurPtr ; 保存当前任务控制块地址 OSTCBCurPtr->R5
;
LDR R6,[R5] ;
R5 -> R6
STR R0,[R6] ;
R6 -> R0(当前所指向的堆栈地址)
;到此为止完成上文保存
MOV R4,LR ;防止调用函数期间返回地址变更,保存返回地址 LR
-> R4
BL OSTaskSwHook ;
OSTaskSwHook();
; 将当前优先级切换为高优先级 OSPrioCur
= OSPrioHighRdy;
MOV32 R0,OSPrioCur ;
&OSPrioCur -> R0;
MOV32 R1,OSPrioHighRdy ;
&OSPrioHighRdy -> R1;
LDRB R2,[R1] ;
OSPrioHighRdy -> R2;
STRB R2,[R0] ;
OSPrioHighRdy -> OSPrioCur;
; 将当前任务控制块指针切换为高优先级任务控制块指针 OSTCBCurPtr
= OSTCBHighRdyPtr;
MOV32 R1,OSTCBHighRdyPtr;
&OSTCBHighRdyPtr -> R1;
LDR R2,[R1] ;
OSTCBHighRdyPtr -> R2;
STR R2,[R5] ;
OSTCBHighRdyPtr -> OSTCBCurPtr
ORR LR,R4, #0x04 ; 确保返回地址R4
-> LR;使用PSP
LDR R0,[R2] ;
OSTCBHighRdyPtr -> R0;
LDMFD R0!, {R4-R11} ;
R4-R11出栈
MSR PSP,R0 ;OSTCBHighRdyPtr
-> PSP
CPSIE I ; 开中断
BX LR ; 返回
END
在实际调试时一直不明白BX LR是如何跳转到指定的任务入口的,原来是在BX
LR语句执行时会执行其他CPU寄存器的出栈操作,该操作和入栈时一样,是由硬件自动完成的,出栈的顺序为R0~R3
R12 R14(LR) PC xPSR.然后跳转到PC处执行代码。
![](https://img-blog.csdn.net/20160316083807059?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图2-1切换过程分析
2.2、调度过程
![](https://img-blog.csdn.net/20160316083818513?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
图2-2任务调度流程
1、Task1正在执行(此处不会在任务堆栈中执行,这里只是示意)。
2、产生任务调度,可能是自身挂起让出CPU使用权,也可能是有高优先级任务抢占执行。
3、入栈操作来保存当前运行环境。
4、将SP指针指向高优先级任务Task2.
5、出栈操作来还原之前保存的运行环境。
6、执行高优先级任务(此处不会在任务堆栈中执行,这里只是示意)。
7、发生任务调度,具体流程同上。
三、总结
实时系统会帮助用户最大程度的利用CPU资源,多任务切换会造多CPU的假象,任务切换依赖于独立的任务堆栈空间,任务堆栈空间主要用于上下文切换和一些任务相关的临时变量,在使用实时系统时要注意任务堆栈空间的分配,还要注意一些系统API的使用场景及方式,后面会对uCOS-III的系统API使用进行总结,主要包括多任务创建、行为同步、数据通信、临界区保护、定时器等操作。
一、基本概念
uCos-iii是一个可裁剪,可固化,可剥夺的多任务内核,没有任务数目的限制,其源代码开放,支持时间片轮转调度,系统API使用简单,易作为通用操作系统来进行学习,本章主要对前后台系统及实时内核的结构及调度进行总结。1.1、前后台系统
简单的小系统通常设计成前后台结构,这个系统包括一个主循环和若干个中断服务程序,应用程序是一个主循环,循环中调用相关的函数完成相应的操作(后台),中断服务程序用于处理系统的异步事件(前台),前台也称作中断级,后台是任务级。前后台系统的缺点在于任务级响应延时,一些时间要求较高的操作通常会放在中断中进行处理,这会导致中断的执行时间变长,中断程序即使快速的生成了特定的数据,后台程序也需要运行到特定的代码处才能进行处理。
图1-1 前后台系统
1.2、实时内核
实时系统通常把系统划分为多个任务,每个任务仅负责实现某一功能,每个任务都是一段简单的程序,通常是一个死循环,CPU在任一时刻只能执行一个任务,但每个任务都认为自己在独自使用整个CPU。实时内核的作用是尽最大效率的利用CPU资源,决定什么时候停止任务,什么时候进行任务切换。
图1-2可剥夺型多任务内核
二、任务调度
用习惯了前后台系统刚刚使用实时操作系统时总是感觉不适应,不适应的原因很简单,对操作系统的工作方式不是很清楚,不清楚内核到底帮我们做了哪些工作,借助ucos-iii操作系统把通用操作系统的任务调度流程进行总结,明白了操作系统的调度方式,也就基本掌握了操作系统的使用,剩下的就是一些系统API的调用。
任务通常是一个循环,当任务挂起或有高优先级任务需要执行时会进行任务切换,任务切换首先调用OS_TASK_SW宏,这里只进行地址赋值,接着通过CPU_INT_EN宏跳转到OS_CPU_PendSVHandler汇编代码处执行上下文的切换操作,首先将当前的CPU寄存器做入栈操作,然后将堆栈指针指向高优先级任务的入口地址,再进行出栈操作,将栈中保存的CPU寄存器值还原到CPU寄存器中,这样高优先级任务就得到正确执行,执行结束后根据需要进行相关调度,详细流程参见代码注释及流程图。
2.1、代码片段
OS_CPU_PendSVHandler
CPSID I ;关闭中断
MRS R0,PSP ;保存任务堆栈地址到R0寄存器PSP
->R0
STMFD R0!, {R4-R11} ; 保存R4-R11到R0指向的存储单元中,地址自动+1
MOV32 R5,OSTCBCurPtr ; 保存当前任务控制块地址 OSTCBCurPtr->R5
;
LDR R6,[R5] ;
R5 -> R6
STR R0,[R6] ;
R6 -> R0(当前所指向的堆栈地址)
;到此为止完成上文保存
MOV R4,LR ;防止调用函数期间返回地址变更,保存返回地址 LR
-> R4
BL OSTaskSwHook ;
OSTaskSwHook();
; 将当前优先级切换为高优先级 OSPrioCur
= OSPrioHighRdy;
MOV32 R0,OSPrioCur ;
&OSPrioCur -> R0;
MOV32 R1,OSPrioHighRdy ;
&OSPrioHighRdy -> R1;
LDRB R2,[R1] ;
OSPrioHighRdy -> R2;
STRB R2,[R0] ;
OSPrioHighRdy -> OSPrioCur;
; 将当前任务控制块指针切换为高优先级任务控制块指针 OSTCBCurPtr
= OSTCBHighRdyPtr;
MOV32 R1,OSTCBHighRdyPtr;
&OSTCBHighRdyPtr -> R1;
LDR R2,[R1] ;
OSTCBHighRdyPtr -> R2;
STR R2,[R5] ;
OSTCBHighRdyPtr -> OSTCBCurPtr
ORR LR,R4, #0x04 ; 确保返回地址R4
-> LR;使用PSP
LDR R0,[R2] ;
OSTCBHighRdyPtr -> R0;
LDMFD R0!, {R4-R11} ;
R4-R11出栈
MSR PSP,R0 ;OSTCBHighRdyPtr
-> PSP
CPSIE I ; 开中断
BX LR ; 返回
END
在实际调试时一直不明白BX LR是如何跳转到指定的任务入口的,原来是在BX
LR语句执行时会执行其他CPU寄存器的出栈操作,该操作和入栈时一样,是由硬件自动完成的,出栈的顺序为R0~R3
R12 R14(LR) PC xPSR.然后跳转到PC处执行代码。
图2-1切换过程分析
2.2、调度过程
图2-2任务调度流程
1、Task1正在执行(此处不会在任务堆栈中执行,这里只是示意)。
2、产生任务调度,可能是自身挂起让出CPU使用权,也可能是有高优先级任务抢占执行。
3、入栈操作来保存当前运行环境。
4、将SP指针指向高优先级任务Task2.
5、出栈操作来还原之前保存的运行环境。
6、执行高优先级任务(此处不会在任务堆栈中执行,这里只是示意)。
7、发生任务调度,具体流程同上。
三、总结
实时系统会帮助用户最大程度的利用CPU资源,多任务切换会造多CPU的假象,任务切换依赖于独立的任务堆栈空间,任务堆栈空间主要用于上下文切换和一些任务相关的临时变量,在使用实时系统时要注意任务堆栈空间的分配,还要注意一些系统API的使用场景及方式,后面会对uCOS-III的系统API使用进行总结,主要包括多任务创建、行为同步、数据通信、临界区保护、定时器等操作。
相关文章推荐
- 【LeetCode】69. Sqrt(x)
- 使用简单工厂模式实现四则运算 C++
- bzoj4037 Str 矩阵乘法&动态规划
- 选择驾校经验
- iOS---cell-自适应高度
- 深入浅出之Spring第二章注解
- MySQL优化—工欲善其事,必先利其器之EXPLAI
- Android IOS WebRTC 音视频开发总结(六五)-- 给韩国电信巨头做咨询
- 定义一个继承Thread类,并覆盖run()方法,并在run()方法中每隔一百毫秒 打印一句话
- codechef CBAL
- dom4j api 详解【转】
- linux之etc目录
- 1901: Zju2112 Dynamic Rankings|树状数组套主席树
- 6.<1>四则运算的研究[栈]
- mongodb与sql语句对照表
- Python核心编程读书笔记0
- .NET Framework 各版本区别
- leetCode 53.Maximum Subarray (子数组的最大和) 解题思路方法
- DOM4J介绍与代码示例
- pku1080 Human Gene Functions DP