当前位置: 首页 > news >正文

Small RTOS51 学习笔记(6)如何切换任务(上)

个人笔记,主要内容均来自原文

文章目录

  • CPU 可以执行多个任务的原因
  • CPU 怎样运行才能执行多个任务
  • 何时进行任务切换
  • Small RTOS51 任务切换时的程序框图
  • 数组 OSTsakStackBotton[] 和 Small RTOS51 的堆栈结构
  • 变量 OSFastSwap
  • 常数数组 OSMapTb[]

CPU 可以执行多个任务的原因

原文从汇编指令的角度描述了 CPU 可以同时执行多个任务的原因,我不太理解原理,所以只把结论记录一下,以下结论摘自原文。

对于一段程序,如果能保证以下条件,程序的执行结果是一致的:

  1. CPU 执行了同样的指令序列,不管指令是从哪里来的,中间是否插入了别的指令;
  2. 所有指令执行时所需的关键数据一样,不管数据存储的位置。

所有的多任务操作系统都利用了这样这样一个事实:让任务轮流执行,又让每一个任务满足以上两点。当速度足够快时,人们就认为多个任务在同时运行时,而且人们看到每个任务都运行正确(只是速度变慢了)。

CPU 怎样运行才能执行多个任务

当一个任务从某个地址开始存放代码,另一个任务就不可以在那里存放不同的代码,也就是说各个任务所占用的代码空间不可以重叠。另外各个任务所占用的数据空间也不可以重叠。

不过我们一般使用高级语言编写程序,即使需要使用汇编,也是用宏汇编,极少使用小汇编,这样,编译器或汇编器就会产生与位置无关的代码,让连接器来确定代码和数据存放的位置。也就是说,无论代码和数据放到任何位置,程序都能正确执行。这样的话,就满足了上一章的条件一。

同样,连接器也将各个任务的数据分配到不同的空间,所以上一章的条件二也已满足。但连接器不会为每一个任务分配独立的堆栈,如果此时多个任务交叉运行,就会破坏这些任务的堆栈数据。所以操作系统要为每个任务分配独立的堆栈,并在任务切换时改变堆栈指针。

另外,各个任务会共享寄存器,所以需要在任务切换时对每个任务的寄存器值进行保存和恢复,这些寄存器值存放在上面提到的各个任务的独立堆栈中。

到这里,CPU 就可以执行多个任务了。

何时进行任务切换

对于协作式操作系统(如 Windows 3.1 和 一些免费的 RTOS 等),任务切换是在任务主动放弃 CPU 时进行的;对于基于时间片轮询调度算法的操作系统(如 RTX51Tiny),任务切换除了发生在任务主动放弃 CPU 时外,还会发生在任务的时间片使用完时;对于基于有优先级的抢占式的操作系统,有两种方法能中断当前任务而运行另一个任务:一种是任务自己放弃 CPU,另一种是中断服务程序让更高优先级任务就绪,出中断后进行任务切换。

有一些操作系统既有优先级调度算法,又有时间片轮询调度算法。Small RTOS51 是完全基于有优先级的抢占式的操作系统。

Small RTOS51 任务切换时的程序框图

图片摘自原文:
在这里插入图片描述

数组 OSTsakStackBotton[] 和 Small RTOS51 的堆栈结构

不知道为什么是 Tsak,原文和源码都是 Tsak,难道不是 Task ?
Small RTOS51 把所有的内部自由 RAM 空间分配给当前任务。为了顺利进行堆栈变化,Small RTOS51定义了一个数组 OSTsakStackBotton[] 保存所有任务的顶端和低端位置,它的定义如下:

uint8 idata * data OSTsakStackBotton[OS_MAX_TASKS + 2];/* 任务堆栈底部位置            */

在 CPU 初始化函数中,将每个任务的 OSTsakStackBotton[] 赋值为系统堆栈的首地址,后续如何操作这里暂不研究。

/*********************************************************************************************************
** 函数名称: OSCPUInit
** 功能描述: Small RTOS 与系统相关的初始化
** 输 入: 无
** 输 出 : 无
** 全局变量: OSTaskID,OSTsakStackBotton,SP
** 调用模块: LoadCtx
** 
** 作 者: 陈明计
** 日 期: 2002年2月22日
**-------------------------------------------------------------------------------------------------------
** 修改人:
** 日 期:
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
        void OSCPUInit(void)  small
{
    uint8 i;

    for (i = 0; i < OS_MAX_TASKS + 1; i++)
    {
        OSTsakStackBotton[i] = STACK;
    }
    OSTsakStackBotton[OS_MAX_TASKS + 1] = (uint8 idata *)(IDATA_RAM_SIZE % 256);
    
}

变量 OSFastSwap

#if OS_MAX_TASKS < 9            
uint8 data OSFastSwap[1];                        /* 任务是否可以快速切换 */
#else
uint8 data OSFastSwap[2];
#endif

任务快速切换的标志,当 OSFastSWap[] 中某一位为 0 时,表示这一位对应的任务是通过中断被强制放弃 CPU 时间的,之后它获得 CPU 时间而继续运行时,必须从该任务的堆栈中恢复所有寄存器;当 OSFastSWap[] 中某一位为 1 时,表示这一位对应的任务是通过调用内核函数主动放弃 CPU 时间的,之后它获得 CPU 时间而继续运行时,只需切换 PC 指针,不需要恢复寄存器。

原理:Keil C51 编译器在编译 C 语言程序时,如果一个函数调用了一个外部函数,当这个函数返回时,R0~R7、ACC、B、PSW、DPH 和 DPL 等寄存器会发生变化。因此不需要提前保存寄存器的值。

常数数组 OSMapTb[]

该数组在前面的笔记中也有所提及,主要用来对标志的置位和复位。数组里的值对应的是任务ID在某些数据中对应的偏移量。

uint8 const OSMapTbl[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00};

下面是内核代码中关于 OSMapTb[] 的例子(这个数组的值其实就是对 0x1 进行了适当的偏移)

        if ((OSTaskCreated[0] & OSMapTbl[TaskID]) != 0)
        {
            return FALSE;
        }
        OSTaskCreated[0] |= OSMapTbl[TaskID];
        OSTaskRuning[0] |= OSMapTbl[TaskID];

相关文章:

  • Oracle数据库中的动态SQL(Dynamic SQL)
  • [数据集][目标检测]烟叶病害检测数据集VOC+YOLO格式612张3类别
  • 数据库语言、SQL语言、数据库系统提供的两种语言
  • flink 常见的缩减状态的方式
  • CS61C 2020计算机组成原理Lecture01-数字表示,溢出
  • 电脑上如何多开微信软件(多个微信同时使用)
  • iOS 通过NSURLProtocol拦截WKWebView网络请求
  • springboot+vue前后端分离适配cas认证的跨域问题
  • 2024智慧城市革命:人工智能、场景与运营的融合之力
  • 计算机网络—ENSP常用指令
  • STM32学习5 时钟系统
  • 【数据结构】周末作业
  • 【笔试题】【day7】
  • 【算法 | 实验6-1】n*n的网格,从左上角开始到右下角结束遍历所有的方块仅一次,总共有多少种不同的遍历路径
  • (附源码)springboot人体健康检测微信小程序 毕业设计 012142
  • 《uni-app》一个非canvas的飞机对战小游戏实现-requestAnimationFrame详解
  • Centos7安装Docker搭建Pikachu靶场
  • 【C语言 数据结构】线性表 - 顺序表的实现
  • 【学生管理系统】学生管理(重点)
  • 普通索引还是唯一索引?
  • 详解:递归 和 排序(冒泡排序,选择排序,插入排序,归并排序,快速排序,希尔排序)
  • 【问题记录】防止mimikatz获取到明文密码
  • 超实用的JS常用算法详解(推荐)
  • 02-nginx环境准备
  • CSS 基础知识 属性
  • 【学生管理系统】整合JWT(完)
  • maya2023 安装和导入PyMEL
  • Java学习--JDBC
  • 【HDU No. 1224】 免费DIY之旅
  • 中国软件三季度业绩预测,中国软件股票趋势预测
  • 【MATLAB教程案例26】图像特征点提取算法matlab仿真与分析——sift,surf,kaze,corner,BRISK等
  • Tinyhttpd -- 用 C 从零写一个 HTTP 服务器