STM32F042でMbed OS 5 baremetal

LPC11U35に対してやったこととほぼ同じだが、若干違う部分もあるので書いておく。一番の違いはカスタムターゲットを定義しなくていいことに気づいたこと。

開発環境はMbed Studio。

手順

空のプロジェクトを用意する

Mbed Studioで「File」→「New Program...」→「Empty Mbed OS program」を選択して適当な名前をつけてプロジェクトを作る。

baremetalプロファイルに切り替える

以降ではプロジェクトのフォルダ(トップ階層)を「.」で表すことにする。例えば最初からあるmain.cppなら「./main.cpp」と書く。

./mbed_app.jsonを作り、以下のように編集。

{
    "requires": ["bare-metal"]
}

カスタムターゲットについて

LPC11U35のときはここでカスタムターゲットを作っていた。主な目的は

        "release_versions": ["5"],

という行を入れるためで、これがないとMbed Studioでビルドするときに「Mbed OS 5に対応していない」と怒られる。そこでわざわざ元とほぼ同じ内容のカスタムターゲットを作ってMbed OS 5に対応していることを宣言していた。それが上記の行だ。

しかし気づいたのだが、どうやらbaremetalプロファイルにするとrelease_versions"5"が含まれていなくてもちゃんとビルドしてくれるようだ。よって今回はカスタムターゲットを作らずに次に進む。

ソースコードを修正して差し替える

スタックポインタの初期値を表すINITIAL_SPというマクロがあるが、STM32F042用には定義されていないので、./mbed-os/targets/TARGET_STM/mbed_rtx.hを./TARGET_STMフォルダ(自分で作成)にコピーして42行目に次の2行を追加する。

#elif (defined(TARGET_STM32F042K6))
#define INITIAL_SP              (0x20001800UL)

また、./mbed-os/targets/TARGET_STM/TARGET_STM32F0/TARGET_NUCLEO_F042K6/device/us_ticker_data.hを./TARGET_STM/TARGET_NUCLEO_F042K6フォルダにコピーして24行目

#include "stm32f0xx_ll_tim.h":

となっているところを、最後のコロンを消して

#include "stm32f0xx_ll_tim.h"

にする。別にコロンがあってもエラーにはならないが警告が出てジャマなので対処しておく。

最後にコピー元のファイルを無効にするために./.mbedignoreを作り、以下のように編集。

mbed-os/targets/TARGET_STM/TARGET_STM32F0/TARGET_NUCLEO_F042K6/device/us_ticker_data.h
mbed-os/targets/TARGET_STM/mbed_rtx.h

コンフィグ情報を変更する

ここまででビルドは通るがthread_sleep_for()を実行するとエラーになるので、mbed_app.jsonを以下のように変更する。

{
    "requires": ["bare-metal"],
    "target_overrides": {
        "NUCLEO_F042K6": {
            "target.tickless-from-us-ticker": true
        }
    }
}

この例のようにAPIを使わないと出てこないエラーもあるので、他に判明したらここに情報を追加していこうと思う。

以上で作業は終了。STM32F042用のバイナリがビルドできるようになった。

ほかのプロジェクトでも使う

今回作成したファイルをそのまま別のプロジェクトのフォルダにコピーすれば、そのままビルドできる。

(余談)スタックサイズを調整する

Mbed Studioでビルドすると最後にRAMとFlashの使用量がレポートされるが、これまでの作業を行った状態で実際にプログラムをビルドしていると例えばこんな感じになる。

| Module              |       .text |  .data |      .bss |
|---------------------|-------------|--------|-----------|
| [lib]\libcppabi_p.l |      44(+0) |  0(+0) |     0(+0) |
| [lib]\mc_p.l        |    3240(+0) |  8(+0) |    40(+0) |
| [lib]\mf_p.l        |    1144(+0) |  0(+0) |     0(+0) |
| anon$$obj.o         |      32(+0) |  0(+0) | 4848(-64) |
| main.o              |    2008(+0) |  0(+0) |    60(+0) |
| mbed-os\drivers     |    447(+96) |  0(+0) |     0(+0) |
| mbed-os\hal         |   1948(+34) |  4(+0) |    66(+0) |
| mbed-os\platform    |  5708(+155) | 64(+0) |  301(+56) |
| mbed-os\targets     |    6135(+0) |  4(+0) |   332(+0) |
| Subtotals           | 20706(+285) | 80(+0) |  5647(-8) |
Total Static RAM memory (data + bss): 5727(-8) bytes
Total Flash memory (text + data): 20786(+285) bytes

よく見てみるとanon$$obj.oのRAM使用量がやたら多い。STM32F042は6KBしかRAMがないのに5KB近くも使っている。.mapファイルを調べてみると、そのうち4KBはスタック領域として使われている。Mbed OS 2のデフォルトのスタックサイズがそのまま使われているようだ(参考)。

これではすぐにRAMが尽きてしまうので、スタックサイズを調整する。./mbed_app.jsonを以下のように再編集する。

{
    "requires": ["bare-metal"],
    "target_overrides": {
        "NUCLEO_F042K6": {
            "target.boot-stack-size": "1024",
            "target.tickless-from-us-ticker": true
        }
    }
}

target.boot-stack-sizeを上書きすることでスタックサイズを変更できる。ここではとりあえず1KBにしてみた。再ビルドすると

| Module              |     .text |  .data |     .bss |
|---------------------|-----------|--------|----------|
| [lib]\libcppabi_p.l |    44(+0) |  0(+0) |    0(+0) |
| [lib]\mc_p.l        |  3240(+0) |  8(+0) |   40(+0) |
| [lib]\mf_p.l        |  1144(+0) |  0(+0) |    0(+0) |
| anon$$obj.o         |    32(+0) |  0(+0) | 4848(+0) |
| main.o              |  2008(+0) |  0(+0) |   60(+0) |
| mbed-os\drivers     |   447(+0) |  0(+0) |    0(+0) |
| mbed-os\hal         |  1948(+0) |  4(+0) |   66(+0) |
| mbed-os\platform    |  5708(+0) | 64(+0) |  301(+0) |
| mbed-os\targets     |  6135(+0) |  4(+0) |  332(+0) |
| Subtotals           | 20706(+0) | 80(+0) | 5647(+0) |
Total Static RAM memory (data + bss): 5727(+0) bytes
Total Flash memory (text + data): 20786(+0) bytes

…変わってない。.mapを見てみると

    0x20000450   0x00000ef0   Zero   RW            1    ARM_LIB_HEAP.bss    anon$$obj.o

減らした分は代わりにヒープにいったようだ。ちゃんと調整されてるのね。