5 votes

Éviter l'écrasement accidentel du micrologiciel

Tout d'abord, un peu de contexte. Quand un firmware se plante pour une raison quelconque (par exemple débordement de pile, pointeur de fonction corrompu...), il peut arriver qu'il saute quelque part et commence à exécuter du code. Ceci résultera tôt ou tard en une réinitialisation du chien de garde. Le MCU se réinitialisera et nous serons de nouveau sur la bonne voie. A moins que...

Qu'en est-il lorsque nous avons du code qui écrit sur la flash (par exemple le bootloader) ? Maintenant il peut arriver que l'on saute accidentellement directement dans le code d'écriture flash - sautant toutes les vérifications. Avant que le chien de garde n'aboie, vous vous retrouverez avec un firmware corrompu. C'est exactement ce qui m'est arrivé.

Maintenant, certains pourraient dire - fixer le bug de la racine qui a causé que nous avons même sauté dans le code d'écriture. Eh bien, lorsque vous développez, vous modifiez constamment le code. Même s'il n'y a pas de bogue à ce moment-là, il pourrait y en avoir un demain. De plus, aucun code n'est exempt de bogues - ou du moins pas le mien.

Alors maintenant, je fais une sorte de vérification croisée. J'ai une variable nommée "wen" que je fixe à 0xa5 avant les contrôles habituels (par exemple, vérifier que la destination est valide). Ensuite, juste avant de procéder à l'effacement ou à l'écriture, je vérifie que 'wen' est bien à 0xa5. Sinon, cela signifie que nous avons accidentellement sauté dans le code d'écriture. Après une écriture réussie, 'wen' est effacé. J'ai fait cela en C et cela a bien fonctionné. Mais il y a toujours une petite chance théorique qu'une corruption se produise, car il y a peu d'instructions entre cette vérification finale de 'wen' et l'écriture dans le registre SPMCR.

Maintenant je veux améliorer cela en mettant cette vérification dans l'assemblage, entre l'écriture à SPMCR et l'instruction spm.

__asm__ __volatile__
(   
    "lds __zero_reg__, %0\n\t"
    "out %1, %2\n\t"
    "ldi r25, %3\n\t"
    "add __zero_reg__, r25\n\t"
    "brne spm_fail\n\t"
    "spm\n\t"
    "rjmp spm_done\n\t"
    "spm_fail: clr __zero_reg__\n\t"
    "call __assert\n\t"
    "spm_done:"
    :
    : "i" ((uint16_t)(&wen)),
      "I" (_SFR_IO_ADDR(__SPM_REG)),
      "r" ((uint8_t)(__BOOT_PAGE_ERASE)),
      "M" ((uint8_t)(-ACK)),
      "z" ((uint16_t)(adr))
   : "r25"
);

Je n'ai pas encore essayé le code, je le ferai demain. Voyez-vous des problèmes ? Comment faites-vous/feriez vous pour résoudre ces problèmes ?

3voto

tomlogic Points 5044

Une technique que j'ai vue consiste à s'assurer que les octets précédant immédiatement vos routines d'écriture flash déclencheront une sorte de délai de surveillance, ou réinitialiseront le processeur. De cette façon, il n'est pas possible d'exécuter des données aléatoires avant la fonction d'écriture flash et de simplement "tomber" dans la fonction.

Il se peut que vous ayez besoin de quelques NOP avant votre réinitialisation pour vous assurer que les instructions sont interprétées correctement.

Votre technique consistant à vérifier que la fonction s'est exécutée depuis le début semble bonne, en supposant que vous effacez le fichier wen une fois que vous avez effectué l'écriture.

2voto

AShelly Points 17389

Je ne sais pas pourquoi vous devez avoir la capacité d'écrire sur la mémoire flash dans votre chargeur de démarrage. Notre chargeur de démarrage le fait, car il peut mettre à jour le programme d'application via le port série. Nous éliminons donc le potentiel d'écriture par inadvertance en nous assurant que le chargeur ne contient aucun des codes qui écrivent sur la mémoire flash. Ce code est téléchargé dans un en-tête dans le même paquet qui contient l'image à écrire. L'image embarquée a la somme de contrôle de l'algo de programmation stockée, et la vérifie avant de l'exécuter.

Si vous écrivez des choses qui sont générées en interne, alors je regarderais les interlocks liés au matériel. N'autorisez l'écriture que si vous avez préalablement mis une broche de sortie discrète particulière sur ON. Pour répondre au problème "que se passe-t-il si l'IP saute les contrôles" ? vous pouvez le faire en 2 parties. D'abord, définissez certaines variables critiques pour l'algorithme. (l'adresse à laquelle écrire par exemple - gardez-la initialisée à la mémoire invalide, et ne la définissez correctement que dans un appel séparé fait avant l'écriture. Ensuite, la fonction d'écriture vérifie votre interlock HW. Faites l'une des étapes d'activation dans une interruption, ou en réponse à un timer, quelque chose qui a peu de chances d'être atteint dans la séquence correcte si vous avez une IP rebelle.

Si votre IP peut vraiment sauter n'importe où, il peut être impossible d'empêcher une écriture par inadvertance. Le mieux que vous puissiez espérer est que vous vous assuriez que le seul chemin pour y parvenir mette en place tout ce qui est nécessaire pour une écriture réussie.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X