uCOS-Ⅲ学习笔记:任务定义与切换

举报
JeckXu666 发表于 2022/01/18 01:10:46 2022/01/18
【摘要】 任务的定义与切换的实现 1. 创建任务1.1 定义任务堆栈1.2 定义任务函数1.3 定义任务控制块1.4 实现任务创建函数1.5 任务堆栈初始化函数1.6 就绪列表 2. OS系统初始化3....

1. 创建任务

1.1 定义任务堆栈

1.栈是RAM内一段连续内存
2.定义任务栈就是给函数定义一个数组:

static     CPU_STK       Task1Stk[TASK1_STK_SIZE]
 
  • 1

1.2 定义任务函数

每个任务函数必须是一个死循环,其内必须有阻塞延时函数以进行任务调度!!!

1.3 定义任务控制块

定义一个结构体,里面可以存放每个任务的堆栈,名称,形参等等参数,对任务的操作都可以通过这个TCB来实现

struct os_tcb 
{
    CPU_STK            *STKPTR
    CPU_STK_SZIE StkSize
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

1.4 实现任务创建函数

把任务堆栈、任务实体、任务的TCB联系起来的函数

void OSTaskCreate
			 (
	                  OS_TCB *p_tcb, 
	                  OS_TASK_PTR   p_task, 
	                  void          *p_arg,
	                  CPU_STK       *p_stk_base,
	                  CPU_STK_SIZE  stk_size,
	                  OS_ERR        *p_err
	   			 );
   			 {
				CPU_STK *p_sp;
				p_sp=OSTaskStkInit(//返回的栈顶指针
													p_task,		
													p_arg,
													p_stk_base,
													stk_size
													);
				//把栈顶指针和栈大小给到tcb里面
				p_tcb->StkPtr = p_sp;
				p_tcb->StkSize= stk_size;
			}			

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

参数介绍:
OS_TCB -任务TCB
OS_TASK_PTR -任务指针
*p_arg -参数指针
CPU_STK -堆栈基地址
CPU_STK_SIZE -堆栈大小
OS_ERR -错误枚举

1.5 任务堆栈初始化函数

该函数第一次运行时使用,把堆栈的数据预加载到CPU的寄存器

CPU_STK *OSTaskStkInit 
			(
	              OS_TASK_PTR    p_task,
	               void         *arg,
	               CPU_STK      *p_stk_base,
	               CPU_STK_SIZE   stk_size);
			{
				CPU_STK  *p_stk;
				p_stk = &p_stk_base[stk_size];
			   以下只适合Coterx-M3
																		/* 异常发生时自动保存的寄存器                              */
				*--p_stk = (CPU_STK)0x01000000u;                        /* xPSR的bit24必须置1                                     */
				*--p_stk = (CPU_STK)p_task;                             /* 任务的入口地址                                         */
				*--p_stk = (CPU_STK)0x14141414u;                        /* R14 (LR)                                               */
				*--p_stk = (CPU_STK)0x12121212u;                        /* R12                                                    */
				*--p_stk = (CPU_STK)0x03030303u;                        /* R3                                                     */
				*--p_stk = (CPU_STK)0x02020202u;                        /* R2                                                     */
				*--p_stk = (CPU_STK)0x01010101u;                        /* R1                                                     */
				*--p_stk = (CPU_STK)p_arg;                              /* R0 : 任务形参                                          */
																		/* 异常发生时需手动保存的寄存器                            */
				*--p_stk = (CPU_STK)0x11111111u;                        /* R11                                                    */
				*--p_stk = (CPU_STK)0x10101010u;                        /* R10                                                    */
				*--p_stk = (CPU_STK)0x09090909u;                        /* R9                                                     */
				*--p_stk = (CPU_STK)0x08080808u;                        /* R8                                                     */
				*--p_stk = (CPU_STK)0x07070707u;                        /* R7                                                     */
				*--p_stk = (CPU_STK)0x06060606u;                        /* R6                                                     */
				*--p_stk = (CPU_STK)0x05050505u;                        /* R5                                                     */
				*--p_stk = (CPU_STK)0x04040404u;                        /* R4                                                     */
				return (p_stk);
			}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

1.6 就绪列表

该列表存放已经就绪的列表,表示其中的任务可以进行调度

					struct os_rdy_list
					{
						OS_TCB        *HeadPtr;
						OS_TCB        *TailPtr;
					};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

2. OS系统初始化

OSRuning存放系统任务运行状态
OSTCBCurPtr和OSTCBHighRdyPtr是当前任务指针以及最高任务指针

本函数主要初始化清零,初始化就绪列表(清零列表)和空闲任务

		void OSInit (OS_ERR *p_err)
		{
			OSRunning =  OS_STATE_OS_STOPPED;
			
			OSTCBCurPtr = (OS_TCB *)0;//当前任务控制块指针
			OSTCBHighRdyPtr = (OS_TCB *)0;//最高优先级指针
			
			OS_RdyListInit();//就绪列表初始化,列表清零
			//初始化空闲任务
			OS_IdleTaskInit(p_err);
			*p_err = OS_ERR_NONE;//执行到这无报错
		}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

3. 启动系统

系统启动,配置最高任务TCB指针,在下一个TICK中切换

void OSStart (OS_ERR *p_err)
{	
	if( OSRunning == OS_STATE_OS_STOPPED )
	{
		/* 手动配置任务1先运行 */
		OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;
		
		/* 启动任务切换,不会返回 --汇编.s文件里面*/
		OSStartHighRdy();
		
		/* 不会运行到这里,运行到这里表示发生了致命的错误 */
		*p_err = OS_ERR_FATAL_RETURN;
	}
	else
	{
		*p_err = OS_STATE_OS_RUNNING;
	}
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

4. 任务切换

该函数把就绪列表最高任务赋给下一个最高就绪优先级
(OS_TASK_SW()函数用于把PENDSV异常在中断标志中置位,使之进入PENDSV中断,开启上下文切换)
OS_CRITICAL_ENTER() 开启屏蔽中断—使进入上下文切换不被打断

void OSSched (void)
{
	CPU_SR_ALLOC();
	OS_CRITICAL_ENTER();
	
	OSPrioHighRdy = OS_PrioGetHighest();
 	OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;
	if(OSTCBCurPtr == OSTCBHighRdyPtr)
	{
		OS_CRITICAL_EXIT();
		return;
	}
	
			OS_CRITICAL_EXIT();
	//任务切换
	OS_TASK_SW();
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

5. MAIN函数

1—初始化相关变量
2—创建任务
3—任务添加到就绪列表
4—启动OS

6. 参考资料教程

野火UCOS-Ⅲ教程
UCOS-Ⅲ内核实现与应用开发实战指南-基于STM32
正点原子开发板

文章来源: blog.csdn.net,作者:JeckXu666,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq_45396672/article/details/109278913

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。