Spresense SDKにCMSIS-DSPをリンクする

Spresense SDKにCMSIS-DSPライブラリをリンクしました。これによって、ARMが提供している基本演算や信号処理ライブラリをSpresenseアプリケーションで使えるようになります。

なぜCMSIS-DSPが必要か

CMSIS-DSPは、ARMがCMSIS-5の一部として公開している演算ライブラリです。このライブラリは固定小数点数、浮動小数点数による関数を集めたもので、基本的なものからフィルタ、FFTといった信号処理関数まで含んでいます。わざわざ信号処理関数を集めたのは、汎用DSPがおさえていた組み込み信号処理市場に手を伸ばすためでしょう。

なんにせよ、このライブラリをアプリケーションから使うことで信号処理アプリの開発が楽になります。CMSISはドキュメントがそこそこしっかりしているので、使うときのハードルが低いのも良い点です。

NuttXへの外部ライブラリの追加方法

外部ライブラリの追加は、実際にはNuttXカーネルに対して行います。言い換えると、アプリケーションごとにライブラリを分けてリンクするのではなく、パッケージ全体にライブラリを1つ追加します。

CMSIS-DSPのライブラリは、ARMがコンパイル済みのライブラリをgithubにプッシュしているので、そちらを使います。どこにおいても構いませんが、私はspresenseディレクトリの直下に置きました。以下のスクリプトでCMSIS-5のリポジトリをクローンし、masterからチェックアウトしています。

# Clone CMSIS-5
cd ~/spresense
git clone https://github.com/ARM-software/CMSIS_5.git
cd CMSIS_5
git checkout master
git pull

持ってきたライブラリを使用するには、ビルドルールの中にインクルードファイルやライブラリを追加しなければなりません。追加の仕方についてはHow to properly include an external library source in a NuttX build?として論じられている内容を参考にしました。

具体的にはMake.defsに対してCFLAGS, EXTRA_LIBS, EXTRA_LIBPATHを追加します。Spresense SDKにはMake.defsが複数あるのですが、spresense/sdk/Make.defsに追加しました。なお、ARM_MATH_CM4マクロと__FPU_PRESENTマクロについてはドキュメントを参考にしました。

CFLAGS += -I$(SDKDIR)/../CMSIS_5/CMSIS/DSP/Include
CFLAGS += -I$(SDKDIR)/../CMSIS_5/CMSIS/Core/Include
CFLAGS += -DARM_MATH_CM4
CFLAGS += -D__FPU_PRESENT=1

CXXFLAGS += -I$(SDKDIR)/../CMSIS_5/CMSIS/DSP/Include
CXXFLAGS += -I$(SDKDIR)/../CMSIS_5/CMSIS/Core/Include
CXXFLAGS += -DARM_MATH_CM4
CXXFLAGS += -D__FPU_PRESENT=1

EXTRA_LIBS += -larm_cortexM4lf_math
EXTRA_LIBPATHS += -L$(SDKDIR)/../CMSIS_5/CMSIS/Lib/GCC

サンプルアプリケーション

ソースコードだけ貼り付けておきます。sine関数を計算して出力します。

/****************************************************************************
 * Included Files
 ****************************************************************************/

#include <sdk/config.h>
#include <stdio.h>

#include <arm_math.h>

/****************************************************************************
 * Public Functions
 ****************************************************************************/

/****************************************************************************
 * cmsis_main
 ****************************************************************************/

#ifdef CONFIG_BUILD_KERNEL
int main(int argc, FAR char *argv[])
#else
int cmsisdsp_main(int argc, char *argv[])
#endif
{
  int i;
  float theta;
  
  for ( i = 0; i<100; i++ ) 
  {
      theta = i * 3.1415*2 / 100.0;
      printf("arm_sin_f32(%8.5g) : %8.5g\n", theta, arm_sin_f32(theta) );
  }

  return 0;
}

このプログラムを書いた時に気がついたのですが、NuttXのprintf()関数は、浮動小数点型を出力する際フォーマット文字列で明示的にフィールド幅と小数点以下の数字を指示する必要があるようです。最初は無指定で出力していたのですが、四捨五入されて整数として表示されるので困惑しました。

実行結果はこんな感じになります。

CMSIS-DSPを使ったアプリケーションの実行結果
CMSIS-DSPを使ったアプリケーションの実行結果

スクリプト

CMSIS-DSPの環境設定用のスクリプトを以下に示します。Spresense SDKのインストールと、ターミナル・デバイス名の設定も混じっていますが、不要であれば適当に削ってください。spresenseディレクトリはホームディレクトリにあるものと仮定したスクリプトになっています。

Ubuntu 16.04 LTSで動作確認済みです。なおkermitの設定ファイルがspresense/sdkにコピーされますが、生のubuntu desktop 16.04 LTSにはckermitパッケージが入っていません。使ってみたい方はapt-getでインストールしてください。

########################################################################################
# Spresense SDK installation
########################################################################################
# based on https://developer.sony.com/ja/develop/spresense/developer-tools/get-started-using-nuttx/set-up-the-nuttx-environment

# Install the enssential ubuntu tools.
sudo apt-get install -yV git gperf libncurses5-dev flex bison gcc-arm-none-eabi genromfs pkg-config autoconf automake


# Download the NuttX configuration tool, build and install
cd ~
mkdir nuttxtool
cd nuttxtool
git clone https://bitbucket.org/nuttx/tools.git
cd tools/kconfig-frontends/
./configure --disable-shared
make
sudo make install
cd ~
rm nuttxtool -rf

# Clone the Spresense SDK repo.
cd ~
git clone --recursive git@github.com:sonydevworld/spresense.git

########################################################################################
# CMSIS-DSP installation
########################################################################################
# Clone CMSIS-5
cd ~/spresense
git clone https://github.com/ARM-software/CMSIS_5.git
cd CMSIS_5
git checkout master
git pull


# Additional definition to use CMSIS-5-DSP
cat >> ~/spresense/sdk/Make.defs <<-'EOF'

    CFLAGS += -I$(SDKDIR)/../CMSIS_5/CMSIS/DSP/Include
    CFLAGS += -I$(SDKDIR)/../CMSIS_5/CMSIS/Core/Include
    CFLAGS += -DARM_MATH_CM4
    CFLAGS += -D__FPU_PRESENT=1

    CXXFLAGS += -I$(SDKDIR)/../CMSIS_5/CMSIS/DSP/Include
    CXXFLAGS += -I$(SDKDIR)/../CMSIS_5/CMSIS/Core/Include
    CXXFLAGS += -DARM_MATH_CM4
    CXXFLAGS += -D__FPU_PRESENT=1

    EXTRA_LIBS += -larm_cortexM4lf_math
    EXTRA_LIBPATHS += -L$(SDKDIR)/../CMSIS_5/CMSIS/Lib/GCC

EOF

########################################################################################
# Terminal device setting for Spresense
########################################################################################
# Terminal device name setting as /dev/ttySPRESENSE
sudo cat <<-'EOF' | sudo tee /etc/udev/rules.d/52-spresense.rules > /dev/null
    # SONY SPRESENSE ( main board )
    # The deivce will be linked to /dev/ttySPRESENSE

    SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE="0666", SYMLINK+="ttySPRESENSE"

    # If you have more than 1 CP210x devices connected to system, 
    # you can not distinguish them correctly by above declaration. 
    # In this case, you need to specify the unique serial number of 
    # your SPRESENSE device.
    # In the following description, we assume your SPRESENSE board is 
    # registered as /dev/ttyUSB0

    # First of all, comment out the above declaration. 
    # Then, run following command in the console. 
    # sudo udevadm info -n /dev/ttyUSB0 | grep  SERIAL_SHORT

    # Now, you will see the output like this 
    # E: ID_SERIAL_SHORT=b869b9acca27e811a67ce54aa9a0087c

    # where b869.... is the unique serial number copy your displayed 
    # strings and substitute the serial number of the following 
    # declaration by your device's one.
    # Then, remove "#" of the following line to enable it. 

    # SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", ATTRS{serial}=="b869b9acca27e811a67ce54aa9a0087c", MODE="0666", SYMLINK+="ttySPRESENSE"

EOF

# Make a script file for kermit
cat  > ~/spresense/sdk/terminal <<- 'EOF'
    #!/usr/bin/kermit +
    set line /dev/ttySPRESENSE
    set speed 115200
    set carrier-watch off
    set flow-control none

EOF
chmod +x ~/spresense/sdk/terminal

 

コメントする

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください