Bonjour,
Je viens d’équiper les systèmes odroid (c2 et c4 en armbian) de la box jeedom de mon fils et la mienne d’une horloge RTC.
Ca m’a pris du temps, car le peu de doc qu’on trouve concerne des odroid c2 et c4 en ubuntu ; et ça diffère pas mal.
J’ai utilisé des ‹ shield RTC › comme celui-ci : RTC Shield – ODROID ; achetés 2.40€ pièce chez domadoo, mais je crains avoir acheté la fin du stock …
Ce périphérique contient une puce pcf8563 ; il fonctionne en device i2c, à l’adresse 0x51.
La principale doc qui m’a été utile est celle-ci (malheureusement pour ubuntu) : https://wiki.odroid.com/accessory/add-on_boards/rtc_shield
Ce premier post concerne l’installation sur un odroid c2 ; le post suivant concernera les différences pour l’odroid c4.
Les deux systèmes sont en Bullseye
Installation sur odroid C2
En préalable, on constate que le support i2c est compilé dans le noyau ; le device /dev/i2c-0 correspond à l’interface i2c du GPIO (adresse c1108500), il est actif, et le support du pcf8563 est disponible en module.
/dev/rtc0 correspond à un device RTC virtuel, utilisé par le service fake-hwclock qui tente de faire pour le mieux coté horloge lors du boot, en l’absence d’une vrai horloge RTC.
# ls -al /dev/i2c*
crw-rw---- 1 root i2c 89, 0 6 juin 07:17 /dev/i2c-0
crw-rw---- 1 root i2c 89, 1 6 juin 07:17 /dev/i2c-1
# udevadm info /dev/i2c-0
P: /devices/platform/soc/c1100000.bus/c1108500.i2c/i2c-0/i2c-dev/i2c-0
# ls -al /dev/rtc*
lrwxrwxrwx 1 root root 4 6 juin 07:17 /dev/rtc -> rtc0
crw------- 1 root root 251, 0 6 juin 07:17 /dev/rtc0
# lsmod | grep rtc
rtc_meson_vrtc 16384 1
# apt install device-tree-compiler i2c-tools
# i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
...
50: -- 51 -- -- -- -- -- -- -- -- -- -- -- -- -- --
grace à i2cdetect, on voit que le pcf8563 est bien vu à l’adresse 51 sur /dev/i2c-0
################ premiers essais, pour vérifier le fonctionnement ###########################
On va charger le module correspondant au pcf8563 :
# lsmod | grep rtc
rtc_pcf8563 24576 0
rtc_meson_vrtc 16384 1
puis on informe le noyau de la présence d’un périphérique pcf8563 présent à l’adresse 0x51 sur /dev/ic2-0
# echo pcf8563 0x51 > /sys/class/i2c-adapter/i2c-0/new_device
# tail /var/log/syslog
2024-06-04T18:51:26.987235+02:00 odroidc2VM kernel: [10104.566303] rtc-pcf8563 0-0051: registered as rtc1
2024-06-04T18:51:26.992491+02:00 odroidc2VM kernel: [10104.569934] i2c i2c-0: new_device: Instantiated device pcf8563 at 0x51
# ls -al /dev/rtc*
lrwxrwxrwx 1 root root 4 3 juin 19:12 /dev/rtc -> rtc0
crw------- 1 root root 251, 0 3 juin 19:12 /dev/rtc0
crw------- 1 root root 251, 1 3 juin 19:18 /dev/rtc1
# i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
...
50: -- UU -- -- -- -- -- -- -- -- -- -- -- -- -- --
#### The "UU" indicates devices owned by the kernel, being managed by a device driver.
maintenant, on vérifie le fonctionnement du RTC avec hwclock
# hwclock -v --show -f /dev/rtc1
hwclock from util-linux 2.38.1
System Time: 1717435134.720866
Using the rtc interface to the clock.
Assuming hardware clock is kept in UTC time.
Waiting for clock tick...
ioctl(4, RTC_UIE_ON, 0): Argument invalide
Waiting in loop for time from /dev/rtc1 to change
...got clock tick
Time read from Hardware Clock: 2024/06/03 17:11:42
Hw clock time : 2024/06/03 17:11:42 = 1717434702 seconds since 1969
Time since last adjustment is 1717434702 seconds
Calculated Hardware Clock drift is 0.000000 seconds
2024-06-03 19:11:41.460319+02:00
##### lire la date de la RTC
# hwclock -r -f /dev/rtc1
#### écrire la date système dans la rtc :
# hwclock -w -f /dev/rtc1
############## rendre permanente la prise en charge du RTC ######################
Tout fonctionne donc correctement ; il reste maintenant à faire démarrer tout cela automatiquement lors du boot. il faut également que l’horloge RTC soit prise en compte au plus tôt ; donc on n’utilisera pas le fichier /etc/rc.local, qui serait traité trop tard.
Pour la prise en charge du module, c’est très simple : ajout de la ligne suivante dans /etc/modules
# cat /etc/modules
rtc_pcf8563
# reboot
Pour la déclaration du périphérique, on va créer un ‹ user overlay ›.
On créer un fichier DTS (source device-tree) comme celui-ci :
# cat meson-pcf8563.dts
/dts-v1/;
/plugin/;
/ {
compatible = "amlogic";
fragment@0 {
target-path = "/soc/bus@c1100000/i2c@8500";
__overlay__ {
pcf8563@51 {
compatible = "rtc-pcf8563,pcf8563";
reg = <0x51>;
status = "okay";
};
};
};
};
La commande suivante va compiler ce fichier vers /boot/overlay-user/meson-pcf8563.dtbo et déclarer le user overlay dans armbianEnv.txt :
# armbian-add-overlay meson-pcf8563.dts
# cat /boot/armbianEnv.txt
...
user_overlays=meson-pcf8563
# reboot
Au boot suivant, on vérifie que tout fonctionne corectement :
# ls -al /dev/rtc*
lrwxrwxrwx 1 root root 4 11 juin 08:45 /dev/rtc -> rtc0
crw------- 1 root root 251, 0 11 juin 08:45 /dev/rtc0
crw------- 1 root root 251, 1 11 juin 08:45 /dev/rtc1
# dmesg | grep rtc
[ 2.037327] meson-vrtc c81000a8.rtc: registered as rtc0
[ 2.037376] meson-vrtc c81000a8.rtc: setting system clock to 1970-01-01T00:00:02 UTC (2)
[ 3.751523] rtc-pcf8563 0-0051: registered as rtc1
Maintenant, on veut que le système soit mis à jour avec l’horloge RTC au boot, au plus tôt. Pour cela, on va créer puis activer un service (hwrtc) :
# cat /lib/systemd/system/hwrtc.service
[Unit]
Description=Synchronise System clock to hardware RTC
DefaultDependencies=no
After=systemd-modules-load.service fake-hwclock.service
Before=systemd-journald.service time-sync.target sysinit.target cron.service shutdown.target
Conflicts=shutdown.target
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/hwclock --hctosys --rtc=/dev/rtc1 --utc --noadjfile
RestrictRealtime=yes
[Install]
WantedBy=sysinit.target
# systemctl enable hwrtc
# reboot
On controle au boot suivant :
# dmesg | grep rtc
[ 2.037327] meson-vrtc c81000a8.rtc: registered as rtc0
[ 2.037376] meson-vrtc c81000a8.rtc: setting system clock to 1970-01-01T00:00:02 UTC (2)
[ 3.751523] rtc-pcf8563 0-0051: registered as rtc1
[ 3.833695] systemd[1]: Starting hwrtc.service - Synchronise System clock to hardware RTC...
[ 3.928232] systemd[1]: Finished hwrtc.service - Synchronise System clock to hardware RTC.
# systemctl status hwrtc
● hwrtc.service - Synchronise System clock to hardware RTC
Loaded: loaded (/lib/systemd/system/hwrtc.service; enabled; preset: enabled)
Active: active (exited) since Tue 2024-06-11 08:45:30 CEST; 18min ago
Process: 1161 ExecStart=/sbin/hwclock --hctosys --rtc=/dev/rtc1 --utc --noadjfile (code=exited, status=0/SUCCESS)
Main PID: 1161 (code=exited, status=0/SUCCESS)
CPU: 14ms
Maintenant, je ne suis pas certain que l’horloge du pcf8563 se mette à jour automatiquement à partir du système synchronisé en NTP. Je pense que c’est souhaitable pour éviter une dérive.
J’ai créé le script suivant, exécuté une fois par semaine ; il pourra également m’informer en cas de problème (pile déchargée, …)
#!/bin/bash
DEST=xxxx@yyyy
REPLYTO=xxxx@yyy
HOSTNAME=`hostname`
DATE=`date`
for i in {1..5}
do
/usr/sbin/ntpwait -v
RET=$?
if [ $RET -eq 0 ]; then
break
fi
sleep 2
done
if [ $RET -ne 0 ]; then
echo "ERREUR lors de la mise a jour de l'horloge RTC : synchro NTP" | mail -s "$HOSTNAME. erreur mise a jour horloge RTC, $DATE" -r $REPLYTO $DEST
fi
/usr/sbin/hwclock -w -f /dev/rtc1
if [ $? -ne 0 ]; then
echo "ERREUR lors de la mise a jour de l'horloge RTC, sur la commande hwclock" | mail -s "$HOSTNAME. erreur mise a jour horloge RTC, $DATE" -r $REPLYTO $DEST
fi
Et voila, l’horloge RTC fonctionne parfaitement sur mon système android c2 en armbian …