Numéro de série PIC modifiable dans le fichier HEX

8

Actuellement, j'ai un numéro de série codé en dur dans mon firmware pour une conception avec laquelle je travaille. Le micrologiciel peut lire et signaler le numéro de série. Cela fonctionne bien pour ce dont j'ai besoin. Le problème est que chaque nouveau numéro de série me demande de changer mon code et de recompiler. C'est lourd quand il y a beaucoup d'unités à construire, peut éventuellement introduire des erreurs et c'est une mauvaise pratique générale. Les numéros de série m'ont été donnés et la conception matérielle est gravée dans le marbre, donc je ne peux pas ajouter de fonctionnalités matérielles pour sérialiser les unités (EEPROM / puce ID silicone / Pull-Ups). Ce que je voudrais faire, c'est localiser le numéro de série à une adresse fixe, compiler le code une fois, puis modifier cette adresse dans le fichier HEX compilé pour chaque nouveau numéro de série. Le numéro est référencé à plusieurs endroits, donc idéalement, je veux le définir et le localiser une fois, puis référencez cette "variable" partout ailleurs dans mon code. Quelqu'un sait-il comment localiser des données constantes à un emplacement de mémoire adressable spécifique de mon choix, à l'aide du compilateur C18? Y a-t-il une meilleure façon de suggérer?

Joel B
la source
1
Environ la moitié des PIC18 ont entre 128 octets et 1K d'EEPROM intégrés. Je suppose que d'après votre question, votre PIC18 fait partie des 50% qui n'ont pas d'EEPROM?
tcrosley

Réponses:

4

Spécifiquement pour résoudre la question de la liaison des variables à des adresses spécifiques dans la mémoire flash sur le PIC18 avec le compilateur C18, veuillez référencer la section "Pragmas" dans hlpC18ug.chm dans le répertoire doc où le compilateur est installé.

Pour ce faire, vous devez définir une nouvelle "section" en mémoire et la lier à une adresse de début afin

#pragma romdata serial_no_section=0x1700

Cela crée une nouvelle section appelée "serial_no_section" qui commence à l'adresse 0x1700 dans la mémoire flash (programme) (car nous avons défini "romdata" dans le #pragma).

Directement après la ligne #pragma, définissez vos variables de la manière suivante:

#pragma romdata serial_no_section=0x1700
const rom int mySerialNumber = 0x1234;
#pragma romdata

Vous avez maintenant 0x12 à l'adresse 0x1700 et 0x34 à l'adresse 0x1701 en mémoire (car PIC18 utilise le modèle little-endian). Le "const rom" garantit que le compilateur sait qu'il s'agit d'un type de variable const, et que la variable se trouve dans la mémoire "rom" et doit donc être accessible via des instructions de lecture de table.

L' #pragma romdatainstruction finale garantit que toutes les déclarations de variables suivantes sont liées aux sections de mémoire par défaut comme l'éditeur de liens voit les ajustements plutôt que de suivre dans la section "serial_no_section".

Désormais, tout le code peut simplement référencer la variable "mySerialNumber", et vous savez exactement à quelle adresse le numéro de série se trouve en mémoire.

La modification du code HEX peut être un peu difficile car vous devez calculer la somme de contrôle pour chaque ligne que vous modifiez. Je travaille sur une classe C ++ pour décoder et encoder les fichiers Intel HEX, ce qui devrait faciliter les choses, mais ce n'est pas encore terminé. Le décodage des fichiers fonctionne, le codage n'est pas encore implémenté. Le projet (si vous êtes intéressé) est ici https://github.com/codinghead/Intel-HEX-Class

J'espère que cela t'aides

Stuart Cording
la source
4

J'ai fait le numéro de série (s / n pour faire court) d'une manière similaire à ce que Joel décrit. J'utilisais PIC18F4620 et le compilateur CCS. L'emplacement de s / n dans la mémoire Flash a été forcé sur les 4 derniers octets. Étant donné que j'utilisais seulement 80% de Flash, mon compilateur et l'éditeur de liens n'écriraient pas de code exécutable dans les 4 derniers octets.

Ensuite, j'ai eu 2 façons alternatives d'écrire réellement s / n dans des unités individuelles:

  • Le débogueur en circuit CCS (ICD) avait une fonctionnalité qui permettait de manipuler n'importe quel emplacement à l'intérieur de Flash. C'était un hack utile. Dans des révisions ultérieures, ils l'ont malheureusement supprimé.
  • PIC avait une liaison série avec un PC. s / n a été téléchargé à travers elle. Le micrologiciel avait une routine qui recevrait le s / n et le stockait dans Flash.

Répondre au commentaire de Joel

Je ne sais pas pour C18, mais le compilateur CCS est livré avec les fonctions de bibliothèque write_program_eeprom(...)et read_program_eeprom(...). Voici à quoi ils ressemblent en assemblage.

.................... write_program_eeprom (i_ADDR, iWord);
EF84: BSF FD0.6
EF86: CLRF FF8
EF88: MOVLW 7F
EF8A: MOVWF FF7
EF8C: MOVLW F0
EF8E: MOVWF FF6
EF90: MOVLB 0
EF92: BRA EF24
EF94: MOVLW F0
EF96: MOVWF FF6
EF98: MOVFF 490, FF5
EF9C: TBLWT * +
EF9E: MOVFF 491, FF5
EFA2: TBLWT *
EFA4: BCF FA6.6
EFA6: BSF FA6.4
EFA8: RCALL EF3C
EFAA: RCALL EF3C
EFAC: CLRF FF8
EFAE: CLRF FF8
.................... iWord = read_program_eeprom (i_ADDR); 
EF60: CLRF FF8
EF62: MOVLW 7F
EF64: MOVWF FF7
EF66: MOVLW F0
EF68: MOVWF FF6
EF6A: TBLRD * +
EF6C: MOVF FF5, W
EF6E: TBLRD *
EF70: MOVFF FF5,03
EF74: CLRF FF8
EF76: MOVLB 4
EF78: MOVWF x90
EF7A: MOVFF 03,491
Nick Alexeev
la source
1
Oui, c'est exactement ce que je demande! Pouvez-vous décrire les attributs de code que vous avez utilisés pour compresser votre S / N dans les derniers octets de Flash?
Joel B
"Le micrologiciel avait une routine qui recevrait le s / n et le stockerait dans Flash" write_program_eeprom(...)et read_program_eeprom(...). L'EEPROM et le Flash sont deux choses différentes!
m.Alin
@ m.Alin C'est ainsi que les fonctions "en conserve" fournies avec CCS ccompiler ont été appelées. En fait, ils écrivaient et lisaient Flash.
Nick Alexeev
2

Je l'ai fait plusieurs fois. Habituellement, je définis une zone d'informations sur le firmware dans un emplacement fixe dans la mémoire du programme, puis j'écris un programme qui crée un fichier HEX sérialisé à partir du fichier HEX modèle. Ce sont toutes des choses faciles à faire.

En production, vous exécutez le programme de sérialisation une fois que tous les tests ont réussi. Il crée le fichier HEX temporaire avec le numéro de série unique, qui est programmé dans le PIC, puis le fichier HEX temporaire est supprimé.

Je ne laisserais pas l'emplacement être déplaçable, alors je devrais le trouver. Cela peut changer chaque version à mesure que l'éditeur de liens déplace les choses. Je l'ai fait pour de très petits PIC comme la série 10F où ces constantes font partie des instructions MOVLW. Dans ces cas, je le fais lire le fichier MAP à la volée pour déterminer où se trouvent ces emplacements. J'ai du code d'analyse de fichier MPLINK MAP dans une bibliothèque juste à cet effet.

Pour placer quelque chose dans un emplacement fixe, définissez un segment à une adresse fixe. L'éditeur de liens place d'abord ces segments absolus, puis ceux qui peuvent être déplacés autour de lui. N'oubliez pas d'utiliser CODE_PACK au lieu de simplement CODE sur un PIC 18, sinon vous aurez affaire à des mots d'instuction entiers au lieu d'octets individuels. Par exemple (juste tapé, pas passé devant l'assembleur):

.fwinfo code_pack h'1000 '; zone d'informations sur le firmware à l'adresse connue fixe
         db h'FFFFFFFF '; numéro de série, renseigné par programme de production
         db fwtype; ID de type de ce firmware
         db fwver; numéro de version
         db fwseq; numéro de séquence de génération
Olin Lathrop
la source
2

Je suggère de stocker le numéro de série dans une adresse fixe. Selon votre compilateur / éditeur de liens et la partie en question, vous pouvez adopter quelques approches:

  1. Définissez une section déplaçable qui contiendra le numéro de série, utilisez une directive #pragma dans votre code pour forcer le numéro de série dans cette section et forcez l'adresse de cette section dans la spécification de lien.
  2. Pour les parties qui peuvent lire directement la mémoire de code, excluez une zone de mémoire de la zone que l'éditeur de liens est autorisé à utiliser (c'est-à-dire que la partie est par exemple quatre octets plus petite qu'elle ne l'est réellement), puis lisez le numéro de série dans le code en utilisant quelque chose comme `((const long non signé *) 0x3FFC)`.
  3. Pour les parties qui ne peuvent pas lire directement la mémoire de code, vous pourrez peut-être mettre des instructions «RETLW» à une adresse fixe, puis convaincre l'éditeur de liens qu'il existe des fonctions appelables qui renvoient «octet» à ces adresses. Ensuite, on dirait par exemple "out_hex (ser_byte0 ()); out_hex (ser_byte1 ()); out_hex (ser_byte2 ()); pour sortir les octets du numéro de série.
supercat
la source
Tous les PIC 18F peuvent lire leur mémoire de programme via le mécanisme de lecture de table.
Olin Lathrop
C'est vrai. Certaines parties 14 bits sont également capables de lire la mémoire du programme. Cependant, même sur les PIC qui peuvent lire la mémoire du programme, l' retlwapproche est souvent beaucoup plus rapide (sur les PIC de 18 bits, a callà a retlwprendra quatre cycles au total; l'utilisation en clrf TBLPTRU/movlw xx/movwf TBLPTRH/movlw xx/movwf TBLPTRL/tblrd *+/movf TABLAT,wprendrait huit).
supercat
1

Je ferais le contraire: compiler et lier le code, puis savoir où la valeur est stockée à partir du fichier de l'éditeur de liens. Vous devrez peut-être localiser la variable explicitement dans un segment mappé sur flash.

Je n'ai pas demandé cela, mais le logiciel PC que je fournis pour mon programmeur Wisp648 a la capacité de lire un fichier .hex, de modifier un emplacement spécifique et de réécrire le fichier .hex (dans le même fichier ou dans un autre fichier). Pas besoin d'avoir mon programmeur présent. La source est disponible (en Python), la licence permet toute utilisation: www.voti.nl/xwisp Peut être utile une fois que vous avez résolu votre problème principal.

Wouter van Ooijen
la source
Merci @Wouter van Ooijen! J'essaie d'éviter l'approche "savoir où la valeur est stockée", car cela signifie très probablement que la valeur est déplacée sur des compilations successives et m'oblige (ou un triste camarade qui vient derrière moi) pour savoir où la valeur est situé à nouveau, introduisant assurément des problèmes.
Joel B