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

freertos笔记-任务切换

红叶何时落水

任务切换,调用PendSV
 

#define taskYIELD() portYIELD()
#define portYIELD() \
{ \portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; \ 通过向中断控制和壮态寄存器 ICSR 的 bit28 写入 1 挂起 PendSV 来启动 PendSV 中断\__dsb( portSY_FULL_READ_WRITE ); \__isb( portSY_FULL_READ_WRITE ); \
}

系统滴答定时器(SysTick)中断
 

void xPortSysTickHandler( void )
{vPortRaiseBASEPRI(); 关中断{if( xTaskIncrementTick() != pdFALSE ) //增加时钟计数器 xTickCount 的值{portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; }}vPortClearBASEPRIFromISR(); 开中断
}

查找下一个要运行的任务
vTaskSwitchContext
见freertos笔记-各种列表运行原理.txt


任务调度
xTaskIncrementTick() 被滴答定时器调用
1. 滴答计数+1
2. 判断滴答计数是否溢出最大值
    2.1 如果溢出,代表计数值为0 调用taskSWITCH_DELAYED_LISTS();
      

  #define taskSWITCH_DELAYED_LISTS()                                                                    \{                                                                                                    \List_t *pxTemp;                                                                                    \pxTemp = pxDelayedTaskList;                                                                        \pxDelayedTaskList = pxOverflowDelayedTaskList;                                                    \pxOverflowDelayedTaskList = pxTemp;                                                                \xNumOfOverflows++;                                                                                \prvResetNextTaskUnblockTime();                                                                    \}


            2.1-prvResetNextTaskUnblockTime( void )
               

 {TCB_t *pxTCB;if( listLIST_IS_EMPTY( pxDelayedTaskList ) != pdFALSE ){/* The new current delayed list is empty.  Set xNextTaskUnblockTime tothe maximum possible value so it is    extremely unlikely that theif( xTickCount >= xNextTaskUnblockTime ) test will pass untilthere is an item in the delayed list. */xNextTaskUnblockTime = portMAX_DELAY;}else{/* The new current delayed list is not empty, get the value ofthe item at the head of the delayed list.  This is the time atwhich the task at the head of the delayed list should be removedfrom the Blocked state. */( pxTCB ) = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( pxDelayedTaskList );//获取列表中的第一个任务xNextTaskUnblockTime = listGET_LIST_ITEM_VALUE( &( ( pxTCB )->xStateListItem ) );}}

3. 判断是否有任务到期 添加死循环
    3.1 获取延时列表里的第一个任务(列表是升序排列的)
    3.2 判断获取当前任务的溢出值是否大于计数值 xItemValue在xStateListItem里面放着
        是 xNextTaskUnblockTime = xItemValue;跳出 3. 循环 (一般用于死循环的第二次循环,因为第一次肯定是溢出了,但是,可能溢出的不止一个,所以要把所有溢出的都找到,最后,找到下一个溢出值)
        否 泡泡
    3.3 uxListRemove xStateListItem和xEventListItem
    3.4 添加到就绪列表中 prvAddTaskToReadyList()
       

 #define prvAddTaskToReadyList( pxTCB )                                                                \traceMOVED_TASK_TO_READY_STATE( pxTCB );                                                        \taskRECORD_READY_PRIORITY( ( pxTCB )->uxPriority );                                                \vListInsertEnd( &( pxReadyTasksLists[ ( pxTCB )->uxPriority ] ), &( ( pxTCB )->xStateListItem ) ); \//可以看出来任务会被添加到当前point的前一个,也就是说,后添加的后执行tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB )


    3.5 判断是否要进行任务切换,如果溢出任务优先级高于运行任务优先级的话,会切换任务,而且切换的任务一定是是先添加进去的任务,原因1 高优先级的列表一定为空,pxIndex=>xlistend,而且添加的任务是添加到
        pxIndex前面,那就意味着,pxIndex-xlistend => pxIndex-xlistend-1 => pxIndex-xlistend-1-2 下一个执行的是任务1
4. 判断当前优先级下是否有其他就绪任务,如果是,就切换任务。作用场景为 当前任务和溢出的任务相同优先级,那么下一个执行的会是溢出的任务,当然如果列表里还有其他任务的话不一定是会执行这个溢出任务,
   这种情况的原因在于当前优先级的就绪列表中不一定只有当前任务在运行,所以任务切换后,也不一定会立马切换到溢出的任务,经过检测,没问题,会受到干扰

5. 返回任务上下文切换标志


PendSV中断

__asm void xPortPendSVHandler( void )
{extern uxCriticalNesting;extern pxCurrentTCB;extern vTaskSwitchContext;PRESERVE8mrs r0, pspisbldr    r3, =pxCurrentTCB        /* Get the location of the current TCB. */当前任务结构体ldr    r2, [r3]stmdb r0!, {r4-r11}            /* Save the remaining registers. */str r0, [r2]                /* Save the new top of stack into the first member of the TCB. */当前任务环境保存stmdb sp!, {r3, r14}mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITYmsr basepri, r0dsbisbbl vTaskSwitchContext     //判断下一个任务是哪个mov r0, #0msr basepri, r0ldmia sp!, {r3, r14}ldr r1, [r3]ldr r0, [r1]                /* The first item in pxCurrentTCB is the task top of stack. */ldmia r0!, {r4-r11}            /* Pop the registers and the critical nesting count. */msr psp, r0isbbx r14nop
}


vTaskSwitchContext();

void vTaskSwitchContext( void )
{if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE ){xYieldPending = pdTRUE;}else{xYieldPending = pdFALSE;taskSELECT_HIGHEST_PRIORITY_TASK();//获取就绪最高优先级}
}#define taskSELECT_HIGHEST_PRIORITY_TASK()                                                        \{                                                                                                \UBaseType_t uxTopPriority;                                                                        \\/* Find the highest priority list that contains ready tasks. */                                \portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );                                \configASSERT( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ uxTopPriority ] ) ) > 0 );        \listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );        \//获取最高优先级中的任务,就是( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext执行后pxIndex的指向} /* #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;                                            \}    

相关文章:

freertos笔记-任务切换

红叶何时落水 任务切换,调用PendSV #define taskYIELD() portYIELD() #define portYIELD() \ { \portNVIC_INT_CTRL_REG portNVIC_PENDSVSET_BIT; \ 通过向中断控制和壮态寄存器 ICSR 的 bit28 写入 1 挂起 PendSV 来启动 PendSV 中断\__dsb( portSY_FULL_READ…...

企业电子招投标采购系统源码之登录页面-java spring cloud

​ 信息数智化招采系统 服务框架:Spring Cloud、Spring Boot2、Mybatis、OAuth2、Security 前端架构:VUE、Uniapp、Layui、Bootstrap、H5、CSS3 涉及技术:Eureka、Config、Zuul、OAuth2、Security、OSS、Turbine、Zipkin、Feign、Monitor、…...

接口测试|Fiddler弱网测试

Fiddler进行弱网测试 弱网测试 概念:弱网看字面意思就是网络比较弱,我们通称为信号差,网速慢。 意义:模拟在地铁、隧道、电梯和车库等场景下使用APP ,网络会出现延时、中断和超时等情况。 在这里插入图片描述 Fidd…...

Linux-0.11 文件系统super.c详解

Linux-0.11 文件系统super.c详解 模块简介 该模块主要包含了对超级块的一些读写操作。 函数详解 lock_super static void lock_super(struct super_block * sb)该函数的作用是锁定bh块。 cli();//关中断while (sb->s_lock)//如果已经被锁定sleep_on(&(sb->s_wai…...

什么是ChatGPT、历史发展及应用领域

什么是ChatGPT ChatGPT是一种基于深度学习的自然语言处理技术,它可以生成高质量的自然语言文本,该技术是由OpenAI团队开发,旨在使计算机能够像人类一样理解和产生自然语言。ChatGPT使用了深度神经网络和自然语言处理技术,通过对大…...

Spring的创建与使用

目录 1.创建 Spring 项⽬ 1.1 创建一个 maven 项目 1.2 添加 spring 框架支持(spring-context/spring-beans) 2.将 Bean (对象) 存储到 Spring (容器) 中 2.1 在resources中创建一个spring配置文件 2.2 将 Bean 对象存储到 Spring 当中 2.2.1 创建 Bean 对象 2.2.2 将B…...

抖音Flutter插件的使用

Flutter是一个开源的移动应用程序开发框架,由谷歌开发,支持Android和iOS。随着Flutter的发展和成熟,许多人开始使用它来开发跨平台应用程序。本文将介绍如何使用抖音的Flutter插件,以增强Flutter应用程序的功能。 1. 安装Flutter…...

Debezium报错处理系列之六十八:No resolvable bootstrap urls given in bootstrap.servers

Debezium报错处理系列之六十八:No resolvable bootstrap urls given in bootstrap.servers 一、完整报错二、错误原因三、解决方法Debezium报错处理系列一:The db history topic is missing. Debezium报错处理系列二:Make sure that the same history topic isn‘t shared b…...

Python二级编程:分词去重

一、原题 参考编程模板,完善代码,实现以下功能。‪‪‪‪‪‫‫‪‪‪‪‪‪‪‪‪‪‪‪‪‪‪‪‪‫‪‪‪‪‪‪‪‪‪‪‪‪‪‫ 利用 jieba 库实现中文分词。对分词后的列表进行去重处理,然后将分词结果中字符数大于等于 3 的词语&…...

Android Wifi开发——Wifi锁(十九)

有的时候我们需要 APP 在手机后台运行,但是会遇到手机一旦息屏或者断网,APP 无法正常运行的情况,这是因为手机屏幕关闭之后,并且其他的应用程序没有在使用 Wifi 的时候,系统大概在两分钟之后,会关闭 Wifi,使得 Wifi 处于睡眠状态。而 Wifi 锁 就是 Android 锁屏后 Wifi …...

Nginx的优化与防盗链

目录 一. 隐藏版本号方法一:配置文件隐藏版本号方法二:源代码隐藏版本号 修改用户与组缓存时间日志切割连接超时更改进程数配置网页压缩配置防盗链fpm参数优化 一. 隐藏版本号 可以使用 Fiddler 工具抓取数据包,查看 Nginx版本,也…...

STP协议

目录 STP的基本概念: 桥ID(Bridge ID): 根桥: 开销(Cost): RPC(根路径开销): Port ID: BPDU:(网桥协议…...

方法——检查参数的有效性

检查参数的有效性 绝大多数方法和构造方法对于传递给它们的参数都会有某些限制,比如对象引用不能为null,比如必须是正数等.你应该在文档中(或者注释中)清楚地指出所有这些限制,并且在方法体的开头检查参数,并且强制施加这些限制.如果做不到这一点,检测出错误的可能性就很小,即…...

七、Docker仓库之nexus搭建(四)

Nexus简介 使用 Docker 官方的 Registry 创建的仓库面临一些维护问题。比如某些镜像删除以后空间默认是不会回收的,需要一些命令去回收空间然后重启 Registry。在企业中把内部的一些工具包放入 Nexus 中是比较常见的做法,最新版本 Nexus3.x 全面支持 Doc…...

MySQL 锁机制

1.概述 锁是计算机协调多个进程或线程并发访问某一种资源的机制。 在数据库中,除去计算机硬件资源(CPU、RAM、I/O等)的争用外,数据也是一种供许多用户共享的资源。如何保证并发访问数据的一致性、有效性是所有数据库必须解决的一…...

HACKER KID: 1.0.1实战演练

文章目录 HACKER KID: 1.0.1实战演练一、前期准备1、相关信息 二、信息收集1、端口扫描2、访问网站3、扫描目录4、查看源码5、请求参数6、burpsuite批量请求7、编辑hosts文件8、DNS区域传输9、编辑hosts10、访问网站11、注册账号12、burpsuite抓包13、XML注入14、解密15、登录网…...

Android车载学习笔记1——车载整体系统简介

一、汽车操作系统 汽车操作系统包括安全车载操作系统、智能驾驶操作系统和智能座舱操作系统。 1. 安全车载操作系统 安全车载操作系统主要面向经典车辆控制领域,如动力系统、底盘系统和车身系统等,该类操作系统对实时性和安全性要求极高,生态…...

Apache Doris

Apache Doris教程 1.Doris 简介 1.1 Doris 概述 Apache Doris 由百度大数据部研发(之前叫百度 Palo,2018 年贡献到 Apache 社区后, 更名为 Doris ),在百度内部,有超过 200 个产品线在使用,…...

GB28181 对接海康平台,解决音视频卡顿问题

GB28181 对接海康平台,解决音视频卡顿问题 一、概述二、问题分析1、设备对比分析2、抓包对比分析3、验证分析结果三、总结四、讨论一、概述 设备使用GB28181协议对接海康平台时,发现音频和视频存在卡顿现象,不是一直卡顿,有时候卡有时候不卡,但是卡顿的时候音视频一起卡顿…...

Linux系统编程面试题

1. 什么是系统调用?它与普通函数调用有什么不同? 系统调用和普通函数调用的区别在于它们执行的上下文和权限不同。系统调用是操作系统内核提供的一组接口,允许用户程序请求操作系统执行特权操作,例如打开或关闭文件、创建新进程等…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...

【Oracle APEX开发小技巧12】

有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...

linux 错误码总结

1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...

数据链路层的主要功能是什么

数据链路层(OSI模型第2层)的核心功能是在相邻网络节点(如交换机、主机)间提供可靠的数据帧传输服务,主要职责包括: 🔑 核心功能详解: 帧封装与解封装 封装: 将网络层下发…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

Linux --进程控制

本文从以下五个方面来初步认识进程控制: 目录 进程创建 进程终止 进程等待 进程替换 模拟实现一个微型shell 进程创建 在Linux系统中我们可以在一个进程使用系统调用fork()来创建子进程,创建出来的进程就是子进程,原来的进程为父进程。…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言: 在Java编程中,类的生命周期是指类从被加载到内存中开始,到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期,让读者对此有深刻印象。 目录 ​…...

Linux 中如何提取压缩文件 ?

Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...