Construire un système Linux embarqué tolérant aux pannes basé sur le module Mars ZX3 d'Enclustra

En raison de la charge de travail des spécialistes, il y a plusieurs années, nous avons été obligés de donner un développement aux contreparties. Le développement a été effectué sur le module Enclustra Mars ZX3, qui utilise le SOC ARM + FPGA Zynq-7020. Pour construire Linux, nous avons utilisé Bcl d'Enclustra (bsp-xilinx), qui a été légèrement modifié.

Lors du test du logiciel développé, nous avons immédiatement rencontré des pannes logicielles lorsque l'alimentation a été coupée. Au cours de l'analyse, il a été constaté que les commandes de configuration envoyées à l'appareil via le réseau étaient écrites dans des fichiers qui, lors d'une panne de courant, s'avéraient parfois vides ou complètement absents. Cela nous a obligés à reconsidérer l'idéologie de la construction de l'assemblage Linux qui nous a été remis. Le processus de construction du système lui-même est bien décrit sur le site du fabricant du module, donc je ne m'y attarderai pas. Je ne décrirai que ce qui nous a permis de résoudre la tâche qui nous attend: accroître la fiabilité et prévenir les défaillances.

Le module Mars ZX3 possède des puces Flash QSPI et Flash NAND. Dans notre cas, le module est chargé avec QSPI Flash, dans lequel U-Boot a été écrit. Comme les deux puces utilisent les mêmes broches Zynq-7020, après le chargement de U-Boot, les broches sont converties en NAND Flash, sur lequel le script de démarrage, l'arborescence des périphériques, le noyau Linux, le système de fichiers ubifs et les variables d'environnement sont écrits dans des sections distinctes. De plus, toutes les sections, à l'exception de la section avec des variables d'environnement, étaient réservées (c'est-à-dire qu'il y avait deux de ces sections). Ce qui suit est un fragment du fichier de l'arborescence des périphériques, qui montre comment NAND Flash a été rompu dans la version qui nous a été transmise par les contractants:

partition@nand-linux { label = "nand-linux"; reg = <0x0 0x500000>; }; partition@nand-device-tree { label = "nand-device-tree"; reg = <0x500000 0x100000>; }; partition@nand-bootscript { label = "nand-bootscript"; reg = <0x600000 0x100000>; }; partition@nand-linux-second { label = "nand-linux-second"; reg = <0x700000 0x500000>; }; partition@nand-device-tree-second { label = "nand-device-tree"; reg = <0xC00000 0x100000>; }; partition@nand-bootscript-second { label = "nand-bootscript"; reg = <0xD00000 0x100000>; }; partition@nand-rootfs { label = "nand-rootfs"; reg = <0xE00000 0xF500000>; }; partition@nand-rootfs-second { label = "nand-rootfs"; reg = <0x10300000 0xF500000>; }; partition@boot-env { label = "nand-env"; reg = <0x1F800000 0x100000>; }; 

Les deuxièmes sections étaient censées être utilisées lorsque les sections principales ont échoué. Pour ce faire, Linux a dû implémenter un processus qui surveille l'intégrité du système et, en cas de panne, écrit une valeur dans la variable d'environnement qui demande de démarrer le système à partir des partitions de sauvegarde. Cet algorithme devait être implémenté à l'avenir.

Les données de configuration ont été enregistrées dans deux dossiers pour la sauvegarde, mais cela n'a pas sauvé la situation. Il est supposé qu'en l'absence de fichiers de configuration, ils sont recréés automatiquement, avec les paramètres par défaut.

Le problème est que NAND Flash écrit les données une page à la fois et l'effacement se produit par blocs. Ainsi, si une panne de courant se produit pendant l'enregistrement des données, non seulement ces données seront corrompues, mais le système de fichiers peut être endommagé. Le démarrage d'un système de sauvegarde ne peut que retarder l'apparition d'un problème. Bien que dans ce cas, il est possible de réaliser la restauration des partitions principales à partir des partitions de sauvegarde.

Nous avons décidé d'aller dans l'autre sens, de monter rootfs en tant que système de fichiers en lecture seule et d'écrire des fichiers de configuration dans des sections de données et de sauvegarde distinctes qui ont été montées pour la lecture et l'écriture. Dans ce cas, le besoin de partitions de sauvegarde disparaît, mais nous les avons laissées pour l'avenir, car la quantité de mémoire nous a permis de le faire. Si nécessaire, ils peuvent être supprimés.

Par conséquent, le partitionnement NAND Flash suivant a été effectué:

  partition@nand-linux { label = "nand-linux"; reg = <0x0 0x500000>; }; partition@nand-device-tree { label = "nand-device-tree"; reg = <0x500000 0x100000>; }; partition@nand-bootscript { label = "nand-bootscript"; reg = <0x600000 0x100000>; }; partition@nand-linux-second { label = "nand-linux-second"; reg = <0x700000 0x500000>; }; partition@nand-device-tree-second { label = "nand-device-tree"; reg = <0xC00000 0x100000>; }; partition@nand-bootscript-second { label = "nand-bootscript"; reg = <0xD00000 0x100000>; }; partition@nand-rootfs { label = "nand-rootfs"; reg = <0xE00000 0x9600000>; }; partition@nand-rootfs-second { label = "nand-rootfs"; reg = <0xA400000 0x9600000>; }; partition@nand-data { label = "nand-data"; reg = <0x13A00000 0x5F00000>; }; partition@nand-data-backup { label = "nand-data-backup"; reg = <0x19900000 0x5F00000>; }; partition@boot-env { label = "nand-env"; reg = <0x1F800000 0x100000>; }; 

Lorsque vous flashez NAND Flash à l'aide de la commande U-Boot, nous effaçons les sections nand-data et nand-data-backup :

 u-boot>nand erase.part nand-data u-boot>nand erase.part nand-data-backup 

Dans le script de démarrage Linux, nous avons implémenté le montage du système de fichiers racine en lecture seule, en remplaçant la ligne dans le fichier / etc / inittab dans l'assembly Linux:

 ::sysinit:/bin/mount -o remount,rw / 

sur

 ::sysinit:/bin/mount -o remount,ro / 

Nous avons ajouté un script de démarrage dans le dossier /etc/init.d/ , qui monte les sections nand-data et nand-data-backup pour la lecture et l'écriture. En cas d'erreur de montage (lors du premier démarrage ou si le système de fichiers est endommagé), ces partitions sont formatées et remontées. Les dossiers / mnt / data / et / mnt / backup / doivent être créés au préalable dans le système de fichiers racine.

 #!/bin/sh # # datafs Mount datafs. # umask 077 start() { printf "Starting mount datafs..." /usr/sbin/ubiattach /dev/ubi_ctrl -m 8 /usr/sbin/ubiattach /dev/ubi_ctrl -m 9 mount_datafs_err=0; mount_datafs_backup_err=0; /bin/mount -t ubifs ubi1:datafs /mnt/data mount_datafs_err=$? if [ $mount_datafs_err -ne 0 ]; then /usr/sbin/ubidetach -p /dev/mtd8 /usr/sbin/ubiformat /dev/mtd8 -y /usr/sbin/ubiattach /dev/ubi_ctrl -m 8 /usr/sbin/ubimkvol /dev/ubi1 -N datafs -s 81MiB /bin/mount -t ubifs ubi1:datafs /mnt/data mount_datafs_err=$? fi /bin/mount -t ubifs ubi2:datafs /mnt/backup mount_datafs_backup_err=$? if [ $mount_datafs_backup_err -ne 0 ]; then /usr/sbin/ubidetach -p /dev/mtd9 /usr/sbin/ubiformat /dev/mtd9 -y /usr/sbin/ubiattach /dev/ubi_ctrl -m 9 /usr/sbin/ubimkvol /dev/ubi2 -N datafs -s 81MiB /bin/mount -t ubifs ubi2:datafs /mnt/backup mount_datafs_backup_err=$? fi printf "Mount datafs: " if [ $mount_datafs_err -ne 0 ]; then echo "Error" else echo "OK" fi printf "Mount backup datafs: " if [ $mount_datafs_backup_err -ne 0 ]; then echo "Error" else echo "OK" fi touch /var/lock/datafs } stop() { /bin/umount /mnt/data /bin/umount /mnt/backup rm -f /var/lock/datafs } restart() { stop sleep 1 start } case "$1" in start) start ;; stop) stop ;; restart|reload) restart ;; *) echo "Usage: $0 {start|stop|restart|reload}" exit 1 esac exit 0 

Lors du téléchargement, si les fichiers de configuration du dossier / mnt / data / sont manquants, ils sont téléchargés à partir du dossier / mnt / backup / . S'il n'y a pas de fichiers de configuration dans / mnt / backup / , ils sont automatiquement créés à partir du logiciel avec les paramètres par défaut. Si les fichiers sont présents dans / mnt / data / mais pas dans / mnt / backup / , ils sont copiés de / mnt / data / vers / mnt / backup / . Toutes ces opérations sont effectuées par le logiciel utilisateur.

À l'étape suivante, pour augmenter la fiabilité, nous avons refusé d'écrire la configuration dans un fichier pour chaque commande. La configuration entière est maintenant stockée dans la RAM et, si nécessaire, par une commande distincte peut être enregistrée dans des fichiers dans les dossiers / mnt / data / et / mnt / backup / .

Si, pendant le travail, vous devez apporter des modifications au système de fichiers racine sans reflasher le périphérique, vous pouvez remonter le système à partir de la console pour lire et écrire avec la commande

 mount -o remount,rw / 

Apportez des modifications, puis remontez en lecture seule:

 mount -o remount,ro / 

Source: https://habr.com/ru/post/fr483900/


All Articles