1.はじめに
PIC24Fはデータ記憶用のROMがなく、データの保存にはプログラム領域のROMを用いる必要があるらしい。
とあることから、300程度のINTデータを保存しておきたくなったのだが、インターネット上でざっと私が調べた範囲では、多くても1ページ(3Byte×64)を使うもので、ページをまたがってデータを保存する方法が簡単に書かれたものはなかった。使い方を理解するのに相当の時間を費やしたので、ここにまとめておく。
ただしまだ完全とは言えず、データROMに使う領域を変更すると、一部使えなくなることがある(詳細は後述)。つまり、ここに書いてあることは、まったくの間違いという可能性もある。このプログラムを使う際はトライアルを厳重にする等、十分注意をお願いします。
なお、本調査にあたっては、以下のブログを参考にさせていただいた。
あらためてお礼を申し上げるとともに、リンクフリーとのことなので、リンクを張らせていただく。まず、こちらを読んだほうが理解が深まると思う。
ハム三昧さん
http://jr4pdp.blog.enjoy.jp/myblog/2019/05/pic24f64ga004ee-d37e.html
2.前提条件
・利用したPICは、PIC24FJ64GA002
その他のPIC24でも使えると思う(未確認)。その場合はメモリマップを参照の上、利用する領域を適宜変更のこと。
・INT(16Bit)データを読み書きする。
・データの消去単位である1536Byteを対象とするが、1/3は使いにくいので使わないこととし、1024Bit(=Intで512個)のデータを読み書きする。
・コンパイラは、X16 V1.24。古いがご勘弁を。
3.使い方
3-1.事前準備
(1) ヘッダーファイルの準備
p24FJ64GA002.h
をインクルードする。私の環境では、
C:\Program Files (x86)\Microchip\xc16\v1.24\support\PIC24F\h
にあった。
(2)データROM領域の定義
コンフィギュレーションビット設定の前に
const __attribute__*1 unsigned int _flash_datas[96*8];
を追記する。
上記は、0x9C00~0xA1FFをデータROMにする例である。
このスタートアドレス(0x9C00)は、0x600 ごとに設定できる(0x9000,0x9600,0x9C00,0xA200・・・)。
*なぜか0x9600、0xA200に設定した場合は、半分の256個までしか使えなかった。
理由は不明。間違っているのかもしれない と書いたのはこれが理由。
3-2.書き込み
da_tmp にあるデータを書き込みたい場合は以下とする。
複数ページに書き込む場合、要はoffsetを128づつインクリメントしていけばよい。
void Flash_Write() {
unsigned int i=0;
unsigned int j=0;
unsigned int page = __builtin_tblpage(&_flash_datas);
unsigned int offset = __builtin_tbloffset(&_flash_datas);
// ページ消去
TBLPAG = page;
__builtin_tblwtl(offset, 0x0000); //
NVMCON = 0x4042;
asm volatile ("disi #5");
__builtin_write_NVM(); //erase 8line = 64*8
while(NVMCONbits.WR);
// メモリー書き込み
for(j=0;j<8;j++) {
NVMCON = 0x4001;
TBLPAG = page;
for (i=0; i<64; i++) {
__builtin_tblwtl(offset + i*2, da_tmp[i+j*64]); // *2 偶数
__builtin_tblwth(offset + i*2, 0xFF);
}
asm volatile ("disi #5");
__builtin_write_NVM();
while(NVMCONbits.WR);
offset=offset+128;
}
}
3-3. 読み込み
da にデータを読み込む場合は以下。
こちらも、offsetを128づつインクリメントする。
void Flash_Read() {
unsigned int i=0;
unsigned int j=0;
unsigned int page = __builtin_tblpage(&_flash_datas);
unsigned int offset = __builtin_tbloffset(&_flash_datas);
// フラッシュメモリー読み込み
TBLPAG=page;
for(j=0;j<8;j++){
for(i=0;i<64;i++){
da[i+j*64] = __builtin_tblrdl(offset + i*2);
}
offset=offset+128;
}
}
*1:section(".Data_Memory"), space (prog), address (0x9c00)