En ccs puedes cargar en una variable de entorno los valores de write_size y de erase_size de tu micro de la siguiente forma:
#define ERASE_SIZE getenv("FLASH_ERASE_SIZE")
#define WRITE_SIZE getenv("FLASH_WRITE_SIZE")
Con eso ya conoces el tamaño del bloque de escritura y además conoces el tamaño del bloque que se va a borrar de la flash cada vez que escribas si elijes una dirección múltiplo de WRITE SIZE.
Por ejemplo, en mi caso, un 18f26k20 tiene un Write_size de 32 bytes y un erase_size de 64 bytes, eso significa que si yo elijo la dirección de memoria 0 y empiezo a escribir un bloque de 32 bytes desde ahí, lo primero que sucede es que la función borra automáticamente un bloque erase_size, que en mi caso serían 64 bytes y luego graba los 32 bytes del bloque dejando entonces 32 grabados y 64 eliminados.
si elijo la posición 32 para grabar a partir de ahí se van a grabar 8 bytes (del 32 al 39) ambos inclusives, y se borra "erase_size" (64 en mi caso), es decir, los bytes del 32 al 39 contendrá los nuevos datos, y del 40 al 95 inclusive serán limpiados
Ahora, si elijo una dirección fuera de write_size, por ejemplo, addres = 3, se escriben los bytes PERO NO se borra nada por que no es una dirección multiplo de Write_Size.
Puede ser un poco lioso pero es fácil de entender.
Ahora usas la función:
write_program_memory(addr, data, count);
Donde addr es la dirección donde vas a empezar a escribir,
"data" es un puntero a un array o a un solo byte que contiene el/los dato/s que quieres grabar en la flash
y "count" es un entero de 8 bits para los pic 16, o de 16 bits para los pic18, y es el numero de bytes que quieres grabar.
por ejemplo, si escribes:
write_program_memory(64, data, 5); //Como 64 es multiplo de Write_size se borra un bloque erase_size que en mi caso son 64 bytes, desde la posicion 64 a la 128 se borra todo su contenido, y ahora se graban los 5 primeros bytes del array "data" en los 5 primeros bytes del bloque direccionado, es decir, las posiciones 64,65,66,y 67 serán grabadas y el resto hasta 128 se habrán puesto a 0xFF.
Si escribo:
write_program_memory(65,data,20); // se graban los primeros 20 bytes del array "data" en los 20 bytes siguientes a la addres elegida, en este caso 65,66,67,68...........84. Pero el resto del bloque queda sin eliminar por que 65 no es multiplo de Write_size
Grabar en direcciones fuera de multiplo es algo que hay que asegurarse bien de lo que se está haciendo por que el resto del bloque queda ahí grabado y si por ejemplo es un bootloader esto sería catastrófico y hay que tener en cuenta y controlar cuando la funcion borra el bloque erase_size y cuando no lo hace y lo tenemos que hacer manualmente...
Es un poco liosa de usar esta función en CCS por eso a mucha gente no le funciona.
Saludos.