【学习FreeRTOS】第9章——FreeRTOS任务调度

1.开启任务调度器

vTaskStartScheduler()

作用:用于启动任务调度器,任务调度器启动后, FreeRTOS 便会开始进行任务调度【动态创建任务为例】

  • 创建空闲任务
  • 如果使能软件定时器,则创建定时器任务
  • 关闭中断,防止调度器开启之前或过程中,受中断干扰,会在运行第一个任务时打开中断
  • 初始化全局变量,并将任务调度器的运行标志设置为已运行
  • 初始化任务运行时间统计功能的时基定时器 【可选】
  • 调用函数 xPortStartScheduler()

xPortStartScheduler()

作用:该函数用于完成启动任务调度器中与硬件架构相关的配置部分,以及启动第一个任务

  • 检测用户在 FreeRTOSConfig.h 文件中对中断的相关配置是否有误
  • 配置 PendSV 和 SysTick 的中断优先级为最低优先级
  • 调用函数 vPortSetupTimerInterrupt()配置 SysTick(清空计数值、配置节拍频率、重装载值、启动计数与中断)
  • 初始化临界区嵌套计数器为 0
  • 调用函数 prvEnableVFP()使能 FPU
  • 将FPCCR寄存器的[31:30]置l,这样在进出异常时,FPU的相关寄存器就会自动地保存和恢复(M4/M7)
  • 调用函数prvStartFirstTask() 启动第一个任务

2.启动第一个任务

prvStartFirstTask()

__asm void prvStartFirstTask( void ) { /* 8字节对齐 */ PRESERVE8 ldr r0, =0xE000ED08 	/* 0xE000ED08为VTOR地址 */ ldr r0, [ r0 ] 					/* 获取VTOR的值 */ ldr r0, [ r0 ]					/* 获取MSP的初始值 */ /* 初始化MSP */ msr msp, r0/* 使能全局中断 */ cpsie i cpsie f dsb isb /* 调用SVC启动第一个任务 */ svc 0 nop nop 
}

执行过程为:

  • 获取MSP的初始值(栈顶地址)
  • 将MSP重新赋值为栈底指针(让MSP回到原点,启动任务一去不复返)
  • 使能全局中断
  • 使用SVC指令,传入系统调用信号,出发SVC中断vPortSVCHandler ()
  • 关于MSP指针
    程序在运行过程中需要一定的栈空间来保存局部变量等一些信息。当有信息保存到栈中时,MCU 会自动更新 SP 指针,ARM Cortex-M 内核提供了两个栈空间
    主堆栈指针(MSP)它由 OS 内核、异常服务例程以及所有需要特权访问的应用程序代码来使用。
    进程堆栈指针(PSP)用于常规的应用程序代码(不处于异常服务例程中时)。
    在裸机中,程序全部使用MSP,在FreeRTOS中,中断使用MSP(主堆栈),中断以外使用PSP(进程堆栈)
  • 关于0xE000ED08
    0xE000ED08是VTOR(中断向量表)的地址,向量表的第一个是 MSP 指针,取 MSP 的初始值的思路是先根据向量表的位置寄存器 VTOR (0xE000ED08) 来获取向量表存储的地址;在根据向量表存储的地址,来访问第一个元素,也就是初始的 MSP。

vPortSVCHandler ()

__asm void vPortSVCHandler( void ) 
{ /* 8字节对齐 */ PRESERVE8 /* 获取任务栈地址 */ ldr r3, = pxCurrentTCB 		/* r3指向优先级最高的就绪态任务的任务控制块 */ ldr r1, [ r3 ] 				/* r1为任务控制块地址 */ ldr r0, [ r1 ] 				/* r0为任务控制块的第一个元素(栈顶) */ /* 模拟出栈,并设置PSP */ ldmia r0 !, { r4 - r11 } 	/* 任务栈弹出到CPU寄存器 */ msr psp, r0 				/* 设置PSP为任务栈指针 */ isb /* 使能所有中断 */ mov r0, # 0 msr basepri, /* 使用PSP指针,并跳转到任务函数 */ orr r14, # 0xd bx r14 }

运行过程为:

  • 获取优先级最高的就绪任务的TCB,并取其栈顶元素pxTopOfStack
  • 模拟出栈,将寄存器值出栈至CPU寄存器,并设置PSP指针
  • 开启中断
  • 线与0xd,将r14设置为线程模式并使用PSP
  • 跳转到任务的任务函数中运行,CPU自动出栈R0-xPSR等寄存器(M4:若EXC_RETURN使用FPU,则恢复浮点单元)

M4的vPortSVCHandler () ,除了手动出栈r4-r11外,还有r14,这是因为M4等系列支持FPU,需要该变量进行判别
M4的vPortSVCHandler () ,不需要线与0xd,因为在初始化时,已经对EXC_RETURN进行赋值了,不需要再线与
一般情况下,使用动态创建任务,第一个启动的任务是软件定时器任务
注意:SVC中断只在启动第一次任务时会调用一次,以后均不调用

在这里插入图片描述
在这里插入图片描述

开启任务调度器及启动第一个任务总结

在这里插入图片描述

3.任务切换

任务切换的本质:就是CPU寄存器的切换(又称上下文切换),在PendSV中断服务函数中完成 主要分为两步:

  • 需暂停任务A的执行,并将此时任务A的寄存器保存到任务堆栈,这个过程叫做保存现场
  • 将任务B的各个寄存器值(被存于任务堆栈中)恢复到CPU寄存器中,这个过程叫做恢复现场

触发PendSV中断方式

  • 滴答定时器中断调用
  • 执行FreeRTOS提供的相关API函数:portYIELD()
  • 本质:通过向中断控制和状态寄存器 ICSR 的bit28 写入 1 挂起 PendSV 来启动 PendSV 中断

在这里插入图片描述
在这里插入图片描述

PendSV中断服务函数xPortPendSVHandler()

  • 进入中断,使用PSP自动压栈
  • 当前的psp是正在运行的任务的栈指针,读取当前PSP进程指针,存入r0(M4还要考虑FPU压栈)
  • 手动压栈,并将最终结果封存至pxTopOfStack,方便下次恢复
  • 屏蔽中断
  • 调用vTaskSeitchContext(),获取当前最高优先级任务的任务控制块
  • 使能中断
  • 从最高优先级的TCB中获取pxTopOfStack,并手动出栈
  • 更新切换后的任务的的栈指针给PSP
  • PSP负责自动出栈
  • bx r14 执行新任务函数

查找最优先级任务vTaskSwitchContext( )

通过这个函数完成:taskSELECT_HIGHEST_PRIORITY_TASK( )

  • 使用硬件方式(本文使用)
  • 使用软件方式
 #define taskSELECT_HIGHEST_PRIORITY_TASK()
{UBaseType_t uxTopPriority;portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0);listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );
}

前导置零指令
所谓的前导置零指令,大家可以简单理解为计算一个 32位数,头部 0 的个数。通过前导置零指令获得最高优先级

#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities )      uxTopPriority = ( 31UL - ( uint32_t ) __clz( ( uxReadyPriorities ) ) )

在这里插入图片描述

获取最高优先级任务的任务控制块
通过该函数获取当前最高优先级任务的任务控制块

#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList )
{List_t * const pxConstList = ( pxList );( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ){(pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext;}( pxTCB ) = ( pxConstList )->pxIndex->pvOwner;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/43577.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Microsoft ISA服务器配置及日志分析

Microsoft ISA 分析器工具,可分析 Microsoft ISA 服务器(或 Forefront 威胁管理网关服务器)的日志并生成安全和流量报告。支持来自 Microsoft ISA 服务器组件的以下日志: 数据包过滤器ISA 服务器防火墙服务ISA 服务器网络代理服务…

透过源码理解Flutter中widget、state和element的关系

1、framework源码组成 Flutter中widget、state、element的源码位于framework.dart中,整个文件6693行(版本Flutter 3.12.0-14.0.pre.28)。整个代码可划分为若干部分,主要包括key、widget、state、element四部分。 1.1 key 关于key的代码65行到272行&am…

GuLi商城-前端基础Vue-生命周期和钩子函数

下图展示了实例的生命周期。你不需要立马弄明白所有的东西,不过随着你的不断学习和使用,它 的参考价值会越来越高。 VUE 的生命周期指的是组件在创建、运行和销毁过程中所经历的一系列事件,通过这些事件可以 让开发者在不同阶段进行相应的…

vue3 + antv/x6 实现拖拽侧边栏节点到画布

前篇:vue3ts使用antv/x6 自定义节点 前篇:vue3antv x6自定义节点样式 1、创建侧边栏 用antd的menu来做侧边栏 npm i --save ant-design-vue4.x//入口文件main.js内 import Antd from ant-design-vue; import App from ./App; import ant-design-vue/…

安卓的代码加固和其他安全问题

文章目录 安卓加固apk文件结构dex加固过程 其它安全问题 安卓加固 从App的加固技术来看:主流分为dex加密和so加密,目前来看保护dex文件更为重要,因为dex反编译后的java代码可读性更强。 android-ndk: Native Development Kit 官网解释:这套工具使您能在 Android 应…

Kvm配置ovs网桥

环境:部署在kvm虚拟环境上(让虚拟机和宿主机都可以直接从路由器获取到独立ip) 1、安装ovs软件安装包并启动服务(一般采用源码安装,此处用yum安装) yum install openvswitch-2.9.0-3.el7.x86_64.rpm syste…

Git常见操作

一、全局配置命令 配置级别: –local(默认,高级优先):只影响本地仓库 –global(中优先级):只影响所有当前用户的git仓库 –system(低优先级):影响到全系统的git仓库 1…

剑指 Offer 40. 最小的k个数(C+实现)

剑指 Offer 40. 最小的k个数https://leetcode.cn/problems/zui-xiao-de-kge-shu-lcof/ 法1&#xff1a;二叉堆 通过最小堆&#xff0c;直接筛选出最小的k个数 vector<int> getLeastNumbers(vector<int>& arr, int k) {priority_queue<int, vector<int>…

YOLOv8改进后效果

数据集 自建铁路障碍数据集-包含路障&#xff0c;人等少数标签。其中百分之八十作为训练集&#xff0c;百分之二十作为测试集 第一次部署 版本&#xff1a;YOLOv5 训练50epoch后精度可达0.94 mAP可达0.95.此时未包含任何改进操作 第二次部署 版本&#xff1a;YOLOv8改进版本 首…

WebRTC | ICE详解

目录 一、Candidate种类与优先级 二、ICE策略 1. iceServers 2. iceTransportPolicy 三、P2P连接 1.Nat类型 &#xff08;1&#xff09;完全锥型NAT &#xff08;2&#xff09;IP限制锥型NAT &#xff08;3&#xff09;端口限制锥型NAT &#xff08;4&#xff09;对称…

iPhone 15受益:骁龙8 Gen 3可能缺席部分安卓旗舰机

明年一批领先的安卓手机的性能可能与今年的机型非常相似。硅成本的上涨可能是原因。 你可以想象&#xff0c;2024年许多最好的手机都会在Snapdragon 8 Gen 3上运行&#xff0c;这是高通公司针对移动设备的顶级芯片系统的更新&#xff0c;尚未宣布。然而&#xff0c;来自中国的…

C#生产流程控制(串行,并行混合执行)

开源框架CsGo https://gitee.com/hamasm/CsGo?_fromgitee_search 文档资料&#xff1a; https://blog.csdn.net/aa2528877987/article/details/132139337 实现效果 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37…

Windows11 Docker Desktop 启动 -wsl kernel version too low

系统环境&#xff1a;windows11 1&#xff1a;docker下载 Docker: Accelerated Container Application Development 下载后双击安装即可 安装后启动Docker提示&#xff1a;Docker Desktop -wsl kernel version too low 处理起来也是非常方便 1:管理员身份启动&#xff1a;…

C#程序随系统启动例子 - 开源研究系列文章

今天讲讲C#中应用程序随系统启动的例子。 我们知道&#xff0c;应用程序随系统启动&#xff0c;都是直接在操作系统注册表中写入程序的启动参数&#xff0c;这样操作系统在启动的时候就根据启动参数来启动应用程序&#xff0c;而我们要做的就是将程序启动参数写入注册表即可。此…

【3Ds Max】车削命令的简单使用(以制作花瓶为例)

简介 在3ds Max中&#xff0c;"车削"&#xff08;Lathe&#xff09;是一种建模命令&#xff0c;用于创建围绕轴线旋转的几何形状。通过车削命令&#xff0c;您可以将一个闭合的平面或曲线几何形状旋转&#xff0c;从而生成一个立体对象。这种方法常用于创建圆柱体、…

大数据Flink学习圣经:一本书实现大数据Flink自由

学习目标&#xff1a;三栖合一架构师 本文是《大数据Flink学习圣经》 V1版本&#xff0c;是 《尼恩 大数据 面试宝典》姊妹篇。 这里特别说明一下&#xff1a;《尼恩 大数据 面试宝典》5个专题 PDF 自首次发布以来&#xff0c; 已经汇集了 好几百题&#xff0c;大量的大厂面试…

【制作npm包4】api-extractor 学习

制作npm包目录 本文是系列文章&#xff0c; 作者一个橙子pro&#xff0c;本系列文章大纲如下。转载或者商业修改必须注明文章出处 一、申请npm账号、个人包和组织包区别 二、了解 package.json 相关配置 三、 了解 tsconfig.json 相关配置 四、 api-extractor 学习 五、npm包…

Dockerfile自定义镜像

文章目录 Dockerfile自定义镜像镜像结构Dockerfile语法构建java项目 小结 Dockerfile自定义镜像 常见的镜像在DockerHub就能找到&#xff0c;但是我们自己写的项目就必须自己构建镜像了。 而要自定义镜像&#xff0c;就必须先了解镜像的结构才行。 镜像结构 镜像是将应用程序及…

服务器数据库中了360后缀勒索病毒怎么办?360后缀勒索病毒的加密形式

随着信息技术的发展&#xff0c;企业的计算机服务器数据库变得越来越重要。然而&#xff0c;在数字时代&#xff0c;网络上的威胁也日益增多。近期&#xff0c;我们收到很多企业的求助&#xff0c;企业的计算机服务器遭到了360后缀勒索病毒的攻击&#xff0c;导致服务器内的所有…

《TCP IP网络编程》第二十四章

第 24 章 制作 HTTP 服务器端 24.1 HTTP 概要 本章将编写 HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;服务器端&#xff0c;即 Web 服务器端。 理解 Web 服务器端&#xff1a; web服务器端就是要基于 HTTP 协议&#xff0c;将网页对…