Predefinición de valores de EEPROM en el compilador XC8

Estoy trabajando con un PIC16F690, usando el compilador XC8 de Microchip. Quiero incrustar valores de EEPROM en el archivo hexadecimal, de modo que la EEPROM se programe al mismo tiempo que la memoria del programa.

He hecho esto en el pasado con el compilador C18 (era para un PIC18, no para este PIC16), de la siguiente manera:

#pragma romdata eedata_scn=0xf00000
    rom unsigned char my_eeprom_values[256] = {0, 4, 2, 1, (and so on), 3};
#pragma romdata

La EEPROM no está realmente en ese espacio de memoria (0xf00000), pero es cómo C18 accede a ella. Puede obtener esta dirección buscando en el script del enlazador:

CODEPAGE NAME=eedata START=0xF00000 END=0xF000FF PROTECTED

De todos modos, esto no funciona en XC8. Hay otra declaración que es similar:

__EEPROM_DATA (0,1,2,3,3,2,1,0);

Pero esta declaración solo puede tomar ocho argumentos, y no puede darle una ubicación de inicio en EEPROM, por lo que sé. Entonces, su código termina con 32 de estas declaraciones (para 256 bytes de EEPROM), lo que parece difícil de manejar.

Además, el Manual del usuario de XC8 dice que esta declaración no está implementada para PIC18. Esto no me afecta ahora, ¡pero lo hará en el futuro!

¿Hay una mejor manera de hacer esto en XC8?


Editar:

Abrí un ticket de soporte con Microchip e hice esta pregunta. Resulta que la macro __EEPROM_DATA es la única forma que recomiendan para inicializar los valores de EEPROM.

En el lado bueno, esta macro, de hecho, funciona para todos los dispositivos PIC18 con EEPROM interna. Mi malentendido provino de esta declaración en el Manual del usuario :

2.5.9.4 ADVERTENCIAS MPLAB XC8 no implementa los calificadores __eeprom para ningún dispositivo PIC18; este calificador funciona como se esperaba para otros dispositivos de 8 bits.

Sin embargo, la macro __EEPROM_DATA sí funciona. Lo acabo de probar con éxito.

Aun así, esto sigue siendo difícil de manejar. ¿Existe alguna solución alternativa que permita la inicialización de una ubicación específica de EEPROM, sin comenzar desde el principio?

Gracias de nuevo.

Respuestas (2)

Para probar todo a continuación, utilicé MPLAB 8.76, compilador XC8 ver 1.30:

Primero, una digresión/consejo: si ha cambiado a PIC16F690 recientemente: ~ Hace 6 semanas decidí abandonar este chip, excepto para proyectos realmente pequeños. Tiene poco FLASH, poca RAM y solo 256 EEPROM. Y no puede depurarlo fácilmente en un objetivo real. Ahora uso 18FK4620: tiene 16 veces más FLASH (64kB), 4 veces más EEPROM (1kB) y casi 16 veces más RAM (~ 4kB), puede funcionar hasta a 64MHz Fosc (!), además de más puertos, etc.

Y lo MÁS IMPORTANTE: puede DEPURAR 18F46K20 usando PICKIT2 estándar y MPLAB 8.76 ... 8.91 (todavía no uso MPLAB X, ya que escuché muchas malas historias al respecto). Y no necesita ninguna placa de interfaz adicional, etc. Solo su placa de destino --> PICKIT2 (es decir, no tiene que cambiar a un contratiempo PICKIT3)

Y el precio es muy similar: 18F46K20 cuesta ~ $ 2,90 y 16F690 cuesta ~ $ 2,40 al por menor.

AHORA SOLUCIONES PARA USTED:

---------------------- Solución 1a: use algo como esto (y cambie '20' al tamaño de matriz que desee):

__eeprom unsigned char my_eeprom_values[20] =  
        {   0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20,
            0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30};**

Pero si usa lo anterior, entonces NO sabe dónde el compilador los colocará en EEPROM. (Tenga en cuenta que el calificador __eeprom es ignorado por el compilador XC8 para muchos dispositivos PIC18Fxxx)

---------------------- Solución 1b:

const unsigned char abc1 @ 0x2100 = 0x11; // @ EEPROM addr = 0
    // ......
    const unsigned char abc2 @ 0x2110 = 0x22; // @ EEPROM addr = 17**

Tenga en cuenta que parece que la EEPROM en 16F690 comienza en addr. 0x2100 (no 0xF00000 como mencionaste). Revisé el archivo .map después de la compilación. También verifiqué el resultado de lo anterior después de compilar el código y luego vi la EEPROM usando PICKIT2 (o si depura en MPLAB usando MPLAB SIM, luego de compilar el código, vaya a Menú -> VER -> EEPROM). Verá todos los datos allí como desee.

---------------------- Solución 1c:

Puede mezclar (1a) y (1b) arriba, puede usar 'int' en lugar de 'char', pero: - tenga en cuenta que debido a que __EEPROM_DATA no permite especificar la dirección eerpom, una declaración sobrescribirá algunas de las otras . Para ilustrar esto, coloqué 0x99 en lugares que SERÍAN sobrescritos. XC8 advierte sobre esto de todos modos: vea el final de mi publicación. - Endian que XC8 usa 'intercambios' bytes DE tipo 'int': los datos 'abc' a continuación se almacenarán como: 22114433, en lugar de 11223344.

---------------------- EJEMPLO:

Aquí hay un ejemplo probado para 16F690 bajo XC8 ver 1.30:

    const unsigned int abc1 @ 0x2100 = 0x1122;
    const unsigned int abc2 @ 0x2102 = 0x3344;
  __EEPROM_DATA(0x99, 0x99, 0x99, 0x99, 5, 6, 7, 8);
    const unsigned int abc3 @ 0x2108 = 0x5566;
    __EEPROM_DATA(0x99, 0x99, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88);
    __eeprom unsigned char my_eeprom_values[20] = \ 
    {   0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x20,
        0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x30};

El CONTENIDO EEPROM resultante es este:

22 11 44 33 05 06 07 08 66 55 83 84 85 86 87 88
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
27 28 29 30 FF FF FF FF FF FF FF FF FF FF FF FF
FF FF FF FF FF ...

Entonces 0x(22 11 44 ​​33) ha sobrescrito 4 x 0x99. Lo mismo con 0x(66 55). Pero tenga en cuenta que el resto es solo una copia simple de datos en código C.

---------------------- Solución 2: 'yours': Tal como usted dijo, coloque tantas declaraciones __EEPROM_DATA de '8 bytes' como necesite. ¿Qué tiene de malo esto? Es simple y funciona siempre. El compilador coloca los datos en el orden en que los tendrá en su código C. Si necesita que algunos bytes no cambien, coloque 0xFF para ellos. P.ej.

__EEPROM_DATA(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF);  // addr: 0x00 ... 0x07 
__EEPROM_DATA(0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88);  // addr: 0x08 ... 0x0F
__EEPROM_DATA(0x55, 0x66, 0x87, 0x65, 0xFF, 0xFF, 0xFF, 0xFF);  // addr: 0x10 ... 0x17 
etc.

Durante la compilación (1b/1c), el compilador XC8 da estas advertencias:

.... object "_abc1" lies outside available code space

... (1343) hexfile data at address 0x4200 (0x99) overwritten with 0x22 

pero obtuve los datos que quería en la EEPROM donde los quería, así que no me importa.

Resumen de memoria: Espacio de programa utilizado F00h (3840) de 1000h palabras (93,8%) Espacio de datos utilizado E4h (228) de 100h bytes (89,1%) Espacio de EEPROM utilizado 24h (36) de 100h bytes (14,1%) ...

-fin-

Después de mirar las sugerencias anteriores y algunas otras búsquedas, encontré la siguiente solución. Esto incluye las actualizaciones del compilador, por lo que estoy usando MPLABX 5.25 y XC8 v2.1. Usé el siguiente comando ya que eeprom para el PIC1846K80 está "ubicado" a partir de 0xF00000.

const uint8_t mi_variable __at(0xF0000C) = 0xA5; //0xF0000C para escribir en la ubicación 0xC

Lo anterior produjo el siguiente archivo hexadecimal con el siguiente fragmento. La primera línea indica que ahora se refiere a eeprom, la segunda línea enumera 1 byte en la memoria 0x0C de eeprom tiene 0xA5, la última línea indica el final del archivo.

:0200000400F00A // desplazamiento a la ubicación de la eeprom

:01000C00A54E // en la dirección eeprom 0x0C escribir 0xA5

:00000001FF // fin del archivo