md
Module horloge et mémoire EEPROM I²C dans Rasberry Pi OS
2020-06-21
<-Module horloge et mémoire EEPROM I²C pour Raspberry Pi --

Ce billet contient des instructions sur la façon d'ajouter un module I²C avec une horloge en temps réel et une puce de mémoire EEPROM à un Raspberry Pi exécutant le système d'exploitation Raspberry Pi OS nouvellement publié. La grande puce du module est le DS3231, qui est l'horloge en temps réel, et la puce à 8 broches beaucoup plus petite est une EEPROM AT24C32 de 32 Ko (4K octets). Ce texte est une version corrigée de celui publié pour la première fois en février 2020. Il existe des différences entre Raspberry Pi OS et Raspbian Buster même si les deux systèmes d'exploitation sont basés sur Debian 10 et le noyau Linux 4.19 . La différence majeure est que dans Buster, le chargement du pilote de l'horloge en temps réel activait automatiquement le contrôleur I²C et ce n'est plus le cas dans la nouvelle version du système d'exploitation du Raspberry Pi. J'estime que les instructions contenues ici s'appliqueraient donc si Raspbian était encore utilisé sur le Raspberry Pi.

Il y a quelques problèmes avec la nouvelle mouture du système d'exploitation. L'installation dynamique du module I²C virtuel de l'arborescence des périphériques (device tree overlay) ne fonctionne pas. Le problème a déjà été résolu, mais le nouveau module doit être chargé manuellement comme expliqué ci-dessous. Cette étape ne sera pas nécessaire avec la prochaine version du système d'exploitation Raspberry Pi OS.

Table des matières

  1. I²C sur le Raspberry Pi
  2. Logiciels utiles
  3. Utilisation de l'horloge sur le bus I²C matériel
  4. Utilisation de la mémoire Flash sur le bus I²C matériel
  5. Utilisation de l'horloge sur le bus I²C émulé
  6. Utilisation de la mémoire Flash sur le bus I²C émulé
  7. Multiples bus I²C
  8. Raspberry Pi 4 et le Compute Module
  9. Le second bus I²C matériel
  10. Lecture de la température avec le DS3231
  11. Choix d'une pile

I²C sur le Raspberry Pi toc

p> I²C (Inter-Integrated Circuit ou encore TWI - Two Wire Interface) est un protocole de communication série fréquemment utilisé pour relier de nombreux dispositifs tels horloges, afficheurs, mémoires EEPROM, et sondes à un microcontrôleur. La communication, qui n'est pas très rapide, se fait à l'aide de deux signaux et une connexion vers la masse.

Tous les modèles Raspberry Pi ont un bus I²C matériel sur les broches 3 (SDA) et 5 (SCL) du connecteur d'entrée/sortie de 26 ou 40 broches selon le modèle. Cependant, le bus n'est pas activé par défaut et tant qu'il n'est pas activé les broches 3 et 5 sont des E/S générales. Des bus I²C virtuels peuvent être crées en ajoutant un module.

Alors que plusieurs dispositifs peuvent être connectés simultanément au bus I²C, seuls deux dispositifs peuvent échanger des données à un moment donné. Le dispositif qui initie la connexion est le maître, le destinateur est l'esclave. Le bus peut comprendre plus d'un maître, mais l'échange de données entre maîtres est impossible, de même qu'entre esclaves. De plus un esclave ne peut initier la communication avec un maître. Voir Understanding the I²C Bus, Texas Instruments Application Report SLVA704, p. 3. de Jonathan Valdez et Jared Becker (juin 2015).

En principe, un dispositif peut être maître ou esclave; jamais les deux simultanément. En pratique, la plupart des dispositifs plus simples ne sont que des esclaves et seuls les microcontrôleurs ont la possibilité d'être esclave en plus d'être maître, mais ce n'est pas toujours le cas. D'ailleurs, il semble que le Raspberry Pi n'est pas en mesure de mettre son bus I²C en mode esclave.

On s'en doute, un bus I²C est représenté par un fichier dans le répertoire des périphériques /dev dans Linux. À titre d'exemple, il y a trois bus I²C activés sur un Orange Pi PC 2.

opipc@orangepipc2:~$ ls -l /dev/i2* crw-rw---- 1 root i2c 89, 0 Feb 16 04:02 /dev/i2c-0 crw-rw---- 1 root i2c 89, 1 Feb 16 04:02 /dev/i2c-1 crw-rw---- 1 root i2c 89, 2 Feb 16 04:02 /dev/i2c-2

Et voici la liste des périphériques I²C sur un Raspberry Pi 3 B dont le bus I²C matériel a été activé.

woopi@goldserver:~ $ ls -l /dev/i2c* crw-rw---- 1 root i2c 89, 1 Feb 10 22:17 /dev/i2c-1

Logiciels utiles toc

Trois logiciels sont utilisés ci-dessous. Il y a i2cdetect et ic2get qui sont contenus dans le paquet i2c-tools. Le premier affiche l'adresse des dispositifs branchés sur un bus I²C. Le second peut lire les registres d'un esclave I²C. L'installation du paquet i2c-tools est très simple.

woopi@goldserver:~ $ sudo apt install -y i2c-tools

Pour en faciliter l'utilisation, j'ai ajouté l'utilisateur par défaut du Pi au groupe i2c. Sinon, il sera nécessaire d'obtenir les privilèges root lors de l'exécution de tout utilitaire dans le paquet ajouté ci-dessus. En d'autres termes, chaque fois que i2cdetect et i2cget sont invoqués, il sera nécessaire d'utiliser le préfixe sudo si l'utilisateur ne fait pas partie du groupe i2c. L'ajout de l'utilisateur par défaut n'est pas du tout complexe.

woopi@goldserver:~ $ sudo adduser $USER i2c Adding user `woopi' to group `i2c' ... Adding user woopi to group i2c Done.

Cependant, il faut redémarrer la session (en se déconnectant puis en se reconnectant) pour mettre à jour les autorisations utilisateur.

L'installation du programme eeprog qui peut écrire et lire sur la mémoire EEPROM est un peu plus complexe. Il faut obtenir le code source et compiler l'utilitaire. De plus, plusieurs versions de eeprog sont disponibles sur le Web. Les seules qui fonctionnent sont la version « tear» du logiciel eeprog élaboré par Kris Rusocki ou des dérivées de celle-ci dont celle de Ján Sáreník sur GitHub.

woopi@goldserver:~ $ wget https://github.com/jsarenik/eeprog/archive/master.zip --2020-01-29 19:10:06-- https://github.com/jsarenik/eeprog/archive/master.zip ... 2020-01-29 19:10:07 (268 KB/s) - ‘master.zip’ saved [19445] woopi@goldserver:~ $ unzip 0.7.7_master.zip ... woopi@goldserver:~ $ mv eeprog-master eeprog woopi@goldserver:~ $ cd eeprog woopi@goldserver:~/eeprog $ make ...

Le problème avec les versions originales de eeprog est qu'en écriture elles utilisent une fréquence trop élevée. Il faut ralentir la cadence. La fréquence I²C de l'EEPROM AT24C32 dépend de l'alimentation. Il se peut que l'on puisse enregistrer des données avec la version originale de eeprog sur l'EEPROM AT24C32 si l'alimentation de ce dernier est à 5 volts. Avec un tel potentiel, le signal de synchronisation de l'EEPROM peut atteindre 400 kHz. Toutefois, le module doit fonctionner à 3,3 volts parce qu'il est branché à un Raspberry Pi. Or la fréquence d'opération I²C de l'EEPROM diminue rapidement lorsque la tension est réduite. Je ne sais pas la valeur exacte de cette fréquence à 3,3 volts, mais à 2,7 volts la fréquence maximale est réduite à 100 kHz.

Ni i2c-tools, ni eeprog ne sont nécessaire au fonctionnement de l'horloge et de la mémoire Flash. On pourra donc tout éliminer plus tard si désiré. Voici comment faire.

woopi@goldserver:~/some_dir/or_other $ cd ~ woopi@goldserver:~ $ rm eeprog-0.7.7_master.zip woopi@goldserver:~ $ rm -r eeprog woopi@goldserver:~ $ sudo apt purge i2c-tools -y

Utilisation de l'horloge sur le bus I²C matériel toc

Le branchement du module est très facile puisque les connexions sont très bien indiquées sur la plaquette. Au minimum, il faut relier quatre broches de cette dernière aux broches correspondantes du connecteur E/Sdu Raspberry Pi: l'alimentation et la masse (VCC et GND) et les signaux de données et de synchronisation (SDA et SCL) du bus I²C. Pour des raisons exposées plus loin, je n'ai pas installé de pile initialement.

Initialement, on peut installer temporairement le module I²C et le pilote de l'horloge. Deux commandements réalisent ces deux tâches. Après on peut vite confirmer l'action.

woopi@goldserver:~ $ sudo dtparam i2c_arm=on woopi@goldserver:~ $ sudo dtoverlay i2c-rtc ds3231 woopi@goldserver:~ $ ls -l /dev/i2c* /dev/rt* crw-rw---- 1 root i2c 89, 1 Jan 29 02:57 /dev/i2c-1 lrwxrwxrwx 1 root root 4 Jan 29 02:57 /dev/rtc -> rtc0 crw------- 1 root root 253, 0 Jan 29 02:57 /dev/rtc0

Le périphérique i2c-1 (on dit aussi contrôleur) a été crée, ainsi que le périphérique rtc0 qui communique avec l'horloge par l'entremise du contrôleur i2c-1. La commande i2cdetect affiche les adresses des dispositifs branchés sur le bus I²C matériel.

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

Deux dispositifs ont été trouvés. Le premier est la mémoire Flash (eeprom) à l'adresse 0x57 et le second est l'horloge à l'adresse 0x68. Le UU est une indication qu'un pilote a pris en charge le dispositif.

woopi@goldserver:~ $ sudo hwclock -v hwclock from util-linux 2.33.1 System Time: 1580275162.357510 Trying to open: /dev/rtc0 Using the rtc interface to the clock. Last drift adjustment done at 1580060171 seconds after 1969 Last calibration done at 1580060171 seconds after 1969 Hardware clock is on UTC time Assuming hardware clock is kept in UTC time. Waiting for clock tick... ioctl(3, RTC_UIE_ON, 0): Invalid argument Waiting in loop for time from /dev/rtc0 to change ...got clock tick Time read from Hardware Clock: 2020/01/29 05:19:23 Hw clock time : 2020/01/29 05:19:23 = 1580275163 seconds since 1969 Time since last adjustment is 214992 seconds Calculated Hardware Clock drift is 0.000000 seconds 2020-01-29 01:19:22.840443-04:00

Clairement l'horloge matérielle est en fonction. On peut être surpris de voir que l'heure est juste en l'absence d'une pile. L'explication est simple. Le système d'exploitation, ou plus précisément le composant systemd-timesync, obtient l'heure actuelle d'un serveur de référence SNTP lors du démarrage du Raspberry Pi. Dès que pilote i2c-rtc est installé, le système ajuste l'horloge matérielle.

Puisque tout fonctionne, on peut installer i2c-rtc de façon permanente en ajoutant la commande dtparam pour activer le contrôleur I²C et la commande dtoverlay pour charger le pilote de l'horloge dans le fichier de configuration du système d'exploitation.

woopi@goldserver:~ $ sudo nano /boot/config.txt

... # Uncomment some or all of these to enable the optional hardware interfaces dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on # For access to I2C RTC and other I2C devices on hardware I2C bus (SDA on GPIO2, SCL on GPIO3) dtoverlay=i2c-rtc,ds3231 ...

Il n'est pas nécessaire d'activer le protocole I²C avec l'utilitaire raspi-config. Auparavant, je disais qu'il fallait aussi modifier le script qui ajuste l'heure de l'horloge matérielle quand le module i2c-rtc est embarqué. Voici comment faire.

woopi@goldserver:~ $ sudo nano /lib/udev/hwclock-set

Normalement le script ne fait rien, car son exécution est arrêtée dès le test initial, du moins dans les distributions utilisant systemd dont Raspberry Pi OS. Il faut enlever ce test ou l'escamoter avec des « # » au début des lignes ce qui les transforme en commentaires.

#!/bin/sh # Reset the System Clock to UTC if the hardware clock from which it # was copied by the kernel was in localtime. dev=$1 #if [ -e /run/systemd/system ] ; then # exit 0 #fi ...

Ceci n'est probablement pas une bonne idée. À la prochaine mise à jour, le script /lib/udev/hwclock-set sera écrasé, remplacé par la version originale. Voir Debian Bug report logs - #855203 hwclock-set: Synchronize from hwclock despite systemd presence

Utilisation de la mémoire Flash sur le bus I²C matériel toc

Si l'on a installé l'horloge comme indiqué à la section précédente, on peut immédiatement vérifier qu'il est possible d'écrire et de lire le EEPROM AT24C32. Autrement, le bus I²C n'est pas encore en service.

woopi@goldserver:~ $ i2cdetect -l woopi@goldserver:~ $ ls /dev/i2* ls: cannot access '/dev/i2*': No such file or directory

L'installation temporaire du module i2c1 qui met en œuvre le bus I²C matériel broches E/S 2 et 3 est très simple.

woopi@goldserver:~ $ sudo dtparam i2c_arm=on woopi@goldserver:~ $ ls -l /dev/i2c* crw-rw---- 1 root i2c 89, 1 Jun 21 20:52 /dev/i2c-1

Si on affiche les adresses des dispositifs I²C branchés sur le bus 1 quand le module de prise en charge du bus est i2c1 on en observe deux au minimum.

woopi@goldserver:~ $ i2cdetect -y 1 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 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --

L'adresse 0x57 est celle du EEPROM AT24C32 (en réalité c'est l'adresse par défaut qu'on peut modifier avec quelques soudures). L'adresse 0x68 est celle de l'horloge matérielle. Parce que seul le bus I²C est activé et qu'aucun pilote pour l'horloge n'a été chargé, i2detect montre l'adresse 0x68 et non le UU comme à la section précédente.

Si le module i2c-rtc a été installé plutôt que i2c1, alors i2cdetect affiche les adresses des dispositifs en indiquant que le pilote de l'horloge est en place.

woopi@goldserver:~ $ i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --

Puisque le bus I²C est activé et que l'adresse du EEPROM est connue, on peut écrire un message dans la mémoire et puis lire celle-ci pour s'assurer que l'accès est possible.

woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-1 0x57 -r 0:29 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-1, Address: 0x57, Mode: 16bit Operation: read 29 bytes from offset 0, Output file: <stdout> Reading 29 bytes from 0x0 Lorem ipsum dolor si... woopi@goldserver:~ $ echo "This is working!" | eeprog/eeprog -f -16 -w 0x00 -t 2 /dev/i2c-1 0x57 eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-1, Address: 0x57, Mode: 16bit Operation: write at offset 0, Input file: <stdin> Write cycle time: 2 milliseconds Writing <stdin> starting at address 0x0 ................. woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-1 0x57 -r 0:18 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-1, Address: 0x57, Mode: 16bit Operation: read 18 bytes from offset 0, Output file: <stdout> Reading 18 bytes from 0x0 This is working!

Utilisation de l'horloge sur le bus I²C émulé toc

Les anciens modèles du Rapsberry Pi n'ont qu'un seul bus matériel I²C dont l'utilisation est facile et assurée; les exceptions sont le modèle Pi 4 et le Compute module. Si la broche E/S 2 ou 3 sert à d'autres fin, on peut créer un bus I²C virtuel avec le module i2c-rtc-gpio.

woopi@goldserver:~ $ sudo dtoverlay -h i2c-rtc-gpio Name: i2c-rtc-gpio Info: Adds support for a number of I2C Real Time Clock devices using the software i2c controller Usage: dtoverlay=i2c-rtc-gpio,<param>=<val> Params: abx80x Select one of the ABx80x family: AB0801, AB0803, AB0804, AB0805, AB1801, AB1803, AB1804, AB1805 ds1307 Select the DS1307 device ds1339 Select the DS1339 device ds3231 Select the DS3231 device m41t62 Select the M41T62 device mcp7940x Select the MCP7940x device mcp7941x Select the MCP7941x device pcf2127 Select the PCF2127 device pcf2129 Select the PCF2129 device pcf8523 Select the PCF8523 device pcf8563 Select the PCF8563 device rv3028 Select the Micro Crystal RV3028 device addr Sets the address for the RTC. Note that the device must be configured to use the specified address. trickle-diode-type Diode type for trickle charge - "standard" or "schottky" (ABx80x only) trickle-resistor-ohms Resistor value for trickle charge (DS1339, ABx80x, RV3028) wakeup-source Specify that the RTC can be used as a wakeup source backup-switchover-mode Backup power supply switch mode. Must be 0 for off or 1 for Vdd < VBackup (RV3028 only) i2c_gpio_sda GPIO used for I2C data (default "23") i2c_gpio_scl GPIO used for I2C clock (default "24") i2c_gpio_delay_us Clock delay in microseconds (default "2" = ~100kHz)

Comme on peut voir les E/S GPIO23 et GPIO24 seront utilisées pour les signaux SDA et SCL respectivement. Si le module i2c-rtc a été ajouté au fichier de configuration /boot/config.txt, il doit être enlevé et le Pi doit être redémarrer. Si le module était chargé temporairement, on peut le retirer avec l'utilitaire dtoverlay. Dès qu'on sait qu'il n'y a plus de périphérique pour l'horloge, on peut installer i2c-rtc-gpio.

woopi@goldserver:~ $ sudo dtoverlay -l Overlays (in load order): 0: dtparam i2c_arm=on woopi@goldserver:~ $ sudo dtoverlay -r 0 woopi@goldserver:~ $ ls /dev/rtc ls: cannot access '/dev/rtc': No such file or directory woopi@goldserver:~ $ sudo dtoverlay i2c-rtc-gpio ds3231 woopi@goldserver:~ $ woopi@goldserver:~ $ ls -l /dev/rt* ls: cannot access '/dev/rt*': No such file or directory

Tout comme dans Raspbian Buster, le module ne pouvait pas être chargé au moment de l'exécution, mais au moins il n'était pas nécessaire de redémarrer en raison d'une erreur de segmentation. Il peut être chargé au démarrage si le fichier de configuration système est modifié.

woopi@goldserver:~ $ sudo nano /boot/config.txt

# Uncomment some or all of these to enable the optional hardware interfaces #dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on ... # For access to I2C RTC and other I2C devices on software I2C bus (SDA on GPIO23, SCL on GPIO24 by default) dtoverlay=i2c-rtc-gpio,ds3231 ...

Après un redémarrage, le bus I²C virtuel et le périphérique de l'horloge sont installés correctement.

woopi@goldserver:~ $ sudo i2cdetect -l i2c-3 i2c i2c-gpio-rtc@0 I2C adapter woopi@goldserver:~ $ sudo i2cdetect -y 3 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- woopi@goldserver:~ $ sudo hwclock -v hwclock from util-linux 2.33.1 System Time: 1580409344.320549 Trying to open: /dev/rtc0 Using the rtc interface to the clock. Last drift adjustment done at 1580060171 seconds after 1969 Last calibration done at 1580060171 seconds after 1969 Hardware clock is on UTC time Assuming hardware clock is kept in UTC time. Waiting for clock tick... ioctl(3, RTC_UIE_ON, 0): Invalid argument Waiting in loop for time from /dev/rtc0 to change ...got clock tick Time read from Hardware Clock: 2020/01/30 18:35:45 Hw clock time : 2020/01/30 18:35:45 = 1580409345 seconds since 1969 Time since last adjustment is 349174 seconds Calculated Hardware Clock drift is 0.000000 seconds 2020-01-30 14:35:44.845273-04:00

Utilisation de la mémoire Flash sur le bus I²C émulé toc

Si le module i2c-rtc-gpio a été installé comme expliqué à la section précédente, alors on peut communiquer avec la mémoire Flash à l'adresse 0x57 sur le périphérique i2c-3. S'il n'y a pas d'horloge avec la mémoire Flash alors on ajoute le module i2c-gpio.

woopi@goldserver:~ $ dtoverlay -h i2c-gpio Name: i2c-gpio Info: Adds support for software i2c controller on gpio pins Usage: dtoverlay=i2c-gpio,<param>=<val> Params: i2c_gpio_sda GPIO used for I2C data (default "23") i2c_gpio_scl GPIO used for I2C clock (default "24") i2c_gpio_delay_us Clock delay in microseconds (default "2" = ~100kHz) bus Set to a unique, non-zero value if wanting multiple i2c-gpio busses. If set, will be used as the preferred bus number (/dev/i2c-<n>). If not set, the default value is 0, but the bus number will be dynamically assigned - probably 3.

Sans surprise, le module i2c-rtc-gpio n'a pas pu être chargé dynamiquement au moment de l'exécution.

woopi@goldserver:~ $ sudo dtoverlay i2c-gpio * Failed to apply overlay '0_i2c-gpio' (kernel)

Pire encore, le Pi ne démarrerait plus après une modification du fichier de configuration pour charger le module au démarrage en insérant la ligne suivante.

# for access to I2C devices on software I2C bus (SDA on GPIO23, SCL on GPIO24 by default) dtoverlay=i2c-gpio

woopi@goldserver:~ $ sudo reboot [ 690.133676] reboot: Restarting system

Le Pi se bloquait à ce stade. J'ai du retirer la carte SD pour l'insérer dans le lecteur de carte SD de l'ordinateur de bureau pour supprimer la ligne dtoverlay=i2c-gpio du fichier /boot/config.txt. Il était alors possible de redémarrer le Pi à partir de la carte SD corrigée.

Ce problème a été corrigé, mais cette correction n'est pas encore intégrée au système d'exploitation. Voici une façon de remplacer le module fautif d'après les indications by PhilE.

woopi@goldserver:~ $ sudo mv /boot/overlays/i2c-gpio.dtbo /boot/overlays/i2c-gpio.dtbo-bad woopi@goldserver:~ $ sudo wget https://github.com/raspberrypi/firmware/raw/master/boot/overlays/i2c-gpio.dtbo -O /boot/overlays/i2c-gpio.dtbo --2020-06-22 04:37:58-- https://github.com/raspberrypi/firmware/raw/master/boot/overlays/i2c-gpio.dtbo ... Length: 1055 (1.0K) [application/octet-stream] ... woopi@goldserver:~ $ sudo dtoverlay i2c-gpio woopi@goldserver:~ $ i2cdetect -l i2c-3 i2c ffffffff.i2c I2C adapter woopi@goldserver:~ $ i2cdetect -y 3 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 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --

Comme on peut le voir, le nouveau module (qui fera partie du noyau 5.4) peut être chargé au moment de l'exécution sans problème. L'adresse 0x68 ne sera pas affichée s'il n'y a pas d'horloge I²C. L'EEPROM est accessible comme auparavant, mais le bus I²C doit être réglé; c'est maintenant i2c-3.

woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-3 0x57 -r 0:29 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-3, Address: 0x57, Mode: 16bit Operation: read 29 bytes from offset 0, Output file: <stdout> Reading 29 bytes from 0x0 Lorem ipsum dolor si... woopi@goldserver:~ $ echo "* A new EEPROM *" | eeprog/eeprog -f -16 -w 0x00 -t 2 /dev/i2c-3 0x57 eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-3, Address: 0x57, Mode: 16bit Operation: write at offset 0, Input file: <stdin> Write cycle time: 2 milliseconds Writing <stdin> starting at address 0x0 ................. woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-3 0x57 -r 0:18 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-3, Address: 0x57, Mode: 16bit Operation: read 18 bytes from offset 0, Output file: <stdout> Reading 18 bytes from 0x0 * A new EEPROM *

Multiples bus I²C toc

Il est possible d'avoir plus d'un bus I²C en place. Voici la partie pertinente du fichier /boot/config.txt qui active le bus matériel et un bus virtuel simultanément.

... # Uncomment some or all of these to enable the optional hardware interfaces dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on
# For access to I2C RTCand other I2C devices on hardware I2C bus (SDA on GPIO2, SCL on GPIO3) dtoverlay=i2c-rtc,ds3231 # For access to I2C devices other than RTC on software i2c bus (SDA on GPIO23, SCL on GPIO24 by default) dtoverlay=i2c-gpio
...


woopi@goldserver:~ $ ls /dev/i2c* /dev/i2c-1 /dev/i2c-3 woopi@goldserver:~ $ i2cdetect -l i2c-3 i2c ffffffff.i2c I2C adapter i2c-1 i2c bcm2835 I2C adapter I2C adapter woopi@goldserver:~ $ i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- woopi@goldserver:~ $ i2cdetect -y 3 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 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- woopi@goldserver:~ $ sudo hwclock -v hwclock from util-linux 2.33.1 System Time: 1580420342.707524 Trying to open: /dev/rtc0 Using the rtc interface to the clock. Last drift adjustment done at 1580060171 seconds after 1969 Last calibration done at 1580060171 seconds after 1969 Hardware clock is on UTC time Assuming hardware clock is kept in UTC time. Waiting for clock tick... ioctl(3, RTC_UIE_ON, 0): Invalid argument Waiting in loop for time from /dev/rtc0 to change ...got clock tick Time read from Hardware Clock: 2020/01/30 21:39:04 Hw clock time : 2020/01/30 21:39:04 = 1580420344 seconds since 1969 Time since last adjustment is 360173 seconds Calculated Hardware Clock drift is 0.000000 seconds 2020-01-30 17:39:03.151299-04:00 woopi@goldserver:~ $ echo "Hardware I2C bus" | eeprog/eeprog -f -16 -w 0x00 -t 2 /dev/i2c-1 0x57 eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-1, Address: 0x57, Mode: 16bit Operation: write at offset 0, Input file: <stdin> Write cycle time: 2 milliseconds Writing <stdin> starting at address 0x0 ................. woopi@goldserver:~ $ echo "Software I2C bus" | eeprog/eeprog -f -16 -w 0x00 -t 2 /dev/i2c-3 0x57 eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-3, Address: 0x57, Mode: 16bit Operation: write at offset 0, Input file: <stdin> Write cycle time: 2 milliseconds Writing <stdin> starting at address 0x0 ................. woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-1 0x57 -r 0:18 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-1, Address: 0x57, Mode: 16bit Operation: read 18 bytes from offset 0, Output file: <stdout> Reading 18 bytes from 0x0 Hardware I2C bus 4woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-3 0x57 -r 0:18 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-3, Address: 0x57, Mode: 16bit Operation: read 18 bytes from offset 0, Output file: <stdout> Reading 18 bytes from 0x0 Software I2C bus

On peut choisir quelle horloge à installer, car il n'est pas nécessaire d'utiliser le bus matériel. Avec la configuration suivante, l'horloge reliée au bus logiciel sera activée.

... # Uncomment some or all of these to enable the optional hardware interfaces dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on
# For access to I2C RTCand other I2C devices on hardware I2C bus (SDA on GPIO2, SCL on GPIO3) dtoverlay=i2c-rtc-gpio,ds3231
...

Les commandes habituelles peuvent être émises après le redémarrage pour confirmer que les deux modules RTC-EEPROM sont disponibles sur les deux bus I²C et que le pilote de l'horloge en temps réel est connecté au bus logiciel.

woopi@goldserver:~ $ ls /dev/i2c* /dev/i2c-1 /dev/i2c-3 woopi@goldserver:~ $ i2cdetect -y 1 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 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- woopi@goldserver:~ $ i2cdetect -y 3 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- 57 -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- UU -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- --

Sur le Raspberry Pi 3 B, le module i2c-rtc-gpio va créer le bus 3 ou bien le contrôleur logiciel ne sera pas installé. Pour être plus précis, si les modules sont chargés dans l'ordre suivant dans /boot/config.txt

dtoverlay=i2c-gpio,bus=3 dtoverlay=i2c-rtc-gpio,ds3231
alors le pilote de l'horloge est chargé et il utilise le contrôleur logiciel I²C sur le bus 3 et le module i2c-gpio ne peut pas installer le contrôleur logiciel I²C en raison du conflit de numéro de bus.

woopi@goldserver:~ $ i2cdetect -l i2c-3 i2c i2c-gpio-rtc@0 I2C adapter i2c-1 i2c bcm2835 I2C adapter I2C adapter woopi@goldserver:~ $ dmesg | grep i2c [ 2.944681] i2c /dev entries driver [ 4.120751] gpio-23 (i2c-gpio-rtc@0): enforced open drain please flag it properly in DT/ACPI DSDT/board file [ 4.120828] gpio-24 (i2c-gpio-rtc@0): enforced open drain please flag it properly in DT/ACPI DSDT/board file [ 4.121708] i2c-gpio i2c-gpio-rtc@0: using lines 23 (SDA) and 24 (SCL) [ 4.121946] i2c-gpio 3.i2c: error trying to get descriptor: -16 [ 4.121971] i2c-gpio: probe of 3.i2c failed with error -16

Si les modules sont dans l'ordre suivant dans /boot/config.txt

If the overlays are in the following order in /boot/config.txt

dtoverlay=i2c-rtc-gpio,ds3231 dtoverlay=i2c-gpio,bus=3

alors le pilote de l'horloge n'est pas chargé.

woopi@goldserver:~ $ i2cdetect -l i2c-3 i2c 3.i2c I2C adapter i2c-1 i2c bcm2835 I2C adapter I2C adapter woopi@goldserver:~ $ dmesg | grep i2c [ 2.858077] i2c /dev entries driver [ 4.054726] i2c-gpio 3.i2c: using lines 23 (SDA) and 24 (SCL) [ 4.054966] i2c-gpio i2c-gpio-rtc@0: error trying to get descriptor: -16 [ 4.054990] i2c-gpio: probe of i2c-gpio-rtc@0 failed with error -16

Contrairement à des commentaires lus sur les forums, il ne semble pas y avoir de contraintes sur le numéro de bus I²C ni sur la séquence de création des bus.

... # Uncomment some or all of these to enable the optional hardware interfaces dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on
dtoverlay=i2c-gpio,bus=6,i2c_gpio_sda=27,i2c_gpio_scl=22 # For access to I2C RTCand other I2C devices on hardware I2C bus (SDA on GPIO2, SCL on GPIO3) dtoverlay=i2c-rtc,ds3231 # For access to I2C devices other than RTC on software i2c bus (SDA on GPIO23, SCL on GPIO24 by defa$ dtoverlay=i2c-gpio,bus
...

woopi@goldserver:~ $ i2cdetect -l i2c-3 i2c ffffffff.i2c I2C adapter i2c-1 i2c bcm2835 I2C adapter I2C adapter i2c-6 i2c 6.i2c I2C adapter

... # Uncomment some or all of these to enable the optional hardware interfaces dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on
# For access to I2C devices other than RTC on software i2c bus (SDA on GPIO23, SCL on GPIO24 by default) dtoverlay=i2c-gpio # For access to I2C RTCand other I2C devices on hardware I2C bus (SDA on GPIO2, SCL on GPIO3) dtoverlay=i2c-rtc,ds3231 dtoverlay=i2c-gpio,bus=9,i2c_gpio_sda=27,i2c_gpio_scl=22
...

woopi@goldserver:~ $ i2cdetect -l i2c-3 i2c ffffffff.i2c I2C adapter i2c-1 i2c bcm2835 I2C adapter I2C adapter i2c-9 i2c 9.i2c I2C adapter

La seule contrainte est qu'il ne doit pas y avoir de conflit dans le numéro de bus. Il est même possible de créer un contrôleur I²C virtuel pour le bus 1 si le bus I²C matériel n'est pas activé.

... # Uncomment some or all of these to enable the optional hardware interfaces #dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on
# for access to I2C devices on software I2C bus (SDA on GPIO23, SCL on GPIO24 by default) dtoverlay=i2c-gpio # Create software I2C bus 1 dtoverlay=i2c-gpio,bus=1,i2c_gpio_sda=27,i2c_gpio_scl=22
...

woopi@goldserver:~ $ i2cdetect -l i2c-3 i2c ffffffff.i2c I2C adapter i2c-1 i2c 1.i2c I2C adapter

Cependant, il semble que les bus 0 et 2 soient réservés par le système.

Raspberry Pi 4 et le Compute Module toc

Je n'ai ni module de calcul ni Raspberry Pi 4, donc ce que je vais dire n'est pas basé sur l'expérience et peut donc être complètement faux. Il semble très clair qu'il existe plus de 2 bus matériels I²C sur ces appareils. Consultez la liste des module I²C de l'arborescence des périphériques disponibles.

woopi@goldserver:~ $ dtoverlay -a | grep i2c bmp085_i2c-sensor i2c-bcm2708 i2c-gpio i2c-mux i2c-pwm-pca9685a i2c-rtc i2c-rtc-gpio i2c-sensor i2c0 i2c0-bcm2708 i2c1 i2c1-bcm2708 i2c3 i2c4 i2c5 i2c6 sc16is750-i2c sc16is752-i2c

La plupart des schémas de brochage E/S du Raspberry Pi affichent uniquement la fonction par défaut des broches. Les bus matériels 3 à 6 n'apparaissent pas sur ces schémas, car que ce sont des fonctions dites "alternatives" de certaines broches d'E/S. Une exception, Raspberry Pi 4 Model B Default GPIO Pinout with PoE Header, de Element 14, est un graphique compact et bien clair des 6 fonctions alternatives des 30 broches d'E/S de connecteur de 40 broches (les 10 autres broches sont les connexions d'alimentation et de terre). Malheureusement, une recherche de texte pour trouver SDA3 par exemple ne peut pas être effectuée pour savoir sur quelles broches elle est disponible. Il y a un autre schéma sur les forums Raspberry Pi par clicky qui identifie clairement les bus I²C supplémentaires disponibles uniquement sur le modèle 4. La source faisant autorité et accessible à tous est peut être le document PDF intitulé BCM2711 ARM Peripherals Version 1, 5th February 2020, Raspberry Pi (Trading) Ltd. Voir les pages 98 à 100 de la section Section 5.3. Alternative Function Assignments of Chapter 5. General Purpose I/O (GPIO).

La documentation de certains de ces contrôleurs matériels I²C mentionne des « transactions combinées » qui me laissait un peu perplexe.

woopi@goldserver:~ $ dtoverlay -h i2c0 Name: i2c0 Info: Change i2c0 pin usage. Not all pin combinations are usable on all platforms - platforms other then Compute Modules can only use this to disable transaction combining. Usage: dtoverlay=i2c0,<param>=<val> Params: pins_0_1 Use pins 0 and 1 (default) pins_28_29 Use pins 28 and 29 pins_44_45 Use pins 44 and 45 pins_46_47 Use pins 46 and 47 combine Allow transactions to be combined (default "yes")

La réponse suivante de Phil Elwell (pelwell) au problème intitulé smbus read_i2c_block_data Fails on Latest Kernel #828

My theory is that the I2C device you are trying to control does not support repeated starts. If you find that everything springs into life with the old driver, try repeating your test after turning on the "combined" module parameter ...

me fait penser que lorsque les transactions ne sont pas combinées, un bloc d'octets est envoyé un octet à la fois avec un octet d'adresse précédant chaque octet de données. Une transaction combinée aurait un seul octet d'adresse précédant le bloc d'octets de données. Voir aussi Transaction format de la page I²C de Wikipedia.

La nécessité de prendre des précautions avec la terminaison des lignes SDA et SCL, surtout pour ce qui est des bus I²C alternatifs, devient évidente à la lecture des problèmes de connexion I²C. Ce n'est pas un problème avec le module qui est utilisé ici, car il possède des résistances de tirage facilement identifiées près de la puce EEPROM. Cependant, avec un dispostif I²C sans résistances de rappel, il se peut que les résistances de tirage internes du Raspberry Pi ne soient pas suffisantes (c'est-à-dire qu'elles peuvent avoir une valeur trop élevée pour pouvoir tirer les lignes à 3,3 volts lorsque l'esclave et le maître les laissent flotter).

Le second bus I²C matériel toc

Si le connecteur E/S du Raspberry Pi possède 40 broches, il y a un deuxième bus I²C matériel qui est affecté à l'identification des cartes d'extensions (les HAT) en utilisant les broches 27 (ID_SD) et 28 (ID_SC). En principe on ne devrait pas se servir de ce bus. Les avertissements sont nombreux à ce sujet. La Fondation Raspberry le dit deux fois plutôt qu'une dans ses instructions sur la conception des cartes d'extensions. Dans les alinéas GPIO Requirements et ID EEPROM il y a le même passage:

Within the set of pins available on the GPIO header, ID_SC and ID_SD (GPIO0/SCL and GPIO1/SDA) are reserved for board detection / identification. The only allowed connections to the ID_ pins are an ID EEPROM plus 3.9K pull up resistors. Do not connect anything else to these pins!

On retrouve sensiblement le même avertissement sur les schématiques des divers modèles. Dans son tutoriel sur le protocole I²C, Sparkfun ajoute « It's only there to talk to EEPROMs at addresses 0x50 during boot time. User access at runtime is problematic. If you want a general purpose I2C bus on the B+, you'll need to use I2C-1, on pins 3 and 5 of the 40-pin connector ». Cependant, le tutoriel enchaîne avec la marche à suivre pour utiliser le bus. Il s'agit d'utiliser le module i2c_vc qu'on peut charger avec l'utilitaire dtparam. Avant de l'installer, voyons l'information que l'utilitaire affiche à propos de ce module.

woopi@goldserver:~ $ sudo dtparam -h i2c_vc i2c_vc Set to "on" to enable the i2c interface usually reserved for the VideoCore processor (default "off") woopi@goldserver:~ $ sudo dtparam i2c_vc=on woopi@goldserver:~ $ ls /dev/i2* /dev/i2c-0

Puisque le périphérique est en place, j'ai pris la chance de brancher le module d'horloge avec mémoire flash aux broches 27 (SDA) et 28 (SCL) du second bus I2C (et aussi la masse et VCC à 3,3 volts bien sûr) en prenant soin de couper l'alimentation avant de procéder. Après il a été facile de vérifier qu'il était possible de se servir de la mémoire flash.

woopi@goldserver:~ $ sudo i2cdetect -y 0 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 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-0 0x57 -r 0:29 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-0, Address: 0x57, Mode: 16bit Operation: read 29 bytes from offset 0, Output file: <stdout> Reading 29 bytes from 0x0 Lorem ipsum dolor si... woopi@goldserver:~ $ echo "eeprom on i2c-0 " | eeprog/eeprog -f -16 -w 0x00 -t 2 /dev/i2c-0 0x57 eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-0, Address: 0x57, Mode: 16bit Operation: write at offset 0, Input file: <stdin> Write cycle time: 2 milliseconds Writing <stdin> starting at address 0x0 ................. woopi@goldserver:~ $ eeprog/eeprog -16 /dev/i2c-0 0x57 -r 0:18 -f eeprog 0.7.7-tear12, a 24Cxx EEPROM reader/writer Copyright (c) 2003-2004 by Stefano Barbato - All rights reserved. Copyright (c) 2011 by Kris Rusocki - All rights reserved. Bus: /dev/i2c-0, Address: 0x57, Mode: 16bit Operation: read 18 bytes from offset 0, Output file: <stdout> Reading 18 bytes from 0x0 eeprom on i2c-0

Il ne semble pas y avoir de module qui prenne en charge l'horloge avec ce bus I²C. J'ai pu toutefois vérifier qu'il était possible d'accéder à la puce DS3231 avec un script Python qui est décrit en plus de détails dans un autre billet.

woopi@goldserver:~ $ ve rtcpy (rtcpy) woopi@goldserver:~ $ ./rtc -i 0 -bash: ./rtc: No such file or directory (rtcpy) woopi@goldserver:~ $ rtcpy/rtc -i 0 Sat Feb 22 20:53:42 2020 (rtcpy) woopi@goldserver:~ $ rtcpy/rtc -i 0 -u -s "2138-12-09 12:13:14" (rtcpy) woopi@goldserver:~ $ rtcpy/rtc -i 0 Tue Dec 9 12:13:27 2138

Pour installer ce bus I²C matériel de façon permanente, on ajoute une ligne dans le fichier de configuration.

woopi@goldserver:~ $ sudo nano /boot/config.txt

# Uncomment some or all of these to enable the optional hardware interfaces #dtparam=i2c_arm=on #dtparam=i2s=on #dtparam=spi=on dtparam=i2c_vc=on

Je n'ai pas testé l'utilisation de ce bus avec l'autre bus I²C matériel ou d'autres bus virtuels, mais j'estime que cela devrait fonctionné. Ceci étant dit, il n'est certes pas recommandé et peut-être même pas possible d'utiliser le controleur i2c0. Comme l'indique la fin de la commande d'aide générale de l'utilitaire dtparam, il pourrait y avoir un conflit avec la caméra Pi.

woopi@goldserver:~ $ sudo dtparam -h ... N.B. It is recommended to only enable those interfaces that are needed. Leaving all interfaces enabled can lead to unwanted behaviour (i2c_vc interfering with Pi Camera, I2S and SPI hogging GPIO pins, etc.)

De même, il est fort probable qu'il y aurait un conflit avec tout dispositif I²C branché sur ce bus qui utiliserait l'adresse 0x50.

Lecture de la température avec le DS3231 toc

Pour assurer la précision, la puce DS3231 pare aux variations provoquées par les changements de température. Donc, elle incorpore une sonde de température dont il est possible d'obtenir la valeur. La température de la puce se trouve dans les registres 0x11 et 0x12 qu'on peut lire avec l'utilitaire i2cget.

woopi@goldserver:~ $ sudo i2cget -y 1 0x68 0x11 Error: Could not open file `/dev/i2c-1' or `/dev/i2c/1': No such file or directory woopi@goldserver:~ $ i2cget -y 1 0x68 0x11 Error: Could not set address to 0x68: Device or resource busy

Le problème est que le périphérique à l'adresse 0x68 est l'horloge qui est pris en charge par le pilote rtc_ds1307.

woopi@goldserver:~ $ lsmod | grep rtc rtc_ds1307 24576 0 hwmon 16384 2 rtc_ds1307,raspberrypi_hwmon

Si l'on retire le module, on aura accès au DS3231.

woopi@goldserver:~ $ sudo rmmod rtc_ds1307 woopi@goldserver:~ $ sudo i2cget -y 1 0x68 0x11 0x14 woopi@goldserver:~ $ sudo i2cget -y 1 0x68 0x12 0x40

Le registre 0x11 contient la partie entière de la température en degré Celsius, alors que les deux bits les plus significatifs du registre 0x12 contiennent la partie fractionnaire de la température en quart de degré Celsius. Or 0x40 = 01000000 dont les deux bits les plus significatifs sont 01. Donc la température est 20 + 1* (1/4) = 20,25 °C ce qui était raisonnable.

On peut réinstaller le module rtc_ds1307 et l'horloge fonctionnera de nouveau.

woopi@goldserver:~ $ sudo modprobe rtc_ds1307 woopi@goldserver:~ $ sudo hwclock -v hwclock from util-linux 2.33.1 System Time: 1580085041.982210 Trying to open: /dev/rtc0 Using the rtc interface to the clock. Last drift adjustment done at 1580060171 seconds after 1969 Last calibration done at 1580060171 seconds after 1969 Hardware clock is on UTC time Assuming hardware clock is kept in UTC time. Waiting for clock tick... ioctl(3, RTC_UIE_ON, 0): Invalid argument Waiting in loop for time from /dev/rtc0 to change ...got clock tick Time read from Hardware Clock: 2020/01/27 00:30:43 Hw clock time : 2020/01/27 00:30:43 = 1580085043 seconds since 1969 Time since last adjustment is 24872 seconds Calculated Hardware Clock drift is 0.000000 seconds 2020-01-26 20:30:42.444318-04:00

Choix d'une pile toc

Le module comprend un support pour une pile bouton dont la fonction est de maintenir l'horloge en marche lorsque l'alimentation est coupée. Il y a un circuit assez sommaire pour charger un accumulateur de façon constante lorsque le module est alimenté. D'ailleurs un accumulateur (LIR2032) était fourni avec ces modules initialement. Sans surprise, les modules que j'ai obtenus de deux fournisseurs dernièrement n'avaient pas de piles incluses. Les nouveaux règlements à propos du transport de pile de type lithium-ion étant beaucoup plus sévères, les vendeurs évitent d'en expédier.

On retrouve sur le forum Arduino une discussion au sujet du module qui commence en novembre 2014 et qui demeure active. Je me permets de résumer ce long débat.

Pour ces raisons, au moins un revendeur enlève la résistance de 200 ohms pour désactiver le circuit et recommande l'utilisation d'une pile lithium CR2032 non rechargeable. Puisqu'il est difficile de trouver le LIR2032 localement à un prix raisonnable et puisque je doute fort de l'efficacité du circuit pour charger la pile quand le module est alimenté à 3,3 volts, j'imite ce revendeur avec les modules en ma possession.

<-Module horloge et mémoire EEPROM I²C pour Raspberry Pi --