From fdf08bf1d7651700930011030fe1f4422375df34 Mon Sep 17 00:00:00 2001 From: Pierre Date: Wed, 23 Sep 2026 14:51:33 +0200 Subject: [PATCH] =?UTF-8?q?Unification=20des=20sources=20CM4/CM5=20:=20mak?= =?UTF-8?q?efiles=20scind=C3=A9s=20(common/cm4/cm5/cm5.debug),=20#ifdef=20?= =?UTF-8?q?CIBLE=5FCM5=20pour=20GPIO,=20correctifs=20get=5Fip=5Faddress()/?= =?UTF-8?q?signal=20handler/backtrace,=20portabilit=C3=A9=2032/64=20bits?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + make/mak.sh | 3 +- make/mak_debug.sh | 27 +++++++++++ make/makefile | 46 ------------------ make/makefile.cm4 | 20 ++++++++ make/makefile.cm5 | 23 +++++++++ make/makefile.cm5.debug | 22 +++++++++ make/makefile.common | 20 ++++++++ make/sync_vers_cm4.sh | 19 ++++++++ sources/bdd_admin.c | 10 ++++ sources/bdd_init.c | 19 ++++++-- sources/bdd_synchro.c | 5 +- sources/c_commandes.c | 2 +- sources/entrees.c | 14 +++++- sources/g_bus.c | 4 +- sources/gnss.c | 2 +- sources/m_bus.c | 2 +- sources/main.c | 66 ++++++++++++++++++-------- sources/main.h | 24 ++++++---- sources/reseaux.c | 100 +++++++++++++++++----------------------- sources/serial.c | 2 +- sources/sorties.c | 13 ++++++ sources/systeme.c | 83 +++++++++++++++++++++++++++++---- 23 files changed, 373 insertions(+), 154 deletions(-) create mode 100755 make/mak_debug.sh delete mode 100644 make/makefile create mode 100644 make/makefile.cm4 create mode 100644 make/makefile.cm5 create mode 100644 make/makefile.cm5.debug create mode 100644 make/makefile.common create mode 100755 make/sync_vers_cm4.sh diff --git a/.gitignore b/.gitignore index 0f21c9d..097325c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ objets/ bin/ versions/ sources/_version.txt +objets_debug/ diff --git a/make/mak.sh b/make/mak.sh index a23a9e4..224d1ae 100755 --- a/make/mak.sh +++ b/make/mak.sh @@ -3,7 +3,6 @@ # Informations : # 1. Ce fichier doit être exécutable : sudo chmod +x # 2. il peut être lancé manuellement par : ./ -# 3. les sorties standard et d'erreur sont redirigées vers un fichier dans le répertoire UPLOAD (donc il sera uploadé à la prochaine connexion puis supprimé localement) ################################################################################################# # Variables globales : DATEVERSION=$(date +"%y%m%d_%H%M%S") @@ -13,7 +12,7 @@ DATEVERSION=$(date +"%y%m%d_%H%M%S") echo "#define VERSION_LOGICIEL \""$DATEVERSION"\"" > ../sources/_version.txt #============================================================================================================== # Lancement du makefile : -make +make -f makefile.cm5 #============================================================================================================== # Sauvegarde de la version : cp "../bin/shipheart_appli" "../versions/shipheart_appli_"$DATEVERSION diff --git a/make/mak_debug.sh b/make/mak_debug.sh new file mode 100755 index 0000000..12e305c --- /dev/null +++ b/make/mak_debug.sh @@ -0,0 +1,27 @@ +#!/bin/bash +################################################################################################# +# Version DEBUG (ASan) — ne génère PAS d'entrée dans versions/, uniquement le binaire de test. +################################################################################################# +# Variables globales : +DATEVERSION=$(date +"%y%m%d_%H%M%S") +#============================================================================================================== +# Met à jour le fichier '_version.txt' dans le répertoire ../sources avec le 'datecode'. Celui-ci sera +# utilisé lors de la compilation/link de l'application comme version du logiciel. +echo "#define VERSION_LOGICIEL \""$DATEVERSION"\"" > ../sources/_version.txt +#============================================================================================================== +# Lancement du makefile : +make -f makefile.cm5.debug +#============================================================================================================== +# Déploiement vers le CM5 (nécessaire depuis le passage en cross-compilation WSL2 - +# auparavant la compilation avait lieu directement sur le CM5, donc le binaire y +# était déjà présent). Utilise l'alias SSH 'cm5' défini dans ~/.ssh/config. +# NB : shipheart_appli tourne en permanence sur le CM5 - une écriture directe sur +# le fichier cible échoue ("Text file busy"). On écrit donc dans un fichier +# temporaire, puis on renomme (opération atomique, fonctionne même sur un +# exécutable en cours d'utilisation). +scp -q "../bin/shipheart_appli" cm5:/home/koriolan/shipheart/versions/current/shipheart_appli.new +ssh cm5 "mv /home/koriolan/shipheart/versions/current/shipheart_appli.new /home/koriolan/shipheart/versions/current/shipheart_appli" +#============================================================================================================== +# Fin : +exit 0 + diff --git a/make/makefile b/make/makefile deleted file mode 100644 index 7306a60..0000000 --- a/make/makefile +++ /dev/null @@ -1,46 +0,0 @@ -# Choix du compilateur croisé (cible aarch64/CM5, exécuté depuis WSL2 x86_64) : -CC=aarch64-linux-gnu-gcc - -# Recherche pkg-config restreinte aux .pc arm64 uniquement (PKG_CONFIG_LIBDIR -# écrase le chemin de recherche par défaut, pour ne jamais mélanger avec les -# .pc x86_64 de l'hôte). mariadb_config est abandonné : ce script n'est pas -# conscient du multiarch et renverrait les chemins x86_64 de l'hôte. -PKGCONFIG = PKG_CONFIG_PATH= PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig pkg-config - -# Options de compilation : -# PRODUCTION : -CFLAGS = -O3 -Wall $(shell $(PKGCONFIG) --cflags mariadb alsa libssl libcrypto json-c libgpiod) -# DEBUG : -#CFLAGS = -O3 -Wall $(shell $(PKGCONFIG) --cflags mariadb alsa libssl libcrypto json-c libgpiod) -gstabs -# Possibilité d'utiliser aussi '-Wunused-variable' si besoin... Voire 'Wall' si on veut se faire mal...! - -# Options de link pour accéder à MariaDB, Alsa, OpenSSL, json-c et GPIO : -LIBS = $(shell $(PKGCONFIG) --libs mariadb alsa libssl libcrypto json-c libgpiod) -lm - -# Localisation des répertoires : -SRCDIR=../sources -OBJDIR=../objets -EXEDIR=../bin - -# Nom de l'éxécutable généré : -EXECUTABLE=shipheart_appli -#------------------------------------------------------------------------------------------------------------ -# !!!!!!!!! .............................NE DOIT PAS ETRE MODIFIE EN DESSOUS.......................!!!!!!!!!! -#------------------------------------------------------------------------------------------------------------ -SRC= $(wildcard $(SRCDIR)/*.c) -DEPS= $(wildcard $(SRCDIR)/*.h) -OBJ = $(subst $(SRCDIR),$(OBJDIR), $(patsubst %.c, %.o, $(SRC)) ) -# Règle de plus haut niveau : -all: $(EXEDIR)/$(EXECUTABLE) -# Linker (dépendance de l'exécutable vs les fichiers Objet) : -$(EXEDIR)/$(EXECUTABLE): $(OBJ) - $(CC) -o $@ $^ $(LIBS) -# Compilateur (dépendance des fichiers Objet vs leur fichier Source et TOUS les Headers) : -$(OBJDIR)/%.o: $(SRCDIR)/%.c $(DEPS) - $(CC) -o $@ -c $< $(CFLAGS) -# Cas particulier du fichier '_version.c' qui dépend, en plus, du fichier '_version.txt' : -# cf fichier '_version.c' pour détails. -$(OBJDIR)/_version.o: $(SRCDIR)/_version.c $(SRCDIR)/_version.txt - $(CC) -o $(OBJDIR)/_version.o -c $(SRCDIR)/_version.c $(CFLAGS) -# NB : Les focntions de type Clean ou Mrproper ne sont pas laissées car -# on part du principe qu'on garde les fichiers objets dans le répertoire dédié... diff --git a/make/makefile.cm4 b/make/makefile.cm4 new file mode 100644 index 0000000..02fb27d --- /dev/null +++ b/make/makefile.cm4 @@ -0,0 +1,20 @@ +# Choix du compilateur 'gcc' ou 'g++' NB : un (seul) test avec les deux donne un exécutable 20% plus petit avec GCC qu'avec G++ ! +CC=gcc + +# Options de compilation : +CFLAGS = -O3 -Wall -funwind-tables -fno-omit-frame-pointer `mariadb_config --cflags` + +# Options de link pour accéder à MariaDB et à Alsa : +LIBS = -rdynamic `mariadb_config --libs` -lm -lasound -lssl -lcrypto -ljson-c + +# Localisation des répertoires : +SRCDIR=../sources +OBJDIR=../objets +EXEDIR=../../versions/current + +# Nom de l'éxécutable généré : +EXECUTABLE=shipheart_appli + +# Inclusion des règles communes (aux CM4/CM5 et debug) : +include makefile.common + diff --git a/make/makefile.cm5 b/make/makefile.cm5 new file mode 100644 index 0000000..1cb9f21 --- /dev/null +++ b/make/makefile.cm5 @@ -0,0 +1,23 @@ +# Choix du compilateur croisé (cible aarch64/CM5, exécuté depuis WSL2 x86_64) : +CC=aarch64-linux-gnu-gcc + +# Recherche pkg-config restreinte aux .pc arm64 uniquement (PKG_CONFIG_LIBDIR écrase le chemin de recherche par défaut, pour ne jamais mélanger avec les .pc x86_64 de l'hôte). +PKGCONFIG = PKG_CONFIG_PATH= PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig pkg-config + +# Options de compilation : +CFLAGS = -O3 -Wall -funwind-tables -fno-omit-frame-pointer $(shell $(PKGCONFIG) --cflags mariadb alsa libssl libcrypto json-c libgpiod) +CFLAGS += -DCIBLE_CM5 + +# Options de link pour accéder à MariaDB, Alsa, OpenSSL, json-c et GPIO : +LIBS = -rdynamic $(shell $(PKGCONFIG) --libs mariadb alsa libssl libcrypto json-c libgpiod) -lm + +# Localisation des répertoires : +SRCDIR=../sources +OBJDIR=../objets +EXEDIR=../bin + +# Nom de l'éxécutable généré : +EXECUTABLE=shipheart_appli + +# Inclusion des règles communes (aux CM4/CM5 et debug) : +include makefile.common diff --git a/make/makefile.cm5.debug b/make/makefile.cm5.debug new file mode 100644 index 0000000..2d8b226 --- /dev/null +++ b/make/makefile.cm5.debug @@ -0,0 +1,22 @@ +# Choix du compilateur croisé (cible aarch64/CM5, exécuté depuis WSL2 x86_64) : +CC=aarch64-linux-gnu-gcc + +# Recherche pkg-config restreinte aux .pc arm64 uniquement (PKG_CONFIG_LIBDIR écrase le chemin de recherche par défaut, pour ne jamais mélanger avec les .pc x86_64 de l'hôte). +PKGCONFIG = PKG_CONFIG_PATH= PKG_CONFIG_LIBDIR=/usr/lib/aarch64-linux-gnu/pkgconfig pkg-config + +# Options de compilation : +CFLAGS = -O3 -Wall -funwind-tables -fno-omit-frame-pointer $(shell $(PKGCONFIG) --cflags mariadb alsa libssl libcrypto json-c libgpiod) -fsanitize=address -g + +# Options de link pour accéder à MariaDB, Alsa, OpenSSL, json-c et GPIO : +LIBS = -rdynamic $(shell $(PKGCONFIG) --libs mariadb alsa libssl libcrypto json-c libgpiod) -lm -fsanitize=address + +# Localisation des répertoires : +SRCDIR=../sources +OBJDIR=../objets_debug +EXEDIR=../bin + +# Nom de l'éxécutable généré : +EXECUTABLE=shipheart_appli + +# Inclusion des règles communes (aux CM4/CM5 et debug) : +include makefile.common diff --git a/make/makefile.common b/make/makefile.common new file mode 100644 index 0000000..55a3895 --- /dev/null +++ b/make/makefile.common @@ -0,0 +1,20 @@ +SRC= $(wildcard $(SRCDIR)/*.c) +DEPS= $(wildcard $(SRCDIR)/*.h) +OBJ = $(subst $(SRCDIR),$(OBJDIR), $(patsubst %.c, %.o, $(SRC)) ) + +# Règle de plus haut niveau : +all: $(EXEDIR)/$(EXECUTABLE) + +# Linker (dépendance de l'exécutable vs les fichiers Objet) : +$(EXEDIR)/$(EXECUTABLE): $(OBJ) + $(CC) -o $@ $^ $(LIBS) + +# Compilateur (dépendance des fichiers Objet vs leur fichier Source et TOUS les Headers) : +$(OBJDIR)/%.o: $(SRCDIR)/%.c $(DEPS) + $(CC) -o $@ -c $< $(CFLAGS) + +# Cas particulier du fichier '_version.c' qui dépend, en plus, du fichier '_version.txt' (cf fichier '_version.c' pour détails) : +$(OBJDIR)/_version.o: $(SRCDIR)/_version.c $(SRCDIR)/_version.txt + $(CC) -o $(OBJDIR)/_version.o -c $(SRCDIR)/_version.c $(CFLAGS) + +# NB : Les fonctions de type Clean ou Mrproper ne sont pas laissées car on part du principe qu'on garde les fichiers objets dans le répertoire dédié... \ No newline at end of file diff --git a/make/sync_vers_cm4.sh b/make/sync_vers_cm4.sh new file mode 100755 index 0000000..e50095f --- /dev/null +++ b/make/sync_vers_cm4.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Usage : ./sync_vers_cm4.sh +if [ -z "$1" ]; then + echo "Usage : $0 " + echo "NB : Le certificat est lié à une adresse précise. Si changement d'adresse cible, mettre à jour dans WSL2 par 'nano ~/.ssh/config' " + exit 1 +fi + +CM4_HOST="cm4-dev" +CM4_DEST="~/shipheart/appli" + +echo "Synchronisation des sources vers ${CM4_HOST}:${CM4_DEST}..." +rsync -av --delete ../sources/ ${CM4_HOST}:${CM4_DEST}/sources/ + +echo "Synchronisation des makefiles..." +rsync -av makefile.common makefile.cm4 ${CM4_HOST}:${CM4_DEST}/make/ + +echo "Terminé. Pour compiler sur la carte :" +echo "Terminé. Pour compiler : ssh ${CM4_HOST} 'cd ${CM4_DEST}/make && ./mak.sh'" diff --git a/sources/bdd_admin.c b/sources/bdd_admin.c index d1bf609..fb0a3b2 100644 --- a/sources/bdd_admin.c +++ b/sources/bdd_admin.c @@ -341,6 +341,16 @@ char suffixe_fichier_log[MAX_LONGUEUR_NOM_FICHIER]; char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; + +// sprintf(tmp, "/!\\ \tFonction d'archivage TEMPORAIREMENT suspendue..."); +// affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_WARNING); +// return(0); + + + + + + // Calcul de la date courante pour nommer le fichier de logs : time(&now); maintenant = *localtime(&now); diff --git a/sources/bdd_init.c b/sources/bdd_init.c index ce2a3eb..14db43c 100644 --- a/sources/bdd_init.c +++ b/sources/bdd_init.c @@ -200,22 +200,31 @@ affichage_debug(__FILE__, __LINE__, "------------------BDD_INIT", TYPE_MESSAGE_D else if (strcmp(row[0], "Periode_check_adresses_ip") == 0) reseaux.periode_check_adresses_ip = atoi(row[1]); else if (strcmp(row[0], "Periode_scan_wifi_sta") == 0) reseaux.periode_scan_sta = atoi(row[1]); - else if (strcmp(row[0], "Acces_webgl_1_validation") == 0) reseaux.webgl_new[0].validite = atoi(row[1]); + else if (strcmp(row[0], "Acces_webgl_1_validation") == 0) + { + if (systeme.generation_shipbase <= GENERATION_SHIPBASE_V2) reseaux.webgl_new[0].validite = atoi(row[1]); // On n'autorise pas la validation de WebGl sur les V3 + } else if (strcmp(row[0], "Acces_webgl_1_parametres") == 0) { if (strlen(row[1]) < MAX_LONGUEUR_PARAMETRES_WEBGL) strcpy(reseaux.webgl_new[0].parametres, row[1]); } - else if (strcmp(row[0], "Acces_webgl_2_validation") == 0) reseaux.webgl_new[1].validite = atoi(row[1]); + else if (strcmp(row[0], "Acces_webgl_2_validation") == 0) + { + if (systeme.generation_shipbase <= GENERATION_SHIPBASE_V2) reseaux.webgl_new[1].validite = atoi(row[1]); // On n'autorise pas la validation de WebGl sur les V3 + } else if (strcmp(row[0], "Acces_webgl_2_parametres") == 0) { if (strlen(row[1]) < MAX_LONGUEUR_PARAMETRES_WEBGL) strcpy(reseaux.webgl_new[1].parametres, row[1]); } - else if (strcmp(row[0], "Acces_webgl_3_validation") == 0) reseaux.webgl_new[2].validite = atoi(row[1]); + else if (strcmp(row[0], "Acces_webgl_3_validation") == 0) + { + if (systeme.generation_shipbase <= GENERATION_SHIPBASE_V2) reseaux.webgl_new[2].validite = atoi(row[1]); // On n'autorise pas la validation de WebGl sur les V3 + } else if (strcmp(row[0], "Acces_webgl_3_parametres") == 0) { if (strlen(row[1]) < MAX_LONGUEUR_PARAMETRES_WEBGL) strcpy(reseaux.webgl_new[2].parametres, row[1]); } - else if (strcmp(row[0], "Courant_masses_maxi_sp8dc") == 0) // SDIR #318 + else if (strcmp(row[0], "Courant_masses_maxi_sp8dc") == 0) // SDIR #318 { systeme.courant_masses_maxi_sp8dc = atof(row[1]); if (systeme.courant_masses_maxi_sp8dc > MAX_COURANT_MASSES_SP8DC) systeme.courant_masses_maxi_sp8dc = MAX_COURANT_MASSES_SP8DC; @@ -865,7 +874,7 @@ printf("Ciruit affecté à un module de type %i \n", systeme.modules_config[circ sprintf(requete, "SELECT Cle_primaire, Adresse_module, Type_entrees, Entrees, Mode_entrees, ID_Variable, Etat, Decalage, Gain, Valeur, \ Valeur_coeff_filtrage, Mode_enregistrement_mesures, Mode_enregistrement_historique \ FROM TB_Capteurs ORDER BY Type_entrees, Cle_primaire"); -printf("Requete = [ %s; ]\n", requete); +//printf("Requete = [ %s; ]\n", requete); mysql_query(bdd.pointeur, requete); // Envoi de la requête à MYSQL result = mysql_store_result(bdd.pointeur); // Récup des résultats de la requête while((row = mysql_fetch_row(result))) // Boucle sur tous les résultats de la requête diff --git a/sources/bdd_synchro.c b/sources/bdd_synchro.c index 92fbf44..485e7e0 100644 --- a/sources/bdd_synchro.c +++ b/sources/bdd_synchro.c @@ -164,7 +164,7 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; } else if (strlen(ptr[0]) >= MAX_LONGUEUR_NOM_FICHIER) { - sprintf(tmp, "Le nom de fichier reçu via le champ New_bip est trop long (%li caractères pour %i max). La demande est rejetée...", strlen(ptr[0]), MAX_LONGUEUR_NOM_FICHIER); + sprintf(tmp, "Le nom de fichier reçu via le champ New_bip est trop long (%zu caractères pour %i max). La demande est rejetée...", strlen(ptr[0]), MAX_LONGUEUR_NOM_FICHIER); affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); } else emission_bip(ptr[0], atoi(ptr[1]), atoi(ptr[2]), atoi(ptr[3])); // NB : si 'atoi()' rencontre une erreur, il retourne '0' qui sera traité sans problème par 'emission_bip()' @@ -1043,7 +1043,8 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; // ******************************************************************************************************************************************************** // Mise à jour du timestamp dans la BDD : - sprintf(requete, "UPDATE TB_Systeme SET Valeur='%li' WHERE Nom='Heart_beat'", (uint64_t) time(NULL)); // Enregistrement du timestamp de MAINTENANT (permet sur les pages Web d'afficher les feux vert, orange ou rouge en fonction de la dernière valeur écrite par l'application) + sprintf(requete, "UPDATE TB_Systeme SET Valeur='%" PRIu64 "' WHERE Nom='Heart_beat'", (uint64_t) time(NULL)); // Enregistrement du timestamp de MAINTENANT (permet sur les pages Web d'afficher les feux vert, orange ou rouge en fonction de la dernière valeur écrite par l'application) + mysql_query(bdd.pointeur, requete); diff --git a/sources/c_commandes.c b/sources/c_commandes.c index 1fa9a6b..83e7d41 100644 --- a/sources/c_commandes.c +++ b/sources/c_commandes.c @@ -1945,7 +1945,7 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; //etat_nmea = commande->cde[ptr_cde ++]; // Debug : -// printf("Etat du Compagnon reçu : Etat alim = %i, Tension = %6.3f V, Courant=%6.3f A, Courant USB=%5.3f A, Température = %5.2f °C, Humidité=%5.2f %%RH, Pression=%7.2f hPa, Origine reset = %i \n", alim_etat, in_v, in_i, usb_i, temp, hum, pat, orig); +//printf("Etat du Compagnon reçu : Etat alim = %i, Tension = %6.3f V, Courant=%6.3f A, Courant USB=%5.3f A, Température = %5.2f °C, Humidité=%5.2f %%RH, Pression=%7.2f hPa, Origine reset = %i \n", alim_etat, in_v, in_i, usb_i, temp, hum, pat, orig); } diff --git a/sources/entrees.c b/sources/entrees.c index 64b9023..20fcd90 100644 --- a/sources/entrees.c +++ b/sources/entrees.c @@ -33,9 +33,11 @@ uint8_t lecture_entree_gpio(uint8_t no, int8_t logique); // Variables globales : struct Struct_entrees entrees; + +#ifdef CIBLE_CM5 struct gpiod_chip *gpiod_chip0; // Nécessaire pour CM5 struct gpiod_line_request *gpiod_entrees_request; // Nécessaire pour CM5 - +#endif /********************************************************************************************************************************************************************************** @@ -574,6 +576,7 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; //==================================================================================================== if (systeme.generation_shipbase == GENERATION_SHIPBASE_V3) { +#ifdef CIBLE_CM5 unsigned int offsets[MAX_NOMBRE_ENTREES_GPIO]; uint8_t nb_lignes = 0; @@ -627,6 +630,13 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; entrees.gpio.sequenceur.compteur = TEMPO_INIT_ENTREES_GPIO; return(0); // On sort ici : la boucle V1/V2 ci-dessous ne doit pas s'exécuter pour V3 + +#else // Compilation pour CM4 donc V1 ou V2. Ne devrait jamais arriver ... : + sprintf(tmp, "GENERATION_SHIPBASE_V3 incompatible avec cette plateforme de compilation."); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + return(-1); +#endif + } @@ -849,12 +859,14 @@ uint8_t lecture_entree_gpio(uint8_t no, int8_t logique) uint8_t x; +#ifdef CIBLE_CM5 if (systeme.generation_shipbase == GENERATION_SHIPBASE_V3) { enum gpiod_line_value val = gpiod_line_request_get_value(gpiod_entrees_request, no); x = (val == GPIOD_LINE_VALUE_ACTIVE) ? ON : OFF; } else // Pour V1 & V2 : accès direct aux registres +#endif { // Lecture dans les registres du BCM2836 : if (no < 32) // Entrées 0 à 31 : diff --git a/sources/g_bus.c b/sources/g_bus.c index 40db5f8..973f40d 100644 --- a/sources/g_bus.c +++ b/sources/g_bus.c @@ -68,7 +68,7 @@ int8_t ret; char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; - if (systeme.generation_shipbase != GENERATION_SHIPBASE_V2) return; + if (systeme.generation_shipbase == GENERATION_SHIPBASE_V1) return; switch(g_bus.sequenceur.etat) { @@ -446,7 +446,7 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; else g_bus.down.ptr_fin_buffer_cdes --; // Message de débug : - sprintf(tmp, "Buffer de commandes M-Bus plein. La demande de stockage d'une nouvelle commande a été rejetée..."); + sprintf(tmp, "Buffer de commandes G-Bus plein. La demande de stockage d'une nouvelle commande a été rejetée..."); affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); // Enregistrement dans l'historique : diff --git a/sources/gnss.c b/sources/gnss.c index 9e3ff95..b7ed57e 100644 --- a/sources/gnss.c +++ b/sources/gnss.c @@ -61,7 +61,7 @@ uint16_t lg_cde; char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; - if (systeme.generation_shipbase != GENERATION_SHIPBASE_V2) return; + if (systeme.generation_shipbase == GENERATION_SHIPBASE_V1) return; switch(gnss.sequenceur.etat) { diff --git a/sources/m_bus.c b/sources/m_bus.c index f78e129..e8c4e6f 100644 --- a/sources/m_bus.c +++ b/sources/m_bus.c @@ -122,7 +122,7 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; if (ret == 1) affichage_debug_bus(TYPE_BUS_DEBUG_M_BUS, "Rx", (char *) m_bus.down.reponse.reponse, __DEBUG_M_BUS); // Cas d'une réponse normale else { - sprintf(tmp, "[%li data bytes]", strlen((const char *)m_bus.down.reponse.reponse)); + sprintf(tmp, "[%zu data bytes]", strlen((const char *)m_bus.down.reponse.reponse)); affichage_debug_bus(TYPE_BUS_DEBUG_M_BUS, "Rx", tmp, __DEBUG_M_BUS); // Cas d'une réponse en mode binaire } #endif diff --git a/sources/main.c b/sources/main.c index 33367ce..0479735 100644 --- a/sources/main.c +++ b/sources/main.c @@ -10,7 +10,8 @@ // Prototypes : int8_t init(void); -void sigintHandler(int dummy); +void sigintHandler(int32_t signal); +void sigfatalHandler(int32_t signal); void lancement_reinit(uint16_t tempo); int8_t analyse_signal(void); int8_t init_signaux(void); @@ -323,6 +324,7 @@ int8_t retour = 0; return(retour); } + //================================================================================================================================================================== // Fonction : Initialisation des handlers de signaux (vers une seule et même fonction). // Reçoit : Rien @@ -331,41 +333,45 @@ int8_t retour = 0; int8_t init_signaux(void) { systeme.faucheuse.signal_recu = SYSTEME_SIGNAL_AUCUN; + + // Signaux ne permettant pas de traitement à proprement parler (fatal) : + // On utilise alors un gestionnaire de signaux dédié... + signal(SIGILL, sigfatalHandler); // 4 SIGILL Instruction illégale + signal(SIGTRAP, sigfatalHandler); // 5 SIGTRAP Trace trap + signal(SIGABRT, sigfatalHandler); // 6 SIGABRT (ANSI) Instruction (ABORT) + signal(SIGBUS, sigfatalHandler); // 7 SIGBUS Bus error + signal(SIGFPE, sigfatalHandler); // 8 SIGFPE Floating-point exception - Exception arithmétique + signal(SIGSEGV, sigfatalHandler); // 11 SIGSEGV Violation de mémoire + signal(SIGSYS, sigfatalHandler); // 31 SIGSYS Erreur d'appel système - signal(SIGHUP, sigintHandler); // 1 SIGHUP Instruction (HANG UP) - Fin de session - signal(SIGINT, sigintHandler); // 2 SIGINT Interruption + // Signaux moins violents, permettant un traitement après réception : + signal(SIGHUP, sigintHandler); // 1 SIGHUP Instruction (HANG UP) - Fin de session + signal(SIGINT, sigintHandler); // 2 SIGINT Interruption signal(SIGQUIT, sigintHandler); // 3 SIGQUIT Instruction (QUIT) - signal(SIGILL, sigintHandler); // 4 SIGILL Instruction illégale - signal(SIGTRAP, sigintHandler); // 5 SIGTRAP Trace trap - signal(SIGABRT, sigintHandler); // 6 SIGABRT (ANSI) Instruction (ABORT) - signal(SIGIOT, sigintHandler); // 6 SIGIOT (BSD) IOT Trap - signal(SIGBUS, sigintHandler); // 7 SIGBUS Bus error - signal(SIGFPE, sigintHandler); // 8 SIGFPE Floating-point exception - Exception arithmétique - signal(SIGKILL, sigintHandler); // 9 SIGKILL Instruction (KILL) - termine le processus immédiatement + signal(SIGIOT, sigintHandler); // 6 SIGIOT (BSD) IOT Trap + signal(SIGKILL, sigintHandler); // 9 SIGKILL Instruction (KILL) - termine le processus immédiatement. En pratique, inutile car toujours intercepté par le noyau... signal(SIGUSR1, sigintHandler); // 10 SIGUSR1 Signal utilisateur 1 - signal(SIGSEGV, sigintHandler); // 11 SIGSEGV Violation de mémoire signal(SIGUSR2, sigintHandler); // 12 SIGUSR2 Signal utilisateur 2 signal(SIGPIPE, sigintHandler); // 13 SIGPIPE Broken PIPE - Erreur PIPE sans lecteur signal(SIGALRM, sigintHandler); // 14 SIGALRM Alarme horloge signal(SIGTERM, sigintHandler); // 15 SIGTERM Signal de terminaison signal(SIGSTKFLT, sigintHandler); // 16 SIGSTKFLT Stack Fault signal(SIGCHLD, sigintHandler); // 17 SIGCHLD ou SIGCLD modification du statut d'un processus fils - signal(SIGCLD, sigintHandler); // 17 SIGCHLD ou SIGCLD modification du statut d'un processus fils + signal(SIGCLD, sigintHandler); // 17 SIGCHLD ou SIGCLD modification du statut d'un processus fils signal(SIGCONT, sigintHandler); // 18 SIGCONT Demande de reprise du processus - signal(SIGSTOP, sigintHandler); // 19 SIGSTOP Demande de suspension imbloquable + signal(SIGSTOP, sigintHandler); // 19 SIGSTOP Demande de suspension imbloquable. En pratique, inutile car toujours intercepté par le noyau... signal(SIGTSTP, sigintHandler); // 20 SIGTSTP Demande de suspension depuis le clavier signal(SIGTTIN, sigintHandler); // 21 SIGTTIN lecture terminal en arrière-plan signal(SIGTTOU, sigintHandler); // 22 SIGTTOU écriture terminal en arrière-plan - signal(SIGURG, sigintHandler); // 23 SIGURG évènement urgent sur socket + signal(SIGURG, sigintHandler); // 23 SIGURG évènement urgent sur socket signal(SIGXCPU, sigintHandler); // 24 SIGXCPU temps maximum CPU écoulé signal(SIGXFSZ, sigintHandler); // 25 SIGXFSZ taille maximale de fichier atteinte signal(SIGVTALRM, sigintHandler); // 26 SIGVTALRM alarme horloge virtuelle signal(SIGPROF, sigintHandler); // 27 SIGPROF Profiling alarm clock signal(SIGWINCH, sigintHandler); // 28 SIGWINCH changement de taille de fenêtre signal(SIGPOLL, sigintHandler); // 29 SIGPOLL (System V) occurence d'un évènement attendu - signal(SIGIO, sigintHandler); // 29 SIGIO (BSD) I/O possible actuellement - signal(SIGPWR, sigintHandler); // 30 SIGPWR Power failure restart - signal(SIGSYS, sigintHandler); // 31 SIGSYS Erreur d'appel système + signal(SIGIO, sigintHandler); // 29 SIGIO (BSD) I/O possible actuellement + signal(SIGPWR, sigintHandler); // 30 SIGPWR Power failure restart return(0); } @@ -375,7 +381,7 @@ int8_t init_signaux(void) // Fonction : Handler unique de tous les signaux. Récupére la valeur du signal et met à jour la variable globale correspondante. // ATTENTION : il ne faut PAS faire de printf (ou équivalent) ici car il y a des restrictions dans les signals handlers. // En l'occurence, le traitement en fonction du numéro de signal est fait dans la fonction 'analyse_signal()' ci-dessus. -// Reçoit : Rien +// Reçoit : Signal reçu // Retour : Rien //================================================================================================================================================================== void sigintHandler(int32_t signal) @@ -385,3 +391,27 @@ void sigintHandler(int32_t signal) } +//================================================================================================================================================================== +// Fonction : Handler des signaux d'erreur fatale. Dans ce cas, un 'return' n'est pas acceptable car il ne débouchera, au mieux, que sur la répétition de +// l'erreur sans traitement possible. +// Reçoit : Signal reçu +// Retour : Rien +//================================================================================================================================================================== +void sigfatalHandler(int32_t signal) +{ + // Uniquement des fonctions "async-signal-safe" ici : pas de sprintf/printf classiques, pas de mutex, pas de malloc. write() sur un fd est sûr : + const char msg[] = "/!\\ Signal fatal recu (SIGSEGV/SIGBUS/SIGILL/SIGFPE) - Arret immediat....\n"; // Pas d'accents... + write(STDERR_FILENO, msg, sizeof(msg) - 1); + + // Optionnel : capturer une pile d'appel avant de sortir (backtrace() est généralement sûr en pratique même si pas garanti strictement async-signal-safe) : + void *tab[20]; + int n = backtrace(tab, 20); + + char buf[64]; + int len = sprintf(buf, "La fontion backtrace() a retourne %d frame(s) :\n", n); // Pas d'accents... + write(STDERR_FILENO, buf, len); + + if (n > 0) backtrace_symbols_fd(tab, n, STDERR_FILENO); + + _exit(1); // JAMAIS return ici, et de préférence _exit() plutôt que exit() qui appelle des handlers atexit/flush non signal-safe +} diff --git a/sources/main.h b/sources/main.h index 1ea0258..4bb8dd9 100644 --- a/sources/main.h +++ b/sources/main.h @@ -19,10 +19,11 @@ #include #include #include +#include #include #include -#include // Nécessaire pour E/S GPIO sur CM5 #include +#include #include #include #include @@ -44,6 +45,10 @@ #include #include +#ifdef CIBLE_CM5 +#include // Nécessaire pour E/S GPIO sur CM5 +#endif + #include "audio.h" #include "batteries.h" #include "bdd.h" @@ -73,7 +78,6 @@ #include "usb.h" - // ********************************************************************************************************************************************************************************** // Define : // ********************************************************************************************************************************************************************************** @@ -82,8 +86,12 @@ #define OFF 0 #define ON 1 -#define FALSE 0 -#define TRUE 1 +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef TRUE +#define TRUE 1 +#endif #define HIGH 1 #define LOW 0 @@ -1089,10 +1097,6 @@ struct Struct_module_physique uint8_t maj_soft_disponible; // Indique si une mise à jour de logiciel a été chargée dans la carte et est disponible pour être activée. Utilisée dans le séquenceur 'gestion_chargement_carte()' (auparavant était stocké en BDD mais retiré en 02/2022) }; - - - - struct Struct_fichier_download { char nom[MAX_LONGUEUR_NOM_FICHIER]; @@ -1101,6 +1105,7 @@ struct Struct_fichier_download bool flag_a_telecharger; bool flag_a_supprimer; }; + struct Struct_download { char nom_repertoire_destination[MAX_LONGUEUR_NOM_REPERTOIRE_LOCAL]; // Nom du répertoire sur lequel le fichier sera uploadé @@ -1194,7 +1199,8 @@ struct Struct_compute_module uint8_t otp_reading_allowed; uint8_t warranty_bit; uint8_t new_style_revision; - uint8_t memory_size; + uint8_t ram_size; + uint64_t flash_size; uint8_t manufacturer; uint8_t processor; uint8_t type; diff --git a/sources/reseaux.c b/sources/reseaux.c index 23eeecf..2c852bb 100644 --- a/sources/reseaux.c +++ b/sources/reseaux.c @@ -981,10 +981,44 @@ sudo iwlist wlan0 scan | grep -i 'Address:\|Channel:\|ESSID:\|Quality=' +//================================================================================================================================================================== +// Fonction : Recherche une interface réseau donnée par son nom dans la liste chaînée retournée par 'getifaddrs()', et récupère son adresse IPV4 si elle est +// active (bit IFF_RUNNING positionné). Le test du bit 'IFF_RUNNING' est nécessaire car le port peut être UP (visible via IFF_UP, équivalent de +// 'ifconfig') mais ne pas être physiquement connecté. +// Reçoit : La liste des interfaces (issue de 'getifaddrs()'), le nom de l'interface recherchée (ex : "eth0") et le pointeur destination pour l'adresse IP +// Renvoit : Rien. La destination n'est modifiée que si l'interface est trouvée, active, et possède une adresse IPV4. +//================================================================================================================================================================== +static void extraire_ip_interface(struct ifaddrs *addresses, const char *nom_interface, char *destination) +{ +struct ifaddrs *address; +char chaine_ip[TAILLE_ADRESSE_IP]; +const uint32_t family_size = sizeof(struct sockaddr_in); + + for (address = addresses; address != NULL; address = address->ifa_next) + { + if (address->ifa_addr == NULL) continue; // Protection : certaines interfaces (virtuelles, tunnels...) n'ont pas d'adresse assignée + if (address->ifa_addr->sa_family != AF_INET) continue; // On ne traite que les IPV4 pour le moment... + if (strcmp(address->ifa_name, nom_interface) != 0) continue; // Ce n'est pas l'interface recherchée + if ((address->ifa_flags & IFF_RUNNING) == 0) continue; // Interface non physiquement connectée + + getnameinfo(address->ifa_addr, family_size, chaine_ip, TAILLE_ADRESSE_IP_V4, 0, 0, NI_NUMERICHOST); + strcpy(destination, chaine_ip); + +#ifdef __DEBUG_RESEAUX +{ +char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; +sprintf(tmp, "Adresse IP sur l'interface '%s' = %s [IFF_RUNNING=Oui]", nom_interface, destination); +affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT); +} +#endif + return; // Trouvée : inutile de continuer à parcourir la liste pour cette interface + } +} + //================================================================================================================================================================== // Fonction : Récupère l'adresse IP en cours // Cette fonction a été trouvée ici : https://subscription.packtpub.com/book/cloud-and-networking/9781789349863/1/ch01lvl1sec22/listing-network-adapters-from-c -// dans la partie Unix. +// dans la partie Unix, puis factorisée via 'extraire_ip_interface()' pour éviter la répétition du parcours de liste pour chaque interface. // Par défaut, elle retourne quelque chose comme : // lo IPv4 127.0.0.1 // eth0 IPv4 192.168.1.31 @@ -1004,11 +1038,8 @@ sudo iwlist wlan0 scan | grep -i 'Address:\|Channel:\|ESSID:\|Quality=' //================================================================================================================================================================== int8_t get_ip_address(void) { - struct ifaddrs *addresses; - struct ifaddrs *address; - char chaine_ip[TAILLE_ADRESSE_IP]; - const uint32_t family_size = sizeof(struct sockaddr_in); - char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; +struct ifaddrs *addresses; +char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; // Recherche de la liste de toutes les interfaces disponibles : if (getifaddrs(&addresses) == -1) @@ -1023,58 +1054,13 @@ int8_t get_ip_address(void) strcpy(reseaux.wifi.sta.adresse_ip, ADRESSE_IP_INCONNUE); strcpy(reseaux.wifi.ap.adresse_ip, ADRESSE_IP_INCONNUE); - // Boucle sur toutes les interfaces reçues : - address = addresses; - while(address) - { - int family = address->ifa_addr->sa_family; -// if (family == AF_INET || family == AF_INET6) // AF_INET correspond à IPV4 et AF_INET6 correspond à IPV6 - if (family == AF_INET) // On ne traite que les IPV4 pour le moment... - { - getnameinfo(address->ifa_addr, family_size, chaine_ip, TAILLE_ADRESSE_IP_V4, 0, 0, NI_NUMERICHOST); // Permet de récupérer la - - if (strstr(address->ifa_name, "eth0") != NULL) - { - if ((address->ifa_flags & IFF_RUNNING) != 0) strcpy(reseaux.ethernet.adresse_ip, chaine_ip); // Le test du bit 'IFF_RUNNING' est nécessaire car le port peut être UP (visible via IFF_UP équivalent de 'ifconfig') mais ne pas être physiquement connecté... -#ifdef __DEBUG_RESEAUX -sprintf(tmp, "Adresse IP sur le réseau Ethernet du bord = %s [IFF_RUNNING=%s]", reseaux.ethernet.adresse_ip, ((address->ifa_flags & IFF_RUNNING) == 0 ? "Non" : "Oui") ); -affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT); -#endif - } - else if (strstr(address->ifa_name, "wlan0") != NULL) - { - if ((address->ifa_flags & IFF_RUNNING) != 0) strcpy(reseaux.wifi.sta.adresse_ip, chaine_ip); // Le test du bit 'IFF_RUNNING' est nécessaire car le port peut être UP (visible via IFF_UP équivalent de 'ifconfig') mais ne pas être physiquement connecté... - -#ifdef __DEBUG_RESEAUX -sprintf(tmp, "Adresse IP sur le réseau Wifi du bord (connecté en mode STA) = %s [IFF_RUNNING=%s]", reseaux.wifi.sta.adresse_ip, ((address->ifa_flags & IFF_RUNNING) == 0 ? "Non" : "Oui") ); -affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT); -#endif - } - else if (strstr(address->ifa_name, "uap0") != NULL) - { - if ((address->ifa_flags & IFF_RUNNING) != 0) strcpy(reseaux.wifi.ap.adresse_ip, chaine_ip); // Le test du bit 'IFF_RUNNING' est nécessaire car le port peut être UP (visible via IFF_UP équivalent de 'ifconfig') mais ne pas être physiquement connecté... -#ifdef __DEBUG_RESEAUX -sprintf(tmp, "Adresse IP de ShipBase sur le réseau Wifi ShipHeart (mode AP) = %s [IFF_RUNNING=%s]", reseaux.wifi.ap.adresse_ip, ((address->ifa_flags & IFF_RUNNING) == 0 ? "Non" : "Oui") ); -affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_PAR_DEFAUT); -#endif - } - - -/* - printf("%s\t", address->ifa_name); - printf("%s\t", family == AF_INET ? "IPv4" : "IPv6"); - - - getnameinfo(address->ifa_addr, family_size, chaine_ip, TAILLE_ADRESSE_IP_V4, 0, 0, NI_NUMERICHOST); - printf("\t%s\n", chaine_ip);*/ - - } - address = address->ifa_next; - } + // Recherche de l'adresse IP de chacune des 3 interfaces suivies : + extraire_ip_interface(addresses, "eth0", reseaux.ethernet.adresse_ip); + extraire_ip_interface(addresses, "wlan0", reseaux.wifi.sta.adresse_ip); + extraire_ip_interface(addresses, "uap0", reseaux.wifi.ap.adresse_ip); freeifaddrs(addresses); - - return 0; -} \ No newline at end of file +} + diff --git a/sources/serial.c b/sources/serial.c index 59e5622..c3e9723 100644 --- a/sources/serial.c +++ b/sources/serial.c @@ -346,7 +346,7 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; //-------------------------------------------------------------------------------------------------------------------------------- // Finalisation du message de débug : - strcat(tmp, ")\t: OK"); + strcat(tmp, ")\t\t: OK"); affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK); return(0); diff --git a/sources/sorties.c b/sources/sorties.c index 3941b47..da319ec 100644 --- a/sources/sorties.c +++ b/sources/sorties.c @@ -17,8 +17,11 @@ int16_t sortie_no(uint8_t type, uint8_t module, uint8_t no); // Variables globales : struct Struct_sorties sorties; + +#ifdef CIBLE_CM5 struct gpiod_chip *gpiod_chip0_sorties; // Nécessaire pour CM5 struct gpiod_line_request *gpiod_sorties_request; // Nécessaire pour CM5 +#endif /********************************************************************************************************************************************************************************** @@ -220,6 +223,7 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; //==================================================================================================== if (systeme.generation_shipbase == GENERATION_SHIPBASE_V3) { +#ifdef CIBLE_CM5 unsigned int offsets[MAX_NOMBRE_SORTIES_GPIO]; uint8_t nb_lignes = 0; @@ -266,6 +270,13 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; } return(0); // On sort ici : la boucle V1/V2 ci-dessous ne doit pas s'exécuter pour V3 + +#else // Ne devrait jamais arriver ... : + sprintf(tmp, "GENERATION_SHIPBASE_V3 incompatible avec cette plateforme de compilation."); + affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); + return(-1); +#endif + } //==================================================================================================== @@ -346,6 +357,7 @@ int8_t on; else on = ON; +#ifdef CIBLE_CM5 //-------------------------------------------------------- // V3 : if (systeme.generation_shipbase == GENERATION_SHIPBASE_V3) @@ -354,6 +366,7 @@ int8_t on; gpiod_line_request_set_value(gpiod_sorties_request, no, val); return; } +#endif //-------------------------------------------------------- // V1 & V2 : diff --git a/sources/systeme.c b/sources/systeme.c index 0cf2181..db5f17a 100644 --- a/sources/systeme.c +++ b/sources/systeme.c @@ -1593,11 +1593,11 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; //Fermeture de MySQL : mysql_close(bdd.pointeur); - + // Désactivation des sorties de commandes d'alimentations : // ecriture_sortie(TYPE_SORTIE_GPIO, 0, CM3P_DO_USBPWR_EN, OFF); // Coupure de l'alim des USB /!\ Il ne faut PAS couper en mode debuug ous peine de ne plus avoir accès au réseau Ethernet via le routeur USB/Ethernet....! -// ecriture_sortie(TYPE_SORTIE_GPIO, 0, audio.cle_primaire_sortie_cm_do_audio_sd, OFF); // Coupure du circuit audio + ecriture_sortie(TYPE_SORTIE_GPIO, 0, audio.sortie_gpio_cm_do_audio_sd, OFF); // 0 est l'adresse de ShipBase// Coupure du circuit audio (évite les glitch désagréable après un CTR+C) // ecriture_sortie(TYPE_SORTIE_GPIO, 0, ecran.cle_primaire_sortie_cm_pdown_hdmi_cmd_n, OFF); // Coupure de la sortie du flux HDMI // ecriture_sortie(TYPE_SORTIE_GPIO, 0, ecran.cle_primaire_sortie_cm_do_lcd_en_vgx, OFF); // Coupure de l'alim VGx @@ -1792,6 +1792,8 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; printf("\n"); } + json_object_put(parsed_json); // Libère l'objet JSON racine (et, par cascade, tous ses sous-objets/champs internes) + return(json_version); } @@ -1887,13 +1889,25 @@ int8_t version_compute_module(void) FILE *fp; char revcode[32]; uint32_t code; +unsigned long long nb_secteurs; +unsigned long long taille_octets; +double taille_go_reelle; char chaine_valeur[300]; char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; + //======================================================================================================== + // Lecture des données système et extraction des données : + //======================================================================================================== + + //--------------------------------------------------------------- fp = popen("cat /proc/cpuinfo | awk '/Revision/ {print $3}'", "r"); // récupération du code de Révision via la commande "cat /proc/cpuinfo | awk '/Revision/ {print $3}'". Exemple de retour : "c03141" - if (fp == NULL) return(-1); // Cas où la commande n'a pas pu être exécutée correctement + if (fp == NULL) + { + affichage_debug(__FILE__, __LINE__, "/!\\ La lecture du fichier 'cpuinfo' est impossible...!", TYPE_MESSAGE_DEBUG_ERREUR); + return(-1); + } fgets(revcode, sizeof(revcode), fp); // Lecture de la ligne pclose(fp); // Fermeturre du fichier @@ -1905,13 +1919,41 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; systeme.cm.otp_reading_allowed = (code >> 29) & 0x1; systeme.cm.warranty_bit = (code >> 25) & 0x1; systeme.cm.new_style_revision = (code >> 23) & 0x1; - systeme.cm.memory_size = (code >> 20) & 0x7; + systeme.cm.ram_size = (code >> 20) & 0x7; systeme.cm.manufacturer = (code >> 16) & 0x0F; systeme.cm.processor = (code >> 12) & 0x0F; systeme.cm.type = (code >> 4) & 0xFF; systeme.cm.revision = (code >> 0) & 0x0F; - if (systeme.cm.new_style_revision == 0) // Ce bit indique le format du code de révision. Le 'new' type est actif depuis le RaspberryPi2 donc on devrait toujours être dans ce cas... + + //--------------------------------------------------------------- + fp = fopen("/sys/block/mmcblk0/size", "r"); + + if (fp == NULL) + { + affichage_debug(__FILE__, __LINE__, "/!\\ La lecture du fichier 'cpuinfo' est impossible...!", TYPE_MESSAGE_DEBUG_ERREUR); + return(-1); + } + + if (fscanf(fp, "%llu", &nb_secteurs) != 1) + { + affichage_debug(__FILE__, __LINE__, "/!\\ La lecture du nombre de secteurs de flash est impossible...!", TYPE_MESSAGE_DEBUG_ERREUR); + return(-1); + } + + fclose(fp); + + taille_octets = nb_secteurs * 512ULL; // /sys/block//size est toujours exprimé en secteurs de 512 octets, quelle que soit la taille physique du secteur + taille_go_reelle = (double)taille_octets / 1000000000.0; // Go décimaux (norme fabricants eMMC), pas Gio + + systeme.cm.flash_size = taille_octets; + + + //======================================================================================================== + // Traitement de l'affichage de debug et génération de la ligne 'Version_cm" de TB_Systeme : + //======================================================================================================== + + if (systeme.cm.new_style_revision == 0) // Ce bit indique le format du code de révision. Le 'new' type est actif depuis le RaspberryPi2 donc on devrait toujours être dans ce cas... { sprintf(tmp, "/!\\ Le bit de style de révision indique un ancien style de révision qui ne peut pas être lu...!"); affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_ERREUR); @@ -1948,7 +1990,12 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; case 0x13 : { strcpy(chaine_valeur, "400"); break; } case 0x14 : { strcpy(chaine_valeur, "CM4"); break; } case 0x15 : { strcpy(chaine_valeur, "CM4S"); break; } + case 0x16 : { strcpy(chaine_valeur, "Internal Use only"); break; } + case 0x17 : { strcpy(chaine_valeur, "5"); break; } case 0x18 : { strcpy(chaine_valeur, "CM5"); break; } + case 0x19 : { strcpy(chaine_valeur, "500/500+"); break; } + case 0x1A : { strcpy(chaine_valeur, "CM5 Lite"); break; } + case 0x1B : { strcpy(chaine_valeur, "CM0"); break; } case 0x07 : case 0x0B : @@ -1964,7 +2011,7 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; //--------------------------------------------------------------- - switch (systeme.cm.memory_size) + switch (systeme.cm.ram_size) { case 0 : { strcpy(chaine_valeur, "256Mo"); break; } case 1 : { strcpy(chaine_valeur, "512Mo"); break; } @@ -1972,9 +2019,11 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; case 3 : { strcpy(chaine_valeur, "2Go"); break; } case 4 : { strcpy(chaine_valeur, "4Go"); break; } case 5 : { strcpy(chaine_valeur, "8Go"); break; } + case 6 : { strcpy(chaine_valeur, "16Go"); break; } + case 7 : { strcpy(chaine_valeur, ">16Go"); break; } default : { - sprintf(chaine_valeur, "Inconnue [code = %i]", systeme.cm.memory_size); + sprintf(chaine_valeur, "Inconnue [code = %i]", systeme.cm.ram_size); break; } } @@ -1982,6 +2031,25 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; strcat(systeme.cm.chaine_version, "-"); strcat(systeme.cm.chaine_version, chaine_valeur); + strcat(systeme.cm.chaine_version, "[RAM]"); + + + //--------------------------------------------------------------- + + + // Arrondi à la taille commerciale la plus proche (la capacité réelle exposée est toujours < capacité nominale, à cause du sur-provisionnement) + if (taille_go_reelle <= 9.0) strcpy(chaine_valeur, "8Go"); + else if (taille_go_reelle <= 18.0) strcpy(chaine_valeur, "16Go"); + else if (taille_go_reelle <= 36.0) strcpy(chaine_valeur, "32Go"); + else if (taille_go_reelle <= 72.0) strcpy(chaine_valeur, "64Go"); + else if (taille_go_reelle <= 144.0) strcpy(chaine_valeur, "128Go"); + else sprintf(chaine_valeur, "%.1fGo", taille_go_reelle); + + affichage_ligne_version_compute_module(tmp, "Taille Flash", chaine_valeur); + + strcat(systeme.cm.chaine_version, "-"); + strcat(systeme.cm.chaine_version, chaine_valeur); + strcat(systeme.cm.chaine_version, "[FLASH]"); //--------------------------------------------------------------- @@ -2064,7 +2132,6 @@ char tmp[MAX_LONGUEUR_BUFFER_TEMPORAIRE_DEBUG]; } affichage_ligne_version_compute_module(tmp, "Processeur", chaine_valeur); - //--------------------------------------------------------------- affichage_debug(__FILE__, __LINE__, tmp, TYPE_MESSAGE_DEBUG_OK);