uCOS

uCOS为可剥性型实时操作系统,顾名思义可剥夺型意为:
① 在系统的运行过程中高优先级任务可剥夺低优先级任务的CPU使用权。
② 低优先级任务不可打断高优先级任务。
在uCOS操作系统中,多个任务的优先级不同,而在系统的运行过程中,uCOS总是在任务就绪表里面寻找最高优先级的任务来执行

#define OS_TICKS_PER_SEC 200u /* 在一秒内设置节拍数,每次间隔5ms产生一次节拍中断 */

*************************************************
(正点原子UCOSII例程)
调用该delay_init()函数后,程序每隔5ms会产生一次中断,如下

//systick中断服务函数,使用ucos时用到
void SysTick_Handler(void)
{	
	if(delay_osrunning==1)		//OS开始跑了,才执行正常的调度处理
	{
		OSIntEnter();			//进入中断
		OSTimeTick();       	//调用ucos的时钟服务程序               
		OSIntExit();       	 	//触发任务切换软中断
	}
}

OSIntExit(); 这个函数中会发生任务调度,事实上,为了保证系统的实时性,实时操作系统时钟中断里面和任何的中断退出时都会产生调度。(多重中断嵌套,必须是完全退出时)

void delay_us(u32 nus)     //这个延时不会被节拍中断打断
{		
	u32 ticks;
	u32 told,tnow,tcnt=0;
	u32 reload=SysTick->LOAD;			//LOAD的值	    	 
	ticks=nus*fac_us; 					//需要的节拍数	  		 
	tcnt=0;
	OSSchedLock();			 //阻止OS调度,防止打断us延时
	told=SysTick->VAL;        		 //刚进入时的计数器值
	while(1)
	{
		tnow=SysTick->VAL;	
		if(tnow!=told)
		{	//这里注意一下SYSTICK是一个递减的计数器就可以了.    
			if(tnow<told)tcnt+=told-tnow;	
			else tcnt+=reload-tnow+told;	    
			told=tnow;
			if(tcnt>=ticks)break;	//时间超过/等于要延迟的时间,则退出.
		}  
	};
	OSSchedUnlock();				//恢复OS调度									    
}

OSSchedLock(); 只是阻止OS任务调度,并没有关闭系统每5ms产生的中断,所以在while循环中仍然可以进入中断,但不会发生任务调度,确保delay_us延时的准确性,OSSchedLock()和OSSchedUnlock()函数必须成对出现。

阻止OS任务调度实现方法:对 OSLockNesting++(多任务锁嵌套级别)

void  OSIntExit (void)
{
#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register */
    OS_CPU_SR  cpu_sr = 0u;
#endif
    if (OSRunning == OS_TRUE) 
    {
        OS_ENTER_CRITICAL();       //关闭中断
        if (OSIntNesting > 0u) 
        {                  
            OSIntNesting--;
        }
        if (OSIntNesting == 0u)  /*中断嵌套级别 */
        {           
            if (OSLockNesting == 0u)   /*多任务锁嵌套级别 */
            {         
            	OS_SchedNew();   //任务调度
           		......
            }
        }
        OS_EXIT_CRITICAL();      //打开中断
    }
}

UCOS在什么时候发生任务调度及任务调度时间点
1.使用UCOS延时函数OSTimedly()或者OSTimeDlyHMSM()。
2.释放信号量或者发送消息。
3.任务等待的事情还没有发生,如等待信号量,消息队列等。
4.任务取消等待。
5.创建任务,删除任务。
6.删除一个内核对象。
7.任务改变自身的优先级或者其他任务的优先级。
8.调用OSTaskSuspend()将自己挂起。
9.任务解除被挂起的任务。
10.退出所有的嵌套中断,中断嵌套级别 OSIntNesting=0。
11.任务锁嵌套OSLockNesting=0。
*************************************************
使用UCOS读取DS18B20时,时序很重要,避免发生任务调度,破坏时序,虽然使用了delay_us(),但是TEMP_DATA_OUT=1; … 等语句仍然可以被节拍中断打断,产生任务调度,可以使用OSMutexPend(mutex,0,&err)提高任务优先级,防止任务调度。

uint8_t DS18_Init()
{
	uint8_t flag=0;
	OSMutexPend(mutex,0,&err);    //提高优先级
	TEMP_IO_OUT();        //输出方向
	
	TEMP_DATA_OUT=1;             
	delay_us(2);
	TEMP_DATA_OUT=0;             
	delay_us(500);
    TEMP_DATA_OUT=1;             
	
	TEMP_IO_IN();       //输入方向
	delay_us(50);
	if(TEMP_DATA_IN==0) flag=1;   //ds18b20拉低总线,告诉主机本器件已做好准备  GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_9)==0
	else 				flag=0;
	delay_us(480);
	TEMP_DATA_OUT=1;
	OSMutexPost(mutex);     //恢复优先级
	return flag;
}

你可能感兴趣的:(ucos,stm32)