Linux $BMQ%j%"%k%?%$%`%/%m%C%/%I%i%$%P(B
====================================
$BA4$F$N(B PC (Alpha $B%^%7%s$b4^$_$^$9(B) $B$K$O!"%j%"%k%?%$%`%/%m%C%/$,AH$_(B
$B9~$^$l$F$$$^$9!#DL>o!"$3$l$i$O%3%s%T%e!<%?$N%A%C%W%;%C%H$KAH$_9~$^$l(B
$B$F$$$k$N$G$9$,!"(BMotorola MC146818 ($B$b$7$/$O$=$N%/%m!<%s(B) $B$,%\!<%I>e$K(B
$BEk:\$5$l$F$$$k>l9g$b$"$j$^$9!#$3$N%/%m%C%/$O!"%3%s%T%e!<%?$NEE8;$,(B
$BMn$A$F$$$k$"$$$@$b!";~$r9o$_B3$1$F$$$^$9!#(B
$B%j%"%k%?%$%`%/%m%C%/$O!"(B2Hz $B$H$$$&DcB.$+$iHf3SE*9bB.$N(B 8192Hz $B$^$G$N(B
$BHO0O$K$"$k<~GH?t(B $B!=!=C"$7!"(B2 $B$NN_>hCM$N<~GH?t!=!=(B $B$GH/@8$9$k%7%0%J%k$r(B
$B@8@.$9$k$N$K$b;H$&$3$H$,$G$-$^$9!#$3$N%7%0%J%k$O!"3d9~$_HV9f(B 8 $B$GDLCN(B
$B$5$l$^$9(B ($B$^$5$K$3$N$?$a$K(B IRQ 8 $B$,;H$o$l$F$$$k$N$G$9(B!) $B!#@_Dj$5$l$?(B
$B;~9o$K$J$C$?$H$-$K(B IRQ 8 $B$rH/@8$5$;$k(B 24 $B;~4V%"%i!<%`$H$7$F;H$&$3$H$b(B
$B$G$-$^$9!#%W%m%0%i%_%s%02DG=$J(B 3 $B$D$NCM$N2?$i$+$NAH$_9g$o$;(B $B!=!=Nc$($P!"(B
$BKh!X;~!Y;0==!XJ,!Y;0==!XIC!Y!=!=(B $B$r%A%'%C%/$9$k$?$a$@$1$K%"%i!<%`$r(B
$BMQ$$$k$3$H$b$G$-$^$9!#99?7%/%m%C%/$N$?$S$K3d9~$_$rH/@8$5$;$k$h$&$K$9(B
$B$l$P!"(B1Hz $B$N%7%0%J%k$r@8@.$5$;$k$3$H$b$G$-$^$9!#(B
$B3d9~$_$O!"(Bunsigned long $B7?$NJQ?t$H$7$F(B /dev/rtc ($B%a%8%c!A[%U%!%$%k(B /proc/driver/rtc $B$+$i%9%F!<%?%9>pJs$rl9g$K$O!"$3$N(B
$B5!G=$,Lr$KN)$A$^$9!#(B
RTC $B$r9b$$<~GH?t$K@_Dj$7$F$$$k$+!"$b$7$/$OIi2Y$,9b$$>uBV$N$H$-$K$O!"(B
$B$$$o$f$k3d9~$_$NN_@Q$,H/@8$7$F$7$^$C$F$$$J$$$+$I$&$+$r3NG'$9$k$?$a!"(B
$B:G8e$KFI=P$7=hM}$r$*$3$J$C$?;~E@$+$i$N3d9~$_l9g!"$H$-$*$j3d9~$_$NN_@Q$,H/@8$7$F$7$^$$$^$9(B ($B$D$^$j!":G8e$N(B
$BFI9~$_=hM};~$+$i(B 2 $B$D0J>e$N(B IRQ $B%$%Y%s%H$,H/@8$7$F$$$k(B) $B!#$G$9$N$G!"(B
$BFI$_=P$7$?CM$N>e0L%P%$%H$O%A%'%C%/$9$Y$-$G$7$g$&!#FC$K!"DL>o$N%?%$%^(B
$B3d9~$_$N<~GH?t(B (100Hz) $B$h$j$b9b$$<~GH?t$N>l9g$O!"@'Hs$H$b%A%'%C%/(B
$B$7$F$/$@$5$$!#(B
64Hz $B$h$jBg$-$$3d9~$_<~GH?t$r@_Dj$7$?$jM-8z$K$7$?$j$9$k$3$H$,5v$5$l$F(B
$B$$$k$N$O!"(Broot $B$N$_$G$9!#$3$l$O.2=$9$k$?$a!"3d9~$_%O%s%I%i$O$[$s$N?t9T$N%3!<%I$N$_$G9=@.(B
$B$5$l$F$$$^$9!#(B
$B$^$?!"%+!<%M%k;~9o$,30It%=!<%9$HF14|$7$F$$$k>l9g!"%+!<%M%k$O(B 11 $BJ,$4$H$K(B
CMOS $B$X;~9o$r=q$-9~$_$^$9!#$3$N=hM}$r$*$3$J$C$F$$$k$"$$$@$O!"(BRTC $B<~4|(B
$B3d9~$_$O0l;~E*$K%*%U$K$5$l$F$$$^$9!#(BRTC $B$r;H$C$F=EMW$J=hM}$r$*$3$J$C$F(B
$B$$$k>l9g$O!"$3$N$3$H$KN10U$7$F$*$$$F$/$@$5$$!#30It%=!<%9(B (NTP $B$J$I(B) $B$H(B
$B%+!<%M%k;~9o$rF14|$5$;$F$$$J$$>l9g$O!"%+!<%M%k$O(B RTC $B$K0l@Z4XCN$7$J$$(B
$B$N$G!"%"%W%j%1!<%7%g%s@lMQ$N%G%P%$%9$H$7$F(B RTC $B$rGSB>E*$K;HMQ$9$k$3$H$,(B
$B$G$-$^$9!#(B
include/linux/rtc.h $B$K%j%9%H%"%C%W$5$l$F$$$kMM!9$J(B ioctl(2) $B8F=P$7$r(B
$B;H$$!"%"%i!<%`$d3d9~$_<~GH?t$r(B RTC $B$K%W%m%0%i%_%s%0$9$k$3$H$,$G$-$^$9!#(B
ioctl() $B$J$I$K$D$$$F(B 50 $B%Z!<%8$b5-=R$9$k$h$j$b!"$=$l$i$N;H$$J}$d%I%i(B
$B%$%P$N5!G=$r<($9>.$5$J%F%9%H%W%m%0%i%`$rDs<($7$?$[$&$,M-1W$@$H;W$$$^$9!#(B
$B$3$N%I%i%$%P$r;H$&%"%W%j%1!<%7%g%s$r:n@.$9$k$3$H$K6=L#$N$"$k?M!9$K$H$C(B
$B$F$O!"%3!<%I$N$[$&$,$:$C$HLr$KN)$D$G$7$g$&!#(B
Paul Gortmaker
$BK]LuCDBN!'(BJF $B%W%m%8%'%/%H(B < http://www.linux.or.jp/JF/ >
$BK]Lu$l!"(Bupdate_interrupt_test(),
* alarm_test(), periodic_interrupt_test()
* $B$K$"$j$^$9!#(B
*
* GNU General Public License, version 2 $B$G(B
* $B%i%$%;%s%9$5$l$^$9!#(B
*/
/*
* [ 2.4.17 $B;~E@$N(B include/linux/rtc.h $B$h$j(B ]
*
* RTC_AIE_ON $B%"%i!<%`3d9~$_$rM-8z$K$9$k(B
* RTC_AIE_OFF $B%"%i!<%`3d9~$_$rL58z$K$9$k(B
* RTC_UIE_ON $B99?73d9~$_$rM-8z$K$9$k(B
* RTC_UIE_OFF $B99?73d9~$_$rL58z$K$9$k(B
* RTC_PIE_ON $B<~4|3d9~$_$rM-8z$K$9$k(B
* RTC_PIE_OFF $B<~4|3d9~$_$rL58z$K$9$k(B
* RTC_WIE_ON $B%&%)%C%A%I%C%03d9~$_$rM-8z$K$9$k(B
* RTC_WIE_OFF $B%&%)%C%A%I%C%03d9~$_$rM-8z$K$9$k(B
*
* RTC_ARM_SET $B%"%i!<%`;~9o$r%;%C%H$9$k(B
* RTC_ARM_READ $B%"%i!<%`;~9o$rFI$_=P$9(B
* RTC_RD_TIME RTC $B;~9o$rFI$_=P$9(B
* RTC_SET_TIME RTC $B;~9o$r%;%C%H$9$k(B
* RTC_IRQP_READ IRQ $B<~GH?t$rFI$_=P$9(B
* RTC_IRQP_SET IRQ $B<~GH?t$r%;%C%H$9$k(B
* RTC_EPOCH_READ $B%(%]%C%/;~9o$rFI$_=P$9(B
* RTC_EPOCH_SET $B%(%]%C%/;~9o$r%;%C%H$9$k(B
*
* RTC_WKALM_SET $B5/>2%"%i!<%`$r%;%C%H$9$k(B
* RTC_WKALM_RD $B5/>2%"%i!<%`$re$N%$%Y%s%H$,DI2C$5$l$F$$$k$3$H$r(B\n"
"'cat /proc/interrupts' $B$G3NG'$9$k$3$H$,$G$-$^$9!#(B\n\n",
m_irqcount
);
return EXIT_SUCCESS;
}
/**************************************************
do_tests()
**************************************************/
static void
do_tests(void)
{
/************************************************************
RTC $B$N%G%P%$%9%U%!%$%k(B '/dev/rtc' $B$r%*!<%W%s$9$k!#(B
************************************************************/
m_fd = Open("/dev/rtc", O_RDONLY);
/************************************************************
$B99?73d9~$_%F%9%H(B
************************************************************/
update_interrupt_test();
/************************************************************
$B%"%i!<%`%F%9%H(B
************************************************************/
alarm_test();
/************************************************************
$B<~4|3d9~$_%F%9%H(B
************************************************************/
periodic_interrupt_test();
/************************************************************
RTC $B$N%G%P%$%9%U%!%$%k(B '/dev/rtc' $B$r%/%m!<%:$9$k!#(B
************************************************************/
close(m_fd);
}
/**************************************************
perror_exit()
**************************************************/
static void
perror_exit(const char *msg)
{
perror(msg);
exit(errno);
}
/**************************************************
print_msg()
**************************************************/
static void
print_msg(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
/************************************************************
stderr $B$O%*!<%W%s;~$K$O%P%C%U%!%j%s%0$5$l$F$$$J$$$N$G!"(B
$B$o$6$o$6(B fflush(stderr) $B$OpJs$rI=<($9$k!#(B
************************************************************/
print_msg("\t* $B%"%i!<%`;~9o$,(B '%02d $B;~(B %02d $BJ,(B %02d $BIC(B' $B$K@_Dj$5$l$^$7$?!#(B\n",
rtc_tm.tm_hour, rtc_tm.tm_min, rtc_tm.tm_sec
);
/************************************************************
$B%"%i!<%`3d9~$_$rM-8z$K$9$k!#(B
************************************************************/
Ioctl(m_fd, RTC_AIE_ON, 0);
}
/**************************************************
read_current_rtc()
**************************************************/
static void
read_current_rtc(struct rtc_time *rtc_tm)
{
/************************************************************
$B8=:_$N(B RTC $B;~9o$rFI$_=P$7$F(B rtc_tm $B$K%;%C%H$9$k!#(B
************************************************************/
Ioctl(m_fd, RTC_RD_TIME, rtc_tm);
/************************************************************
$B8=:_$N(B RTC $B;~9o$rI=<($9$k!#(B
************************************************************/
print_msg("\t* RTC $B8=:_;~9o(B: %d $BG/(B %d $B7n(B %d $BF|(B %02d $B;~(B %02d $BJ,(B %02d $BIC(B\n",
rtc_tm->tm_year + 1900, rtc_tm->tm_mon + 1, rtc_tm->tm_mday,
rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec
);
}
/**************************************************
add_sec_to_rtc_time()
**************************************************/
static void
add_sec_to_rtc_time(struct rtc_time *rtc_tm, int sec)
{
rtc_tm->tm_sec += sec;
if ( rtc_tm->tm_sec >= 60 ) {
rtc_tm->tm_sec %= 60;
rtc_tm->tm_min++;
}
if ( rtc_tm->tm_min == 60 ) {
rtc_tm->tm_min = 0;
rtc_tm->tm_hour++;
}
if ( rtc_tm->tm_hour == 24 ) {
rtc_tm->tm_hour = 0;
}
}
/*
*
*
* $B<~4|3d9~$_%F%9%H(B
*
*
*/
/**************************************************
periodic_interrupt_test()
**************************************************/
static void
periodic_interrupt_test(void)
{
print_msg("\n$B<~4|3d9~$_%F%9%H(B\n");
/************************************************************
$B<~4|(B IRQ $B%l!<%H$rI=<($9$k!#(B
************************************************************/
print_periodic_irq_rate();
/************************************************************
$B<~4|(B IRQ $B%l!<%H$rJQ2=$5$;$J$,$i!"(BRTC $B$NFI9~$_%F%9%H$r9T$&!#(B
************************************************************/
count_periodic_interrupt();
}
/**************************************************
print_periodic_irq_rate()
**************************************************/
static void
print_periodic_irq_rate(void)
{
unsigned long pirq_rate;
/************************************************************
$B<~4|(B IRQ $B%l!<%H$rFI$_=P$9!#(B
************************************************************/
Ioctl(m_fd, RTC_IRQP_READ, &pirq_rate);
/************************************************************
$B<~4|(B IRQ $B%l!<%H$rI=<($9$k!#(B
************************************************************/
print_msg("\t* $B<~4|(B IRQ $B%l!<%H$O(B %luHz $B$G$7$?!#(B\n", pirq_rate);
}
/**************************************************
count_periodic_interrupt()
**************************************************/
static void
count_periodic_interrupt(void)
{
unsigned long pirq_rate;
unsigned long rate_max;
print_msg("\t* $B<~GH?t$rJQ2=$5$;$J$,$i(B RTC $BFIl9g$O!"(B8192Hz $B$^$G%F%9%H$9$k!#(Broot $B$G$O$J$$(B
$B>l9g$O!"(B64Hz $B$^$G$N%F%9%H$H$9$k!#(B
************************************************************/
if ( geteuid() == 0 ) {
rate_max = 8192; /* 8192Hz */
}
else {
rate_max = 64; /* 64Hz */
}
/************************************************************
$B<~GH?t$r(B 2Hz, 4Hz, 8Hz, 16Hz, 32Hz, 64Hz $B$K=g
Linux $B%+!<%M%k(B 2.4 $BImB0J8=q0lMw$XLa$k(B
JF Project $B%a%$%s%Z!<%8$X(B
JF Project $BA4HL$K4X$o$k$40U8+$4MWK>$O(B JF@linux.or.jp $B$^$G$*4j$$$7$^$9(B.