FreeRTOS启动第一个任务和任务的切换实现过程

2023-05-16

FreeRTOS启动第一个任务和任务的切换实现过程

此篇文章主要参考了野火的《FreeRTOS内核实现与应用开发指南》,和其他博主的一些资料并加入了一些个人理解,作为学习笔记,在此感谢火哥和其他博主;

第一个任务的启动

vPortSVCHandler函数开始真正启动第一个任务;
上代码:

__asm void vPortSVCHandler( void )
{
	extern pxCurrentTCB; 	(1)
	PRESERVE8
	ldr r3, =pxCurrentTCB   (2)
	ldr r1, [r3] 			(3)
	ldr r0, [r1]            (4)
	ldmia r0!, {r4-r11}     (5)
	msr psp, r0             (6)
	isb
	mov r0, #0              (7)
	msr basepri, r0         (8)
	orr r14, #0xd           (9)
	bx r14                  (10)
}

(1) 是声明外部变量pxCurrentTCB,pxCurrentTCB是一个全局变量指针,用来指向当前正在运行或者即将运行任务的任务控制块。
(2) 加载pxCurrentTCB任务控制块的地址到R3中;
(3) 加载pxCurrentTCB到R1
(4) 加载pxCurrentTCB指向的任务控制块到R0中,因为任务控制块中的第一个成员变量就是任务的栈顶指针: pxTopOfStack,所以,R0就等于下图中的pxTopOfStack。
在这里插入图片描述:-:
图1任务栈初始化完成后的栈空间分布图
(5) 以r0为基地址(指针先加后操作)将栈中的8个字的数据加载到CPU中的R4-R11中。这时候的R0中的地址见图2;
(6) 将操作5后新的栈顶指针R0更新到PSP中(注意:在执行异常的时候,SP以MSP为栈指针,在执行任务时SP以PSP为栈指针);
(7) 执行7之前清流水线,确保操作6指令执行完毕。清除R0;
(8) 设置BASEPR寄存器为0 即打开所有中断;
(9) (10)两个操作具体解释如下
当r14为0xFFFFFFFX,执行是中断返回指令,
cortext-m3的做法,X的bit0为1表示返回thumb状态,bit1和bit2分别表示返回后sp用msp还是psp、以及返回到特权模式还是用户模式;
异常返回,这个时候栈中的剩下内容将会自动加载到CPU寄存器:xPSR,PC(任务入口地址),R14,R12,R3,R2,R1,R0(任务的形参)同时PSP的值也将更新,即指向任务栈的栈顶 。

0x0D 表示返回后为thumb状态,且指定SP出栈指针使用PSP作为出栈指针,这里的栈指针指向的准备运行的栈,所有在执行BX LR后,在恢复现场时会以当前的PSP为基地址,把栈中的剩下内容将会自动加载到CPU寄存器: xPSR,PC(任务入口地址),R14,R12,R3,R2,R1,R0(任务的形参)中,又因为跳转是BX 无链接,所以跳转后的R15 PC会被从新的PC从堆栈中恢复到R15(PC)寄存器中,所以程序会从该新任务入口函数开始执行。

(注意:)发生异常跳转到异常处理服务前,自动执行的现场保护会保留返回模式。

在这里插入图片描述
图2第一个任务启动后PSP的指向位置

任务的切换

在FreeROTS任务的切换实际由xPortPendSVHandler函数完成,主要完成上下文切换即保存上文,切换下文两个主要目的操作;
切换前我们需要了解上文需要保存什么,下文切换的又是什么;
上文中保存的主要内容是:
(1).寄存器中的R4-R11数据(其余的进入异常前CPU自动保存);
(2).当前任务的栈顶指针;
(3).全局TCB地址;
下文切换需要切换的内容主要是:
(1).最新任务的TCB;
(2).最新任务中栈中的r4-r11数据到CPU R4-R11;
(3)新任务栈顶存入PSP,用来出栈根据PSP调用新任务;
主要流程如下图所示:
在这里插入图片描述
上代码:

__asm void xPortPendSVHandler( void ) 
{
	extern pxCurrentTCB;                          (1) 
	extern vTaskSwitchContext;                 	  (2) 
	PRESERVE8                                     (3)  
	mrs r0, psp                                   (4) 
	isb 
	
	ldr r3, =pxCurrentTCB                         (5) 
	ldr r2, [r3]                                  (6) 
	stmdb r0!, {r4-r11}                           (7) 
	str r0, [r2]                                  (8) 
	stmdb sp!, {r3, r14}                          (9) 
	mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY    (10) 
	msr basepri, r0                                  (11) 
	dsb 
	isb 
	bl vTaskSwitchContext                            (12) 
	mov r0, #0                                       (13) 
	msr basepri, r0                                   
	ldmia sp!, {r3, r14}                             (14) 
	ldr r1, [r3]                                     (15) 
	ldr r0, [r1]                                     (16) 
	ldmia r0!, {r4-r11}                              (17) 
	msr psp, r0                                      (18) 
	isb 
	bx r14                                           (19) 
	nop 
} 

说明;

上文的保存

注意:在进入该函数前,系统(CPU)会自动的将上一个任务的运行的环境即: xPSR,PC(任务入口地址),R14,R12,R3,R2,R1,R0(任务的形参)这些寄存器的值会存储到任务的栈中,是自动完成的。
(4) 进入到xPortPendSVHandler函数中第一步要做的是将剩下的 R4~R11手动保存入栈,同时PSP 会自动更新(在更新之前 PSP 指向任务栈的栈顶)。
这时当前PSP指向见图3
在这里插入图片描述
图3上文环境自动保存到任务栈后PSP的指向
(5)将pxCurrentTCB的地址加载到R3中;
(6)将R3中指向的内容加载到R2中R2 =pxCurrentTCB ;
(7)先将R0指向地址递减在以新R0为及地址将CPU中的R4-R11手动入栈,这时的R0的具体指向见图4;

图4上一个任务的运行环境手动入栈后,R0的指向 图4上一个任务的运行环境手动入栈后,R0的指向
(8)将R0的值存储到R2指向的内容,因为R2等于pxCurrentTCB,而pxCurrentTCB的第一个成员为pxTopOfStack,所以就是将R0存储到的上一个任务的pxTopOfStack任务栈顶指针中。完成了上文的保存;

切换下文

(9)把R14(LR)寄存器入栈保存,是因为调用vTaskSwitchContext函数返回时,CPU会把返回地址自动保存到LR寄存器中,R14(LR)寄存器的值被覆盖故需要进入入栈保护处理。把R3一并入栈保存是因为下面要调用vTaskSwitchContext函数来切换任务控制块,可能会用到R3,把R3的值覆盖,而我们还需要原R3来找到当操作新的pxCurrentTCB,所以保险起见一并把R3也保存了起来;
(10)把configMAX_SYSCALL_INTERRUPT_PRIORITY值存到R0中,用来屏蔽BASEPRI的值;
(11)关闭部分高优先级中断;
(12)调用vTaskSwitchContext函数用来更新下一个需要运行任务的任务控制块pxCurrentTCB;
(13)退出临界段,开中断,直接往 BASEPRI写 0;
(14)从堆栈中恢复R3,R14的值,此时SP使用的时MSP;
(15)将将要运行任务的任务控制块pxCurrentTCB的地址指向的内容即任务控制块本身加载到R1中;
(16)加载R1中指向的内容即将要运行的任务的栈顶指针到R0中;
(17)把R0为基地址,将下一个将要运行任务的栈加载到R4-R11寄存器中,此时的R0的指向已经变化;
(18)将R0的值更新到PSP中,用来退出异常后以PSP为及地址,将新任务栈中剩下的内容加载到CPU寄存器中,然后清流水线,保证此操作完成后在执行下一条指令。
(19) 异常发生时,R14中保存异常返回标志,包括返回后进入线程模式还是处理器模式、使用PSP堆栈指针还是MSP堆栈指针,当调用 bx r14指令后,硬件会知道要从异常返回, 然后出栈,这个时候堆栈指针PSP已经指向了新任务堆栈的正确位置,当新任务的运行地址及参数r0,r1,r2,r3,r12,r14,r15,xpsr自动加载到R0,R1,R2,R3,R12,R14,R15(PC)以及xPSR寄存器后,CPU根据被出栈到PC寄存器的值,执行新的任务指令。

刚入门FreeRTOS系统实现,此文章叙述任务的调度,后期把任务的创建机制及管理方式实现补上来。看了几天比较吃力,可能以上理解稍有偏差,仅供个人笔记和学习参考使用。

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

FreeRTOS启动第一个任务和任务的切换实现过程 的相关文章

  • 学习MySQL——单表查询

    文章目录 一 SQL语言规范二 基本的SELECT语句1 列的别名2 去除重复行3 空值参与运算4 着重号 96 96 5 显示表结构 三 运算符 比较运算符1 等号运算符 xff08 61 xff09 2 不等于运算符 xff08 lt
  • FreeRTOS-启动第一个任务

    FreeRTOS开始第一个任务源码分析 vTaskStartScheduler xff1a 1 创建一个空任务 xff1a 优先级为0 2 是否使用软件定时器 是的话 创建软件定时器 3 关闭中断 xff08 关中断操作的寄存器是BASEP
  • 我的2014个人总结——学习篇、工作篇、生活篇

    2013的个人总结在我印象当中是写过的 xff0c 2014已成为过去 xff0c 当我想回过头来看看我2013年的总结时 xff0c 奈何我已不知它的踪迹了 xff0c 所以决定以后的个人总结还是以博客的形式记录吧 xff01 平静下来
  • ubuntu vnc 已经配置好,一键开启,节省大家时间

    1 粘贴复制 自己找个目录复制过去 2 修改权限 sudo chmod 777 x0vncserver 3 开启 x0vncserver rfbport 61 5900 SecurityTypes 61 None 下载地址 xff1a ht
  • ArcGIS Engine许可突然用不了了或者localhost没有有效的许可管理器

    ArcGIS Engine许可突然用不了了或者localhost没有有效的许可管理器 在Arc Engine安装包中再重新安装一次许可管理
  • ZeroMQ学习 (五)发布-订阅模式

    7 发布 订阅模式 发布者不用管是否有订阅者 xff0c 它只管不停的发布 xff0c 也不用接受客户端的请求 多订阅者可以尝试链接发布者 xff0c 来接受信息 xff0c 但是不能往发布者发送请求 发布者源码 xff1a span st
  • 树莓派3B+安装Ubuntu20.04

    ros2已经出到F版本了 xff0c 本来想下载一个尝鲜一下 xff0c 怒肝了两天终于把Ubuntu20 04装到树莓派里面了 但是 xff0c 忽然发现F版本的还未发行 xff0c 只是在网站上更新了安装方法 xff0c 安装包和公钥都
  • 【SpringBoot】SpringBoot+SpringSecurity+CAS实现单点登录

    文章目录 一 CAS的概述1 SSO2 CAS3 概念 二 CAS的流程三 CAS服务端部署1 下载地址2 源码打包3 部署运行4 java io FileNotFoundException etc cas thekeystore 系统找不
  • Google Scholar 谷歌学术文献检索技巧总结

    原文链接 xff1a https zhuanlan zhihu com p 24369927 身边有朋友想学如何使用谷歌学术 xff0c 为了更广泛的传播和重复查阅 xff0c 故将个人了解到的谷歌学术检索文献的技巧总结在此 当然 xff0
  • kubernetes flannel pod CrashLoopBackoff解决

    背景 某环境客户部署了一个kubernetes集群 xff0c 发现flannel的pod一直重启 xff0c 始终处于CrashLoopBackOff状态 排查 对于始终CrashLoopBackOff的pod xff0c 一般是应用本身
  • MapReduce之二次排序

    目录 应用场景 什么是二次排序 怎样实现二次排序 示例代码 应用场景 假如输入文件内容如下 xff1a a 1 z 3 b 2 a 100 a 3 b 1 要求经过MapReduce处理后 xff0c key升序排列 xff0c 相同key
  • DirectUI和无窗口用户界面

    http blog joycode com jiangsheng archive 2010 03 22 115921 joy DirectUI DirectUser是一个用户界面框架 xff08 http msdn microsoft co
  • 魔百盒CM201-1刷机教程

    家里有一块魔百盒CM201 1一直在家积灰 xff0c 由于看到网上教程可以刷各种系统 xff0c 所以想着玩来试试看 先刷一个电视版安卓系统看 盒子样子大概就是下面这样 xff1a 拿到手之后就迫不及待的将外壳拆掉了 xff0c 下面这样
  • RK3288刷机教程:安装Ubuntu 16.04

    网上有很多基于瑞芯微RK3288芯片的板子 xff0c 个人感觉配置都非常不错 xff01 然后就淘了两块玩玩 如下图所示 xff1a 然后可以看到 xff0c 各种接口也比较全乎 xff01 有HDMI和VGA视频输出接口 xff0c 两
  • No package ‘orocos-bfl‘ found

    目录 问题 xff1a 原因 xff1a 解决办法 xff1a 问题 xff1a 在编译ros工程的时候 xff0c 出现如下错误提示 xff1a No package 39 orocos bfl 39 found 如下图所示 xff1a
  • 卡尔曼滤波(Kalman filter)算法以及Arduino应用-mpu6050(导航贴)

    正在更新中 这篇文章要跟大家一起完全搞明白卡尔曼滤波 xff0c 连一个标点符号也不放过 xff0c 完完全全理解明白 如果你看不懂 xff0c 那说明我写的不好 本文是看了dr con博士的视频后做的 xff0c 建议可以去看看 如果哪里
  • pop_back()的用法及运行机制

    vector在c 43 43 中非常好用 xff0c 简单的说 xff0c vector是一个能够存放任意类型的动态数组 能够增加和压缩数据 一般使用push back 和pop back 函数将数据存放进容器末尾 如下例程 xff1a i
  • Gazebo为机器人添加传感器

    Gazebo Tutorials 在gazebo仿真中 xff0c 为了验证算法 xff0c 往往需要很多传感器输入作为控制输出量的输入数据 xff0c 因此 xff0c 需要学习添加各式各样的传感器并获取传感器数据 1 IMU传感器 2
  • the selected library block “Contact_forces_lib/3D/sphere to plane force“ no longer exists

    问题 在matlab的simulink里面进行simscape仿真的时候 xff0c 由于添加了接触力 xff0c 因此实现装了 Simscape Multibody Contact Forces Library 这个库 xff0c 装完之
  • matlab画圆(及其他常用图形)

    画图 1 matlab画圆 xff08 1 xff09 代码 xff1a x 61 y 61 r 61 1 for i 61 1 100 x i 61 r cos i 2 pi 100 y i 61 r sin i 2 pi 100 plo

随机推荐

  • CircuitPython入门贴

    前言 以前一直玩arduino的 xff0c 但是恼火于每次写完代码 xff0c 都要编译并烧录到MCU上 xff0c 刚开始的blink例程类的小代码还好 xff0c 起码十几秒钟就能烧录成功 xff0c 但是后来随着程序代码量的增加 x
  • Ready! Use 192.168.191.2 to access clientGuru Meditation Error: Core 1 panic‘ed (LoadProhibited).

    问题描述 在用esp32通过wifi和ros主机进行话题通信的过程中 xff0c 串口一直打印如下信息 xff1a Connecting to Zhitong Ready Use 192 168 191 2 to access client
  • Kolla环境部署命令

    注 xff1a 此博客皆为经验所得 xff0c 如有雷同 xff0c 纯属巧合 xff01 1 根据需要 xff0c 配置 etc kolla global yml xff0c 可选择需要部署的容器 xff1b 2 在 etc kolla
  • Baize_ServoDriver_esp32(ROS+Arduino驱动舵机机械臂,通过串口或WiFi话题通信)(数字孪生:虚拟和现实同步)

    介绍 硬件平台 控制板 xff1a Baize ServoDriver esp32 舵机机械臂 xff1a 通过Baize ServoDriver esp32这块舵机驱动板 xff0c 我们来驱动我们的机器人 首先 xff0c 我们通过串口
  • VMware Workstation 17 Player安装Ubuntu22.04

    ps xff1a 部分内容来自于网络整合 首先去官网下载https www vmware com products workstation player html 点击DOWNLOAD FOR FREE 点击GO TO DOWNLOADS
  • opencv运行出现错误ffmpeg

    调试opencv程序 xff0c 运行时出现 xff1a Error opening file build opencv modules videoio src cap ffmpeg impl hpp 578 网络查询 xff0c 原因 x
  • 美团2014校招笔试题第二题答案分析

    今天在论坛里看到一网友贴出的美团2014校招笔试题 xff0c 其中第二题个人觉得答案应该为7次 xff0c 这里做了一个分析 xff0c 欢迎大家指出其中的纰漏 题目 xff1a 有25匹马 xff0c 每次比赛只能有5匹马参加 xff0
  • ssh连接不上

    之前执行ssh ip命令一直ok 最近换环境了 xff0c 执行ssh ip命令 xff0c 登录不了 xff0c 卡住 man一下 xff0c 知道有个 v的用法 xff1a v Verbose mode Causes ssh to pr
  • 怎么把ubuntu系统从英文修改为中文界面

    Ubuntu系统默认安装的语言是英文 xff0c 有些小伙伴使用起来可能觉得不是很方便 xff0c ubuntu是支持中文界面的 xff0c 修改方法也很简单 xff0c 下面就来看看详细的操作 1 更改语言之前首先确保你的虚拟机能够上网
  • 浅谈一次函数的斜率

    以下是一次函数的基本形式 请证明 本函数的斜率为 我们先来看斜率 我们就以函数为例 这个函数的图像是个直线 是吗 没错 所以如何求一个函数的斜率 设高为 底为 所以斜率就是 看到这个式子是不是感到和微分有关系 没错 微分的定义就是求切线函数
  • 华为 5680 OLT native vlan配置方式

    分为两部分 xff1a 1 配置给ONU端口 2 配置给OLT端口 1 在ONU 端口生效 ont port native vlan profile mode 命令功能 此命令用于配置ONT端口的缺省VLAN 当ONT的Native VLA
  • taskset 设置进程的CPU亲和性

    命令行形式 taskset options mask command arg taskset options p mask pid PARAMETER mask cpu亲和性 当没有 c选项时 其值前无论有没有0x标记都是16进制的 当有
  • 关于win7安装nvm和npm遇到的坑

    nvm到官网 xff08 https github com coreybutler nvm windows releases xff09 下载后 xff0c 直接安装 xff0c 可选择安装路径和nodejs的路径 安装完nvm后win7系
  • Highcharts的学习

    简介 xff1a Highcharts 是一个用纯 JavaScript 编写的一个图表库 xff0c 能够很简单便捷的在 Web 网站或是 Web 应用程序添加有交互性的图表 xff0c 并且 免费 提供给个人学习 个人网站和非商业用途使
  • 侠客精神 与 程序员的梦想

    侠客精神 与 程序员的梦想 我高考的那年是2013年 xff0c 也就是说你们高考完 xff0c 我也快要毕业了 促使我写这篇文章不单单是CSDN的 款款相待 xff0c 也是打算对自己的大学生活做一总结和对未来的人生做一规划 先说高考 x
  • 人脸识别之SphereFace

    2017的一篇cvpr xff0c SphereFace Deep Hypersphere Embedding for Face Recognition xff0c 继centerloss之后又一大作 文章主要提出了归一化权值 xff08
  • LovaszSoftmax

    论文 The Lovasz Softmax loss A tractable surrogate for the optimization of the intersection over union measure in neural n
  • ROS::ubuntu18.04 sudo: rosdep:找不到命令

    ubuntu18 04按照wiki上安装步骤执行sudo rosdep init是出现 sudo rosdep xff1a 找不到命令 原因 xff1a python rosdep这个包没有装 解决办法 xff1a 安装python ros
  • LCD12864液晶显示屏工作原理是什么呢?

    LCD12864液晶显示屏应用的非常广泛 xff0c 比如美容仪 xff0c 温度计 xff0c 保温杯 xff0c 汽车仪表等行业领域 xff0c 本文重点是由深圳兴宇合电子技术人员为大家讲解LCD12864液晶显示屏工作原理 xff0c
  • FreeRTOS启动第一个任务和任务的切换实现过程

    FreeRTOS启动第一个任务和任务的切换实现过程 此篇文章主要参考了野火的 FreeRTOS内核实现与应用开发指南 xff0c 和其他博主的一些资料并加入了一些个人理解 xff0c 作为学习笔记 xff0c 在此感谢火哥和其他博主 xff