はじまり なんとTIが無料のARM用 Clang/LLVMコンパイラの提供をはじめた様です。 情報がほとんどないので結構最近のことでしょうか。 Arm(R) コード生成ツール:コンパイラ 上記ページの「ARM-CGT-CLANG-1」というのがそうです。 コンパイルからリンクまで全部Clang/LLVMで完結するタイプです。(gcc不要) ただのコンパイラなのでTI以外のマイコンでも当然使えるはずです。(^^; リンクサイズ制限などの記述も今のところない感じです。 MDK-Armと同様にTIもそれまでの自社製コンパイラを捨ててClang/LLVMに乗り換えた。。。 というのが、ここまでの遭遇結果。xD 特徴:(2020/12 現在) (1) ダウンロードとインストールに一切 登録不要。 最近では劇的に好印象! (2) コマンドラインツール。 (3) Windows 64bit, MacOS, Linuxのインストーラ付き。 (4) ライブラリは浮動小数点あり、なしのマルチlib構成。 (5) 標準ライブラリはTI謹製のソースコード付きライブラリ。(軽量かどうかは不明) newlib-nanoに相当する軽量版はない様だ。 (6) 対応マイコン: Cortex-m0(+) Cortex-m3,m4 Cortex-R4,R5 https://software-dl.ti.com/codegen/docs/tiarmclang/rel1_0_0_sts/tiarmclang_ug/tiarmclang-portfolio/getting_started_guide/supported_arm_processors.html (7) ターゲットが決まっているので、--target=[TRIPLE] 指定が不要。 (8) コマンド名が「clang」ではなく、 tiarmclang の様にtiarm+[コマンド名]という見慣れない表記。 本家版と混乱しない様にしてある。 (9) インストール容量が160MBと、非常に軽量で好印象。 (gcc-armは 670MB) TIのマイコン持ってないけど、違うマイコンでちょっとお試しで使ってみようと思います。(^^;
2020年12月08日
Clang/LLVM: ARM 無料のTI製 Clangコンパイラのメモ 2020/12
2020年12月05日
STM32をClang/LLVMでコンパイルした時のメモ 2020/12
はじまり Clang/LLVMを使ったARMマイコン(主にSTM32)のコンパイルは、かなり前からできることは知っていたが、 今回初めてトライしたところ意外と迷走してしまったのでメモ。 経緯 Clang/LLVMがARMマイコンで使えると知ってから何年も経つので Windows上でインストールからコンパイルまでアッという間にできるかと思ったら、 ネット上にほとんど情報(注1)がなくて悶絶しました。orz armclang 商用で有料のMDK ARMは、v6.0からそれまでのコンパイラ(armcc)を捨ててClang/LLVMに移行(注2)した様です。 それほどメリットがあるというこでしょうか。でかすね。:D (注5) 最近使ってないmbed系のコンパイラもarmclang(Clang/LLVM)になっているみたい。 実は簡単にコンパイルできた。orz orz 迷走から脱出するきっかけとなったページ https://github.com/RIOT-OS/RIOT/issues/8356 「簡単な対策はリンク時もgccを使うんだよ」の記述。この一文がキモでした。 RTOSのRIOTもそのうち試してみよう。 結構迷走しましたが、 分かってしまえば、かなり簡単にコンパイルできてしまいしました。 「これを 最初に教えてくれよ!」って感じです。 xD (注0) Clang/LLVM コンパイルとリンクの概要 これを先に分かっておくと楽。 現状(2020/12)、Clang/LLVMは組み込みARM(eabi)用のコンパイル済みC(++)言語用 標準ライブラリ群+α(注3)を持っていない。 従ってそれらは、 (1) arm-none-eabi-*ツール群に付属のライブラリをリンクして使う。 (2) C(++)言語ソースのコンパイル時に限り「clang(++)」を使い、 あと(アセンブル(*.s)、リンク、bin/hex/lstファイルの生成)は全部arm-none-eabi-*ツール群に任せる。(注6) (3) 上記 arm-none-eabi-*ツール群のライブラリを使うために、clangに「ライブラリのヘッダファイル」の場所を教える必要がある。 (4) clangを使う時は必ずオプションに「--target=arm-none-eabi」を加える。 ただし、このオプションをarm-none-eabi-*ツール群に加えるとエラーで落ちるので注意(以下の-Ozもエラーになる)。 その他: (a) 最適化オプションは -Ozを指定。 gccの-Osよりもサイズが小さくなるとか、ならないとか。:D らしい。 (b) enumの取扱いがgccと異なるので「-fshort-enums」で合わせておく。(注4) まとめ STM32CubeMXが吐き出したC言語ソースと「Makefile」を使ってコンパイルします。 Makefileの改変部分は以下の様になる。 ざっくり言うと、コンパイラをclangに替えた以外はほぼ無変更+α 程度でいける。と覚える。xD
Make変数 | Clang/LLVMを使う時 | arm-none-eabi-*を使う時 | |
コンパイラ | CC = | clang | arm-none-eabi-gcc |
リンカ | LD = | 同右, arm-none-eabi-gccを使う (CCをLDに変更) | リンカはCCで代用(本来LDは未定義) |
アセンブラ | AS = | 同右 or (clang -x assembler-with-cpp) | arm-none-eabi-gcc -x assembler-with-cpp |
binutils | CP = | 同右 or (llvm-objcopy) | arm-none-eabi-objcopy |
binutils | SZ = | 同右 or (llvm-size) | arm-none-eabi-size |
追加オプション | CFLAGS += | --target=arm-none-eabi -Oz -fshort-enums | - |
追加オプション | C_INCLUDES += | ライブラリヘッダの場所を指定 | - |
PREFIX = arm-none-eabi- ARM_GNU_CC = $(PREFIX)gcc ARM_CORTEXM_SYSROOT = $(shell $(ARM_GNU_CC) $(MCU) -print-sysroot 2>&1) C_INCLUDES += -I$(subst \,/,$(ARM_CORTEXM_SYSROOT))/includeC_INCLUDESがgccライブラリのヘッダファイル・パスなのでこれをコンパイル時に加える。 絶対パス指定の時は、 C_INCLUDES += -Ic:/[arm-gcc]/arm-none-eabi/include [arm-gcc]はarm-none-ebai-*ツールのトップフォルダ。 Linux/Debian(buster)32bit では絶対パス指定: Debian上のarm-none-eabi-gcc(gcc-arm-none-eabi)だと「-print-sysroot」が使えないので ヘッダファイル指定は絶対パスとしました。以下の3つを指定した。 というか、指定しないとエラーになった。orz C_INCLUDES += -I/usr/lib/gcc/arm-none-eabi-gcc/7.3.1/include C_INCLUDES += -I/usr/include C_INCLUDES += -I/usr/include/i386-linux-gnu Clang/LLVMのインストール(v11.0.0) !?: Clang/LLVMはWindowsパソコン用のものを使います。 以下の話はARMマイコンのコンパイルだけに使う(PC用のコンパイルはしない)なら気にしなくて良いものの PC上でもそれなり使える様にしたメモです。 Clang/LLVMのダウンロードは本家のこれがそうですが、これは無視します。(オイ というのも結局単独では完結しなくて * Visual Studio C++ツールが必要とか、 * MinGWのgccがデフォルトの場所にインストールされていることが必要とか、 デフォルトの場所ってどこよ ? c:/MinGW/らしいんだけど、なにそれ? 状態。 この場所にMinGWのgccがあることが前提条件。え? そこにはないし、 そこにインストールする単独のMinGW/gccってどこ? 終了。。。 orz 自分の場合: 利用中のMsys2/MinGWのgccがあるからいいやと思って 本家のClang/LLVMをインストールしてみたら、 迷走しました。orz 結局使えたものの、デフォルトの場所にMinGW/gccがないと面倒くさいことになるのであきらめました。 Msys2/MinGWでインストール OK 楽ちん: 自分の場合、前提条件はMsys2/MinGWです。 pacmanを使ってMinGW/gccはインストール済みなのでClang/LLVMは以下でインストール終了しました。 $ pacman -S mingw-w64-i686-clang mingw-w64-i686-lld mingw-w64-i686-lldb 64bit版は、 $ pacman -S mingw-w64-x86_64-clang mingw-w64-x86_64-lld mingw-w64-x86_64-lldb Clang/LLVMは最新版のv11.0.0がインストールされました。 さ、最初にこれに気づけば。。。 orz orz ちみにgccはこれ mingw-w64-i686-gcc 32bit版 mingw-w64-x86_64-gcc 64bit版 Clang/LLVMのインストールサイズの違い: 本家版: 約1.4GB MinGW版: 約0.85GB 詳細不明なものの恐らくMinGW版はVisual Studioツール系が手薄なのかも。 Clang/LLVM: NUCLEO-F411RE コンパイル サンプルプロジェクト for STM32CubeMX (Makefile) Clang/arm-none-eabi-*ツール群に実行パスが通っていることが前提です。 トップフォルダにあるMakefileで $ make とすればデフォルトでClang/LLVMでコンパイルします。 $ make TOOLCHAIN= なら(TOOLCHAINには何も指定しない) arm-none-eabi-gccでコンパイルします。 ダウンロード: stm32f411cube_v1.1-2020012.7z old: stm32f411cube_v1.0-2020012.7z 標準ライブラリ(newlib-nano)のprintfを使うにはSrc/main.cの「xprintf(...);」を printfに変えればOK。
c:\stm32f411cube_v1.1-2020012> make mkdir build Compiling : clang : Src/main.c Compiling : clang : Src/gpio.c Compiling : clang : Src/stm32f4xx_it.c Compiling : clang : Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_gpio.c Compiling : clang : Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rcc.c Compiling : clang : Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_utils.c Compiling : clang : Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_exti.c Compiling : clang : Src/system_stm32f4xx.c Compiling : clang : Src/usart.c Compiling : clang : Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usart.c Compiling : clang : Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma.c Compiling : clang : lib/xprintf/xprintf.c Compiling : clang : Src/syscalls.c Assembling: arm-none-eabi-gcc -x assembler-with-cpp : startup_stm32f411xe.s Linking : arm-none-eabi-gcc : build/stm32f411cube.elf text data bss dec hex filename 3900 12 36 3948 f6c build/stm32f411cube.elf
c:\stm32f411cube_v1.1-2020012> make TOOLCHAIN= mkdir build Compiling : arm-none-eabi-gcc : Src/main.c Compiling : arm-none-eabi-gcc : Src/gpio.c Compiling : arm-none-eabi-gcc : Src/stm32f4xx_it.c Compiling : arm-none-eabi-gcc : Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_gpio.c Compiling : arm-none-eabi-gcc : Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_rcc.c Compiling : arm-none-eabi-gcc : Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_utils.c Compiling : arm-none-eabi-gcc : Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_exti.c Compiling : arm-none-eabi-gcc : Src/system_stm32f4xx.c Compiling : arm-none-eabi-gcc : Src/usart.c Compiling : arm-none-eabi-gcc : Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usart.c Compiling : arm-none-eabi-gcc : Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_dma.c Compiling : arm-none-eabi-gcc : lib/xprintf/xprintf.c Compiling : arm-none-eabi-gcc : Src/syscalls.c Assembling: arm-none-eabi-gcc -x assembler-with-cpp : startup_stm32f411xe.s Linking : arm-none-eabi-gcc : build/stm32f411cube.elf text data bss dec hex filename 3896 12 36 3944 f68 build/stm32f411cube.elfC言語の標準ライブラリを使わない場合のメモ 上はlibc.a系(標準ライブラリ)を使う前提の話で、もしそれらを使わない場合、 (1) 標準ライブラリ未使用なのでヘッダファイル指定もいらない? (2) 従って、arm-none-eabi-*ツールも不要? (3) リンクもclang(ld.lld)で可能? リンク自体はもともと「--target=arm-none-eabi」を指定すれば 上の方に書いたやり方でも可能かも。ダメでした。orz という話になるんだけど、ググって迷走中だった時の情報によると、 なぜかgccに固有のライブラリ「libgcc.a」(マクロ関数等々)が必要らしい。 clangがgccと互換を保つために「libgcc.a」内の関数と同じ名前の関数呼び出しを吐き出す様だ。 それと同等のものをClangで作れば完全に縁が切れる風な話が恐らくこれ。 https://interrupt.memfault.com/blog/arm-cortexm-with-llvm-clang#cross-compiling-with-clang libclang_rt.builtins.*.a という名前のものを作るらしい。 結局、作るならマルチlibにしないといけないので、やっぱり面倒くさそう感はある。 $ arm-none-eabi-gcc $(MCU) $(CFLAGS) -print-libgcc-file-name でlibgccのフルネームが分かるらしい。 これも参考 Armv6-m, Armv7-m and Armv7E-M targets https://www.derhaeg.be/doc/llvm8/HowToCrossCompileBuiltinsOnArm.html#armv6-m-armv7-m-and-armv7e-m-targets Compiler_rt: libgcc相当のソースコードはこれの様です。 https://github.com/llvm-mirror/compiler-rt/tree/master/lib/builtins 各種IDEで使う 試してないものの、上述の様にIDE上の設定にclangを指定すれば使えると思う。 ベアメタルARMをClangで使うページ: これらのページに最初にたどりつけばよかったのに。orz * 6年前(2014年)の記事だけど、ここにエッセンスが凝縮されていた。orz ARM Bare Metal Hello World: Comparing LLVM & ARM-GCC * Interface 2015年3月号 知らないとカッコ悪い!ARM用GCC&LLVM初体験 高性能でフリー!新時代コンパイラ入門 このPDFの図1にもgccツールを使えとちゃんと書いてあった。orz その他 AVRで試してみたメモ: clang + avr-gccも同様に簡単にコンパイルできるハズと思ってやってみたが、 以下の3つの問題に遭遇して現状では諦めました。 (1) PROGMEM,PSTR問題 AVR固有の仕様。 PROGMEMは以下の様な感じで置き換え可能だが、PSTRは難しそう。 #undef PROGMEM #define PROGMEM addrspace(1) 既存プログラムの書き換えは必至。 (2) libgcc.a問題 Armのlibgcc.aとは内容や関数名が違って、ここで未定義エラーが出る。 リンク時に最大で以下の4つの関数未定義エラーが出る。 https://github.com/avr-rust/rust-legacy-fork/issues/149 __ashlsi3 __lshrsi3 __divmodti4 __ashrsi3 avr-rustプロジェクトが上記関数をrust言語で書いたのを参考にC言語で 書き直せばひとまずOK. (3) 割り込み関数 定義問題 以下のアトリビュートに対応済みなはずだけどエラーになる。orz 無理にやるとclangがクラッシュした。orz orz __attribute__((interrupt)) avr-rustプロジェクトを参考にするしかないのかも。 (注0) 以下arm-none-eabi-gccをgccと書いたり、いろいろざっくりgccと書いたりします。:-) (注1) 簡単に分かる解説。日本語、英語含めて。 (注2) 5年くらい前? (注3) gccコンパイラ固有のlibgcc.a 。 (注4) arm-none-eabi-* のライブラリ群がこのオプションでコンパイルされている前提なんだけど、未確認。(^^; (注5) 巨大なメリットがあるならもっと情報が溢れていてもいいはず。。。 (注6) リンカ以外はClang/LLVMツールを使う手も可能。ここでは省略。
2020年11月14日
STM32: libopencm3に入門した時のメモ 2020/11
- はじまり
- 少し前にSTM32CubeMXが「64bit PC専用版のVer6.0」に勝手に更新されてしまって、
家の32bit PCだと動作不能に陥いってしまった。orz orz orz (注2)
慌てて代用品を探して思い出したのが、
libopencm3
- かなり前から極まれに検索にひっかかっていたのは気づいていたが、(注3)
STM32CubeMXがあるので無視していたのだった。
- 少し前にSTM32CubeMXが「64bit PC専用版のVer6.0」に勝手に更新されてしまって、
家の32bit PCだと動作不能に陥いってしまった。orz orz orz (注2)
- libopencm3とは
- ARM Cortex-M系 マイコン用の超軽量低機能なペリフェラルライブラリである。
- 対応するマイコンは以下。
- ST STM32 F0xx/F1xx/F2xx/F30x/F37x/F4xx/F7xx/H7xx series
- ST STM32 G0xx G4xx L0xx L1xx L4xx series
- Atmel SAM3A/3N/3S/3U/3X series, as well as SAMDxx and friends
- NXP LPC1311/13/17/42/43
- Stellaris LM3S series (discontinued, without replacement)
- TI (Tiva) LM4F series (continuing as TM4F, pin and peripheral compatible)
- EFM32 Gecko series (only core support)
- Freescale Vybrid VF6xx
- Qorvo (formerly ActiveSemi) PAC55XX
- Synwit SWM050
- 少し使ってみたので 以下気づいた点を列挙する。
- ダウンロードするのにメールアドレス不要でログインしなくても良い :-)
- libopencm3は細々とメンテナンスされている。
- レジスタ直打ちしなくていい様な必要最低限のライブラリ群
- 対応マイコンはSTM32系が優勢の様だ。
- 最近のSTM32G0シリーズにも対応している風。
- Cortex-M4F以降のマイコンはハードウェア浮動小数がデフォルトでON状態。
- リンカスクリプトはpythonで自動生成されて手間いらず。
- スタートアップコードもリセットベクタ系も自動リンクされて手間いらず。
- HTMLドキュメントはSTM32F4用しかないが非常に見やすく好印象。
- exampleプロジェクト を見ればPLL,SYSTICK,USART,GPIO,DMA,USB,ADC,I2C等の初期設定はほぼ分かる。
-
単純なライブラリなのでコンパイルオプションCFLAGSに以下の3つを加えるだけで使える。
(ライブラリのコンパイルは必要) -
CFLAGS += -lopencm3_stm32f0 // ライブラリ名 CFLAGS += -Llibopencm3/lib // ライブラリの場所 CFLAGS += -Ilibopencm3/include // インクルードパス
-
STM32 HALライブラリ >> STM32 LLライブラリ > libopencm3ライブラリ > レジスタ直打ち
低機能ライブラリなおかげでサイズが極小なので、最近 秋月電子に出現した
FLASH 16KB, SRAM 2KBのSTM32L010F4P6 あたりに丁度良いかも。
ちなみにFLASH 16KBでHALライブラリだと恐らくペリフェラルの初期化と割込み処理のラッパーだけでFLASH容量が終了します。(^^; (注4)
そのためのLLライブラリだけど、さらに4割程度小さい感じ。(注4)
- git (ライブラリ取得時のみ): git for windows
- arm-gcc: arm-none-eabi-gcc
- python: リンカスクリプトを自動生成するために必要。 python3.x
- gnu tools for windows: git付属のツールで代用する。
- make.exe: https://sourceforge.net/projects/ezwinports/files/ https://sourceforge.net/projects/ezwinports/files/make-4.3-without-guile-w32-bin.zip/download
上記のツール群をインストールしたフォルダに実行パスを通します。(注5)
例:setenv.bat (上記以外のパスは無視する設定例)
例:setenv.bat (上記以外のパスは無視する設定例)
@echo off set vPy=386 path=D:\Git\bin set path=%path%;D:\Git\usr\bin set path=%path%;D:\Python%vPy% set path=%path%;D:\Python%vPy%\Scripts set path=%path%;C:\arm-gcc\bin set path=%path%;C:\make\bin echo %path%MS-DOSコマンドラインを開いてトップフォルダにある上記「setenv.bat」を実行すれば準備は終了。
以下は、自分用に作った便利サンプルプロジェクトの説明。
MS-DOSコマンドラインを適当な作業フォルダで開いて、生成物:
first_libopencm3/lib/libopencm3/lib の中に
次に、make
と打てば全てのサンプルコードがコンパイルされます。
個別コンパイルする時は、例えば
Makefileは、
上記 DEVICE変数にマイコン名をフルネームで指定すると、自動でリンカスクリプトを生成します。(注1)
この場合「generated.stm32f411ret6.ld」というリンカスクリプトが生成されます
デモフォルダ:
特定ターゲットのライブラリだけをコンパイルする方法
以下はトップレベルのMakefileから抜粋したもので、libopencm3をコンパイルする時のオプション。
ライブラリのHTMLドキュメントを生成する時も同様に、
ちなみに、HTMLドキュメントを生成するにはmsys2上で少なくとも、
ライブラリのHTMLドキュメントについて
割り込みハンドラの名前
MS-DOSコマンドラインを適当な作業フォルダで開いて、
> git clone --recurse-submodules https://github.com/dinau/first_libopencm3.git > cd first_libopencm3 > make libと打つとgitのリポジトリからlibopencm3をダウンロードしてきて STM32F0/L1/F3/F4それぞれのライブラリのみコンパイルされます。(最適化は「-Os」)
- libopencm3_stm32f0.a
- libopencm3_stm32l1.a
- libopencm3_stm32f3.a
- libopencm3_stm32f4.a
> cd nucleo_f411re\ledblink
> make
CC main_src.c
CC ../hardware.c
CC ../../lib/TSoftPwm.c
CC ../../lib/disp_info.c
CC ../../lib/hardware_common.c
CC ../../lib/systick.c
CC ../../lib/xprintf/xprintf.c
GENLNK stm32f411ret6
LD .BUILD/ledblink_STM32F411.elf
OBJCOPY .BUILD/ledblink_STM32F411.bin
text data bss dec hex filename
2312 12 8 2332 91c .BUILD/ledblink_STM32F411.elf
PROJECT = ledblink_$(DEV_NAME)
CFLAGS += -DSYSTEM_CLOCK=84000000
CFLAGS += -DUSART_BAUDRATE=115200
SHARED_DIR = . .. ../../lib ../../lib/xprintf
LIB_CSRC += $(wildcard ../../lib/*.c)
LIB_CSRC += $(wildcard ../../lib/xprintf/*.c)
CSRC += $(wildcard *.c) $(wildcard ../*.c)
CFILES += $(notdir $(CSRC)) $(notdir $(LIB_CSRC))
#AFILES +=
# TODO - you will need to edit these two lines!
DEVICE = stm32f411ret6
DEV_NAME = STM32F411
#OOCD_FILE = board/stm32f4discovery.cfg
include ../../common.mk
- 対応するマイコンボードは、
- Nucleo-F411RE
- Nucleo-L152RE
- STM32F0Discovery
- STM32F3Discovery
- ledblink: LEDチカチカ
- softpwm: ソフトPWMでLEDホアンホアン
- freertos: FreeRTOSでLED点滅タスクとペリフェラルレジスタ値をUARTで表示するタスク。
TARGET_MCU = "stm32/f0 stm32/l1 stm32/f4 stm32/f3" # コンパイル対象のライブラリは必要なものだけ OPTIMIZE = -Os # 最適化はサイズ優先 LIBOPENCM3 = lib/libopencm3 # ライブラリがある場所 # libopencm3ライブラリをコンパイル $(MAKE) -C $(LIBOPENCM3) TARGETS=$(TARGET_MCU) CFLAGS=$(OPTIMIZE)
> cd lib/libopencm3
> make doc TARGETS="stm32/f4 stm32/f0"
等とする。
"TARGETS=..."がなければ全てのマイコンが対象となり膨大な時間がかかる。
- doxygen
- graphviz
$ pacman -S doxygen mingw-w64-i686-graphvizが必要。後は忘れました。:-)
- まともなドキュメントがあるのはSTM32F4用だけですが、
- 差異部分を除けばSTM32マイコンは、ほぼ共通なので十分使えると思います。
- 差異部分はソースコード見るしかないですが。。。
- Armコアの割り込みハンドラ名はSTM32CubeMXとは違っていてハマリがち。
- 以下は、FreeRTOSで使う時の設定(FreeRTOSConfig.h)
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS standard names - or at least those used in the unmodified vector table. */ #define vPortSVCHandler sv_call_handler // SVC_Handler #define xPortPendSVHandler pend_sv_handler // PendSV_Handler #define xPortSysTickHandler sys_tick_handler // SysTick_Handler // cf: libopencm3\lib\cm3\vector.c
上の緑の部分がlibopencm3での割込み定義名。
- (注1) libopencm3が持つ機能。
- (注2) その後、古いバージョンが取得可能なことに気づいたので事なきを得た。
- ちなみに、32bitでまともに動くのはVer.5.6.0まで。
- (注3) 以前は libopenstm32だったらしい。
- (注4) 個人の感想です。 :-)
- (注5) msys2系使用中なら不要かも
- (注6) nvic.h や特定のファイル・フォルダはlibopencm3をビルドしないと生成されない。
2020年10月18日
STM32: Flash書き込み時にマイコンを判別してから書込む方法 2020/10
経緯: 事件発生、 (1) Nucleo-F030R8ボードにNucleo-F411REのHEXファイルを誤って書き込んで、 Nucleo-F030R8ボードを壊した。orz (2) そのすぐ後にSTM32VLDiscoveryボードに今度は恐らくNucleo-F030R8のHEXファイルを 誤って書き込んで、 STM32VLDiscoveryボードを壊した。 orz 原因: Makefile中に以下のターゲットを作ってw: all st-link_cli.exe -c SWD -P $(TARGET).hex -Rst> make w で、お気楽極楽にコンパイルと書き込みを行っていたのが原因。 Nucleoボードでは、さらに、w: all cp $(TARGET).bin /dの様にドライブへのコピーだけで書けてしまう。こっちも同様に危険。 対策: st-link_cli.exeのオプションを見ても 「マイコンの品種(family)をチェックして違っていたら書き込まない」 というのが見つからなかったのでMakefile中にチェック機構を追加することにした。 mbedのcliなどは似たようなことをやっていた気がするが忘れた。 前提: 上記 st-link_cli.exeを含む「ST-Link Utility」は将来「STM32CubeProg」に置き換えられるのは明らかなので、 今後はSTM32CubeProg中に含まれるFlash書込み用 コマンドライン・プログラム 「STM32_Programmer_CLI.exe」を使うことにする。 これを使って、 > make w と打って(ビルドと)Flash書き込みを行う時の対策とする。 STM32_Programmer_CLI.exeの出力: Nucleo/DiscoveryボードをUSB接続して、 > STM32_Programmer_CLI.exe -c port=SWD を実行するとNucleo-F411reの場合、... Board : -- Voltage : 3.25V SWD freq : 4000 KHz Connect mode: Normal Reset mode : Software reset Device ID : 0x431 Revision ID : Rev A Device name: STM32F411xC/E Flash size : 512 KBytes Device type : MCU Device CPU : Cortex-M4STM32F4Discoveryを繋いだ時は、... Board : -- Voltage : 2.89V SWD freq : 4000 KHz Connect mode: Normal Reset mode : Software reset Device ID : 0x413 Revision ID : Rev Z Device name : STM32F405xx/F407xx/F415xx/F417xx Flash size : 1 MBytes (default) Device type : MCU Device CPU : Cortex-M4という出力になるので「Device name」以降の文字列を「マイコン特定文字列」としてMakefile中で 照合することで誤書込みを防止する。 方法: 前述のMakefile中の書き込みターゲット「w」は以下のように書ける。 Linux/Unixツールズの「grepコマンド」が必要。# Write to Flash ST_PROGM_CLI_EXE = "d:/STM32CubeProgrammer/bin/STM32_Programmer_CLI.exe" DEV_INFO = $(shell $(ST_PROGM_CLI_EXE) -c port=SWD | grep -i "device name") w: all ifneq (,$(findstring $(DEV_NAME), $(DEV_INFO))) @echo Device = $(DEV_NAME) $(ST_PROGM_CLI_EXE) -c port=SWD -d $(BINHEX_DIR)/$(TARGET).hex -Rst else @echo $(DEV_INFO) @echo Device = ???? $(DEV_NAME) endif使い方: 例えば、上記Makefileのどこかに、 Nucleo-F411reの場合、DEV_NAME = F411 STM32F4Discoveryの場合、DEV_NAME = F407 を追加して>make wを実行すれば、 「Flashに書き込む前にデバイス名(Device name)の照合(注) を行い、正しいデバイスなら書き込む」 という動作となる。 (注) 上記 "Device name:"以降の黄色文字列ならどの部分でも一致し照合OKと判断する。
2015年01月28日
NUCLEO-F411RE ボードでシンプル・マルチタスク・スケジューラ
* はじまり STM32CubeF4ドライバが最新版(V1.4.0)になったので、 勉強のため、このHALドライバを使ってベタで書いてみた。 STM32CubeF4 http://www.st.com/web/en/catalog/tools/PF259243 勉強内容: :D (1) シンプル・マルチタスクスケジューラを動かしてみる。 ここら辺と同じ。 STM32F0 Discovery: シンプル・スケジューラ ARM: Cortex-M3/M0: シンプル・スケジューラ (2) UARTの設定と送受信の動作。 115200bps (3) ChaNさんのxprintfで文字列出力。 (4) FPUを使う設定の確認。 (5) Makefileを使ってスタートアップコードからコンパイルと 動作確認。 (6) システムクロック周りの確認。 (7) 最新のSTM32CubeF4 HALドライバの構成、動作確認。 (8) GPIOでLEDを点灯。 (9) Newlib nano で浮動小数ありなしオプションで且つ、ハードFPU有効な動作。 (10) 標準のNewlibで以下同上。 (11) syscalls.cでリターゲットの確認。 (注) xprintf()以外のprintf()を使う時は、タスクのスタック容量を5000byte以上に 設定しないと動かない。 * 使用ボード NUCLEO-F411RE http://developer.mbed.org/platforms/ST-Nucleo-F411RE/ システムクロック(内蔵クロックベース)とSRAM容量を NUCLEO-F401REレベルに設定 (Systemclock=84MHz, SRAM=96KByte) したので、NUCLEO-F401REでも動作する可能性があるけど、 持ってないので不明。:D * コンパイル コマンドライン: MinGW/MSysコンソール Cygwinコンソール Linuxコンソール のどれかの環境。 コンパイラ: ARM gcc https://launchpad.net/gcc-arm-embedded arm-none-eabi-gcc.exeに実行パスを通しておいてください。 v4.8.4で動作確認。 コンパイル方法: Makefileがあるトップフォルダで「make 一発」。 xD 実際には「make -j4」とかが現実的。 * 動作確認 *.binファイルをNUCLEO-F411REボード用に見えるドライブにコピーするだけ。 (mbedと同じやり方) *.hexをSTLINK経由で書き込んでも良い。 UARTターミナルに1から9の数字を打てば、LEDホアンホアン xD 速度が変わる。 * Download v02: タスク・スタックを200バイトに増量 nucleo-f411re-scheduler-2015-01-v02.7z v01: nucleo-f411re-scheduler-2015-01.7z な、なんと gcc-arm-embedded の最新gcc v4.9.3だと動かない! xD。 え"?! 調べるか。 orz orz 原因判明。 タスク用のスタックをケチり過ぎた。 200バイトでOK. * ハマリポイント :D HALドライバの作法に慣れていないのもあるけど、 UARTの割込み送受信が分りにくくて動くまでorzだった。 キーワードは以下。void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) void USART2_IRQHandler(void) { HAL_UART_IRQHandler(&huart2); } HAL_UART_Transmit_IT( &huart2, &c, 1); HAL_UART_Receive_IT( &huart2, &rcvData, 1);Web検索しても分りにくくて結構困ってる人多いみたい。 スケジューラのUART部分は、あくまで自分用のデモなので、xD 実際にはリングバッファ等を使うのがいいと思う。