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

📄 time.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 2 页
字号:
/* $Id: time.c,v 1.17 2002/11/15 14:49:24 oskarp Exp $ * *  linux/arch/cris/kernel/time.c * *  Copyright (C) 1991, 1992, 1995  Linus Torvalds *  Copyright (C) 1999, 2000, 2001, 2002 Axis Communications AB * * 1994-07-02    Alan Modra *	fixed set_rtc_mmss, fixed time.year for >= 2000, new mktime * 1995-03-26    Markus Kuhn *      fixed 500 ms bug at call to set_rtc_mmss, fixed DS12887 *      precision CMOS clock update * 1996-05-03    Ingo Molnar *      fixed time warps in do_[slow|fast]_gettimeoffset() * 1997-09-10	Updated NTP code according to technical memorandum Jan '96 *		"A Kernel Model for Precision Timekeeping" by Dave Mills * * Linux/CRIS specific code: * * Authors:    Bjorn Wesen *             Johan Adolfsson   * 2002-03-04    Johan Adolfsson *      Use prescale timer at 25000 Hz instead of the baudrate timer at  *      19200 to get rid of the 64ppm to fast timer (and we get better  *      resolution within a jiffie as well. * 2002-03-05    Johan Adolfsson *      Use prescaler in do_slow_gettimeoffset() to get 1 us resolution (40ns) * 2002-09-06    Johan Adolfsson *      Handle lost ticks by checking wall_jiffies, more efficient code  *      by using local vars and not the pointer argument. * */#include <linux/errno.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/param.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/interrupt.h>#include <linux/time.h>#include <linux/delay.h>#include <asm/segment.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/delay.h>#include <asm/rtc.h>#include <linux/timex.h>#include <linux/config.h>#include <asm/svinto.h>#define CRIS_TEST_TIMERS 0static int have_rtc;  /* used to remember if we have an RTC or not *//* define this if you need to use print_timestamp *//* it will make jiffies at 96 hz instead of 100 hz though */#undef USE_CASCADE_TIMERSextern int setup_etrax_irq(int, struct irqaction *);#define TICK_SIZE tickextern unsigned long wall_jiffies;/* The timers count from their initial value down to 1  * The R_TIMER0_DATA counts down when R_TIM_PRESC_STATUS reaches halv * of the divider value. */ unsigned long get_ns_in_jiffie(void){	unsigned char timer_count, t1;	unsigned short presc_count;	unsigned long ns;	unsigned long flags;	save_flags(flags);	cli();		timer_count = *R_TIMER0_DATA;	presc_count = *R_TIM_PRESC_STATUS;  	/* presc_count might be wrapped */	t1 = *R_TIMER0_DATA;	if (timer_count != t1){		/* it wrapped, read prescaler again...  */		presc_count = *R_TIM_PRESC_STATUS;		timer_count = t1;	}	restore_flags(flags);	if (presc_count >= PRESCALE_VALUE/2 ){		presc_count =  PRESCALE_VALUE - presc_count + PRESCALE_VALUE/2;	} else {		presc_count =  PRESCALE_VALUE - presc_count - PRESCALE_VALUE/2;	}	ns = ( (TIMER0_DIV - timer_count) * ((1000000000/HZ)/TIMER0_DIV )) + 	     ( (presc_count) * (1000000000/PRESCALE_FREQ));	return ns;}#if CRIS_TEST_TIMERS #define NS_TEST_SIZE 4000static unsigned long ns_test[NS_TEST_SIZE];void cris_test_timers(void){	int i;#if 0	for (i = 0; i < NS_TEST_SIZE; i++)	{		ns_test[i] = *R_TIMER0_DATA | (*R_TIM_PRESC_STATUS<<16);	}	for (i = 1; i < NS_TEST_SIZE; i++)	{		printk("%4i. %lu %lu %09lu ns \n",		       i, ns_test[i]&0x0FFFF, (ns_test[i]>>16), 	get_ns_in_jiffie_from_data(ns_test[i]&0x0FFFF, ns_test[i]>>16));	}#else	for (i = 0; i < NS_TEST_SIZE; i++)	{		ns_test[i] = get_ns_in_jiffie();	}	for (i = 1; i < NS_TEST_SIZE; i++)	{		printk("%4i. %09lu ns diff %li ns\n",		       i, ns_test[i], ns_test[i]- ns_test[i-1]);	}#endif}#endifstatic unsigned long do_slow_gettimeoffset(void){	unsigned long count, t1;	unsigned long usec_count = 0;	unsigned short presc_count;	static unsigned long count_p = TIMER0_DIV;/* for the first call after boot */	static unsigned long jiffies_p = 0;	/*	 * cache volatile jiffies temporarily; we have IRQs turned off. 	 */	unsigned long jiffies_t;	/* The timer interrupt comes from Etrax timer 0. In order to get	 * better precision, we check the current value. It might have	 * underflowed already though.	 */#ifndef CONFIG_SVINTO_SIM	/* Not available in the xsim simulator. */	count = *R_TIMER0_DATA;	presc_count = *R_TIM_PRESC_STATUS;  	/* presc_count might be wrapped */	t1 = *R_TIMER0_DATA;	if (count != t1){		/* it wrapped, read prescaler again...  */		presc_count = *R_TIM_PRESC_STATUS;		count = t1;	}#else	count = 0;	presc_count = 0;#endif 	jiffies_t = jiffies;	/*	 * avoiding timer inconsistencies (they are rare, but they happen)...	 * there are one problem that must be avoided here:	 *  1. the timer counter underflows	 */	if( jiffies_t == jiffies_p ) {		if( count > count_p ) {			/* Timer wrapped, use new count and prescale 			 * increase the time corresponding to one jiffie			 */			usec_count = 1000000/HZ;		}	} else		jiffies_p = jiffies_t;        count_p = count;	if (presc_count >= PRESCALE_VALUE/2 ){		presc_count =  PRESCALE_VALUE - presc_count + PRESCALE_VALUE/2;	} else {		presc_count =  PRESCALE_VALUE - presc_count - PRESCALE_VALUE/2;	}	/* Convert timer value to usec */	usec_count += ( (TIMER0_DIV - count) * (1000000/HZ)/TIMER0_DIV ) +	              (( (presc_count) * (1000000000/PRESCALE_FREQ))/1000);	return usec_count;}#define do_gettimeoffset() do_slow_gettimeoffset()/* * This version of gettimeofday has near microsecond resolution. */void do_gettimeofday(struct timeval *tv){	unsigned long flags;	unsigned long usec, sec;	save_flags(flags);	cli();	usec = do_gettimeoffset();	{		unsigned long lost = jiffies - wall_jiffies;		if (lost)			usec += lost * (1000000 / HZ);	}	sec = xtime.tv_sec;	usec += xtime.tv_usec;	restore_flags(flags);	while (usec >= 1000000) {		usec -= 1000000;		sec++;	}	tv->tv_sec = sec;	tv->tv_usec = usec;}void do_settimeofday(struct timeval *tv){	unsigned long flags;	signed long new_usec, new_sec;	save_flags(flags);  	cli();	/* This is revolting. We need to set the xtime.tv_usec	 * correctly. However, the value in this location is	 * is value at the last tick.	 * Discover what correction gettimeofday	 * would have done, and then undo it!	 */	new_usec = tv->tv_usec;	new_usec -= do_gettimeoffset();	new_usec -= (jiffies - wall_jiffies) * (1000000 / HZ);	new_sec = tv->tv_sec;	while (new_usec < 0) {		new_usec += 1000000;		new_sec--;	}	xtime.tv_sec = new_sec;	xtime.tv_usec = new_usec;	time_adjust = 0;		/* stop active adjtime() */	time_status |= STA_UNSYNC;	time_state = TIME_ERROR;	/* p. 24, (a) */	time_maxerror = NTP_PHASE_LIMIT;	time_esterror = NTP_PHASE_LIMIT;	restore_flags(flags);}/* * BUG: This routine does not handle hour overflow properly; it just *      sets the minutes. Usually you'll only notice that after reboot! */static int set_rtc_mmss(unsigned long nowtime){	int retval = 0;	int real_seconds, real_minutes, cmos_minutes;	printk("set_rtc_mmss(%lu)\n", nowtime);	if(!have_rtc)		return 0;	cmos_minutes = CMOS_READ(RTC_MINUTES);	BCD_TO_BIN(cmos_minutes);	/*	 * since we're only adjusting minutes and seconds,	 * don't interfere with hour overflow. This avoids	 * messing with unknown time zones but requires your	 * RTC not to be off by more than 15 minutes	 */	real_seconds = nowtime % 60;	real_minutes = nowtime / 60;	if (((abs(real_minutes - cmos_minutes) + 15)/30) & 1)		real_minutes += 30;		/* correct for half hour time zone */	real_minutes %= 60;	if (abs(real_minutes - cmos_minutes) < 30) {		BIN_TO_BCD(real_seconds);		BIN_TO_BCD(real_minutes);		CMOS_WRITE(real_seconds,RTC_SECONDS);		CMOS_WRITE(real_minutes,RTC_MINUTES);	} else {		printk(KERN_WARNING

⌨️ 快捷键说明

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