浅谈FreeRTOS任务启动与切换流程

2023-05-16

一个轻量级操作系统最核心的地方就在于任务的执行与切换,像FreeRTOS和ucOSⅢ在任务启动与切换方面都差不多,本文主要从枝干而省去了所有细枝末节让你最快的了解操作系统的任务创建与切换。
以正点原子FreeRTOS移植实验代码为例,该代码主要移植了FreeRTOS操作系统,并创建了4个任务,开始任务、LED闪烁1、LED闪烁2、浮点运算。
1.先从.s启动文件说起
启动文件里面有三个中断是操作系统必要的:
在这里插入图片描述
即SVC_Handler,PendSV_Handler,SysTick_Handler。其中:SVC是用于触发一个PendSV异常来进行一个上下文切换,具体切换过程在PendSV_Handler里完成,SysTick_Handler则是为操作系统提供一个时基,进行一系列操作比如延时时切换任务等。
简单点来说:
SVC_Handler是用于启动第一个任务的中断;
PendSV_Handler是用于每次任务切换中断;
SysTick_Handler是一个定时器,比如一个任务运行3s,这3s就是用这个定时器来计时得到的。
至于为什么这些操作要放在这几个中断内进行,这是因为CM3内核有两种模式:用户和特权,模式不同,权限不同,有些操作需要在特权模式下进行。
具体的代码分析放在后面,现在只了解存在这三个中断。(想了解的可以搜索:CM3的两种模式,两种权限,以及两个指针MSP与PSP,中断与异常)
接下来直接进入到main函数
在这里插入图片描述
在main里面关于操作系统主要存在于三个函数内:delay_init,xTaskCreate,vTaskStartScheduler
其中delay_init中主要开启了SysTick中断:

在这里插入图片描述
然后xTaskCreate是创建函数任务,里面主要操作是为任务申请堆栈空间
在这里插入图片描述
其中分为两种情况:堆栈向上和向下生长两种情况,不做具体讨论。
在为任务申请完空间之后,还有很重要的两个操作:
在这里插入图片描述
填充任务控制块信息和把新创建的任务加入就绪列表。
其中填充任务控制块中比较重要的是:
1获取栈顶地址pxTopOfStack
在这里插入图片描述
protSTACK_GROWTH<0即栈为向下生长,栈顶在高地址,然后需要8字节对齐。
可以看出来pxTopOfStack = 为任务申请的堆栈(数组)首地址+堆栈(数组)大小-1
2填充堆栈区域
在这里插入图片描述
上面的函数即为填充堆栈:
在这里插入图片描述
在这里插入图片描述

至此任务初始化完成。简单来说,任务创建过程就是:

  1. 申请内存
  2. 填充内存
    至于为什么要这么填充内存,其实和取用的时候有关,后面会详细解释。
    接下来就是开始任务调度:
    在这里插入图片描述
    在开启任务调度里面比较重要的是:
    1创建了空闲函数
    2开启任务切换
    在这里插入图片描述
    在这里插入图片描述
    xPortStartScheduler()是开启任务调度,里面除了设置相关内容,最重要的函数如下:
    在这里插入图片描述

即开始第一个任务。
在这里插入图片描述

该函数主要两个作用:

  1. 复位MSP值(MSP存在向量表的起始地址,而向量表起始地址存在SCB_VTO寄存器里(地址:0xE000ED08))
  2. 触发SVC
    SVC的内容如下:
    在这里插入图片描述

该函数主要内容:
8字节对齐
加载pxCurrentTCB(任务控制块,存储每个任务的相关信息)的地址到R3
加载pxCurrentTCB的地址里面的内容到R1
因为pxCurrentTCB的地址里面的内容还是一个地址,所以又加载这个地址里面的内容到R0
R0=pxCurrentTCB首地址内容即栈顶地址,pxCurrentTCB是一个结构体,结构体第一个成员为任务控制块栈顶地址
在这里插入图片描述

所以现在R0=栈顶地址,然后以R0为基址,向高地址++,把地址内的内容依次加载到R4、R5、R6、R7、R8、R9、R10、R11、R14等寄存器
然后把R0此时的地址赋给psp
然后R0=0
basepri=R0
然后用BX指令,把以psp为基址,向高地址++,里面的的内容依次加载到R0、R1、R2、R3、R12、R14、R15、xPSR寄存器内
从这里就可以理解了初始化任务堆栈时,为什么要按顺序填充内存,因为取的时候是按顺序取的。
然后任务的切换是在滴答定时器中断内进行的:
在这里插入图片描述

可以看到里面就一个函数:
在这里插入图片描述

函数里面最重要的是通过设置相应寄存器触发了PendSV中断。
PendSV里面的内容如下:
在这里插入图片描述

主要内容:

  • 把当前任务运行现场保存在当前任务的任务堆栈内
  • 把下个要运行的任务的任务堆栈里面的内容加载到寄存器内
    (s16~s31是开启专门运算浮点的模块时,需要用到的寄存器)。

其实上面两条,1和任务刚初始化时做的一样,只不过任务初始化时是初始化为0,而现在是把当前寄存器内值存起来,保存的位置都一样。2和启动第一个任务一样,把任务堆栈内的内容一一对应加载到对应寄存器内。
至此,操作系统最基本的任务流程就完成了。
总结一下
一. 开启系统滴答定时器
二. 为任务分配运行空间,把任务启动时每个寄存器里面的值按规定好的顺序存在任务分配的运行空间里
三. 触发SVC,开始第一个任务,即把第一个任务运行空间里面的存的寄存器的值按顺序加载到寄存器里
四. 系统滴答定时器中断触发,把现在寄存器内的所有值存进当前任务的运行空间里,加载下个要运行的任务运行空间里面的值到寄存器里。
在这里插入图片描述

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

浅谈FreeRTOS任务启动与切换流程 的相关文章

  • 心跳跟随的心形灯(STM32(HAL)+WS2812+MAX30102)

    文章目录 前言 介绍 系统框架 原项目地址 本项目开发开源地址 硬件PCB 软件功能 详细内容 硬件外壳制作 WS2812级联及控制 MAX30102血氧传感器 0 96OLED FreeRTOS 效果视频 总结 前言 在好几年前 我好像就
  • FreeRTOS系列

    1 多任务系统 1 1 前后台系统 单片机裸机开发时 一般都是在main函数里面用while 1 做一个大循环来完成所有的处理 循环中调用相应的函数完成所需的处理 有时也需要在中断中完成一些处理 相对于多任务系统而言 这就是单人单任务系统也
  • 详解FreeRTOS中的软件定时器

    软件定时器用于让某个任务定时执行 或者周期性执行 比如设定某个时间后执行某个函数 或者每隔一段时间执行某个函数 由软件定时器执行的函数称为软件定时器的回调函数 参考资料 Mastering the FreeRTOS Real Time Ke
  • 基于HAL库的FREERTOS----------二.任务API函数

    任务API函数览概 CUBEMX对 做了API的封装 很多 的函数没有封装到位 可以用原函数调用 任务API函数分别介绍 1 uxTaskPriorityGet 此函数用来获取指定任务的优先级 要使用此函数的话宏 INCLUDE uxTas
  • FreeRTOS快速上手

    FreeRTOS使用 一 源码下载和移植文件提取 1 1 源码下载 在网站https sourceforge net projects freertos 可以找到freertos最新的源码 1 2 移植文件提取 根据第一步 我们会得到一个f
  • FreeRTOS简述和移植文档

    FreeRTOS简述和移植文档 文章目录 FreeRTOS简述和移植文档 1 前言 2 FreeRTOS简述 1 概述 2 实现 3 主要特色 4 支持平台 3 移植FreeRTOS 4 最后 1 前言 目前由于IOT的飞速发展 针对单片机
  • FreeRTOS学习笔记(3、信号量、互斥量的使用)

    FreeRTOS学习笔记 3 信号量 互斥量的使用 前言 往期学习笔记链接 学习工程 信号量 semaphore 两种信号量的对比 信号量的使用 1 创建信号量 2 give 3 take 4 删除信号量 使用计数型信号量实现同步功能 使用
  • Freertos中vTaskDelay()是怎么用的

    1 常见的使用场景 void vLED Task void pvParameters while 1 Heartbeat LED vTaskDelay 1000 portTICK RATE MS 说明 上面这段代码的意思是 led翻转后经过
  • 【FreeRTOS】队列的使用

    作者主页 凉开水白菜 作者简介 共同学习 互相监督 热于分享 多加讨论 一起进步 专栏资料 https pan baidu com s 1nc1rfyLiMyw6ZhxiZ1Cumg pwd free 点赞 收藏 再看 养成习惯 订阅的粉丝
  • FreeRTOS临界区

    FreeRTOS临界区是指那些必须完整运行 不能被打断的代码段 比如有的外设的初始化需要严格的时序 初始化过程中不能被打断 FreeRTOS 在进入临界区代码的时候需要关闭中断 当处理完临界区代码以后再打开中断 FreeRTOS 系统本身就
  • freeRTOS使用uxTaskGetStackHighWaterMark函数查看任务堆栈空间的使用情况

    摘要 每个任务都有自己的堆栈 堆栈的总大小在创建任务的时候就确定了 此函数用于检查任务从创建好到现在的历史剩余最小值 这个值越小说明任务堆栈溢出的可能性就越大 FreeRTOS 把这个历史剩余最小值叫做 高水位线 此函数相对来说会多耗费一点
  • 基于HAL库的FREERTOS-----------三.队列

    一 队列简介 在实际的应用中 常常会遇到一个任务或者中断服务需要和另外一个任务进行 沟通交流 这个 沟通交流 的过程其实就是消息传递的过程 在没有操作系统的时候两个应用程序进行消息传递一般使用全局变量的方式 但是如果在使用操作系统的应用中用
  • FreeRTOS基础五:软件定时器

    软件定时器简介 软件定时器的作用 在指定的时间到来时执行指定的函数 或者以某个频率周期性地执行某个函数 被执行的函数叫做软件定时器回调函数 软件定时器由FreeRTOS内核实现 不需要硬件支持 软件定时器只有在软件定时器回调函数被调用时才需
  • FreeRTOS学习(三)开关中断

    声明及感谢 跟随正点原子资料学习 在此作为学习的记录和总结 环境 keil stm32f103 背景知识 Cotex M3的NVIC最多支持240个IRQ 中断请求 1个不可屏蔽 NMI 1个Systick 滴答定时器 Cortex M处理
  • 基于STM32的FreeRTOS学习之中断测试实验(五)

    记录一下 方便以后翻阅 本章内容是接着上一章节进行的实际演练 1 实验目的 FreeRTOS可以屏蔽优先级低于configMAX SYSCALL INTERRUPT PRIORITY的中断 不会屏蔽高于其的中断 本次实验就是验证这个说法 本
  • RT-Thread记录(五、RT-Thread 临界区保护与FreeRTOS的比较)

    本文聊聊临界区 以及RT Thread对临界区的处理 通过源码分析一下 RT Thread 对临界区保护的实现以及与 FreeRTOS 处理的不同 目录 前言 一 临界区 1 1 什么是临界区 1 2 RTOS中的临界区 二 RT Thre
  • FreeRTOS轻量级同步--任务通知

    1 简介 在FreeRTOS的配置参数中的configUSE TASK NOTIFICATIONS宏打开 一般RTOS会默认打开 如图1所示 图1 notify宏开关 RTOS在创建任务时 会创建一个32位的通知值ulNotifiedVal
  • FreeRTOS笔记(二)

    FreeRTOS笔记 二 静态任务 文章目录 FreeRTOS笔记 二 静态任务 一 任务定义 二 任务创建 2 1 定义任务栈 2 2 定义任务函数 2 3 定义任务控制块 2 4 实现任务创建函数 三 实现就绪列表 3 1 定义就绪列表
  • 再论FreeRTOS中的configTOTAL_HEAP_SIZE

    关于任务栈和系统栈的基础知识 可以参考之前的随笔 FreeRTOS 任务栈大小确定及其溢出检测 这里再次说明 define configTOTAL HEAP SIZE size t 17 1024 这个宏 官方文档解释 configTOTA
  • 使用 GCC 编译器的 ARM 内核的堆栈回溯(当存在 MSP 到 PSP 切换时)

    核心 ARM Cortex M4 编译器 GCC 5 3 0 ARM EABI 操作系统 免费 RTOS 我正在使用 gcc 库函数 Unwind Reason Code Unwind Backtrace Unwind Trace Fn v

随机推荐

  • 切换JDK版本运行java命令时报Error: could not open xxx解决方法

    安装了jdk8和jdk11两个版本 xff0c 并配置好环境变量后 切换jdk8没有问题 xff0c 切换jdk11时输入java version检查版本出现了如下图片问题 xff1b 解决方案1 xff1a 将环境变量path中 JAVA
  • 阿里云服务器ubuntu18.04安装可视化界面

    这里写目录标题 一 远程连接ubuntu二 安装可视化界面三 安装过程中的问题 一 远程连接ubuntu 输入root密码即可 xff08 这个为实例密码 xff09 二 安装可视化界面 依次输入以下shell命令 apt span cla
  • 奇偶检验等N、O、E、M、S 五种串口检验位类型

    一 检验位 在串行通讯所发送数据的最后一位 xff0c 用来粗略的检验数据在传输过程中是否有出错 二 检验位的五种类型 1 N xff08 None 没有 xff09 无校验 不加校验位 xff0c 可以少传输一位数据 2 O xff08
  • Onvif登录海康、大华摄像机(IPC)提示权鉴失败的问题解决

    最近用我们的Onvif设备发现客户端测试 xff0c 发现连接某些摄像机Onvif获取不到设备信息 xff0c 提示401权鉴失败 确认用户名和密码都没错的情况下 xff0c 都还是失败 xff0c 软件提示信息截图如下 xff1a 我们测
  • 反解析Android APK

    重命名APK为zip 并解压到当前文件中 下载dex解析工具dex2jar link https github com pxb1988 dex2jar releases tag v2 2 SNAPSHOT 2021 10 31 解析文件命令
  • 大数加法越界处理

    大数越界处理 当数据很大时 xff0c 求中点的方法 i 43 j 2的结果有可能会超出 int 类型的取值范围 在此情况下 xff0c 我们需要换一种计算中点的写法 i 43 j 有可能超出 int 的取值范围 int m 61 i 43
  • idea使用断言

    测试程序 public class TestAssert public static void main String args String s1 61 null assert s1 61 null 默认assert不起作用 需开启 ve
  • 2018年面试总结 -- 多线程很重要,多总结很重要

    2018年面试总结 先后面试了Android Linux C C 43 43 QT 得到的结论有以一下几条 xff1a 1 多线程作为一个高级话题太重要了 几乎每种开发环境下都会问到 xff0c 无论是Android还是QT xff1b 2
  • 平常使用的小问题【Windows11开启不了热点,开启热点后连不上去】

    故障现象 xff1a xff08 1 xff09 连接设备一直显示obtaining ip address xff08 2 xff09 电脑没有显示连接的设备 解决措施 xff1a xff08 1 xff09 先转到设置 xff08 2 x
  • IOException: No such file or directory 问题解决

    文章目录 问题描述 xff1a 注册权限动态申请权限总结 xff1a 问题描述 xff1a Android开发 xff0c 在访问文件夹创建文件的时候 xff0c 报错IOException No such file or director
  • 2020(春)工程伦理MOOC期末考试答案

    单选题 多选题 判断题
  • Git中Fork使用

    GitLab或者GitHub中的Fork可以理解为一个物理副本 xff0c 用来管理代码的一种手段 在参与开源项目代码贡献时 xff0c 通常不会直接获得源代码仓库的Developer权限 这点和一般公司开发不太一样 xff0c 公司一般都
  • 在OK6410上运行QT程序找不到libQtGui.so.4的解决

    想在OK6410上运行自己经过交叉编译的QT程序 xff0c OK6410上烧写的是光盘所带的Linux系统 xff0c 运行程序时出现以下现象 xff1a qt server error while loading shared libr
  • Docker的安装

    这篇文章原文是我2016年10月份写的 xff0c 当时在研究docker xff0c 上周六不经意翻了出来 xff0c 由于3月换工作 xff0c 新环境比较忙 xff0c 没时间写些东西 xff0c 所以先把之前写的东西放一下 xff0
  • CRAZEPONY飞控学习(一)

    在不久前曾研究过最近最为流行的开源飞控Pixhawk的源代码 xff0c 但是由于在这之前没有接触过操作系统这个概念 xff0c 在不知道代码执行流程的情况下看了几个星期的时间 xff0c 脑子里还是一团乱 xff0c 所以决定还是从裸机开
  • PHP常用的设计模式

    php常用的设计模式 xff1a 1 单例模式 xff08 构造方法私有化 xff0c 对外提供实例化对象的静态调用方法 xff09 class Site span class token punctuation span public s
  • 003.多线程-主线程、守护线程、用户线程的区别

    对于线程的分类 xff0c 我们可以简单划分为 xff1a 主线程 xff08 每个进程只有一个主线程 xff09 子线程 主线程 xff1a main方法 子线程 xff1a 非主线程皆是子线程 子线程中可以简单划分为 xff1a 守护线
  • Ubuntu中在当前目录下打开终端

    在Ubuntu中 xff0c 打开终端可以通过Ctrl 43 Alt 43 T来打开 xff0c 但其打开的是 下的 xff0c 如果进入指定的目录 xff0c 便需要通过cd命令来进行切换 xff0c 故本文提供一个可以通过鼠标右键来在当
  • C语言经典面试题100道(校对详解版)

    题目非本人整理 xff0c 转载于https blog csdn net qq 42613510 article details 81225935 做了校对与详解 xff0c 方便大家参考 最后编程答案自己做的 xff0c 还没写完 xff
  • 浅谈FreeRTOS任务启动与切换流程

    一个轻量级操作系统最核心的地方就在于任务的执行与切换 xff0c 像FreeRTOS和ucOS 在任务启动与切换方面都差不多 xff0c 本文主要从枝干而省去了所有细枝末节让你最快的了解操作系统的任务创建与切换 以正点原子FreeRTOS移