FreeRTOS任务调度最后篇

2023-05-16

“FreeRTOS开启任务调度”一篇说到启动任务调度最后启动Systick定时器,通过SVC中断引导第一个任务执行。然后系统就在Systick的定时中断下调度任务执行,这次介绍最后的部分,Systick和PendSV。

SysTick时钟是STM32的一个定时器,使能之后设置中断频率就会按频率触发SysTick中断。这样就可以用SysTick中断给OS切换任务提供时机。因为硬件是中断来了就会把CPU当前任务压栈,会执行中断处理函数,中断处理完成后会出栈之前数据。继续执行之前被中断的任务。在没OS情况下都是在MSP执行。既然需要OS调度,那么就要使能control寄存器,让CPU在非中断时候使用PSP栈指针。在中断MSP逻辑控制执行的PSP。所以OS调度离不开中断,同时用到双堆栈MSP和PSP隔离任务和OS。即内核空间和用户空间,OS调度在中断执行,运行在内核空间。任务在非中断执行,运行在用户空间,任务通过SVC中断调用内核。

如果SysTick不设置最低优先级,在SysTick里切换任务还会导致硬件异常。
因为在Cortex-M3中,如果OS在某个中断活跃时,抢占了该中断,而且又发生了任务调度,并执行了任务,切换到了线程运行模式,将直接触发Fault异常。(所以把SysTick和PendSV中断优先级设置最低也是有原因的,就是为了OS调度不抢占其他中断导致Fault的问题)

按理SysTick设置最低优先级就可以切换任务上下文了。一般OS在调度任务时,会关闭中断,也就是进入临界区,而OS任务调度是要耗时的,这就会出现一种情况:在任务调度期间,如果新的外部IRQ发生,CPU将不能够快速响应处理。比如串口在发数据,在OS进入临界区屏蔽中断执行任务切换期间就可能丢失读取串口发来的数据。(这是在SysTick执行任务切换带来的降低其他中断处理速度问题)

所以为了解决SysTick切换任务导致IRQ处理速度降低问题,就利用PendSV【缓期执行】的特点。滴答定时器中断,只做业务调度前的判断工作,不做任务切换。触发PendSV,PendSV并不会立即执行,因为PendSV的优先级最低,如果此时正好有IRQ请求,那么先响应IRQ,最后等到所有优先级高于PendSV的IRQ都执行完毕,再执行PendSV,进行任务调度(这样就解决了IRQ性能降低的问题)

这样也不是没缺点的,因为SysTick设置最低,如果其他中断特别频繁,就会导致SysTick执行频繁挂起,导致时钟不准,任务调度慢。因为SysTick自身执行机会被抢的很少,但是这些问题影响面已经很小了。

那如果把SysTick优先级设置最高,PendSV优先级设置最低是不是可以完美解决呢。因为SysTick的优先级最高,而且又是周期性的触发,会导致经常抢占外部IRQ,这就会导致外部IRQ响应变慢,这在一些对实时性要求高的,比如按键、断电中断等待,是不能接受的,你肯定不希望你的按键扫描体验卡顿。(SysTick又频繁抢占其他IRQ)

所以没有完美的方法,一般把SysTick和PendSV设置最低满足大部分情况,毕竟外部IRQ那么多的情况不多,一般不会影响SysTick的周期性。如果外部IRQ很多,那么可以考虑提高SysTick优先级,PendSV一直设置最低,来适当解决OS调度SysTick被抢占太厉害的问题。

设置SysTick和PendSV中断的资料来源如下图:
在这里插入图片描述

//启动调度器
BaseType_t xPortStartScheduler(void)
{
	//使PendSV成为最低优先级的中断。11111111<<16为00000000111111110000000000000000
	portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
	//使SysTick成为最低先级的中断。11111111<<24为11111111000000000000000000000000
	portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;

	//启动滴答计时器,设置频率。中断在这里被禁用
	vPortSetupTimerInterrupt();

	//初始化为第一个任务准备的关键嵌套计数。
	uxCriticalNesting = 0;

	//开启第一个任务
	prvStartFirstTask();

	//正常执行不到这里
	return 0;
}

要点:
1.SysTick和PendSV一般设置最低优先级,来保证及时处理外部中断,因为是嵌入式实时系统对不。
2.SysTick可以按实际适当提高优先级,比重要中断低,比不重要中断高。PendSV还是以最低优先级执行。
3.SysTick在最低优先级是能切换任务的,只是会多执行切换逻辑,导致IRQ处理性能降低。引入PendSV不是必须的,主要利用PendSV缓期执行的特点提高IRQ性能。

SysTick逻辑如下,就是判断是否要切换任务,要切换的话就触发PendSV完事

//滴答时钟中断。内核通过滴答中断判断是否需要切换上下文
//如果需要切换上下文则设置PendSV寄存器触发PendSV中断进行上下文切换
void xPortSysTickHandler(void)
{
	/*SysTick 以最低的中断优先级运行,所以当这个中断
	* 执行所有中断必须被取消屏蔽。 因此没有必要
	* 保存然后恢复中断屏蔽值,因为它的值已经是
	* 已知 - 因此使用稍快的 vPortRaiseBASEPRI() 函数
	* 代替 portSET_INTERRUPT_MASK_FROM_ISR()。*/
	//屏蔽比OS级别低的中断和刷新指令和数据流水线
	vPortRaiseBASEPRI();
	{
		//增加OS的节拍数。返回是否需要切换上下文
		if (xTaskIncrementTick() != pdFALSE)
		{
			//需要上下文切换。产生PendSV中断 。
			portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
		}
	}
	//取消屏蔽中断
	vPortClearBASEPRIFromISR();
}

PendSV逻辑如下,就是压栈上下文,切换pxCurrentTCB后恢复新任务上下文,然后退出中断到PSP执行新任务。

/*PendSV是可悬起异常,如果我们把它配置最低优先级,那么如果同时有多个异常被触发,它会在其他异常执行完毕后再执行,
而且任何异常都可以中断它。更详细的内容在《Cortex-M3 权威指南》里有介绍,下面我摘抄了一段。
OS 可以利用它“缓期执行”一个异常——直到其它重要的任务完成后才执行动 作。悬起 PendSV 的方法是:
手工往NVIC的PendSV悬起寄存器中写 1。悬起后,如果优先级不够 高,则将缓期等待执行。
PendSV的典型使用场合是在上下文切换时(在不同任务之间切换)。例如,一个系统中有两个就绪的任务,上下文切换被触发的场合可以是:
1、执行一个系统调用
2、系统滴答定时器(SYSTICK)中断,(轮转调度中需要)
让我们举个简单的例子来辅助理解。假设有这么一个系统,里面有两个就绪的任务,并且通过SysTick异常启动上下文切换。
但若在产生 SysTick 异常时正在响应一个中断,则 SysTick异常会抢占其 ISR。在这种情况下,OS是不能执行上下文切换的,
否则将使中断请求被延迟,而且在真实系统中延迟时间还往往不可预知——任何有一丁点实时要求的系统都决不能容忍这 种事。
因此,在 CM3 中也是严禁没商量——如果 OS 在某中断活跃时尝试切入线程模式,将触犯用法fault异常。
为解决此问题,早期的 OS 大多会检测当前是否有中断在活跃中,只有在无任何中断需要响应 时,才执行上下文切换(切换期间无法响应中断)。
然而,这种方法的弊端在于,它可以把任务切 换动作拖延很久(因为如果抢占了 IRQ,则本次 SysTick在执行后不得作上下文切换,
只能等待下 一次SysTick异常),尤其是当某中断源的频率和SysTick异常的频率比较接近时,会发生“共振”, 使上下文切换迟迟不能进行。
现在好了,PendSV来完美解决这个问题了。PendSV异常会自动延迟上下文切换的请求,直到 其它的 ISR都完成了处理后才放行。
为实现这个机制,需要把 PendSV编程为最低优先级的异常。如果 OS检测到某 IRQ正在活动并且被 SysTick抢占,
它将悬起一个 PendSV异常,以便缓期执行 上下文切换。
1.关闭中断
2.保存上文
3.加载下文
4.打开中断
*/
//进入该中断后讲使用MSP栈指针,PSP不会被盖。这时候Context内核已经自动压栈了xPSR,R15(PC),R14(LR),R12(SP),R3,R2,R1,R0到用户栈空间
__asm void xPortPendSVHandler(void)
{
	extern uxCriticalNesting;
	//当前运行的任务
	extern pxCurrentTCB;
	//任务切换上下文
	extern vTaskSwitchContext;

	//指定当前文件的堆栈按照 8 字节对齐
	PRESERVE8
		//R0=PSP  Process Stack Pointer (PSP)
		//取出用户栈指针到r0.r0存当前用户栈地址
		mrs r0, psp
		//指令同步屏障,清除指令流水线
		isb
		//LDR指令用于从存储器中将一个32位的字数据传送到目的寄存器中。该指令通常用亍从存储器中读取32位的字数据到通用寄存器,然后对数据迕行处理
	  //获取pxCurrentTCB变量的地址到r3(这时候pxCurrentTCB变量存当前运行任务的tcb首地址)
		ldr r3, =pxCurrentTCB /* Get the location of the current TCB. */
		//把pxCurrentTCB变量指向的tcb地址读入r2
		ldr r2, [r3]
		//stmdb将寄存器压栈,保存剩余的寄存器。叹号标识自动调整地址
		//r0里面地址从高到低自动调节,依次把r4到r11寄存器的内容储存r0的任务栈里面
	  //把r4到r11寄存器值压入当前用户的栈(PSP指向的栈)
		stmdb r0 !, { r4 - r11 } /* Save the remaining registers. */
		//STR{条件} 源寄存器,<存储器地址>
		//STR指令用亍从源寄存器中将一个32位的字数据传送到存储器中。该指令在程序设计中比较常用
		//将新的栈顶保存到TCB的第一个成员中。
		//把r0存的用户栈地址存入r2指向的地址里,即pxCurrentTCB的开始位置,也就是第一个成员里
		str r0, [r2] /* Save the new top of stack into the first member of the TCB. */
		//stmdb将寄存器压栈,入栈保存R3(即&pxCurrentTCB)和 R14(链接寄存器)。叹号标识自动调整地址
		//sp里面地址从高到低自动调节,依次把r3和r14寄存器的内容储存sp的任务栈里面
		//把r3(现在存的pxCurrentTCB变量地址)和r14(链接寄存器)值压入主栈
		stmdb sp !, { r3, r14 }
		//读入最大优先级进入r0
		mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
		//设置屏蔽中断寄存器basepri为OS所能调用管理的最高优先级
		//这里中断优先级0-255,越大优先级越低。即屏蔽所有比设置的OS所能管理的最大优先级低的中断
		msr basepri, r0
		//数据同步令牌,清除数据流水线
		dsb
		//指令同步屏障,清除指令流水线
		isb
		//进行任务切换,在临界段切换就绪队列中优先级最高的任务,更新pxCurrentTCB
		//跳转到vTaskSwitchContext执行需要返回
		bl vTaskSwitchContext
		//把0读入r0
		mov r0, #0
		//设置屏蔽中断寄存器basepri为0,开启中断
		msr basepri, r0
		//从主堆栈中恢复寄存器R3和R14的值,此时SP使用的是MSP。叹号标识自动调整地址
		//sp里面地址由低到高自动调节,依次把sp的任务栈弹出到r3到r14寄存器
		//从主栈里恢复r3(r3存的是pxCurrentTCB变量的地址)和r14(链接寄存器,也就是做切换逻辑前的链接)
		//和stmdb sp !, { r3, r14 }是对应的,切换任务前压入主栈了,切换完成后从主栈弹出
		ldmia sp !, { r3, r14 }
		//r3里面是pxCurrentTCB变量指向的地址。把该地址存的当前tcb地址读入r1(由于切换了任务pxCurrentTCB变量存了新任务的tcb首地址)
		ldr r1, [r3]
		//pxCurrentTCB中的第一项是栈顶任务,读出PCB存的栈顶位置到r0(pxCurrentTCB这时候已经存的新任务的tcb,这样就得到新任务的栈顶)
		//和str r0, [ r2 ]是对应的,str r0, [ r2 ]存PSP到tcb第一个元素的栈顶指针变量里
		ldr r0, [r1] /* The first item in pxCurrentTCB is the task top of stack. */
		//弹出寄存器和关键嵌套计数
		//r0里面地址由低到高自动调节,依次把r0的任务栈弹出到r4到r11寄存器。叹号标识自动调整地址
		//从r0指向的栈依次弹出r4-r11(这时候r0存的新任务的栈顶,因此是弹出新要执行的任务的寄存器值)
		ldmia r0 !, { r4 - r11 } /* Pop the registers and the critical nesting count. */
		//PSP=R0,更新PSP使异常退出时PSP为基地址进行其他寄存器的自动出栈
		//把新要执行任务栈顶地址写入用户栈顶指针寄存器
		msr psp, r0
		//指令同步屏障,清除指令流水线
		isb
		//系统以PSP作为SP指针出栈,把新任务的任务堆栈中剩下的内容加载到CPU寄存器:
		//R0(任务形参)、R1、R2、R3、R12、R14(LR)、R15(PC)和xPSR,切换到新任务
		//调转到r14的指令不用返回
		bx r14
		//空指令,占用一个时钟周期
		nop
}

这就是我对SysTick和PendSV的理解。调度策略也是看系统定位是看重实时性还是均衡调度。及按照IRQ的数量和不同中断类型重要决定SysTick优先级,如果不能评估,那么最低优先级本来就是不错的选择。

所以方案没有完美的方案,就看关注什么了而已。注重OS调度性能的话那么就会占用其他IRQ的处理时间,可能导致重要中断超时(比如导弹飞过头了)。重视IRQ处理那么可能会因为频繁的IRQ导致OS调度很缓慢。适合自己的就是最好的。

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

FreeRTOS任务调度最后篇 的相关文章

  • FreeRTOS例程4-串口DMA收发不定长数据

    FreeRTOS例程4 串口DMA收发不定长数据 知乎 zhihu com
  • FreeRTOS-内核控制函数

    FreeRTOS 内核控制函数 FreeRTOS中有一些内核函数 一般来说这些内核函数在应用层不会使用 但是内核控制函数是理解FreeRTOS中断的基础 接下来我们逐一分析这些内核函数 taskYIELD 该函数的作用是进行任务切换 这是一
  • FreeRTOS软件定时器创建、复位、开始和停止(备忘)

    目录 一 简介 1 1 开发环境 1 2 摘要 二 STM32CubeIDE配置 三 创建定时器 3 1 头文件声明 3 2 工程文件定义 3 3 创建定时器 3 4 开启 复位 和关闭定时器 四 定时器回调函数 一 简介 1 1 开发环境
  • FreeRTOS学习笔记(3、信号量、互斥量的使用)

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

    使用普通的Timer中断方式时 Timer中断可以正常运行 但是UDP通信进程无法启动 其中TimerIntrHandler是中断服务程序 打印程序运行时间与从BRAM中读取的数据 void SetupInterruptSystem XSc
  • FreeRTOS学习笔记<中断>

    中断概念 Cortex M的NVIC最多支持240个IRQ 中断请求 1个不可屏蔽中断 NMI 1个Systick 滴答定时器 定时器中断和多个系统异常 Cortex M处理器有多个用于管中断和异常的可编程寄存器 这些寄存器大多数都在 NV
  • FreeRTOS ------- 任务(task)

    在学习RTOS的时候 个人觉得带着问题去学习 会了解到更多 1 什么是任务 在FreeRTOS中 每个执行线程都被称为 任务 每个任务都是在自己权限范围内的一个小程序 其具有程序入口每个任务都是在自己权限范围内的一个小程序 其具有程序入口通
  • FreeRTOS打印任务对CPU的占有率

    1 配置RTOS 1 打开RTOS Config Parameter 找到Run Time And Task States gathering related definitions 使能GENERATE RUN TIME STATS US
  • FreeRTOS记录(九、一个裸机工程转FreeRTOS的实例)

    记录一下一个实际项目由裸机程序改成FreeRTOS 以前产品的平台还是C8051单片机上面的程序 硬件平台改成了STM32L051 同时使用STM32CubeMX生成的工程 使用FreeRTOS系统 EEPROM数据存储读取函数修改更新 2
  • 【FreeRTOS(三)】任务状态

    文章目录 任务状态 任务挂起 vTaskSuspend 取消任务挂起 vTaskResume 挂起任务调度器 vTaskSuspendAll 取消挂起任务调度器 xTaskResumeAll 代码示例 任务挂起 取消任务挂起 代码示例 挂起
  • FreeRTOS:中断配置

    目录 一 Cortex M 中断 1 1中断简介 1 2中断管理简介 1 3优先级分组定义 1 4优先级设置 1 5用于中断屏蔽的特殊寄存器 1 5 1PRIMASK 和 FAULTMASK 寄存器 1 5 2BASEPRI 寄存器 二 F
  • FreeRTOS,串口中断接收中使用xQueueOverwriteFromISR()函数,程序卡死在configASSERT

    原因 UART的中断优先级设置的太高 高于了configMAX SYSCALL INTERRUPT PRIORITY宏定义的安全中断等级 UART的中断等级小于等于宏定义的优先等级即可
  • FreeRTOS轻量级同步--任务通知

    1 简介 在FreeRTOS的配置参数中的configUSE TASK NOTIFICATIONS宏打开 一般RTOS会默认打开 如图1所示 图1 notify宏开关 RTOS在创建任务时 会创建一个32位的通知值ulNotifiedVal
  • 单片机通信数据延迟问题排查

    1 问题说明 笔者在最近的项目中 发现系统的响应延迟较高 经过排查 排除了单片机运行卡死的问题 2 原因分析 具体排查过程这里就不细致说明了 直接给出排查后原因 任务执行周期规划不合理 导致freertos队列发送接收到的命令有延迟 为了便
  • FreeRTOS临界段

    1 临界段 在访问共享资源时不希望被其他任务或者中断打断的代码 这段要执行的代码称为临界段代码 2 设置临界段的目的 保护共享资源 例如 全局变量 公共函数 不可重入函数 函数里面使用 了一些静态全局变量 malloc 等 保护外设的实时性
  • FreeRTOSConfig.h 配置优化及深入

    本篇目标 基于上一篇的移植freertos stm32f4 freertos 上 修改 FreeRTOSConfig h 文件的相关配置来优化辅助 FreeRtos 的使用 并且建立一些基本功能 信号量 消息地列等 的简单应用位于 stm3
  • 当一个任务写入变量而其他任务读取该变量时,我们是否需要信号量?

    我正在研究 freeRtos 并且我有一个名为 x 的变量 现在 每秒只有一个任务正在写入该变量 而其他任务正在读取该变量值 我需要用互斥锁来保护变量吗 如果变量为 32 位或更小 并且其值是独立的并且不与任何其他变量一起解释 则不需要互斥
  • 防止GCC LTO删除函数

    我使用 GCC ARM Embedded 和 FreeRTOS FreeRTOS具有的功能vTaskSwitchContext 仅在某些情况下使用 内联汇编代码 问题是 当我使用LTO时 GCC不考虑内联汇编代码并认为该函数没有被使用 因此
  • 有可用的 FreeRTOS 解释语言库吗?

    我在一家公司工作 该公司使用 FreeRTOS 为多个设备创建固件 最近 我们对新功能的要求已经超出了我们固件工程师的工作能力 但我们现在也无力雇用任何新人 即使进行微小的更改 也需要固件人员在非常低的级别上进行修改 我一直在为 FreeR
  • C++ freeRTOS任务,非静态成员函数的无效使用

    哪里有问题 void MyClass task void pvParameter while 1 this gt update void MyClass startTask xTaskCreate this gt task Task 204

随机推荐

  • 运动相机检测无人机-- Detecting Flying Objects using a Single Moving Camera

    Detecting Flying Objects using a Single Moving Camera PAMI 2017 http cvlab epfl ch research unmanned detection https dri
  • [转载]Python SMTP发送邮件-smtplib模块

    在进入正题之前 xff0c 我们需要对一些基本内容有所了解 xff1a 常用的电子邮件协议有SMTP POP3 IMAP4 xff0c 它们都隶属于TCP IP协议簇 xff0c 默认状态下 xff0c 分别通过TCP端口25 110和14
  • c语言和c++有什么区别

    差不多是win98跟winXP的关系 C 43 43 是在C的基础上增加了新的理论 xff0c 玩出了新的花样 所以叫C加加 C是一个结构化语言 xff0c 它的重点在于算法和数据结构 C程序的设计首要考虑的是如何通过一个过程 xff0c
  • 梳理LVM逻辑卷管理,

    在Linux操作系统会时不时碰到卷有关的操作 xff0c 以下也是罗列了相关操作内容 xff0c 仅供参考 创建PV VG LV的方法 将各物理磁盘或分区的系统类型设为Linux LVM xff0c 其system ID为8e xff0c
  • 使用sqlyog连接 Mysql 出现1251错误

    使用sqlyog连接 Mysql 出现1251错误 简述 xff1a 1251 client does not support authentication protocol requested by server consider upg
  • 准备给ubuntu18.04安装杀毒软件

    如题 xff0c 电脑最近总出现些奇奇怪怪的小问题 xff0c 还是得装个杀毒软件 xff0c 看是不是中病毒了 输入sudo apt get install clamtk 安装完成后 xff0c 输入clamtk 即可 xff0e 卸载方
  • 使用Nginx代理地址

    DotNetCore在Linux发布时候 xff0c 由于不止一个产品组发布网站 xff0c 不像以前大家都用IIS的80发布网站 那么就存在大家抢80端口的情况 xff0c 为了让大家不比加上端口为此用Nginx代理URL实现网站地址代理
  • CentOS安装Cache数据库

    适用CentOS7 6 CentOS8上安装Intersystem公司的Cache数据库 xff0c 资料基本是空白 xff0c 分享一下 首先安装解压软件unzip和libicu xff0c 最小化安装的缺 xff0c 全安装的不缺 yu
  • Cache数据库之ECP搭建

    Cache作为非关系数据库 xff0c 其强大毋庸置疑 首先其Globle结构 xff0c 直接暴露的表Globel数据 xff0c 以及提供的M语言操作Globle达到的最优查询速度 ECP xff08 企业缓存协议 xff09 更是提供
  • Sebia电泳绘图

    Sebia这仪器真是个奇葩的存在 自己仪器有图不存文件 xff0c LIS要的话还得自己按数据绘制 还有蛋白电泳 固定电泳 画不画参考线等不同要求 xff08 奇葩的很 xff09 按理这种事不属于lis范围 xff0c 无奈国内lis太卷
  • nginx代理与负载均衡

    随着谷歌浏览器不断的改变https调用websocket和非https资源的策略 xff0c 从谷歌大概70以后不允许https调用非https资源和ws的websocket 后面实现了wss解决谷歌这一策略的影响 随着谷歌到90后版本限制
  • FreeRTOS学习第一篇

    之前在STM32Nano开发板开发是基于裸机开发 xff0c 即自己在main方法写死循环 死循环轮流执行各个任务逻辑的方法 这样做直接简单 xff0c 但是不同任务有不同优先级 xff0c 对CPU响应要求不同 逻辑容易某个任务卡住了 x
  • FreeRTOS之heap4

    操作系统离不开内存管理 FreeRTOS提供了5种内存管理方法 实现在portable MemMang里heap1到heap5 每种管理方案策略不同 我采用的是比较有代表性的heap4管理方案 该模式定义了ucHeap全局数组充当堆内存池
  • FreeRTOSMini

    最近在研究实时操作系统FreeRTOS FreeRTOS作为开源的RTOS xff0c 源码规模不大 xff0c 可以供操作系统学习 xff0c 加上我的STM32 Nano开发板正好可以学习OS 借着五一放假宅家里学习 实现的FreeRT
  • 双master节点+keepalived方式部署K8s 1.18.20

    相关部署方式也挺多 xff0c 自己采用双master节点 43 单node节点方式 xff0c 并且采用keepalived部署1 18 20版本 xff0c 中间也出现过相关小问题 xff0c 但都一一处理 xff0c 记录以给需要的同
  • FreeRTOS之TCB

    FreeRTOSMini实现了最小任务调度 现在分开介绍进程调度重要部分 进程调度的基础首先是定义任务调度的数据结构 xff0c 来保存任务堆栈结构和任务状态所在状态列表 xff0c 然后就是任务的优先级唯一号等 最小Mini内核参照 Fr
  • FreeRTOS任务调度主要变量

    之前介绍的和FreeRTOS任务调度相关的数据结构即内存分配实现 xLIST heap 4 TCB结构体 任务调度就是基于这些结构体实现 这次介绍调度相关的主要变量 代码在FreeRTOSMini c文件签名部分 span class to
  • Base64串介绍

    以前写winform时候没接触过Base64 刚开始接触时候还不知道是个啥 最开始接触Base64串时候是仪器出图 很长一段时间我还真以为Base64就是表示图的 xff0c 很多人也是这么认为的 xff0c 这次介绍一下什么是Base64
  • FreeRTOS创建任务

    CPU有这些寄存器 R0 R12为通用寄存器 R13为栈顶指针 xff0c 在OS时候中断函数的R13使用MSP的指针 xff08 内核态 xff09 非中断里面使用PSP指针 xff08 用户态 xff09 正是有双堆栈指针可以保证OS切
  • FreeRTOS任务调度最后篇

    FreeRTOS开启任务调度 一篇说到启动任务调度最后启动Systick定时器 xff0c 通过SVC中断引导第一个任务执行 然后系统就在Systick的定时中断下调度任务执行 xff0c 这次介绍最后的部分 xff0c Systick和P