ドキュメント(pdf) - IAR Systems

By Shawn Prestridge, IAR Systems Software Inc.
Co-author Colin Flournoy, IAR Systems Software Inc.
IAR Embedded Workbench と STM32F207ZG-SK を
使用したブートローダの構築の実例

Download application project (zip)
ソフトウェアが複雑になるにつれ、出荷後に発生する問題に対処するため、ファームウェアはフィール
ドで自分自身を書き換えできるように設計されるようになりました。ファームウェアの書き換えはブー
トローダが行います。この記事では、IAR Embedded Workbench と評価キット STM32F20ZG-SK を使
用してブートローダを構築する方法や問題点について解説します。
ブートローダに要求される機能は様々で、設計の実際について議論することは難しいと言えます。書き
換えのためのデータを取り込む方法ひとつをとっても様々で、マイコンの周辺デバイスの USB、同じ
く周辺デバイスの Ethernet を使用した TCP/IP、または古めかしい RS232C などだったりします。ブー
トローダはいろいろな場面で必要になる機能なので、設計を始める前に、使用するマイコンで使えるブ
ートローダのサンプルがすでに作られていないかどうか、マイコンメーカに確かめてみることをお勧め
します。もしそれが手に入るなら、ブートローダの構築の手間をかなり省くことができます。
選択するアーキテクチャによっても微妙な差があります。例えば、デバイスが ARM か Cortex-M3 かで
リセットベクタが異なります。またデバイスメーカにより、ベクタテーブルを再配置できるもの・でき
ないものがあります。ここでは、話を簡単にするために、ひとつのデバイスとその評価キットを実例と
することにします。
評価キット STM32F20ZG-SK は Cotex-M3 デバイスを搭載しています。 この記事ではこのボードが手
元にあり、デバイスにプロジェクトをダウンロードする方法をすでに理解していて、EWARM のデバッ
ガ C-SPY のマクロファイルシステムが、デバッガをスタートする前にどのようにレジスタの値などを
操作することができるかなどについて知識があることを前提とします。
図 1: STM32F207ZG-SK 評価キット
Page 2
ワークスペースはプロジェクト管理の最上位であり、IAR Embedded Workbench を起動すると自動的
にオープンします。ワークスペースには複数のプロジェクトを登録することができるので、ここではメ
インのアプリケーションとブートローダのプロジェクトを登録します。このワークスペースの中で、ど
の順番でプロジェクトをビルドするか決めることができます。ここでは、メインのアプリケーションプ
ロジェクト(キット用に用意されたプロジェクトをベースにしたもので、プロジェクト名は LCD)、
ブートローダの順にビルドすることにします。なぜなら、ブートローダをビルドする時にアプリケーシ
ョンのイメージデータをロードする予定だからです。これは、IAR Embedded Workbench IDE のバッ
チビルドの機能により実現でき、プロジェクトメニュー > バッチビルドをクリックすることで起動す
ることができます (図 2 参照)。バッチを編集し、ビルドするプロジェクトを追加したり、プロジェクト
の順番を変えたりすることも、マニュアルでビルドを行うこともできます。
図 2: バッチビルド
アプリケーションとブートローダを同一のプロジェクトに置くことはどうしてもできません。1つの理
由は、IAR Embedded Workbench が (特に、ブートローダとアプリケーションのスタートアドレスが離
れている場合)非常に大きなバイナリファイルを作ってしまうことです。ブートコードの最後とアプリ
ケーションの最初のコードの間に周辺デバイスのアドレスがあると、空きエリアのデータを周辺デバイ
スに書こうとしてフラッシュローダが誤動作することがあります。このことが問題にならないとしても、
ブートローダはコードを受け取る静的に配置された配列を持つのでアプリケーションの走行時に必要な
メモリ領域を圧迫してしまいます。2つの独立したプロジェクトにすることにより、リンカは効果的に
メモリを配置することができます。もう1つの理由は、ブートローダとアプリケーションが同じプロジ
ェクトに属していると、これらを別々に変更することができないことです。つまり、片方を変更すると
いうことは、もう片方も変更することになり、デバッグに時間がかかってしまうことです。
基本的な設定
この例では、メインのアプリケーションプロジェクトを特定のアドレス (この例では 0x0801000)より
上側に置き、ブートローダを下側に置きます。(0x08000000 より開始) 。一度この設定を行うと、ブー
トローダ・プロジェクトのバイナリイメージを作成することができます。この方法の有利な点は、ブー
トローダのバイナリイメージをアプリケーションに取り込むことができ、デバッガでアプリケーション
とブートローダを同時にダウンロードするこができることです。まとめると、
Page 3
ブートローダのプロジェクト:
1. ブートローダのプロジェクトを作成します。
2. ブートローダのコードと固定データをブートローダ用に確保した空間 (このプロジェクトでは
0x08000000 と 0x08000FFF の間)に配置します。(図 3 参照)
図 3: リンカの設定
3.
4.
ブートローダ・プロジェクトの出力コンバータ (プロジェクトメニュー > オプション > 出力コンバ
ータ> 出力) を、バイナリファイルを生成するように設定します。(図 4 参照)
バイナリファイルは、メモリの内容のそのもので、フォーマットやアドレス情報を含みません。
図 4: 出力コンバータの設定
Page 4
アプリケーションプロジェクト:
1. メインのアプリケーションのプロジェクトを作成します (app)。この記事では、STM32F207ZGSK 用評価キットに付属のサンプルプロジェクトである LCD プロジェクトを使用します。
2. プログラムコードと固定データを、アプリケーション用に確保した場所に配置します。この例では、
ブートローダの次の部分 0x08001000 からフラッシュメモリの最後 0x080FFFFF(STM32F207ZG
の場合)までです。次にリンカ設定ファイル(.icf) に以下の行を追加し、
place at address mem:0x08000000 { section .bootloader };
.bootloader セクションを配置します。この行は、フラッシュメモリの最初の部分に、ブートロー
ダのバイナリイメージを配置することを意味します。(図 5 参照)
図 5: リンカの設定 2
3.
プロジェクトメニュー > オプション>リンカ > 入力と選び、ブートローダ・プロジェクトで作成し
たバイナリイメージを読み込むように設定します。リンカはバイナリイメージを定数の配列のよう
に扱い、リンカ設定ファイルで指定したアドレスにそのままコピーします。さらにこのバイナリイ
メージのシンボル名と所属するセクション名を設定し、このシンボルが他の部分から参照されてい
なくても配置されるように設定します。この記事のプロジェクトでは、シンボル名を bootloader、
所属するセクション名を .bootloader、アラインメントは 4 とします。(図 6 参照)
Page 5
図 6: リンカの入力
デバッグ
アプリケーションのデバッグは通常の場合と同じですが、デバイスとアーキテクチャの違いにより多少
の変更が必要になる場合があります。デバッグを開始する前にもう一度整理すると以下のようになりま
す。
1. アプリケーションの追加入力である、ローバイナリファイルを生成するブートローダ・プロジェク
トを作成します。
2. アプリケーションのプロジェクトは、プロジェクトオプションでこのローバイナリファイルを追加
入力とするように設定します。
3. 両方のプロジェクトのリンカ設定ファイルは、コードとデータが重なり合わないように修正します。
それから、デバッグ対象がアプリケーションだけでなくブートローダも同時にデバッグしなくてはなら
ないことを、デバッガに知らせなくてはなりません。STM32F2xx にはベクタテーブルのベースアドレ
スを指定するレジスタがあり、ブートローダからアプリケーションにジャンプする時に、このレジスタ
を書き換えてベクタテーブルを持ち替えます。
さて、デバッグ対象のプログラムはアプリケーションのリセットベクタのアドレスではなく、ブートロ
ーダのリセットベクタよりスタートすることをデバッガに知らせなくてはなりません。これは、デバッ
ガのマクロファイルを呼び出すことにより実現できます(.mac)。以下が、デバッガに対して、ブートロ
ーダを先に実行し、後からアプリケーションに移動することを知らせるマクロです。この記事よりリン
クされているプロジェクトサンプル内には、test.mac というマクロファイルが含まれていて、アプリケ
ーションのプロジェクトオプションに追加されています。マクロファイルの名前は、拡張子が.mac で
あれば自由につけることができます。このファイルを使用して、デバッガに対し、デバッグ対象のプロ
グラムがブートローダにあるリセットベクタにある Reset_Handler というアドレスからスタートする
ことを知らせます。このファイルで、スタックポインタの初期化も行います。下記が、このマクロファ
イルの内容で、以上のことをどのように行っているか理解することができます。
Page 6
// test.mac ファイル
execUserReset()
{
MSP = *(int*)0x08000000;
PC = *(int*)0x08000004;
//スタックポインタをブートローダのベクタテーブルの
先頭アドレスにセット
//プログラムカウンタをブートローダのリセットハンド
ラの先頭アドレスにセット
}
マクロファイルの編集が終わったら、プロジェクトメニュー > デバッガ > 設定タブのページでプロジ
ェクトに追加し、有効にします。プログラムのテストの最初のステップは、ブートローダがデバッガ内
で正常に動くことを確認することです。この目的のために、下の図の ”run to main”のチェックははずし
ておきます。
図 7: デバッガの設定
アプリケーション (app)には、ローバイナリイメージを追加済みですが、ローバイナリイメージのデバ
ッグ情報が含まれていません。デバッグ情報を追加してソースレベルデバッグを可能にするには、プロ
ジェクトメニュー > オプション> デバッガ > イメージタブを開き、ブートローダの .out ファイルを指
定します。.out ファイルには実行コードだけでなくデバッグ情報も含まれています。この.out ファイル
は通常プロジェクトファイル\ビルド構成名の下の exe フォルダに作成されます。デバッグ情報をのみ
が必要なので「デバッグ情報のみ」のチェックを入れて、オフセットは 0 にします。
Page 7
図 8 : デバッガ、イメージの設定
設定が済んで、「ダウンロードしてデバッグ」アイコンをクリックすると、「フラッシュメモリをプロ
グラム中です」のウィンドウが2回表示されます。これは正常な動作で、アプリケーションだけでなく
フラッシュローダも書き込まれていることを表わしています。次に、マクロファイルにより、プログラ
ムカウンタがブートローダのベクタテーブルのリセットアドレスに設定されます。ブートローダからシ
ングルステップでアプリケーションプロジェクトに入ることは、問題なくできます。
アプリケーションプロジェクトを経由して、2つのプロジェクトをダウンロードしたことを思い出して
ください。これは、ブートローダのソースファイルではなく、アプリケーションのソースファイルに直
接アクセスしていることを意味します。デバッグ中、ブートローダのソースファイルをクリックすると、
ビルド設定ないしプロジェクトを切り替えるかどうか聞かれます。これは、両方のプロジェクトのデバ
ッグをしたいのですから、好ましいことではありません。これを避けるには、ブートローダのコード
(main 関数)に到達するまでアセンブラのシングルステップで進むか、命令コードのところにブレークポ
イントを置きます。表示メニュー > ブレークポイントを開き、ウィンドウ上で右クリックし、新規ブ
レークポイントを選択し、新しい「コードブレークポイント」を追加します。
Page 8
図 9:コードブレークポイント
ブートローダ・プロジェクトの main の最初の部分はブートローダ・プロジェクトのマップ (.map)ファ
イル内で表示されますから、適切なブレークポイントを選択するのに役立ちます。これがうまくいくと
run アイコンをクリックするとブートローダのメイン関数のどこかでブレークすることができます。
「ブートローダをどう実装するか」の議論の範囲は広いのですが、デモンストレーションの目的で、一
番簡単なサンプルを作成しました。これは、入力の状態によらず、常にアプリケーションにジャンプし
ます。ジャンプは、アプリケーションのリセットハンドラを指す関数へのポインタを介して行われます。
この部分のコードは、以下に含まれます。
//in bootloader main.c
int main(void)
{
//jump to application via function pointer
int * address = (int *)0x08001004;
//アプリケーションのリセットハンドラへのポ
インタ
__set_MSP(*(int*)0x08001000);
//スタックポインタをアプリケーションのスタ
ックエリアに設定
*(int*)0xE000ED08 = 0x08001000;
// VTOR: ベクタテーブルをアプリケーション
のものに設定
((void (*)())(*address))();
// ポインタ関数としての再キャスト
while(1){ };
// アプリケーションは実行しない
}
ここは STM32F2xx の情報を取り始める部分です。ブートローダがアプリケーションにジャンプする前
に、ベクタテーブルを移動しなくてはなりません。現在のところ、ブートローダとデバイスはブートロ
ーダのベクタテーブルは永久に 0x08000000 番地にあり続けると信じています。ブートローダのコード
は、ベクタテーブルアドレスをアプリケーションが最初にリンクされた時の 0x08001000 番地にリセッ
トします。このことにより、アプリケーションのコードが正しく動き、ベクタテーブルも適切な位置に
セットされます。
Page 9
ここまでで道のりの半分で、これからメインアプリケーションに到達し正しく走らせることができるか
どうか検証する必要があります。アプリケーションの main 関数のどこかにブレークポイントを設定し
てあればそこでブレークし、LCD 表示を確認し、再度走らせることができます。実行アイコンをクリ
ックし、ブートローダがアプリケーションへ至るまでの走行をコントロールしているところを確認して
ください。
まとめると、ほとんどの基本的な種類のブートローダは実現可能です。ブートローダは常にアプリケー
ションにジャンプします。このプロジェクトは以下の 3 つことを例示・実証していますが、他の条件や
ユーザの入力によりもっと複雑なブートローダに拡張することができます。
1.
2.
3.
ブートローダの骨格の作り方。
ブートローダとアプリケーション・コードを統合し、ターゲットにダウンロードし同時にデバッグ
する方法。
実ハードウェア上で動きかつ、実用途向けに改造可能であること。
ブートローダは、フィールドでプログラムを書き換え可能にする有用なツールです。この記事を参考に
して、ご自身のブートローダを作成する際の参考にして頂ければ幸いです。以下のリンクは、この記事
で使用したプロジェクトファイルです。

Download application project (zip)