みつきんのメモ

組み込みエンジニアです。Interface誌で「My オリジナルLinuxの作り方」連載中

STM32F4Discovery向けのNuttXをClangでビルドする

はじめに

NuttXは次のボードについてClangでのビルドに対応している。

  • nucleo-f446re
  • nucleo-f4x1re
  • stm32f746g-disco

筆者的によく使用するSTM32F4DiscoveryもClangでビルドできないか試してみる。

今回はclang-9を使用している。

clangの設定方法はここを参照。

NuttXのビルドやSTMへの書き込みに必要なパッケージの設定はここを参照。

Nuttxのビルド環境の作成

ソースの取得

$ mkdir ~/nuttx
$ cd ~/nuttx
$ git clone https://bitbucket.org/nuttx/nuttx.git
$ git clone https://bitbucket.org/nuttx/apps.git
$ cd nuttx

Clang対応

Make.defsの修正

./boards/arm/stm32/stm32f4discovery/scripts/Make.defsを修正し、Clangでのビルドに対応する。

この修正はすでにClangのビルドに対応してある環境のものを参考にする。

diff --git a/boards/arm/stm32/stm32f4discovery/scripts/Make.defs b/boards/arm/stm32/stm32f4discovery/scripts/Make.defs
index 48179cb2a5..189670ae2d 100644
--- a/boards/arm/stm32/stm32f4discovery/scripts/Make.defs
+++ b/boards/arm/stm32/stm32f4discovery/scripts/Make.defs
@@ -55,9 +55,6 @@ else
   ARCHSCRIPT = -T$(TOPDIR)/boards/$(CONFIG_ARCH)/$(CONFIG_ARCH_CHIP)/$(CONFIG_ARCH_BOARD)/scripts/$(LDSCRIPT)
 endif
 
-CC = $(CROSSDEV)gcc
-CXX = $(CROSSDEV)g++
-CPP = $(CROSSDEV)gcc -E
 LD = $(CROSSDEV)ld
 STRIP = $(CROSSDEV)strip --strip-unneeded
 AR = $(ARCROSSDEV)ar rcs
@@ -65,7 +62,6 @@ NM = $(ARCROSSDEV)nm
 OBJCOPY = $(CROSSDEV)objcopy
 OBJDUMP = $(CROSSDEV)objdump
 
-ARCHCCVERSION = ${shell $(CC) -v 2>&1 | sed -n '/^gcc version/p' | sed -e 's/^gcc version \([0-9\.]\)/\1/g' -e 's/[-\ ].*//g' -e '1q'}
 ARCHCCMAJOR = ${shell echo $(ARCHCCVERSION) | cut -d'.' -f1}
 
 ifeq ($(CONFIG_DEBUG_SYMBOLS),y)
@@ -73,19 +69,41 @@ ifeq ($(CONFIG_DEBUG_SYMBOLS),y)
 endif
 
 ifneq ($(CONFIG_DEBUG_NOOPT),y)
-  ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fno-strength-reduce -fomit-frame-pointer
+  ARCHOPTIMIZATION += $(MAXOPTIMIZATION) -fno-strict-aliasing -fomit-frame-pointer
 endif
 
 ARCHCFLAGS = -fno-builtin
-ARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new -fno-rtti
+ARCHCXXFLAGS = -fno-builtin -fno-exceptions -fcheck-new
 ARCHWARNINGS = -Wall -Wstrict-prototypes -Wshadow -Wundef
 ARCHWARNINGSXX = -Wall -Wshadow -Wundef
 ARCHDEFINES =
 ARCHPICFLAGS = -fpic -msingle-pic-base -mpic-register=r10
 
-CFLAGS = $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe -funwind-tables
+ifeq ($(CONFIG_ARMV7M_TOOLCHAIN_CLANGL),y)
+  ARCHCCVERSION = {shell $(CC) -v 2>&1 | sed -n '/clang version/p' | sed -e 's/.* clang version \([0-9\.]\)/\1/g' -e 's/[-\ ].*//g'}
+  HOSTCC = clang
+  CC = clang
+  CXX = clang++
+  CPP = clang -E
+  ARCHCFLAGS += -nostdlib -ffreestanding -target arm-none-eabi -march=armv7-m -mcpu=cortex-m4
+  ARCHCXXFLAGS += -nostdlib -ffreestanding -target arm-none-eabi -march=armv7-m -mcpu=cortex-m4 -DCONFIG_WCHAR_BUILTIN
+else
+  ARCHCCVERSION = ${shell $(CC) -v 2>&1 | sed -n '/^gcc version/p' | sed -e 's/^gcc version \([0-9\.]\)/\1/g' -e 's/[-\ ].*//g' -e '1q'}
+  HOSTCC = gcc
+  CC = $(CROSSDEV)gcc
+  CXX = $(CROSSDEV)g++
+  CPP = $(CROSSDEV)gcc -E
+  ARCHCFLAGS += -funwind-tables
+  ARCHCXXFLAGS += -fno-rtti -funwind-tables
+  ifneq ($(CONFIG_DEBUG_NOOPT),y)
+    ARCHOPTIMIZATION += -fno-strength-reduce
+  endif
+
+endif
+
+CFLAGS = $(ARCHCFLAGS) $(ARCHWARNINGS) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe
 CPICFLAGS = $(ARCHPICFLAGS) $(CFLAGS)
-CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe -funwind-tables
+CXXFLAGS = $(ARCHCXXFLAGS) $(ARCHWARNINGSXX) $(ARCHOPTIMIZATION) $(ARCHCPUFLAGS) $(ARCHXXINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES) -pipe
 CXXPICFLAGS = $(ARCHPICFLAGS) $(CXXFLAGS)
 CPPFLAGS = $(ARCHINCLUDES) $(ARCHDEFINES) $(EXTRADEFINES)
 AFLAGS = $(CFLAGS) -D__ASSEMBLY__
@@ -131,7 +149,6 @@ ifeq ($(CONFIG_DEBUG_SYMBOLS),y)
 endif
 
 
-HOSTCC = gcc
 HOSTINCLUDES = -I.
 HOSTCFLAGS = -Wall -Wstrict-prototypes -Wshadow -Wundef -g -pipe
 HOSTLDFLAGS =

コンフィグレーション

次のコマンドを実行し、STM32F4Discovery向けに設定する。

$ tools/configure.sh -l stm32f4discovery:nsh

make menuconfigでメニューを表示する。

$ make menuconfig

/キーで検索画面を表示しclangを検索する。検索結果の画面で1を押すとメニューにジャンプできる。

f:id:mickey_happygolucky:20200109102202p:plain
clangの検索結果

Toolchain SelectionのメニューからGeneric Clang toolchain under Linuxを選択する。

f:id:mickey_happygolucky:20200109102254p:plain
ツールチェインの選択

変更を保存し、メニューを終了する。

ビルド

下記のコマンドでビルド。

$ make -j $(nproc)

ビルドにclangが使用されているか確認したい場合は次のようにする。

$ make SHELL='sh -x' -j $(nproc)

nuttx.binが生成されればOK。

書き込み

次のコマンドで書き込む

$ st-flash write nuttx.bin 0x8000000

接続

USB-TTL変換ケーブルで、次の3つの信号を接続する。

ケーブル側 STM32F4Discovery
GND GND
TXD PA3(USART2_RX)
RXD PA2(USART2_TX)

実行

minicomなどでコンソールを開き、ターゲットをリセットする。

NuttShell (NSH) NuttX-8.2
nsh> help
help usage:  help [-v] [<cmd>]

  [         cp        exec      kill      mount     rmdir     true
  ?         cmp       exit      ls        mv        set       uname
  basename  dirname   false     mb        mw        sh        umount
  break     dd        free      mkdir     ps        sleep     unset
  cat       df        help      mkrd      pwd       test      usleep
  cd        echo      hexdump   mh        rm        time      xd

Builtin Apps:
  hello  nsh
nsh>

nshが使用できればOK。

まとめ

すでにNuttX側にClangのサポートが取り込まれているため、少しの修正でSTM32F4Discovery向けの環境でもClangでビルドできた。