Actualmente tengo un número de serie codificado en mi firmware para un diseño con el que estoy trabajando. El firmware puede leer e informar el número de serie. Eso funciona bien para lo que necesito. El problema es que cada nuevo número de serie requiere que cambie mi código y vuelva a compilar. Esto es engorroso cuando hay muchas unidades para construir, tiene la posibilidad de introducir errores y es una mala práctica en general. Me dan los números de serie y el diseño del hardware es inamovible, por lo que no puedo agregar ninguna función en el hardware para serializar las unidades (EEPROM/Silicon ID Chip/Pull-Ups). Lo que me gustaría hacer es ubicar el número de serie en una dirección fija, compilar el código una vez y luego editar esa dirección en el archivo HEX compilado para cada nuevo número de serie. Se hace referencia al número en varios lugares, por lo que, idealmente, quiero definirlo y ubicarlo una vez, luego haga referencia a esa "variable" en cualquier otro lugar de mi código. ¿Alguien sabe cómo ubicar datos constantes en una ubicación de memoria direccionable específica de mi elección, usando el Compilador C18? ¿Hay una mejor manera que alguien pueda sugerir?
Específicamente para resolver la cuestión de vincular variables a direcciones específicas en la memoria flash en el PIC18 con el compilador C18, consulte la sección "Pragmas" en hlpC18ug.chm en el directorio doc donde está instalado el compilador.
Para hacer esto, debe definir una nueva "sección" en la memoria y vincularla a una dirección de inicio para que
#pragma romdata serial_no_section=0x1700
Esto crea una nueva sección llamada "serial_no_section" que comienza en la dirección 0x1700 en la memoria flash (programa) (porque definimos "romdata" en el #pragma).
Directamente después de la línea #pragma, define tu(s) variable(s) así:
#pragma romdata serial_no_section=0x1700
const rom int mySerialNumber = 0x1234;
#pragma romdata
Ahora tiene 0x12 en la dirección 0x1700 y 0x34 en la dirección 0x1701 en la memoria (porque PIC18 usa el modelo little-endian). La "rom const" garantiza que el compilador sepa que se trata de un tipo de variable const y que la variable se encuentra en la memoria "rom" y, por lo tanto, debe accederse a ella a través de instrucciones de lectura de tabla.
La #pragma romdata
declaración final asegura que las siguientes declaraciones de variables estén vinculadas a las secciones de memoria predeterminadas, ya que el vinculador considera que encaja en lugar de continuar en la sección "serial_no_section".
Ahora todo el código puede simplemente hacer referencia a la variable "mySerialNumber", y sabrá exactamente en qué dirección se puede encontrar el número de serie en la memoria.
Editar el código HEX puede ser un poco desafiante ya que necesita calcular la suma de verificación para cada línea que edite. Estoy trabajando en una clase de C++ para decodificar y codificar archivos HEX de Intel, lo que debería facilitarlo, pero aún no está terminado. La decodificación de archivos funciona, la codificación nuevamente aún no está implementada. El proyecto (si está interesado) está aquí https://github.com/codinghead/Intel-HEX-Class
Espero que esto ayude
He hecho el número de serie (s/n para abreviar) de una manera similar a lo que describe Joel. Estaba usando el compilador PIC18F4620 y CCS. La ubicación de s/n en la memoria Flash fue forzada a los últimos 4 bytes. Como estaba usando solo el 80% de Flash, mi compilador y enlazador no escribían código ejecutable en los últimos 4 bytes.
Luego tuve 2 formas alternativas para escribir s/n en unidades individuales:
Responder al comentario de Joel
No sé sobre C18, pero el compilador CCS viene con funciones de biblioteca write_program_eeprom(...)
y read_program_eeprom(...)
. Así es como se ven en el ensamblaje.
................... escribir_programa_eeprom(i_ADDR, iWord); EF84: BSFFD0.6 EF86: CLRF FF8 EF88: MOVLW 7F EF8A: MOVWF FF7 EF8C: MOVIL F0 EF8E: MOVWF FF6 EF90: MOVLB 0 EF92: SUJETADOR EF24 EF94: MOVIL F0 EF96: MOVWF FF6 EF98: MOVFF 490, FF5 EF9C: TBLWT*+ EF9E: MOVFF 491, FF5 EFA2: TBLWT* EFA4: FBC FA6.6 EFA6: BSF FA6.4 EFA8: LLAMADA EF3C EFAA: RCALL EF3C EFAC: CLRF FF8 EFAE: CLRF FF8
..................... iPalabra = read_program_eeprom(i_ADDR); EF60: CLRF FF8 EF62: MOVLW 7F EF64: MOVWF FF7 EF66: MOV LW 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
write_program_eeprom(...)
y read_program_eeprom(...)
. ¡La EEPROM y Flash son dos cosas diferentes!He hecho esto un par de veces. Por lo general, defino un área de información de firmware en una ubicación fija en la memoria del programa, luego escribo un programa que crea un archivo HEX serializado a partir del archivo HEX de plantilla. Todas estas son cosas fáciles de hacer.
En producción, ejecuta el programa de serialización una vez que han pasado todas las pruebas. Crea el archivo HEX temporal con el número de serie único, que se programa en el PIC, luego se elimina el archivo HEX temporal.
No dejaría que la ubicación fuera reubicable, luego tendría que encontrarla. Eso puede cambiar cada compilación a medida que el enlazador mueve las cosas. Lo he hecho para PIC muy pequeños como la serie 10F donde estas constantes son parte de las instrucciones MOVLW. En esos casos, hago que lea el archivo MAP sobre la marcha para determinar dónde están esas ubicaciones. Tengo un código de análisis de archivos MPLINK MAP en una biblioteca solo para ese propósito.
Para poner algo en una ubicación fija, defina un segmento en una dirección fija. El enlazador colocará dichos segmentos absolutos primero, luego los reubicables a su alrededor. No olvide usar CODE_PACK en lugar de solo CODE en un PIC 18, de lo contrario, tendrá que lidiar con palabras de instrucciones completas en lugar de bytes individuales. Por ejemplo (simplemente tecleado, no pase el ensamblador):
.fwinfo code_pack h'1000' ;área de información de firmware en una dirección conocida fija db h'FFFFFFFF' ;número de serie, rellenado por el programa de producción db fwtype; tipo ID de este firmware db fwver ;número de versión db fwseq ;número de secuencia de compilación
Sugeriría almacenar el número de serie en una dirección fija. Dependiendo de su compilador/enlazador y la parte en cuestión, hay algunos enfoques que podría tomar:
retlw
enfoque suele ser mucho más rápido (en los PIC de 18 bits, de aa call
tomará retlw
cuatro ciclos en total; usar clrf TBLPTRU/movlw xx/movwf TBLPTRH/movlw xx/movwf TBLPTRL/tblrd *+/movf TABLAT,w
tomaría ocho).Yo haría lo contrario: compilar y vincular el código, luego averiguar dónde se almacena el valor del archivo del vinculador. Es posible que deba ubicar la variable explícitamente en un segmento que está asignado a flash.
No pedí esto, pero el software de PC que proporciono para mi programador Wisp648 tiene la capacidad de leer un archivo .hex, modificar una ubicación específica y volver a escribir el archivo .hex (en el mismo archivo o en otro). No es necesario que mi programador esté presente. La fuente está disponible (en Python), la licencia permite todos los usos: www.voti.nl/xwisp Podría ser útil una vez que haya resuelto su problema principal.
crosley