見出し画像

リアルタイム・クロックとアクティブ・ロー

不具合が報告された内容は次のようなものでした。

マシンを起動するたびにマシンの内部時計が1秒遅れる。試しに数分間に再起動を10回繰り返したところ内部時計の時刻が10秒も遅れた

現在時刻(年月日時分秒)の管理はいろいろな方法があると思いましすが、多くの組込みシステムでは『リアルタイム・クロック(RTC : Real-Time Clock)』という部品を使っています。このRTCはボタン電池や2次電池で動作するようになっていて、機器(マイコン)の主電源をオフした後も、淡々と時を刻んでいます。

「停電で電源が落ちてリセットされて時刻表示が点滅していた」なんてことがたまにありますが、RTCがそもそも組み込まれていないか、ボタン電池や2次電池が劣化して働いていないことに起因します。

いつの間にか時計が数秒遅れるのであれば「時計の誤差」で片付けるのですが、マシン起動のたびに「きっちり1秒」遅れるという再現性があるため調査しました。

システムに載っていたRTCは時刻を読み出す期間, CS(Chip-Select)端子をアクティブにして時刻をロックする仕様になっていました。1回のアクセスで年月日時分秒を一括して読み出すことができないため、CS端子をアクティブにして時刻をロックします。例えば 10時59分59秒 に「時 = 10」と「分 = 59」を読み込んで、秒を読み込もうとした瞬間に11時00分00秒に切り変わり秒を読み込むと「秒 = 00」。時分秒を組み合わせると 10時59分00秒 と本来の時刻よりも1分遅れてしまいます。そこで CS端子をアクティブにして時刻の更新をロックすると11時59分59秒のまま時刻が固定されて59秒が読み込まれます。本来の時刻からは1秒遅れますが実際には10時59分59秒987 と 11時00分00秒013 程度の数十ミリ秒の誤差なので許容範囲です。 

「年」、「月」、「日」、「時」、「分」、「秒」の読取りタイミングが数十ミリ秒〜数百ミリ秒程度の短時間ではあるが「ずれる」ということを補償するための仕組みです。そしてロック中に繰り上がるべき時刻は保留されており、CS端子を非アクティブにした瞬間に更新されます。

「複数の要素(時や分や秒)をまとめて読み込むときは継続的にCS端子をアクティブにして時刻更新をロック(保留)してください」というのが、このRTCの仕様でした。ただし、保留されるのは1秒だけ。1秒を越えてロックしてしまうと時刻は2秒進んでも3秒進んでもCS端子を非アクティブにした瞬間に繰り上がるのは『1秒だけ』。これが不具合の原因といえば原因でした。

さて、ここからが不具合の解決編です。システム起動直後にRTCから現在時刻を読み取る処理が入っていたのですが、いくらこの処理を確認しても1秒を越えてCS端子をアクティブにする振る舞いがみつかりません。

そこでCS端子の電圧変化をオシロスコープで観測すると1秒以上CS端子をアクティブにする瞬間が見つかりました。

ここで端子(信号ライン)の『アクティブ』と『非アクティブ』の説明です。多くのロジック・デバイス(半導体)では「電圧が低い(=ほぼゼロ)のときをアクティブ」、「電圧が高い(ほぼ電源電圧)ときを非アクティブ」という仕様にしています。これを『アクティブ・ロー』と呼びます。ソフト屋の 0 と 1 の感覚からは外れるかもしれませんが、ハードウェア(電気回路や半導体)のいろいろな事情があってこうなっています。そこでリセット直後のマイコンのI/O出力のデフォルトは非アクティブ=電圧が高い(HIGH)になっています。

マイコンの電源を落としてもリセットしてもCS端子がアクティブになることはない「はず」でした。ところがここにRTCの特殊事情が関係してきます。RTCはマイコンの主電源をオフしてもボタン電池で自分一人で動き続けます。そこでCS端子の電圧が低い(LOW)のときをアクティブと決めてしまうと、マイコンがお亡くなりになった途端にロックがかかってしまいます。そこでRTCのCS端子は電圧が高い(HIGH)のときにアクティブという仕様になっていました。これを『アクティブ・ハイ』と呼びます。

「マイコンのアクティブの定義」と「RTCのアクティブの定義」が食い違っていたのです。実はマイコンのリセット直後にI/Oの設定(configuration)のプログラムが走って、アクティブ・ローからアクティブ・ハイへ切り替えていたのですが、このconfigurationのプログラムが走るまでに1秒以上かかっていました。「マイコンの基本的な設定を反映させるまでに1秒以上かかるなんて何やっているんだ!」と思いますが、なぜか後回しでも良い処理を先に実行してからI/Oのconfigurationを実行していました。結果としてはマイコンは非アクティブのつもりでRTCはアクティブを受け取っている期間が1秒以上存在していました。これがマシンを起動(再起動)するたびにRTCが1秒遅れる理由でした。

純粋な計算処理では処理の途中に別の処理が割り込んで後回しにしても不具合に至るケースは稀なのですが、ハードウェアが関係する組込みシステムでは不具合につながるという例でした。

この記事が気に入ったらサポートをしてみませんか?