PIC24FJ128GB204用 Flash Memory書き込みプログラム
PIC24FJ128にはEEPROMが無いので、設定値等を記憶しておくことが難しくなります。一つの解決策として任意のプログラムエリアの1ページをFlashメモリに割り当ててそのエリアをEEPROM代わりに使う方法があります。
作成したコードは次の通りです。
//--------------------------------------------
// フラッシュデータ書き込み
// unsigned int *values: 書き込みたいデータのポインター
// unsigned int head: 先頭から何ワード目か指定する
// unsigned int length:書き込みワード数
// ワード(BP0-BP23:有効、BP24-31:データ無効)
//--------------------------------------------
//0x1C00-0x2000までをFlashメモリに割り当てる。Hexファイルでは0x3800-0x4000
const __attribute__ ( (section("const_eeprom"), space (prog), address (0x1C00) ) ) unsigned int _flash_datas[512]; //※①
void Flash_Bulk_Write_With_Erase(unsigned int *values, unsigned int head, unsigned int length) {
unsigned int i=0;
unsigned int buffer[64];
unsigned int page = __builtin_tblpage(_flash_datas);
unsigned int offset = __builtin_tbloffset(_flash_datas);
// rescue to buffer(一時的な64ワードのバッファにの64ワードのデータを退避する)
TBLPAG = page;
for (i=0; i < 64; i++) {
buffer[i] = __builtin_tblrdl(offset + i*2);
}
// bulk over-write(引き渡されたデータをバッファにマージする)
for (i=0; i < length; i++) {
buffer[i + head] = values[i];
}
// Erase Page(1ページ消去する)
TBLPAG = page;
__builtin_tblwtl(offset, 0x0000); // this is important see reference.
NVMCON = 0x4042; //WREN=1, ERASE=1:消去/プログラミングイネーブルビット, NVMOP=0010:メモリのページ消去動作
asm volatile ("disi #5"); //Disable Interrupts For 5 Instructions
__builtin_write_NVM(); //erase 8line = 64*8
while(NVMCONbits.WR);
// Write 64 instructions(バッファからフラッシュメモリにデータを書き込む)
NVMCON = 0x4001;
TBLPAG = page;
for (i=0; i < 64; i++) {
__builtin_tblwtl(offset + i*2, buffer[i]); // *2 is required because address is 0 2 4 6 ,,,,,
__builtin_tblwth(offset + i*2, 0xFF);
}
asm volatile ("disi #5"); //Disable Interrupts For 5 Instructions
__builtin_write_NVM();
while(NVMCONbits.WR);
}
//--------------------------------------------
// フラッシュデータ読み出し
// unsigned int address: アドレス
//--------------------------------------------
unsigned int ReadEprom(unsigned int address) {
unsigned int page = __builtin_tblpage(_flash_datas);
unsigned int offset = __builtin_tbloffset(_flash_datas);
TBLPAG = page;
return __builtin_tblrdl(offset + address*2);
}
================================================
※①の所の配列_flash_datasの大きさが96*8=768個では、ページをERASEしたときにページまたがりにより、他のエリアが消去されて、その結果マイコンが暴走しました。色々と検討した結果512個という結論に至りました。Read Device Memory to Fileボタンを押してHexデータダウンロードしてERASEする前と後を比較してみます。
【ERASE前】 【ERASE/データWR後】
プログラム上:0x1C00 - 0x2000に割り当てますが、Hexデータでは、アドレスが2倍されているので0x3800 - 0x4000のエリアがERASEできているのが分かります。前後のエリアに悪影響が無いことを確認しています。
※参考にしたURL