ラズパイを使ったTOPPERS用Cortex-M開発環境の構築

##はじめに
以前に WindowsPC + VirtualBox + Linux を使った**TOPPERS/ASP** の開発環境を構築する記事「**<a href="https://qiita.com/Yukiya_Ishioka/items/9ecbe080939600c323c6">TOPPERS/ASPをビルドして動かしてみる</a>**」、「**<a href="https://qiita.com/Yukiya_Ishioka/items/13b642eeffca1c266641">TOPPERS/ASP(2020-03-10版)をビルドして動かす</a>**」を記しました。
この方式だとWindowsPCへ VirtualBoxのインストールが必要で、会社支給のPCなどでは任意のアプリのインストールが制限されていたり、
VirtualBox上で Linuxを動作させるため CPUパワーやメモリ、HDDの容量など WindowsPCへの負荷が高くなる問題があります。
このため、WindowsPCへ負荷をかけずに開発を行えるよう利用者や保有者が非常に多いと考えらられる ラズパイ上にTOPPERS/ASP用Cortex-M の開発環境を構築し、開発に利用しようと考えました。
また、ラズパイが非常に小型のマイコンボードで持ち運びや設置が容易であること、さらに起動や運用のディスクとしてマイクロSDカードを用いることから環境の貸し借り、コピーも容易であり、多くの人に利用してもらえるのでないかと考えました。

##Linux環境の構築

###Linuxのインストール
ラズパイ用の Linuxは複数のSDカードのイメージがインターネット上に公開されていますが、後で説明する ARM のクロスツールチェーンの新しい版は６４ビット環境用しか提供されていないため **ARM64用**の **Ubuntu 20.04.1 LTS** を用いることとしました。（2020年09月30日現在最新版）
このため、使用するラズパイは Raspberry Pi 3、Raspberry Pi 3+、Raspberry Pi 4が必要となります。

SDカードのイメージは以下のダウンロードページの「Ubuntu 20.04.1 LTS」「Download 64-bit」からダウンロードします。xz形式のファイルがダウンロードできるので、これを展開してできたイメージファイルをイメージ書込みソフトを使ってマイクロSDカードへ書き込みます。

**Raspberry Pi 用 64bit Ubuntu 20.04.1 LTS**
　<https://ubuntu.com/download/raspberry-pi>
　<https://ubuntu.com/download/raspberry-pi/thank-you?version=20.04.1&architecture=arm64+raspi>

###ネットワーク設定
**ubuntu 20.04**では有線LANの eth0をDHCPでIPアドレスが取得できるよになっています。DHCPサーバが動作しているネットワーク環境でLANケーブルを接続すればネットワークで通信を行うことができます。
また、**/etc/netplan** 配下に設定ファイルを追加してIPアドレスなどを定義することで固定のIPアドレスでの運用も可能となります。
以下は私の自宅環境で使っている設定ファイルです。

``` /etc/netplan/99_config.yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    eth0:
      dhcp4: false
      dhcp6: false
      addresses: [192.168.0.140/24]
      gateway4: 192.168.0.1
      nameservers:
        addresses: [192.168.0.1, 8.8.8.8, 8.8.4.4]
```

###追加ミドルウェアのインストール
ネットワークで通信ができるようになったら、「**apt-get install**」コマンドを使って以下の追加ミドルウェアをインターネットからダウンロードしてインストールします。なお、「apt-get install」前に「**apt-get update**」コマンドでダウンロード用の情報を最新の情報へ更新しておいてください。

```
net-tools
g++
libboost-all-dev
libxerces-c-dev
make
minicom
samba
```

##クロスツールチェーンの構築
**GNU Arm Embedded Toolchain Downloads** のページからクロスコンパイラなどのツールチェーンをダウンロードし、ラズパイ上に展開します。今回は**GCC10**用のツールチェーンを用いましたが、安定版の「**9-2020-q2-update June 30, 2020**」をダウンロードして用いても問題ありません。
ダウンロードするのは **Linux AArch64 Tarball** です。

**GNU Arm Embedded Toolchain: 10-2020-q2-preview June 29, 2020**
gcc-arm-none-eabi-10-2020-q2-preview-aarch64-linux.tar.bz2
<https://developer.arm.com/-/media/Files/downloads/gnu-rm/10-2020q2/gcc-arm-none-eabi-10-2020-q2-preview-aarch64-linux.tar.bz2?revision=a7134e5c-fad8-490c-a62b-9200acca15ef&la=en&hash=12954B763712885C1DDE3318D10DF96B1606463A> 

tar.bz2形式のファイルをダウンロード後、tarコマンドで「-C」で指定したインストール先のディレクトリへ展開します。
以下は **/home/ubuntu/bin** 配下へ展開するコマンドの例です。

```
mkdir ~/bin
tar xjf gcc-arm-none-eabi-10-2020-q2-preview-aarch64-linux.tar.bz2 -C ~/bin
```

今回展開したツールチェーンを利用するには、TOPPERS/ASPのビルド前に環境変数 PATHへ実行ファイルのパスを設定します。
私の自宅環境では、以下の定義を「~/.bashrc」へ追加し、ログイン後にいつでも使える状態にしてあります。

```
export PATH=~/bin/gcc-arm-none-eabi-10-2020-q2-preview/bin:$PATH
```

##コンフィグレータの変更・ビルド
コンフィギュレータ Release 1.9.6を使ってコンフィギュレータのビルドを行い、TOPPERS/ASPカーネルのビルドができるようにします。ただし、コンフィギュレータのページには以下の注記があることなどからダウンロードしたままではビルドすることができませんでした。

```
64bitのLinux用のboostライブラリに現状問題があるため、
64bitのLinuxでビルドしたcfgは正しく動作しません。
64bitのLinuxでcfgを使用する場合は、下記の32bit Linux用
バイナリを使用するか、32bitのLinuxでソースからビルドして
スタティックリンクしたバイナリを使用下さい。
```

以前に記した記事でもこの問題を避けるため 32bitのLinuxを用いて開発環境の構築を行ってきました。
今回はこの問題を回避する修正なども含めてあります。

コンフィギュレータ Release 1.9.6
<https://www.toppers.jp/download.cgi/cfg-1.9.6.tar.gz>

まず、コンフィギュレータのページから以下のファイルをダウンロードして任意のディレクトリへ配置します。
以後の説明では以下のディレクトリに配置した想定でコマンド入力などを記します。

```
/home/ubuntu/toppers
```

● ソースの展開
ダウンロードした tar.gzファイルを展開します。
以下のコマンドで展開すると cfgディレクトリが生成され、配下にソースファイルなどが展開されます。

```
tar zxf cfg-1.9.6.tar.gz
```

● ソースの展開
cfgディレクトリへ移動します。

```
cd cfg
```

● libboost用ヘッダファイルの追加
コンフィギュレータをビルドするとヘッダファイルのインクルード不足によるエラーで止まってしまうため、以下のように toppers/text.hppファイルとtoppers/cpp.hppファイルへインクルードの定義を追加します。

``` toppers/text.hpp
 54 #include "toppers/text_line.hpp"
 55 #include "toppers/misc.hpp"
 56 #include <boost/next_prior.hpp>  /* ※ 追加 */
 57 #include <boost/utility.hpp>
 58 #include <boost/iterator/iterator_facade.hpp>
```

``` toppers/cpp.hpp
 44 #include "toppers/codeset.hpp"
 45 #include "toppers/diagnostics.hpp"
 46 #include <boost/next_prior.hpp>  /* ※ 追加 */
 47 #include <boost/utility.hpp>
 48 #include <boost/filesystem/path.hpp>
```

● コンフィギュレーション実行
コンフィギュレータのビルド前の環境設定を行います。ただし、展開直後の configureスクリプトは改行コードに「0x0d」が含まれているためこのままではエラーとなってしまいます。
このため以下のコマンドで不要なコードの削除などを行います。

```
mv configure configure.org
tr -d '\r' < configure.org > configure
chmod u+x configure
```

修正後、以下のコマンドでコンフィグレーションを実行します。

```
./configure --with-libraries=/usr/lib/aarch64-linux-gnu
```

configureスクリプトの実行が成功したら以下のコマンドでコンフィギュレータをビルドします。
Raspberry Pi 3で２０分弱ほどかかります。

```
make OPTIONS=-std=c++11
```

cfg/cfgコマンドができていたら成功です。

```
cfg/cfg -v

TOPPERS Kernel Configurator version 1.9.6
```

##ＡＳＰカーネルの変更・コンフィグレーショーン
TOPPERS/ASPカーネル ターゲット非依存部パッケージ **asp-1.9.3.tar.gz** とARM Cortex-M4アーキテクチャ・GCC依存部パッケージ **asp_arch_arm_m4_gcc-1.9.6.tar.gz** を **/home/ubuntu/toppers** ディレクトリへダウンロードしてASPカーネルのビルドします。

● ソースの展開
ダウンロードした tar.gzファイルを展開します。
以下のコマンドで展開すると aspディレクトリが生成され、配下にソースファイルなどが展開されます。

```
cd /home/ubuntu/toppers
tar xzf asp-1.9.3.tar.gz
tar xzf asp_arch_arm_m4_gcc-1.9.6.tar.gz
```

● コンフィギュレータのコピー
ビルドして作成したコンフィギュレータをaspは以下にコピーします。
以下のコマンドで必要なディレクトリを作成してコピーすることができます。

```
mkdir -p  asp/cfg/cfg
cp  cfg/cfg/cfg  asp/cfg/cfg
```

以下のコマンドを実行し、バージョン情報が出力されたらコピー成功です。


```
asp/cfg/cfg/cfg -v

TOPPERS Kernel Configurator version 1.9.6
```

● コンフィギュレーションエラーの回避
展開されたASPカーネルでは、GNU Arm Embedded Toolchainの GCC7以降でカーネルビルド時に使われるリンカスクリプトで使われている「**PROVIDE()**」が意図した動作をせず、常に記述されている「**hardware_init_hook = 0**」が有効となり hardware_init_hook関数のアドレスが**常に 0x0番地**でバイナリが生成されます。
これにより ASPカーネルをボード上で実行すると 0x0番地へジャンプし、**リセットを繰り返す**ことになります。
このため以下のように hardware_init_hook用のコードをコメントアウトします。
以下は stm32f401nucleo_gcc用のリンカスクリプトの修正内容です。

asp/target/stm32f401nucleo_gcc/stm32f4xx_rom.ld

```C++
 10 PROVIDE(hardware_init_hook = 0);
 11 PROVIDE(software_init_hook = 0);
 12 PROVIDE(software_term_hook = 0);
 13 STARTUP(start.o)
```

↓

```C++
 10 /* PROVIDE(hardware_init_hook = 0); */
 11 PROVIDE(software_init_hook = 0);
 12 PROVIDE(software_term_hook = 0);
 13 STARTUP(start.o)
```

※今回のアプリケーションの構築方法では **software_init_hook**、**software_term_hook** は **0x0番地で問題ありません**。

なお、このままではビルド中の cfg1_outの生成でエラーとなるため、「PROVIDE(hardware_init_hook = 0)」の代替処理を start.Sへ追加します。
以下のように start.Sの終端行へ以下の処理を追加します。

``` asp/arch/arm_m_gcc/common/start.S
.weak  hardware_init_hook
        bx  lr
```

● ＡＳＰカーネルのコンフィギュレーショーン
ASPカーネルのコンフィギュレーションはアプリケーションをビルドするディレクトリで実行します。今回は STM32F401 Nucleo-64ボードをターゲットとして、/home/ubuntu/toppers/f401/obj ディレクトリにアプリケーションのビルド環境を構築します。
以下のコマンドで f401/obj ディレクトリを作成します。

```
cd /home/ubuntu/toppers
mkdir -p f401/obj
```

以下のコマンドで f401/objディレクトリへ移動し、コンフィギュレーションを実行します。

```
cd f401/obj
../../asp/configure -T stm32f401nucleo_gcc -dROM
```

以下のファイルが生成されたら成功です。

```
-rw-rw-r-- 1 ubuntu ubuntu 15335 Aug 30 18:22 Makefile
-rw-rw-r-- 1 ubuntu ubuntu 15652 Aug 30 18:22 sample1.c
-rw-rw-r-- 1 ubuntu ubuntu   918 Aug 30 18:22 sample1.cfg
-rw-rw-r-- 1 ubuntu ubuntu  3246 Aug 30 18:22 sample1.h
```

##アプリケーションのビルド

Nucleoボードは PCへUSBで接続することでディスクドライブとして見えるようになり、このディレクトリへビルドして生成されたバイナリコードをコピーすることでプログラムを書き込むことができます。
アプリケーションのビルドでバイナリコードが生成されるよう Makefileの以下の箇所に .binファイル生成の記述を追加します。

Makefile

```
327 $(OBJFILE): $(APPL_CFG) kernel_cfg.timestamp $(ALL_OBJS) $(LIBS_DEP)
328         $(LINK) $(CFLAGS) $(LDFLAGS) -o $(OBJFILE) $(START_OBJS) \
329                         $(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) $(ALL_LIBS) $(END_OBJS)
330         $(NM) -n $(OBJFILE) > $(OBJNAME).syms
331         $(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
332         $(CFG) --pass 3 --kernel asp $(INCLUDES) \
```

↓

```
327 $(OBJFILE): $(APPL_CFG) kernel_cfg.timestamp $(ALL_OBJS) $(LIBS_DEP)
328         $(LINK) $(CFLAGS) $(LDFLAGS) -o $(OBJFILE) $(START_OBJS) \
329                         $(APPL_OBJS) $(SYSSVC_OBJS) $(CFG_OBJS) $(ALL_LIBS) $(END_OBJS)
330         $(NM) -n $(OBJFILE) > $(OBJNAME).syms
331         $(OBJCOPY) -O srec -S $(OBJFILE) $(OBJNAME).srec
**332         $(OBJCOPY) -O binary -S $(OBJFILE) $(OBJNAME).bin　　　←★追加**
333         $(CFG) --pass 3 --kernel asp $(INCLUDES) \
```

追加後、f401/objディレクトリで makeを実行することでアプリケーションのビルドを実行できます。

```
cd f401/obj
make
```

以下のファイルが生成されたらビルド成功です。

```
-rwxrwxr-x 1 ubuntu ubuntu 363656 Aug 30 18:35 asp*
-rwxrwxr-x 1 ubuntu ubuntu  28442 Aug 30 18:35 asp.bin*
-rwxrwxr-x 1 ubuntu ubuntu  85392 Aug 30 18:35 asp.srec*
-rw-rw-r-- 1 ubuntu ubuntu   8109 Aug 30 18:35 asp.syms
```

STM32F401 Nucleo-64ボードへ asp.binをコピーしてプログラムを実行するとSTM32F401 Nucleo-64ボードの仮想COMポートへ以下のメッセージが出力されます。

![clip1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370759/4ea6402f-27ed-7473-85be-c7ba10d5c34e.jpeg)

● WindowsPC上での asp.binファイルのコピー
ラズパイにSambaをインストール・設定することで、ラズパイ上のasp.binファイルをWindowsPCのエクスプローラー上でドラッグ＆ドロップ操作によりSTM32F401-Nucleoへ書き込むことができます。

![clip2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370759/501c5031-091a-08f7-6bf7-85decaae7209.jpeg)

##運用構成
ラズパイを使った開発では、WindowsPCを介してラズパイ上で生成さたバイナリファイルをターゲットボードへ書き換える方法のほか、ラズパイへモニタやキーボード、ターゲットボードを接続したラズパイ単体の運用構成も可能になります。
STM32F401-NucleoボードはLinuxからもUSB接続で仮想COMポートの/dev/ttyACM、マスストレージの/dev/sda1としてアクセスできることから、ターゲットボードへの書き込みから実行後の syslog()出力もラズパイ単体で運用することができます。

● WindowsPCを介した運用構成
![clip3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370759/4195aae3-c053-3370-f2a4-35df8b0cf603.jpeg)

● ラズパイ単体の運用構成
![clip4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/370759/5e3b8367-b159-1803-b0ce-2226c78f0023.jpeg)

##さいごに
もし Raspberry Pi 3、Raspberry Pi 3+、Raspberry Pi 4 のいずれかを持っていたら、ここに記した手順で環境を構築し、プログラムのビルドを試されてはいかがでしょうか。
ラズパイそのものを電子工作用のボードやコントローラとして用いる記事や情報が多くありますが、今回のように開発環境としても十分に使えることが分かってもらえるのではないかと思います。

－ 以上 －