Skyduino:~#
Articles
arduino, tutoriel

[Arduino] Sauvegarder le programme d’une carte Arduino (ou compatible)

Bonjour tout le monde !

La question suivante m’a été posée sur Twitter. Comme elle me semblait intéressante, j’ai décidé de faire un rapide article dessus 😉

La question : « Comment faire pour sauvegarder le programme d’une carte Arduino »

Petite mise au point avant de commencer

L’idée ici est de récupérer le programme binaire (« le firmware » en bon english) dans la carte Arduino, mais en aucun cas de récupérer le code source du programme.
Programme binaire et code source sont deux choses radicalement différentes, bien qu’intimement liées.

On peut compiler un code source en programme binaire, mais l’inverse (binaire vers code source) n’est pas aussi simple, pour ne pas dire impossible (sauf pour quelques spécialistes).
Si vous pensiez pouvoir obtenir d’un clic de souris du code source C/C++ à partir d’un binaire, désolé de vous ramener sur terre, mais ce n’est pas comme cela que ça marche dans la vraie vie 😉

Maintenant que les choses ont été mises au clair, on peut continuer.

Le bootloader Arduino : optiboot

Ce qui rend possible la sauvegarde du programme binaire présent dans une carte Arduino, sans faire usage du moindre outil spécialisé, c’est le « bootloader ».
Dans le cas d’une carte Arduino, celui se nomme « Optiboot ». C’est un joli bébé de 512 octets écrit en code C.

Un bootloader n’est rien d’autre qu’un petit bout de code qui s’exécute avant le code utilisateur (votre code).
Ce petit bout de code n’a qu’une seule et unique fonction : transférer un programme binaire d’un point A (le port série USB dans le cas d’une carte Arduino) à un point B (la mémoire interne du microcontrôleur).

Pour ce faire, un bootloader implémente en général deux fonctions : lire une page mémoire et écrire une page mémoire.
La fonction d’écriture permet d’écrire le programme en mémoire (logique) et la fonction de lecture permet de vérifier que tout s’est bien passé en relisant les données.

Dans la vraie vie, sous-entendu dans un vrai produit vendu au grand public, le bootloader (s’il y en a un) est verrouillé pour éviter les bidouilles.
Les utilisateurs de smartphones Android connaissent bien le principe des bootloaders bloqués, sur microcontrôleur c’est pareil.

Dans un vrai produit, lors de la mise en production, on fait en général trois choses :
– on verrouille la mémoire du microcontrôleur pour éviter qu’une personne avec le bon matériel ne puisse physiquement lire ou écrire la mémoire,
– on désactive tout ce qui touche au débug (que ce soit dans le code ou dans le hardware) pour éviter de donner une porte d’accès aux vilains bidouilleurs,
– et pour finir, on verrouille le bootloader (via en général un système de chiffrement, avec signature cryptographique) pour permettre à l’utilisateur final de mettre à jour son produit facilement sans outils, mais sans pour autant le laisser faire n’importe quoi.

La philosophie open source fait que les cartes Arduino (et autres cartes compatibles Arduino) sont livrées non verrouillés et avec un bootloader dont on connait absolument tout, du protocole de communication jusqu’au code source.

On peut donc faire quelque chose qui serait impossible sur un produit lambda du marché : récupérer le programme binaire dans la mémoire du microcontrôleur.

AVRDUDE

Avrdude est un logiciel bien pratique qui permet de parler avec plein de microcontrôleurs AVR différents, au moyen de plein de sondes de débug, programmateurs ou bootloaders différents.
Et parmi les bootloader supportés, on retrouve un nom qu’on connait bien : « arduino ».

Je préviens de suite, c’est un utilitaire en ligne de commande, donc si vous avez la phobie des terminaux et des consoles systèmes, ça risque de vous déplaire.
Pour les autres, montez à bords, on décolle.

L’IDE Arduino utilise Avrdude pour envoyer les programmes après compilation, l’exécutable d’Avrdude doit donc se trouver quelque part ?
Exact ! Dans « Arduino-1.0.x\hardware\tools\avr\bin » pour être précis.

Si vous êtes sous Seven ou Windows 8, rendez-vous dans le dossier en question puis faites click droit en appuyant sur la touche majuscule gauche.
Vous devriez voir apparaître une option « Ouvrir une fenêtre de commande ici » dans la liste déroulante, cliquez dessus.

Saisissez maintenant la commande : « avrdude -v » (sans les quotes) pour voir si Avrdude répond.
Vous devriez obtenir une réponse de cette forme :
E:\PortableApps\Arduino-1.0.6\hardware\tools\avr\bin>avrdude -v

avrdude: Version 5.11, compiled on Sep 2 2011 at 19:38:36
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2009 Joerg Wunsch

Si c’est le cas, cela signifie que Avrdude est prêt pour la bataille.

Let’s go dump

Il ne reste maintenant plus qu’à connecter votre carte Arduino et noter le port série qui lui correspond.

La commande de base pour lire le contenu de la mémoire est la suivante :
avrdude -p LENOMDUMICRONTROLEUR -P LENOMDUPORTSERIE -c LENOMDUBOOTLOADER -U flash:r:LENOMDEMONFICHIER.hex:i

Avant de lancer la commande, détaillons un peu la structure de celle-ci :
avrdude : le nom de l’utilitaire qui nous intéresse
-p : (p minuscule) le prochain argument sera le nom du microcontrôleur de la carte (« m328p » pour une carte Arduino classique, « m2560 » pour une carte Mega2560)
LENOMDUMICRONTROLEUR : le nom du microcontrôleur (« m328p », « m2560 », ou autre en fonction de la carte)
-P : (P majuscule) le prochain argument sera le nom du port série
LENOMDUPORTSERIE : dans mon cas COM3, mais chez vous se sera surement un autre port
-c : le prochain argument sera le nom du protocole de communication à utiliser (« arduino » pour les cartes Arduino classiques, « stk500v2 » pour les cartes Mega, « stk500 » pour les vieilles cartes Arduino)
LENOMDUBOOTLOADER : le nom du protocole de communication (« arduino », « stk500v2 » ou « stk500 » en fonction de la carte)
-U : le prochain argument sera une commande Avrdude
flash:r:LENOMDEMONFICHIER.hex:i : ça ce complique, voici le détail :
flash : on travaille sur le mémoire flash interne (mémoire programme)
:r: : on souhaite lire le contenu de la mémoire
LENOMDEMONFICHIER.hex : le chemin vers le fichier de sortie (avec des quotes autours si nécessaire)
:i : on souhaite obtenir un fichier de sortie au format Intel Hex (le format classique)

Exemple avec une carte arduino UNO Rev3 (microcontrôleur « m328p » et bootloader « arduino » donc), sur le port « COM3 » et un fichier « toto.hex » (que je vais enregistrer sur mon bureau).
avrdude -p m328p -P COM3 -c arduino -U flash:r:C:\Users\Fabien\Desktop\toto.hex:i

Le résultat :
E:\PortableApps\Arduino-1.0.6\hardware\tools\avr\bin>avrdude -p m328p -P COM3 -c arduino -U flash:r:C:\Users\Fabien\Desktop\toto.hex:i

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e950f
avrdude: reading flash memory:

Reading | ################################################## | 100% 4.25s

avrdude: writing output file "C:\Users\Fabien\Desktop\toto.hex"

avrdude: safemode: Fuses OK (H:00, E:00, L:00)

avrdude done. Thank you.

J’obtiens alors un fichier « toto.hex » avec le contenu de la mémoire.
Si on l’ouvre avec un éditeur de texte, on voit bien qu’il contient des données :
(...)
:20026000551FEA95D1F7203080E0380781E0480780E0580720F481E08093190112C02030A1
:2002800080E0380788E0480780E0580778F482E08093190173E056954795379527957A959D
:2002A000D1F730931801209317013FC0203080E0380780E4480780E0580758F483E08093AD
:2002C000190166E056954795379527956A95D1F7E8CF203080E0380780E0480781E0580793
:2002E00040F484E080931901BB27A52F942F832F18C0203080E0380780E0480784E05807D5
:2003000058F485E0809319018AE056954795379527958A95D1F7C5CF85E0809319018FEFBB
:200320009FEF90931801809317018091170190911801909387008093860080911901806116
:20034000809381001F910F91FF90EF9008950F931F930BEA11E0C80140E052EC61E070E01C
(...)

(je vous fais grâce des +1000 lignes restantes)

Au contraire, si le fichier ne contenait que des FF (mémoire vide) ont aurait eu ce genre de chose :
(...)
:207A0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF86
:207A2000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF66
:207A4000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF46
:207A6000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF26
:207A8000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF06
:207AA000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE6
:207AC000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC6
:207AE000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA6
(...)

(si vous obtenez que des FF ou 00, c’est que le bootloader est verrouillé, chose qui ne devrait pas arriver avec Optiboot, mais on ne sait jamais)

IMPORTANT TOUJOURS faire DEUX lectures de la mémoire, dans DEUX fichiers séparés, puis comparer si ceux-ci sont identiques (checksum, diff, comme vous voulez) et non vides.
Si les deux fichiers sont identiques : c’est bon vous avez votre sauvegarde.
S’ils sont différents : attention danger, quelque chose cloche. Vous n’avez surement pas le vrai contenu de la mémoire dans le fichier (erreur de communication, mémoire défectueuse, bootloader modifié, il peut y avoir plein de raison à cela).

OK. J’ai ma sauvegarde, je fais comment pour la restaurer ?

C’est simple, la commande est la même, seul le :r: de la commande -U change pour devenir :w: (write = écriture).
Avrdude lancera alors l’effacement de la mémoire, l’écriture des données, puis la relecture complète de la mémoire pour vérification.

Remarque : cela supprimera TOUTES les informations contenues dans la mémoire flash pour restaurer celles du fichier de sauvegarde.
Cela ne modifiera pas cependant les informations contenues dans la mémoire EEPROM (mémoire de données utilisateurs).
Avrdude supporte le mode « eeprom » au lieu de « flash » pour la commande -U, mais par défaut Optiboot (sauf sur les cartes Mega) ne supporte pas ce mode.

Discussion

12 réflexions sur “[Arduino] Sauvegarder le programme d’une carte Arduino (ou compatible)

  1. Salut Fabien,
    Toujours aussi efficaces 😉

    Publié par Icare Petibles | 14 février 2015, 13 h 36 min
  2. Re,
    Pour la partie conversion du fichier .hex, il reste la solution de passer par un « décompilateur »
    A partir d’un source en assembleur, il sera toujours possible de retravailler ou adapter le code.
    Même si la tâche n’est pas évidente.
    @+

    Publié par Icare Petibles | 14 février 2015, 14 h 02 min
    • Même avec le code assembleur, comprendre son fonctionnement peut prendre des mois, voir des années selon la complexité du code.

      Publié par Skywodd | 14 février 2015, 14 h 07 min
      • heu, ça dépend fortement hein, on est d’accord 🙂

        Publié par f4grx | 16 février 2015, 11 h 18 min
      • ^commentaire au dessus a supprimer… Ca dépend, mais si t’arrives a obfusquer un code (genre arduino) pour qu’il résiste des années, on t’embauche sur le champ 😀

        Publié par f4grx | 16 février 2015, 11 h 21 min
    • La décompilation marche généralement très mal, sauf pour le java ou .net, et en plus elle n’est pas toujours nécessaire.

      Ce qui est plus en commun c’est le désassemblage, qui est la traduction du hex en code source asm.

      Publié par f4grx | 16 février 2015, 11 h 19 min
  3. Est-ce que Atmel JTAG ICE mkII est réellement compatible avec AVRDUDE comme cela est indiqué sur le site de référence http://www.nongnu.org/avrdude/ ?
    Il me semble que depuis que j’ai installé des versions d’Atmel Studio récentes et le driver « Jungo », rien ne va plus!

    Publié par jmparatte | 14 février 2015, 19 h 51 min
  4. Merci d’avoir dit « chiffrement » et non pas « cryptage »…

    Sinon merci pour le tuto, ça me fait un site de référence facile à trouver pour quand j’en aurai besoin 🙂

    Publié par f4grx | 16 février 2015, 10 h 32 min
  5. Bonjour, merci pour ce magnifique tuto, pour Linux, on fait comment ? J’ai pas mal de messages d’erreur quand je lance avrdude -v

    Publié par F4FXO | 18 janvier 2017, 10 h 55 min

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

Skyduino devient Carnet du Maker

Le site Carnet du Maker remplace désormais le blog Skyduino pour tout ce qui touche à l'Arduino, l'informatique et au DIY.