CMakeメモ

CMakeとは?

  • 簡単な設定ファイル( CMakeLists.txt )を書くだけで Makefile を生成してくれるツール
  • Linux, Windows, Macなど各々のビルド環境のしきたりに沿った Makefile がおまかせで生成される。
  • コマンドラインベースのツール

CMakeの使い方

  1. CMakeLists.txt のあるディレクトリを指定して cmake コマンドを実行すると Makefile が生成される。
  2. make コマンドでビルドする。

ただし、Windowsの場合は make のかわりに nmake ないし msbuild を用いる。

 # nmakeの場合
mkdir build
cd build
cmake .. -G "NMake Makefiles"
nmake

# msbuildの場合
mkdir build
cd build
cmake ..
msbuild ALL_BUILD.vxcproj

nmakeとは?

CMakeLists.txtの書き方メモ

  • cmake_minimum_required : CMakeの最小要求バージョンを指定
  • project : プロジェクト名と使用言語を指定
  • file : ソースファイルを指定
  • include_directories : インクルードファイルのディレクトリを指定
  • target_link_libraries : リンクするライブラリを指定
  • add_executable : ターゲットの実行ファイルを指定
  • add_library : ターゲットのライブラリを指定
    • STATIC か SHARED の指定で、静的ライブラリか共有ライブラリ(WindowsならDLL)かを指定
  • install : インストール先を指定
  • add_subdirectory : サブプロジェクトのCMakeLists.txtのあるディレクトリを指定

ゲージ表示用の.NETフォーム コントロール

ゲージ表示用のコントロールをProgressBarをベースに作った。ProgressBarからの変更点は、

  • アニメーション表示しない
  • バーの色はForeColorで設定できる
  • ニュートラルの値(Neutral)を基準にプラスマイナスの表示
using System;
using System.Drawing;
using System.Windows.Forms;

namespace Utility
{
    class GaugeBar : ProgressBar
    {
        public GaugeBar()
        {
            // OnPaintイベントが発生するようにする
            // ダブルバッファリングを有効にする
            base.SetStyle(
                ControlStyles.UserPaint |
                ControlStyles.AllPaintingInWmPaint |
                ControlStyles.OptimizedDoubleBuffer,
                true);
        }

        // ニュートラル値
        private int m_Neutral = 0;
        public int Neutral
        {
            get
            {
                return m_Neutral;
            }
            set
            {
                m_Neutral = value;
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            Rectangle rec = e.ClipRectangle;
            Brush foreBrush = new SolidBrush(this.ForeColor);

            // 枠線描画
            if (ProgressBarRenderer.IsSupported)
            {
                ProgressBarRenderer.DrawHorizontalBar(e.Graphics, e.ClipRectangle);
            }

            // ニュートラル値の座標
            int neutral = 2 + (rec.Width - 4) * (m_Neutral - Minimum) / (Maximum - Minimum);

            // プラスの場合
            if (Value > m_Neutral)
            {
                int offset = Value - m_Neutral;
                int width = (rec.Width - 4) * offset / Maximum;
                int height = rec.Height - 4;
                e.Graphics.FillRectangle(foreBrush, neutral, 2, width, height);
            }
            // マイナスの場合
            else if (Value < m_Neutral)
            {
                int offset = m_Neutral - Value;
                int width = (rec.Width - 4) * offset / Maximum;
                int height = rec.Height - 4;
                e.Graphics.FillRectangle(foreBrush, neutral - width, 2, width, height);
            }

            // ニュートラルの線
            if (m_Neutral != Minimum)
            {
                e.Graphics.DrawLine(Pens.DarkGray, neutral, 1, neutral, rec.Height - 1);
            }
        }
    }
}

Windows 10でのWinPcap代替 = Npcap

Windows版の pcap (パケットキャプチャ) ライブラリとして有名な WinPcap ですが、Windows 10では安定して動作しません。Windows 10では WinPcap の代わりに Npcap を使いましょう。
(Win10Pcap というのもありますが保守されてないようなのでスルーで。)

ちょっと分かりにくいですが、インストールのオプションで「Install Npcap in WinPcap API-compatible Mode」にチェックを入れます。これで従来のWinPcapの代替となります。

f:id:licheng:20190419201357p:plain

【2021/11/01 追記】
今はWiresharkのインストール時に同時にインストールできるようになっています。
f:id:licheng:20211101091837p:plain

メモ: VirtualBoxにUbuntu18.04をセットアップ

基本的にビルド環境として使うので、無用のトラブルを避けるために日本語Remix版は使わず、言語も「English」でインストールする。ただし、キーボードは日本語キーボードを使用するのでその点を注意する。

ISOイメージの入手

仮想マシンの作成

  • VirtualBoxの「仮想マシン」>「新規」で仮想マシンを作成する。
  • OSのタイプとバージョンは「Linux」「Ubuntu(64bit)」を選択する。
  • 仮想ハードディスクのサイズはデフォルトでは10GBであるが余裕をもって設定する。

Ubuntuのインストール

  • 作成した仮想マシンを起動する。
  • 起動ディスクを求められるので、UbuntuのISOイメージファイルを指定する。
  • 「Welcome」の画面で言語は「English」を選択し、「Install Ubuntu」を選択。
  • 「Keyboard Layout」の画面では「Japanese」「Japanese」を選択。
  • 「Whre are you?」の画面では「Tokyo」を選択。
  • 「Who are you?」の画面では、ホスト名・ユーザー名・パスワードを設定。
  • インストールが完了したら「Restart Now」で再起動。

Ubuntuのアップデート

  • ログインすると「Software Updater」のダイアログが出るので「Install Now」を選択。
  • アップデートが完了したら「Restart」で再起動。
  • ログインして「Activities」から Terminal を起動。
  • Terminalを「Add to Favorites」でドックに追加。
  • 不要なアイコンは「Remove from Favorites」でドックから削除。
  • Terminalで下記コマンドを実行してaptパッケージを更新する。
sudo apt update
sudo apt upgrade

コピペと画面リサイズの設定 (Guest Additions)

Guest Additionsをインストールする。

  • 仮想マシンのメニューから「デバイス」>「Guest Additions CDイメージの挿入」を選択。
  • 「Would you like to run it?」で「Run」を選択。
  • インストールが完了したら、デスクトップにあるGuest AdditionsのCDを「Eject」する。
  • 仮想マシンのメニューから「仮想マシン」>「設定」>「一般」>「高度」>「クリップボードの共有」を「双方向」に設定。
  • Ubuntuをいちど「Power Off」して再起動。

以上で、ゲスト⇔ホスト間のテキストのコピペと、ゲストの画面リサイズができるようになる。

ネットワークの設定

  • 仮想マシンの「設定」>「ネットワーク」
    • アダプタ1 : 「NAT」
    • アダプタ2 : 「ホストオンリーアダプタ」

Windows10では、「ホストオンリーアダプタ」でネットワークアダプタを選択できない場合がある。その場合は下記手順でネットワークアダプタを追加する。

  • 「ファイル」>「ホストネットワークマネージャー」で「Create」する。
  • DHCPサーバ」を「有効」にする。

共有フォルダの設定 (samba)

VirtualBoxの共有フォルダ機能は使わない。
sambaでUbuntuのホームディレクトリをWindows側に見せる。

まず、sambaをインストールする。

sudo apt-get install samba
sudo vi /etc/samba/smb.conf

smb.confのホームディレクトリ共有設定の記述を下記のように修正。

[homes]
   comment = Home Directories
   browseable = no
   read only = no
   valid users = %S

sambaユーザを設定し、sambaのサービスを再起動。

sudo smbpasswd -a ユーザ名    # Ubuntuのユーザ名と同じ名前を設定。
sudo systemctl restart smbd nmbd

IPアドレスを確認する。Ubuntu 18.04ではデフォルトではifconfigコマンドは無く、ipコマンドを使う。

ip address show

たとえばIPアドレスが192.168.246.3であったら、Windowsエクスプローラで \\192.168.246.3 と入力すれば共有フォルダにアクセスできる。

その他のツールのインストール

sudo apt-get install unzip
sudo apt-get install tar
sudo apt-get install git
sudo apt-get install curl
sudo apt-get install python3
sudo apt-get install build-essential

マイコンでTensorFlow!? (4)

今回はいよいよTensorFlow Liteのサンプルコードをビルドしてボードに書き込んでみます。

サンプルコードの内容

SparkFun Edgeボードの2つのマイクに入力される音声から「Yes」と「No」という単語を検出します。これには畳み込みニューラルネットワークによる音声検出モデルを使用します。これはSparkFun Edgeボードに出荷時に書き込み済みのファームウェアと同じものです。

TensorFlowのリポジトリのダウンロード

Gitを使うのでインストールされていないなら下記のコマンドでインストールします。

sudo apt-get install git

TensorFlowのリポジトリをクローンします。ここではホームディレクトリ直下に置くとします。

cd 
git clone https://github.com/tensorflow/tensorflow.git

ビルド

以下のコマンドを実行します。前回の記事でGCC, SDK, BSPをインストールしましたが、TensorFlow Liteでは別途これらのツールをリポジトリ内のディレクトリにダウンロードして使うことに注意してください。そのため、初回のmakeには時間がかかります。

cd tensorflow

# 次の1行はMacの場合のみ必要(Linuxでは不要)
PATH=tensorflow/lite/experimental/micro/tools/make/downloads/gcc_embedded/bin/:$PATH

# 長いパスが面倒なので変数に入れておきます
MAKEPATH=tensorflow/lite/experimental/micro/tools/make
SCRIPTPATH=$MAKEPATH/downloads/AmbiqSuite-Rel2.0.0/tools/apollo3_scripts

# 諸事情によりファイルコピー
cp $SCRIPTPATH/keys_info0.py $SCRIPTPATH/keys_info.py

# ビルド
make -f $MAKEPATH/Makefile TARGET=sparkfun_edge micro_speech_bin

# 下記を実行して "Success!" と表示されればビルド成功です。
test -f $MAKEPATH/gen/sparkfun_edge_cortex-m4/bin/micro_speech.bin; \
    if [ $? -eq 0 ]; then echo "Success!"; else echo "No binary file!"; fi

# マイコンに書き込むためにファイルに変換
python3 $SCRIPTPATH/create_cust_image_blob.py \
    --bin $MAKEPATH/gen/sparkfun_edge_cortex-m4/bin/micro_speech.bin \
    --load-address 0xC000 --magic-num 0xCB \
    -o main_nonsecure_ota --version 0x0
python3 $SCRIPTPATH/create_cust_wireupdate_blob.py \
    --load-address 0x20000 \
    --bin main_nonsecure_ota.bin -i 6 \
    -o main_nonsecure_wire --options 0x1

シリアルポートの接続とシリアルポート名の確認

前回の記事と同じ要領でSparkFun FTDI Basic Breakoutを介してSparkFun EdgeボードをPCのUSBポートに接続し、シリアルポートのデバイスノードを確認します。

プログラム書き込み

前回の記事と同じ要領で、SparkFun Edgeボードのボタン14を押したままリセットボタンを押して離し、そのままボタン14を押し続けます。そして下記のコマンドを実行します。(シリアルポートが/dev/ttyUSB0の場合の例です。) 「Sending Data Packet of length 8180」というメッセージが出たらボタン14を離します。

sudo python3 $SCRIPTPATH/uart_wired_update.py -b 921600 \
    /dev/ttyUSB0 -r 1 -f main_nonsecure_wire.bin -i 6

出荷時に書き込み済みのファームウェアと同じ動作をすることを確認します。「Yes」と言ったら黄色のLEDが点灯しますか? まあ、もともとめったに反応しないんですが

コードを読んでみる

まず、下記のソースファイルを読んでみましょう。

tensorflow/lite/experimental/micro/examples/micro_speech/sparkfun_edge/command_responder.cc

RespondToCommand()メソッドは音声が検出されたときに呼ばれ、「Yes」か「No」かまたは不明な音声が聞こえた場合に異なるLEDを点灯させます。

下記のページにもう少し詳しい説明があります。適当に変更してリビルドしてボードに書き込んでみましょう。

参考URL

この記事は下記のページをもとに書きました。
codelabs.developers.google.com

マイコンでTensorFlow!? (3)

今回はサンプルコードのビルドとボードへの書き込みをやってみます。以下の2つを試します。

  1. Edge Test:GPIO、UART、ADC、I2Cなどのハードウェア機能のデモ。
  2. Makefile Project Template : 自分でプロジェクトを作るためのテンプレート。

(1) Edge Test

4つのLEDを点灯し、マイクと加速度センサからの取得したデータを115200ボーのシリアル通信で送信します。ボタン14を押すと省電力のためにオフします。4つのLEDはGoogleカラーの赤・青・緑・黄ですね。

f:id:licheng:20190410075144j:plain:w500

プロジェクトのディレクト
~/AmbiqSuite/boards/SparkFun_Edge_AmbiqSDK_BSP/examples/example1_edge_test
シリアルポートの接続とデバイスノードの確認

SparkFun FTDI Basic Breakoutを介してSparkFun EdgeボードをPCのUSBポートに接続します。必ず3.3Vのものを使うことと、向きを間違えないように気を付けてください。向きは「GRN」「BLK」のシルクを目印にして合わせます。SparkFun EdgeボードをPCに接続する前後でシリアルポートを一覧して、追加されたものがSparkFun Edgeボードのシリアルポートです。

  • Macの場合、ls /dev/cu* でシリアルポートのデバイスノードを一覧できます。
  • Linuxの場合、ls /dev/tty* でシリアルポートのデバイスノードを一覧できます。
Makefileの修正

上記プロジェクトディレクトリの gcc/Makefileテキストエディタで開き、「SERIAL_PORT ?= 」の行を修正します。たとえば、SparkFun Edgeボードのシリアルポートが /dev/ttyUSB0 であれば、下記のように修正します。

#### Bootloader Configuration
SERIAL_PORT ?= /dev/ttyUSB0
ビルド

以下のコマンドを実行します。

cd ~/AmbiqSuite/boards/SparkFun_Edge_AmbiqSDK_BSP/examples/example1_edge_test/gcc
make clean
make
ボードへの書き込み

SparkFun Edgeボードのボタン14を押しながらリセットボタンを押し、ボタン14を押したままリセットボタンを離します。これでSparkFun Edgeボードはプログラム書き込み待ちになります。ボタン14を押したまま下記のコマンドを実行すると、SparkFun Edgeボードにプログラムが書き込まれます。組込みマイコンではおなじみのシリアル書き込みの作法ですが、書き込み中もボタン14を押し続けないといけない点が要注意です。ちょっと操作しにくいですね。片手でボタン14を押して片手でEnterキーを叩きましょう。

sudo make bootload
動作確認

お好みのシリアルターミナルでSparkFun Edgeボードのシリアルポートを開き、出力を確認します。ボーレートは115200です。Windowsならここは仮想マシン上ではなくWindows側でTera Termなどを使うのが簡単でしょう。ボタン14を押すとオフし、リセットボタンを押すと再起動します。

ライブラリの使い方

src/main.c をながめてみます。ライブラリを使うために以下のヘッダファイルをインクルードしています。

#include "am_mcu_apollo.h"
#include "am_bsp.h"
#include "am_util.h"

ライブラリ関数の使い方は、以下のディレクトリのヘッダファイルを見て感じ取ります。組込み系のライブラリなんてそういうものです。

  • ~/AmbiqSuite/mcu/apollo3/hal
  • ~/AmbiqSuite/boards/SparkFun_Edge_BSP/bsp
  • ~/AmbiqSuite/utils

(2) Makefile Project Template

プロジェクトのディレクト
~/AmbiqSuite/boards/SparkFun_Edge_AmbiqSDK_BSP/examples/SparkFun_Edge_Project_Template
Makefile

gcc/Makefile をながめてみます。

  • TARGET : 生成されるバイナリ名
  • COM_PORT : 'make bootload'コマンドでプログラムを書き込むときに使うシリアルポート
  • SDKPATH : SDKのパス
  • BOARDPATH : BSPのパス
  • USER_INCLUDEDIRS : ユーザーのインクルードディレクトリ (複数)
  • USER_SOURCEDIRS : ユーザーのソースディレクトリ (複数)
  • USER_MAIN_SRC : ユーザーのメインのソースファイル
  • USER_SOURCE_FILES : ユーザーのソースファイル (複数)
ビルドと書き込みのコマンド

gccディレクトリで以下のコマンドを実行します。

プロジェクトのクリーン

make clean

プロジェクトのビルド

make

ボードへのプログラム書き込み

sudo make bootload
ブートローダについて

このような便利なシリアル書き込みのために、Sparkfun EdgeボードではブートローダがApollo3マイコンに書き込み済みです。生のApollo3マイコンを買ってきた場合はJTAGかSWDでプログラムを書く必要があります。

参考URL

この記事は下記のSparkFunのページをもとに書きました。
learn.sparkfun.com

マイコンでTensorFlow!? (2)

今回は開発環境をセットアップしていきます。前回説明した通り、SparkFun EdgeボードはまだGUIIDEが用意されていないので、コマンドラインベースの開発環境を構築する必要があります。

(1) Bash

コマンドラインツール、いわゆるシェルです。MacLinuxを使ってる開発者にはおなじみのものなので説明の必要はないでしょう。問題はWindowsの場合です。SparkFunのページではGit Bashを使う方法が紹介されていますが地雷臭しかしないので、素直にVirtualBox等の仮想マシンLinux使う方が良いと思います。

VirtualBoxの場合、デフォルトの仮想ハードディスクのサイズは10GBですが、10GBではTensorFlowのビルドをすると足りなくなるので余裕をもったサイズで作成しましょう。あとからパーティションを拡張するのは面倒です。

f:id:licheng:20190409233013p:plain:w500

(2) Make

自動ビルドツールです。MacLinuxを使ってる開発者にはおなじみのものなので説明の必要はないでしょう。Windowsの場合は仮想マシンLinuxを使いましょう。SparkFunのページではGit Bash上でGNU MCU Eclipse Windows Build Toolsを使う方法が紹介されていますが、ここではそういうケッタイな方法はとりません。

Ubuntuなら下記のコマンドを実行してください。Makeを含む基本的なビルドツール一式がインストールされます。

sudo apt-get install build-essential

(3) Python3

SparkFun Edgeボードの開発のためのもろもろのスクリプトPythonで書かれています。

Ubuntuなら下記のコマンドでインストールできます。SparkFunのページではWindowsの場合の注意点が書かれてますが、仮想マシンLinux使うなら関係ありません。

sudo apt-get install python3

Pythonで暗号化とシリアル通信をおこなうためにPyCryptodomeとPySerialをインストールします。Ubuntuなら下記のコマンドを実行してください。

sudo apt-get install python3-pip
sudo pip3 install pycryptodome
sudo pip3 install pyserial

(4) GNU Arm Embedded Toolchain

かんじんのCコンパイラです。ARM Cortex-R/Mマイコン用のGCCであるGNU Arm Embedded Toolchain (GNU-RM) を用います。

GNU Arm Embedded Toolchainはここからダウンロードしてインストールできますが、Ubuntuならもっと簡単です。下記のコマンドを実行してください。

sudo apt-get install gcc-arm-none-eabi

(5) Ambiq SDK

Ambiq Apolloマイコン用のSDKです。Ambiq社の下記ページの下のほうの「Apollo3 Blue」の「Software」の「AmbiqSuite SDK Version X.X.X」からzipファイルをダウンロードし、適当なディレクトリに解凍します。ここではホームディレクトリ直下のAmbiqSuiteに解凍したとして話を進めます。

※ 2019/04/07の時点で最新版はAmbiqSuite SDK Version 2.1.0ですが、後述のSparkFun Edge BSPとの整合性がとれないので、「Software - Earlier Releases 」からAmbiqSuite SDK Version 2.0.0をダウンロードして使用します。

SDKの主なフォルダ構成は以下のようになっています。

  • boards : 各ボードサポートパッケージ
  • CMSIS : ARM Cortexプロセッサ用の標準化されたライブラリ
  • mcu/apollo3 : Ambiq Apolloマイコン用のライブラリ
  • tools/apollo3_scripts : ビルドとFlash書き込みのためのPythonスクリプト
  • utils : ディレイや文字列操作などのユーティリティーライブラリ

諸事情により下記の修正が必要です。

cd ~/AmbiqSuite
cp tools/apollo3_scripts/keys_info0.py tools/apollo3_scripts/keys_info.py
chmod +x tools/apollo3_scripts/*.py

(6) SparkFun Edge BSP

SparkFun Edgeボード用のBSP(サポートパッケージ)です。下記のGitHubリポジトリからcloneするなりzipをダウンロードするして、~/AmbiqSuite/boards/ の下に配置します。ここでは~/AmbiqSuite/boards/SparkFun_Edge_BSPに配置したとします。

諸事情により下記の修正が必要です。

cd ~/AmbiqSuite/boards/SparkFun_Edge_BSP
chmod +x bsp/tools/*.py

以上で開発環境のセットアップは完了です。次回はサンプルコードのビルドとボードへの書き込みを行います。

参考URL

この記事は下記のSparkFunのページをもとに書きました。