NVIDIA Jetson

【JetPack6対応版】DS3231 RTCモジュールの設定と起動時時刻自動更新する方法

【JetPack6対応版】DS3231 RTCモジュールの設定と起動時時刻自動更新する方法

― JetPack5の方法でJetPack6で動かなかった理由と解決まで ―

対象機種:Jetson Orin Nano Developer Kit
開発環境:JetPack 6

JetPack5では問題なく動いていたRTC(リアルタイムクロック)が、

JetPack6にバージョンアップ後、

同じやり方でRTC(リアルタイムクロック)を設定しても動作しませんでした。

 

「配線は合っているのに認識しない」

「i2cdetectで何も出ない、RTCを認識していない?」

 

原因はハードではなく、i2Cバス番号の違いでした。

この記事では、

どこを確認すればよいのか、どう設定すれば動くのかを、

「解説 → コマンド → 実行結果」 の流れで解説していきます。

※記事内にアフィリエイトが含まれています。

 

DS3231が認識されているか確認する

Jetson Orin Nanoが、RTCモジュール「DS3231」を認識しているかを

確認することから始めます。

今回使用するRTCは「DS3231」です。

【重要ポイント!】

DS3231のI2Cアドレスは 【 0x68 】 です。

I2Cバスをスキャンして「68」と表示されれば

RTC「DS3231」が認識されています。

① PIO-40ピンヘッダ設定を確認する

SDA / SCL がどのI2Cに設定されているか確認します。

PIO-40ピンヘッダの設定内容を確認するには、

コマンドから確認できます。

 

【40ピンヘッダ設定を確認するコマンド】

sudo /opt/nvidia/jetson-io/jetson-io.py

 

コマンドを実行すると以下の結果が表示されました。

【実行結果】

=================== Jetson Expansion Header Tool ===================
| |
| |
| 3.3V ( 1) .. ( 2) 5V |
| i2c8 ( 3) .. ( 4) 5V |
| i2c8 ( 5) .. ( 6) GND |
| unused ( 7) .. ( 8) uarta |
| GND ( 9) .. ( 10) uarta |
| unused ( 11) .. ( 12) unused |
| unused ( 13) .. ( 14) GND |
| unused ( 15) .. ( 16) unused |
| 3.3V ( 17) .. ( 18) unused |
| unused ( 19) .. ( 20) GND |
| unused ( 21) .. ( 22) unused |
| unused ( 23) .. ( 24) unused |
| GND ( 25) .. ( 26) unused |
| i2c2 ( 27) .. ( 28) i2c2 |
| unused ( 29) .. ( 30) GND |
| unused ( 31) .. ( 32) unused |
| unused ( 33) .. ( 34) GND |
| unused ( 35) .. ( 36) unused |
| unused ( 37) .. ( 38) unused |
| GND ( 39) .. ( 40) unused |
| |
| |
Jetson 40pin Header:

Configure for compatible hardware
Configure header pins manually
Back

実行結果の赤文字部分を見ます。

( 3) i2c8
( 5) i2c8

3番ピン(SDA)
5番ピン(SCL)

3番ピン(SDA)、5番ピン(SCL)は、「 i2c8 」に設定されています。

使うのは:i2cdetect -y 8 になります。

⚠ ここが重要

設定表示されている番号を確認する必要があります。

i2c8(ピン表示) ≠ i2c-8(Linuxデバイス)数字は一致しません。

 

② i2Cバスに接続されているデバイスを調べる

I2c-8 を試すとどうなる?

I2Cバス番号8をスキャンして、接続されているデバイスのアドレスを調べます。

【I2Cバス番号8を調べるコマンド】

sudo i2cdetect -y 8

 

【実行結果】

user@user-desktop:~$ sudo i2cdetect -y 8
[sudo] user のパスワード:
Error: Could not open file /dev/i2c-8′ or /dev/i2c/8′: No such file or directory

「Error:Could not open file」

「ファイルを開くことができませんでした」とエラーが出ています。

つまり、LinuxがI2Cデバイスにアクセスできなかったという結果です。

「 i2c8 」は、Linux上では別の番号になっています。

 

③ 実際に存在する i2Cバスを確認する

このLinuxに存在している「 i2C 」バスの一覧を表示するコマンドで調べてみます。

【i2Cバスの一覧を表示するコマンド】

sudo i2cdetect -l

 

 

【実行結果】

user@user-desktop:~$ sudo i2cdetect -l
i2c-0 i2c 3160000.i2c I2C adapter
i2c-1 i2c c240000.i2c I2C adapter
i2c-2 i2c 3180000.i2c I2C adapter
i2c-4 i2c Tegra BPMP I2C adapter I2C adapter
i2c-5 i2c 31b0000.i2c I2C adapter
i2c-7 i2c c250000.i2c I2C adapter
i2c-9 i2c NVIDIA SOC i2c adapter 0 I2C adapter

この中で注目するのが、

i2c-7 c250000.i2c

jetson-ioの表示にあった i2c8(c250000)と一致しています。

40ピンの i2c8 は Linuxでは「 i2c-7 」

である可能性が高いことになります。

 

④ i2c-7 をスキャンする

「i2c-7」 を調べてみます。

Quick Write ではなく Read モードでしか読めない場合もあるため確認します。

 

【i2Cバス番号8を調べるコマンド】

sudo i2cdetect -y 7

【Quick Write ではなく Read モードで確認コマンド】

sudo i2cdetect -r -y 7

 

【実行結果】

user@user-desktop:~$ sudo i2cdetect -r -y 7
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: — — — — — — — —
10: — — — — — — — — — — — — — — — —
20: — — — — — — — — — — — — — — — —
30: — — — — — — — — — — — — — — — —
40: — — — — — — — — — — — — — — — —
50: — — — — — — — 57 — — — — — — — —
60: — — — — — — — — 68 — — — — — — —

「68」が出ました!

DS3231(RTC本体)を認識しています!

0x57 → EEPROM(AT24C32)

0x68 → DS3231(RTC本体)

 

ここまでで、

✅ 配線 正常
✅ I2C通信 正常
✅ RTC 生きている

ことが確認できました。

 

DS3231をLinuxへ登録する

検出できただけでは、DS3231は使えないため、

使えるようにする為、DS3231をLinuxへデバイス登録していきます。

 

① RTCドライバを読み込む

RTCドライバを読み込んでいきます。

【RTCドライバ読込コマンド】

sudo modprobe rtc-ds1307

 

※ DS3231 は ds1307 ドライバで動きます。

 

② デバイス登録

RTCデバイスを登録していきます。

【RTCデバイスを登録コマンド】

echo ds3231 0x68 | sudo tee /sys/class/i2c-adapter/i2c-7/new_device

 

 

③ RTCデバイスを確認

Linuxに登録されているRTC(時計デバイス)を一覧表示します。

①ls :ファイルやディレクトリを表示するコマンド

②/dev:「ファイル」として扱われます。

※ /dev フォルダには、

USB・I2C・シリアル・RTCなどのデバイスファイルが入っている

④rtc*:* はワイルドカードでrtc で始まるファイルを全部表示する

 

【一覧表示するコマンド】

ls /dev/rtc*

 

【実行結果】

/dev/rtc
/dev/rtc0
/dev/rtc1
/dev/rtc2

Linuxが現在認識しているRTCデバイスが4つあります。

それぞれの意味

/dev/rtc:デフォルトのRTCを指しています(多くの場合 rtc0 へのリンク)。

/dev/rtc0:SoC内蔵のRTCである。

/dev/rtc1:電源管理用のRTCなど、別の内部時計。

/dev/rtc2:「新しいRTCデバイス(DS3231)」を認識して追加した。

 

 どれがDS3231か確認する

追加された「/dev/rtc2」のデバイスを確認します。

① cat:ファイルの中身を表示するコマンド

② /sys/class/rtc/:ここが重要です。

/dev → ハードを操作する入口

/sys → ハードの情報を見る場所という役割があります。

/sys/class/rtc/ には、

今Linuxが認識しているRTCデバイスの情報が入っています。

③ rtc0, rtc1, rtc2

これはそれぞれ

/dev/rtc0:(rtc0 の中身は何か?)
/dev/rtc1:(rtc1 の中身は何か?)
/dev/rtc2:(rtc2 の中身は何か?)

を調べます。

【デバイスの中身を表示するコマンド】

cat /sys/class/rtc/rtc0/name
cat /sys/class/rtc/rtc1/name
cat /sys/class/rtc/rtc2/name

 

【実行結果】

nvvrs-pseq-rtc
tegra_rtc c2a0000.rtc
rtc-ds1307 7-0068

この結果の意味

nvvrs-pseq-rtc → 電源制御系の内部RTC

tegra_rtc → Jetson本体に内蔵されているRTC

rtc-ds1307 7-0068 → 外付けRTC(DS3231)

※ DS3231は ds1307ドライバで動作するため、この名前になります。

「新しく rtc が増えています」

最初は

/dev/rtc
/dev/rtc0
/dev/rtc1

しかなかったのに、

ドライバを読み込み、登録すると

「 /dev/rtc2 」が増えます。

新しいRTCデバイス(DS3231)を認識されたことが確認できました。

 

✔ rtc0, rtc1, rtc2 の中身を確認する
✔ どれがDS3231なのか特定する
✔ hwclockで正しい番号を指定するための準備

という重要な確認作業です。

 

④ 時刻確認

時刻を確認します。

(Xは増えた番号)

【時刻確認するコマンド】

sudo hwclock -r -f /dev/rtcX

 

【実行結果】

rtc-ds1307 7-0068

これがDS3231です。

今回の場合は /dev/rtc2 です。

 

⑤ 時刻の読み込み

RTCからシステム時間に、時刻を読んでみます。

 

【時刻読み込みコマンド】

sudo hwclock -r -f /dev/rtc2

 

【実行結果】

2000-01-01 11:34:38

 

これは正常です。

新品や電池が入っていない場合、初期値は2000年になります。

 

⑥ 時刻の書き込み

システム時刻をRTCに、時刻を書き込んでみます。

インターネット接続して時刻を合わせた後に実行します。

【時刻を書き込むコマンド】

sudo hwclock -w -f /dev/rtc2

RTCに書き込まれているかを確認します。

<手順>

シャットダウン

電源を完全に抜く

10秒待つ

再起動(ネット未接続)

 

RTCから時刻を読み込みます。

【時刻を読み込むコマンド】

sudo hwclock -r -f /dev/rtc2

 

【実行結果】
2000-01-01 11:34:38.609865+09:00

正しい時刻が表示されれば成功です。

 

 

^^^^^^^^^^^^^^^^^^

<起動時RTCモジュールから時刻をシステム時刻に書き込む設定>

⑩ 起動時に自動で時刻を反映させる(JetPack6対応)

JetPack6では rc.local は使いません。
systemdサービスを作成します。

① サービスファイル作成
sudo nano /etc/systemd/system/ds3231.service

内容:

[Unit]
Description=DS3231 RTC setup
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/bin/bash -c “modprobe rtc-ds1307”
ExecStart=/bin/bash -c “echo ds3231 0x68 > /sys/class/i2c-adapter/i2c-7/new_device”
ExecStart=/sbin/hwclock -s -f /dev/rtc2
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
② サービス登録
sudo systemctl daemon-reload
sudo systemctl enable ds3231.service
③ 動作確認
sudo systemctl start ds3231.service

エラーがなければOKです。

最終テスト

シャットダウン

電源を完全に抜く

10秒待つ

起動(ネット未接続)

date

正しい時刻が表示されれば、完全成功です。

まとめ

JetPack6で一番の落とし穴は、

ピン表示の i2c8 と Linux上の i2c-7 が一致しないこと

ハードが壊れているわけではありません。
多くの場合、「番号の対応関係」が原因です。

組み込み開発では、

配線を疑う

バス番号を疑う

デバイス登録を確認する

この順番で考えると、必ず解決に近づきます。

同じように悩んでいる学生さんの助けになれば嬉しいです。