Esto de la escritura en flash eeprom requiere de atención y cuidado.
Cuando se usa write_program_eeprom() por primera vez al recién grabar el pic, el dato se guarda correctamente, pero la segunda vez ya no. Como comentó Bafan, es necesario borrar la flash eeprom para volverla a grabar.
Para eso existe erase_program_eeprom() pero tiene la peculiaridad de que no borra una sola localidad, borra todo un bloque. Este bloque depende del modelo de pic que se esté usando. Puede ser de 64 bytes por ejemplo. Así que si queremos grabar un sólo byte hay que respaldar todos los demás que deben quedar intactos y luego borrarlos. Una vez borrados se graba el byte nuevo y los bytes viejos todo un bloque.
Lo ideal es usar write_program_memory() ya que borra y graba bloques en una sola instrucción. También es recomendable grabar datos con tamaño idéntico a un bloque.
La dirección en la que comienza el bloque debe ser múltiplo del tamaño del bloque. Por ejemplo, si el bloque mide 64 bytes, no es recomendable iniciar una grabación en 0x3F (63), es mejor iniciar en 0x40 (64).
En sí, esto es un resumen de lo que la ayuda de CCS explica. Existen varios temas al respecto en el foro y todo esto es una síntesis de ellos.
The flash program memory is readable and writable in some chips and is just readable in some. These options lets the user read and write to the flash program memory. These functions are only available in flash chips.
Relevant Functions:
read_program_eeprom
(address)
Reads the program memory location(16 bit or 32 bit depending on the device).
write_program_eeprom
(address, value)
Writes value to program memory location address.
erase_program_eeprom
(address)
Erases FLASH_ERASE_SIZE bytes in program memory.
write_program_memory
address,dataptr,count)
Writes count bytes to program memory from dataptr to address. When address is a mutiple of FLASH_ERASE_SIZE an erase is also performed.
read_program_memory
(address,dataptr,count)
Read count bytes from program memory at address to dataptr.
Relevant Preprocessor:
#ROM address={list}
Can be used to put program memory data into the hex file.
#DEVICE(WRITE_EEPROM=ASYNC)
Can be used with #DEVICE to prevent the write function from hanging. When this is used make sure the eeprom is not written both inside and outside the ISR.
Relevant Interrupts:
INT_EEPROM
Interrupt fires when eeprom write is complete.
Relevant Include Files:
None, all functions built-in
Relevant getenv() parameters
PROGRAM_MEMORY
Size of program memory
READ_PROGRAM
Returns 1 if program memory can be read
FLASH_WRITE_SIZE
Smallest number of bytes written in flash
FLASH_ERASE_SIZE
Smallest number of bytes erased in flash
Example Code:
For 18F452 where the write size is 8 bytes and erase size is 64 bytes
#rom 0xa00={1,2,3,4,5}
//inserts this data into the hex file.
erase_program_eeprom(0x1000);
//erases 64 bytes strting at 0x1000
write_program_eeprom(0x1000,0x1234);
//writes 0x1234 to 0x1000
value=read_program_eeprom(0x1000);
//reads 0x1000 returns 0x1234
write_program_memory(0x1000,data,8);
//erases 64 bytes starting at 0x1000 as 0x1000 is a multiple
//of 64 and writes 8 bytes from data to 0x1000
read_program_memory(0x1000,value,8);
//reads 8 bytes to value from 0x1000
erase_program_eeprom(0x1000);
//erases 64 bytes starting at 0x1000
write_program_memory(0x1010,data,8);
//writes 8 bytes from data to 0x1000
read_program_memory(0x1000,value,8);
//reads 8 bytes to value from 0x1000
For chips where getenv("FLASH_ERASE_SIZE") > getenv("FLASH_WRITE_SIZE")
WRITE_PROGRAM_EEPROM -
Writes 2 bytes,does not erase (use ERASE_PROGRAM_EEPROM)
WRITE_PROGRAM_MEMORY -
Writes any number of bytes,will erase a block whenever the first (lowest) byte in a block is written to. If the first address is not the start of a block that block is not erased.
ERASE_PROGRAM_EEPROM -
Will erase a block. The lowest address bits are not used.
For chips where getenv("FLASH_ERASE_SIZE") = getenv("FLASH_WRITE_SIZE")
WRITE_PROGRAM_EEPROM -
Writes 2 bytes, no erase is needed.
WRITE_PROGRAM_MEMORY -
Writes any number of bytes, bytes outside the range of the write block are not changed. No erase is needed.
ERASE_PROGRAM_EEPROM -
Not available.