⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pg_task.c

📁 一个移植到凌阳单片机spce061a上面的实时操作系统
💻 C
字号:
///////////////////////////////////////////////////////////////
//
//
//   PGOS : A Portable,Configable Embedded System Kernel
//
//           
//
//   This is an open source project under GPL lincence  
//
//        Version 0.9.0 ---- Development Snopshot
//
//   File name : pg_task.c : Task functions implemention  
//   History :
//
//          2005-07-24  First build by X.K. @ PGOS Team
//          2005-08-09  Fix a bug in pgos_tk_cre
//          2005-08-09  Upgrade for programming style
//          2005-08-21  Fix a bug in pgos_tk_switch 
//   Note : 
//           pgos_tk_remove still has a little bug need to fix 
/////////////////////////////////////////////////////////////////

#include <stdlib.h>
#include "pgos.h"

    /******************************
     TK_SWITCH() is a macro here. 
     And in your porting code ,
     it also must be a MACRO .
    ******************************/
#define  TK_SWITCH()   __asm("break")


pgTASKLIST*     task_freelist ;      // points to the task pre lists
pgTASKLIST*     task_list ;          // points to the task lists tail
pgTASKLIST*     task_list_head ;     // points to the task lists head
pgTASKSEARCH*   task_table ;         // task entry table
extern pgTASK*  task_nxt ;           // task which is next to run
pgTASK*  task_cur ;                  // task which is current running
extern pgTASK*  task_prv ;           // task which is last run 

BYTE  task_cur_id ;                  // current running task id 
BYTE  task_cur_prio ;                // current running task prio
BYTE  task_nxt_id ;                  // next run task id
BYTE  task_nxt_prio ;                // next run task prio 
BYTE  tasknum ;                      // total number of the task(s)
extern  BYTE schedular ;             
extern  BYTE pgos_running ;

#if PG_SCH_ROUNDROBIN == 1
DWORD  maxtime ;
#endif

#if PG_STAT_SUPPORT == 1
extern DWORD  task_sw ;
#endif

#if  PG_TASK_BASIC_SUPPORT == 1
////////////////////////////////////////////////////
//
//pgos_tk_cre
// 
//  Create a task and insert it to the task list .
//  if successful,returns PGOS_SUCCESS 
//
////////////////////////////////////////////////////
PGOS_STATUS  pgos_tk_cre( VOID ( *task )(), BYTE prio, REGSZ* stk, BYTE* id )
{
   pgTASK*  Task ;
   pgos_int_disable() ;
   if( tasknum == MAXTASK )
      return  PGOS_FAIL_OV ; // task too many
   // Alloc memory for task
   if( task_freelist->next == NULL )
      return  PGOS_FAIL_MEM ;
   stk = pgos_tk_initstk( stk,task ) ;
   if( task_list == NULL )
   {
   	  task_list = task_freelist ;
	  task_list_head = task_list ;
   }
   else
   {
   	  task_list->next = task_freelist ;
	  task_list = task_list->next ;
   }
   task_freelist = task_freelist->next ;
   task_list->next = NULL ;
   Task = task_list->pTask ;
   // Initliaze the task
   Task->pgSP = stk ;
   Task->id = tasknum ;
   *id = tasknum ;
   tasknum ++ ;
   Task->prio = prio ;
   Task->state = PG_READY ;
   Task->delay = 0 ;

#if  PG_MSG_SUPPORT == 1
   Task->pgMessage->uflag = MSG_NEW ;
   Task->pgMessage->rflag = MSG_NO_READ ;
   Task->pgMessage->m_msg = PGOS_MMSG_Create ;
   Task->pgMessage->From = MSG_PGOS_SEND ;
   Task->pgMessage->To = MSG_TASK_RECV | Task->id ;
#if PG_DRV_SUPPORT == 1
   pgos_call_drv( SYS_MSG_S, ( void * )Task->pgMessage ) ;
#endif // end of PG_DRV_SUPPORT
#endif // end of PG_MSG_SUPPORT

#if  PG_SCH_ROUNDROBIN == 1
   Task->runtime = 0 ;
#endif
   pgos_tk_insert( Task ) ;
   
#if  PG_DRV_SUPPORT == 1
      pgos_call_drv( SYS_TK_C, NULL ) ;
#endif
    
   if( pgos_running == 1 )
   {
         pgos_int_enable() ;
	  if( prio > task_cur_prio )
	  {
	       pgos_tk_switch() ;
	  }
	  else
	  {
	       return  PGOS_SUCCESS ;
	  }
   }
   
   return PGOS_SUCCESS ;
}


////////////////////////////////////////////////////////
//
//pgos_tk_sleep
//
//  Make a task sleep .
//
////////////////////////////////////////////////////////
PGOS_STATUS  pgos_tk_sleep( BYTE id, WORD time )
{
   pgTASK*  pTask ;
   pgos_int_disable() ;
   pTask = pgos_tk_lookup( id ) ;
   if( !pTask )
   {
      pgos_int_enable() ;
      return  PGOS_FAIL_NM ;
   }
   pTask->state = PG_SLEEP ;
   pTask->delay = time ;
   if( id ==  task_cur_id )
   {
      pgos_tk_switch() ;
   }
   pgos_int_enable() ;
   return PGOS_SUCCESS ;
}

////////////////////////////////////////////////////////
//
//pgos_tk_wakeup
//
//  Wakeup a task .
//
/////////////////////////////////////////////////////////
PGOS_STATUS  pgos_tk_wakeup( BYTE id )
{
   pgTASK*  pTask ;
   pgos_int_disable() ;
   pTask = pgos_tk_lookup( id ) ;
   if( !pTask || pTask->state != PG_SLEEP )
   {
      pgos_int_enable() ;
      return  PGOS_FAIL_NM ;
   }
   pTask->state = PG_READY ;
   pTask->delay = 0 ;
   if( pTask->prio > task_cur_prio )
   {
      task_cur->state = PG_READY ;
      pgos_tk_switch() ;
   }
   pgos_int_enable() ;
   return PGOS_SUCCESS ;
}

PGOS_STATUS  pgos_tk_suspend( BYTE id )
{
   pgTASK*  pTask ;
   pgos_int_disable() ;
   pTask = pgos_tk_lookup( id ) ;
   if( !pTask )
   {
      pgos_int_enable() ;
      return  PGOS_FAIL_NM ;
   }
   pTask->state = PG_SUSPEND ;
   if( id == task_cur_id )
   {
      pgos_tk_switch() ;
   }
   pgos_int_enable() ;
   return PGOS_SUCCESS ;
}

PGOS_STATUS  pgos_tk_resume( BYTE id )
{
   pgTASK*  pTask ;
   pgos_int_disable() ;
   pTask = pgos_tk_lookup( id ) ;
   if( !pTask )
   {
      pgos_int_enable() ;
      return  PGOS_FAIL_NM ;
   }
   pTask->state = PG_READY ;
   if( pTask->prio > task_cur_prio )
   {
      task_cur->state = PG_READY ;
      pgos_tk_switch() ;
   }
   pgos_int_enable() ;
   return PGOS_SUCCESS ;
}

PGOS_STATUS  pgos_tk_remove( BYTE id )
{
  pgTASK*      pTask = NULL ;
	pgTASKLIST*  pListNext = NULL ;
	pgTASKLIST*  pListPrv = NULL ;
	pgTASKLIST*  pList = NULL ;
	
  pgos_int_disable() ;
  
	pTask = pgos_tk_lookup( id ) ;
	if( !pTask )
		return PGOS_FAIL_NM ;

	pList = task_list_head ;
	if(  pTask->id == task_cur_id )
		return PGOS_FAIL_NM ;

	if(  pTask == pList->pTask )
	{
	     if( pList->next == NULL )
	     {
	     	 free( pTask->pgSP ) ;
		     free( pTask ) ;
		     free( pList ) ;
		     #if  PG_DRV_SUPPORT == 1
           pgos_call_drv( SYS_TK_R, NULL ) ;
         #endif 
		     // Even the idle task is removed
		     for( ;; ) ; 	 
	     }
	     else
	     {
	       pListNext = pList->next ;
		     free( pTask->pgSP ) ;
		     free( pTask ) ;
		     free( pList ) ;
		     task_list_head = pListNext ;
	     }

       pgos_int_enable() ;
       #if  PG_DRV_SUPPORT == 1
          pgos_call_drv( SYS_TK_R, NULL ) ;
       #endif 
	     return PGOS_SUCCESS ;
  }

	pListPrv = pList ;
	for( ; pList ; pList = pList->next )
	{
	     	  if(  pList->pTask == pTask )
	     	  {
	     	        if( pList->next->next != NULL )
	     	        {
	     	                pListNext = pList->next->next ;
				                free( pTask->pgSP ) ;
				                free( pTask ) ;
				                pListPrv->next = pListNext ;
				                free( pList ) ;
	     	        }
			          else
			          {
			                     free( pTask->pgSP ) ;
				                 free( pTask ) ;
				                 pListPrv->next = NULL ;
				                 free( pList ) ;
			          }
                #if  PG_DRV_SUPPORT == 1
                  pgos_call_drv( SYS_TK_R, NULL ) ;
                #endif 
			          pgos_int_enable() ;
		            return PGOS_SUCCESS ;
	     	  }
          pListPrv = pList ;
	}

  pgos_int_enable() ;
	return PGOS_FAIL_NM ;
}

pgTASK*   pgos_tk_lookup( BYTE id )
{
   if( id <= tasknum )
     return  *(&task_table[ id ].pTask) ;
   return NULL ;
}

pgTASK*  pgos_tk_alloc()
{
   pgTASK* pTask ;
   pTask = ( pgTASK* )malloc( sizeof( pgTASK ) ) ;
   if( !pTask )
     return NULL ;

#if PG_MSG_SUPPORT == 1
   pTask->pgMessage = ( pgMSG * )malloc( sizeof( pgMSG ) ) ;
   if( !pTask->pgMessage )
     return NULL ;
#endif

   return pTask ;
}

pgTASKLIST*  pgos_tk_listalloc()
{
   pgTASKLIST* pList ;
   pList = ( pgTASKLIST* )malloc( sizeof( pgTASKLIST ) ) ;
   if( !pList )
      return NULL ;
   pList->pTask = pgos_tk_alloc() ;
   if( !pList->pTask ) 
      return NULL ;
   return pList ;    
}

pgTASKLIST*  pgos_tk_inilist()
{
   BYTE index ;
   pgTASKLIST* list ;
   pgTASKLIST* list_head ;
   list = pgos_tk_listalloc() ;
   if( !list )
      return NULL ;
   list_head = list ;
   for( index = 0 ;index < MAXTASK ;index ++ )
   {
      list->next = pgos_tk_listalloc() ;
      if( !list->next )  
	        return NULL ;
      list = list->next ;
      list->next = NULL ;
   }

   task_list = NULL ;
   task_list_head = NULL ;
   tasknum = 0 ;

   return list_head ;
}

PGOS_STATUS  pgos_tk_initab( )
{
     task_table = ( pgTASKSEARCH * )malloc( sizeof( pgTASKSEARCH ) * MAXTASK ) ;
     if( !task_table )
	       return PGOS_FAIL_MEM ;
     return PGOS_SUCCESS ;
}

VOID  pgos_tk_insert( pgTASK* pTask )
{
     pgos_int_disable() ;
     task_table[ pTask->id ].pTask = pTask ;
	 pgos_int_enable() ;
}

VOID  pgos_tk_switch()
{     
     pgTASKLIST*  tlist = NULL ;
     
     // If the schedular is locked
     if( schedular == PG_SCH_LOCK ) return ;
     tlist = task_list_head ;
     task_nxt = tlist->pTask ;
     task_nxt_prio = task_nxt->prio ;
	   	
     for( ; tlist ; tlist = tlist->next )
     {
          if( tlist->pTask->state == PG_READY )
          {
             if( task_nxt_prio < tlist->pTask->prio )
             {
                  task_nxt_prio = tlist->pTask->prio ;
                  task_nxt = tlist->pTask ;
             }
          }
     }

#if  PG_SCH_ROUNDROBIN == 1
     task_cur->runtime = 0 ;
#endif

     task_prv = task_cur ;
     task_cur = task_nxt ;
     task_cur_id = task_nxt->id ;
     task_cur_prio = task_nxt_prio ;
     task_nxt->state = PG_RUN ;	  

#if PG_STAT_SUPPORT == 1
     task_sw ++ ;
#endif

#if  PG_DRV_SUPPORT == 1
     pgos_call_drv( SYS_TK_SW, NULL ) ;
#endif 

     TK_SWITCH() ;
}

#endif  // TASK_BASIC_SUPPORT

#if  PG_TASK_ADV_SUPPORT == 1
VOID   pgos_tk_resumeall() 
{
      pgTASK*  pTask ;
      pgTASKLIST*  pList = task_list_head ;

      pgos_int_disable() ; 	  
      task_nxt_prio = pList->pTask->prio ;	  
      for( ; pList ; pList = pList->next )
      {
           pTask = pList->pTask ;
           if( pTask->state == PG_SUSPEND )
           {
                pTask->state = PG_READY ;
		            if( pTask->prio > task_nxt_prio )
		  	          task_nxt_prio = pTask->prio ;
           }
      }

	    if( task_nxt_prio != task_cur_prio )
	    {
	       task_cur->state = PG_READY ;
	       pgos_tk_switch() ;
	    }

	    pgos_int_enable() ;
}

		
BYTE  pgos_tk_getnum()
{
     return  tasknum - 1 ;
}

BYTE  pgos_tk_getcurid( ) 
{
     return  task_cur_id ;
}

BYTE  pgos_tk_getkmax()
{
     return MAXTASK ;
}

VOID  pgos_tk_sleep_sec( WORD sec )
{
   pgos_tk_sleep( task_cur_id, 200 * sec ) ;
}

#endif  // TASK_ADV_SUPPORT

#if  PG_MSG_SUPPORT == 1
PGOS_STATUS  pgos_tk_sendmsg( BYTE id, WORD m_msg, WORD s_msg )
{
  pgTASK*  pTask ;
	pgMSG*   pMsg ;   

  pgos_int_disable() ;
	pTask = pgos_tk_lookup( id ) ;
	if( !pTask )
	{
	       pgos_int_enable() ;
		return PGOS_FAIL_NM ;
	}
	pMsg = pTask->pgMessage ;
#if PG_MESSAGE_UNBLK == 1
	if( pMsg->rflag == MSG_NO_READ )
	{
	       pgos_tk_sleep( task_cur_id,10 ) ;
		if(  pMsg->rflag == MSG_NO_READ )
		{
	       pgos_int_enable() ;
		     return PGOS_FAIL_NM ;
		}
	}
#else
#if PG_MESSAGE_BLOCK == 1
  while( pMsg->rflag == MSG_READ_OK )
  {
  	  pgos_tk_sleep( task_cur_id,10 ) ;
  }
#else
#error Error in PG_CFG.H ........
#endif // end of BLOCK mode
#endif // end of UNBLK Mode
	pMsg->uflag = MSG_NEW ;
	pMsg->rflag = MSG_NO_READ ;
	pMsg->m_msg = m_msg ;
	pMsg->s_msg = s_msg ;
	pMsg->From = MSG_TASK_SEND | ( WORD )task_cur_id ;
	pMsg->To = MSG_TASK_RECV | ( WORD )id ;
	#if  PG_DRV_SUPPORT == 1
      pgos_call_drv( SYS_MSG_S, ( void * )pMsg ) ;
  #endif 
  pgos_int_enable() ;
	return PGOS_SUCCESS ;
}

PGOS_STATUS  pgos_tk_getmsg( WORD*  m_msg, WORD* s_msg, WORD* Sender )
{
   pgMSG*  pMsg ;

	 pgos_int_disable() ;
   pMsg = task_cur->pgMessage ;
#if PG_MESSAGE_UNBLK == 1
	 if( pMsg->uflag == MSG_OLD )
	 {
	        pgos_tk_sleep(  task_cur_id,10 ) ;
		 if(  pMsg->uflag == MSG_OLD  )
		 {
	            pgos_int_enable() ;
		     return PGOS_FAIL_NM ;
		 }
	 }
#else
#if PG_MESSAGE_BLOCK == 1
   while( pMsg->uflag == MSG_NEW && pMsg->rflag == MSG_NO_READ )
   {
   	   pgos_tk_sleep(  task_cur_id,10 ) ;
   }
#else
#error Error in PG_CFG.H............
#endif // end of BLOCK Mode
#endif // end of UNBLK Mode
	 *m_msg = pMsg->m_msg ;
	 *s_msg = pMsg->s_msg ;
   *Sender = pMsg->From ;	
   
	 pMsg->uflag = MSG_OLD ;
	 pMsg->rflag = MSG_READ_OK ;
        
   #if  PG_DRV_SUPPORT == 1
      pgos_call_drv( SYS_MSG_R, ( void * )pMsg ) ;
   #endif 
	 pgos_int_enable() ;

	 return PGOS_SUCCESS ;
}

BOOL  pgos_tk_isnewmsg()
{
   pgTASK*  pTask ;
	 BOOL  Ret ;
	 
	 pgos_int_disable() ;
	 pTask = pgos_tk_lookup( task_cur_id ) ;
	 if( pTask->pgMessage->uflag == MSG_NEW )
	 {
	      Ret = TRUE ;
	 }
	 else
	 {
	      Ret = FALSE ;
	 }

	 pgos_int_enable() ;

	 return Ret ;
}
#endif

#if  PG_SCH_ROUNDROBIN == 1
VOID  pgos_tk_setruntime( DWORD  time  )
{
      if( time == 0 )
	  	   maxtime = MAX_DEF_TIME ;
      else
	  	   maxtime = time ;
}
#endif


BOOL  pgos_tk_basic()
{
 #if  PG_TASK_BASIC_SUPPORT == 1
    return TRUE ;
 #else
    return FALSE ;
 #endif
}

BOOL  pgos_tk_adv()
{
#if  PG_TASK_ADV_SUPPORT == 1
    return TRUE ;
#else
    return FALSE ;
#endif
}

BOOL  pgos_tk_msg()
{
#if  PG_MSG_SUPPORT == 1
    return TRUE ;
#else
    return FALSE ;
#endif
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -