STM32のTips (Flash関係)

開発環境はIARのEWARMです。

binファイルの生成

デフォルトではプロジェクトをビルドするとoutファイルが生成されます。outファイルからbinファイル(バイナリイメージ)を生成するには、プロジェクトの[オプション]の[出力コンバータ]にて、[追加出力ファイルを生成]にチェックし、[出力フォーマット]を[ローバイナリ]に設定します。

図

Flashの特定アドレスに定数を配置

(1) ソースコードでpragma指定

pragmaでセクション名を指定します。
また、コードから参照されない場合には強制配置のため __root を指定します。

#pragma location = "ConstSection"
__root const char HOGE[16] = "PIYO";
(2) リンカ設定ファイルでアドレス指定

リンカ設定ファイル(拡張子.icf)で、セクションのアドレスを指定します。

place at address mem:0x0807FFF0 { readonly section ConstSection };

Flashの特定アドレスにバイナリファイルのデータを配置

(1) プロジェクトのオプションでセクションとファイルを指定

プロジェクトの[オプション]の[リンカ]の[入力]にて、

  • [シンボルをキープ]に適当なシンボル名 (セクションと同名でOK)
  • [ローバイナリイメージ]にファイル名、シンボル名、セクション名、アラインメントを指定

図

(2) 2個以上のバイナリファイルを用いるとき

上記では、シンボル名は複数定義できますが、バイナリファイルは1つしか指定できません。2個以上のバイナリファイルを用いるときは、[シンボルをキープ]でのシンボル名定義に加え、プロジェクトの[オプション]の[リンカ]の[追加オプション]にて、次のように指定します。

--image_input=ファイル名,シンボル名,.セクション名, アラインメント

図

(3) リンカ設定ファイルでアドレス指定

リンカ設定ファイル(拡張子.icf)で、セクションのアドレスを指定します。

place at address mem:0x08080000 { section .RESOURCE };
place at address mem:0x08100000 { section .RESOURCE2 };

ブートローダーを作る

(1) メモリマップを決める

例えばここでは次のように決めます。

  • マイコンFlashサイズは1Mバイト (0x08000000〜0x080FFFFF)
  • 先頭64kバイトにブートローダを置く (0x08000000〜0x0800FFFF)
  • その後にユーザーアプリケーションを置く (0x08010000〜0x080FFFFF)

Flashのセクタ境界で領域を分けるようにします。セクタのサイズはマイコンの型番によって異なるのでデータシートで確認してください。

(2) ブートローダーのコード

ブートローダーは、起動直後になんらかの条件(シリアル受信がある、特定のピンのレベル、など)で、なんらかの手段(シリアル受信、SDカード、など)でFlashのユーザーアプリケーション領域を書き換えます。そして、処理をユーザーアプリケーションに切り替えます。

int main(void)
{
    if(なんらかの条件)
    {
        なんらかの手段でFlashを書き換える
    }

    /***** ユーザーアプリケーションにジャンプ *****/

    //アプリケーションのリセットハンドラ
    int * user_app = (int *)(0x08010000+ 0x04);
    //アプリケーションのスタックエリアをスタックポインタに設定
    __set_MSP(*(int*)(0x08010000+ 0x00));
    //アプリケーションのベクタテーブルをベクタテーブルオフセットレジスタに設定
    *(int*)0xE000ED08 = 0x08010000;
    //アプリケーションを起動
    ((void (*)())(*user_app))();
    
    while(1){ };
}
(3) アプリケーションのコード

main関数の最初におまじないを1行加えます。

int main(void)
{
    // ベクタテーブルのアドレスを変更
    // (IARのスタートアップルーチンが初期化してしまうためここで再設定)
    *(int*)0xE000ED08 = 0x08010000;
    
    以下略
}
(4) ブートローダのリンカ設定ファイル

Flashの開始アドレスと終了アドレス、およびベクタテーブルのアドレスを指定します。

/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08000000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__     = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__       = 0x0800FFFF;
(5) アプリケーションのリンカ設定ファイル

Flashの開始アドレスと終了アドレス、およびベクタテーブルのアドレスを指定します。

/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x08010000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__     = 0x08010000;
define symbol __ICFEDIT_region_ROM_end__       = 0x0807FFFF;