本文将深入介绍RTC(Real Time Clock),并结合代码进行解析。

Introduction

A real-time clock (RTC) is a computer clock (most often in the form of an integrated circuit) that keeps track of the current time.

RTC can only be accessed through IO Ports 0x70 and 0x71.

Shortage

The RTC cannot give accuracy greater than seconds. For that, consider the PIT, or the HPET.

Code

代码源于x86-bare-metal-examples

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
* Reference: https://wiki.osdev.org/CMOS
Register Contents Range
0x00 Seconds 0–59
0x02 Minutes 0–59
0x04 Hours 0–23 in 24-hour mode,
1–12 in 12-hour mode, highest bit set if pm
0x07 Day of Month 1–31
0x08 Month 1–12
0x09 Year 0–99

0x0A Status Register A
RTC has an "Update in progress" flag (bit 7 of Status Register A).
To read the time and date properly you have to wait until
the "Update in progress" flag goes from "set" to "clear".
*/
.equ RTCaddress, 0x70
.equ RTCdata, 0x71

#include "common.h"
BEGIN
update_in_progress:
mov $0x0A, %al
out %al, $RTCaddress
in $RTCdata, %al
testb $0x80, %al
jne update_in_progress

/* Second. */
mov $0x00, %al
out %al, $RTCaddress
in $RTCdata, %al

/* Only print if second changed. */
cmp %al, %cl
je update_in_progress
mov %al, %cl

PRINT_HEX <%al>
PUTC

/* Minute. */
mov $0x02, %al
out %al, $RTCaddress
in $RTCdata, %al
PRINT_HEX <%al>
PUTC

/* Hour. */
mov $0x04, %al
out %al, $RTCaddress
in $RTCdata, %al
PRINT_HEX <%al>
PUTC

/* Day. */
mov $0x07, %al
out %al, $RTCaddress
in $RTCdata, %al
PRINT_HEX <%al>
PUTC

/* Month. */
mov $0x08, %al
out %al, $RTCaddress
in $RTCdata, %al
PRINT_HEX <%al>
PUTC

/* Year. */
mov $0x09, %al
out %al, $RTCaddress
in $RTCdata, %al
PRINT_HEX <%al>
PRINT_NEWLINE

jmp update_in_progress

第23~27行代码解析:
When the chip updates the time and date (once per second) it increases “seconds” and checks if it rolled over. If “seconds” did roll over it increases “minutes” and checks if that rolled over. This can continue through all the time and date registers (e.g. all the way up to “if year rolled over, increase century”). However, it’s entirely possible to read the time and date while an update is in progress and get inconsistent values (for example, at 9:00 o’clock you might read 8:59, or 8:60, or 8:00, or 9:00).

To help guard against this problem the RTC has an “Update in progress” flag (bit 7 of Status Register A). To read the time and date properly you have to wait until the “Update in progress” flag goes from “set” to “clear”.

剩余代码比较容易理解。
往PIO 0x70写入0x00后,从PIO 0x71寄存器中读到的就是当前的秒数。
往PIO 0x70写入0x02后,从PIO 0x71寄存器中读到的就是当前的分钟数。
往PIO 0x70写入0x04后,从PIO 0x71寄存器中读到的就是当前的小时数。

For more details, please refer to 7th Gen (U/Y) and 8th Gen (U Quad-Core) Intel® Processor Families I/O Datasheet, Vol. 2.


参考资料:

  1. CMOS
  2. Real-time clock
  3. RTC