Je travaille sur un gros sketch pour une alarme avec GSM. Jusqu’à hier, le watchdog fonctionnait parfaitement mais ne fonctionne plus depuis que j’ai dépassé un certain seuil de taille du programme. Suite à tests, avec une taille pgm de 147814 bytes ça fonctionne, et avec 147834, ça ne fonctionne plus.
Quand le watchdog fonctionne normalement (pgm de 147814 bytes), les leds du GSM continuent de clignoter et le programme (Setup()) redémarre correctement. Avec le programme à 147834 bytes, quand je force le watchdog à faire la Reset (délai de + de 8s dépassé), au moment du reset, je vois que quelque chose se passe car les leds du GSM cessent de clignoter mais le code ne s’exécute pas.
Ce qui n'est pas normal est que le GSM s'arrête comme pour une Reset physique (ligne Reset de l'arduino LOW) alors que normalement la reset du watchdog force juste le redémarrage du sketch.
J’ai donc suspecté un problème d’initialisation de la « Vector Table. Après création des fichiers de compilation, j’ai cherché dans le .bin la « Vector Table » mais je ne la trouve pas.
Normalement, elle devrait être initialisée avec l’adresse du démarrage du programme (Setup()) dans l’entrée 0 (Reset) de la Vector Table. Je pensais trouver cette table en fin ou début de programme. En début il y a bien quelque chose qui pourrait ressembler à une table mais je ne fais pas le rapprochement avec le reste du code.
En conclusion, je ne sais pas trop comment m’en sortir. Quelqu'un a t-il une idée.
Je pense que le problème doit être soit une erreur de compilation (ce qui ne serait pas nouveau), soit un problème de bootloader. Je crains qu'il n'y ait pas de solution.
Si je ne résous pas ce problème, je vais devoir ajouter un watchdog externe ce qui ne me satisfait pas car ça impliquera obligatoirement une Reset physique comme le power on... et j'aurais bien voulu éviter ça.
Bonjour,
De toute façon, tant que l'on aura pas ledit gros sketch sous les yeux, je crains que nous ne poussions pas t'aider...
Maintenant, je ne sais pas ce qu'est un gros sketch ![]()
A suivre...
Se pourrait il plutôt que ce ne soit pas le watchdog qui change de comportement selon la taille du programme, mais plutôt le programme qui devient instable au-delà d’un certain seuil, en raison d’un débordement de mémoire ou d’une corruption logique?
À noter aussi (si je me souviens bien) que Si le sketch dépasse 128 ko, des interruptions peuvent pointer vers du code placé trop haut en mémoire Flash, ce qui empêche leur exécution correcte et peut bloquer le programme. (Si vous déclarez avec ISR)
La limite de 128k semble problématique.
Trouvé ici
On a device with more than 128 KiB of flash, how to make function pointers work?
Function pointers beyond the "magical" 128 KiB barrier(s) on larger devices are supposed to be resolved through so-called trampolines by the linker, so the actual pointers used in the code can remain 16 bits wide.
In order for this to work, the option-mrelaxmust be given on the compiler command-line that is used to link the final ELF file. (Older compilers did not implement this option for the AVR, use-Wl,–relaxinstead.)
Je n'ai jamais essayé. Je n'implémente pas mes gros programmes sur AVR mais sur des ESP32.
Concernant la limite des 128K, l'info date de aout 2014.... A mon avis, ce n'est plus d'actualité avec l'IDE d'aujourd'hui, sinon mon sketch de 148k ne fonctionnerait pas du tout.
Qu'il fasse 147814 ou 14834 bytes, donc pour le cas 1 le watchdog fonctionne et le cas 2 il ne fonctionne pas, j'utilise l'interrupt0 pour le GSM (pour SMS ou appels entrants initialisé avec AttachInterrupt) et dans les 2 cas, l'interrupt est bien traité.
Pour l'Atmega2560, la mémoire disponible est 253952 (3E000) donc 18 bits. Je suppose que tout est prévu dans le design IDE et Bootloader.. sinon => carton rouge aux développeurs.
J'ai éssayé pour voir le software reset (void (* ResetFunc) (void) = 0;) mais il ne fonctionne pas... Ca fige le programme et in finé, c'est le watchdog qui prend le relais... sauf que pour mon cas 2 ça ne redémarre pas.
Dans le sketch de 147814 bytes, j'ai changé une ligne de code (a) par 2 lignes (b) :
a: Lcd_Line2[p] = (i + 1) | 0x30; // On insère le n° de la boucle (1 à 8) dans la ligne
b: if (i == 0) { Lcd_Line2[p] = '9'; } // On insère le n° de la 1ère boucle
b: else { Lcd_Line2[p] = (i - 1) | 0x30; } // Pour les boucles 10 à 16, on ne met que le 2ème chiffre soit 0 à 6
La taille passe de 147814 à 147852 et avec 147852 le watchdog ne fonctionne plus.
A la fin du Setup(), je fais le wdt_enable(WDTO_8S). Pour voir, j'ai voulu mettre un while(1) pour tester le watchdog avant de passer à loop().
Ce test est impossible car la compilation est suffisamment intelligente pour ne pas prendre tout le code. La taille obtenue dans ces conditions est 116670, donc le watchdog va forcément fonctionner.
Si je met le while(1) au début de loop(), la compil donne 45798 bytes... pourquoi pas 116670 ???? surprenant.
A la réponse de J.M.L, je ne vois pas pourquoi le programme deviendrait instable au-delà d'un certain seuil. Pour mon cas 2 le pgm fonctionne très bien sauf le watchdog.
Que voyez vous par débordement de mémoire ?? Le programme est dans une EEPROM qui ne peut être écrite que pendant le téléversement. Le seul problème concernant les corruptions éventuelles sont dans la RAM. Exemple : on a défini un buffer de 100 caractères et on en écrit plus de 100. Dans ce cas, on écrase les positions mémoires derrière ce buffer.
Qu'entendez vous aussi par "corruption logique" ??
Si vous êtes limite en RAM et que le code supplémentaire nécessite des allocations mémoire.
Pour votre interruption vous utilisez attachInterrupt() ou ISR()?
Sinon sur la Mega 2560, les codes dépassant 128 Ko de flash peuvent poser des soucis liés à l’architecture mémoire du microcontrôleur. La mémoire flash y est linéaire mais au-delà de 128 Ko (0x1FFFF), l’adressage change : il faut utiliser le registre RAMPZ pour accéder correctement aux données en mémoire flash. (l’accès au-delà de 128 Ko nécessite une gestion spéciale pour les données constantes lues avec les instructions LPM, car celles-ci utilisent un adressage 16 bits par défaut. Pour accéder aux adresses au-delà de 128 Ko, le registre RAMPZ fournit les bits supplémentaires.)
Cela a plusieurs implications :
Les fonctions utilisant PROGMEM peuvent mal fonctionner si elles ne sont pas conçues pour lire au-delà de 128 Ko. Par exemple, pgm_read_byte() ou pgm_read_word() n’accèdent correctement qu’aux 128 premiers Ko, sauf si on utilise les versions 24 bits comme pgm_read_byte_far() ou pgm_read_word_far().
Certains outils ou bibliothèques n’ont pas été prévus pour gérer cette extension d’adressage, ce qui peut entraîner des corruptions de données ou des plantages si les données sont placées au-delà de cette limite.
Les strings constantes (stockées avec F()) et les gros tableaux doivent être manipulés avec soin, surtout lorsqu’on utilise des pointeurs vers des données flash, sous peine d’accéder à des données incorrectes si le registre RAMPZ n’est pas pris en compte.
Enfin il y a le souci des fonctions d’interruption que je mentionnais précédemment (les fonctions appelées par une ISR doivent être compilées correctement pour supporter les sauts longs si elles se trouvent au-delà de 128 Ko. Le compilateur s’en charge normalement, mais des problèmes peuvent apparaître si une bibliothèque ne gère pas bien ce cas, ou si des pointeurs vers des fonctions sont utilisés de façon incorrecte.)
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.