SCIでデータを不揮発メモリに格納し、電源OFF前のデーターを保持する必要が発生しました。
最初EEP-ROM のキーワードで探したが、WEBではどうにも見つからない。悩んでもがいてみると、ようやく解決方法が見えてきた。
データーシートの中では、NVM(不揮発性メモリ)という検索キーワードでした。
その中で、データー用のメモリは、DFM(データーフラッシュメモリー)の記述にて解説していました。集中力が切れてると、探せません・・・
DFMは、8bit X 1024 の大きさです。詳細は、データーシート、10.4に記載されています。
読み出しの手順は、
1. Set the NVMADR registers to an address within the intended page.
2. Set the NVMCMD control bits to ‘b000 (Byte Read).
3. Set the GO bit to start the DFM byte read.
4. Monitor the GO bit or NVMIF interrupt flag to determine when the read has completed.
でサンプルコードは、Example 10-9. Reading a Byte from Data Flash Memory in C
// Code sequence to read one byte from DFM
// DFM target address is specified by DFM_ADDR
// Variable to store the byte value from desired location in DFM
uint8_t ByteValue;
// Load NVMADR with the desired byte address
NVMADR = DFM_ADDR;
NVMCON1bits.CMD = 0x00; // Set the byte read command
NVMCON0bits.GO = 1; // Start byte read
while (NVMCON0bits.GO); // Wait for the read operation to complete
ByteValue = NVMDATL; // Store the read value to a variable
読み込みだけなので、簡単みたいです。
書込み手順は、
1. Set NVMADR registers with the target byte address.
2. Load NVMDATL register with desired byte.
3. Set the NVMCMD control bits to ‘b011 (Byte Write).
4. Disable all interrupts.
5. Perform the unlock sequence as described in the Unlock Sequence section.
6. Set the GO bit to start the DFM byte write.
7. Monitor the GO bit or NVMIF interrupt flag to determine when the write has been completed.
8. Interrupts can be enabled after the GO bit is clear.
9. Set the NVMCMD control bits to ‘b000.
そのコードは、Example 10-10. Writing a Byte to Data Flash Memory in C
// Code sequence to write one byte to a DFM
// DFM target address is specified by DFM_ADDR
// Target data is specified by ByteValue
// Save interrupt enable bit value
uint8_t GIEBitValue = INTCON0bits.GIE;
// Load NVMADR with the target address of the byte
NVMADR = DFM_ADDR;
NVMDATL = ByteValue; // Load NVMDAT with the desired value
NVMCON1bits.CMD = 0x03; // Set the byte write command
INTCON0bits.GIE = 0; // Disable interrupts
//––––––––– Required Unlock Sequence –––––––––
NVMLOCK = 0x55;
NVMLOCK = 0xAA;
NVMCON0bits.GO = 1; // Start byte write
//–––––––––––––––––––––––––––––––––––––––––––––––
while (NVMCON0bits.GO); // Wait for the write operation to complete
// Verify byte write operation success and call the recovery function if needed
if (NVMCON1bits.WRERR){
WRITE_FAULT_RECOVERY();
}
INTCON0bits.GIE = GIEBitValue; // Restore interrupt enable bit value
NVMCON1bits.CMD = 0; // Disable writes to memory
どこかで見たことがある様な、EEP⁻ROM の書き込み手順と同じな気がします。
(因みに消し方とかは、DataSheet から確認を。)
さて、このコード内で自分で決めるのは、2つ
ByteValue はデーターの値なので まあ簡単かもしれない。
DFM_ADDR は、何を入れるのですか?
NVMADR のレジスタ長は、24 ビット長という事なので、これを指定すればよいのね。
但し上位2ビットはマスクされるので、実質22ビットのアドレス空間と考えれば良さそうです。
Figure 9-1. Program and Data Memory Map
から考えるとData EEPROM (1024Bytes)は 380000h~3803FFh にエントリーされている様子
1バイトのデーターならこの空間内のアドレスを指定すればいいのでしょう。
#define EEPROM_START 380000h
にオフセットアドレスを加える感じで、アドレス指定すればいいのではないかと思います。
これを元に関数として作成したのがこちらです。(XC8、MPLAB X V6.05)
void EEP_ROM_write(uint8_t ByteVAlue, uint8_t Bytedata){
uint8_t GIEBitValue = INTCON0bits.GIE; // Save interrupt enable bit value
// Load NVMADR with the target address of the byte
NVMADR = EEPROM_START+ ByteVAlue; // EEPROM START ADD + Offset Add
NVMDATL = Bytedata; // Load NVMDAT with the desired value
NVMCON1bits.CMD = 0x03; // Set the byte write command
INTCON0bits.GIE = 0; // Disable interrupts
//????????? Required Unlock Sequence ?????????
NVMLOCK = 0x55;
NVMLOCK = 0xAA;
NVMCON0bits.GO = 1; // Start byte write
//???????????????????????????????????????????????
while (NVMCON0bits.GO); // Wait for the write operation to complete
INTCON0bits.GIE = GIEBitValue; // Restore interrupt enable bit value
NVMCON1bits.CMD = 0; // Disable writes to memory
}
この関数を書き込んで、チェック。無事コンパイル通りました。
無事に、電源OFF前に書き換えた内容で、再起動時に表示。
動作OKです。