Aitendoで買ったこのボードにSTM32Duino Bootloaderを導入すべく苦心したまとめ。またlibmapleコア(Github mainブランチ版)で使う前提です。見よう見まねで結果オーライという部分があり、確実な動作確認も取れているわけではないのであしからず。あくまでも参考程度でお願いします。
また、僕のメインの環境はMacなので、以下はmacOSの場合の方法です。Windowsの場合は試してはいませんが参考になる情報など調べた範囲で入れておきます。Linuxの場合はMacとだいたい同じかと。またターミナル(コマンドライン)の操作に慣れている前提です。
1. はじめに
通常Bootloaderは、プリビルドのバイナリが公開されている。
https://github.com/rogerclarkmelbourne/STM32duino-bootloader/
ボードのユーザーLEDのピン番号に合わせたものをダウンロードしてくる。
今回のターゲットとなるボード回路を見ると、
ピン番号は、PC6、PC7、PD13、PD6の4つである。しかしプリビルドのもので該当するものが無い。つまり自分でBootloaderをビルドする必要がある。今回はPC6を設定することにする。
またBootloaderには強制的にDFUモードに入る機能があります。その機能をユーザースイッチに割り当てることができます。Blue PillではPC14をプルアップして電源投入すると強制DFUモードになるというアレです。Blue Pillだとリセットスイッチしか無いので割り当てできませんが、ユーザースイッチが有るなら割り当てたほうが便利です。(割り当てたこのボタンは実行モード時は通常のユーザースイッチとして利用可能です)
回路図を見てみると、
PE5、PE4、PE3、PE2がユーザースイッチ。今回はPE5にこの機能を割り当ててみます。
またUSB周りの回路(USBシリアル回路で無い方)を見てみると
こんな感じ。Blue PillとかならD+/DPが抵抗を介して直接3V3か5Vにプルアップされているんだけど、この回路はPC13で制御できるようになっている。これはこのUSBをクライアント、ホスト(OTG)の両方で使えるようにということであろう。僕としては今のところはUSBシリアルポートとして使うことしか考えていないのでクライアントで使えれば良いので、トランジスタ外して短絡するとかいう手もある。あえて今回はこの回路を活かしたまま使えるようにしてみたいと思う。結果からいうとこの設定はBootloaderだけではなく、libmapleコア側のvariant(ボードの定義)側の修正も必要です。というのもBootloaderが動作しているときはPC13がプルアップされるのだけど、実行モードではその設定は引き継がれないので、USBポートが認識されなくなります。プログラムでPC13をHIGHにセットしてやれば実行モードでプログラムが実行されればUSBポートが認識されるようになるんだけど、毎回スケッチにそれを書くのは面倒です。なのでボードの定義で対応しておくのが良さそうです。
2. bootloaderのビルド
2-1. ソースの修正
ソースの編集はテキストエディタで行いました。
GithubからBootloaderのソースを一式ダウンロードしてきます。
https://github.com/rogerclarkmelbourne/STM32duino-bootloader/
cloneしても良いし、zipでまとめて落としてきても良い。適当なフォルダ内に置きます。
編集するのは、「config.h」と「Makefile」の2つ。テキストエディタでOK。
まずは「config.h」から。以下のソースを160行目くらい(PC13の設定のブロックの後というか、#elif defined TARGET_GENERIC_F103_PG15という行の前)に追加します。
#elif defined TARGET_GENERIC_F103_PC6 #define HAS_MAPLE_HARDWARE 1 #define LED_BANK GPIOC #define LED_PIN 6 #define LED_ON_STATE 1 // Button (if you have one) #define BUTTON_BANK GPIOE #define BUTTON_PIN 5 #define BUTTON_PRESSED_STATE 0 #define BOOTLOADER_WAIT 30 /* USB Disc Pin Setup. USB DISC is PC13 */ #define USB_DISC_BANK GPIOC #define USB_DISC_PIN 13
デバイスの定義なわけですが、HAS_MAPLE〜の行はひとまず飛ばしまして、LED_BANKからの3行がユーザーLEDの設定。PC6ピンは、BANKとしてはCの6番ということです。ON_STATEは、ピンの点灯がHIGH(1)なのかLOW(0)なのかの指定。今回の回路では”1″となる。
次のブロックがユーザースイッチの指定。 PE5というのはEバンクの6番ピンということです。PREESED_STATEは、スイッチが押されたときHIGH(1)なのかLOW(0)になるのかという指定。今回の回路の場合は、プルアップされててスイッチを押すとGNDに落ちるので”0″となる。
次のプロック(BOOTLOADER_WAIT)は、通常いらないようです。通常起動時DFUモードから抜けるのは数秒ですが、この指定で変えることができるようです。単位がいまいちわからないのですが、他のブロックで30としてたところがあったので30としました。通常は点滅6回でモードを抜けて、この指定だと30回かなと思うのですが…確証なし
最後のブロックがUSBのプルアップの指定。PC13ピンをセットするので、BANKはCでピンは13番ということですね。で、どうもこの指定だけではダメっぽくて、2行目の「HAS_MAPLE_HARDWARE」の指定がいるらしいのです。
次は「Makefile」の編集。拡張子がないけどテキストファイルなんでテキストエディタで編集できる。編集するのは2箇所。
【1箇所目】119行目の
generic-pc13: begin clean gccversion build_generic-pc13 sizeafter finished copy_generic-pc13 end
という行のあとに、
generic-pc6: begin clean gccversion build_generic-pc6 sizeafter finished copy_generic-pc6 end
を挿入します。ビルド処理の指定かしら。今回ビルドしたいgeneric-pc6のビルドでは、この順番でこの処理を行えという感じ?。どの設定も同じなんで書き換えてるだけです。
【2箇所目】元ファイルでは188行目、上の編集をした後では189行目くらいの
build_generic-pg15: TARGETFLAGS= -DTARGET_GENERIC_F103_PG15
の前に
build_generic-pc6: TARGETFLAGS= -DTARGET_GENERIC_F103_PC6 # Set the linker script build_generic-pc6: LDFLAGS +=-T$(ST_LIB)/c_only_md_high_density.ld build_generic-pc6: elf bin lss sym copy_generic-pc6: @echo @echo "Copying to binaries folder" @echo cp $(TARGET).bin bootloader_only_binaries/generic_boot20_pc6.bin @echo
を入れます。
これは、実際のビルドの指定ですかね。これも他の同じにしています。ビルドされるファイル名は、generic_boot20_pc.binとしました。bootloader_only_binariesというフォルダに作成されます。よく考えたらボード専用なんでgenericじゃないんですよね。
2-2. ビルド
やっとビルドします。ここはターミナル(コマンドライン)での作業です。ターミナルを開いて上記のMakefileのある位置まで移動しておきます。
コンパイラはArduino IDEにインストールされているものを使います。ボードマネージャーでArduino Dueを追加すればインストールされるはず。ARM用のコンパイラインストールしてるけどという場合でGCC4.8の場合はそれが使えますが、4.9以降の場合は使えないのでArduino IDEのものを使います。Arduino IDEのコンパイラへはパスが通っていないので、一時的にパスを通します。ターミナルで
$ export PATH=$PATH:/Users/<username>/Library/Arduino15/packages/arduino/tools/arm-none-eabi-gcc/4.8.3-2014q1/bin
と入れます。<usename>は環境に合わせて変えてください。それ以外はよほど変な設定を指定ない限りこのパスであってるハズ。ターミナルを閉じない限りこのパスは有効です。(ちなみにWinの場合はsetコマンドです。こことか参考になるも。) ただしくセットされても何も表示されないので不安ならば
$ export
としてやれば現在の設定状況が見れます。
でやっとMake(ビルド)します。ターミナルで
$ make generic-pc6
としてやれば、「bootloader_only_binaries」というフォルダの中に「generic_boot20_pc6.binbootloader」というファイルが作成される。もしエラーが出るようならソースの修正が間違っていると思うので見直すべし。
3. ボードの定義を追加する
既存の定義をコピーして必要なところを修正します。パスは標準的なインストール方法に従っている場合です。またターゲットはlibmapleコア(Arduino_STM32)です。Arduino IDEは終了させておきましょう。
/Users/<usename>/Documents/Arduino/hardware/Arduino_STM32/STM32F1/
以下にあるboard.txtを編集します。<username>はそれぞれのユーザー名が入ります。
これはボードの定義へのリンクやコンパイルオプション、転送方法などを定義しているファイルのようです。
board.txtの最後の行(####################)の前に以下を挿入します。テキストエディタでOK。
########################### aitendo STM32F103V ########################### aitendoSTM32F103V.name=aitendo STM32F103V series aitendoSTM32F103V.vid.0=0x1EAF aitendoSTM32F103V.pid.0=0x0004 aitendoSTM32F103V.build.variant=aitendo_stm32f103v aitendoSTM32F103V.build.vect=VECT_TAB_ADDR=0x8000000 aitendoSTM32F103V.build.core=maple aitendoSTM32F103V.build.board=AITENDO_STM32F103V aitendoSTM32F103V.upload.use_1200bps_touch=false aitendoSTM32F103V.upload.file_type=bin aitendoSTM32F103V.upload.auto_reset=true aitendoSTM32F103V.upload.tool=maple_upload aitendoSTM32F103V.upload.protocol=maple_dfu aitendoSTM32F103V.build.error_led_port=GPIOE aitendoSTM32F103V.build.error_led_pin=6 aitendoSTM32F103V.menu.device_variant.STM32F103VC=STM32F103VC aitendoSTM32F103V.menu.device_variant.STM32F103VC.build.cpu_flags=-DMCU_STM32F103VC aitendoSTM32F103V.menu.device_variant.STM32F103VC.upload.maximum_size=262144 aitendoSTM32F103V.menu.device_variant.STM32F103VC.upload.maximum_data_size=49152 aitendoSTM32F103V.menu.device_variant.STM32F103VC.build.ldscript=ld/stm32f103vc.ld aitendoSTM32F103V.menu.device_variant.STM32F103VD=STM32F103VD aitendoSTM32F103V.menu.device_variant.STM32F103VD.build.cpu_flags=-DMCU_STM32F103VD aitendoSTM32F103V.menu.device_variant.STM32F103VD.upload.maximum_size=393216 aitendoSTM32F103V.menu.device_variant.STM32F103VD.upload.maximum_data_size=65536 aitendoSTM32F103V.menu.device_variant.STM32F103VD.build.ldscript=ld/stm32f103vd.ld aitendoSTM32F103V.menu.device_variant.STM32F103VE=STM32F103VE aitendoSTM32F103V.menu.device_variant.STM32F103VE.build.cpu_flags=-DMCU_STM32F103VE aitendoSTM32F103V.menu.device_variant.STM32F103VE.upload.maximum_size=524288 aitendoSTM32F103V.menu.device_variant.STM32F103VE.upload.maximum_data_size=65536 aitendoSTM32F103V.menu.device_variant.STM32F103VE.build.ldscript=ld/stm32f103ve.ld #---------------------------- UPLOAD METHODS --------------------------- aitendoSTM32F103V.menu.upload_method.DFUUploadMethod=STM32duino bootloader aitendoSTM32F103V.menu.upload_method.DFUUploadMethod.upload.protocol=maple_dfu aitendoSTM32F103V.menu.upload_method.DFUUploadMethod.upload.tool=maple_upload aitendoSTM32F103V.menu.upload_method.DFUUploadMethod.build.upload_flags=-DSERIAL_USB -DGENERIC_BOOTLOADER aitendoSTM32F103V.menu.upload_method.DFUUploadMethod.build.vect=VECT_TAB_ADDR=0x8002000 aitendoSTM32F103V.menu.upload_method.DFUUploadMethod.build.ldscript=ld/stm32f103veDFU.ld aitendoSTM32F103V.menu.upload_method.DFUUploadMethod.upload.usbID=1EAF:0003 aitendoSTM32F103V.menu.upload_method.DFUUploadMethod.upload.altID=2 aitendoSTM32F103V.menu.upload_method.serialMethod=Serial aitendoSTM32F103V.menu.upload_method.serialMethod.upload.protocol=maple_serial aitendoSTM32F103V.menu.upload_method.serialMethod.upload.tool=serial_upload aitendoSTM32F103V.menu.upload_method.serialMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 aitendoSTM32F103V.menu.upload_method.STLinkMethod=STLink aitendoSTM32F103V.menu.upload_method.STLinkMethod.upload.protocol=STLink aitendoSTM32F103V.menu.upload_method.STLinkMethod.upload.tool=stlink_upload aitendoSTM32F103V.menu.upload_method.STLinkMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG=1 -DSERIAL_USB -DGENERIC_BOOTLOADER aitendoSTM32F103V.menu.upload_method.BMPMethod=BMP (Black Magic Probe) aitendoSTM32F103V.menu.upload_method.BMPMethod.upload.protocol=gdb_bmp aitendoSTM32F103V.menu.upload_method.BMPMethod.upload.tool=bmp_upload aitendoSTM32F103V.menu.upload_method.BMPMethod.build.upload_flags=-DCONFIG_MAPLE_MINI_NO_DISABLE_DEBUG #-- CPU Clock frequency aitendoSTM32F103V.menu.cpu_speed.speed_72mhz=72Mhz (Normal) aitendoSTM32F103V.menu.cpu_speed.speed_72mhz.build.f_cpu=72000000L aitendoSTM32F103V.menu.cpu_speed.speed_48mhz=48Mhz (Slow - with USB) aitendoSTM32F103V.menu.cpu_speed.speed_48mhz.build.f_cpu=48000000L aitendoSTM32F103V.menu.cpu_speed.speed_128mhz=Overclocked 128Mhz NO USB SERIAL. MANUAL RESET NEEDED TO UPLOAD aitendoSTM32F103V.menu.cpu_speed.speed_128mhz.build.f_cpu=128000000L #-- Optimizations aitendoSTM32F103V.menu.opt.osstd=Smallest (default) aitendoSTM32F103V.menu.opt.osstd.build.flags.optimize=-Os aitendoSTM32F103V.menu.opt.osstd.build.flags.ldspecs= aitendoSTM32F103V.menu.opt.oslto=Smallest Code with LTO aitendoSTM32F103V.menu.opt.oslto.build.flags.optimize=-Os -flto aitendoSTM32F103V.menu.opt.oslto.build.flags.ldspecs=-flto aitendoSTM32F103V.menu.opt.o1std=Fast (-O1) aitendoSTM32F103V.menu.opt.o1std.build.flags.optimize=-O1 aitendoSTM32F103V.menu.opt.o1std.build.flags.ldspecs= aitendoSTM32F103V.menu.opt.o1lto=Fast (-O1) with LTO aitendoSTM32F103V.menu.opt.o1lto.build.flags.optimize=-O1 -flto aitendoSTM32F103V.menu.opt.o1lto.build.flags.ldspecs=-flto aitendoSTM32F103V.menu.opt.o2std=Faster (-O2) aitendoSTM32F103V.menu.opt.o2std.build.flags.optimize=-O2 aitendoSTM32F103V.menu.opt.o2std.build.flags.ldspecs= aitendoSTM32F103V.menu.opt.o2lto=Faster (-O2) with LTO aitendoSTM32F103V.menu.opt.o2lto.build.flags.optimize=-O2 -flto aitendoSTM32F103V.menu.opt.o2lto.build.flags.ldspecs=-flto aitendoSTM32F103V.menu.opt.o3std=Fastest (-O3) aitendoSTM32F103V.menu.opt.o3std.build.flags.optimize=-O3 aitendoSTM32F103V.menu.opt.o3std.build.flags.ldspecs= aitendoSTM32F103V.menu.opt.o3lto=Fastest (-O3) with LTO aitendoSTM32F103V.menu.opt.o3lto.build.flags.optimize=-O3 -flto aitendoSTM32F103V.menu.opt.ogstd=Debug (-g) aitendoSTM32F103V.menu.opt.o3lto.build.flags.ldspecs=-flto aitendoSTM32F103V.menu.opt.ogstd.build.flags.optimize=-Og aitendoSTM32F103V.menu.opt.ogstd.build.flags.ldspecs=
これは、generic STM32F103Vの内容のgenericをaitendoに変えただけです。これはSTM32F103VC、STM32F103VD、STM32F103VEの3種類のMCUに対応しており、今回必要なのはVEのみなのですが、面倒なのでそのままにしています。VCとVDのブロックを消せば表示されなくなると思いますが。
次に実際のボードの定義を編集します。
/Users//Documents/Arduino/hardware/Arduino_STM32/STM32F1/variants/
以下の「generic_stm32f103v」というフォルダをコピーして「aitendo_stm32f103v」とします。はそれぞれのユーザー名が入ります。
中の「board」というフォルダの中のboard.hというファイルを修正します。
35行目くらいの、
#ifndef _BOARDS_GENERIC_STM32F103V_H_ #define _BOARDS_GENERIC_STM32F103V_H_
を
#ifndef _BOARDS_AITENDO_STM32F103V_H_ #define _BOARDS_AITENDO_STM32F103V_H_
とします。
次に109-110行目の編集です。
#define BOARD_USB_DISC_DEV GPIOC #define BOARD_USB_DISC_BIT 12
を
#define BOARD_USB_DISC_DEV GPIOC #define BOARD_USB_DISC_BIT 13
とします。これがUSBのプルアップのピンの設定ですね。おそらく自動的にプログラム実行時にプルアップするという設定かと。
オプションとして、44行目からの
#define BOARD_BUTTON_PIN PC0 #define BOARD_BUTTON_PIN2 PD12 #define BOARD_LED_PIN PE5 #define BOARD_LED_PIN2 PE6
を
#define BOARD_BUTTON_PIN PE5 #define BOARD_BUTTON_PIN2 PE4 #define BOARD_BUTTON_PIN3 PE3 #define BOARD_BUTTON_PIN4 PE2 #define BOARD_LED_PIN PC6 #define BOARD_LED_PIN2 PC7 #define BOARD_LED_PIN3 PD13 #define BOARD_LED_PIN4 PD6
としておきましょうか。ユーザーLEDとユーザースイッチの定義です。Arduinoの標準の形式だと、LEDは、”LED_BUILTIN” です。1つ上の階層のファイル「variant.h」の14行目くらいに、
static const uint8_t LED_BUILTIN = BOARD_LED_PIN; static const uint8_t LED_BUILTIN2 = BOARD_LED_PIN2; static const uint8_t LED_BUILTIN3 = BOARD_LED_PIN3; static const uint8_t LED_BUILTIN4 = BOARD_LED_PIN4;
としておきましょう。これで標準的な書き方ができるようになります。
その他、このボード用にピンアサインを追加修正したほうが良いかもしれませんが、ひとまず今回はここまでとします。
これでBootloaderを本体に書き込んで、Arduino IDEからaitendo STM32F103Vを選べば使える用意になると思います。
bootloaderの書き込みとかはまた別記事にしたいと思います。
コメントを残す