UCOSIII中断和时间管理

Posted 想成为大师啊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UCOSIII中断和时间管理相关的知识,希望对你有一定的参考价值。

1.1、UCOSIII中断:

中断:应内部或外部异步事件的请求中止当前任务,而去处理异步事件所要求的任务的过程叫做中断。

如何在UCOSIII下编写中断服务函数!

void USART1_IRQHandler(void)

	OSIntEnter();
	// 中断服务程序
	OSIntExit();

串口中断服务函数:

void USART1_IRQHandler(void)                	//串口1中断服务程序
	
	u8 Res;
#ifdef SYSTEM_SUPPORT_OS	 	
	OSIntEnter();    
#endif
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //接收中断(接收到的数据必须是0x0d 0x0a结尾)
		
		Res =USART_ReceiveData(USART1);//(USART1->DR);	//读取接收到的数据
		
		if((USART_RX_STA&0x8000)==0)//接收未完成
			
			if(USART_RX_STA&0x4000)//接收到了0x0d
				
				if(Res!=0x0a)USART_RX_STA=0;//接收错误,重新开始
				else USART_RX_STA|=0x8000;	//接收完成了 
				
			else //还没收到0X0D
					
				if(Res==0x0d)USART_RX_STA|=0x4000;
				else
					
					USART_RX_BUF[USART_RX_STA&0X3FFF]=Res ;
					USART_RX_STA++;
					if(USART_RX_STA>(USART_REC_LEN-1))USART_RX_STA=0;//接收数据错误,重新开始接收	  
							 
				
			   		 
      
#ifdef SYSTEM_SUPPORT_OS	 
	OSIntExit();  											 
#endif

1.2、进入和退出中断服务函数:

进入中断服务函数以后使用函数 OSIntEnter()

void  OSIntEnter (void)

    if (OSRunning != OS_STATE_OS_RUNNING)                  /* Is OS running?                                         */
        return;                                             /* No                                                     */
    

    if (OSIntNestingCtr >= (OS_NESTING_CTR)250u)           /* Have we nested past 250 levels?                        */
        return;                                             /* Yes                                                    */
    

    OSIntNestingCtr++;                                      /* Increment ISR nesting level                            */

OSIntNestingCtr来记录中断嵌套次数,UCOSIII最多支持250级的中断嵌套。退出中断服务函数时要调用函数 OSIntExit()

void  OSIntExit (void)

    CPU_SR_ALLOC();



    if (OSRunning != OS_STATE_OS_RUNNING)                  /* Has the OS started?                                    */
        return;                                             /* No                                                     */
    

    CPU_INT_DIS();
    if (OSIntNestingCtr == (OS_NESTING_CTR)0)              /* Prevent OSIntNestingCtr from wrapping                  */
        CPU_INT_EN();
        return;
    
    OSIntNestingCtr--;
    if (OSIntNestingCtr > (OS_NESTING_CTR)0)               /* ISRs still nested?                                     */
        CPU_INT_EN();                                       /* Yes                                                    */
        return;
    

    if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0)         /* Scheduler still locked?                                */
        CPU_INT_EN();                                       /* Yes                                                    */
        return;
    

    OSPrioHighRdy   = OS_PrioGetHighest();                  /* Find highest priority                                  */
    OSTCBHighRdyPtr = OSRdyList[OSPrioHighRdy].HeadPtr;     /* Get highest priority task ready-to-run                 */
    if (OSTCBHighRdyPtr == OSTCBCurPtr)                    /* Current task still the highest priority?               */
        CPU_INT_EN();                                       /* Yes                                                    */
        return;
    

#if OS_CFG_TASK_PROFILE_EN > 0u
    OSTCBHighRdyPtr->CtxSwCtr++;                            /* Inc. # of context switches for this new task           */
#endif
    OSTaskCtxSwCtr++;                                       /* Keep track of the total number of ctx switches         */

#if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
    OS_TLS_TaskSw();
#endif

    OSIntCtxSw();                                           /* Perform interrupt level ctx switch                     */
    CPU_INT_EN();


2、UCOSIII临界段代码保护

临界段代码也叫做临界区,是指那些必须完整连续运行,不可被打断的代码段。当访问这些临界段代码的时候需要对这些临界段代码的时候需要对这些临界段代码进行保护。

当宏 OS_CFG_ISR_POST_DEFERRED_EN为0时,UCOSIII使用中断的方式来保护临界段代码,当设置为1的时候就会采用给调度器上锁的方式来保护临界段代码。

UCOSIII定义了一个进入临界段代码的宏:OS_CRITTICAL_ENTER(),定义了两个退出临界段代码的宏:OS_CRITICAL_EXITOS_CRITICAL_EXIT_NO_SCHED()


3、UCOSIII时间管理

3.1、任务延时:

UCOSIII中的任务是一个无限循环并且还是一个抢占式内核,为了使高优先级的任务不至于独占CPU,可以给其他优先级较低任务获取CPU使用权的机会,UCOSIII中除空闲任务外的所有任务必须在合适的位置调用系统提供的延时函数,让当前的任务暂停运行一段时间并进行一个任务切换。

延时函数有两种,OSTimeDly()OSTimeDlyHMSM()

  • OSTimeDly()函数有三种工作模式:相对模式,周期模式和绝对模式。

    void  OSTimeDly (OS_TICK   dly,
                     OS_OPT    opt,
                     OS_ERR   *p_err)
    
  • OSTimeDlyHMSM()函数仅在相对模式下工作。

    #if OS_CFG_TIME_DLY_HMSM_EN > 0u
    void  OSTimeDlyHMSM (CPU_INT16U   hours,
                         CPU_INT16U   minutes,
                         CPU_INT16U   seconds,
                         CPU_INT32U   milli,
                         OS_OPT       opt,
                         OS_ERR      *p_err)
    

3.2、取消任务的延时:

延时任务任务可通过在其他任务调度函数 OSTimeDlyResume() 取消延时而进入就绪状态,此函数最后会引发一次任务调度。

3.3、获取和设置系统时间:

UCOSIII定义了一个 CPU_INT32U类型的全局变量 OSTickCtr来记录系统时钟节拍数,在调用OSInit() 时被初始化为0,以后每发生1个时钟节拍,OSTickCtr加1。

  • OSTimeSet() 允许用户改变当前时钟节拍计数器的值,慎用!!!
  • OSTimeGet()用来获取动迁时钟节拍计数器的值。

以上是关于UCOSIII中断和时间管理的主要内容,如果未能解决你的问题,请参考以下文章

UCOSIII消息队列

UCOSIII消息队列

UCOSIII中的节拍列表更新

uCOs 学习:0-有关概念

UCOSIII信号量和互斥信号量

UCOSIII信号量和互斥信号量