PendSVC和上下文切换业务流程

最近学习白问网韦东山老师在B站开源的freeRTOS课程,网址:韦东山直播公开课:RTOS实战项目之实现多任务系统 第1节:裸机程序框架和缺陷_哔哩哔哩_bilibili和7天物联网训练营【第2期】7天物联网智能家居实战训练营

在学习过程中按照韦老师的方法分析了下freeRTOS源码,如果有不对的地方请指证。
 

PendSVC和上下文切换业务流程源码分析,基于cubemx生成的freeRTOS工程。

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

  / *八字节对齐*/
	PRESERVE8
   
    /* 当进入PendSVC Handler时,上一个任务运行的环境即:
       xPSR,PC(任务入口地址),R14,R12,R3,R2,R1,R0(任务的形参)
       这些CPU寄存器的值会自动保存到任务的栈中,剩下的r4~r11需要手动保存 */
   
   /*获取任务的堆栈指针*/
	mrs r0, psp
	isb

	ldr	r3, =pxCurrentTCB/*加载pxCurrentTCB的地址到r3*/
	ldr	r2, [r3]        /*加载pxCurrentTCB到r2*/

	/*  浮点数处理,如果使能浮点数,就需要入栈 */
	tst r14, #0x10
	it eq
	vstmdbeq r0!, {s16-s31}

	/* 保存内核寄存器到任务堆栈 */
	stmdb r0!, {r4-r11, r14}

	
	str r0, [r2]  * 将任务栈的新的栈顶指针存储到当前任务TCB的第一个成员,即栈顶指针 */

	stmdb sp!, {r3}              /* 将R3临时压入堆栈,因为即将调用函数vTaskSwitchContext,
                                  调用函数时,返回地址自动保存到R14中,所以一旦调用发生,R14的值会被覆盖,因此需要入栈保护;
                                  R3保存的当前激活的任务TCB指针(pxCurrentTCB)地址,函数调用后会用到,因此也要入栈保护 */
								  
	/* 进入临界段 */							  
	mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY
	msr basepri, r0
	dsb
	isb
	
	/* 调用函数vTaskSwitchContext,寻找新的任务运行,通过使变量pxCurrentTCB指向新的任务来实现任务切换 */
	bl vTaskSwitchContext
	
	/*退出临界段*/
	mov r0, #0
	msr basepri, r0
	
	/*恢复r3*/
	ldmia sp!, {r3}



   /* 当前激活的任务TCB第一项保存了任务堆栈的栈顶,现在栈顶值存入R0*/
	ldr r1, [r3]
	ldr r0, [r1]

	/* 出栈. */
	ldmia r0!, {r4-r11, r14}

	/* 浮点数寄存器出栈 */
	tst r14, #0x10
	it eq
	vldmiaeq r0!, {s16-s31}
    
	
	
	/* 异常发生时,R14中保存异常返回标志,包括返回后进入线程模式还是处理器模式、
                                   使用PSP堆栈指针还是MSP堆栈指针,当调用 bx r14指令后,硬件会知道要从异常返回,
                                   然后出栈,这个时候堆栈指针PSP已经指向了新任务堆栈的正确位置,
                                   当新任务的运行地址被出栈到PC寄存器后,新的任务也会被执行。*/
	
	msr psp, r0
	isb


	bx r14
  nop
  nop
}



上下文切换
void vTaskSwitchContext( void )
{
	if( uxSchedulerSuspended != ( UBaseType_t ) pdFALSE )
	{
		/* 标记调度器状态*/
		xYieldPending = pdTRUE;
	}
	else
	{
		/* 标记调度器状态*/
		xYieldPending = pdFALSE;
	

		/* 检查任务栈是否溢出 */
		taskCHECK_FOR_STACK_OVERFLOW();

		/* 选择优先级最高的任务,把当前的任务控制块进行赋值 */
		taskSELECT_HIGHEST_PRIORITY_TASK();
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值