PIC32MXでNVMを使ってみたメモ

公式の資料を読んでも分かりにくいところがあったからメモ.
間違ってるところが多々ありそう.

 

環境

コントローラ:PIC32MX270F256B
コンパイラ:xc32-gcc(v2.10)
フレームワーク:MPLAB Harmony(v2.06)
回路構成:データシートのFIGURE 2-1: RECOMMENDED MINIMUM CONNECTIONにUSB関係を加えたもの.クロックは外部のセラロック.
 

Harmony Configurator

NVMを使う設定をするためにConfiguratorを使う.
[Harmony Framework Configuration]->[Drivers]->[NVM]からUse NVMにチェックを入れる.
Driver ImplementationはSTATICにしておく.軽く使う分には静的のほうが良さそうな気がする.
NVM Media Start AddressはNVMの中で読み書きに使い始めるアドレス.
デフォルトでは0x9D010000となっているが,プログラム自体を書き換えるのでなければ,プログラムのend addressより大きな番地でなければならない.
具体的なメモリマップはデータシートのFIGURE 4-5: MEMORY MAP ON RESET FOR PIC32MX170/270 DEVICES (64 KB RAM, 256 KB FLASH)を参照.
NVM Media Sizeは何KBの領域を使用するかを表す.例えば5にすると,NVM Media Start Addressから5KBを扱うことになる.
忘れがちなのがConfiguration Bitの設定で,Program Frash Write Protect(PWP)やCode Protect(CP)あたりをOFFにしておかないと動かない気がする.
 

ポーリングのあたり

SYS_Initialize関数の中に
/* Initialize the NVM Driver */
sysObj.drvNvm = DRV_NVM_Initialize(DRV_NVM_INDEX_0, (SYS_MODULE_INIT *)NULL);
があることを確認.また,SYS_Task関数の中に
/* Maintain Device Drivers */
DRV_NVM_Tasks (sysObj.drvNvm);
があることを確認.
 

読み書き

データシートの5.0 FLASH PROGRAM MEMORYのNoteに”The Flash page size on PIC32MX1XX/2XX 28/36/44-pin Family devices is 1KB and the row size is 128 bytes (256 IW and 32 IW, respectively).”とあるので,1ページは1KB,1行は128バイトと分かる.また,NVMのドキュメントのAddressing in NVM Driverのあたりから,Read block size = 1 byte,Write block size = ROW Size,Erase block size = PAGE Sizeであることがわかる.このブロックサイズが読み書きの最小単位となる.
DRV_NVM_Open関数では,ioIntentを指定する必要がある.読み書きするならDRV_IO_INTENT_READWRITE が必要.
DRV_NVM_Read関数ではblockStartとnBlockを指定する必要がある.読み込みでは1ブロックが1バイトとなっている.そのため,blockStartはNVM Media Start Addressから何バイト目かを指定する.つまり,実際にアクセスされる仮想メモリはNVM Media Start Address+blockStartとなる.また,nBlockも同様に何バイト読み込むかを指定する.
DRV_NVM_Write関数では1ブロックが1行,つまり128バイトとなる.よって仮想メモリ上のアクセス先はNVM Media Start Address+(128*blockStart)となる.また,書き込むバイト数は(128*nBlock)となる.なお,NVMはEEPROMなので書き込む前にEraseをかけなければならない.EEPROMでは書き込みは’1’=>’0’という操作のみで,Eraseによりすべてを’1’にする.よって,EraseをかけずにWriteをかけると”前の状態&書き込む内容”となり,要するに必要以上に’0’が増える.よって,Writeをかける前にEraseが必要かどうか検討を行う必要がある.
DRV_NVM_EraseWrite関数は上記の問題を解決するためのもので,その名の通りEraseをかけてからWriteをしてくれる.普通はこっちを使う気がする.