楽天市場
[無料でホームページを作成] [通報・削除依頼]

PIC18F24K42をPICKIT2で焼くTIPS

私はPIC18F24K42を保有しておらず、この先しばらく使用予定も無いのですが、
ある方から「PIC18F24K42に焼くことは出来ないか」と相談を持ちかけられました。

この方と議論するなかで、こうすればうまくいけんじゃね
という手ごたえを得ましたのでTIPSとして紹介します。

はじめに、
PIC18F24/25/26/27K42はPIC18Fシリーズにおける最新のデバイスで、
18シリーズのWレジスタを介した従来の書き込み方式から、
8ビット長のICSPコマンド搭載の書き込み方式に大幅に仕様変更されました。
※PIC18F4X/5XK42,PIC18F6XK40も同じ書き込み方式を採用しています。

参考までに下にPIC18F24/25K42のコマンド表を載せますが、アレッ!これどっかで見たような...
○PIC18F24/25K42のICSPコマンド
img_20180329-212753.jpg
やっぱり、このICSPコマンドはPIC16F188XXのICSPコマンドとまったく同じものでした。
データ転送順もMSBファーストで同じ。
○PIC16F188XXのICSPコマンド
img_20180329-212838.jpg

表中で、わずかにアドレスの扱いが異なりますが、PIC16では14ビットを1アドレスに割り当てて
いるのに対し、PIC18では8ビットを1アドレスに割り当てているための違いであり、実は両者はまったく同じものです。

○PIC18F24K42のICSPデータをいかに処理するか
この命題にいちばん近い答えは、PIC16F188XXの時と同じようにデータをやり取りできるかという命題の答えです。
PIC16F188XXの時と同じようにデータをやり取りできれば、ホスト側の修正もPIC16F188XXの時と同じ箇所での修正で済むからです。

ICSPコマンドの考察

①Load PC Adressコマンド
EEPROMのアドレスを指定するPIC16F188XXのLoad PC Adressのスクリプトは以下のようでした。
アドレスとして指定するのは実際のアドレス値の2倍。0xF000*2=0x01E0000 (バイトアドレスを指定)
2018.04.01訂正 2倍の値を指定するのは、アドレス値がホスト内部でLSB側に1ビットシフトされるためでした。
AAF2    BB01    AAE7    BB01    AAF2    BB80    AAF2    BB07    AAF2    BB00

F2 01    WRITE_BYTE_LITERAL    01    //0000.0001 -> 1000.0000    Load PC Address(80)
E7 01    DELAY_SHORT                01    //TDLYの時間を作る
F2 80    WRITE_BYTE_LITERAL    80    //1000.0000 -> 0000.0001    0x01          //Adress U
F2 07    WRITE_BYTE_LITERAL    07    //0000.0111 -> 1110.0000    0xE0          //Adress H
F2 00    WRITE_BYTE_LITERAL    00                                               0x00          //Adress L

PIC18F24K42ではすでにバイトアドレスなので実際のアドレス値0x030000を指定すればよいと思われます。
2018.04.01訂正 2倍の値を指定するのは、アドレス値がホスト内部でLSB側に1ビットシフトされるためでした。
このためPIC18F24K42でもアドレスの2倍値を指定する必要があります。0x300000*2=0x600000

AAF2    BB01    AAE7    BB01    AAF2    BB0C    BB06    AAF2    BB00    AAF2    BB00

F2 01    WRITE_BYTE_LITERAL    01    //0000.0001 -> 1000.0000    Load PC Address
E7 01    DELAY_SHORT                01    //TDLYの時間を作る
F2 0C    WRITE_BYTE_LITERAL    0C    //0000.1100 -> 0011.0000    0x30          //Adress U
F2 06    WRITE_BYTE_LITERAL    06    //0000.0110 -> 0110.0000    0x60          //Adress U
F2 00    WRITE_BYTE_LITERAL    00                                               0x00          //Adress H
F2 00    WRITE_BYTE_LITERAL    00                                               0x00          //Adress L

②Load for NVMコマンド
PIC16F188XXのLoad for NVMのスクリプトは以下のようでした。

AAF2    BB00    AAE7    BB01    AAF2    BB00    AAF1    AAF1

F2 00    WRITE_BYTE_LITERAL    00    //0000.0000 -> 0000.0000    Load for NVM(00)
E7 01    DELAY_SHORT                01    //TDLYの時間を作る
F2 00    WRITE_BYTE_LITERAL    00    //Data U  *0を書き込み
F1         WRITE_BYTE_BUFFER           //Data L   *送信後にホスト内でH<-->L 入れ替え、LAB<-->MSB 並び替え
F1         WRITE_BYTE_BUFFER           //Data H   *送信後にホスト内でH<-->L 入れ替え、LAB<-->MSB 並び替え

PIC18F24K42では以下のようにすればよいと思われます。
AAF2    BB00    AAE7    BB01    AAEE    BB07    AA00    AAF1    AAF1    AAEE    BB01    AA00

F2 00    WRITE_BYTE_LITERAL    00                                               Load for NVM
E7 01    DELAY_SHORT                01    //TDLYの時間を作る
EE 07 00 WRITE_BITS_LITERAL    07 00 //先頭からの7ビットに0を書き出す
F1         WRITE_BYTE_BUFFER               //Data L   *送信後にホスト内でH<-->L 入れ替え、LAB<-->MSB 並び替え
F1         WRITE_BYTE_BUFFER               //Data H   *送信後にホスト内でH<-->L 入れ替え、LAB<-->MSB 並び替え
EE 01 00 WRITE_BITS_LITERAL    01 00 //最後の1ビットに0を書き出す

③Read from NVMコマンド
PIC16F188XXのRead from NVMのスクリプトは以下のようでした。
AAF2    BB3F    AAE7    BB01    AAEF    AAF0    AAF0

F2 3F    WRITE_BYTE_LITERAL    3F    //0011.1111 -> 1111.1100    Read from NVM(FC)
E7 01    DELAY_SHORT                01    //TDLYの時間を作る
EF         READ_BYTE                        //Data U  *空読み(バッファーにストアしない)
F0         READ_BYTE_BUFFER            //Data L   *受信前にホスト内でH<-->L 入れ替え、LAB<-->MSB 並び替え
F0         READ_BYTE_BUFFER            //Data H   *受信前にホスト内でH<-->L 入れ替え、LAB<-->MSB 並び替え

PIC18F24K42では以下のようにすればよいと思われます。
AAF2    BB3F    AAE7    BB01    AAEB    BB07    AAF0    AAF0    AAEB    BB01

F2 3F    WRITE_BYTE_LITERAL    3F    //0011.1111 -> 1111.1100    Read from NVM
E7 01    DELAY_SHORT                01    //TDLYの時間を作る
EB 07    READ_BITS 7                 07    //先頭からの7ビットを読み捨て
F0         READ_BYTE_BUFFER              //Data L   *受信前にホスト内でH<-->L 入れ替え、LAB<-->MSB 並び替え
F0         READ_BYTE_BUFFER              //Data H   *受信前にホスト内でH<-->L 入れ替え、LAB<-->MSB 並び替え
EB 01    READ_BITS 1                  01    //最後の1ビットを読み捨て

④その他のコマンド
PIC16F188XXに同じ

Load for NVM/Read from NVMコマンドの考察
上記のようにデータをやりとりすれば、一見良さそうに見えますが実はそうではありません。
Load for NVM/Read from NVMコマンドのペイロードでは最後のビットが必ず0でなければならない約束があるため、
Read from NVMコマンド後のバッファーの中身を比較するとPIC16Fのデータは左(MSB側)に1ビットシフトした状態となっています。
(同じようにPIC18Fのデータをシフトさせると、データのMSBが欠落する。
PIC16Fのデータとしてとり得る値は0_0x3FFF(14ビット)なのに対し、
PIC18Fのデータとしてとり得る値は0_0xFFFF(16ビット)であることに注意。)

両者の違いを解決する(ホスト内でデータ形式を完全コンパチにする)手段は、PK2devicefile.datのファミリー内で
指定するProgMemShiftの値です。
PIC16F188XXではProgMemShift=1とすることで、ホスト内部でバッファーの中身は右に1ビットシフトされ復元されます。
PIC18F24K42ではProgMemShift=0とすることで、シフトは行われず、両者のデータ形式を完全コンパチにすることができます。

○以上の考察をふまえたPIC18F24K42書き込みのための手順は以下のようになります。
①新規ファミリーの作成
PIC18F24K42用に、たとえば"PIC18F MSB1st"という名前のファミリーを新規作成。
  EEMemBytesPerWord=2
  EEMemAddressIncrement=2 (2018.04.08 訂正)
  EEMemHexBytes=2 (2018.04.08 訂正)
  EEMemAddressIncrement=1 (2018.04.08 訂正)
  EEMemHexBytes=1 (2018.04.08 訂正)

  ProgMemShift=0とする。
②PIC16F188XX用のスクリプトを全てコピーしてPIC18F24K42用に名前を変更。
たとえばMR_NVM_MSB_First_RdDevID1 -> 18F_NVM_MSB_First_RdDevID1 など、
  名前中の数値を変更するスクリプト
  MR_NVM_MSB_First_UsrIDRd4Int -> 18F_NVM_MSB_First_UsrIDRd8Int
  MR_NVM_MSB_First_UsrIDWr4Int -> 18F_NVM_MSB_First_UsrIDWr8Int

  MR_NVM_MSB_First_EEWr1Int -> 18F_NVM_MSB_First_EEWr2Int (2018.04.10 訂正)
アドレスの違いを修正。
  UserID 0x200000
  Config  0x300000
  EEPROM 0x310000
  DeviceID 0x3FFFFE
UserIDの個数が違うのでループの回数を修正。
上述のLoad for NVM/Read from NVMコマンドを修正。
③Parts ListアイテムにPIC18F24K42を追加。
ファミリー番号に"PIC18F MSB1st"の番号を指定
  DeviceID:6CA0 -> 01.10.11.00.10.10.00.00 -> 00.00.01.01.00.11.01.10 -> 0536
  EERdLocations=64 (2018.04.10 訂正)
  EEWrLocations=2 (2018.04.10 訂正)

④ホストの変更
"Midrange/1.8V Min MSB1st"の場合に実行した処理を同じ箇所で"PIC18F MSB1st"の場合にも適用し、再コンパイル。