10_FreeRTOS任务切换FreeRTOSr任务调度整个过程

文章详细阐述了FreeRTOS系统中的任务切换过程,涉及PendSV中断的触发,xPortPendSVHandler中断服务函数的执行,以及vTaskSwitchContext如何查找并切换到最高优先级任务。上下文切换通过保存和恢复任务的寄存器状态在PendSV中断中完成,确保任务间的平滑过渡。
摘要由CSDN通过智能技术生成

目录

任务切换

xPortPendSVHandler中断服务函数

查找最高优先级任务vTaskSwitchContext函数

FreeRTOS任务调度整个过程脑图


任务切换

任务切换的本质:就是CPU寄存器的切换。就是把任务块的TCB开头的寄存器加载到CPU的R寄存器里面。

假设当由任务A切换到任务B时,主要分为两步:

第一步:需暂停任务A的执行,并将此时任务A的寄存器(CUP的寄存器,因为正在运行的是任务A所以CUP的寄存器应该保存到任务A的任务推栈里面)保存到任务堆栈,这个过程叫做保存现场;

第二步:将任务B的各个寄存器值(被存任务堆栈中)恢复到CPU寄存器中,这个过程叫做恢复现场;

对任务A保存现场,对任务B恢复现场,这个整体的过程称之为:上下文切换

注意:任务切换的过程在PendSV中断服务函数里面完成

PendSV中断的触发

1.滴答定时器中断调用

2.执行FreeRTOS提供的相关API函数:portYIELD()

本质:通过向中断控制和状态寄存器ICSR的bit28写入1挂起PendSV来启动PendSV 中断 

xPortPendSVHandler中断服务函数

__asm void xPortPendSVHandler( void )
{
	extern uxCriticalNesting;
	extern pxCurrentTCB;
	extern vTaskSwitchContext;

	/*保存现场*/
	/*8字节对齐*/
	PRESERVE8
	/*保存PSP进程指针到R0里面,中断里面执行的是MSP主推栈指针*/
	mrs r0, psp
	isb
	/*获取任务控制块地址*/
	ldr	r3, =pxCurrentTCB		/* Get the location of the current TCB. */
	/*通过R3任务控制块的地址,获取任务控制块的值(栈顶指针)*/
	ldr	r2, [r3]
	/*压栈R4-R11*/
	stmdb r0!, {r4-r11}			/* Save the remaining registers. */
	/*把栈顶指针赋值给R2里面,在恢复任务时直接从R0直接出栈*/
	str r0, [r2]				/* Save the new top of stack into the first member of the TCB. */

	/*压栈R3R14 MSP指针,*/
	stmdb sp!, {r3, r14}
	/*获取FreeRTOS所管理的最高中断优先级*/
	mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
	/*把r0的值写到中断屏蔽寄存器里面,实现关FreeRTOS所管理的中断*/
	msr basepri, r0
	dsb
	isb
	/*执行vTaskSwitchContext函数查找下一个要运行任务的任务块*/
	bl vTaskSwitchContext
	/*赋值r0为0 */
	mov r0, #0
	/*中断屏蔽寄存器写0,实现开中断*/
	msr basepri, r0
	/*出栈R0和R14*/
	ldmia sp!, {r3, r14}
	/*vTaskSwitchContext执行这个函数后,当前任务控制块指针内容会变成下一个要执行的任务控制块地址*/
	/*获取要执行的任务控制块地址*/
	ldr r1, [r3]
	/*通过R3任务控制块的地址,获取任务控制块的值(栈顶指针)*/
	ldr r0, [r1]				/* The first item in pxCurrentTCB is the task top of stack. */
	/*出栈R4-R11*/
	ldmia r0!, {r4-r11}			/* Pop the registers and the critical nesting count. */
	/*把r0值写到PSP指针里面此时R0指针指向的是R11寄存器的地址,后硬件恢复其他寄存器*/
	msr psp, r0
	isb
	/*返回r14链接寄存,然后去执行任务B的任务函数执行任务*/
	bx r14
	nop
}

查找最高优先级任务vTaskSwitchContext函数

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 ] ) );		\
	} /* taskSELECT_HIGHEST_PRIORITY_TASK() */

FreeRTOS任务调度整个过程脑图

 

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值