ucos记录

使用ucos目的:实现多任务,因此必须保证多个任务都能得到CPU时间运行,所以程序中必须要有任务切换调度。

任务调度切换发生时机:

1.主动进行任务切换:

一般在任务中调用延时函数,比如OSTimeDly(ticks),此时会主动让出CPU,执行一次任务调度,选择最高优先级且为就绪状态的任务运行。

2.在滴答时钟中断中:

多任务的延时是以滴答时钟延时为基本单位,每次产生滴答时钟中断,会遍历每个任务,如果有任务存在延时,则会将相应的延时减1.

滴答时钟中断退出后,会执行OSIntExit();  此时会发生任务切换,执行一次任务调度,选择最高优先级且为就绪状态的任务运行。


所以程序中设计应该关注以下几点:

1.合理分配滴答时钟中断时间,不能太长,也不能太短,一般选取10ms左右。即1秒内产生100次中断,有一百次任务切换机会。

2.合理分配任务优先级,每个任务应当在合适的时机主动让出CPU,因此每个任务要主动调用OSTimeDly(ticks)。

3.每个任务的堆栈大小安排要合理,任务中如果使用大量局部数组,可能会造成堆栈溢出,可以考虑加大堆栈容量。

4.堆栈一板设置如下:

OS_STK START_TASK_STK[START_STK_SIZE];

但是,如果使用了Microlib 库后,printf 等函数对浮点数的处理会出现非预期值, 这时候必须在使用的堆栈前8字节对齐__align(8)。

__align(8) OS_STK START_TASK_STK[START_STK_SIZE];

其中滴答时钟中断设置函数如下:

以STM32为例:系统时钟频率为72MHZ,实现5ms的滴答延时。

SystemCoreClock = 72000000 // 72MHZ
OS_TICKS_PER_SEC = 200  //1秒内200次中断,即每次5ms
void SysTick_Init(void)	 
{
	u32 reload;
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	//选择外部时钟 HCLK/8,即 SysTick_CLK = 72/8 = 9MHZ 
	fac_us=SystemCoreClock/8000000;	//为系统时钟的1/8  这里fac_us = 9,即1us计数9次
	 
	reload=SystemCoreClock/8000000;	//92000000/8000000=9 相当于 1us 计数9次   
	reload*=1000000/OS_TICKS_PER_SEC;//根据OS_TICKS_PER_SEC设定溢出时间 , 此时reload = 9*5000 次, 除以9 = 5000us=5ms, 即 定时器中断为5ms
					 //reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右	
	fac_ms=1000/OS_TICKS_PER_SEC;//代表ucos可以延时的最少单位	   这里fac_ms = 5
	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;   	//开启SYSTICK中断
	SysTick->LOAD=reload; 	//每1/OS_TICKS_PER_SEC秒中断一次	,即5ms中断一次
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;   	//开启SYSTICK    
}					
两个延时函数:
void delay_ms(u16 nms)
{	
	if(OSRunning==TRUE)//如果os已经在跑了	    
	{		  
		if(nms>=fac_ms)//延时的时间大于ucos的最少时间周期 
		{
   			OSTimeDly(nms/fac_ms);//ucos延时,里面会进行任务调度
		}
		nms%=fac_ms;				//ucos已经无法提供这么小的延时了,采用普通方式延时    
	}
	delay_us((u32)(nms*1000));	//普通方式延时,此时ucos无法启动调度.
}
如果使用ms级延时必须要在5ms以上的延时才能做到任务切换,也就是延时必须要大于一个滴答中断周期。
void delay_us(u32 nus)
{		
	u32 ticks;
	u32 told,tnow,tcnt=0;
	u32 reload=SysTick->LOAD;	//LOAD的值	    	 
	ticks=nus*fac_us; 			//需要的节拍数	  		 
	tcnt=0;
	told=SysTick->VAL;        	//刚进入时的计数器值
	while(1)
	{
		tnow=SysTick->VAL;	      //当前计数值
		if(tnow!=told)
		{	    
			if(tnow<told)
				tcnt+=told-tnow;//这里注意一下SYSTICK是一个递减的计数器就可以了.
			else 
				tcnt+=reload-tnow+told;	    
			told=tnow;
			if(tcnt>=ticks)break;//时间超过/等于要延迟的时间,则退出.
		}  
	}; 									    
}

中断函数:

void SysTick_Handler(void)
{
    OSIntEnter();	//进入中断
    OSTimeTick();       //调用ucos的时钟服务程序,遍历任务,将任务的等待延时减1           
    OSIntExit();        //触发任务切换软中断,会进行任务调度
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值