嵌入式实时操作系统3——任务切换

2023-05-16

任务切换原理
假设有一程序,程序内有一个无限循环,在循环内部有5个表达式,代码如下:
在这里插入图片描述
程序在循环中,会依次执行表达式1-》表达式2-》表达式3-》表达式4-》表达式5-》表达式1无限循环。假设没有使用静态变量,没有使用堆空间,没有中断程序。程序每执行一个表达式后的处理器状态如下(每一种颜色代表一种状态,颜色变化说明状态变化):
在这里插入图片描述
程序循环周期执行,处理器的状态也循环周期变化。
我们将指令存储器,数据存储器,寄存器堆的所有数据称为:处理器总值。上图中处理器总值为P1,P2,P3,P4,P5 。

假设现在有一种“神奇的力量”将处理总值改变成P3,处理器将如何运行?
处理器将会按照P3,P4,P5,P1,P2,P3的顺序运行,运行图如下:
在这里插入图片描述
对应的程序运行状态:表达式3-》表达式4-》表达式5-》表达式1-》表达式2-》表达式3无限循环。
我们可以得出一个结论:在不考虑外设,中断等因素,给处理器一个合理总值Pn,处理器的下一个总值必然为Pn+1 。

利用这个原理,给处理器任意一个合理总值Pn,使得程序从任意一个合理位置开始运行。(关于总值切换详细说明请参考《RTOS系列2——任务调度子系统1》)

我们设计一种模式:每个任务有独立的代码区,有独立的栈区。多任务系统处理器状态如下图:
在这里插入图片描述
每个任务的代码区(代码区可多任务共享),独立任务栈区,静态区(可以共享)。将每个任务的代码区,独立任务栈区,静态区,独立寄存器堆所有数据称为相对总值。通过保存和载入相对总值实现任务切换。单个任务处理器状态如下图:
在这里插入图片描述
由于代码区数据不会改变,独立任务栈区不会被其他任务操作,任务栈区相对任务不会变,寄存器堆会变化,因此在这种情况下保存相对总值,等效为保存寄存器堆数据

如何让任务有独立任务栈区,在静态区创建一个静态数组task1_stack[SIZE],任务使用这一个静态数组作为独立任务栈区,栈指针指向这个静态数组,栈的大小为SIZE。栈指针保存在静态区,作为一个全局变量。
在这里插入图片描述
如何保存任务的寄存器堆数据,当任务需要暂停并切换其他任务时,将寄存器堆的值保存到任务独有栈区,当任务需要恢复运行时,从任务独有的堆栈区恢复CPU寄存器的值。这样就实现了任务“独享”CPU寄存器。
在这里插入图片描述
代码区不会变化,并且可以被多个任务共享。同一个任务代码可以创建多个任务。静态区内的数据可以共享,也可以私有。

在这种设计模式下,通过保存寄存器堆数据值和装载寄存器堆数据实现任务切换。保存寄存器堆数据称为保存现场 ,载入寄存器堆数据称为恢复现场。保存现场和恢复现场称为上下文切换

任务切换源码分析
上文我们了解了任务切换的原理,接下来我们通过分析一下任务切换的代码(参数CM3平台下FREERTOS源码):
在这里插入图片描述
代码分析:
在这里插入图片描述
将寄存器堆的值保存到任务的栈空间,并将任务的栈指针保存到任务的TCB结构中,任务的TCB结构通常为一个全局结构变量,TCB的第一个变量通常用于存放栈指针。pxCurrentTCB为一个全局TCB指针变量。
在这里插入图片描述
将找出最高优先级任务,并将pxCurrentTCB指向最高优先级任务TCB。
在这里插入图片描述
取出最高优先级的栈指针,利用栈指针恢复寄存器堆数据实现任务切换。

任务切换5个步骤:
1、保存现场 ,将寄存器堆的值保存到任务的栈空间。
2、保存栈指针,将栈指针保存到当前任务的TCB结构中。
3、找出最高优先级任务,并修改当前任务对象。
4、读取栈指针,当前任务的TCB结构中读取栈指针。
5、恢复现场,从任务的栈空间恢复寄存器堆的值。

任务切换实现
代码如何实现任务切换,分析代码如下:
在这里插入图片描述
示例中使用“语句”代替实现该功能的代码。

示例代码的意图是在任务完成函数处理后,直接使用语句实现保存现场 ,保存栈指针,找出最高优先级任务,取出栈指针,恢复现场。“企图”使用这种方式实现任务切换,这种方式可行吗?

假设我们的设计目的是task1运行,task1执行完task1_handle函数后将自己设置为等待,将task2设置为就绪,然后切换到task2运行,task2执行完task2_handle函数后将自己设置为等待,将task1设置为就绪,然后切换到task1运行,循环运行。根据这种设计逻辑我们来分析一下。
在这里插入图片描述
虽然这种方式无法实现任务切换 ,但是我们得出如下结论:

1、调用任务切换语句是单一语句。
2、保存现场保存的PC值是调用任务切换语句的下一条语句。
3、任务切换功能需要在另外一处实现。

根据以上结论,可以通过两种方式实现切换功能:函数调用,软中断。
这两种方式的特点是:

1、执行函数调用或者中断函数是单一语句。
2、执行函数调用或者中断函数前,处理器会自动保存下一条用户指令的PC值。
3、切换代码可以在被调用的函数或中断函数中实现
4、函数返回或者中断返回,会载入切换点的下一条语句。

通过函数调用实现切换示例。
在这里插入图片描述
保存点如上图所示,当任务被恢复时,从被保存点开始执行。切换代码在被调用的函数中实现。

通过软中断实现切换示例。
在这里插入图片描述
保存点如上图所示,当任务被恢复时,从被保存点开始执行。切换代码在中断函数中实现。

前文分析的__asm void xPortPendSVHandler( void ) 函数是通过软中断机制实现。通常情况下首选软中断方式,当处理器硬件不支持软中断时才使用函数调用的方式。软中断方式会触发一个中断,硬件会自动入栈保存部分寄存器,上下文切换效率较高。

任务切换等级
任务切换通常分为两个等级:任务级切换中断级切换

任务级切换指的是任务再运行过程中调用了操作系统切换任务接口函数实现任务切换。任务级切换需要实现保存现场 ,保存栈指针,找出最高优先级任务,取出栈指针,恢复现场。

中断级切换指的是任务运行时发生了一个中断,中断函数中调用了一些操作系统接口函数,导致高优先级任务就绪,在中断返回时需要进行任务切换。中断级切换只用实现找出最高优先级任务,取出栈指针,恢复现场。因为在进入中断是已经完成了保存现场 ,保存栈指针的工作。

任务切换点
前文中说明了任务切换原理,现在还有一个问题:任务切换发生在哪里?

假设现在有两个任务:高优先级任务task1和低优先级任务task2 。task1执行时需要等待信号S,等待信号时task1休眠,task2运行并发送信号S,此时task1被唤醒并执行。运行图如下:
在这里插入图片描述
分析:在执行等待信号函数后task1任务休眠,此时发生一次任务切换;在发送信号函数后task1运行,此时又发生一次任务切换。正是因为这种机制使得条件准备就绪后(发送信号)重要的任务可以立即执行(task1被唤醒并执行),实现了实时操作系统的核心价值——实时性。

任务切换不仅仅存在于信号发生和等待,任务切换发生在如下情况:

1、等待信号,发生信号
2、创建任务,删除任务
3、挂起任务,恢复任务
4、调用延时,取消延时
5、中断程序返回
6、任务主动调用调度函数

TCB设计
上文中提到需要把任务的栈指针保存到静态区,对于一个任务有许多信息需要保存,因此我们需要在静态区创建一个任务的信息对象,这个对象为 task control block 简写为 TCB。 我们开始为任务任务定义一个简单的TCB结构:
在这里插入图片描述
定义的TCB中包含了栈指针,优先级。本系列会根据提到的知识点逐步完善任务的TCB结构。TCB结构于寄存器堆,任务栈的关系图如下:
在这里插入图片描述
静态区定义的任务TCB对象中的栈指针指向任务栈区的栈顶,任务栈区保存着寄存器堆的数据,寄存器堆中的PC值指向任务的代码区。

未完待续…
实时操作系统系列将持续更新
创作不易希望朋友们点赞,转发,评论,关注。
您的点赞,转发,评论,关注将是我持续更新的动力
作者:李巍
Github:liyinuoman2017

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式实时操作系统3——任务切换 的相关文章

  • FreeRTOS 源码注释(vTaskDelete)

    void vTaskDelete xTaskHandle pxTaskToDelete tskTCB pxTCB taskENTER CRITICAL if pxTaskToDelete 61 61 pxCurrentTCB pxTaskT
  • 循环冗余校验(CRC)算法入门引导

    写给嵌入式程序员的循环冗余校验 xff08 CRC xff09 算法入门引导 前言 CRC校验 xff08 循环冗余校验 xff09 是数据通讯中最常采用的校验方式 在嵌入式软件开发中 xff0c 经常要用到CRC 算法对各种数据进行校验
  • FreeRTOS 移植要点(2)

    port c port c 中主要实现了几个函数 xff1a pxPortInitialiseStack xPortStartScheduler vPortEndScheduler vPortYield vPortTickInterrupt
  • DLA (扩散限制凝聚)模型的计算机模拟

    几年前写的一个小程序 xff0c 最近找到了 程序写的比较简单 xff0c 也没做什么优化 对正在学习计算物理的同学可能会有点帮助 下面关于DLA 模型的介绍来自百度百科 Diffusion limited Aggregation xff0
  • matlab 读取处理 wav 文件

    最近工作需要 xff0c 要对wav 文件中存储的声音信息进行分析处理 所以花了些时间收集了各种数学软件中处理 wav 文件的方法 Matlab Matlab 是最方便的 甚至于不用写任何代码就能读取 wav 文件 xff08 我用的是 m
  • Savitzky-Golay 滤波器

    Savitzky Golay滤波器 xff08 通常简称为S G滤波器 xff09 最初由Savitzky 和 Golay 于 1964 年提出 xff0c 发表于Analytical Chemistry 杂志 之后被广泛地运用于数据流平滑
  • 关于查看ros中可以安装的功能包

    可以通过以下命令查看软件库中是否包含你所需要的功能包 apt cache search xxxx 其中xxx为你要搜索的关键字
  • 教你如何用原生css和html搭建一个好看的Table表格

    前言 大家在学习 lt table gt 标签的时候 xff0c 可能还没有接触css xff0c 所以你做出来的表格可能是这样的 xff1a 或者是这样的 xff1a 大家有想过自己做一个漂亮的表格吗 xff1f 我知道大家在做项目的时候
  • 如何在 Ubuntu 20.04 启用 SSH

    简介 xff1a Secure Shell SSH 是一个网络协议 xff0c 它主要被用来加密客户端和服务端之间的连接 在客户端和服务端的每一次交互都被加密 本文主要为大家讲解如何在 Ubuntu 20 04 启用 SSH 镜像下载 域名
  • 树莓派镜像SD卡烧录成功磁盘没内容解决方法

    这个情况很可能是删除分区后发生的 xff0c 只需要此电脑 管理 磁盘管理 驱动器路径 添加 确定就可以解决了
  • C++ 类学习总结(五) 继承与多态

    继承 基本概念 xff0e 基类 xff1a 可供其他类继承的类 xff0c 基类的成员也将成为派生类的成员 xff0e 派生类 xff1a 从基类继承而来的类 xff0c 称为派生类 xff0e 虚函数 xff1a 基类中希望其派生类可以
  • 行业术语 英文

    IDE 一般指集成开发的环境 如QT Creator Visual Studio等 Application framework 一般指的是应用程序框架 xff08 包含 XML xff0c GUI组件 xff0c 程序 xff0c 网络框架
  • VSCode C/C++ 格式化配置【最完整准确版本】

    一 下载Clang format 1 在VSCode插件商店下载 C C 43 43 插件 和 Clang format 插件 二 生成 clang format 文件 2 去到 C Users lt 你的用户名 gt vscode ext
  • 【时间规划】C/C++发展之路--读书

    0 xff1a 图书馆的N本C xff0c C 43 43 书 1 xff1a C语言深度解剖 2 xff1a 高质量C 43 43 c编程指南 3 xff1a C 43 43 primer第四版 4 xff1a Windows程序设计 5
  • 【Cocos2d-x】Win7+ vs2012,2010 + Cocos2d-x2.2 配置Cocos2d-X项目-环境

    新安装搭建cocos2d X的跳过这里 xff0c 看下面红色开始 xff1a cocos2d x删除vs2012项目模板 这一步新使用cocos2d x的不需要 如果你切换cocos2d x版本的话 xff0c 要将之前版本的vs模板删除
  • 【Cocos2d-x】Cocos2d-x参考案例源码解析之一:Cocos2dx各个文件说明

    这里本人电脑配置是win7 64位 xff0c cocos2d x2 20 xff0c VS2012 1 xff1a 首先当然是下载cocos2d x啦 我采用的是2 20版本 说明 xff1a 2 14以后的版本和之前的VS模板生成和环境
  • 【Cocos2d-x】Cocos2d-x参考案例源码解析之三:HelloWorld

    允许我讲些与源码无关的事情 xff01 稍后K我 由于cocos2dX3 0快出来了 xff0c 官网上说放弃objective c风格 xff0c 本屌学的是C 43 43 xff0c 所以真是太高兴了 xff0c 所以放慢的源码解析 x
  • 【Cocos2d-x】Cocos2d-x跨Android平台搭建之四:Win7 64位+ eclipse + cocos2dX

    开始研究cocos2dx xff0c mark一下这个的配置步骤 1 下载eclipse 2 下载android sdk xff0c 配置sdk路径 xff0c 添加环境变量 3 安装adt 4 下载android ndk xff0c 配置
  • 【网络通信】Wince 和 PC 通过USB 用Socket 进行通信

    网上资料比较少或者说讲的不太详细 xff0c 现在进行总结下 xff0c 刚毕业没接触过WINce xff0c 不过和MFC差不多 xff0c 现在进入正题 刚开始我的疑惑是Wince是如何和PC进行通信的 xff0c 以及能在USB模式下
  • 如何在 Ubuntu 20.04 上添加交换空间

    简介 xff1a 本文主要为大家讲解如何在 Ubuntu 20 04上添加并激活一个交换空间 镜像下载 域名解析 时间同步请点击 阿里巴巴开源镜像站 交换空间是硬盘上的一个空间 xff0c 当物理 RAM 内存被用尽时 xff0c 被紧急征

随机推荐

  • VScode+Sphinx+ReadTheDocs 从环境搭建到放弃

    概述 此篇博客用来记录在windows10中配置环境的过程 xff0c 注意是Windows下 xff0c 我没有在Linux下面尝试过配置 一下参考了各路教程加上自己亲测 xff0c 应该是没有问题的 被掏空 目录 概述 目录材料清单工具
  • 分布式游戏服务器设计

    分布式游戏服务器设计 服务器解释整体设计图网关服务器网络连接消息处理权限管理业务支持消息路由 登录服务器网络连接用户注册用户登录 中心服务器用户管理消息推送全局功能 游戏服务器数据读取数据落地消息处理 存储服务器工作模式数据一致性 依赖系统
  • Ubuntu 更新apt源及apt常用命令

    Ubuntu 更新apt源及常用命令 替换apt国内源更新软件包信息可更新的包信息更新所有包安装编译必备安装软件包查找软件包名查找包含文件的软件包名列出软件包的所有文件删除软件包 替换apt国内源 执行以下命令 span class tok
  • UUID/GUID介绍、生成规则及生成代码

    UUID GUID介绍 生成规则及生成代码 1 UUID介绍1 1 介绍1 2 UUID优势1 3 UUID劣势 2 UUID版本2 1 版本1 基于时间的UUID2 1 1优点2 1 2 缺点2 1 3 生成规则 2 2 版本2 分布式安
  • Linux开启root远程密码ssh登录

    Linux开启root远程密码ssh登录 登录修改root密码登录root修改sshd配置重启sshd服务 登录 先使用pubkey登录到普通用户 修改root密码 然后执行以下命令更新root密码 span class token fun
  • Windows安装go-python环境--使用golang执行python3

    Windows安装go python环境 目的项目路径安装python3 7 9安装包便携版 安装pkg config新增PC文件安装TMD GCC添加环境变量安装go python测试不兼容接口 目的 在go中使用C API调用CPyth
  • Github自动构建及推送DockerHub

    Github自动构建及推送DockerHub DockerHub Automated BuildsGithub 官方免费方法 DockerHub Automated Builds DockerHub需要付费才能自动绑定Github构建 米多
  • VMware Workstation 与 Device/Credential Guard 不兼容

    VMware Workstation 与 Device Credential Guard 不兼容 问题出现问题的原因解决方案第一步 打开 基于虚拟化的安全设置为 已禁用 第二步 win 43 R 打开运行 xff0c 输入services
  • TortoiseGit拉取远端Gerrit公钥不识别问题

    Gerrit与TortoiseGit公钥不识别问题 现象解决办法 现象 远程repo使用Gerrit服务器本地使用TortoiseGit客户端id rsa pub 已经设置到远端服务器git clone正常拉取TortoiseGit客户端拉
  • Windows Docker Desktop开放API端口2375用于远程调用

    Windows Docker Desktop开放API端口2375用于远程调用 问题解决开启IP Helper服务开启Docker配置开放2375端口 端口映射找到需要暴露的IP执行端口映射命令 Windows防火墙关闭防火墙添加防火墙规则
  • Linksys WRT路由器刷入OpenWrt与原厂固件双固件及切换

    Linksys路由器OpenWrt与原厂固件双固件刷入及切换 双固件机制使用原厂固件刷其他固件使用原厂固件切换启动分区使用OpenWrt刷入Sysupgrade使用OpenWrt刷入Img使用OpenWrt切换分区通用的硬切换分区 xff0
  • 如何在 Ubuntu 20.04 上安装 Apache

    简介 xff1a Apache 是世界上最流行的网站服务器之一 它是开源并且跨平台的 HTTP 服务器 xff0c 它托管了互联网上大量的网站 Apache 提供了很多强大的功能 xff0c 并且可以扩展其他的模块 本文主要为大家介绍如何在
  • 浅谈C++中的多线程(一)

    本篇文章围绕以下几个问题展开 xff1a 何为进程 xff1f 何为线程 xff1f 两者有何区别 xff1f 何为并发 xff1f C 43 43 中如何解决并发问题 xff1f C 43 43 中多线程的语言实现 xff1f 同步互斥原
  • 如何用ASCII码表白

    前提摘要 刚好学到了字符流输入输出那块东西 xff0c 从文本文档里敲入老师课件里的东西 xff0c 控制台 输出了对应的数字编码 xff0c 就萌生了 xff1a 嗯 可以用来表白的小想法 xff0c 就是把一对酷酷的扔 过去 xff0c
  • 走进前端 VScode插件安装 Gitee提交

    一 xff0c 认识前端 什么是前端 前端即网站前台部分 xff0c 运行在PC端 xff0c 移动端等浏览器上展现给用户浏览的网页 前端技术一般分为前端设计和前端开发 xff0c 前端设计理解为网站网页的视觉设计 xff0c 前端开发则是
  • freeRTOS与ucos II区别

    freeRTOS比uCOS II优胜的地方 1 内核ROM和耗费RAM都比uCOS 小 xff0c 特别是RAM 这在单片机里面是稀缺资源 xff0c UCOS至少要5K以上 xff0c 而freeOS用2 3K也可以跑的很好 xff1b
  • 嵌入式软件架构设计

    如何设计一个好的软件架构 xff0c 如何提高软件的扩展性 xff0c 移植性 xff0c 复用性和可读性 xff1f 很多做嵌入式开发的朋友经常会遇到这种情况 xff1a 一个项目软件设计完成了 xff0c 客户提出了一些新的功能需求 这
  • 深入理解C语言小括号用法

    学了这么多年C语言 xff0c 你真的会用小括号吗 xff1f 我们今天来总结一下小括号 xff08 xff09 有哪些用法 xff0c 用法如下表 xff1a 示例 1 聚组 聚组是用来改变运算优先级 xff0c 实例如下 xff1a 例
  • 嵌入式实时操作系统1——初识嵌入式实时操作系统

    嵌入式实时操作系统是什么 嵌入式实时操作系统是一个特殊的程序 xff0c 是一个支持多任务的运行环境 嵌入式实时操作系统最大的特点就是 实时性 xff0c 如果有一个任务需要执行 xff0c 实时操作系统会立即执行该任务 xff0c 不会有
  • 嵌入式实时操作系统3——任务切换

    任务切换原理 假设有一程序 xff0c 程序内有一个无限循环 xff0c 在循环内部有5个表达式 xff0c 代码如下 xff1a 程序在循环中 xff0c 会依次执行表达式1 表达式2 表达式3 表达式4 表达式5 表达式1无限循环 假设