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

📄 clock.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"io.h"#include	"ureg.h"#include	"../port/error.h"enum {	RTCREGS	=	0x90010000,	/* real time clock registers */	RTSR_al	=	0x01,		/* alarm detected */	RTSR_hz	=	0x02,		/* 1Hz tick */	RTSR_ale=	0x04,		/* alarm interrupt enable */	RTSR_hze=	0x08,		/* 1Hz tick enable */	Never	=	0xffffffff,};typedef struct OSTimer{	ulong		osmr[4];	/* match registers */	volatile ulong	oscr;		/* counter register */	ulong		ossr;		/* status register */	ulong		ower;	/* watchdog enable register */	ulong		oier;		/* timer interrupt enable register */} OSTimer;typedef struct RTCregs {	ulong	rtar;	/* alarm */	ulong	rcnr;	/* count */	ulong	rttr;	/* trim */	ulong	dummy;	/* hole */	ulong	rtsr;	/* status */} RTCregs;OSTimer *timerregs = (OSTimer*)OSTIMERREGS;RTCregs *rtcregs = (RTCregs*)RTCREGS;static int clockinited;static void	clockintr(Ureg*, void*);static void	rtcintr(Ureg*, void*);static uvlong	when;	/* scheduled time of next interrupt */long	timeradjust;enum{	Minfreq = ClockFreq/HZ,		/* At least one interrupt per HZ (50 ms) */	Maxfreq = ClockFreq/10000,	/* At most one interrupt every 100 µs */};ulongclockpower(int on){	static ulong savedtime;	if (on){		timerregs->ossr |= 1<<0;		timerregs->oier = 1<<0;		timerregs->osmr[0] = timerregs->oscr + Minfreq;		if (rtcregs->rttr == 0){			rtcregs->rttr = 0x8000; // nominal frequency.			rtcregs->rcnr = 0;			rtcregs->rtar = 0xffffffff;			rtcregs->rtsr |= RTSR_ale;			rtcregs->rtsr |= RTSR_hze;		}		if (rtcregs->rcnr > savedtime)			return rtcregs->rcnr - savedtime;	} else		savedtime = rtcregs->rcnr;	clockinited = on;	return 0L;}voidclockinit(void){	ulong x;	ulong id;	/* map the clock registers */	timerregs = mapspecial(OSTIMERREGS, sizeof(OSTimer));	rtcregs   = mapspecial(RTCREGS, sizeof(RTCregs));	/* enable interrupts on match register 0, turn off all others */	timerregs->ossr |= 1<<0;	intrenable(IRQ, IRQtimer0, clockintr, nil, "clock");	timerregs->oier = 1<<0;	/* figure out processor frequency */	x = powerregs->ppcr & 0x1f;	conf.hz = ClockFreq*(x*4+16);	conf.mhz = (conf.hz+499999)/1000000;	/* get processor type */	id = getcpuid();	print("%lud MHZ ARM, ver %lux/part %lux/step %lud\n", conf.mhz,		(id>>16)&0xff, (id>>4)&0xfff, id&0xf);	/* post interrupt 1/HZ secs from now */	when = timerregs->oscr + Minfreq;	timerregs->osmr[0] = when;	/* enable RTC interrupts and alarms */	intrenable(IRQ, IRQrtc, rtcintr, nil, "rtc");	rtcregs->rttr = 0x8000; 	// make rcnr   1Hz	rtcregs->rcnr = 0;		// reset counter	rtcregs->rtsr |= RTSR_al;	rtcregs->rtsr |= RTSR_ale;	timersinit();	clockinited = 1;}/*  turn 32 bit counter into a 64 bit one.  since todfix calls *  us at least once a second and we overflow once every 1165 *  seconds, we won't miss an overflow. */uvlongfastticks(uvlong *hz){	static uvlong high;	static ulong last;	ulong x;	if(hz != nil)		*hz = ClockFreq;	x = timerregs->oscr;	if(x < last)		high += 1LL<<32;	last = x;	return high+x;}voidtimerset(uvlong v){	ulong next, tics;	/* Must be unsigned! */	static int count;	next = v;	/* post next interrupt: calculate # of tics from now */	tics = next - timerregs->oscr - Maxfreq;	if (tics > Minfreq){		timeradjust++;		next = timerregs->oscr + Maxfreq;	}	timerregs->osmr[0] = next;}static voidclockintr(Ureg *ureg, void*){	/* reset previous interrupt */	timerregs->ossr |= 1<<0;	when += Minfreq;	timerregs->osmr[0] = when;	/* insurance */	timerintr(ureg, when);}voidrtcalarm(ulong secs){	vlong t;	if (t == 0){		iprint("RTC alarm cancelled\n");		rtcregs->rtsr &= ~RTSR_ale;		rtcregs->rtar = 0xffffffff;	} else {		t = todget(nil);		t = t / 1000000000ULL; // nsec to secs		if (secs < t)			return;		secs -= t;		iprint("RTC alarm set to %uld seconds from now\n", secs);		rtcregs->rtar = rtcregs->rcnr + secs;		rtcregs->rtsr|= RTSR_ale;	}}static voidrtcintr(Ureg*, void*){	/* reset interrupt */	rtcregs->rtsr&= ~RTSR_ale;	rtcregs->rtsr&= ~RTSR_al;	rtcregs->rtar = 0;	iprint("RTC alarm: %lud\n", rtcregs->rcnr);}voiddelay(int ms){	ulong start;	int i;	if(clockinited){		while(ms-- > 0){			start = timerregs->oscr;			while(timerregs->oscr-start < ClockFreq/1000)				;		}	} else {		while(ms-- > 0){			for(i = 0; i < 1000; i++)				;		}	}}voidmicrodelay(int µs){	ulong start;	int i;	µs++;	if(clockinited){		start = timerregs->oscr;		while(timerregs->oscr - start < 1UL+(µs*ClockFreq)/1000000UL)			;	} else {		while(µs-- > 0){			for(i = 0; i < 10; i++)				;		}	}}/*   *  performance measurement ticks.  must be low overhead. *  doesn't have to count over a second. */ulongperfticks(void){	return timerregs->oscr;}

⌨️ 快捷键说明

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