UCOSⅢ学习总结3:OSStart()

前两篇任务创建好,系统初始化完毕之后,就可以开始启动系统了。
手动配置优先级 启动任务切换
void OSStart (OS_ERR *p_err);—> OSTCBHighRdyPtr = OSRdyList[0].HeadPtr; —>OSStartHighRdy();

                                                  调用 OS_TASK_SW()--->触发 PendSV 异常,然后在 PendSV 异常里面实现任务的切换。
                                                      ↑

void Task1( void *p_arg );–>OSSched();—>void Task2( void *p_arg )—>OSSched();

/* 启动RTOS,将不再返回 */
void OSStart (OS_ERR *p_err)
{	
	if( OSRunning == OS_STATE_OS_STOPPED )
	{
		/* 手动配置任务1先运行,OSTCBHIghRdyPtr 指向就序列表第0个要运行的任务的TCB。OSTCBHighRdyPtr 因为暂时
不支持优先级,所以系统启动时先手动指定第一个要运行的任务。OSTCBHighRdyPtr,在OSInit()中指向优先级最高的任务 */
		OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;
		/*OSStartHighRdy()用于启动任务切换,即配置 PendSV 的优先级为最低,然后触发 PendSV 异常,在PendSV 异常服务函数中进行任务切换。 */
		OSStartHighRdy();	//(1)
		/* 不会运行到这里,运行到这里表示发生了致命的错误 */
		*p_err = OS_ERR_FATAL_RETURN;
	}
	else
	{
		*p_err = OS_STATE_OS_RUNNING;
	}
}

(1)当调用 OSStartHighRdy()函数,触发 PendSV 异常后,就需要编写 PendSV 异常服务函数,然后在里面进行任务切换。由汇编编写完成,可以只了解,只需明白任务的切换在此函数完成即可。

void main()
{
    OS_ERR err;
	/* 初始化相关的全局变量 */
	OSInit(&err);
	/* 创建任务 */
	OSTaskCreate ((OS_TCB*)      &Task1TCB,   // 指向任务控制块结构体
	              (OS_TASK_PTR ) Task1,       //任务名称
	              (void *)       0,  
	              (CPU_STK*)     &Task1Stk[0],    //任务栈基地址
	              (CPU_STK_SIZE) TASK1_STK_SIZE,  //任务栈大小
	              (OS_ERR *)     &err);

	OSTaskCreate ((OS_TCB*)      &Task2TCB, 
	              (OS_TASK_PTR ) Task2, 
	              (void *)       0,
	              (CPU_STK*)     &Task2Stk[0],
	              (CPU_STK_SIZE) TASK2_STK_SIZE,
	              (OS_ERR *)     &err);
				  
	/* 将任务加入到就绪列表 */
	OSRdyList[0].HeadPtr = &Task1TCB;
	OSRdyList[1].HeadPtr = &Task2TCB;
	
	/* 启动OS,将不再返回 */				
	OSStart(&err);
}
void Task1( void *p_arg )
{
	for( ;; )
	{
		flag1 = 1;
		delay( 100 );		
		flag1 = 0;
		delay( 100 );
		
		/* 任务切换,这里是手动切换 */		
		OSSched();
	}
}
/* 任务2 */
void Task2( void *p_arg )
{
	for( ;; )
	{
		flag2 = 1;
		delay( 100 );		
		flag2 = 0;
		delay( 100 );
		/* 任务切换,这里是手动切换 */
		OSSched();
	}
}

OSSched();讲解 OSSched()函数的调度算法很简单,即如果当前任务是任务 1,那么下一个任务就是任
务 2,如果当前任务是任务 2, 那么下一个任务就是任务 1,然后再调用 OS_TASK_SW()
函数触发 PendSV 异常,然后在 PendSV 异常里面实现任务的切换。

/* 任务切换,实际就是触发PendSV异常,然后在PendSV异常中进行上下文切换 */
void OSSched (void)
{
	if( OSTCBCurPtr == OSRdyList[0].HeadPtr )
	{
		OSTCBHighRdyPtr = OSRdyList[1].HeadPtr;
	}
	else
	{
		OSTCBHighRdyPtr = OSRdyList[0].HeadPtr;
	}
	/*OS_TASK_SW()函数其实是一个宏定义,具体是往中断及状态控制寄存器 SCB_ICSR 的位 28
	(PendSV 异常使能位)写入 1,从而触发 PendSV 异常。
	#define OS_TASK_SW() NVIC_INT_CTRL = NVIC_PENDSVSET */
	OS_TASK_SW();  
}

你可能感兴趣的:(UCOSⅢ学习总结3:OSStart())