組込み系システム開発室by藤原技研M

製作中の組込み機器や気になる開発ツールなどを中心に記事を書いています。

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後】

f:id:fujiharagiken:20181024204710p:plain

 

f:id:fujiharagiken:20181024204732p:plain

プログラム上:0x1C00 - 0x2000に割り当てますが、Hexデータでは、アドレスが2倍されているので0x3800 - 0x4000のエリアがERASEできているのが分かります。前後のエリアに悪影響が無いことを確認しています。

 

※参考にしたURL 

yuki-sato.com