USBブートローダ

PICkit2等の書き込み機無しでプログラムを書き換えられるのは便利です。
趣味の電子工作にとってはあまり便利ではないと思いますが、キットメーカーや教育関係者にとっては購入者や学生にプログラム書き込み機を購入させることなくファームウェアの更新が出来るので大きなメリットになります。


●USBブートローダー
  ・Microchip社がC言語で書いたブートローダーを公開している。当ページはこれを使ってます。
   他にもフリーのブートローダーもいくつかあるようです。
   ブートローダーについては「千秋ゼミ」のwikiが最も内容が充実している。必読。
  ・ブートローダーのサイズは1kワード、このサイズだけROMを食ってしまう。
   (PIC18FシリーズはROMサイズが大きいので問題にならない)
  ・割り込みベクタは Hex1008 と Hex1018 に配置する必要がある
   C言語の試用期間の制限で2008と2018に変更しておいた方が良い
  ・使ってしまうPICの足
   28ピンデバイスの場合
     USBのD+、D-で2本
     USBの3.3V電源用に1本(0.47μFのコンデンサ付ける)
     ブートローダーとアプリケーションプログラムを切り替える為のスイッチに1本 標準状態ではポートB4
   合計4本
   40ピンデバイスの場合は上記に加えて
     ブートローダー動作確認用のLED2個に2本 標準ではポートD0、ポートD1
   合計6本。省略しても良いがブートローダーが動いているときに何かそれを表示する物が無いと使いにくい
  ・サポートしているPICはPIC18FシリーズのUSBが付いているもの
  ・アプリケーションプログラムはブートローダーと同じ言語で開発する必要は無い
  ・コンフィグレーションビットはPICに1つしかないのでブートローダーとアプリケーションプログラムで共通の物を
   使用しなければならない。
   コンフィグレーションビットで設定する機能の一部はブログラム実行中にも変更できる
   (例えば内部クロックと外部クロックの切り替えなど)が変更できない物もあるので
   ブートローダーの微修正が出来る環境を整えておいた方がよい。
  ・ブートローダーの微修正をする環境は無料で手に入る
   必要な物以下の3つ
     -MPLAB
     -MPLAB C for PIC18 v3.34 Standard-Eval Version
       コードのオプティマイザが2ヶ月経過すると無効になる制約があるがそれ以外は全機能が使える
       2ヶ月経過するとオプティマイザが効かずブートローダーが1Kワードに収まらなくなるのでアドレスを変更する
     -Microchip Application Libraries <-ソース&HEXの集合体
   全部マイクロチップ社のサイトからダウンロードできる。
   一番下のライブラリーは何処にあるのかわかりにくいので上記名前でサイト内を検索すると見つかる
   全部で200MB近くある。必要な物はこの中のごく一部だけなのだが...
  ・ブートローダーを破壊しないようにコンフィグレーションワードで WRTB,WRT0 をセットしておく
   これはmain.cの中の#pragmaで設定
   WRT0をセットする場合は1FFFまでプロテクトされるのでアプリケーションもこれ以降にロードされるように変更する必要有り
   割り込みベクタも同様に2000以降に配置

●アプリケーションプログラム(ファームウェアのこと)

  ・プログラムのROM上のアドレスを指定できる機能と割り込みベクタを設定できる機能を持った言語が必要
  ・BASICでは Swordfish SE が良い
    無料版ではRAMの使用上限が256バイトという制約がかかっているだけ
    当方が今までに作ったプログラムでこの上限を超える物は非常に少ないので実質的な無料ソフトといえる
    日本国内に情報少ないが
     ・共用体(union)が使える
     ・Dim LED As PORTC.0 といった具合にポート別名の命名がきれい
     ・コンフィグレーションビットの設定が古くさくソースに記述する方式なのでサンプルプログラムの公開に都合がよい
      プロジェクトファイルなどが無く全てがソースファイル1つで完結する
     ・コメントに日本語が使える
    等
    (mikroBASICでは都合が悪い部分を改善できるので今後当方のPIC18Fのプログラムはこれを使用していくことにする)
  ・mikroBASICでは各サブルーチンのアドレスを個別に設定しなければいけないようなので
   アップリケーションプログラムの開発は実質不可(面倒くさすぎる)
  ・書き込みには専用のプログラム HIDBootLoader.exe を使う
   これは上記 Microchip Application Libraries に含まれている
   HIDデバイス(キーボードやマウスの仲間)なのでデバイスドライバーは不要

●開発の流れ

  ・面倒だがブートローダーの修正環境をインストールする
   上に書いたMPLAB、Cコンパイラ、アプリケーションライブラリの3つだ
   アプリケーションライブラリの中にブートローダーが含まれている
   インストールの目的は
    ・コンフィグレーションビットの修正(PICkit2でHEXを修正しても良い)
    ・ブートローダーで使用しているPICの足の変更
   これらが必要なければ(ぜっだいに替えたくなる)このステップは省略しても良い
  ・ブートローダーのソースを微修正してコンパイルする
   C言語が読めなくても何とかなるはず
  ・PICkit2等のライターでブートローダーをPICに書き込む
  ・ターゲット回路を作る
    -USBコネクタ
    -発信器(20MHzの水晶かセラロック)
    -ポートB4に10kΩでプルアップしたタクトスイッチ
    -40ピンデバイスなら2個のLED
   これに加えてアプリケーションを動かすに必要な部品
  ・ソードフィッシュコンパイラーでアプリケーションプログラムを作る
   ブートローダーに対応させるために以下3行の決まり文句をプログラムに書いておく
    #option org_reset = $1000
    #option vector_isr_hi = $1008
    #option vector_isr_lo = $1018
  ・HIDBootLoader.exe(アプリケーションライブラリに含まれている)を実行する
  ・タクトスイッチを押したままターゲット回路をUSBでパソコンに繋ぐ
  ・開発したアプリケーションプログラムのHEXファイルを HIDBootLoader で読み込んで
   ターゲットに書き込む。
   書き込み終わったらUSBから切り離す
  ・スイッチを押さずに電源を入れればブートローダーではなくアプリケーションプログラムの方が実行される
  ・量産するときはPICを外してPICkit2でROMを読み出して他のPICにCOPYする


2010-01-02

ブートローダー HEXファイル PIC18F2550 や PIC18F4550 で使える 発振子は20MHz用
ファイル ファイルタイプ 添付ファイルの解説
Bootloader.zip OTHER ブートローダー PIC18F2550でのみ動作確認済み
以下の物で動く(らしい)
PIC18F4553/4458/2553/2458
PIC18F4550/4455/2550/2455
PIC18F4450/2450
PIC18F14K50/13K50
このブートローダーはMCLRに10kΩプルアップ抵抗をつけないで良いように修正してある。(標準状態のブートローダーは抵抗必要)
ソースは40ピンの4550用なのだが28ピンの2550でも動く。

USB、発振子、スイッチ、USB電源用の0.47μFコンデンサだけでブートローダーは機能する。

PICT1355.jpg

必要最小限の回路

LEDはブートローダーに必要な回路ではない。実質ブートローダー特有の物はスイッチだけ。

bl.PNG
LEDを点滅させるアプリケーションプログラム
0001  Device = 18F2550
0002 Clock = 48
0003
0004 #option org_reset = $1000
0005 #option vector_isr_hi = $1008
0006 #option vector_isr_lo = $1018
0007
0008 Dim LED As PORTC.0
0009
0010 While true
0011 High(LED)
0012 DelayMS (1000)
0013 Low(LED)
0014 DelayMS (1000)
0015 Wend
行番号
解説
4行目
このプログラムはHex1000以降にロードするという意味
5行目
高優先順位の割り込みベクタのアドレス
6行目
低優先順位の割り込みベクタのアドレス 4~6行目はブートローダーを使用するときの決まり文句となる
ブートローダーのソース メイン関数のみ抜粋
0001  void main(void)
0002 {
0003 ADCON1 = 0x0F; //Need to make sure RB4 can be used as a digital input pin
0004 // TRISBbits.TRISB4 = 1; //No need to explicitly do this since reset state is = 1 already.
0005
0006 //Check Bootload Mode Entry Condition
0007 if(sw2 == 1) //This example uses the sw2 I/O pin to determine if the device should enter the bootloader, or the main application code
0008 {
0009 ADCON1 = 0x07; //Restore "reset value" of the ADCON1 register
0010 _asm
0011 goto 0x1000 //If the user is not trying to enter the bootloader, go straight to the main application remapped "reset" vector.
0012 _endasm
0013 }
0014
0015 InitializeSystem();
0016 while(1)
0017 {
0018 ClrWdt();
0019 USBTasks(); // Need to call USBTasks() periodically
0020 // it handles SETUP packets needed for enumeration
0021
0022 BlinkUSBStatus();
0023
0024 if((usb_device_state == CONFIGURED_STATE) && (UCONbits.SUSPND != 1))
0025 {
0026 ProcessIO(); // This is where all the actual bootloader related data transfer/self programming takes place
0027 } // see ProcessIO() function in the Boot87J50Family.c file.
0028 }//end while
0029 }//end main
行番号
解説
先頭のif文
スイッチ2がONなら0x1000番地にジャンプ、そうでなければプログラムを書き込むというロジックが見て取れる

PIC18FXXXX用のブートローダーはここにある。

PICT1356.jpg

ブートローダーを修正するときはMPLABでこれを開く。
1つのプロジェクトファイルに多数ファイルが含まれているが修正することになるであろう物は
 main.c
 io_cfg.h
の2つだけ。

PICT1358.jpg

HID Bootloader PIC18 Non J.mcw

アプリケーションプログラム(ファームウェア)の書き込みプログラム HIDBootLoader.exe
ブートローダーとHIDBootLoader.exeによって書き込まれるプログラム、2つのHEXファイルがアドレスHex1000を境界線として1つのPICに書き込まれることになる。

HIDbl.PNG

2011-12-09

MPLAB C18の場合はこんな感じ。ソードフィッシュコンパイラが僅か3行で対応できるのとは対照的。修正すべき物は3つ
 1.プログラムの割り込みルーチンのアドレス設定(main関数のあるソースファイル)
 2.リンカスクリプト。
   標準状態ではプログラムのインストールディレクトリにあるが変更して使うので、
   プログラムのあるフォルダーにCOPYしてプロジェクトにaddしておく。
 3.スタートアップルーチン(c018i.c)
   これも標準状態ではプログラムのインストールディレクトリにあるコンパイル済みのc018i.oを使うが、
   リセットアドレスを変更するのでリンカスクリプトからc018i.oを削除し、c018i.cをプログラムの
   あるフォルダーにCOPYしてプロジェクトにaddしておく。

リンカスクリプト変更箇所(オリジナルをCOPYして使うこと!!)
0001  // File: 18f4550_g.lkr
0002 // Generic linker script for the PIC18F4550 processor
0003
0004 #DEFINE USE_BOOTLOADER
0005
0006 #DEFINE _CODEEND _DEBUGCODESTART - 1
0007 #DEFINE _CEND _CODEEND + _DEBUGCODELEN
0008 #DEFINE _DATAEND _DEBUGDATASTART - 1
0009 #DEFINE _DEND _DATAEND + _DEBUGDATALEN
0010
0011 LIBPATH .
0012
0013 #IFDEF _CRUNTIME
0014 #IFDEF _EXTENDEDMODE
0015 FILES c018i_e.o
0016 FILES clib_e.lib
0017 FILES p18f4550_e.lib
0018
0019 #ELSE
0020 // FILES c018i.o
0021 FILES clib.lib
0022 FILES p18f4550.lib
0023 #FI
0024
0025 #FI
0026
0027 #IFDEF _DEBUGCODESTART
0028 #IFDEF USE_BOOTLOADER
0029 CODEPAGE NAME=page START=0x2000 END=_CODEEND
0030 #ELSE
0031 CODEPAGE NAME=page START=0x0000 END=_CODEEND
0032 #FI
0033 CODEPAGE NAME=debug START=_DEBUGCODESTART END=_CEND PROTECTED
0034 #ELSE
0035 #IFDEF USE_BOOTLOADER
0036 CODEPAGE NAME=page START=0x2000 END=0x7FFF
0037 #ELSE
0038 CODEPAGE NAME=page START=0x0000 END=0x7FFF
0039 #FI
0040 #FI
0041
0042 以下略
行番号
解説
4行目
この定義を削除するとブートローダーを使用しない設定になる。 オリジナルのリンカスクリプトと比較すればどう変更すべきかすぐ解る。
c018i.cの変更箇所(オリジナルをCOPYして使うこと!!)
0001  /* $Id: c018i.c,v 1.7 2006/11/15 22:53:12 moshtaa Exp $ */
0002
0003 /* Copyright (c)1999 Microchip Technology */
0004
0005 /* MPLAB-C18 startup code, including initialized data */
0006
0007 /* external reference to __init() function */
0008
0009 #define USE_BOOTLOADER
0010
0011 extern void __init (void);
0012 /* external reference to the user's main routine */
0013 extern void main (void);
0014 /* prototype for the startup function */
0015 void _entry (void);
0016 void _startup (void);
0017 /* prototype for the initialized data setup */
0018 void _do_cinit (void);
0019
0020 extern volatile near unsigned long short TBLPTR;
0021 extern near unsigned FSR0;
0022 extern near char __FPFLAGS;
0023 #define RND 6
0024
0025 #ifdef USE_BOOTLOADER
0026 #pragma code _entry_scn=0x002000
0027 #else
0028 #pragma code _entry_scn=0x000000
0029 #endif
0030 void
0031 _entry (void)
0032 {
0033 _asm goto _startup _endasm
0034
0035 }
0036
0037 以下略
行番号
解説
9行目
プログラムが完成するまではブートローダーはかえって邪魔になるので、この定義を切り替えて使うと便利。これもオリジナルと比べると違いがすぐわかる。
プログラム本体
0001  以上略
0002
0003 //----------------------------------------------------------------------------
0004 // set LOW & HIGH interrupt vector
0005 //----------------------------------------------------------------------------
0006
0007 #define USE_BOOTLOADER
0008
0009 #ifdef USE_BOOTLOADER
0010 #pragma code InterruptVectorLow = 0x2018
0011 #else
0012 #pragma code InterruptVectorLow = 0x0018
0013 #endif
0014 void InterruptVectorLow (void)
0015 {
0016 _asm
0017 goto Low_priority_interrupt //jump to interrupt routine
0018 _endasm
0019 }
0020
0021 #ifdef USE_BOOTLOADER
0022 #pragma code InterruptVectorHigh = 0x2008
0023 #else
0024 #pragma code InterruptVectorHigh = 0x0008
0025 #endif
0026 void InterruptVectorHigh (void)
0027 {
0028 _asm
0029 goto High_priority_interrupt //jump to interrupt routine
0030 _endasm
0031 }
0032
0033 #pragma code
0034 #pragma interruptlow Low_priority_interrupt
0035 #pragma interrupt High_priority_interrupt
0036
0037
0038 //----------------------------------------------------------------------------
0039 // High priority interrupt routine
0040 //----------------------------------------------------------------------------
0041 void High_priority_interrupt ()
0042 {
0043 // 略
0044 }
0045
0046 //----------------------------------------------------------------------------
0047 // Low priority interrupt routine
0048 //----------------------------------------------------------------------------
0049 void Low_priority_interrupt ()
0050 {
0051 // 略
0052 }
0053
0054 以下略
行番号
解説
7行目
この行をコメントにすればBOOTLOADER非対応になる。