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

📄 tmrtsk.c

📁 一个操作系统源代码 用于嵌入式设备 在Vc++环境下仿真 成功移植到多款处理器上
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************
*
* Copyright  2001 National ASIC Center, All right Reserved
*
* FILE NAME: timertask.c
* PROGRAMMER: caihongliang
* Date of Creation: 2001/10/23
* 
* DESCRIPTION: the server for application using RTC timer. It includes TimerProc
*	CreateTimer,FreeTimer,StartTimer,StopTimer,ans so on.
*
* NOTE: 
* 
*
* FUNCTIONS LIST:
* -------------------------------------------------------------------------
*	void	timer_task(void);

*	STATUS	CreateTimer(P_U32 t_id,U32 interval,void (*func)(void *),void *arg, U16 mode);
*	STATUS	FreeTimer(U32 t_id);
*	STATUS	StartTimer(U32 t_id);
*	STATUS	StopTimer(U32 t_id);
*	U32		ReadTimer(U32 t_id);

*	U32		rdclock();
*	void	DefaultTimerProc(struct timer *t);


*	SetDateTime
*	ReadDateTime
*
* GLOBAL VARS LIST:
* 
* static struct timer *Timers;
* define the head point of timer task chain
* 
* 
*
*
**************************************************************************
* MODIFICATION HISTORY
*
* 2001/10/23 by caihongliang 	Creation of this file
* 2001/10/26 by Pessia			Add Critical Section Protection(turn ON/OFF interrupt)
* 								Change TimerProc to timer_task
*								Use TWF_CLR to clear event flag(Line 90)
*								Use System Clock Ticks to take place of CLOCK used before by Cai 
* 2001/10/27 by Pessia			Fix Serious Bug!!!
*									original code : (clock - Timers->expiration) >= 0
*									while clock and expiration are all in type of U32,
*									so the result will always be true!!!
*									It should be changed into (clock >= Timers->expiration)!
* 2001/12/10 by Pessia			Add mode in SysCreateTimer()
* 2002/4/4	 by Pessia			Fix Serious Bug in SysFreeTimer()(L401)!
*************************************************************************/ 
#include <kernel\ros33\Ros33.h>
#include <asixsys.h>
#include <asixapp.h>
#include <sys\rtc.h>
#include "xtmrtsk.h"

/* System Clock Ticks which is increased in RTC interrupt */
extern DWORD currentclock;
extern DWORD passedticks;

/* Head of running timer chain.
 * The list of running timers is sorted in increasing order of expiration;
 * i.e., the first timer to expire is always at the head of the list.
 */
static struct timer *Timers = NULL;

static void	DefaultTimerProc(struct timer *t);

UINT MSPTICK = 32; /* Milliseconds per tick: 32 ==1000/32 */

#define rdclock(rval) \
	vDisableInterrupt(); \
	rval = currentclock; \
	vEnableInterrupt()
	
/*
static DWORD rdclock()
{	
	DWORD rval;
	
	vDisableInterrupt();
	rval = currentclock;
	vEnableInterrupt();
	return rval;
}
*/
BYTE	MonthDay[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
WORD	AccumMonthDays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
WORD	StdYear = 2002;

DWORD	timer_tsk_stk[STACK_SIZE];

TASKDESCRIPTION TimerTskDesp = 
{"timer_task",	ASIX_SERVICE,	NOT_IN_ANYGROUP,	NULL,	STACK_SIZE,	0,	0,	0,	timer_task,	SERVICE_PRI};

TASKDESCRIPTIONLIST	TimerTskDespLst =
{NULL,	NULL,	&TimerTskDesp, TIMERTASK_ID, timer_tsk_stk};

/* Process that handles clock ticks */
void timer_task(void)
{
	register struct timer *t;
	register struct timer *expired;		
	DWORD 	clock;
	static	UINT  flgptn;

	for(;;){
		/* Atomic read and decrement of Tick */
		for(;;){			
			vDisableInterrupt();
			if(passedticks != 0){
				passedticks--;
				vEnableInterrupt();
				break;
			}	
			vEnableInterrupt();
						
			/*Pessia : use TWF_CLR to clear event flag */
			wai_flg(&flgptn,TIMER_EVENT,TIMER_FLG,TWF_ORW | TWF_CLR);
		}

		if(Timers == NULL)
			continue;	/* No active timers, all done */

		/* Initialize null expired timer list */
		expired = NULL;
		//clock = rdclock();
		rdclock(clock);

		/* Move expired timers to expired list. Note use of
		 * subtraction and comparison to zero rather than the
		 * more obvious simple comparison; this avoids
		 * problems when the clock count wraps around.
		 */
		/* shit code */
		/*while(Timers != NULL && (clock - Timers->expiration) >= 0){*/
		/* right code */
		while(Timers != NULL && (clock >= Timers->expiration)){
			
			/* Save Timers since stop_timer will change it */
			t = Timers;
			SysStopTimer((DWORD)t);/*Timers = Timers->next*/
			t->state = TIMER_EXPIRE;
			/* Add to expired timer list */
			t->next = expired;
			expired = t;
		}
		/* Now go through the list of expired timers, removing each
		 * one and kicking the notify function, if there is one
		 */
		while((t = expired) != NULL){
			expired = t->next;
			
			if(t->func){
				(*t->func)(t->arg);
			} else {
				DefaultTimerProc(t);	
			}
			if(t->mode & (ALARM_MODE|AUTO_CLEAR_MODE))
				SysFreeTimer((DWORD) t);
			else
			if(t->mode & (CYC_MODE|AUTO_START_MODE))
				SysStartTimer((DWORD)t);
		}
		
	}
}

/* Start a timer */
STATUS
SysStartTimer(DWORD  t_id)
{
	register struct timer *tnext;
	struct timer *tprev = NULL;
	DWORD clock;

	struct timer *t;
	if((struct timer *)t_id == NULL)
		return	TIMER_ERROR;
	t = (struct timer *)t_id;
	if(t -> flag != 0xface)
		return	TIMER_ERROR;

	if(t->duration == 0)
		return	TIMER_ERROR;		/* A duration value of 0 disables the timer */

	if(t->state == TIMER_RUN)
		SysStopTimer((DWORD)t);

	rdclock(clock);
	t->expiration = clock + t->duration;
	t->state = TIMER_RUN;

	/* Enter Critical Section */
	vDisableDispatch();

	/* Find right place on list for this guy. Once again, note use
	 * of subtraction and comparison with zero rather than direct
	 * comparison of expiration times.
	 */
	 /* shit code */
	 /*
	for(tnext = Timers;tnext != NULL;tprev=tnext,tnext = tnext->next){
		if((tnext->expiration - t->expiration) >= 0)
			break;
	}
	*/
	for(tnext = Timers;tnext != NULL;tprev=tnext,tnext = tnext->next){
		if((tnext->expiration >= t->expiration))
			break;
	}
			
	/* At this point, tprev points to the entry that should go right
	 * before us, and tnext points to the entry just after us. Either or
	 * both may be null.
	 */
	if(tprev == NULL)
		Timers = t;		/* Put at beginning */
	else
		tprev->next = t;

	t->next = tnext;
	
	/* Leave Critical Section */
	vEnableDispatch();
	
	return		TIMER_OK;
}

/* Stop a timer */
STATUS
SysStopTimer(DWORD t_id)
{
	register struct timer *t;
	struct timer *tlast = NULL;
	
	struct timer *timer;
	if((struct timer *)t_id == NULL)
		return	TIMER_ERROR;
	timer = (struct timer *)t_id;
	if( (timer -> flag != 0xface)||(timer->state != TIMER_RUN) )
		return	TIMER_ERROR;
	
	/* Enter Critical Section */
	vDisableDispatch();
	
	/* Verify that timer is really on list */
	for(t = Timers;t != NULL;tlast = t,t = t->next)
		if(t == timer)
			break;

	if(t == NULL)
	{
		vEnableDispatch();
		return	TIMER_ERROR;		/* Should probably panic here */
	}

	/* Delete from active timer list */
	if(tlast != NULL)
		tlast->next = t->next;
	else
		Timers = t->next;	/* Was first on list */

	/* Leave Critical Section */
	vEnableDispatch();

	t->state = TIMER_STOP;
	
	return		TIMER_OK;
}

/* Return milliseconds remaining on this timer */
DWORD
SysReadTimer(DWORD t_id)
{
	DWORD clock;
	struct timer *t;
	
	if((struct timer *)t_id == NULL)
		return 	TIMER_ERROR;
	t = (struct timer *)t_id;
	
	if( (t -> flag != 0xface) || (t->state != TIMER_RUN) )
		return 	TIMER_ERROR;
	
	//clock = rdclock();
	rdclock(clock);
	
	if(t->expiration <= clock)
		return 0;	/* Already expired */
	else
		return (t->expiration - clock) * MSPTICK;
}

STATUS
SysCreateTimer(PDWORD t_id, DWORD interval, void (*func)(void *),void *arg,WORD mode)
{
	struct timer *t;
	ID	id;

	//if((mode & CYC_MODE) ==0 && (mode & ALARM_MODE)==0)	return TIMER_ERROR;
	if((mode & CYC_MODE) && (mode & ALARM_MODE))	return TIMER_ERROR;
	if((mode & CYC_MODE) && (mode & AUTO_CLEAR_MODE))	return TIMER_ERROR; 
	if((mode & ALARM_MODE) && (mode & AUTO_START_MODE))	return TIMER_ERROR; 
		
	/*Pessia : Get id of running task */
	get_tid(&id);
	
	t = (struct timer *)SysLcalloc(sizeof(struct timer));
	if(t == NULL)
		return	TIMER_ERROR;
		
	t->next = NULL;
	t->flag = 0xface;
	
	if(interval != 0)
	{
		// 2002/03/27 longn_qi revised
//		t->duration = 1 + (interval + MSPTICK - 1)/MSPTICK;
		if( interval <= MSPTICK )
			t->duration = 1;
		else
			t->duration = interval/MSPTICK + ((interval%MSPTICK > MSPTICK/2)?1:0);
	}
	else
		t->duration = 0;
	
	t->func = func;
	t->arg = arg;
	t->taskid = id;
	t->state = TIMER_STOP;
	t->mode = mode;
	
	*t_id = (DWORD)t;

	
	return TIMER_OK;
}

STATUS
SysSetTimer(DWORD t_id, DWORD interval, void (*func)(void *),void *arg)
{
//	struct timer *t,*tlast = NULL;
	struct timer *timer;
	BYTE oldstate = TIMER_STOP;

	if(interval == 0)  return TIMER_ERROR;
	if((struct timer *)t_id == NULL)  return	TIMER_ERROR;

	timer = (struct timer *)t_id;
	if(timer -> flag != 0xface)		return	TIMER_ERROR;

	/* if it is running, stop it */
	if(timer->state == TIMER_RUN)
	{
		oldstate = TIMER_RUN;
		SysStopTimer(t_id);
	}	
	/* set values */
	// 2002/03/27 longn_qi revised
//	timer->duration = 1 + (interval + MSPTICK - 1)/MSPTICK;
	if( interval <= MSPTICK )
		timer->duration = 1;
	else
		timer->duration = interval/MSPTICK + ((interval%MSPTICK > MSPTICK/2)?1:0);
	/* when func==NULL, use original values */
	if(func!=NULL)
	{
		timer->func = func;
		timer->arg = arg;
	}
	/* if it was running, start it */
	if(oldstate == TIMER_RUN)
		SysStartTimer(t_id);

	return TIMER_OK;
}

STATUS
SysFreeTimer(DWORD t_id)
{
	register struct timer *t;
	struct timer *tlast = NULL;
	
	struct timer *timer;
	if((struct timer *)t_id == NULL)
		return	TIMER_ERROR;
	timer = (struct timer *)t_id;

⌨️ 快捷键说明

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