UCOSIII(3)——实现任务切换的多种方式

uCOS里面触发任务切换是通过触发PendSv异常,然后在PendSv异常服务函数里面实现的。

在运行中实现任务切换的函数有两个:1、任务级任务切换 2、中断级任务切换

任务级任务切换:

OSCtxSw
    LDR     R0, =NVIC_INT_CTRL      ;把 NVIC_INT_CTRL寄存器值加载到R0 ; Trigger the PendSV exception (causes context switch)
    LDR     R1, =NVIC_PENDSVSET		;触发PendSv信号NVIC_PENDSVSET加载到R1
    STR     R1, [R0]                ;触发PendSv中断
	BX      LR

中断级任务切换:

OSIntCtxSw
    LDR     R0, =NVIC_INT_CTRL      ;把 NVIC_INT_CTRL寄存器值加载到R0 ; Trigger the PendSV exception (causes context switch)
    LDR     R1, =NVIC_PENDSVSET		;触发PendSv信号NVIC_PENDSVSET加载到R1
    STR     R1, [R0]                ;触发PendSv中断
	BX      LR

OSCtxSw 和 OSIntCtxSw 这两个是用来做任务切换的,这两个代码是一样的,它们都只是触发一个 PendSV 异常,然后在 PendSV异常服务函数里面进行任务切换。
这两个函数虽然看起来是一样的,但是他们的意义是不同的

  • OSCtxSw 是任务级切换,比如从任务 A 切换到任务B;
  • OSIntCtxSw 是中断级切换,是从中断退出时切换到一个任务中,从中断切换到任务时,CPU 的寄存器入栈工作已经完成,无需再做第二次。

比如,在OSSched (void)函数里面调用的是OSCtxSw 进行任务级的任务切换;
在OSIntExit (void)中断退出函数调用的是OSIntCtxSw 进行了中断级任务切换。

在这里先了解一下UCOS处理中断的两种方式:
uC/OS-III 有两种方法处理来自于中断的事件,直接发布(或者称为释放)和延迟发布
通过 os_cfg.h 中的 OS_CFG_ISR_POST_DEFERRED_EN 来选择。
当设置为 0 时,uCOS 使用中断直接发布;
当设置为 1 时,使用中断延迟发布。

在这里插入图片描述

一、任务级的任务切换:

关于OSCtxSw的宏定义:

#define  OS_TASK_SW()               OSCtxSw()

在void OSSched (void)函数里面调用了OS_TASK_SW()函数来触发PendSv异常。

经常用于任务级任务切换的5个函数:

  1. OSTimeDly()函数

  2. OSTimeDlyHMSM()函数

  3. OSSchedRoundRobinYield()函数
    该函数只用于在系统使用时间片轮转调度的时候,当一个任务想放弃本次时间片而把 CPU 的使用权让给同优先级下的另外一个任务的任务切换。

  4. OS_IntQTask()函数
    OS_IntQTask()函数是uCOS自己创建的,优先级为0的中断服务管理任务;该任务函数用于中断延迟发布的方式,可以将中断级发布转换成任务级发布。如果要使用中断延迟发布记得把 OS_CFG_ISR_POST_DEFERRED_EN 定义为 1。

  5. OSStartHighRdy()函数
    OSStartHighRdy()函数(汇编函数,没有调用OSCtxSw函数)触发了PendSv异常(OSStart函数调用),发生了任务切换。(OSStart函数用于开启uCOS,在定义第一个任务的结尾用到了)

二、中断级任务切换:

void OSIntExit (void)函数里面调用了OSIntCtxSw()函数来触发中断级PendSv异常。
所以在我们所有的中断服务函数的后面我们都会调用OSIntExit()函数来进行任务切换。
在uCOS中断服务函数的写法:

//**********uCOS中中断服务函数的写法**************//
void XXX_Handler(void)
{	
	if(delay_osrunning==1)					//OS开始跑了,才执行正常的调度处理
	{
		OSIntEnter();						//进入中断
		//***********中断函数的内容***********//             
		OSIntExit();       	 				//触发任务切换软中断
	}
}

uCOS里的中断服务函数只要在裸机程序的基础上再在开头和结尾加上这3条语句即可。

注意:

时间片轮转调度通过调用 OS_SchedRoundRobin()函数来完成,这个函数由OSTimeTick()或者 OS_IntQTask()调用。时间片轮转调度的调度方式取决于uCOS处理中断的方式。
1、在使用中断延时发布时,最终是在OS_IntQTask()中断服务管理函数里面发生任务级调度;
2、在使用中断直接发布时,采用中断级任务调度,在SysTick中断服务函数里面调用OSTimeTick函数(在OSTimeTick函数里面调用 OS_SchedRoundRobin函数里面对参数TimeQuantaCtr的修改)。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值