PIC24向けのSDカードBOOTLOADERを作った


PIC24向けSDカードBOOTLOADER

PICの内部のプログラムメモリの書き換えはここで示した。
このようにPICは内部から自身のメモリを書き換えることができるので、外部から実行コードを読み込み適切にメモリに配置すれば、BOOTLOADERとして動作させることができるはず。
今回はSDカードからPIC用のHEXフォーマットを読み込み、プログラムメモリに展開し、実行してみたのでその方法を示す。

方針

すでにシリアルからプログラムの読み子書きを実施するシリアルBOOTLOADERはmicrochipから配布されている。 (AN1157

動作原理としては単純で、下記のように規定されたコマンドでシリアル経由でプログラムを読み書きおよび実行ができ、それを用意にできるようなwindowsのアプリケーションが用意されている。

ScreenClip

今回はこれを改造してSDカード用にBOOTLOADERを作成する。
SDカードからのファイルの読み書きはmicrochipから提供されているMLAライブラリを使用。

プログラムは実行と同時に下記のながれで実行する。
1. SDカードを読み込み適当な.HEXファイルの読み込み。
2. .HEXのファイルを読み込みフォーマットをパース。
3. プログラムメモリのユーザ領域にコードを書き込む。
4. ユーザー領域の先頭にとびユーザー領域のコードを実行。

(実際には起動時に何かしたのピン入力が設定されていた場合BOOTモードで起動し、それ以外は直接ユーザー指定領域に移動するのがよさそう。)

HEXファイルの解析

MPLABが吐き出すHEXファイルはIntel Hexと呼ばれるファイル形式。

例)
:100000000004040000000000C6040000C604000054

上記の例のように:(スタートコード)で始まり
10: 0x10バイトのデータフィールド長(バイトカウント)
0000: アドレス
00: レコードタイプ (PICの場合data:0x00, EOF:0x01, 0x04:拡張リニアアドレスのみ)
0004040000000000C6040000C6040000 : データ0x10バイトある。
54 : チェックサム
となっている。

(下記参考にしました.
http://nanoappli.com/blog/archives/3307
http://quickturn.xrea.jp/pic/hexfile.html

なので下記のようにパースする。

//Define intel hex format.
typedef struct intel_hex_format{
    unsigned char   status_code;
    unsigned int    data_length;
    unsigned long   address_offset;
    unsigned int    record_type;
    unsigned char   data[DATA_BUF];
    unsigned char   check_sum;<br />
} FORMAT;</p>

<p>int parse_hex_format(const char *str, FORMAT *format ){
    char hex_data[DATA_BUF+4];</p>

<pre><code>//NULL check    
if(format == NULL ){return -1;}
if(str==NULL){return -1;}

//Read status code.
if(str[0]!=':'){    
    return -1;
}else{
    format-&amp;gt;status_code = ':';
}

//Read data length
format-&amp;gt;data_length = 0x10*char2hex(str[1])+char2hex(str[2]);

//Read address format
format-&amp;gt;address_offset= 0x1000*char2hex(str[3])+
                        0x0100*char2hex(str[4])+
                        0x0010*char2hex(str[5])+
                        0x0001*char2hex(str[6]);

//Read record type
format-&amp;gt;record_type= 0x10*char2hex(str[7])+char2hex(str[8]);

//Read data
int i;
for(i=0;i&amp;lt;format-&amp;gt;data_length;i++){
    format-&amp;gt;data[i]=0x10*char2hex(str[ 9+2*i])+
                    0x01*char2hex(str[ 10+2*i]);
}
//Read check sum
format-&amp;gt;check_sum = (unsigned char)0x10*char2hex(str[9+2*format-&amp;gt;data_length])+char2hex(str[10+2*format-&amp;gt;data_length]);

return 0;
</code></pre>

<p>}

BOOTLOADERおよび、ユーザアプリのメモリ配置

PIC24Fのプログラムメモリは下図の構成。
AN1157のシリアルBOOTLOADERでは0x400をBOOTLOADERの開始領域としているので同じとした。
また、SDBOOTLOADERの場合ファイルシステムの領域が大きく、メモリを食うのでユーザープログラムの開始領域は0x80C0とした。

ScreenClip

割り込みの設定

割り込みベクタはは本来0x00~0x0Cの間に配置されるが、ユーザのプログラムで割り込みを使用するためには、一度0x00~0x0Cで受けた割り込みをユーザー割り込みの領域に実行コードに飛ばす必要がある。
今回は一度0x00~0x0Cから0x8000~0x80C0まで飛ばし、そこからさらにユーザーの割り込み関数の実行コードまで飛ばすこととした。
このときのリンカスクリプトの設定はgithub参照

(リンカスクリプトはmicrochipのPIC24用のブートローダのコードを使用しました。)

 ユーザープログラムのリンカスクリプト

ユーザー側のアプリケーションは0x80C0から配置する必要がある。
こちらのリンカスクリプトはこちら

結果

詳細は省くが実際にSDカードからHEXファイルを読み込み、ユーザのコードを実行することができた。
ブートローダのコードがこちら
ユーザのプログラムのコードがこちら

改善点

今回PIC24FJ64GB002を使用したがメモリの領域がせまく、BOOTLOADERとUSER PROGRAMの領域が同じぐらいになってしまった。
(未使用の関数をコメントアウトするとBOOTLOADERのコードを0x400~0x6000ぐらいまでに収めることができた。)
もう少し大きいProgram memoryを持つPICを使ったほうがよさそう。

The following two tabs change content below.
miyamoto
IoT/ DIY / music / 日本語ラップ
miyamoto

About miyamoto

IoT/ DIY / music / 日本語ラップ

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

Post Navigation