FreeRTOS(三)任务切换

taskYIELD()任务切换

#define taskYIELD()                        portYIELD()	
#define portYIELD()															\
{																				\
	/* 向中断控制寄存器bit28位写入1,将PendSV中断设置为挂起状态,
	等到优先级高于PendSV的中断执行完成后,PendSV中断服务函数将被执行,进行任务切换工作 */								\
	portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;								\
																				
	__dsb( portSY_FULL_READ_WRITE );											\
	__isb( portSY_FULL_READ_WRITE );											\
}

xPortPendSVHandler( )中断服务函数

__asm void xPortPendSVHandler( void )
{
	extern uxCriticalNesting;       /*临界段嵌套计数器,初始化为0xaaaaaaaa,调度器启动后初始化为0,每进入一次临界段+1*/
	extern pxCurrentTCB;            /* 指向当前激活的任务 */
	extern vTaskSwitchContext;      
 
 
	PRESERVE8
 
 
	mrs r0, psp                   /* PSP内容存入R0 */    
	isb                           /* 指令同步隔离,清流水线 */
 
	ldr	r3, =pxCurrentTCB     /* 将当前指向的TCB的地址赋给R3 */
	ldr	r2, [r3]           	  /* 将TCB赋给R2 */
 
	stmdb r0!, {r4-r11}          /* 以r0为基址,指针先递减再操作,保存r4-r11寄存器入栈,并更新r0的值,r0最终指向r4*/
	str r0, [r2]		     /* 将栈顶指针赋给r0 */
 
	stmdb sp!, {r3, r14}         /* 将R3和R14临时压入堆栈,因为即将调用函数vTaskSwitchContext,调用函数时,返回地址自动保存到R14中,所以一旦调用发生,
	                            R14的值会被覆盖,因此需要入栈保护; R3保存的当前激活的任务TCB指针(pxCurrentTCB)地址,函数调用后会用到,因此也要入栈保护*/
	mov r0, #configMAX_SYSCALL_INTERRUPT_PRIORITY   
	msr basepri, r0              /* 屏蔽中断,进入临界区 */
	dsb                         /* 数据和指令同步隔离 */
	isb
	bl vTaskSwitchContext        /* 调用函数,寻找新的任务运行,通过使变量pxCurrentTCB指向新的任务来实现任务切换 */
	mov r0, #0                   /* 开中断,退出临界区*/
	msr basepri, r0
	ldmia sp!, {r3, r14}         /* 恢复R3和R14*/ 
 
	ldr r1, [r3]             /* 将TCB赋给r1*/
	ldr r0, [r1]		     /* 将当前激活的任务TCB的栈顶指针存入R0*/
	ldmia r0!, {r4-r11}	     /* r4-r11出栈*/
	msr psp, r0               /*更新psp指针的值,将最新的栈顶指针赋给psp*/
	isb
	bx r14                      /* 异常发生时,R14中保存异常返回标志,包括返回后进入线程模式还是处理器模式、使用PSP堆栈指针还是MSP堆栈指针,
	                             当调用 bx r14指令后,硬件会知道要从异常返回,然后出栈,这个时候堆栈指针PSP已经指向了新任务堆栈的正确位置,
	                             当新任务的运行地址被出栈到PC寄存器后,新的任务也会被执行。*/
	nop
}

taskSELECT_HIGHEST_PRIORITY_TASK()寻找最高优先级任务
vTaskSwitchContext()函数实际上是调用
taskSELECT_HIGHEST_PRIORITY_TASK()这个函数

	#define taskSELECT_HIGHEST_PRIORITY_TASK()														\
	{																								\
	UBaseType_t uxTopPriority;																		\
																									\
		/* 寻找最高优先级并加入就绪列表中 */								\
		portGET_HIGHEST_PRIORITY( uxTopPriority, uxTopReadyPriority );								\
		/* 就绪列表中找到最高优先级任务的TCB,然后更新到 pxCurrentTCB */
		listGET_OWNER_OF_NEXT_ENTRY( pxCurrentTCB, &( pxReadyTasksLists[ uxTopPriority ] ) );		\
	} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值