IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 【嵌入式操作系统-5】操作系统中的上下文切换 -> 正文阅读

[嵌入式]【嵌入式操作系统-5】操作系统中的上下文切换

操作系统中的任务状态

在FreeRTOS中存在四种任务运行状态:
在这里插入图片描述

  • 每一个状态下对应一个双向循环链表,里面存储了对应状态的任务列表。
  • 任务状态的转换实际上就是将对应任务的任务控制块从一个队列转移到另一个队列的过程。
  • 处于就绪队列中的任务将会被调度,在FreeRTOS中会选择优先级最高的任务让其运行。
  • 当就绪队列中的任务被调度器调度执行后,任务状态便从就绪态转为运行态,如果最高优先级的任务有多个并且使能了时间片轮询,那么操作系统会为这些任务分配时间片交替执行。
  • 当前任务正在运行的时间片用完或者有更高优先级的任务被唤醒时,操作系统会进行上下文切换,此时任务的状态便从运行态转换为就绪状态。
  • 正在运行的任务如果调用了阻塞的函数,设置的阻塞时间不是portMAX_DELAY,那么该任务将会被放入延时队列中,进入阻塞状态,如果阻塞时间设置为portMAX_DELAY,该任务将会被放入挂起队列中,进入挂起状态,避免该任务被周期性的唤醒。
  • 处于延时队列中的任务在条件满足之后任务将会重新添加到就绪队列中,等待被操作系统调度运行。
  • 正在运行的任务调用vTaskSuspend函数,将会把任务从就绪队列转移到挂起队列中,下一次进行任务切换时,调度器从就绪队列中重新查找优先级最高的任务进行调度。
  • 处于挂起队列中的任务在调用vTaskResume后将会重新添加到就绪队列中,等待被操作系统调度运行。

操作系统中的上下文切换

操作系统中的上下文切换分为如下几种情况:

  • 第一种是任务调用portYIELD()将PendSV的挂起位置1。
  • 第二种是处于阻塞状态的任务等待超时重新被唤醒或挂起的被任务恢复,并且他们的优先级足够高,在每个SysTick中断产生之后会检测是否需要进行上下文切换,如果需要则将PendSV的挂起位置1。
  • 第三种是使用了时间片轮询,当一个任务的时间片用完之后,必须要切换到下一个任务,此时SysTick中断中也会将PendSV的挂起位置1。

从上面几种情况中可以看出当需要调度器切换上下文时,必须要将PendSV的挂起位置1,这是切换上下文的前提条件。PendSV的优先级设置为最低,当系统中没有其他中断产生时候,PendSV中断被CPU响应。

#define portYIELD()																\
{																				\
	/* Set a PendSV to request a context switch. */								\
	portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;								\
																				\
	/* Barriers are normally not required but do ensure the code is completely	\
	within the specified behaviour for the architecture. */						\
	__dsb( portSY_FULL_READ_WRITE );											\
	__isb( portSY_FULL_READ_WRITE );											\
}
  • 前面讲解过Cortex-M7处理器在带操作系统运行模式下,中断中使用的栈指针和线程中使用的栈指针是不同的,在中断中使用的是MSP,在线程中使用的是PSP,当前任务的栈顶值位于PSP中,如果直接使用push会把寄存器值放入MSP所指向的栈中,这样无法完成任务切换。
  • 因此第一步是通过MRS加载PSP的值到R0中,然后再加载pxTopOfStack的地址到R2中,加载R0是为了后面使用stm指令保存任务状态到栈上,而pxTopOfStack则保存了当前任务的栈顶,可用于直接访问线程栈和溢出检测等用途。
__asm void xPortPendSVHandler( void )
{
	extern uxCriticalNesting;
	extern pxCurrentTCB;
	extern vTaskSwitchContext;

	PRESERVE8

	/* 获取当前任务栈顶地址 */
	mrs r0, psp
	isb
	/* 将TCB中变量pxTopOfStack的地址加载到R2中,在所有寄存器保存到栈上后需要更新栈顶位置 */
	ldr	r3, =pxCurrentTCB
	ldr	r2, [r3]
  • 然后将需要换出的任务状态保存到栈中,同时更新一下栈顶pxTopOfStack的值,这样换出工作便完成了。
	/* 如果当前任务正在进行浮点运算,需要保存浮点寄存器 */
	tst r14, #0x10
	it eq
	vstmdbeq r0!, {s16-s31}

	/* 保存通用寄存器 */
	stmdb r0!, {r4-r11, r14}

	/* 当把任务的寄存器值保存到栈上之后,栈顶位置发生了变化,需要更新TCB中栈顶位置 */
	str r0, [r2]
  • 进入临近段跳转到vTaskSwitchContext函数中,在这个函数中根据对应的调度算法找出需要运行的下一个任务,将pxCurrentTCB指向新任务然后退出临界段。
	/* 将r0和r3(pxCurrentTCB地址) 保存到栈上*/
	stmdb sp!, {r0, r3}
	/* 屏蔽优先级数值大于等于configMAX_SYSCALL_INTERRUPT_PRIORITY的中断,进入临界段 */
	mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
	cpsid i
	msr basepri, r0
	dsb
	isb
	cpsie i
	/* 跳转到vTaskSwitchContext查找出优先级最高的就绪态任务赋值给pxCurrentTCB */
	bl vTaskSwitchContext
	/* 退出临界段*/
	mov r0, #0
	msr basepri, r0
  • 然后将新任务的栈顶指针加载到R0中,把对应的寄存器从栈中恢复,同时更新新任务的pxTopOfStack值,这样换入工作便完成了。
	/* 恢复R0和R3的值 */
	ldmia sp!, {r0, r3}

	/* 将pxCurrentTCB中pxTopOfStack变量保存的栈顶地址加载到R0中 */
	ldr r1, [r3]
	ldr r0, [r1]

		/* 将新任务的状态进行恢复 */
	ldmia r0!, {r4-r11, r14}

	/* 如果中断位置正包含浮点运算需要先恢复浮点寄存器 */
	tst r14, #0x10
	it eq
	vldmiaeq r0!, {s16-s31}
	
	/* 将新任务的栈顶指针值写入到psp中,PendSV退出之后就会使用该栈继续运行程序 */
	msr psp, r0
	isb
  • 在上下文切换成功之后通过LR进行返回,新任务从上次中断的位置继续往下运行。
	#ifdef WORKAROUND_PMU_CM001 /* XMC4000 specific errata */
		#if WORKAROUND_PMU_CM001 == 1
			push { r14 }
			pop { pc }
			nop
		#endif
	#endif
	/* 将LR寄存器的加载到PC中退出中断并返回线程 */
	bx r14
}
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-05-21 19:08:40  更:2022-05-21 19:10:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 7:54:38-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计