PICのEEPROMとHEFについて

〔PICの動かせ方入門に戻る〕


色々プログラムを組んでいるとぉ、補正/校正値や調整値等のパラメータをメモリに保存して
次回値として利用したいなどと思うのですがぁ、こういう時に使うのがEEPROMですね。
EEPROM (Electrically Erasable Programmable Read-Only Memory)は電源を切ってもデータの内容が
保持されています、いわゆる不揮発性メモリの一種ですね。
因みに、PICのEEPROMは10万回の書き換えと40年の保持期間が有るようです。

だが、最近の12F15xxや16F14xx/16F15xx/16F17xxにはEEPROMが見当たりません、なんでぇやぁ?
データシートをよく見ると”HEF (High-Endurance Flash:高書き込み耐性フラッシュセル)”なるものが
有ります、実はこれがEEPROMの代わりをしてくれるメモリです。

このHEFメモリは、プログラムフラッシュメモリ(プログラムの保管場所)の一部分を利用するものです。
プログラムフラッシュメモリの耐性は1万回で少ないのですが、HEFの部分だけ10万回の耐性にした
メモリの様です、ですのでこのHEFを利用すると言う事は、プログラム容量が減ると言う事です。

PIC18系統で、"XC8 V1.40"のコンパイラを使用し"eeprom_read( )/eeprom_write( )"を使うと
  エラーが出ます、この代わりにMPLAB X IDEのMCC機能を使う様です、
  この話はこちらを参照下さい。
 *2)

《EEPROM》

先ずは、XC8コンパイラによるEEPROMのアクセス方法と、MPLAB XでのEEPROMデータを表示させる
方法を纏めて置きます。

EEPROMデータの表示

MPLAB Xで、PICに書き込まれているEEPROMのデータ内容を表示させる方法です。
@ MPLAB Xを起動させ、PICとPICKit3を接続します。
  (勿論、読み出したいPICのプロジェクトファイルはloadさせて置きますよ)
A MPLABXのツールアイコンのアイコンをクリックしてPICのメモリデータを読み込みます。

B IDEメニューバーの「Window」→「PIC Memory Views」→「EE Data Memory」を順番にクリック
  します、下の画面が表示されEEPROMの内容が表示されるでしょう。

EEPROMデータ表示画面1
この画面は表示のみの様で、データの修正などは出来ない模様です。
因みに、"FF"は何も書き込まれていない状態です。

EEPROMデータの初期化

プログラムでEEPROMデータを初期化する方法です。

EEPROMデータ表示画面2
"__EEPROM_DATA"にエラー(赤丸マーク)が出ていますが使用出来ます。
図下のEEPROM画面内容はコンパイルすれば表示出来ます。

上図の様に"__EEPROM_DATA"を使いますが、バイトデータを8個単位に記述しないとダメです、
ですので256バイトEEPROMならば、32行まで記述出来ると言う事です。

"eeprom char dt=0x30;"の様に記述も可能ですが、通常のRAM変数よりもアクセスに時間が
かかるしぃ、この方法を使う意味が今一つ見いだせないのでぇあんまりお勧めはしません。
ちなみにぃ、"eeprom char dt;"とすると"0"で初期化されます。

PICへプログラムを書き込む時の注意点(EEPROM時)

デフォルトの動作では、PICにプログラムを書き込む際に必ずEEPROMにもデータが書き込まれます
"__EEPROM_DATA"の初期値が有ればそのデータが、又、なければ"FF"のデータが書き込まれます。

折角、調整値等を計測して書き込んで置いて次回も利用しようとした場合に、
プログラムを変更しPICに書き込むとEEPROMデータは"FF"初期値に戻ってしまいます。
それはぁ、困るぞぉ〜って人は下記を操作すればプログラム書込み時にEEPROMは書込まれません。

IDEメニューバーの「File」 → 「Project Properties (xxxx)」をマウスで順番にクリックします。

MPLABX画面2
Categories:」のパネル内で"PICkit3"を選択します。
右のパネルの「Option categories:」で"Memories to Progrm"を選択します。
Preserve EEPROM .....」項の□にチェックを入れ、[OK]ボタンをクリックします。


EEPROM読み書き関数

 ans = eeprom_read(adrs)
  EEPROMの指定した場所から1バイト読み出す処理です
   adrs :読み出す場所のアドレスを指定します、256バイトEEPROMなら0-255を指定
   ans :読み出した1バイトのデータを返します

 eeprom_write(adrs,value)
  EEPROMの指定した場所に1バイト書き込む処理です
   adrs :書き込む場所のアドレスを指定します、256バイトEEPROMなら0-255を指定
   value :書き込む1バイトのデータを指定します

《HEF》

実はPIC1xF1xxx(12F1822等)シリーズにもプログラムメモリエリアから読み出す機能は有った様です、
これと同じアクセス方法なのですが、レジスタ名が異なり、耐性フラッシュではないです。
更に実は、HEF以外のメモリエリアやコンフィギュレーションエリアにもアクセス出来てしまいます、
ですがぁ、このエリアのアクセスには危険が伴うので単純にHEFのみアクセスする事をお勧めします。

HEF構成図1  これがHEFのメモリ構成図です。
 但し、PIC12F1501のプログラムメモリ1024Wordsの場合です。
 プログラムメモリエリアの最後の方128WordsがHEFとして使われます。
 ですのでこのHEFエリアのみ耐性フラッシュと言う事になる様です。

 でぇ更に、HEFエリアをブロック単位に分け、その単位でのみアクセス
 しないとダメです。
 プログラムが2Kwords以下なら1ブロックが16words単位、それ以上なら
 32words単位です。
 って事は、16words単位なら8ブロック、32words単位なら4ブロックです。

 でぇ、プログラムメモリって事は1wordは14ビットですよ、間違わない様に
 (PIC16Fxxxx以下は命令コードが14ビットの長さなのですよ)


HEFからの読出しは1word単位で出来ますが、書込みは1ブロック単位です。
書込みの操作は、
 @ 書き換える場所のブロックを読み出す。
 A そのブロックを全部消す。("3FFF"に初期化される)
 B 読み出した@の値を変更して書き込む。(一部変更しても1ブロック書き込まれる)
消す時と書き込む時に3ms程ストールします、って事はプログラムが停止します、
割込みにも応答できない、完了後に再開されます。
なので、アプリケーション動作が瞬断するといった問題に配慮する必要があります。
まぁ、頻繁に書き込みはしない事ですね。

HEF読み書きライブラリ

AN1673の技術資料に "フラッシュサポート ライブラリのコード"が有ります、これをコピーペしました。
そのコードを、若干変更&2015/03/03現在のPIC12F15xx/16F14xx/16F15xx/16F17xxデバイスに対応
させています。
但し、1word(14ビット)で読み書き可能ですが、このライブラリはLOWビット(0-7)の8ビットのみしか
読み書きを行っていません、HIGHビット(8-13)も読み書きしたい人は自分で改造しましょう。
(って事は、このライブラリ使うなら128バイトのアクセスって事ですかね)

ダウンロードしたファイルの構成は、
 Flash.h・・・・・・・・・・フラッシュサポートライブラリのヘッダファイル
 Flash.c・・・・・・・・・・フラッシュサポートライブラリのソースファイル
 HEFlash.h・・・・・・・・高書き換え耐性フラッシュサポートライブラリのヘッダファイル
 HEFlash.c・・・・・・・・高書き換え耐性フラッシュサポートのソースファイル

 HEFlash.hとHEFlash.cはFlash.cを使った高水準レベルライブラリです。

このライブラリの中から、HEFにアクセスする為に必要な関数(HEFlash.c)のみ説明をして置きます。

 ans = HEFLASH_readByte(radd,offset)
  HEFから指定ブロック内の指定位置から1バイト読込みを行う処理です
   radd :読み込みたいブロックの場所を指定します(0-4 or 0-7)
   offset:読み込みたいデータのブロック内位置を指定します(0-15 or 0-31)
   ans  :読み込んだ1バイトのデータを返します

  ブロック指定でなくアドレス指定が良い人は、FLASH_read( )関数を利用しましょう。

 ans = HEFLASH_readBlock(*buffer,radd,count)
  HEFから指定ブロックの読み込みを行う処理です
   buffer:読み込んだデータを格納する場所を指定します(count数分のエリアは確保する事)
   radd :読み込みたいブロックの場所を指定します(0-4 or 0-7)
   count:読み込むデータサイズ
   ans  : 0=成功
       −1=失敗(raddのブロック指定がデカすぎか、countの値がブロックサイズを超えたぞぉ)

  注意) countがブロックサイズよりも小さい場合は、countまでしか読み込みませんが、
      後で書き戻す場合はブロックサイズ分読み込む事。

 ans = HEFLASH_writeBlock(radd,*buffer,count)
  HEFの指定ブロックに書き込みを行う処理です
   radd :書き込みたいブロックの場所を指定します(0-4 or 0-7)
   buffer:書き込みたいデータを格納した場所を指定します
   count:書き込むデータサイズ
   ans  : 0=成功
       −1=失敗(raddのブロック指定がデカすぎか、countの値がブロックサイズを超えたぞぉ)
    例)
    #include <xc.h>
    #include "Flash.h"
    #include "HEFlash.h"

    char buff[FLASH_ROWSIZE] ; // ブロックサイズの分バッファを確保する

    void main()
    {
         char ans ;

         ans = HEFLASH_readBlock(buff,0,FLASH_ROWSIZE) ; // 0ブロックを読み出す
         buff[0] = 0x10 ;
         buff[1] = 0x11 ;
         buff[2] = 0x12 ;
         ans = HEFLASH_writeBlock(0,buff,FLASH_ROWSIZE) ; // 0ブロックを書き戻す
    }
  注意) countがブロックサイズよりも小さい場合は、ラッチエリアにはその分しかセットされないが、
      書き込まれるのはブロックサイズ分です。

HEFメモリの予約

作成したプログラムをコンパイルするとそのコードはプログラムメモリエリア(0h〜3FFh)の上からで
なく、下の方から使用されていきます。
例えば下の様な感じです。(12F1501での例ですよ)

MPLABX画面5
って事はHEFを使いたい場合に、
プログラムと競合( コードとデータのオーバーラップ等)してしまうのでございます。

ですから、コンパイラがそのHEF部分を避ける様に下記操作を必ずしないとぉあぶない、あぶない。

IDEメニューバーの「File」→「Project Properties」→を順番にクリックします。

MPLABX画面6
Categories:」のパネル内で"XC8 linker"を選択します。
右のパネルの「Option categories:」で"Runtime"を選択します。
Additional options:」項の場所で"--ROM=default,-0380-03ff"を記述し、
[OK]ボタンをクリックします。

 --ROM=default,-(HEF先頭アドレス)-(HEF終了アドレス)
  ここは12F1501の場合で、他のPICの先頭アドレスと終了アドレスは、"Flash.h"を見ましょう。

MPLABX画面7
 ね、こんな感じでズレます、これでHEFエリアを確保しました。
 でもその分プログラム書き込みエリアが少なくなると言う事ですね。
 なので少ししか使わないなら1ブロック分ズラせば良いかもね。


このページではXC8コンパイラを使った記事です、他のコンパイラの場合は000hの上の方から
  プログラムを書き込んで行く物が有る様です、その場合は上の操作は不要かもね。 *1)

プログラムデータエリアの表示

上の画面の様にプログラムデータウィンドウを表示させるには、
IDEメニューバーの「Window」→「PIC Memory Views」→「Program Memory」を順番にクリックします。
因みに、プログラムデータウィンドウ画面の"format"を"Code"に変更すると命令コードで表示されます。

PICへプログラムを書き込む時の注意点(HEF時) *3)

上の操作でHEFメモリの場所を確保しても、デフォルトの動作では、PICにプログラムを書き込む際に
必ず初期値が書き込まれます
"__EEPROM_DATA"の初期値が有ればそのデータが、又、なければ"3FFF"のデータが書き込まれます。

折角、調整値等を計測して書き込んで置いて次回も利用しようとした場合に、
プログラムを変更しPICに書き込むとEEPROMデータは"3FFF"初期値に戻ってしまいます。
それはぁ、困るぞぉ〜って人は下記を操作すればプログラム書込み時にHEFの場所には書込まれません。

IDEメニューバーの「File」 → 「Project Properties (xxxx)」をマウスで順番にクリックします。

MPLABX画面2
Categories:」のパネル内で"PICkit3"を選択します。
右のパネルの「Option categories:」で"Memories to Progrm"を選択します。
Auto select memories and ranges」項で、[Manually select memories and ranges]を選択。
Preserve Program Memory(not available with programmer...)」項の□にチェックを入れます。
Preserve Program Memory range(s)(hex)」項に"380-3ff"の値を設定し、
("380-3ff"は上記で確保したHEFエリアの場所アドレスを設定します)
[OK]ボタンをクリックします。


《その他》

14ビットと半端な為、14ビット(16383)以上のデータを扱おうとすると分けたりの操作が増えるので、
途端に面戸くさくなりますねぇ。
PICを使う側から考えると、EEPROMに比べてHEFは使いづらい様な気がするのですがぁ、
作る側からしたらこの方が良いのでしょうかねぇ?
"__EEPROM_DATA"の初期化みたいな事をHEFで行うには、それ専用のプログラムを作成して
書き込めば良さげな気がします。




記事一部追記(*3) 2017/12/14
記事一部追記(*2) 2017/01/09
記事一部追記(*1) 2016/12/25


【きむ茶工房ガレージハウス】
Copyright (C) 2006-2017 Shigehiro Kimura All Rights Reserved.