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

📄 timer.c

📁 在psos嵌入式操作系统上自己写的一个定时器源代码
💻 C
字号:

#define __TIMER_C

#include      <psos.h>
#include      <string.h>
#include      "sys_conf.h"
#include      "time.h"
#include      "timer.h"
#include      "netntp.h"

#ifndef DB_PRINT
#define DB_PRINT 	printf
#endif // DB_PRINT

#define     PID_TIMER       0
#define     TMCB_NUM        1000

typedef struct TMCBStruc
{
   unsigned char     use ;
   unsigned char     arrived ;
   unsigned int     event ;

   unsigned long     Count1s ;
   unsigned long     rest ;

   void    (*entry)() ;

   unsigned short     prev ;
   unsigned short     next ;
   
}TMCBStruc ;

typedef struct TMCBPoolStruc
{
   unsigned short     count ;
   unsigned short     head ;
   unsigned short     tail ;
   unsigned short     TMid[TMCB_NUM] ;
   
}TMCBPoolStruc;

static TMCBStruc                   TMCB[TMCB_NUM] ;  /* timer control block pointer */
static TMCBPoolStruc               TMCBPool;  /* timer control block queue */
static unsigned long int                         TMCBOverflow ;
static unsigned long int                         TMCBExhaust  ;
static unsigned short                         TMhead , TMtail , TMcount ;


static unsigned int  SysTickCount=0;
unsigned int     SysTickSecond =0;

#define ticks2ps   		146
#define ticks2s         1455
unsigned int SmIdRTCTimer;
unsigned long tidRTCTimer;

void RtcSynTimer();

/********************************************************************
*FUNCTION NAME: unsigned long int        InitTMCB ( void ) ;                      *
*DESCRIPTION:   init Timer control block                            *
*INPUT:         none                                                *
*OUTPUT:        none                                                *
*AUTHOR/DATE:   lijian/98.11.03                               *
*NOTE:                                                              *
********************************************************************/
int             InitTMCB ( void )
{
	unsigned long int         size, i ;

	 /* get TMCB buffer */
	size =  (unsigned long int)( sizeof(TMCBStruc)  * TMCB_NUM ) ;
 
//	rc = rn_getseg ( 0 , size , RN_NOWAIT , 0 , &TMCB ) ;

	/* initial TMCB pool */
    memset ( (unsigned char *)TMCB , 0 , size ) ;

	TMhead         =    NULL_TMID ;
	TMtail         =    NULL_TMID ;
	TMcount        =    0 ;

	TMCBOverflow   =    0 ;
	TMCBExhaust    =    0 ;

   /* initial TMCB pool */
	TMCBPool.count =    TMCB_NUM ;
	TMCBPool.head  =    0 ;
	TMCBPool.tail  =    0 ;
	for ( i = 0; i < TMCB_NUM; i ++ )
		TMCBPool.TMid[i]   =   i ;

	return    1 ;	
}

/********************************************************************
*FUNCTION NAME: unsigned short SetTimer(unsigned short event,unsigned long int Count1s, void(*entry)()) *
*DESCRIPTION:   set timer                                           *
*INPUT:         arg:    timer arg                               *
*               Count1s:  timer length                              *
*               entry:    time out func                             *
*OUTPUT:        timer ID                                            *
*AUTHOR/DATE:   lijian/98.11.03                               *
*NOTE:               
	                                               *
********************************************************************/
unsigned short  _SetTimer( unsigned long int Count1ms, void (*entry)(),unsigned int arg )
{
	TMCBStruc    *ptr;
	unsigned long          sum;
	unsigned short          head , prev , tmid , i ;

	/* get invoking process's task id */
	/* if timer is exist, kill it */
    
     Count1ms /= 100;/*TimerProc is exec once per 100ms now,added by lj 99.5.18*/
	/* get a TMCB from TMCB pool */
	if (TMCBPool.count > 0)
	{
	  TMCBPool.count --;
	  head = TMCBPool.head;
	  if (++ TMCBPool.head >= TMCB_NUM)
		 TMCBPool.head = 0;

	  tmid = TMCBPool.TMid[head];
	}
	else
	{
	  TMCBExhaust ++;
//      poutf( FILE_LINE, PID_TIMER,ALWAYS_PRINT_ID," \nTMCB exhuast!!! " );
	  return NULL_TMID;
	}

	ptr = TMCB + tmid ;
    if (ptr->use != 0)
//        poutf( FILE_LINE, PID_TIMER,ALWAYS_PRINT_ID," \n<Timer exception1!!!> " );
    ;
	/* initial TMCB */
	ptr->Count1s    = Count1ms ;
	ptr->event      = arg ;
	ptr->entry      = entry ;
	ptr->use        = 1 ;
	ptr->arrived    = 0 ;

	/* deal relative timer following */

	if (++TMcount <= 1 )
	{
		ptr->prev  = tmid;
		ptr->next  = tmid;
		ptr->rest  = Count1ms ;
		TMhead = tmid ;
		TMtail = tmid ;
		return  tmid;
	}

	i     = TMhead ;
	sum   = 0;

	/* find position in queue */
	for(;;)
	{
		sum += TMCB[i].rest;
		if (sum >= Count1ms)
		{
			/* has find position, end seeking */
			prev         = TMCB[i].prev;
			ptr->prev    = prev;
			ptr->next    = i;
			ptr->rest    = Count1ms + TMCB[i].rest - sum ;

			TMCB[prev].next  = tmid;
			TMCB[i].prev     = tmid;
			TMCB[i].rest     = sum - Count1ms;
			/* position is head */
			if (i == TMhead)
			   TMhead  = tmid;
			break;
		}

		if (i == TMtail)
		{
			/* position is queue tail */
			TMCB[TMhead].prev  = tmid;
			TMCB[TMtail].next  = tmid;

			ptr->prev    = TMtail;
			ptr->next    = TMhead;
			ptr->rest    = Count1ms - sum;

			TMtail       = tmid;
			break;
		}

		/* continue to seek next */
		i = TMCB[i].next ;
		while ( TMCB[i].rest == 0 ) 
		{
    		if (i == TMtail)
    		{
    			/* position is queue tail */
    			TMCB[TMhead].prev  = tmid;
    			TMCB[TMtail].next  = tmid;

    			ptr->prev    = TMtail;
    			ptr->next    = TMhead;
    			ptr->rest    = Count1ms - sum;

    			TMtail       = tmid;
                
    			return   tmid;
    		}
            i = TMCB[i].next ;
		}
	}
	return  tmid;
}

/********************************************************************
*FUNCTION NAME: unsigned short   StopTimer (unsigned short tmid) ;                        *
*DESCRIPTION:   stop timer                                          *
*INPUT:         tid: timer ID                                       *
*OUTPUT:        0--success                                          *
*               else--fail                                          *
*AUTHOR/DATE:   lijian/98.11.03                               *
*NOTE:                                                              *
********************************************************************/
int    _StopTimer ( unsigned short *ptmid )
{
	TMCBStruc    *ptr;
	unsigned short          tail, prev, next ;
	unsigned short tmid;
	if(ptmid)
		tmid = *ptmid;
	else
		return TM_ERROR;
	if((tmid >= TMCB_NUM) || (tmid == NULL_TMID))
	{
		*ptmid = NULL_TMID;
		return TM_ERROR;
	}
	ptr = (TMCBStruc *)&TMCB[tmid];
	/* tmid is not use */
	if (ptr->use == 0)
	{
		*ptmid = NULL_TMID;
		return TM_ERROR;
	}
	if (ptr->arrived == 1)
//	  poutf( FILE_LINE, PID_TIMER,ALWAYS_PRINT_ID,"\n<Process:%s, kill arrived timer>!!! " );
    ;
	ptr->use = 0;

	prev    = ptr->prev;
	next    = ptr->next;

	/* delete TMCB from timer queue */
	if (ptr->arrived == 0)
	{
		if (-- TMcount == 0)
		{
			/* if no timer in queue, clear queue */
			TMhead = NULL_TMID;
			TMtail = NULL_TMID;
		}
		else
		{
			/* delete from timer queue */
			TMCB[prev].next = next;
			TMCB[next].prev = prev;

			if (tmid != TMtail)
				TMCB[next].rest += ptr->rest;
			else
			{
				/* if tid is timer queu tail */
				TMtail = prev;
			}

			/* the element is head of queue */
			if (TMhead == tmid)
			TMhead = next;
		}
	}

	/* return TMCB to TMCB pool */
	if (TMCBPool.count < TMCB_NUM)
	{
		tail = TMCBPool.tail;
		TMCBPool.TMid[tail] = tmid;
		TMCBPool.count ++;
		if (++ TMCBPool.tail >= TMCB_NUM)
			TMCBPool.tail = 0;
	}
	else
	{
	  TMCBOverflow ++;
//	  poutf( FILE_LINE, PID_TIMER,ALWAYS_PRINT_ID,"\n<TMCB overflow>!!! " );
		*ptmid = NULL_TMID;
	  return TM_ERROR;
	}
	*ptmid = NULL_TMID;
	return TM_SUCCESS;
}

/********************************************************************
*FUNCTION NAME: void       TimerProc ( void ) ;                     *
*DESCRIPTION:   timer process                                       *
*INPUT:         none                                                *
*OUTPUT:        none                                                *
*AUTHOR/DATE:   lijian/98.11.03                               *
*NOTE:                                                              *
********************************************************************/
void       TimerProc ( void )
{
	unsigned short        tmid , next ;
	unsigned char        ArrivedTimerNum ;
	TMCBStruc  *ptr;

    ArrivedTimerNum = 0 ;

    /* if timer queue no element, continue next queue */
    if (TMcount == 0)
        return ;

    /* if timer queue head has not arrive, continue next queue */
    if (-- TMCB[TMhead].rest > 0)
        return ;

    /* deal with arrived timer */
    for(;;)
    {
        if (TMcount == 0)
            break;

        ptr = (TMCBStruc *)&TMCB[TMhead];

        if (ptr->rest > 0)
            break;

        if (ArrivedTimerNum > 200)
        {
            ptr->rest ++;
            break;
        } 

        tmid   =  TMhead ;

        if (-- TMcount == 0)
        {
            /* queue has no element, clear queue */
            TMhead  = NULL_TMID;
            TMtail  = NULL_TMID;
        }
        else
        {
            next              = ptr->next;
            TMCB[TMtail].next = next;
            TMCB[next].prev   = TMtail;
            TMhead            = next;
        }

        /* timer arrived*/
        ptr->use     = 0 ;
        ptr->arrived = 1;
        ArrivedTimerNum ++;
        (*(ptr->entry))(ptr->event);

        if (++ TMCBPool.count <= TMCB_NUM)
        {
            TMCBPool.TMid[TMCBPool.tail] = tmid;
            if (++ TMCBPool.tail >= TMCB_NUM)
                TMCBPool.tail = 0;
        }
        else
        {
            TMCBPool.count = TMCB_NUM;
            TMCBOverflow ++;
            //poutf( FILE_LINE, PID_TIMER,ALWAYS_PRINT_ID,"\n<TMCB overflow>!!! " );
        }

    } /* end while */

}

void IntUserTicks(void)
{
	SysTickCount ++;	
}

void UsrTimerProc()
{
	static unsigned int oldcount1=0,oldcount2=0;
	unsigned int tickcount;
	unsigned int step1, step2;
	int 		i;
	
//	char* strtime;
	
	sm_create("sm_rtc",1,SM_PRIOR,&SmIdRTCTimer);
	for(;;)
	{
		tickcount = SysTickCount;
		if(tickcount > oldcount1 )
		{
			step1 = tickcount - oldcount1;
		}	
		else
		{
			step1 = 0xFFFFFFFF - oldcount1 + tickcount;
		}
		if(tickcount > oldcount2 )
		{
			step2 = tickcount - oldcount2;
		}	
		else
		{
			step2 = 0xFFFFFFFF - oldcount2 + tickcount;
		}
		if(step1 > ticks2ps)
		{
			oldcount1 = tickcount - step1%ticks2ps;
			for(i=0; i <(step1 /ticks2ps);i++)
				TimerProc();
		}
		if(step2 > ticks2s)
		{
			sm_p(SmIdRTCTimer,SM_WAIT,0);
			SysTickSecond += step2/ticks2s;
			sm_v(SmIdRTCTimer);
#if 0
			if((SysTickSecond%60) == 0)
			{
				strtime = ctime((const time_t*)&SysTickSecond);
				DB_PRINT("UsrTimerProc: SysTickSecond = %x,%s\n",SysTickSecond,strtime);
			}
#endif
			oldcount2 = tickcount -step2%ticks2s;
		}
		tm_wkafter(50);
	}
}

int InitSysTimer()
{
	int err;
//	DB_PRINT("netping_init: start\n");
	InitTMCB();
	err=t_create("TICKS",100,10000,10000,0,&tidRTCTimer);
    err=t_start(tidRTCTimer, T_PREEMPT | T_TSLICE | T_ASR | T_ISR, UsrTimerProc, 0);
    if (err)
    {
       	DB_PRINT("t_start failed!!!!! and err = %d. \n", err);
       	return (-1);
    }
	tm_wkafter(50);
	_SetTimer( 15000, RtcSynTimer,0);
	return(0);
}


int SetRtcTimer(unsigned long sec)
{
	sm_p(SmIdRTCTimer,SM_WAIT,0);
	SysTickSecond = sec;
	sm_v(SmIdRTCTimer);
	return 0;
}

unsigned long GetRtcTimer()
{
	return 	SysTickSecond;
}

void RtcSynTimer()
{
	unsigned long mydate;
	char* strtime;
	char  strval[50];
	
	_SetTimer( 1800000, RtcSynTimer,0);
	
#if 1
	mydate = GetRtcTimer();
	strtime = ctime((const time_t*)&mydate);
	strcpy(strval,strtime);
	DB_PRINT("RtcSynTimer:curtime=%x,%s\n ",mydate,strval);
	/*
	SetRtcTimer(28800); 
	mydate = GetRtcTimer();
	strtime = ctime((const time_t*)&mydate);
	strcpy(strval,strtime);
	DB_PRINT("RtcSynTimer-1:curtime=%x,%s\n ",mydate,strval);
	SetRtcTimer(28800 + 3000); 
	mydate = GetRtcTimer();
	strtime = ctime((const time_t*)&mydate);
	strcpy(strval,strtime);
	DB_PRINT("RtcSynTimer-2:curtime=%x,%s\n ",mydate,strval);
	*/
#endif

	
	//  与中心服务器同步时间
	/*
	if(sntpcTimeGet(DST_STREAM_HOST_IP,1000,&mydate) ==0)
	{
		mydate +=28800;// east 8th timearea tune 
		SetRtcTimer(mydate); 
		strtime = ctime((const time_t*)&mydate);
		DB_PRINT("RtcSynTimer:time=%x,%s\n ",mydate,strtime);
	}	
	*/	
}

⌨️ 快捷键说明

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