RT/CMOSから日時を取得する [PC/AT +3]
IBM PC/ATおよびその互換機のRT/CMOS(RTCに内蔵されているRAM)について。
○概要
RT/CMOSとは"Real-Time Clock/Complementary Metal-Oxide Semiconductor RAM"の略で、カレンダー・時計の刻時機能とそれを記録するRAMを内蔵する。RAMの一部の領域は小容量ながらも自由に利用できる。
本家IBMのPC/ATではモトローラ製MC146818が使われており、互換機でもそれに相当するICや機能を備えている。電源オフの状態でもRAMの内容が消えないようにマザーボード上の電池から電源を供給し続けている。
○RT/CMOSのメモリーマップ概要
アドレス | 説明 |
00 - 0Dh | RTC(詳細は下記参照) |
0E | 診断ステータス |
0F | シャットダウンステータス |
10 - 14h | ドライブ接続ステータス |
15h | 基本メモリー容量(下位8ビット)(KiB) |
16h | 基本メモリー容量(上位8ビット)(KiB) |
17h | 拡張メモリー容量(下位8ビット)(KiB) |
18h | 拡張メモリー容量(上位8ビット)(KiB) |
19 - 2Dh | 予約 |
2E - 2Fh | 10-20hのチェックサム |
30h | 拡張メモリー容量(下位8ビット)(KiB) |
31h | 拡張メモリー容量(上位8ビット)(KiB) |
32h | 世紀(10進数)(値は20固定?) |
33 - 3Fh | システム予約 |
PC/ATでは計64バイト。
互換機では40-7Fhに固有のBIOSの設定などを記憶するため計128バイトを使用する機種があるが、00-32hの範囲はPC/ATとほぼ共通する。
15-18hや30-31hで搭載しているメモリーの容量を検出できるが、BIOS割り込み(INT 12h,15h)を用いる方法がより一般的。
○RTC部分のメモリーマップ詳細
アドレス | 説明 |
00h | 秒 |
01h | 秒アラーム |
02h | 分 |
03h | 分アラーム |
04h | 時 |
05h | 時アラーム |
06h | 曜日 |
07h | 日 |
08h | 月 |
09h | 年(下2桁) |
0Ah | レジスターA |
0Bh | レジスターB |
0Ch | レジスターC |
0Dh | レジスターD |
日時データの数値表現はレジスターBの"DM"や"24/12"の設定値によって異なる。12時間モードを指定した場合は午後の間は"時"の最上位ビットが1になる。
曜日データは日曜日を1、月曜日を2、...、土曜日を7、とする。
アラームで指定した時間になるとレジスターCのアラームフラグ(AF)が立ち、その時レジスターBの"AIE"が1であれば割り込み(IRQ 8)が発生する。
アラームの各値の上位2ビットを1(C0-FFhを指定)にするとその項目を無視する。例えば"時アラーム"にFFhを指定すると毎時間"分アラーム"と"秒アラーム"で指定した時刻にアラームフラグが立つ。
○0Ah : RTCレジスターA (読み書き可。ただし"UIP"は読み取りのみ。)
ビット | 名称 | 説明 |
7 | UIP | 時計を更新中またはまもなく更新 |
6-4 | DV2-DV0 | 入力クロックの分周指定 |
3-0 | RS3-RS0 | PF割り込みおよび矩形波出力の周期(分周)指定 |
PC/ATにおけるRT/CMOSの入力クロックは32.768kHzで、レジスターAの既定値は"26h"。
○0Bh : RTCレジスターB (読み書き可)
ビット | 名称 | 既定 | 説明 |
7 | SET | - | 時計の更新を停止する |
6 | PIE | 0 | レジスターCのPFによる割り込みを有効にする |
5 | AIE | 0 | レジスターCのAFによる割り込みを有効にする |
4 | UIE | 0 | レジスターCのUFによる割り込みを有効にする |
3 | SQWE | 0 | 矩形波出力(RS3-RS0で分周値を指定)を有効にする |
2 | DM | - | 日時データの16進/10進表現指定 |
1 | 24/12 | - | 時間データの24時間/12時間表現指定 |
0 | DSE | - | サマータイム動作(米国1966年方式)を有効にする |
"既定"はRT/CMOSのハードウェアリセット時の値で、"-"についてはリセットされない。もっともPC/ATではマザーボード上のRT/CMOS用電池が消耗しない限りRT/CMOSのハードウェアリセットは行われない。
PC/ATにおけるレジスターBの既定値は"02h"(時計更新有効、各種割り込み無効、10進数/24時間表現、サマータイム動作無効。)
日時を変更する際は"SET"を1に設定して更新を止めておく。
PC/ATでは"SQW"ピンが未接続のため矩形波出力は利用できない。
○0Ch : RTCレジスターC (読み取りのみ)
ビット | 名称 | 説明 |
7 | IRQF | 割り込み成立フラグ(=PF*PIE+AF*AIE+UF*UIE) |
6 | PF | 周期フラグ(RS3-RS0で周期を指定) |
5 | AF | アラームフラグ |
4 | UF | 時計更新フラグ |
3-0 | 0 | 予約 |
○0Dh : RTCレジスターD (読み取りのみ)
ビット | 名称 | 説明 |
7 | VRT | 内部RAMやレジスターの記憶保持状態 |
6-0 | 0 | 予約 |
"VRT"は"PS"ピンがHighの時にこのレジスターを読み込むことで1にセットされる。その後は"PS"ピンがLowにならない限り0になることはない。
このビットは電源オン時にRT/CMOSの電源供給状態の確認、つまりCMOS電池の残量確認に使用する。
○RT/CMOSへのアクセス方法
I/Oポート70hでアドレス指定、I/Oポート71hでデータを取得または設定する。
ただしI/Oポート70hの最上位ビットはNMIマスクの有無指定になっているので注意。通常は最上位ビットは0(NMI有効)にする。
A: データを読み出す
- I/Oポート70hに読み出すメモリーアドレスを出力する。
- I/Oポート71hからデータを入力する。
B: データを書き込む
- I/Oポート70hに書き込むメモリーアドレスを出力する。
- I/Oポート71hに書き込むデータを出力する。
○RTCから日時を取得する方法
RTCの日時取得・設定にはBIOS割り込み(INT 1Ah)が利用できるが、今回はDEBUGコマンド上でI/Oポートを通した日時取得の手順をシミュレートしてみる。
Windows(仮想DOSマシン)が互換性のためにI/Oポートをエミュレートしているだけであって、マシンのI/Oポートに直接アクセスしているわけではない。そのためRT/CMOSの構成が実際と異なる場合がある。
(ただしMS-DOSなどのネイティブなDOS環境上のDEBUGコマンドでは実際にI/Oポートにアクセスする。)