Developer World Spresense
English 中文
目次

1. Examples 一覧

Spresense SDKでは、NuttShell の Built-in コマンドとして各種 Example を用意しています。

SDK v2.0 以降から NuttX オリジナルのアプリケーションも Examples に追加されています。

(SDK v1.x 以前のバージョンのチュートリアルは こちら を参照してください)

初めてビルドする方は、はじめにスタートガイドを参照してください。 コンフィグレーションの方法や、ビルドしたプログラムを実行する手順についての詳しい説明があります。

1.1. SDK examples

カテゴリ Example名 説明

Peripheral
Driver

adc_monitor

A/Dコンバータを使用してアナログ入力値を表示するサンプルです。

GPS (GNSS)

gnss

GNSS機能を用いて位置情報を取得するサンプルです。

geofence

GNSS Geofence機能を使用したサンプルです。

gnss_atcmd

GNSS ATコマンドを使用したサンプルです。ターミナル上にNMEAセンテンスを表示します。

gnss_factory

GNSS 評価用のサンプルです。

gnss_pvtlog

GNSS PVTログを出力するサンプルです。

Audio

audio_player

オーディオプレーヤーのサンプルです。

audio_recorder

オーディオレコーダーのサンプルです。

audio_through

オーディオのパススルー機能を用いて、マイク入力、スピーカ出力、I2S入出力を使用したサンプルです。

audio_pcm_capture

PCMデータをキャプチャするサンプルです。

audio_recognizer

音声認識フレームワークのサンプルです。

audio_beep

オーディオビープ音を再生するサンプルです。

audio_dual_players

オーディオのデュアルデコード再生のサンプルです。

audio_player_objif

オブジェクトインターフェース層を用いたオーディオプレーヤーのサンプルです。

audio_recorder_objif

オブジェクトインターフェース層を用いたオーディオレコーダーのサンプルです。

audio_pcm_capture_objif

オブジェクトインターフェース層を用いたPCMキャプチャのサンプルです。

audio_sound_effector

低遅延で音声エフェクトを行うサンプルです。

ASMP

asmp

ASMPフレームワークによるマルチコアを使用したサンプルです。

prime

マルチコアを使用して素数計算を行うサンプルです。

fft

マルチコアを使用してFFT演算を行うサンプルです。

Sensor

accel

加速度センサからセンサ情報を取得するサンプルです。

gyro

ジャイロセンサからセンサ情報を取得するサンプルです。

light

照度センサからセンサ情報を取得するサンプルです。

mag

地磁気センサからセンサ情報を取得するサンプルです。

press

気圧センサからセンサ情報を取得するサンプルです。

proximity

近接センサからセンサ情報を取得するサンプルです。

colorsensor

カラーセンサからセンサ情報を取得するサンプルです。

tilt

加速度センサを使用して傾き検出を行うサンプルです。

decimator

SCUによるデシメータ機能を使って間引き処理を行うサンプルです。

step_counter

加速度センサによる歩数計及び行動認識を行うサンプルです。

Camera

camera

カメラ機能のサンプルです。

multi_webcamera

マルチウェブカメラアプリケーションのサンプルです。

JPEG

jpeg_decode

JPEGデコードのサンプルです。

DNN

dnnrt_lenet

DNN Runtime機能を使用して、数字認識を行うサンプルです。

LTE

lte_http_get

LTE通信機能を用いて、HTTP GETを行うサンプルです。

lte_tls

LTE通信機能を用いて、TLS通信を行うサンプルです。

lte_websocket

LTE通信機能を用いて、WebSocket通信を行うサンプルです。

lte_mqtt

LTE通信機能を用いて、MQTT通信を行うサンプルです。

lte_lwm2m

LTE通信機能を用いて、Lightweight M2M(LWM2M)通信を行うサンプルです。

lte_awsiot

LTE通信機能を用いて、AWS IoTと接続するサンプルです。

Others

setjmp

setjmp()/longjmp() 関数を使用したサンプルです。

1.2. NuttX examples

カテゴリ Example名 説明

Hello

hello

C言語による"Hello, World"を出力するサンプルです。

helloxx

C++言語による"Hello, World"を出力するサンプルです。

Peripheral
Driver

alarm

RTC(リアルタイムクロック)によるアラーム機能を使用したサンプルです。

watchdog

WDTウォッチドッグタイマーを使用したサンプルです。

pwm

PWM出力を行うサンプルです。

Graphics

nx

NX graphics機能を用いて、描画するサンプルです。

nxhello

NX graphics機能を用いて、"Hello"を描画するサンプルです。

nximage

NX graphics機能を用いて、ビットマップを描画するサンプルです。

nxlines

NX graphics機能を用いて、線を描画するサンプルです。

nxtext

NX graphics機能を用いて、テキストを描画するサンプルです。

Network

ftpc

FTP 転送(Client)を行うサンプルです。

ftpd

FTP 転送(Server)を行うサンプルです。

tcpecho

TCP 通信でエコーを行うサンプルです。

tcpblaster

Server/Client 間で TCP 通信を行うサンプルです。

Sensor

bmi160

BMI160加速度/ジャイロの6軸センサを使用したサンプルです。

Battery

charger

充電機能のサンプルです。(Spresenseボードでは充電機能はサポートされていません)

Others

json

cJSON ライブラリを用いた JSON パーサーのサンプルです。

inidumper

inih ライブラリを用いて ini ファイルをパースするサンプルです。

pdcurses

PDCurses 機能を動かすサンプルです。

embedlog

embedlog ライブラリを用てロギングを行うサンプルです。

2. Peripheral Driver チュートリアル

2.1. RTC alarm サンプルアプリケーション

RTC alarm サンプルアプリケーションの動作について説明します。

2.1.1. ビルド手順

ここではコマンドラインによるビルド手順を示します。
IDE を使用してビルドする場合、以下に示すコンフィグレーション情報を参考にしてください。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に examples/alarm を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    tools/config.py examples/alarm
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

2.1.2. 動作確認

シリアルターミナルを開いて、alarm コマンドを実行します。

  1. シリアルターミナルを起動します。

    シリアルポートに /dev/ttyUSB0 を、baudrate に 115200 bps を指定して、 minicom ターミナルを使用する例を示します。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から alarm コマンドを実行します。

    alarm コマンドの使い方を以下に示します。

    nsh> alarm
    ERROR: Invalid number of arguments: 0
    USAGE:
            alarm <seconds>
    Where:
            <seconds>
                    The number of seconds until the alarm expires.

    <seconds> には相対時間(秒)を指定します。例えば、alarm 5 と入力すると、5 秒後にアラームが発火します。

    nsh> alarm 5
    alarm_daemon started
    alarm_daemon: Running
    Opening /dev/rtc0
    Alarm 0 set in 5 seconds
    nsh> alarm_demon: alarm 0 received

2.1.3. 省電力機能と組み合わせて使用する

alarm コマンドと省電力機能を組み合わせて使用する例について紹介します。

Spresense には、Deep Sleep や Cold Sleep モードといった省電力機能が提供されています。 poweroff コマンドを用いてこれらの Sleep 状態に入ることができます。 そして、RTC アラーム機能により、この Sleep 状態から起床することができます

Deep Sleep や Cold Sleep について、詳しくは スリープモード を参照してください。

2.1.3.1. Deep Sleep モードからの起床

以下の例では、10 秒後にアラームを設定してから poweroff コマンドにより Deep Sleep モードに入ります。
10 秒後にアラームが発火して Deep Sleep 状態から起床します。

nsh> alarm 10
alarm_daemon started
alarm_daemon: Running
Opening /dev/rtc0
Alarm 0 set in 10 seconds
nsh> poweroff

NuttShell (NSH) NuttX-8.2
nsh>
2.1.3.2. Cold Sleep モードからの起床

以下の例では、10 秒後にアラームを設定しておいて、poweroff 1 により Cold Sleep モードに入ります。
10 秒後にアラームが発火して Cold Sleep 状態から起床します。

nsh> alarm 10
alarm_daemon started
alarm_daemon: Running
Opening /dev/rtc0
Alarm 0 set in 10 seconds
nsh> poweroff 1

NuttShell (NSH) NuttX-8.2
nsh>

2.1.4. その他の RTC に関するコマンド

date コマンドにより、RTC に時刻を設定したり、RTC に設定された現在時刻を表示することができます。

nsh> help date
date usage:  date [-s "MMM DD HH:MM:SS YYYY"]

例)RTC に 2019年12月1日23時34分56秒を設定する場合、

nsh> date -s "Dec 1 23:34:56 2019"

date コマンドにより現在時刻を表示します。

nsh> date
Dec 01 23:35:14 2019

RTC は、Deep/Cold Sleep といったスリープ中や reboot コマンドにより再起動した場合でも時刻を保持し続けます。ただし、電源供給がオフされたり、リセットボタンが押された場合は、RTC に設定された時刻はリセットされます。

以下に reboot コマンドによる再起動後も時刻が保持されている例を示します。

nsh> date
Dec 01 23:41:08 2019
nsh> reboot

NuttShell (NSH) NuttX-8.2
nsh> date
Dec 01 23:41:12 2019
nsh>

2.2. Watchdog サンプルアプリケーション

Watchdog サンプルアプリケーションの動作について説明します。

2.2.1. ビルド手順

ここではコマンドラインによるビルド手順を示します。
IDE を使用してビルドする場合、以下に示すコンフィグレーション情報を参考にしてください。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に examples/watchdog を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    tools/config.py examples/watchdog
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

2.2.2. 動作確認

シリアルターミナルを開いて、wdog コマンドを実行します。

  1. シリアルターミナルを起動します。

    シリアルポートに /dev/ttyUSB0 を、baudrate に 115200 bps を指定して、 minicom ターミナルを使用する例を示します。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から wdog コマンドを実行します。

    wdog コマンドの使い方を以下に示します。

    nsh> wdog -h
    Usage: wdog [-h] [-d <pingdelay>] [-p <pingtime>] [-t <timeout>]
    
    Initialize the watchdog to the <timeout>. Start the watchdog
    timer. Ping for the watchdog for <pingtime> seconds, then let it expire.
    
    Options include:
      [-d <pingdelay>] = Time delay between pings in milliseconds. Default: 500
      [-p <pingtime>] = Selects the <pingtime> time in milliseconds. Default: 5000
      [-t timeout] = Time in milliseconds that the example will ping the watchdog
        before letting the watchdog expire. Default: 2000
      [-h] = Shows this message and exits
    -d

    指定された周期 [msec] で ioctl(fd, WDIOC_KEEPALIVE, 0) を呼び出すことで watchdog タイマーをクリアします。

    -p

    指定された期間中 [msec] は watchdog をクリアし続けます。

    -t

    指定された値 [msec] で ioctl(fd, WDIOC_SETTIMEOUT, (unsigned long)wdog.timeout) を呼び出しwatchdog タイマーの周期を設定します。

本サンプルアプリケーションは、watchdog タイマーの発火に伴いシステムがリブートすることを確認できます。

wdog コマンドを実行した例を以下に示します。 引数無しで動作させたときは、デフォルト値の 2 秒で watchdog タイマー周期を設定します。 5 秒間は 500 msec 周期で watchdog タイマーをクリアし続けます。 その後、watchdog タイマーをクリアしないままタイマーが満了してシステムがリブートします。

nsh> wdog
  ping elapsed=0
  ping elapsed=500
  ping elapsed=1000
  ping elapsed=1500
  ping elapsed=2000
  ping elapsed=2500
  ping elapsed=3000
  ping elapsed=3500
  ping elapsed=4000
  ping elapsed=4500
  NO ping elapsed=5000
  NO ping elapsed=5500
  NO ping elapsed=6000
up_assert: Assertion failed at file:irq/irq_unexpectedisr.c line: 65 task: Idle Task
up_dumpstate: sp:     0d0279d4
up_dumpstate: IRQ stack:
up_dumpstate:   base: 0d027a00
up_dumpstate:   size: 00000800
up_dumpstate:   used: 00000120
up_stackdump: 0d0279c0: 00000000 0d003e3d 0d0291a8 0d02975c 00000000 00000002 466cc9d4 0d002f69
up_stackdump: 0d0279e0: 0d002f55 0d00703d 00000000 0d02975c 0d028a20 00000003 00000000 0d006fd5
up_dumpstate: sp:     0d029830
up_dumpstate: User stack:
up_dumpstate:   base: 0d029840
up_dumpstate:   size: 00000400
up_dumpstate:   used: 00000000
up_stackdump: 0d029820: 9b7feebc 1f86add5 00000000 0d002e75 0d029844 001567bc 2df7cabf 00000000
up_registerdump: R0: 00000000 0d026bcc 0d02df68 00000014 0d026b54 0d028a20 00000003 00000000
up_registerdump: R8: 0d026ca0 f0bbaf7f dc9161d8 466cc9d4 00000003 0d029830 0d002e79 0d008792
up_registerdump: xPSR: 21000000 BASEPRI: 00000000 CONTROL: 00000000
up_registerdump: EXC_RETURN: ffffffe9
up_taskdump: Idle Task: PID=0 Stack Used=0 of 0
up_taskdump: hpwork: PID=1 Stack Used=344 of 2028
up_taskdump: lpwork: PID=2 Stack Used=352 of 2028
up_taskdump: lpwork: PID=3 Stack Used=352 of 2028
up_taskdump: lpwork: PID=4 Stack Used=352 of 2028
up_taskdump: init: PID=5 Stack Used=1032 of 8172
up_taskdump: cxd56_pm_task: PID=6 Stack Used=320 of 996
up_taskdump: wdog: PID=8 Stack Used=528 of 2028

NuttShell (NSH) NuttX-8.2
nsh>

2.3. ADC サンプルアプリケーション

この章では、ADC サンプルアプリケーションの動作手順を示します。

2.3.1. ビルド手順

CLI 版を使ったビルド手順について書かれていますが、IDE 版でも同様のコンフィグレーションを選択することにより本サンプルアプリケーションをビルドすることができます。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、コンフィグレーションツールのTab補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に examples/adc_monitor を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    tools/config.py examples/adc_monitor
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate として 500000 bps を設定しています。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

2.3.2. 動作確認

シリアルターミナルを開いて、adc_monitor コマンドを実行します。

  1. シリアルターミナルを起動します。

    以下は、minicom ターミナルを使用する例です。 シリアルポートとして /dev/ttyUSB0 を、baudrate として 115200 bps を設定しています。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から adc_monitor コマンドを実行します。

    adc_monitor コマンドの Usage を以下に示します。

    nsh> adc_monitor -h
    Usage: adc_monitor [OPTIONS]
    
    Arguments are "sticky".  For example, once the ADC device is
    specified, that device will be re-used until it is changed.
    
    "sticky" OPTIONS include:
      [-p devpath] selects the ADC device.  /dev/lpadc0, 1, 2, 3, /dev/hpadc0, 1  Current: /dev/lpadc0
      [-n count] set the number of reads.  Current: 10
      [-h] shows this message and exits
    -p

    全部で 6 つの ADC 専用端子があります。-p オプションにより、-p /dev/lpadc[0-3] もしくは /dev/hpadc[0-1] を指定します。 Spresense ボード上のピン番号とデバイスファイルの関係は下記の通りです。

    ピン番号

    A0

    A1

    A2

    A3

    A4

    A5

    /devファイル

    /dev/lpadc0

    /dev/lpadc1

    /dev/lpadc2

    /dev/lpadc3

    /dev/hpadc0

    /dev/hpadc1

    -n

    測定回数を指定します。

例えば、HPADC0 (A4) に対して、10 回分の ADC データ取得を行います。 HPADC0 に対して、ADC データをバッファリングし、その平均値、最小値、最大値を表示します。 ADC データは 16bit の符号付きデータで、範囲は -32767 ~ 32767 です。

nsh> adc_monitor -p /dev/hpadc0 -n 10
ADC example - Name:/dev/hpadc0 bufsize:16
Ave:-32767 Min:-32767 Max:-32767 Cnt:8
Ave:-32767 Min:-32767 Max:-32767 Cnt:8
Ave:-32767 Min:-32767 Max:-32767 Cnt:8
Ave:14673 Min:14668 Max:14676 Cnt:8
Ave:14681 Min:14677 Max:14684 Cnt:8
Ave:14690 Min:14687 Max:14694 Cnt:8
Ave:14684 Min:14680 Max:14690 Cnt:8
Ave:14677 Min:14672 Max:14682 Cnt:8
Ave:14677 Min:14675 Max:14682 Cnt:8
Ave:14672 Min:14667 Max:14677 Cnt:8
ADC example end

2.3.3. ADC サンプリング周波数について

ADC のサンプリング周波数は SCU clock mode により選択されたクロックに依存します。

tutorial scu clock
2.3.3.1. HPADC (High Performance ADC)

HPADC は高速サンプリングが可能な ADC です。

HPADC の クロック系統図を以下に示します。

diag 9ccfe34bb7113fe90709ffcf1dcc8c2e

クロックソースを固定分周して HPADC クロックが決まります。 その ADC クロックを 2 のべき乗で分周してサンプリング周波数が決定されます。

n の値は、次の SDK コンフィグレーションにより変更することができます。

System Type -> CXD56xx Package Configuration -> Peripheral Support ->
  ADC -> HPADC0 -> Coefficient of sampling frequency (CONFIG_CXD56_HPADC0_FREQ)
  ADC -> HPADC1 -> Coefficient of sampling frequency (CONFIG_CXD56_HPADC1_FREQ)
tutorial hpadc coef

n の取りうる範囲は、SCU clock mode によって変わります。

  1. SCU clock mode = RTC の場合

    n 9 10 11

    Fs(Hz)

    64

    32

    16

    Available

  2. SCU clock mode = RCOSC/XOSC の場合

    n 0 1 2 3 4 5 6 7(*)

    Fs(Hz)

    2M

    1M

    512K

    256K

    128K

    64K

    32K

    16K

    Available

    ×

    ×

    ×

    ×

    ×

    (*): デフォルトは SCU clock mode = RCOSC, Coefficient = 7 が選択されています。

2.3.3.2. LPADC (Low Power ADC)

LPADC は HPADC に比べてサンプリングレートは低速ですが省電力で動作する ADC です。 LPADC のクロック系統図を以下に示します。

diag 5f3002e51d27ea8e330c733bd666b326

LPADC を RTC クロックをベースに動作します。そのクロックを 2 のべき乗で分周してサンプリング周波数が決定されます。

n の値は、次の SDK コンフィグレーションにより変更することができます。

System Type -> CXD56xx Package Configuration -> Peripheral Support ->
  ADC -> LPADC0 -> Coefficient of sampling frequency (CONFIG_CXD56_LPADC0_FREQ)
  ADC -> LPADC1 -> Coefficient of sampling frequency (CONFIG_CXD56_LPADC1_FREQ)
  ADC -> LPADC2 -> Coefficient of sampling frequency (CONFIG_CXD56_LPADC2_FREQ)
  ADC -> LPADC3 -> Coefficient of sampling frequency (CONFIG_CXD56_LPADC3_FREQ)
tutorial lpadc coef

n の取りうる範囲は、SCU clock mode によって変わります。 また、LPADC は全部で 4 チャンネルありますが、1 ch のみ使用する場合、2ch で使用する場合、4ch で使用する場合 でもサンプリング周波数の上限値が変わります。それぞれのケースで、n の取りうる値を以下に示します。

tutorial lpadc ch
  1. SCU clock mode = RTC の場合

    1. LPADC channel 0 ~ 3 のいずれか一つのチャンネルを選択した場合

      n 11 12 13 14 15

      Fs(Hz)

      16

      8

      4

      2

      1

      Available

    2. LPADC channel 0 and 1 の二つのチャンネルを選択した場合

      n 12 13 14 15

      Fs(Hz)

      4

      2

      1

      0.5

      Available

    3. LPADC channel 0 ~ 3 の四つのチャンネルを選択した場合

      n 11 12 13 14 15

      Fs(Hz)

      4

      2

      1

      0.5

      0.25

      Available

  2. SCU clock mode = RCOSC の場合

    1. LPADC channel 0 ~ 3 のいずれか一つのチャンネルを選択した場合

      n 3 4 5 6 7 8 9 10 11 12 13 14 15

      Fs(Hz)

      4K

      2K

      1K

      512

      256

      128

      64

      32

      16

      8

      4

      2

      1

      Available

    2. LPADC channel 0 and 1 の二つのチャンネルを選択した場合

      n 6 7 8 9 10 11 12 13 14 15

      Fs(Hz)

      256

      128

      64

      32

      16

      8

      4

      2

      1

      0.5

      Available

    3. LPADC channel 0 ~ 3 の四つのチャンネルを選択した場合

      n 7(*) 8 9 10 11 12 13 14 15

      Fs(Hz)

      64

      32

      16

      8

      4

      2

      1

      0.5

      0.25

      Available

      (*): デフォルトは LPADC 全チャンネル有効で SCU clock mode = RCOSC, Coefficient = 7 が選択されています。

  3. SCU clock mode = XOSC の場合

    1. LPADC channel 0 ~ 3 のいずれか一つのチャンネルを選択した場合

      n 2 3 4 5 6 7 8 9 10 11 12 13 14 15

      Fs(Hz)

      8K

      4K

      2K

      1K

      512

      256

      128

      64

      32

      16

      8

      4

      2

      1

      Available

    2. LPADC channel 0 and 1 の二つのチャンネルを選択した場合

      n 6 7 8 9 10 11 12 13 14 15

      Fs(Hz)

      256

      128

      64

      32

      16

      8

      4

      2

      1

      0.5

      Available

    3. LPADC channel 0 ~ 3 の四つのチャンネルを選択した場合

      n 7 8 9 10 11 12 13 14 15

      Fs(Hz)

      64

      32

      16

      8

      4

      2

      1

      0.5

      0.25

      Available

2.4. PWM サンプルアプリケーション

PWM サンプルアプリケーションの動作について説明します。

2.4.1. ビルド手順

ここではコマンドラインによるビルド手順を示します。
IDE を使用してビルドする場合、以下に示すコンフィグレーション情報を参考にしてください。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に examples/pwm を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    tools/config.py examples/pwm
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

2.4.2. 動作確認

シリアルターミナルを開いて、pwm コマンドを実行します。

  1. シリアルターミナルを起動します。

    シリアルポートに /dev/ttyUSB0 を、baudrate に 115200 bps を指定して、 minicom ターミナルを使用する例を示します。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から pwm コマンドを実行します。

    pwm コマンドの使い方を以下に示します。

    nsh> pwm -h
    Usage: pwm [OPTIONS]
    
    Arguments are "sticky".  For example, once the PWM frequency is
    specified, that frequency will be re-used until it is changed.
    
    "sticky" OPTIONS include:
      [-p devpath] selects the PWM device.  Default: /dev/pwm0 Current: /dev/pwm0
      [-f frequency] selects the pulse frequency.  Default: 1000 Hz Current: 1000 Hz
      [-d duty] selects the pulse duty as a percentage.  Default: 50 % Current: 50 %
      [-t duration] is the duration of the pulse train in seconds.  Default: 5 Current: 5
      [-h] shows this message and exits

    例)PWM1 に対して、周期 2000 Hz、デューティー比 30 % の PWM 信号を 10 秒間出力します。

    nsh> pwm -p /dev/pwm1 -f 2000 -d 30 -t 10
    -p

    全部で 4 つの PWM 専用端子があります。-p オプションにより、-p /dev/pwm[0-3] を指定します。

    -f

    PWM 周期 [Hz] を設定します。

    -d

    デューティー比(周期に対する High 期間の割り合い) [%] は、1 ~ 99 までの数字を指定します。

    -t

    指定された時間 [s] の PWM 信号を出力します。

2.4.3. PWM 周波数とデューティー比について

PWM は SCU clock mode により選択されたクロックで動作します。

tutorial scu clock

SCU clock を以下に示します。

  • Same with SCU32K → RTC 32.768kHz

  • RCOSC → 約8.2MHz

  • XOSC → TCXO 26MHz を CONFIG_CXD56_SCU_XOSC_DIV(=2) で分周した 13MHz

PWM 信号の波形は、下図で表されるように SCU clock の PWM_CYCLE カウント数により周期が決まり、 PWM_THRESH カウント数により Low 出力の期間が決定されます。カウント数の上限は 0xffff です。

tutorial pwm

PWM で設定できる周波数の範囲は、

1 <= PWM frequency <= SCU clock / 2

となり、例えば、SCU clock が RCOSC を選択した場合は、1Hz ~ 約 4MHz までとなります。

デューティー比について、-d で指定された数字から計算上の近似値で Low, High の区間を決定するため、 出力される波形は正確なデューティー比にならず丸め誤差を含むことがあります。

3. GPS チュートリアル

3.1. GNSS サンプルアプリケーション

GNSS サンプルアプリケーションの動作について説明します。

3.1.1. ビルド手順

ここではコマンドラインによるビルド手順を示します。
IDE を使用してビルドする場合、以下に示すコンフィグレーション情報を参考にしてください。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に examples/gnss を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    tools/config.py examples/gnss
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

3.1.2. 動作確認

シリアルターミナルを開いて、gnss コマンドを実行します。

  1. シリアルターミナルを起動します。

    シリアルポートに /dev/ttyUSB0 を、baudrate に 115200 bps を指定して、 minicom ターミナルを使用する例を示します。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から gnss コマンドを実行します。

    tutorial gnss log1
    図 1. gnssコマンド起動時ログ

本アプリケーションを実行すると、はじめに /dev/gps ドライバを open() します。

  fd = open("/dev/gps", O_RDONLY);

openしたドライバに対して ioctl() を用いて、測定周期の設定や衛星システムの選択を行います。

  ret = ioctl(fd, CXD56_GNSS_IOCTL_SET_OPE_MODE, (uint32_t)&set_opemode);
  ret = ioctl(fd, CXD56_GNSS_IOCTL_SELECT_SATELLITE_SYSTEM, set_satellite);

ioctl() の CXD56_GNSS_IOCTL_START コマンドにより測位を開始します。

  ret = ioctl(fd, CXD56_GNSS_IOCTL_START, CXD56_GNSS_STMOD_HOT);

測位結果は、read() を用いて読みだすことができます。

  ret = read(fd, &posdat, sizeof(posdat));

本アプリケーションでは 1 秒周期で測位結果を表示します。
位置情報が取得できるまでの間は、"No Positioning Data"と表示されます。

Hour:0, minute:0, sec:3, usec:503
No Positioning Data

はじめに時刻情報を取得できたら、ターミナル上に UTC 時刻を表示します。
さらに位置情報を取得できたら次のように緯度、経度情報がターミナル上に表示されます。

Hour:9, minute:13, sec:20, usec:559
LAT 35.25.6303
LNG 139.22.1986

本アプリケーションは、位置情報を取得してから約200秒後に測位動作を終了します。
ioctl() の CXD56_GNSS_IOCTL_STOP コマンドにより測位を停止した後に、/dev/gps ドライバを close() します。

  ret = ioctl(fd, CXD56_GNSS_IOCTL_STOP, 0);
  ret = close(fd);

上空がよく見える屋外など受信環境が良い場合は、約30秒~1分ぐらいで測位ができますが、 受信環境がよくない場合は測位するまでに数分かかる場合があります。

3.1.3. 参考

GNSS 機能の詳細は、開発ガイドを参照してください。

3.2. Geofence サンプルアプリケーション

Geofence サンプルアプリケーションの動作について説明します。

Geofence は、GNSS で取得される位置情報を使って、特定のリージョンに入る・抜ける・一定期間滞在している、 といったイベントを検出しアプリケーションに通知する機能を提供します。そのリージョンは、中心座標(緯度経度)とその半径によって 指定され、ユーザーが任意の位置を最大 20 地点まで登録することができます。

3.2.1. ビルド手順

ここではコマンドラインによるビルド手順を示します。
IDE を使用してビルドする場合、以下に示すコンフィグレーション情報を参考にしてください。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に examples/geofence を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    tools/config.py examples/geofence
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

3.2.2. 動作確認

シリアルターミナルを開いて、geofence コマンドを実行します。

  1. シリアルターミナルを起動します。

    シリアルポートに /dev/ttyUSB0 を、baudrate に 115200 bps を指定して、 minicom ターミナルを使用する例を示します。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から geofence コマンドを実行します。

    nsh> geofence

本アプリケーションでは、まず現在位置の情報を測位によって取得します。

その現在位置と、そこを起点として東西南北方向にそれぞれ 50 m ずつ離れた場所の計 5 つのリージョンを登録します。

現在位置の測位が完了しリージョンが設定された後に、デバイスを持ち歩いて移動することにより、 特定のリージョンに入った"ENTER"/抜けた"EXIT"/滞在している"DWELL"、といったステータスの情報がログ上に表示されます。

具体的な Geofence 機能の使い方については以下の通りです。

/dev/gps ドライバを open() して測位を行う方法は、 前述した GNSS サンプルアプリケーション を参照してください。

Geofence 機能を使用するためには /dev/geofence ドライバを open() します。

  g_fdgeo = open("/dev/geofence", O_RDONLY);

openしたドライバに対して ioctl() を用いて、Dead zone [m] や滞在通知期間 [s] を設定します。

  mode.deadzone         = 5;
  mode.dwell_detecttime = 10;
  ret = ioctl(g_fdgeo, CXD56_GEOFENCE_IOCTL_SET_MODE, (unsigned long)&mode);

ioctl() の CXD56_GEOFENCE_IOCTL_ADD コマンドにより、リージョンを追加します。

  region_xxx.id        = 0;
  region_xxx.latitude  = own_latitude;
  region_xxx.longitude = own_longitude;
  region_xxx.radius    = GEOFENE_REGION_RADIUS;

  ret = ioctl(g_fdgeo, CXD56_GEOFENCE_IOCTL_ADD, (unsigned long)&region_xxx);

ioctl() の CXD56_GEOFENCE_IOCTL_START コマンドにより、Geofence 動作を開始します。

  ret = ioctl(g_fdgeo, CXD56_GEOFENCE_IOCTL_START, 0);

Geofence イベントを poll() によって待ち受け、read() により情報を取得します。

  ret = read(g_fdgeo, &g_geofence_status, sizeof(struct cxd56_geofence_status_s));

本アプリケーションは、トータル 10 個のイベント通知がきたら Geofence 動作を終了します。
ioctl() の CXD56_GEOFENCE_IOCTL_STOP コマンドにより停止した後に、/dev/geofence ドライバを close() します。

  ret = ioctl(g_fdgeo, CXD56_GEOFENCE_IOCTL_STOP, 0);
  ret = close(g_fdgeo);

3.2.3. 参考

Geofence 機能の詳細は、開発ガイドを参照してください。

3.3. GNSS ATCMD アプリケーション

gnss_atcmd は Spresense SDK 上で動作する GNSS 機能評価用のサンプルアプリケーションです。 PC 等のホストからシリアルポートを介してコマンドを送信すると、そのシリアルポートに NMEA センテンスの結果が出力されます。具体的なコマンドの仕様とアプリケーションの使用例について示します。

3.3.1. ビルド手順

ここではコマンドラインによるビルド手順を示します。
IDE を使用してビルドする場合、以下に示すコンフィグレーション情報を参考にしてください。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    本アプリケーションを実行するためには、以下の SDK Configuration を有効にしてください。

    CONFIG_CXD56_GNSS=y
    CONFIG_GPSUTILS_CXD56NMEA_LIB=y
    CONFIG_EXAMPLES_GNSS_ATCMD=y

    下記のコマンド実行することでこれらの Configuration を自動的に有効にすることができます。

    ./tools/config.py examples/gnss_atcmd
    

    また、コマンド入出力に使用するポートを、コンフィグレーション GNSS Command IO によって切り替えることができます。

    │ Prompt: GNSS Command IO
    │   Location:
    │     -> Examples
    │       -> GNSS CXD5603 @command emulator example (EXAMPLES_GNSS_ATCMD [=y])
    • Example uses USB CDC tty : 拡張ボード上の USB ポートを使用 (デフォルト)

    • Example uses STDINOUT for nsh debug UART : メイン基板上の USB ポート (UART1)

    • Example uses UART ttyS0 : メイン基板上の USB ポート (UART1)

    • Example uses UART ttyS1 : 非サポート

    • Example uses UART ttyS2 : メインボード及び拡張ボード上の UART ポート (UART2)

      ビルドに成功すると sdk フォルダ直下に nuttx.spk というバイナリファイルが生成されます。

  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

3.3.2. @コマンド仕様

ホストから送信するコマンドの仕様について説明します。

PC 等のホストから送信されたコマンドを gnss_atcmd アプリケーションが受信し、処理結果をホストに返します。コマンド送信から結果が応答されるまでの期間は、NMEA は出力されません。gnss_atcmd アプリケーションからコマンド完了を示す応答メッセージ (Done または Err ) が返ってくる前に別のコマンドを発行しないようにして下さい。なお、コマンド送信からコマンド応答が返るまでの時間はコマンドの種別およびその時の状態により異なりますが、ワーストケースで約 5 秒かかることがあります。ホストコントローラにてタイムアウトを検出する際は 5 秒にてタイムアウトと判断して下さい。

3.3.2.1. コマンドフォーマット

コマンドの書式は以下の通りです。"@" (アットマーク)に続いてコマンド文字列や引数を送信し、最後に改行コードを送ります。

@Command [Argument0] [Argument1]...<CR><LF>
Command

4 文字以内の文字列です。詳細は下表 コマンド一覧 を参照してください。

Argument

10 進数で表される数値です。文字列の先頭が "0x" の場合は 16 進数を表します。 コマンドによっては複数の引数をとります。

<CR><LF>

改行コードを表します。コマンド行の終わりには CR (Carriage Return) + LF (Line Feed) を付けてください。

3.3.2.2. 正常応答フォーマット

正常応答結果の書式は以下の通りです。[送信したコマンド文字列]に続いて、"Done"の文字列が返ります。

[Command] Done<CR><LF>
Command

受信したコマンド文字列を表します。

<CR><LF>

改行を表します。応答行の終わりには CR (Carriage Return) + LF (Line Feed) が付加されています。

3.3.2.3. エラー応答フォーマット

エラー応答結果の書式は以下の通りです。[送信したコマンド文字列]に続いて、"Err"の文字列とエラーコードが返ります。

[Command] Err ErrorCode<CR><LF>
Command

受信したコマンド文字列を表します。

ErrorCode

負値のエラーコードを表します。

<CR><LF>

改行を表します。応答行の終わりには CR (Carriage Return) + LF (Line Feed) が付加されています。

3.3.2.4. コマンドシーケンス

@GCD のような測位開始のコマンドを発行すると、"Done" の応答を返した後に、定期的に NMEA センテンスが Host へ送られます。

diag 39f656ff7a75cce3fd8105715f5adca1

@VER コマンドを発行すると、バージョン情報が送られた後に、"Done" の応答が返ります。

diag aecaf2c20740a1432f3725e6be277c10
3.3.2.5. コマンド一覧

gnss_atcmd が処理可能なコマンド一覧を下記に示します。

Command Argument Description

@AEXT

-

アプリケーションを終了します。本コマンドは測位停止中に実行してください。

@BSSL

NMEAマスク

NMEA 0183 (ver 4.00) 規格で定義されているNMEAセンテンスのうち、 出力するNMEAセンテンスをビットマスク値で引数に指定します。 初期状態ではNMEAマスクには0xefが設定されています。

NMEA Bit Description

$xxGGA

0

時刻、緯度経度、標高、測位状態、DGPS基地局番号などの基本情報

$xxGLL

1

時刻、緯度経度、測位状態などGGAの簡易版

$xxGSA

2

衛星毎の使用不使用、DOP値

$xxGSV

3

可視衛星の衛星番号、仰角、方位角、信号強度

$xxGNS

4

時刻、緯度経度、測位状態

$xxRMC

5

時刻、緯度経度、速度、時期偏差

$xxVTG

6

移動速度に関する詳細情報

$xxZDA

7

年月日を含む時刻情報

$QZQSM

14

災害危機管理通報サービスメッセージ(QZSS独自センテンス)

xx は、以下を表します。

  • GP:GPS衛星で測位している場合

  • GL:GLONASS衛星で測位している場合

  • GZ:QZS衛星で測位している場合

  • BD:BeiDou衛星で測位している場合

  • GA:Galileo衛星で測位している場合

  • GN:複数の衛星システムを利用して測位している場合

コマンド例:

$xxGGAのみ出力を設定

@BSSL 0x1<CR><LF>

$xxRMCと$QZQSMの出力を設定

@BSSL 0x4020<CR><LF>

@BUP

-

受信済みのエフェメリス及び各種パラメータを Flash へセーブします。セーブされたデータは次回起動時に自動的にリストアされます。 本コマンドは測位停止中に実行して下さい。

@GCD

-

Cold Start による測位を開始し、NMEAセンテンスを周期的に出力します。出力されるNMEAセンテンスはNMEAマスクに従います。

@GNS

衛星マスク

測位に使用する衛星を引数のビットマスク値で選択します。
本コマンドは測位停止中に実行してください。
例)GPSの場合は 0x1、Hybridの場合は0x3を指定

Bit Satellite

0

GPS

1

GLONASS

2

SBAS(WAAS)補強

3

QZSS L1C/A補完(みちびき)

4

予約

5

QZSS L1S補強(みちびき)

6

BeiDou

7

Galileo

NOTE
GLONASS, Galileo, BeiDou に関して同時に使用することはできません。

コマンド例:

GPSを選択

@GNS 0x1<CR><LF>

GPS+GLONASS+QZSS L1C/Aを選択

@GNS 0xb<CR><LF>

GPS+BeiDou+QZSS L1C/Aを選択

@GNS 0x49<CR><LF>

GPS+Galileo+QZSS L1C/Aを選択

@GNS 0x89<CR><LF>

@GPOE

<緯度[度]>
<緯度[分]>
<緯度[秒]>
<経度[度]>
<経度[分]>
<経度[秒]>

楕円体座標の受信機現在位置を設定します。

コマンド例:

北緯35°37’09”,東経139°43’51”

@GPOE 35 37 09 139 43 51<CR><LF>

北緯33°07’19”,西経117°19’18”

@GPOE 33 07 19 -117 19 18<CR><LF>

@GSR

-

Hot Start による測位を開始し、NMEAセンテンスを周期的に出力します。
出力されるNMEAセンテンスはNMEAマスクに従います。

@GSTP

-

測位を停止します。

@GSW

-

Warm Start による測位を開始し、NMEAセンテンスを周期的に出力します。
出力されるNMEAセンテンスはNMEAマスクに従います。

@GTIM

<年>
<月>
<日>
<時>
<分>
<秒>

UTC時刻を設定します。

コマンド例:

2018/2/1 13:30'30"

@GTIM 2018 02 01 13 30 30<CR><LF>

2018/7/10 00:00'00”

@GTIM 2018 07 10 00 00 00<CR><LF>

@VER

-

ALLゼロのバージョン番号を返します。

3.3.3. 動作確認

シリアルターミナルを開いて、gnss_atcmd コマンドを実行します。

  1. シリアルターミナルを起動します。

    以下は、minicom ターミナルを使用する例です。 シリアルポートとして /dev/ttyUSB0 を、baudrate として 115200 bps を設定しています。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から gnss_atcmd コマンドを実行します。

    以下に示す例は、コマンド入出力のターミナルとして NuttShell と同じメイン基板上の USB ポートを使用しています。 前述した GNSS Command IO のコンフィグレーションは、"Example uses STDINOUT for nsh debug UART" を選択しています。

    • Example uses USB CDC tty

    • Example uses STDINOUT for nsh debug UART

    • Example uses UART ttyS0

    • Example uses UART ttyS1

    • Example uses UART ttyS2

3.3.3.1. 例: Cold Start による測位の開始と停止

GPS、Glonass、QZSS L1C/A を測位衛星として選び、Cold Start で測位を開始します。 その後 NMEA センテンスが出力され、適当な期間の後、測位を停止して gnss_atcmd を終了します。

nsh> gnss_atcmd       (アプリケーション開始)
@GNS 0x0b↵         (測位衛星の選択)
@GCD↵             (Cold Start測位開始)

----- <NMEA出力> ----

@GSTP↵            (測位停止)
@AEXT↵           (アプリケーション終了)
nsh>

3.3.3.2. 例: GNSS 終了後の Hot Start 測位

初めに GPS、Glonass、QZSS L1C/A を測位衛星として選び、Cold Start で測位を開始します。 測位された後に、Spresense の電源は保ちつつ GNSS を終了し、再度 Hot Start で測位を開始します。 Hot Start では測位開始から数秒後に測位が FIX します。

nsh> gnss_atcmd       (アプリケーション開始)
@GNS 0x0b↵         (測位衛星の選択)
@GCD↵             (Cold Start測位開始)

----- <NMEA出力> ----

@GSTP↵            (測位停止)
@AEXT↵           (アプリケーション終了)

nsh> gnss_atcmd       (アプリケーション開始)
@GSR↵             (Hot Start測位開始)

----- <NMEA出力> ----

@GSTP↵           (測位停止)
@AEXT↵           (アプリケーション終了)
nsh>

3.3.3.3. 例: Spresense 電源 OFF 後の Hot Start 測位

初めに GPS、Glonass、QZSS L1C/A を測位衛星として選び、Cold Start で測位を開始します。 その後、GNSS を終了した後に Spresense の電源を OFF します。

再度 Spresense の電源を入れた後、UTC 時刻と現在位置を入力して Hot Start で測位を開始します。 Hot Start では測位開始から数秒後に測位が FIX します。

nsh> gnss_atcmd       (アプリケーション開始)
@GNS 0x0b↵         (測位衛星の選択)
@GCD↵             (Cold Start測位開始)

----- <NMEA出力> ----

@GSTP↵            (測位停止)
@BUP↵              (Flashへバックアップ)
@AEXT↵           (アプリケーション終了)

----- <Power OFF> -----

----- <Power ON> -----

nsh> gnss_atcmd       (アプリケーション開始)
@GTIM 2018 11 09 02 45 05↵   (UTC 時刻設定)
@GPOE 35 39 31 139 44 05↵  (現在位置の設定)
@GSR↵             (Hot Start測位開始)

----- <NMEA出力> ----

@GSTP↵           (測位停止)
@AEXT↵           (アプリケーション終了)
nsh>

3.3.3.4. みちびきQZQSMセンテンスの出力

衛星マスクにQZSS L1/CAを選び、NMEAマスクでQZQSMセンテンスを有効にした後、測位を開始します。 受信条件が良ければ10秒弱で最初のQZQSMセンテンスが出力され、その後4秒毎に出力されます。

nsh> gnss_atcmd

@GNS 0x29↵

@BSSL 0x40ef↵

@GCD↵

$GPGGA,000001.00,,,,,0,00,,,,,,,*49 $GNGLL,,,,,000001.00,V,N*55
…​
$GNZDA,000008.00,06,01,1980,,*77 $QZQSM,56,9AADF260540002C3F2587F8B101962082C41A588ACB1181623500011439023C*7B $GPGGA,000009.00,,,,,0,00,,,,,,,*41
…​

4. Audio チュートリアル

4.1. Audio Player サンプルアプリケーション

Audio Player サンプルアプリケーションの動作について説明します。

4.1.1. ビルド&ロード手順

ここではコマンドラインによるビルド手順を示します。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に examples/audio_player を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    tools/config.py examples/audio_player
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    
  4. Audio Playerの場合、デコード処理を行うDSPバイナリのロードが必要です。 DSPバイナリの置き場所は、SDカードか、SPI-Flashのどちらかを選択できますが、 ここでは、SDカードからロードする方法を行います。

    DSPバイナリのパスの指定は、アプリケーションコード(audio_player_main.cxx)内で指定します。 audio_player_main.cxx では DSPBIN_FILE_PATH で指定しています。

    #define DSPBIN_FILE_PATH "/mnt/sd0/BIN"

    であれば、SDカードが指定されています。

    SPI-flashにしたい場合は、"/mnt/spif/BIN" を指定してください。

    この "/mnt/sd0/BIN" は、SDカードをPCで読み込んだ時の、ルートディレクトリの下の BIN/ です。
    このディレクトリを作成し、ここに必要なコーデックのDSPを置きます。

    MP3を再生(デコード)する場合は、
    spresense/sdk/modules/audio/dsp/ の下の MP3DEC を選択してください。

  5. 同時に、再生したい音楽ファイルをSDカードに書き込みます。 audio_player_main.cxx では、 PLAYBACK_FILE_PATH で指定しています。

    #define PLAYBACK_FILE_PATH "/mnt/sd0/AUDIO"

    このため、SDカードをPC上で読み込んだ時に、ルートディレクトリの下の AUDIO/ 以下に、 再生したいオーディオファイルを置いて下さい。サブディレクトリに置くこともできます。

  6. 現在のAudio Playerサンプルでは、簡易PlayListを利用した再生を行っています。 このため、playlistファイルの置き場所とファイル名を指定して再生します。 audio_player_main.cxx では、 PLAYLIST_FILE_PATH でパスを指定、 PLAYLIST_FILE_NAME でファイル名を指定しています。

    #define PLAYLIST_FILE_PATH "/mnt/sd0/PLAYLIST"
    #define PLAYLIST_FILE_NAME "TRACK_DB.CSV"

    このため、SDカードをPC上で読み込んだ時の、ルートディレクトリの下の PLAYLIST/ 以下に、 TRACK_DB.CSV というファイルを作成してください。

    TRACK_DB.CSV の中身は、 spresense/sdk/modules/audio/playlist/ の下の README.txt を参照してください。

これらすべてを用意することで、音楽再生が行えます。

4.1.2. Audio Playerの動作確認

この nuttx.spk を実機へロードするとAudio Playerのプログラムが実行されます。

Helloサンプルと同様に、シリアルターミナルを開きます。

minicom -D /dev/ttyUSB0 -b 115200 -s

builtinされている、 audio_player アプリを実行すると、

tutorial player log
図 2. 音楽再生時ログ

というログが表示され、音声が再生されます。

エラーが発生した場合は、オーディオサブシステムのエラーについて を参照してください。

4.1.3. 付録: 独自の信号処理を行う

これまでのチュートリアルで、オーディオプレーヤーとして十分な機能を実現することができました。
ここからは、より高度な処理を行う方法を説明していきます。

AudioPlayerでは、再生する音声に対してユーザー独自の信号処理を行うことが出来ます。
これを行いたい場合にはコンフィグメニューで [Use Postprocess] を有効にする必要があります。

  1. Postprocessを有効にします

    tools/cofig.py -m
    

    [Use Postprocess] にチェックを入れます。

    [Examples]
      [Audio player example]
        [Use Postprocess]        <= Y
    Postrocessの詳細についてはSDKデベロッパーガイドの Set preprocess を参照して下さい。
  2. ビルドを行います。

    make
    

    全ての手順がうまくいけば、 POSTPROC バイナリが spresense/examples/audio_player/worker/ の下に作成されます。
    これをSDカードの /mnt/sd0/BIN (PCから見ると BIN/ )フォルダに置いてください。

    本サンプルアプリケーションでは、 POSTPROC には簡単なRCfilterがデフォルトで組み込まれています。
    独自の信号処理などにカスタムをしたい場合には こちら を参考にして下さい。

    [Use Postprocess] の有効、無効で音声ファイルを再生し違いを確認してみてください。
    再生方法はこちら を参考にして下さい。

4.1.4. DSPバイナリ(POSTPROC)のカスタムについて

DSPバイナリ(POSTPROC)のカスタム方法について記載します。

4.1.4.1. Step1. POSTPROCのコード編集

POSTPROCのコード構成と編集箇所について説明します。
コードは、ユーザー編集すべき部分とフレームワークとして提供される部分の2つに分かれます。

ユーザーが編集するコード

ユーザーが主に編集すべきコードです。
これらのコードを編集してDSPで信号処理を記述することが出来ます。

worker ディレクトリの中にDSPのコードがまとまっており、その中に userproc ディレクトリがあります。
ユーザが信号処理などを書くのは userproc ディレクトリ内のみで、その他は基本的に変更の必要はありません。

main.cpp には、起動処理~MainCPUとのデータ通信制御が書かれていますので変更しないで下さい。

diag a57e6708710cb7114f000efea8bdff15
図 3. コード構成
main.cpp

起動処理やDSP通信処理などが書かれています。編集の必要は有りません。

userproc_command.h

DSPとの通信コマンドを定義するヘッダファイルです。
必要なパラメータはこのファイルに記載します。

userproc.h

ユーザーコードのヘッダファイルです。

userproc.cpp

ユーザーコード本体です。
このファイルに信号処理などを書く、または呼び出します。

ユーザーコードに用意されるインタフェース

userproc.cpp には、 Init , Exec , Flush , Set コマンドの枠組みが用意されており
ユーザーコードはそれぞれに対応する中身を書いていくことでDSP内での処理を実現することが出来ます。

ユーザーが記述すべき処理について説明します。
(※デフォルトではサンプルとしてRCフィルタが組み込まれています。)

コマンドによるDSP内部の状態遷移は下図の通り行われます。

diag 0928a06633729c0a665de831ed913329
図 4. DSPの状態遷移

各コマンドを使い以下のような流れで処理を行います。

  1. AUDCMD_INIT_OUTPUTMIXERがコールされるとDSPが起動します。

  2. Init コマンドで必要なパラメータ(ch数やビット長など)を設定します。

  3. 再生開始するとキャプチャした音声データが Exec コマンドで定期的にDSPに送られるので所望のフィルタ処理をしてください。

  4. 任意のタイミングでDSP内部のパラメータなどを変更したい場合には、 Set コマンドを送ることで実装することを想定しています。このコマンドの実行タイミングは、 Exec を含めた受信順になります。+

  5. 再生停止すると最後の音声データの Exec の後、 Flush コマンドが送られるので終端処理の必要がある場合はここで処理をします。

コマンドの定義

各機能で使用するデータ型は userproc_command.h に書かれており、中身は自由に書き換えることが出来ます。

各コマンドのフォーマットは下図の様になっています。
先頭の白抜きの部分には最低限必要なパラメータが固定で配置されています。これらは変更しないで下さい。
ユーザーが userproc_command.h で定義するパラメータは下図の User param (ピンク色箇所)にあたる部分です。

diag 18441ee8379c82811c49595c4070498f
図 5. コマンドフォーマット

各コマンドについて説明します。

struct InitParam : public CustomprocCommand::CmdBase
  • Init処理用のパラメータです。
    デフォルトではすべてreserveとなっていますが、ch数やビット長など、必要なパラメータに変更してください。

struct ExecParam : public CustomprocCommand::CmdBase
  • Exec処理用のパラメータです。
    音声データのアドレス・サイズは上図の ExecParam にある様に継承元の CustomprocCommand::ExecParamBase に定義されています。
    詳細は /sdk/modules/include/audio/dsp_framework/customproc_command_base.h を参照してください。

struct FlushParam : public CustomprocCommand::CmdBase
  • Flush処理用のパラメータです。
    音声データのアドレス・サイズは上図の ExecParam にある様に継承元の CustomprocCommand::FlushParamBase に定義されています。
    詳細は /sdk/modules/include/audio/dsp_framework/customproc_command_base.h を参照してください。

struct SetParam : public CustomprocCommand::CmdBase
  • Set処理用のパラメータです。
    様々な動的に変更したいパラメータを定義します。デフォルトではRCフィルタのOn/Offや係数を定義しています。

各機能に対応する関数

下記の関数群は userproc.cpp に書かれています。中身は自由に書き換えることが出来ます。
それぞれのコマンド定義に従い処理を行います。

void UserProc::init(InitParam *)
  • InitParamに従い初期化を行う処理を書いて下さい。
    アプリケーションコードからの AUDCMD_INITMPP コマンドで実行されます。
    (デフォルトでは何もしていません。)

void UserProc::exec(ExecParam *)
  • ExecParamに従い信号処理を書いて下さい。
    再生を開始するとSDK内部から定期的に呼ばれます。
    1フレームはLPCMの場合には640サンプル、MP3の場合には1152(ただし16kHz時は1728)サンプルです。
    入力データアドレスからデータを取得し、信号処理を行い、出力データアドレスへ書き出して下さい。
    (デフォルトではRCフィルタ処理が書かれています。)

void UserProc::flush(FlushParam *)
  • FlushParamに従いFlush(終端)処理を書いて下さい。
    再生の停止時にSDK内部から一度だけ呼ばれます。
    IIRやFIRフィルタのように遅延が発生する場合は、最終フレームの後に flush を行い、遅延分の出力を行います。
    出力すべきデータがある場合には、出力データアドレスへ書き出して下さい。
    (デフォルトでは何もしていません。)

void UserProc::set(SetParam *)
  • SetParamに従い設定処理を書いてください。
    アプリケーションコードからの AUDCMD_SETMPPPARAM コマンドで実行されます。
    (デフォルトではRCフィルタの係数を設定しています。)

4.1.4.2. Step2. POSTPROC バイナリのビルド

ConfigurationUser Postprocess を有効にしていれば、本アプリケーションのビルド時に自動で POSTPROC バイナリが作成されます。
作成されるパスは spresense/examples/audio_player/worker/ の下の POSTPROC です。
これをSDカードの /mnt/sd0/BIN (PCから見ると \BIN )フォルダに置いてください。

4.2. Audio Recorder サンプルアプリケーション

Audio Recorderのサンプルアプリケーションの動作について説明します。

4.2.1. ビルド&ロード手順

ここではコマンドラインによるビルド手順を示します。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に examples/audio_recorder を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    tools/config.py examples/audio_recorder
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    
  4. Audio Recorderの場合、エンコード処理を行うDSPバイナリのロードが必要です。 DSPバイナリの置き場所は、SDカードか、SPI-Flashのどちらかを選択できますが、 ここでは、SDカードからロードする方法を行います。

    DSPバイナリのパスの指定は、アプリケーションコード内で指定します。
    audio_recorder_main.cxx では、 DSPBIN_PATH で設定していますので必要に応じてアプリケーションコードを変更して下さい。

    #define DSPBIN_PATH "/mnt/sd0/BIN"

    であれば、SDカードが指定されています。

    この /mnt/sd0/BIN は、SDカードをPCで読み込んだ時の、ルートディレクトリの下の BIN/ です。
    このディレクトリを作成し、ここに必要なコーデックのDSPを置きます。

    SPI-flashにしたい場合は、/mnt/spif/BIN を指定してください。

    MP3で録音(エンコード)する場合は、
    spresense/sdk/modules/audio/dsp/ の下の MP3ENC を選択してください。

    その他のエンコードをする場合のCodec種別とDSPバイナリの組み合わせは下表の通りです。

    Codec DSPバイナリ

    MP3

    MP3ENC

    LPCM

    SRC

4.2.2. Audio Recorderの動作確認

この nuttx.spk をSpresenseへロードするとAudio Recorderのプログラムが実行されます。
Helloサンプルと同様に、シリアルターミナルを開きます。

minicom -D /dev/ttyUSB0 -b 115200 -s

builtinされている、 audio_recorder アプリを実行すると、

tutorial recorder log
図 6. 音声記録時ログ

というログが表示され、音声が記録されます。

記録された音声はPCで再生することが出来ます。その際にはSDカードルートディレクトリの下の REC/ に音声ファイルがあります。
audio_recorder_main.cxx では、 RECFILE_ROOTPATH で設定していますので必要に応じてアプリケーションコードを変更して下さい。

#define RECFILE_ROOTPATH "/mnt/sd0/REC"

であればSDカードのルートの下の REC/ に音声ファイルが作られます。

エラーが発生した場合は、オーディオサブシステムのエラーについて を参照してください。

4.2.3. 付録: 独自の信号処理を行う

これまでのチュートリアルで、レコーダーとして十分な機能を実現することができました。
ここからは、より高度な処理を行う方法を説明していきます。

AudioRecorderでは記録する音声に対してユーザー独自の信号処理を行うことが出来ます。
これを行いたい場合にはコンフィグメニューで [Use preprocess] を有効にする必要があります。

  1. Preprocessを有効にします

    コンフィグメニューを開きます。

    tools/cofig.py -m
    

    [Use preprocess] にチェックを入れます。

    [Examples]
      [Audio recorder example]
        [Use preprocess]        <= Y
    Preprocessの詳細についてはSDKデベロッパーガイドの Set preprocess を参照して下さい。
  2. ビルドを行います。

    make
    

    全ての手順がうまくいけば、 PREPROC バイナリが spresense/examples/audio_recorder/worker/ の下に作成されます。
    これをSDカードの /mnt/sd0/BIN (PCから見ると BIN/ )フォルダに置いてください。

    本サンプルアプリケーションでは、 PREPROC には簡単なRCfilterがデフォルトで組み込まれています。
    独自の信号処理などにカスタムをしたい場合には こちら を参考にして下さい。

    Preprocessの有効、無効で記録した音声ファイルを再生して、違いを確認してみてください。
    記録、再生方法はこちら を参考にして下さい。

    == DSPバイナリ(PREPROC)のカスタムについて

DSPバイナリ(PREPROC)のカスタム方法について記載します。

4.2.3.1. Step1. PREPROCのコード編集

PREPROCのコード構成と編集箇所について説明します。
コードは、ユーザー編集すべき部分とフレームワークとして提供される部分の2つに分かれます。

ユーザーが編集するコード

ユーザーが主に編集すべきコードです。
これらのコードを編集してDSPで信号処理を記述することが出来ます。

worker ディレクトリの中にDSPのコードがまとまっており、その中に userproc ディレクトリがあります。
ユーザが信号処理などを書くのは userproc ディレクトリ内のみで、その他は基本的に変更の必要はありません。

main.cpp には、起動処理~MainCPUとのデータ通信制御が書かれていますので変更しないで下さい。

diag d07ec80436befada0ba13cb476f52819
図 7. コード構成
main.cpp

起動処理やDSP通信処理などが書かれています。編集の必要は有りません。

userproc_command.h

DSPとの通信コマンドを定義するヘッダファイルです。
必要なパラメータはこのファイルに記載します。

userproc.h

ユーザーコードのヘッダファイルです。

userproc.cpp

ユーザーコード本体です。
このファイルに信号処理などを書く、または呼び出します。

ユーザーコードに用意されるインタフェース

userproc.cpp には、 Init , Exec , Flush , Set コマンドの枠組みが用意されており
ユーザーコードはそれぞれに対応する中身を書いていくことでDSP内での処理を実現することが出来ます。

ユーザーが記述すべき処理について説明します。
(※デフォルトではサンプルとしてRCフィルタが組み込まれています。)

コマンドによるDSP内部の状態遷移は下図の通り行われます。

diag 5c366cef4aced2ff49d16fe4e3c5087e
図 8. DSPの状態遷移

各コマンドを使い以下のような流れで処理を行います。

  1. AUDCMD_INIT_MICFRONTENDがコールされるとDSPが起動します。

  2. Init コマンドで必要なパラメータ(ch数やビット長など)を設定します。

  3. 記録開始するとキャプチャした音声データが Exec コマンドで定期的にDSPに送られるので所望のフィルタ処理をしてください。

  4. 任意のタイミングでDSP内部のパラメータなどを変更したい場合には、 Set コマンドを送ることで実装することを想定しています。このコマンドの実行タイミングは、 Exec を含めた受信順になります。+

  5. 記録停止すると最後の音声データの Exec の後、 Flush コマンドが送られるので終端処理の必要がある場合はここで処理をします。

コマンドの定義

各機能で使用するデータ型は userproc_command.h に書かれており、中身は自由に書き換えることが出来ます。

各コマンドのフォーマットは下図の様になっています。
先頭の白抜きの部分には最低限必要なパラメータが固定で配置されています。これらは変更しないで下さい。
ユーザーが userproc_command.h で定義するパラメータは下図の User param (ピンク色箇所)にあたる部分です。

diag 18441ee8379c82811c49595c4070498f
図 9. コマンドフォーマット

各コマンドについて説明します。

struct InitParam : public CustomprocCommand::CmdBase
  • Init処理用のパラメータです。
    デフォルトではすべてreserveとなっていますが、ch数やビット長など、必要なパラメータに変更してください。

struct ExecParam : public CustomprocCommand::CmdBase
  • Exec処理用のパラメータです。
    音声データのアドレス・サイズは上図の ExecParam にある様に継承元の CustomprocCommand::ExecParamBase に定義されています。
    詳細は /sdk/modules/include/audio/dsp_framework/customproc_command_base.h を参照してください。

struct FlushParam : public CustomprocCommand::CmdBase
  • Flush処理用のパラメータです。
    音声データのアドレス・サイズは上図の ExecParam にある様に継承元の CustomprocCommand::FlushParamBase に定義されています。
    詳細は /sdk/modules/include/audio/dsp_framework/customproc_command_base.h を参照してください。

struct SetParam : public CustomprocCommand::CmdBase
  • Set処理用のパラメータです。
    様々な動的に変更したいパラメータを定義します。デフォルトではRCフィルタのOn/Offや係数を定義しています。

各機能に対応する関数

下記の関数群は userproc.cpp に書かれています。中身は自由に書き換えることが出来ます。
それぞれのコマンド定義に従い処理を行います。

void UserProc::init(InitParam *)
  • InitParamに従い初期化を行う処理を書いて下さい。
    アプリケーションコードからの AUDCMD_INIT_PREPROCESS_DSP コマンドで実行されます。
    (デフォルトでは何もしていません。)

void UserProc::exec(ExecParam *)
  • ExecParamに従い信号処理を書いて下さい。
    記録を開始するとSDK内部から定期的に呼ばれます。
    1フレームは記録の設定がLPCMの場合には768サンプル、MP3の場合には1152(ただし16kHz時は1728)サンプルです。
    入力データアドレスからデータを取得し、信号処理を行い、出力データアドレスへ書き出して下さい。
    (デフォルトではRCフィルタ処理が書かれています。)

void UserProc::flush(FlushParam *)
  • FlushParamに従いFlush(終端)処理を書いて下さい。
    記録の停止時にSDK内部から一度だけ呼ばれます。
    IIRやFIRフィルタのように遅延が発生する場合は、最終フレームの後に flush を行い、遅延分の出力を行います。
    出力すべきデータがある場合には、出力データアドレスへ書き出して下さい。
    (デフォルトでは何もしていません。)

void UserProc::set(SetParam *)
  • SetParamに従い設定処理を書いてください。
    アプリケーションコードからの AUDCMD_SET_PREPROCESS_DSP コマンドで実行されます。
    (デフォルトではRCフィルタの係数を設定しています。)

4.2.3.2. Step2. PREPROC バイナリのビルド

ConfigurationPreprocess を有効にしていれば、本アプリケーションのビルド時に自動で PREPROC バイナリが作成されます。
作成されるパスは spresense/examples/audio_recorder/worker/ の下の PREPROC です。
これをSDカードの /mnt/sd0/BIN (PCから見ると \BIN )フォルダに置いてください。

4.3. Audio Recognizer サンプルアプリケーション

Audio Recognizer サンプルアプリケーションの動作について説明します。

4.3.1. ビルド&ロード手順

ここではコマンドラインによるビルド手順を示します。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に examples/audio_recognizer を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    tools/config.py examples/audio_recognizer
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    
  4. Audio Recognizerの場合、音声認識処理を行うDSPバイナリのロードが必要です。 DSPバイナリの置き場所は、SDカードかSPI-Flashのどちらかを選択できますが、 ここでは、SDカードからロードする方法を行いますので、 "/mnt/sd0/BIN" に置きます。

    この /mnt/sd0/BIN は、SDカードをPCで読み込んだ時の、ルートディレクトリの下の BIN/ です。
    このディレクトリを作成し、ここに音声認識に必要なDSPを置きます。

    本サンプルアプリケーションでは、音声認識のDSPバイナリは、ユーザーカスタムのものを使用する設定となっており、バイナリは spresense/examples/audio_recognizer/worker_recognizer/ の下に RCGPROC として生成されます。認識処理をカスタムする場合には、RecognizerPROCのカスタムについてを参照してください。

4.3.2. Audio Recognizerの動作確認

ビルドした nuttx.spk を実機へロードするとAudio Recognizerのプログラムが実行されます。

Helloサンプルと同様に、シリアルターミナルを開きます。

minicom -D /dev/ttyUSB0 -b 115200 -s

builtinされている、 audio_recognizer アプリを実行すると、

tutorial recognizer log
図 10. 音声認識動作時ログ

というログが表示され、音声認識が開始されます。

認識結果はアプリケーションコード( audio_recognizer_main.cpp )中にあるコールバック関数で受け取っています。
受け取るパラメータの構成は音声認識用DSPで決めています。 RecognizerPROC を参照して下さい。
データはMemoryHandleで受信していますので、下記の様に、そのアドレスを参照することでデータを取得することが出来ます。

static void recognizer_find_callback(AsRecognitionInfo info)
{
  /* Get Recognition result */

  MyRecognizerResultFormat *result =
    static_cast<MyRecognizerResultFormat *>(info.getVa())

  /* Print result */
  ...
  printf("Data size %d byte\n", info.size);
  printf("Data1 : %x, Data2 : %x\n", result->data1, result->data2);
  ...
}

エラーが発生した場合は、オーディオサブシステムのエラーについて を参照してください。

4.3.3. 付録: 独自の信号処理を行う

これまでのチュートリアルで、Recognizerとして十分な機能を実現することができました。
ここからは、より高度な処理を行う方法を説明していきます。

キャプチャした音声はサンプリング周波数が48kHzまたは192kHz、ビット長が16bitまたは32bitです。
Audio Recognizerではこれに対して、認識ライブラリの入力フォーマットに合わせ前処理を行うことが出来ます。
これを行いたい場合にはコンフィグメニューで [Use preprocess] を有効にする必要があります。

  1. Preprocessを有効にします

    コンフィグメニューを開きます。

    tools/cofig.py -m
    

    [Use preprocess] にチェックを入れます。

    [Examples]
      [Audio recognizer example]
        [Use preprocess]        <= Y
    Preprocessの詳細についてはSDKデベロッパーガイドの Set preprocess を参照して下さい。
  2. ビルドを行います。

    make
    

    全ての手順がうまくいけば、 PREPROC バイナリが spresense/examples/audio_recognizer/worker_preprocess/ の下に作成されます。
    これをSDカードの /mnt/sd0/BIN (PCから見ると BIN/ )フォルダに置いてください。

    本サンプルアプリケーションでは、 PREPROC には簡単なRCfilterがデフォルトで組み込まれています。
    独自の信号処理などにカスタムをしたい場合には こちら を参考にして下さい。

4.3.4. DSPバイナリのカスタムについて

audio_recognizerサンプルではPre処理用(以下 PREPROC )、認識処理用(以下 RCGPROC )の2つのDSPバイナリを使用します。
それらのカスタム方法について説明します。

4.3.4.1. Step1. PREPROC, RCGPROCのコード編集

PREPROC, RCGPROC のコード構成と編集箇所について説明します。
コードは、ユーザー編集すべき部分とフレームワークとして提供される部分の2つに分かれます。

ユーザーが編集するコード

ユーザーが主に編集すべきコードです。
これらのコードを編集してDSPで信号処理や認識処理を記述することが出来ます。

PREPROCworker_preprocess ディレクトリの中に、 RCGPROCworker_recognizer の中にDSPのコードがまとまっており、それぞれその中に userproc ディレクトリがあります。
ユーザが信号・認識処理などを書くのは userproc ディレクトリ内のみで、その他は基本的に変更の必要はありません。

main.cpp には、起動処理~MainCPU(Supervisor)とのデータ通信制御が書かれていますので変更しないで下さい。

diag 1da20019190b78094d3027d28a8646de
図 11. PREPROC, RCGPROCコード構成
main.cpp

起動処理やDSP通信処理などが書かれています。編集の必要は有りません。

userproc_command.h

Pre処理用DSPとの通信コマンドを定義するヘッダファイルです。
必要なパラメータはこのファイルに記載します。

userproc.h

Pre処理用DSPのユーザーコードのヘッダファイルです。

userproc.cpp

Pre処理用DSPのユーザーコード本体です。
このファイルに信号処理などを書く、または呼び出します。

rcgproc_command.h

認識用DSPとの通信コマンドを定義するヘッダファイルです。
必要なパラメータはこのファイルに記載します。

rcgproc.h

認識用DSPのユーザーコードのヘッダファイルです。

rcgproc.cpp

認識用DSPのユーザーコード本体です。
このファイルに認識処理を書く、または呼び出します。

ユーザーコードに用意されるインタフェース

Init , Exec , Flush , Set コマンドの枠組みが用意されており
ユーザーコードはそれぞれに対応する中身を書いていくことでDSP内での処理を実現することが出来ます。

ユーザーが記述すべき処理について説明します。
(※デフォルトではサンプルとして PREPROC にはRCフィルタが組み込まれています。)

コマンドによるDSP内部の状態遷移は下図の通り行われます。

diag 9d916dafe09fdcdb653433cb66b65989
図 12. DSPの状態遷移

各コマンドを使い以下のような流れで処理を行います。

  1. AUDCMD_INIT_RECOGNIZERがコールされると認識用DSPが起動します。

  2. Init コマンドで必要なパラメータ(ch数やビット長など)を設定します。

  3. 認識処理を開始するとキャプチャした音声データが Exec コマンドで定期的にDSPに送られるので所望の認識処理をしてください。

  4. 任意のタイミングでDSP内部のパラメータなどを変更したい場合には、 Set コマンドを送ることで実装することを想定しています。このコマンドの実行タイミングは、 Exec を含めた受信順になります。+

  5. 認識処理を停止すると最後の音声データの Exec の後、 Flush コマンドが送られるので終端処理の必要がある場合はここで処理をします。

コマンドの定義

各機能で使用するデータ型は、 PREPROC では userproc_command.h に、 RCGPROC では rcgproc_command.h に書かれており、中身は自由に書き換えることが出来ます。

各コマンドのフォーマットは下図の様になっており、これは PREPROC RCGPROC で同じです。
先頭の白抜きの部分には最低限必要なパラメータが固定で配置されています。これらは変更しないで下さい。
ユーザーが userproc_command.h で定義するパラメータは下図の User param (ピンク色箇所)にあたる部分です。

notificationExec コマンドの応答(認識結果)フラグで、0以外の指定でアプリケーションまで応答を戻します。
例えば、通常は応答を戻さず認識結果の変化点(認識無し→有りになった点)などでのみ応答したい場合などに使用出来ます。

diag 18441ee8379c82811c49595c4070498f
図 13. コマンドフォーマット

各コマンドについて説明します。

struct InitRcgParam : public CustomprocCommand::CmdBase
  • Init処理用のパラメータです。
    デフォルトではch数とビット幅が設定されています。必要なパラメータに変更してください。

struct ExecRcgParam : public CustomprocCommand::CmdBase
  • Exec処理用のパラメータです。
    音声データのアドレス・サイズは上図の ExecParam にある様に継承元の CustomprocCommand::ExecParamBase に定義されています。
    詳細は /sdk/modules/include/audio/dsp_framework/customproc_command_base.h を参照してください。

struct FlushRcgParam : public CustomprocCommand::CmdBase
  • Flush処理用のパラメータです。
    音声データのアドレス・サイズは上図の FlushParam にある様に継承元の CustomprocCommand::FlushParamBase に定義されています。
    詳細は /sdk/modules/include/audio/dsp_framework/customproc_command_base.h を参照してください。

struct SetRcgParam : public CustomprocCommand::CmdBase
  • Set処理用のパラメータです。
    様々な動的に変更したいパラメータを定義します。デフォルトでは認識処理のOn/Offを定義しています。

各機能に対応する関数

下記の関数群は rcgproc.cpp に書かれています。中身は自由に書き換えることが出来ます。
それぞれのコマンド定義に従い処理を行います。

void RcgProc::init(InitRcgParam *)
  • InitRcgParamに従い初期化を行う処理を書いて下さい。
    アプリケーションコードからの AUDCMD_INIT_RECOGNIZER_DSP コマンドで実行されます。
    (デフォルトではCh数とビット幅の設定をしています。)

void RcgProc::exec(ExecRcgParam *)
  • ExecRcgParamに従い信号処理を書いて下さい。
    認識処理を開始するとSDK内部から定期的に呼ばれます。
    当サンプルアプリケーションでは1フレームは320サンプルです(アプリケーションで自由に変更できます)。
    入力データアドレスからデータを取得し、認識処理を行い、結果を出力データアドレスへ書き出して下さい。
    (デフォルトでは入力フレーム内サンプル値の最大・最少・平均値を出力しています。)

void RcgProc::flush(FlushRcgParam *)
  • FlushRcgParamに従いFlush(終端)処理を書いて下さい。
    認識処理の停止時にSDK内部から一度だけ呼ばれます。
    認識処理にフレーム遅延が発生する場合は、最終フレームの後に flush を行い遅延分の出力を行います。
    出力すべきデータがある場合には、出力データアドレスへ書き出して下さい。
    (デフォルトでは何もしていません。)

void RcgProc::set(SetRcgParam *)
  • SetRcgParamに従い設定処理を書いてください。
    アプリケーションコードからの AUDCMD_SET_RECOGNIZER_DSP コマンドで実行されます。
    (デフォルトでは認識処理のOn/Offを設定しています。)

4.3.4.2. Step2. PREPROC , RCGPROC バイナリのビルド

本アプリケーションのビルド時に自動で RCGPROC バイナリが作成されます。
また、 ConfigurationPreprocess を有効にしていれば PREPROC バイナリも作成されます。
作成されるパスは worker_recognizer/ の下に RCGPROCworker_preprocess/ の下に PREPROC です。
これをSDカードの /mnt/sd0/BIN (PCから見ると \BIN )フォルダに置いてください。

5. LTE チュートリアル

5.1. LTE HTTP GET サンプルアプリケーション

5.1.1. 概要

本サンプルプログラムは、LTE通信機能を用いて、HTTP GETを行うサンプルです。

5.1.1.1. 動作環境
  • Spresense メインボード

  • Spresense LTE拡張ボード

  • SIM カード

  • microSD カード

接続方法は、SpresenseメインボードとSpresense LTE拡張ボードの接続方法を参照してください。

本スケッチではネットワークに接続するため、SIM カードが必要です。
LTE-M 動作確認SIM Listをご確認ください。

5.1.2. ビルド手順

ここではコマンドラインによるビルド手順を示します。
IDE を使用してビルドする場合、以下に示すコンフィグレーション情報を参考にしてください。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に examples/lte_http_get を指定してコンフィグレーションを実行します。

    tools/config.py examples/lte_http_get
    

    サンプルアプリケーションのコンフィグレーションを変更します。

    tools/config.py -m
    
    1. APNのパラメータを設定します。(ご使用のSIMに合わせて設定してください。)

      Application Configuration -> Spresense SDK -> Examples -> HTTP GET method using LTE example
      - Access Point Name (CONFIG_EXAMPLES_LTE_HTTP_GET_APN_NAME)
      - IP type Selection
      - Authentication type Selection
      - Username used for authentication (CONFIG_EXAMPLES_LTE_HTTP_GET_APN_USERNAME)
      - Password used for authentication (CONFIG_EXAMPLES_LTE_HTTP_GET_APN_PASSWD)
      tutorial lte http get apn
      コンフィグレーション名 説明

      Access Point Name

      アクセスポイント名

      IP type Selection

      APNプロトコル。IPv4IPv6IPv4/v6 から選択します。

      Authentication type Selection

      認証タイプ。 NonePAPCHAP から選択します。

      Username used for authentication

      ユーザ名。 認証タイプに None を選択した場合、設定は無視されます。

      Password used for authentication

      パスワード。 認証タイプに None を選択した場合、設定は無視されます。

    2. HTTPSの設定します。(デフォルトのコンフィグではモデムのTLSプロトコルが有効です。)

      Application Configuration -> Spresense SDK -> Externals -> mbedTLS connection utility support -> Directory path for TLS certification files (CONFIG_EXTERNALS_MBEDTLS_DEFAULT_CERTS_PATH)
      tutorial lte http get certs

      HTTPSで使用するサーバのルート証明書を格納するディレクトリを指定します。
      デフォルトの設定では/mnt/spif/CERTSとなっています。

      ルート証明書の取得方法についてはルート証明書のエクスポート手順を参考にしてください。

      SPI-Flashへのファイル転送方法はZmodem を使ったファイル転送を参照してください。

      ディレクトリのパスを /mnt/sd0/CERTS にすると microSD カードに変更することができます。
      microSD カードに変更した場合は CONFIG_CXD56_SDIO のコンフィグレーションを有効にする必要があります。

      ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

      make
      
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

5.1.3. 動作確認

シリアルターミナルを開いて、lte_http_get コマンドを実行します。

  1. シリアルターミナルを起動します。

    シリアルポートに /dev/ttyUSB0 を、baudrate に 115200 bps を指定して、 minicom ターミナルを使用する例を示します。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から lte_http_get コマンドを実行します。

    lte_http_get コマンドの使い方を以下に示します。

    nsh> lte_http_get <url>
    url

    インターネット上に置かれているファイルのURLを指定します。 http:// もしくは https:// から始まる必要があります。urlを指定しない場合、 http://example.com/index.html となります。

    https:// のURLを指定する場合、事前にHTTPSの設定を行ってください。サーバのルート証明書をコンフィグレーションで記述したディレクトリに格納する必要があります。

本サンプルアプリケーションはurlに指定されたファイルをダウンロードしシリアルターミナルに出力します。

lte_http_get コマンドを実行した例を以下に示します。

nsh> lte_http_get
app_restart_cb called. reason:Modem restart by application.
pdn.session_id : 1
pdn.active     : 1
pdn.apn_type   : 0x202
pdn.ipaddr[0].addr : 10.212.60.255
app_localtime_report_cb called: localtime : "19/12/06 : 18:24:33"
set localtime completed: 2019/12/06,18:24:33
<!doctype html>
<html>
<head>
    <title>Example Domain</title>

    <meta charset="utf-8" />
    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style type="text/css">
    body {
        background-color: #f0f0f2;
        margin: 0;
        padding: 0;
        font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;

    }
    div {
        width: 600px;
        margin: 5em auto;
        padding: 2em;
        background-color: #fdfdff;
        border-radius: 0.5em;
        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
    }
    a:link, a:visited {
        color: #38488f;
        text-decoration: none;
    }
    @media (max-width: 700px) {
        div {
            margin: 0 auto;
            width: auto;
        }
    }
    </style>
</head>

<body>
<div>
    <h1>Example Domain</h1>
    <p>This domain is for use in illustrative examples in documents. You may use this
    domain in literature without prior coordination or asking for permission.</p>
    <p><a href="https://www.iana.org/domains/example">More information...</a></p>
</div>
</body>
</html>
nsh>

本サンプルアプリケーションの、wgetwget_post に変更することによりHTTPのPOSTメソッドが使用できます。
以下の例を参考に wget_post の第2引数にPOSTするデータを設定してください。

wget_post(url, "Hello spresense world!!" ,g_app_iobuffer, APP_IOBUFFER_LEN, app_wget_cb, NULL);

また、本サンプルアプリケーションはダウンロードしたファイルをシリアルターミナルに出力しますが、
以下の様に app_wget_cb() 関数を一部変更することにより、ファイルに保存することができます。

static void app_wget_cb(FAR char **buffer, int offset, int datend,
                        FAR int *buflen, FAR void *arg)
{
  int fd;

  fd = open("/mnt/spif/index.html", (O_WRONLY | O_APPEND));
  if ((fd < 0) && (errno == ENOENT))
    {
      fd = open("/mnt/spif/index.html", (O_CREAT | O_WRONLY), 0666);
    }
  /* Write HTTP data to local file */

  (void)write(fd, &((*buffer)[offset]), datend - offset);

  close(fd);
}

上記の例では、 /mnt/spif/index.html にダウンロードしたデータを保存します。
ファイルは追加書き込みモードで保存されるため、必要に応じて lte_http_get のコマンドを実行する前に
NuttShell から rm /mnt/spif/index.html のコマンドを実行しファイルを削除してください。
保存したファイルの内容は cat /mnt/spif/index.html のコマンドを実行すると確認できます。

5.1.4. 参考

LTE 機能の詳細は、開発ガイドを参照してください。

5.2. LTE TLS サンプルアプリケーション

5.2.1. 概要

本サンプルプログラムは、LTE通信機能を用いて、TLSプロトコルでサーバに接続し、HTTP POSTを行うサンプルです。

5.2.1.1. 動作環境
  • Spresense メインボード

  • Spresense LTE拡張ボード

  • SIM カード

  • microSD カード

接続方法は、SpresenseメインボードとSpresense LTE拡張ボードの接続方法を参照してください。

本スケッチではネットワークに接続するため、SIM カードが必要です。
LTE-M 動作確認SIM Listをご確認ください。

5.2.2. ビルド手順

ここではコマンドラインによるビルド手順を示します。
IDE を使用してビルドする場合、以下に示すコンフィグレーション情報を参考にしてください。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に examples/lte_tls を指定してコンフィグレーションを実行します。

    tools/config.py examples/lte_tls
    

    サンプルアプリケーションのコンフィグレーションを変更します。

    tools/config.py -m
    
    1. APNのパラメータを設定します。(ご使用のSIMに合わせて設定してください。)

      Application Configuration -> Spresense SDK -> Examples -> TLS data communication over LTE network example
      - Access Point Name (CONFIG_EXAMPLES_LTE_TLS_APN_NAME)
      - IP type Selection
      - Authentication type Selection
      - Username used for authentication (CONFIG_EXAMPLES_LTE_TLS_APN_USERNAME)
      - Password used for authentication (CONFIG_EXAMPLES_LTE_TLS_PASSWD)
      tutorial lte tls apn
      コンフィグレーション名 説明

      Access Point Name

      アクセスポイント名

      IP type Selection

      APNプロトコル。IPv4IPv6IPv4/v6 から選択します。

      Authentication type Selection

      認証タイプ。 NonePAPCHAP から選択します。

      Username used for authentication

      ユーザ名。 認証タイプに None を選択した場合、設定は無視されます。

      Password used for authentication

      パスワード。 認証タイプに None を選択した場合、設定は無視されます。

    2. HTTPSの設定をします。

      モデムのTLSプロトコルを使用することが可能です。
      使用する場合は、 モデムのTLSプロトコルを使用する を参照してください。

      Application Configuration -> Spresense SDK -> Examples -> TLS data communication over LTE network example -> Directory for server certification files (CONFIG_EXAMPLES_LTE_TLS_CERTS_PATH)
      tutorial lte tls certs

      HTTPSで使用するサーバのルート証明書を格納するディレクトリを指定します。
      デフォルトの設定では/mnt/sd0/CERTSとなっています。

      ディレクトリのパスを /mnt/spif/CERTS にするとSPI-Flashに変更することができます。

      ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

      make
      
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

5.2.3. 動作確認

シリアルターミナルを開いて、lte_tls コマンドを実行します。

  1. シリアルターミナルを起動します。

    シリアルポートに /dev/ttyUSB0 を、baudrate に 115200 bps を指定して、 minicom ターミナルを使用する例を示します。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から lte_tls コマンドを実行します。

    lte_tls コマンドの使い方を以下に示します。

    nsh> lte_tls <url>
    url

    インターネット上に置かれているファイルのURLを指定します。 https:// から始まる必要があります。urlを指定しない場合、 https://example.com/post となります。

    事前にサーバのルート証明書をコンフィグレーションで記述したディレクトリに格納する必要があります。

本サンプルアプリケーションはHTTPのPOSTメソッドを使用して指定されたurlに任意のデータを送信します。

lte_tls コマンドを実行した例を以下に示します。正常にデータを送信できた場合は "HTTP status code = 200" が出力されます。

nsh> lte_tls https://httpbin.org/post
app_restart_cb called. reason:Modem restart by application.
app_radio_on_cb called. result: 0
app_activate_pdn_cb called. result: 0
pdn.session_id : 1
pdn.active     : 1
pdn.apn_type   : 0x202
pdn.ipaddr[0].addr : 10.212.60.255
app_localtime_report_cb called: localtime : "19/12/10 : 17:26:18"
set localtime completed: 2019/12/10,17:26:18
HTTP status code = 200
app_deactivate_pdn_cb called. result: 0
app_radio_off_cb called. result: 0
nsh>

本サンプルアプリケーションでは、 create_http_post() の関数でPOSTするデータを作成しています。

static int create_http_post(const char    *host,
                            const char    *path,
                            char          *buffer,
                            size_t        buffer_size)
{
  const char *post_data = "Spresense!";
  const char http_post_request[] = "POST %s HTTP/1.1\r\n"
                                   "HOST: %s\r\n"
                                   "Connection: close\r\n"
                                   "Content-Length: %d\r\n"
                                   "\r\n"
                                   "%s";

  return snprintf(buffer, buffer_size,
                  http_post_request,
                  path,
                  host,
                  strlen(post_data),
                  post_data);
}

5.2.4. 参考

LTE 機能の詳細は、開発ガイドを参照してください。

5.3. LTE MQTT サンプルアプリケーション

5.3.1. 概要

本サンプルプログラムは、LTE通信機能を用いて、MQTTブローカに接続し、指定したトピック名に対してサブスクライブするサンプルです。

5.3.1.1. 動作環境
  • Spresense メインボード

  • Spresense LTE拡張ボード

  • SIM カード

接続方法は、SpresenseメインボードとSpresense LTE拡張ボードの接続方法を参照してください。

本スケッチではネットワークに接続するため、SIM カードが必要です。
LTE-M 動作確認SIM Listをご確認ください。

5.3.2. ビルド手順

ここではコマンドラインによるビルド手順を示します。
IDE を使用してビルドする場合、以下に示すコンフィグレーション情報を参考にしてください。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に examples/lte_mqtt を指定してコンフィグレーションを実行します。

    tools/config.py examples/lte_mqtt
    

    サンプルアプリケーションのコンフィグレーションを変更します。

    tools/config.py -m
    
    1. APNのパラメータを設定します。(ご使用のSIMに合わせて設定してください。)

      Application Configuration -> Spresense SDK -> Examples -> MQTT using LTE example
      - Access Point Name (CONFIG_EXAMPLES_LTE_MQTT_APN_NAME)
      - IP type (CONFIG_EXAMPLES_LTE_MQTT_APN_IPTYPE)
      - Authentication type (CONFIG_EXAMPLES_LTE_MQTT_APN_AUTHTYPE)
      - Username used for authentication (CONFIG_EXAMPLES_LTE_MQTT_APN_USERNAME)
      - Password used for authentication (CONFIG_EXAMPLES_LTE_MQTT_APN_PASSWD)
      tutorial lte mqtt apn
      コンフィグレーション名 説明

      Access Point Name

      アクセスポイント名

      IP type

      APNプロトコル。0~2の値を設定します。0: IPv4, 1: IPv6 2: IPv4/v6 から選択します。

      Authentication type

      認証タイプ。0~2の値を設定します。 0: None 、1: PAP 、2: CHAP から選択します。

      Username used for authentication

      ユーザ名。 認証タイプに None を選択した場合、設定は無視されます。

      Password used for authentication

      パスワード。 認証タイプに None を選択した場合、設定は無視されます。

      ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

      make
      
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

5.3.3. 動作確認

シリアルターミナルを開いて、lte_mqtt コマンドを実行します。

  1. シリアルターミナルを起動します。

    シリアルポートに /dev/ttyUSB0 を、baudrate に 115200 bps を指定して、 minicom ターミナルを使用する例を示します。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から lte_mqtt コマンドを実行します。

    lte_mqtt コマンドの使い方を以下に示します。

    nsh> lte_mqtt topicname <options>
    topicname

    サブスクライブするトピック名

    options
    オプション 説明

    --host

    MQTTブローカのホスト名。デフォルトは localhost です。

    --port

    接続先ポート番号。デフォルトは 1883 です。

    --qos

    QOS。0~2の値を指定します。デフォルトは 2 です。

    --delimiter

    区切り文字。 デフォルトは \n です。

    --clientid

    クライアントID。 デフォルトは stdout_subscriber です。

    --username

    ユーザ名。 デフォルトは 未設定 です。

    --password

    パスワード。 デフォルトは 未設定 です。

    --showtopics

    トピック名の表示有無。 on または off を指定します。デフォルトは off です。

    Spresenseでは localhost をサポートしていません。必ず --host でホスト名を指定してください。

本サンプルアプリケーションはMQTTブローカに接続し、指定したトピック名に対してサブスクライブします。
サブスクライブ完了後、シリアルポートにパブリッシュされたメッセージを表示します。

当該トピック名に対してメッセージをパブリッシュするためには、別途操作が必要です。このアプリケーションでは操作できません。操作の例は後述します。

lte_mqtt コマンドを実行した例を以下に示します。正常にサブスクライブが完了した場合は "Subscribed 0" が出力されます。

nsh> lte_mqtt /test --host mqtt.eclipse.org --clientid test
app_restart_cb called. reason:Modem restart by application.
app_radio_on_cb called. result: 0
app_activate_pdn_cb called. result: 0
pdn.session_id : 1
pdn.active     : 1
pdn.apn_type   : 0x202
pdn.ipaddr[0].addr : 10.212.60.255
app_localtime_report_cb called: localtime : "19/12/11 : 11:36:39"
set localtime completed: 2019/12/11,11:36:39
Connecting to mqtt.eclipse.org 1883
Connected 0
Subscribing to /test
Subscribed 0

サブスクライブしているトピック名に対してパブリッシュします。
ここではUbuntu 16.04で mosquitto_pub コマンドを実行してパブリッシュする例を示します。

  • 以下のコマンドを実行し mosquitto-clients をインストールします。

sudo apt-get install mosquitto-clients
  • mosquitto_pub コマンドを実行してメッセージをパブリッシュします。

mosquitto_pub -t /test -m "Hello Spresense world" -h mqtt.eclipse.org
  • パブリッシュに成功するとシリアルポートに以下のメッセージが出力されます。

Hello Spresense world

5.3.4. 参考

LTE 機能の詳細は、開発ガイドを参照してください。

5.4. LTE AWS-IoT サンプルアプリケーション

5.4.1. 概要

本サンプルプログラムは、LTE通信機能とAWS-IoT device SDK for embedded Cを用いて、AWS-IoTサーバに接続し、MQTT通信を行うサンプルです。

5.4.2. 動作環境

  • Spresense メインボード

  • Spresense LTE拡張ボード

  • SIM カード

  • microSD カード

  • AWS-IoT Core

接続方法は、SpresenseメインボードとSpresense LTE拡張ボードの接続方法を参照してください。

本スケッチではネットワークに接続するため、SIM カードが必要です。
LTE-M 動作確認SIM Listをご確認ください。

また、AWS-IoTを利用するには、AWS-IoTの使用開始および、AWS-IoTへのデバイスの登録が必要です。

開始手順については AWS IoT の使用開始 を参考にしてください。

デバイスの登録については、 Registry でデバイスを登録する の手順で登録し、発行した証明書をダウンロードします。ダウンロードするファイルは以下の3つです。

  • ルート証明書:Amazon_Root_CA_1.pem

  • クライアント証明書:c3c4ff2375.cert.pem

  • 秘密鍵:c3c4ff2375.private.key

ダウンロードしたファイルは使用するmicroSD カードにCERTSディレクトリを生成して格納します。

ファイル名は上記リンク先に表示されている例で記載しています。環境によって異なるため適宜読み替えてください。

5.4.3. ビルド手順

ここではコマンドラインによるビルド手順を示します。
IDE を使用してビルドする場合、以下に示すコンフィグレーション情報を参考にしてください。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に examples/lte_awsiot device/sdcard を指定してコンフィグレーションを実行します。

    tools/config.py examples/lte_awsiot device/sdcard
    

    サンプルアプリケーションのコンフィグレーションを変更します。

    tools/config.py -m
    
    1. APNのパラメータを設定します。(ご使用のSIMに合わせて設定してください。)

      Application Configuration -> Spresense SDK -> Examples -> AWS IoT using LTE example
      - Access Point Name (CONFIG_EXAMPLES_LTE_AWSIOT_APN_NAME)
      - IP type (CONFIG_EXAMPLES_LTE_AWSIOT_APN_IPTYPE)
      - Authentication type (CONFIG_EXAMPLES_LTE_AWSIOT_APN_AUTHTYPE)
      - Username used for authentication (CONFIG_EXAMPLES_LTE_AWSIOT_APN_USERNAME)
      - Password used for authentication (CONFIG_EXAMPLES_LTE_AWSIOT_APN_PASSWD)
      tutorial lte awsiot apn
      コンフィグレーション名 説明

      Access Point Name

      アクセスポイント名

      IP type

      APNプロトコル。0~2の値を設定します。0: IPv4, 1: IPv6 2: IPv4/v6 から選択します。

      Authentication type

      認証タイプ。0~2の値を設定します。 0: None 、1: PAP 、2: CHAP から選択します。

      Username used for authentication

      ユーザ名。 認証タイプに None を選択した場合、設定は無視されます。

      Password used for authentication

      パスワード。 認証タイプに None を選択した場合、設定は無視されます。

    2. AWS-IoTを利用するためのパラメータを設定します。(ご使用の環境にあわせて設定してください。)

      Application Configuration -> Spresense SDK -> Examples -> AWS IoT using LTE example
      - AWS IoT cert folder (CONFIG_EXAMPLES_LTE_AWSIOT_CERT)
      コンフィグレーション名 デフォルト値 説明

      AWS IoT cert folder

      "/mnt/sd0/CERTS"

      AWS-IOTと接続する際に必要な認証用ファイルの置き場所を設定します。

      Application Configuration -> Spresense SDK -> Externals -> AWS IoT Device SDK for Embedded C -> AWS-IoT console
      - AWS_IOT_MQTT_HOST (CONFIG_EXTERNALS_AWSIOT_AWS_IOT_MQTT_HOST)
      - AWS_IOT_MQTT_PORT (CONFIG_EXTERNALS_AWSIOT_AWS_IOT_MQTT_PORT)
      - AWS_IOT_MQTT_CLIENT_ID (CONFIG_EXTERNALS_AWSIOT_AWS_IOT_MQTT_CLIENT_ID)
      - AWS_IOT_MY_THING_NAME (CONFIG_EXTERNALS_AWSIOT_AWS_IOT_MY_THING_NAME)
      - AWS_IOT_ROOT_CA_FILENAME (CONFIG_EXTERNALS_AWSIOT_AWS_IOT_ROOT_CA_FILENAME)
      - AWS_IOT_CERTIFICATE_FILENAME (CONFIG_EXTERNALS_AWSIOT_AWS_IOT_CERTIFICATE_FILENAME)
      - AWS_IOT_PRIVATE_KEY_FILENAME (CONFIG_EXTERNALS_AWSIOT_AWS_IOT_PRIVATE_KEY_FILENAME)
      tutorial lte awsiot console
      コンフィグレーション名 デフォルト値 説明

      AWS_IOT_MQTT_HOST

      MQTTブローカー名。ご使用のAWS-IoT環境のエンドポイントを設定します。

      AWS_IOT_MQTT_PORT

      443

      MQTTブローカーのポート番号。AWS-IoTはデフォルト値で接続可能です。

      AWS_IOT_MQTT_CLIENT_ID

      "AWS-IoT-C-SDK"

      MQTTのクライアントID。デバイス毎にユニークである必要があります。

      AWS_IOT_MY_THING_NAME

      "AWS-IoT-C-SDK"

      モノの名前。

      AWS_IOT_ROOT_CA_FILENAME

      "rootCA.crt"

      ルート証明書のファイル名。AWS-IoTサイトからダウンロードしたファイルを指定します。

      AWS_IOT_CERTIFICATE_FILENAME

      "cert.pem"

      クライアント証明書のファイル名。AWS-IoTサイトからダウンロードしたファイルを指定します。

      AWS_IOT_PRIVATE_KEY_FILENAME

      "privkey.pem"

      クライアント認証で用いる秘密鍵のファイル名。AWS-IoTサイトからダウンロードしたファイルを指定します。

      ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

      make
      
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

5.4.4. 動作確認

シリアルターミナルを開いて、lte_awsiot コマンドを実行します。

  1. シリアルターミナルを起動します。

    シリアルポートに /dev/ttyUSB0 を、baudrate に 115200 bps を指定して、 minicom ターミナルを使用する例を示します。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から lte_awsiot コマンドを実行します。

    lte_awsiot コマンドの使い方を以下に示します。

    nsh> lte_awsiot <options>
    options
    オプション 説明

    -x

    パブリッシュの繰り返し回数。デフォルト値は無限回です。

    本サンプルアプリケーションはAWS-IoTにMQTTで接続し、"sdkTest/sub"トピックにサブクライブします。
    サブスクライブ完了後、"sdkTest/sub"トピックにパブリッシュします。

lte_awsiot コマンドを実行した例を以下に示します。

nsh> lte_awsiot -x 1
app_restart_cb called. reason:Modem restart by application.
app_radio_on_cb called. result: 0
app_activate_pdn_cb called. result: 0
pdn.session_id : 1
pdn.active     : 1
pdn.apn_type   : 0x202
pdn.ipaddr[0].addr : 10.212.60.255
app_localtime_report_cb called: localtime : "19/12/13 : 14:15:16"
set localtime completed: 2019/12/13,14:15:16
app_deactivate_pdn_cb called. result: 0
app_radio_off_cb called. result: 0

送信したパブリッシュメッセージはAWS-IoTコンソール上で確認できます。

動作環境によっては通信状態が不安定になり、正しく動作しないことがあります。
詳細はFAQを確認してください。

5.4.5. 参考

LTE 機能の詳細は、開発ガイドを参照してください。

5.5. LTEのネットワークデーモンを使ってネットワーク接続を行う

LTEのネットワークデーモンを使ってネットワーク接続するコマンドについて説明します。
ネットワーク接続に成功するとwgetなどのコマンドを使用してデータ通信が可能となります。

5.5.1. ビルド手順

ここではコマンドラインによるビルド手順を示します。
IDE を使用してビルドする場合、以下に示すコンフィグレーション情報を参考にしてください。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に feature/lte を指定してコンフィグレーションを実行します。

    tools/config.py feature/lte
    

    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

    LTEを使用したexample(examples/lte_http_getなど)のコンフィグレーションでも
    CONFIG_LTE_DAEMON が有効になっているためそのままお使い頂けます。

5.5.2. 動作確認

シリアルターミナルを開いて、lte_daemon コマンドを実行します。

  1. シリアルターミナルを起動します。

    シリアルポートに /dev/ttyUSB0 を、baudrate に 115200 bps を指定して、 minicom ターミナルを使用する例を示します。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から lte_daemon コマンドを実行します。

    lte_daemon コマンドの使い方を以下に示します。

    nsh> lte_daemon <options> <action>
    options(オプションパラメータ、actionがstartの時のみ有効)
    オプション 説明

    -a

    アクセスポイント名。

    -t

    APNタイプ。16進数の値を設定します。詳細な値については LTE API リファレンスを参照してください。
    指定がなければ IADEFAULT の論理和が使用されます。

    -i

    APNプロトコル。0~2の値を設定します。(0: IPv4 , 1: IPv6 , 2: IPv4/v6 )
    指定がなければデフォルトは0: IPv4 です。

    -v

    認証タイプ。0~2の値を設定します。 (0: None , 1: PAP , 2: CHAP )
    指定がなければデフォルトは0: None です。

    -u

    ユーザ名。 認証タイプに 0: None を選択した場合、設定は無視されます。

    -p

    パスワード。 認証タイプに 0: None を選択した場合、設定は無視されます。

    各オプションのデフォルト値は変更することが可能です。(APNタイプを除く)
    詳細は APN設定をデフォルト設定から変更する手順について をご参照ください。

    action(必須パラメータ)
    action 説明

    start

    LTEのネットワークデーモンを開始します。

    stop

    LTEのネットワークデーモンを停止します。

  3. ネットワーク接続する場合、NuttShell から lte_daemon start コマンドと ifup コマンドを実行します。 ifconfig コマンドを実行することでコマンドを実行したタイミングでのインターフェースの状態が確認できます。

    nsh> ifconfig
    nsh>
    nsh> lte_daemon -a internet -v 2 -u user -p pass start
    nsh>
    nsh> ifconfig
    eth0    Link encap:Ethernet HWaddr 00:00:00:00:00:00 at DOWN
            inet addr:0.0.0.0 DRaddr:0.0.0.0 Mask:0.0.0.0
            inet6 addr: ::/0
            inet6 DRaddr: ::/0
    nsh>
    nsh> ifup eth0
    ifup eth0...OK
    nsh>
    nsh> ifconfig
    eth0    Link encap:Ethernet HWaddr 00:00:00:00:00:00 at UP
            inet addr:100.92.28.11 DRaddr:0.0.0.0 Mask:0.0.0.0
            inet6 addr: ::/0
            inet6 DRaddr: ::/0
    
    nsh>
  4. ネットワークに接続した状態で、NuttShell から wget コマンドを実行してインターネット上に置かれているファイルのURLを指定しファイルをダウンロードします。

    nsh> ifconfig
    eth0    Link encap:Ethernet HWaddr 00:00:00:00:00:00 at UP
            inet addr:100.92.28.11 DRaddr:0.0.0.0 Mask:0.0.0.0
            inet6 addr: ::/0
            inet6 DRaddr: ::/0
    
    nsh>
    nsh> wget -o /mnt/spif/index.html http://www.example.com/index.html
    nsh>
    nsh>
    nsh> cat /mnt/spif/index.html
    <!doctype html>
    <html>
    <head>
        <title>Example Domain</title>
    
        <meta charset="utf-8" />
        <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <style type="text/css">
        body {
            background-color: #f0f0f2;
            margin: 0;
            padding: 0;
            font-family: -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
    
        }
        div {
            width: 600px;
            margin: 5em auto;
            padding: 2em;
            background-color: #fdfdff;
            border-radius: 0.5em;
            box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);
        }
        a:link, a:visited {
            color: #38488f;
            text-decoration: none;
        }
        @media (max-width: 700px) {
            div {
                margin: 0 auto;
                width: auto;
            }
        }
        </style>
    </head>
    
    <body>
    <div>
        <h1>Example Domain</h1>
        <p>This domain is for use in illustrative examples in documents. You may use this
        domain in literature without prior coordination or asking for permission.</p>
        <p><a href="https://www.iana.org/domains/example">More information...</a></p>
    </div>
    </body>
    </html>
    nsh>
    
    nsh>
  5. ネットワーク切断する場合、NuttShell から ifdown コマンドを実行します。

    nsh> ifconfig
    eth0    Link encap:Ethernet HWaddr 00:00:00:00:00:00 at UP
            inet addr:100.92.28.11 DRaddr:0.0.0.0 Mask:0.0.0.0
            inet6 addr: ::/0
            inet6 DRaddr: ::/0
    
    nsh>
    nsh> ifdown eth0
    ifdown eth0...OK
    nsh>
    nsh> ifconfig
    eth0    Link encap:Ethernet HWaddr 00:00:00:00:00:00 at DOWN
            inet addr:0.0.0.0 DRaddr:0.0.0.0 Mask:0.0.0.0
            inet6 addr: ::/0
            inet6 DRaddr: ::/0
    
    nsh>
  6. LTEのネットワークデーモンを終了させる場合、NuttShell から lte_daemon stop コマンドを実行します。

    nsh> ifconfig
    eth0    Link encap:Ethernet HWaddr 00:00:00:00:00:00 at DOWN
            inet addr:0.0.0.0 DRaddr:0.0.0.0 Mask:0.0.0.0
            inet6 addr: ::/0
            inet6 DRaddr: ::/0
    
    nsh>
    nsh>
    nsh> lte_daemon stop
    nsh>
    nsh> ifconfig
    nsh>

5.5.3. APN設定をデフォルト設定から変更する手順について

ここではlte_daemonの引数に指定するAPN設定のデフォルト値を変更する手順を示します。

  1. lte_daemonのコンフィグレーションを変更します。

    tools/config.py -m
    
    1. APNのパラメータを設定します。(ご使用のSIMに合わせて設定してください。)

      Application Configuration -> Spresense SDK -> System tools -> lte_daemon
      - Access Point Name (CONFIG_LTE_DAEMON_APN_NAME)
      - IP type Selection
      - Authentication type Selection
      - Username used for authentication (CONFIG_LTE_DAEMON_APN_USERNAME)
      - Password used for authentication (CONFIG_LTE_DAEMON_APN_PASSWD)
      tutorial system lte daemon apn
      コンフィグレーション名 デフォルト値 説明

      Access Point Name

      アクセスポイント名

      IP type Selection

      0: IPv4

      APNプロトコル。0~2の値を設定します。0: IPv4, 1: IPv6 2: IPv4/v6 から選択します。

      Authentication type Selection

      0: None

      認証タイプ。0~2の値を設定します。 0: None 、1: PAP 、2: CHAP から選択します。

      Username used for authentication

      ユーザ名。 認証タイプに None を選択した場合、設定は無視されます。

      Password used for authentication

      パスワード。 認証タイプに None を選択した場合、設定は無視されます。

6. Network チュートリアル

6.1. ftp サンプルアプリケーション

この章では、NuttXの標準サンプルである、ftpc及びftpdに関するサンプルアプリケーションの動作手順を示します。

6.1.1. ソースコードパス

このサンプルのソースコードは、

  • FTP Client側: sdk/apps/examples/ftpc

  • FTP Server側: sdk/apps/examples/ftpd

にそれぞれ入っています。

6.1.2. 動作環境

このサンプルを動作させるには、以下のハードウェアを使う前提となっています。 サーバ用とクライアント用の2セット用意するか、サーバ用に1セットとクライアント用にftp clientがインストールされたPCを1台用意する必要があります。

Spresense Main Board
IDY Wi-Fi Add-on Board iS110B

6.1.3. ビルド手順

CLI 版を使ったビルド手順について書かれていますが、IDE 版でも同様のコンフィグレーションを選択することにより本サンプルアプリケーションをビルドすることができます。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、コンフィグレーションツールのTab補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. コンフィグレーションとビルドを行います。

    引数に examples/ftp を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    make distclean
    tools/config.py examples/ftp
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate として 500000 bps を設定しています。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

    Spresenseをもう1台使う場合はそちらにも同じnuttx.spkを書き込んでください。

6.1.4. 動作確認

シリアルターミナルを開いて、Wi-Fiに接続し、ftpd_start コマンドを実行して、 クライアントの接続を待ちます。 この例では、SpresenseのSPI Flash上に適当なファイル(test_ftp.txt)を作成して、 それをクライアントが取得(get)し、また、PC側からSpresenseに対して適当なファイルを送信(put)する動作を確認します。

  1. シリアルターミナルを起動します。

    下記の例では、シリアルポートとして /dev/ttyUSB0 を、baudrate として 115200 bps を設定してminicomで接続しています。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShellでSPI Flash上に適当なテキストファイルを作成します。

    以下のコマンドを叩いて、test_ftp.txtというファイルを作成します。

    nsh> echo This is Spresense FTPD > /mnt/spif/test_ftp.txt
    nsh> echo Everything is OK. >> /mnt/spif/test_ftp.txt

    catコマンドを使って、正しくファイルが作られているかを確認します。

    nsh> cat /mnt/spif/test_ftp.txt
    This is Spresense FTPD
    Everything is OK.
  3. NuttShell から Wi-Fi接続を行い、 ftpd_start コマンドを実行します。

    実機をAPモードでWi-Fiの設定を行い、ftpd_startでFTPデーモンを起動してClientからの接続待ち状態にします。 下記の例では、APモードでWi-Fiを起動し、SSIDをspresense_net、パスワードを0123456789としています。 ifconfigコマンドでIPアドレスを確認して、FTPデーモンを起動します。

    nsh> gs2200m -a 1 spresense_net 0123456789 &
    nsh> sleep 5
    nsh> ifconfig
    eth0    Link encap:Ethernet HWaddr 3c:95:09:00:56:49 at UP
            inet addr:192.168.11.1 DRaddr:192.168.11.1 Mask:255.255.255.0
    nsh> ftpd_start
    Initializing the network
    Starting the FTP daemon
    FTP daemon [10] started
    Adding accounts:
    1. Root account: USER=root PASSWORD=abc123 HOME=(none)
    2. User account: USER=ftp PASSWORD=(none) HOME=(none)
    3. User account: USER=anonymous PASSWORD=(none) HOME=(none)

    このftpdのサンプルでは、上記3つのアカウントが登録されています。これらのアカウント情報は、クライアントから接続する際に必要になります。

  4. PCからSpresenseのFTPサーバに接続します。

    上記の状態でPC側からSpresenseと同一のSSIDにWi-Fiを接続し、ftpコマンドでSpresense側に接続します。
    以下、Spresense側のIPアドレスが192.168.11.1として説明します。お使いの環境に合わせて適宜読み替えてください。 PCから接続すると、ユーザ名とパスワードが要求されるので、上記の3つのアカウントから好きなものを選び入力して接続を行なってください。以下の例では、rootアカウントを利用しています。
    (なお、お使いのPC環境によって、メッセージの出方は異なります)

    ftp 192.168.11.1
    Connected to 192.168.11.1.
    220 NuttX FTP Server
    Name (192.168.11.1:user): root
    331 Password required for root
    Password:
    230 Login successful.
    Remote system type is UNIX.
    Using binary mode to transfer files.
    ftp>
    

    あとは通常のftpのコマンドでファイルを取り出したり書き込んだりすることが出来ます。 まず、先ほど作成した/mnt/spif/test_ftp.txtを取得してみます。

    ftp> cd /mnt/spif
    250 CWD command successful
    ftp> get test_ftp.txt
    local: test_ftp.txt remote: test_ftp.txt
    229 Entering Extended Passive Mode (|||50000|).
    150 Opening data connection
    100% |**************************************************************************************************************************|    41        0.50 KiB/s    00:00 ETA
    226 Transfer complete
    41 bytes received in 00:00 (0.50 KiB/s)

    無事に転送が成功すると、上記のようなメッセージがPC側に出て来ます。
    FTPクライアントアプリを終了し、test_ftp.txtがあるか、中身が同じものかを確認します。

    ftp> quit
    221 Good-bye
    
    $ ls test_ftp.txt
    test_ftp.txt
    
    $ cat test_ftp.txt
    This is Spresense FTPD
    Everything is OK.

    無事に取得が出来たことがわかります。
    続いて、ファイルの書き込みを行なってみます。 まず、PC側でファイルを準備します。(ファイル名:test_pc.txt)

    echo "This is Host PC." > test_pc.txt
    echo "Nothing wrong with me." >> test_pc.txt
    cat test_pc.txt
    This is Host PC.
    Nothing wrong with me
    

    再度FTPクライアントを接続し、作成したファイルをputコマンドでSpresenseに転送します。

    ftp 192.168.11.1
    Connected to 192.168.11.1.
    220 NuttX FTP Server
    Name (192.168.11.1:user): root
    331 Password required for root
    Password:
    230 Login successful.
    Remote system type is UNIX.
    Using binary mode to transfer files.
    
    ftp> put test_pc.txt /mnt/spif/test_pc.txt
    local: test_pc.txt remote: /mnt/spif/test_pc.txt
    229 Entering Extended Passive Mode (|||50000|).
    150 Opening data connection
    100% |**************************************************************************************************************************|    40       63.61 KiB/s    00:00 ETA
    226 Transfer complete
    40 bytes sent in 00:00 (0.84 KiB/s)
    

    無事に転送が完了すると上記のようなメッセージがPC側で表示されます。
    Spresense側で転送されたファイルを見てみます。
    Spresenseに接続しているminicomターミナル上で以下のように確認が出来ます。 (nsh> というプロンプトが見えない場合、Enterキーを押せば出て来ます。)

    nsh> cat /mnt/spif/test_pc.txt
    This is Host PC.
    Nothing wrong with me.
    nsh>
  5. もう1台のSpresenseからクライアント接続する場合

    もう1台のSpresenseからクライアント接続を行う場合を説明します。
    サーバ側のSpresenseは上記のままで、Client側のSpresenseにminicomで接続し、Wi-Fi接続します。 サーバ側のSpresense同様にminicomでSpresenseのターミナルに接続してください。この例では、シリアルポートとして /dev/ttyUSB1 を、baudrate として 115200 bps を設定してminicomで接続しています。

    minicom -D /dev/ttyUSB1 -b 115200
    

    続いて、Wi-Fiに接続後、ftpcコマンドでサーバに接続します。

    nsh> gs2200m spresense_net 0123456789 &
    nsh> sleep 5
    nsh> ifconfig
    eth0    Link encap:Ethernet HWaddr 3c:95:09:00:56:49 at UP
            inet addr:192.168.11.2 DRaddr:192.168.11.1 Mask:255.255.255.0
    nsh>
    nsh> ftpc 192.168.11.1
    NuttX FTP Client:

    NuttX標準のftpクライアントでは、特にプロンプト等は表示されません。
    この状態でログインを行います。この例では、アカウントrootでログインしています。

    login root abc123

    特になんの応答もありませんが、これでログインは成功します。
    先ほどPCで取得したサーバ側のSpreseneにある、/mnt/spif/test_ftp.txtを取得してみます。

    get /mnt/spif/test_ftp.txt /mnt/spif/test_ftp.txt

    login同様になんの応答もありませんが、これでファイルの取得が成功しています。
    ftpcコマンドから抜けて、ファイルが取得出来たかを確認します。

    quit
    nfc> Exiting...
    
    nsh> cat /mnt/spif/test_ftp.txt
    This is Spresense FTPD
    Everything is OK.

    無事に転送が出来ていれば、上記のようにサーバ側で作成したファイルを見ることが出来ます。

6.1.5. Tips 既存のWi-Fiネットワークに接続する場合

場合によっては、APモードではなく、Spresenseを既存でお使いのWi-Fiネットワークに接続したい場合もあるかと思います。 その場合は、実機側でのコマンド入力を以下のようにしてください。

nsh> gs2200m <接続したいSSID> <SSIDのパスワード> &
nsh> sleep 5
nsh> ifconfig
eth0    Link encap:Ethernet HWaddr 3c:95:09:00:56:49 at UP
        inet addr:XXX.XXX.XXX.XXX DRaddr:XXX.XXX.XXX.XXX Mask:XXX.XXX.XXX.XXX
nsh> ftpd_start
Initializing the network
Starting the FTP daemon
FTP daemon [10] started
Adding accounts:
1. Root account: USER=root PASSWORD=abc123 HOME=(none)
2. User account: USER=ftp PASSWORD=(none) HOME=(none)
3. User account: USER=anonymous PASSWORD=(none) HOME=(none)

IPアドレスやネットマスクは、そのSSIDによって割り振られ、ifconfigで確認できます。

6.2. tcpecho サンプルアプリケーション

この章では、NuttXの標準サンプルである、tcpechoに関するサンプルアプリケーションの動作手順を示します。 TCPのシンプルなエコーサーバのサンプルになります。

6.2.1. ソースコードパス

このサンプルのソースコードは、 sdk/apps/examples/tcpecho 以下にあります。

6.2.2. 動作環境

このサンプルを動作させるには、以下のハードウェアを使う前提となっています。

Spresense Main Board
IDY Wi-Fi Add-on Board iS110B
ホストPC (telnetクライアントがインストールされていること)

6.2.3. ビルド手順

CLI 版を使ったビルド手順について書かれていますが、IDE 版でも同様のコンフィグレーションを選択することにより本サンプルアプリケーションをビルドすることができます。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、コンフィグレーションツールのTab補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. コンフィグレーションとビルドを行います。

    引数に examples/tcpecho を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    make distclean
    tools/config.py examples/tcpecho
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate として 500000 bps を設定しています。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

6.2.4. 動作確認

シリアルターミナルを開いて、Wi-Fiに接続し、tcpecho コマンドを実行して、クライアントから接続してechoバックを確認します。

  1. シリアルターミナルを起動します。

    まず、シリアルポートとして /dev/ttyUSB0 を、baudrate として 115200 bps を設定してminicomで接続しています。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から tcpecho コマンドを実行します。

    実機をAPモードでWi-Fiの設定を行い、tcpechoを起動してClientからの接続待ち状態にします。 下記の例では、APモードでWi-Fiを起動し、SSIDをspresense_net、パスワードを0123456789としています。 ifconfigコマンドでIPアドレスを確認して、tcpechoを起動します。

    nsh> gs2200m -a 1 spresense_net 0123456789 &
    nsh> sleep 5
    nsh> ifconfig
    eth0    Link encap:Ethernet HWaddr 3c:95:09:00:56:49 at UP
            inet addr:192.168.11.1 DRaddr:192.168.11.1 Mask:255.255.255.0
    nsh> tcpecho

    この状態でPC側から上記のSSIDにWi-Fiを接続し、telnetで192.168.11.1のポート80番に接続します。

    telnet 192.168.11.1 80
    Trying 192.168.11.1...
    Connected to 192.168.11.1.
    Escape character is '^]'.
    

    後はPCで適当な文字を打ってEnterキーを打てば、エコーバックが帰ってきます。

    hello
    hello        <- エコーバック文字列
    Spresense
    Spresense    <- エコーバック文字列

6.3. tcpblaster サンプルアプリケーション

この章では、NuttXの標準サンプルである、tcpblasterに関するサンプルアプリケーションの動作手順を示します。 TCPで接続したserver / client間でデータの送受信を行い、その転送レートを計測するサンプルです。

6.3.1. ソースコードパス

このサンプルのソースコードは、 sdk/apps/examples/tcpblaster 以下にあります。

6.3.2. 動作環境

このサンプルを動作させるには、以下のハードウェアを2セット使う前提となっています。 なお、対向をPCにして、1セットのみで動作させることも可能です。 最後にTipsとして、コンフィグの変更方法を載せています。

Spresense Main Board
IDY Wi-Fi Add-on Board iS110B

6.3.3. ビルド手順

CLI 版を使ったビルド手順について書かれていますが、IDE 版でも同様のコンフィグレーションを選択することにより本サンプルアプリケーションをビルドすることができます。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、コンフィグレーションツールのTab補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. コンフィグレーションとビルドを行います。

    引数に examples/tcpblaster を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    make distclean
    tools/config.py examples/tcpblaster
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    2つの機材に同じプログラムを焼き込みます。 この例では シリアルポートとして /dev/ttyUSB0, /dev/ttyUSB1 を、書き込み速度の baudrate として 500000 bps を設定しています。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    tools/flash.sh -c /dev/ttyUSB1 -b 500000 nuttx.spk
    

6.3.4. 動作確認

シリアルターミナルを開いて、Wi-Fiに接続し、tcpserver / tcpclient コマンドを実行します。

  1. シリアルターミナルを起動します。

    以下は、2つのminicom ターミナルを使用する例です。 まず、一つ目のターミナルから、シリアルポートとして /dev/ttyUSB0 を、baudrate として 115200 bps を設定してminicomで接続しています。

    minicom -D /dev/ttyUSB0 -b 115200
    

    まず、二つ目も同様に、シリアルポートを /dev/ttyUSB1 として接続しています。

    minicom -D /dev/ttyUSB1 -b 115200
    
  2. それぞれのNuttShell から tcpserver もしくは tcpclient コマンドを実行します。

    まず、片方の実機をAPモードでWi-Fiの設定を行います。 下記の例では、APモードでWi-Fiを起動し、SSIDをspresense_net、パスワードを0123456789としています。 Wi-Fiモジュールが正しく起動されると、IPアドレスが設定されるので、それを確認します。 ifconfigコマンドで、下記のように、IPアドレスが割り当てられます。

    ★ターミナル1
    nsh> gs2200m -a 1 spresense_net 0123456789 &
    nsh> sleep 5
    nsh> ifconfig
    eth0    Link encap:Ethernet HWaddr 3c:95:09:00:56:49 at UP
            inet addr:192.168.11.1 DRaddr:192.168.11.1 Mask:255.255.255.0

    続いてもう一方のminicomのターミナルに対して、上記で作成したAPにSTAモードで接続し、同様に割り当てられたIPアドレスを確認します。 gs2200mにてWi-Fiの設定を行なった後、5秒程度待ちます。これは、Wi-Fi APからのDHCPでのIPアドレスが付与されるなどを待つのが目的です。 無事に接続が上手く出来ると、下記のように、デフォルトルーターが上記APのアドレスになって、自己のIPアドレスが割り振られます。

    ★ターミナル2
    nsh> gs2200m spresense_net 0123456789 &
    nsh> sleep 5
    nsh> ifconfig
    eth0    Link encap:Ethernet HWaddr 3c:95:09:00:64:91 at UP
            inet addr:192.168.11.2 DRaddr:192.168.11.1 Mask:255.255.255.0

    この状態で、tcpserverを起動してClientからの接続待ち状態にします。

    ★ターミナル1
    nsh> tcpserver
    Binding to IPv4 Address: 00000000
    server: Accepting connections on port 5471

    続いて、tcpclientを起動します。引数に接続先のIPアドレスを設定します。 ターミナル1側のIPアドレス(この例では、192.168.11.1)を設定しています。 正しく動作すると、データの送受信が開始され、通信レートが算出されて表示されます。

    ★ターミナル2
    nsh> tcpclient 192.168.11.1
    Connecting to IPv4 Address: 010ba8c0
    client: Connected
    Sent 50 buffers:     50.0 Kb (avg   1.0 Kb) in   0.25 Sec (  195.1 Kb/Sec)
    Sent 50 buffers:     50.0 Kb (avg   1.0 Kb) in   0.16 Sec (  308.8 Kb/Sec)
    Sent 50 buffers:     50.0 Kb (avg   1.0 Kb) in   0.15 Sec (  329.8 Kb/Sec)
    Sent 50 buffers:     50.0 Kb (avg   1.0 Kb) in   0.17 Sec (  282.6 Kb/Sec)
    Sent 50 buffers:     50.0 Kb (avg   1.0 Kb) in   0.17 Sec (  286.9 Kb/Sec)
6.3.4.1. Tips 対向機をPCにする方法

この例では2セットのSpresenseを用いて速度計測をしていましたが、 片方をPCにすることも可能です。

その場合、上記コンフィグ手順まで終わった状態で、 menuconfigを開いて、以下のようにビルド設定を変更します。 spresense/sdk以下で、

make menuconfig

とし、

Application Configuration ->
  Examples ->
    TCP Performance Test

にある、

Second endpoint is a target

のチェックを外します。 これで、一旦cleanしてから再度ビルドを行います。

make clean
make

無事にビルドが完了すると、ホスト側のプログラムとして、tcpclient が、sdk/apps/examples/tcpblasterの下にできています。 この使い方は、上記のtcpclientと同様です。 Spresense側でtcpserverを立ち上げておき、PCからtcpclientで接続することで、 動作可能です。

7. Graphics チュートリアル

7.1. NX サンプルアプリケーション

この章では、NuttXのグラフィックスシステムである、NXに関するサンプルアプリケーションの動作手順を示します。 NuttXのグラフィックスサブシステムに関する詳細は、 NuttX NX Graphic Subsystem を参照してください。

Spresenseで動作確認をしているNXに関するサンプルコードとそれぞれのソースコードのディレクトリパスは、 下記の様になります。

表 1. NXサンプルコード
サンプル名 ソースコードパス デフォルトコンフィグ名 概要

fb

sdk/apps/examples/fb

examples/fb

フレームバッファをダイレクトに操作するサンプル

nx

sdk/apps/examples/nx

examples/nx

NXのWindowシステムの描画に関するサンプル

nxdemo

sdk/apps/examples/nxdemo

examples/nxdemo

NXの描画に関するサンプル

nxhello

sdk/apps/examples/nxhello

examples/nxhello

NXのテキスト描画に関するサンプル

nximage

sdk/apps/examples/nximage

examples/nximage

NXのイメージ描画に関するサンプル

nxlines

sdk/apps/examples/nxlines

examples/nxlines

NXの直線描画に関するサンプル

nxtext

sdk/apps/examples/nxtext

examples/nxtext

NXのテキスト描画とポップアップウィンドウの描画に関するサンプル

7.1.1. ビルド手順

CLI 版を使ったビルド手順について書かれていますが、IDE 版でも同様のコンフィグレーションを選択することにより本サンプルアプリケーションをビルドすることができます。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、コンフィグレーションツールのTab補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. コンフィグレーションとビルドを行います。

    引数に 上記の表の デフォルトコンフィグ名 に記載されている値を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    make distclean
    tools/config.py <デフォルトコンフィグ名>
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate として 500000 bps を設定しています。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

7.1.2. 動作環境

このサンプルを動作させるには、以下のハードウェアを使う前提となっています。

Spresense Main Board
Spresense Extension Board
Arduino UNO LCD Connector board
ILI9341 2.2inch LCD

7.1.3. 動作確認

シリアルターミナルを開いて、nx コマンドを実行します。

  1. シリアルターミナルを起動します。

    以下は、minicom ターミナルを使用する例です。 シリアルポートとして /dev/ttyUSB0 を、baudrate として 115200 bps を設定しています。

    minicom -D /dev/ttyUSB0 -b 115200
    
7.1.3.1. NuttShell から それぞれのコマンドを実行します。
  1. fb サンプルの場合

    以下の様なメッセージとともに、LCDディスプレイに様々な色の矩形が描画されます。

    nsh> fb
    VideoInfo:
          fmt: 11
         xres: 320
         yres: 240
      nplanes: 1
    PlaneInfo (plane 0):
        fbmem: 0xd0353c0
        fblen: 153600
       stride: 640
      display: 0
          bpp: 16
    Mapped FB: 0xd0353c0
     0: (  0,  0) (319,239)
     1: ( 29, 21) (290,218)
     2: ( 58, 42) (261,197)
     3: ( 87, 63) (232,176)
     4: (116, 84) (203,155)
     5: (145,105) (174,134)
    Test finished
  2. nx サンプルの場合

    以下の様なメッセージとともに、LCDディスプレイにWindowが描画されます。

    nsh> nx
    nx_main: NX handle=0xd032050
    nx_main: Set background color=8087790
    nx_main: Create window #1
    nx_main: hwnd1=0xd03aeb0
    nx_main: Screen resolution (319,239)
    nx_main: Set window #1 size to (159,119)
    nx_main: Sleeping
    
    nxeg_position1: hwnd=0xd03aeb0 size=(159,119) pos=(4,4) bounds={(0,0),(319,239)}
    nxeg_position1: hwnd=0xd03aeb0 size=(159,119) pos=(4,4) bounds={(0,0),(319,239)}
    nxeg_redraw1: hwnd=0xd03aeb0 rect={(0,0),(158,118)} more=false
    nx_main: Set window #1 position to (39,29)
    nx_main: Sleeping
    
    nxeg_position1: hwnd=0xd03aeb0 size=(159,119) pos=(39,29) bounds={(0,0),(319,239)}
    nxeg_redraw1: hwnd=0xd03aeb0 rect={(0,0),(158,118)} more=false
    nx_main: Add toolbar to window #1
    nx_main: Sleeping
    
    nxeg_redraw1: hwnd=0xd03aeb0 rect={(0,0),(158,102)} more=false
    nxeg_tbredraw1: hwnd=0xd03aeb0 rect={(0,0),(158,15)} more=false
    nx_main: Create window #2
    nx_main: hwnd2=0xd03af10
    nx_main: Sleeping
    
    nxeg_position2: hwnd=0xd03af10 size=(0,0) pos=(0,4) bounds={(0,0),(319,239)}
    nx_main: Set hwnd2 size to (159,119)
    nx_main: Sleeping
    
    nxeg_position2: hwnd=0xd03af10 size=(159,119) pos=(4,4) bounds={(0,0),(319,239)}
    nxeg_redraw2: hwnd=0xd03af10 rect={(0,0),(158,118)} more=false
    nx_main: Set hwnd2 position to (121,91)
    nx_main: Sleeping
    
    nxeg_position2: hwnd=0xd03af10 size=(159,119) pos=(121,91) bounds={(0,0),(319,239)}
    nxeg_redraw2: hwnd=0xd03af10 rect={(0,0),(158,118)} more=false
    nxeg_redraw1: hwnd=0xd03aeb0 rect={(0,0),(158,41)} more=false
    nxeg_tbredraw1: hwnd=0xd03aeb0 rect={(0,0),(158,15)} more=false
    nxeg_redraw1: hwnd=0xd03aeb0 rect={(0,42),(77,102)} more=false
    nx_main: Add toolbar to window #2
    nx_main: Sleeping
    
    nxeg_redraw2: hwnd=0xd03af10 rect={(0,0),(158,102)} more=false
    nxeg_tbredraw2: hwnd=0xd03af10 rect={(0,0),(158,15)} more=false
    nx_main: Lower window #2
    nx_main: Sleeping
    
    nxeg_redraw1: hwnd=0xd03aeb0 rect={(78,42),(158,102)} more=false
    nx_main: Raise window #2
    nx_main: Sleeping
    
    nxeg_redraw2: hwnd=0xd03af10 rect={(0,0),(158,102)} more=false
    nxeg_tbredraw2: hwnd=0xd03af10 rect={(0,0),(158,15)} more=false
    nx_main: Close window #2
    nx_main: Close window #1
    nx_main: Disconnect from the server
    nxeg_redraw1: hwnd=0xd03aeb0 rect={(78,42),(158,102)} more=false
    nx_listenerthread: Lost server connection: 117
  3. nxdemo サンプルの場合

    以下の様なメッセージがターミナルに表示され、LCDディスプレイに様々な模様が描画されます。

    nsh> nxdemo
    nxdemo_listener: Connected
    nxdemo_main: NX handle=0xd031440
    nxdemo_main: Screen resolution (320,240)
    nxdemo_main: Disconnect from the server
    nxdemo_listener: Lost server connection: 117
  4. nxhello サンプルの場合

    以下の様なメッセージがターミナルに表示され、LCDディスプレイの中央に Hello, World! という文字が描画されます。

    nsh> nxhello
    nxhello_main: NX handle=0xd031440
    nxhello_main: Set background color=31581
    nxhello_main: Screen resolution (320,240)
    nxhello_hello: Position (114,105)
    nxhello_main: Disconnect from the server
    nxhello_listener: Lost server connection: 117
  5. nximage サンプルの場合

    このサンプルでは、コマンドが nxhello となります。 実行すると以下の様なメッセージがターミナルに表示され、LCDディスプレイの中央にNuttXのロゴマークが描画されます。

    nsh> nxhello
    nximage_main: NX handle=0xd033d80
    nximage_main: Set background color=0
    nximage_listener: Connected
    nximage_main: Screen resolution (320,240)
    nximage_main: Disconnect from the server
    nximage_listener: Lost server connection: 117
  6. nxlines サンプルの場合

    以下の様なメッセージがターミナルに表示され、LCDディスプレイに円と円の中央に線が描画され続けます。

    nsh> nxlines
    Angle: 0002bfaa vector: (184,60)->(136,180)
    Angle: 0002f1ed vector: (172,57)->(148,183)
    Angle: 00032430 vector: (160,56)->(160,184)
    Angle: 00035673 vector: (147,57)->(173,183)
    Angle: 000388b6 vector: (135,60)->(185,180)
    Angle: 0003baf9 vector: (124,66)->(196,174)
    Angle: 0003ed3c vector: (114,74)->(206,166)
    Angle: 00041f7f vector: (106,84)->(214,156)
    Angle: 000451c2 vector: (100,95)->(220,145)
    Angle: 00048405 vector: (97,107)->(223,133)
    Angle: 0004b648 vector: (96,119)->(224,121)
    Angle: 0004e88b vector: (97,132)->(223,108)
    Angle: 00051ace vector: (100,144)->(220,96)
    Angle: 00054d11 vector: (106,155)->(214,85)
    Angle: 00057f54 vector: (114,165)->(206,75)
  7. nxtext サンプルの場合

    以下の様なメッセージがターミナルに表示され、LCDディスプレイに様々な文字が描画されると共にポップアップ矩形が描画されます。

    nsh> nxtext
    nxtext_initialize: Starting NX server
    nxtext_main: NX handle=0xd032450
    nxtext_main: Set background color=31581
    nxtext_listener: Connected
    nxtext_main: Screen resolution (320,240)
    nxpu_open: Create pop-up
    nxpu_open: Set pop-up position to (22,99)
    nxtext_main: Close pop-up
    nxpu_open: Create pop-up
    nxpu_open: Set pop-up position to (90,46)
    nxtext_main: Close pop-up
    nxpu_open: Create pop-up
    nxpu_open: Set pop-up position to (171,136)
    nxtext_main: Close pop-up
    nxpu_open: Create pop-up
    nxpu_open: Set pop-up position to (42,164)
    nxtext_main: Close pop-up
    nxpu_open: Create pop-up
    nxpu_open: Set pop-up position to (100,16)
    nxtext_main: Close pop-up
    nxpu_open: Create pop-up
    nxpu_open: Set pop-up position to (132,67)
    nxtext_main: Close pop-up
    nxpu_open: Create pop-up

7.1.4. Tips LCD画面のオリエンテーションの変更方法

作成されるアプリケーションによって、LCD画面の前後左右を変更したい場合、 以下のコンフィグを変更することで、LCDのオリエンテーションを変更することが可能です。 tools/config.py -m でコンフィグメニューを開き、下記の階層にある、 LCD Orientation の設定値を変更してください。

Device Drivers ->
  LCD Driver Support ->
    Graphic LCD Driver Support ->
      LCD driver selection ->
        LCD Orientation ()

8. FileSystem チュートリアル

8.1. SmartFS

SPI-Flash のファイルシステムに使用している SmartFS について説明します。

SmartFS ファイルシステムの詳細については以下のNuttX Wikiを参照してください。

8.1.1. 初期化&マウント処理

起動時に呼ばれる cxd56_bringup() 関数から board_flash_initialize() を呼び出します。

File: nuttx/boards/arm/cxd56xx/spresense/src/cxd56_bringup.c

#ifdef CONFIG_CXD56_SFC
  ret = board_flash_initialize();
  if (ret < 0)
    {
      _err("ERROR: Failed to initialize SPI-Flash. %d\n", errno);
    }
#endif

board_flash_initialize() 関数の中で、SPI-Flash を SmartFS ファイルシステムとして 初期化し、/mnt/spif ディレクトリへマウントします。

File: nuttx/boards/arm/cxd56xx/common/src/cxd56_flash.c

int board_flash_initialize(void)
{
  int ret;
  FAR struct mtd_dev_s *mtd;

  mtd = cxd56_sfc_initialize(); (1)
  if (!mtd)
    {
      ferr("ERROR: Failed to initialize SFC. %d\n ", ret);
      return -ENODEV;
    }

  /* use the FTL layer to wrap the MTD driver as a block driver */

  ret = ftl_initialize(CONFIG_SFC_DEVNO, mtd);
  if (ret < 0)
    {
      ferr("ERROR: Initializing the FTL layer: %d\n", ret);
      return ret;
    }

#if defined(CONFIG_FS_SMARTFS)
  /* Initialize to provide SMARTFS on the MTD interface */

  ret = smart_initialize(CONFIG_SFC_DEVNO, mtd, NULL); (2)
  if (ret < 0)
    {
      ferr("ERROR: SmartFS initialization failed: %d\n", ret);
      return ret;
    }

  ret = mount("/dev/smart0d1", "/mnt/spif", "smartfs", 0, NULL); (3)
  if (ret < 0)
    {
      ferr("ERROR: Failed to mount the SmartFS volume: %d\n", errno);
      return ret;
    }
#elif defined(CONFIG_FS_NXFFS)
1 Memory Technology Device (MTD) デバイスとして登録します。
2 MTD デバイスを SmartFS ファイルシステムとして初期化します。
3 /dev/smart0d1 デバイスファイルを /mnt/spif へマウントします。

8.1.2. コンフィグレーション

SmartFS を使用するにあたり、いくつかのコンフィグレーションが存在します。

SDK としてデフォルトで設定している推奨構成(sdk/configs/default/defconfig)を以下に示します。

Configuration Value Description

CONFIG_FS_SMARTFS

y

SmartFS ファイルシステムを有効にします

CONFIG_SMARTFS_ERASEDSTATE=0xff

0xff

SPI-Flashの値が0xFFのときにErase状態を意味します。

CONFIG_SMARTFS_MAXNAMLEN

30

ファイル名の最大長は30文字です。

CONFIG_SMARTFS_MULTI_ROOT_DIRS

y

マルチルートディレクトリをサポートしていますが、 デフォルトでは 1 つのルートディレクトリエントリを使用しています。

CONFIG_MTD_SMART

y

MTD デバイスとして SmartFS を使用します

CONFIG_MTD_SMART_SECTOR_SIZE

4096

1 セクタのサイズは 4096 バイトです。ファイルの最小単位として 1 セクタ分を使用します。 このサイズを小さくすると管理できるファイル数は増えますが、 小さくしすぎるとファイルのサーチ処理に時間がかかるようになります。

CONFIG_MTD_SMART_WEAR_LEVEL

n

これを有効にすると Read-only ファイルについても定期的にセクタ移動を行います。 Read-only ファイルについても移動中に電源がOffされてファイルが消去される可能性があるため、 途中で電源断が発生し得るシステムの場合は Disable することを推奨します。

CONFIG_MTD_SMART_ENABLE_CRC

y

CRCを使用して書き込み不良のチェックを行います。

CONFIG_MTD_SMART_FSCK

y

ファイル操作中に電源断が発生した場合など、ファイルシステムとして不整合のある状態が発生します。 これを有効にすると、起動時にファイルシステムの整合性をチェックし、ファイルとして成立していない ファイルを削除してファイルシステムを整合性の取れた状態に保ちます。

CONFIG_MTD_SMART_MINIMIZE_RAM

n

論物変換セクタをキャッシュする操作ですが、有効にするとアクセス速度が低下するため デフォルトではdisableしています。

8.1.3. 動作確認

NuttShell プロンプトから df コマンドによって Filesystem を確認することができます。

nsh> df -h
  Filesystem    Size      Used  Available Mounted on
  smartfs         4M       68K      4028K /mnt/spif
  procfs          0B        0B         0B /proc

/mnt/spifsmartfs ファイルシステムとしてマウントされていること、 トータル 4Mバイトのサイズのうち、使用サイズ (Used)、空きサイズ (Available) を確認することができます。

ファイルを作成する
nsh> echo "This is a test file." > /mnt/spif/test.txt
作成されたファイルのサイズを確認する
nsh> ls -l /mnt/spif
/mnt/spif:
 -rw-rw-rw-      21 test.txt
ファイルの内容を確認する
nsh> cat /mnt/spif/test.txt
This is a test file.

プログラムからファイル操作を行う場合は、 open/read/write/closeといった低水準入出力関数や fopen/fread/fwrite/fcloseといったファイル入出力関数を使うことができます。

8.1.4. フォーマット手順

SPI-Flash は工場出荷時に SmartFS ファイルシステムとして使用できるように初期化されています。 SPI-Flash をクリーンアップしたいときには mksmartfs コマンドを利用することができます。

Usage
nsh> help mksmartfs
mksmartfs usage:  mksmartfs [-s <sector-size>] [-f] <path> [<num-root-directories>]
Example
nsh> $ mksmartfs -s 4096 -f /dev/smart0d1 1

mksmartfs コマンドを実行後に、root directory 領域として数セクタが予約され、残りを使用することが可能です。

nsh> df -h
  Filesystem    Size      Used  Available Mounted on
  smartfs         4M       28K      4068K /mnt/spif
  procfs          0B        0B         0B /proc

9. その他のチュートリアル

9.1. json サンプルアプリケーション

この章では、NuttXの標準サンプルである、jsonに関するサンプルアプリケーションの動作手順を示します。 このサンプルは、組み込み向けオープンソースの、 cJSONをライブラリとして利用しています。

cJSONはjsonフォーマットで記載されたテキストをパースするためのライブラリです。+ json形式のファイルはネットなどでのやり取りする情報などの構造化によく用いられています。

ビルド時にcJSONをwgetにてダウンロードされるため、wgetをインストールしておく必要があります。

9.1.1. ソースコードパス

このサンプルのソースコードは、 sdk/apps/examples/json 以下にあります。
また、ダウンロードされるオープンソースcJSONは、 sdk/apps/netutils/cJSON 以下にダウンロードされます。

9.1.2. ビルド手順

CLI 版を使ったビルド手順について書かれていますが、IDE 版でも同様のコンフィグレーションを選択することにより本サンプルアプリケーションをビルドすることができます。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、コンフィグレーションツールのTab補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. コンフィグレーションとビルドを行います。

    引数に examples/json を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    make distclean
    tools/config.py examples/json
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate として 500000 bps を設定しています。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

9.1.3. 動作確認

シリアルターミナルを開いて、json コマンドを実行します。

  1. シリアルターミナルを起動します。

    以下は、minicom ターミナルを使用する例です。 シリアルポートとして /dev/ttyUSB0 を、baudrate として 115200 bps を設定しています。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から json コマンドを実行します。

    このサンプルコマンドでは、cJSONを用いて、サンプルコード内にハードコードされたjson形式のテキストデータのパースや、 json形式のテキストの生成を行います。

    nsh> json
    {
      "name": "Jack (\"Bee\") Nimble",
      "format": {
        "type": "rect",
        "width":  1920,
        "height": 1080,
        "interlace":  false,
        "frame rate": 24
      }
    }
    ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
    [[0, -1, 0], [1, 0, 0], [0, 0, 1]]
    {
      "Image":  {
        "Width":  800,
        "Height": 600,
        "Title":  "View from 15th Floor",
        "Thumbnail":  {
          "Url":  "http:/*www.example.com/image/481989943",
          "Height": 125,
          "Width":  "100"
        },
        "IDs":  [116, 943, 234, 38793]
      }
    }
    [{
        "precision":  "zip",
        "Latitude": 37.7668,
        "Longitude":  -122.3959,
        "Address":  "",
        "City": "SAN FRANCISCO",
        "State":  "CA",
        "Zip":  "94107",
        "Country":  "US"
      }, {
        "precision":  "zip",
        "Latitude": 37.371991,
        "Longitude":  -122.02602,
        "Address":  "",
        "City": "SUNNYVALE",
        "State":  "CA",
        "Zip":  "94085",
        "Country":  "US"
      }]
    {
      "name": "Jack (\"Bee\") Nimble",
      "format": {
        "type": "rect",
        "width":  1920,
        "height": 1080,
        "interlace":  false,
        "frame rate": 24
      }
    }
    ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
    [[0, -1, 0], [1, 0, 0], [0, 0, 1]]
    {
      "Image":  {
        "Width":  800,
        "Height": 600,
        "Title":  "View from 15th Floor",
        "Thumbnail":  {
          "Url":  "http:/*www.example.com/image/481989943",
          "Height": 125,
          "Width":  "100"
        },
        "IDs":  [116, 943, 234, 38793]
      }
    }
    [{
        "precision":  "zip",
        "Latitude": 37.7668,
        "Longitude":  -122.3959,
        "Address":  "",
        "City": "SAN FRANCISCO",
        "State":  "CA",
        "Zip":  "94107",
        "Country":  "US"
      }, {
        "precision":  "zip",
        "Latitude": 37.371991,
        "Longitude":  -122.026,
        "Address":  "",
        "City": "SUNNYVALE",
        "State":  "CA",
        "Zip":  "94085",
        "Country":  "US"
      }]

9.2. ini_dumper サンプルアプリケーション

この章では、NuttXの標準サンプルである、ini_dumperに関するサンプルアプリケーションの動作手順を示します。 このサンプルは、組み込み向けオープンソースのiniファイルパーサー、 inihを利用しています。

iniファイルはWindowsで設定ファイルとしてよく用いられているフォーマットです。+ アプリ開発を行う際に、複数の機材に対して同じアプリを使い、それぞれの機材に合わせて変更したい場合などに便利です。

ビルド時にinihをwgetにてダウンロードされるため、wgetをインストールしておく必要があります。

9.2.1. ソースコードパス

このサンプルのソースコードは、 sdk/apps/examples/ini_dumper 以下にあります。
また、ダウンロードされるオープンソースinihは、 sdk/apps/fsutils/inih 以下にダウンロードされます。

9.2.2. ビルド手順

CLI 版を使ったビルド手順について書かれていますが、IDE 版でも同様のコンフィグレーションを選択することにより本サンプルアプリケーションをビルドすることができます。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、コンフィグレーションツールのTab補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. コンフィグレーションとビルドを行います。

    引数に examples/ini_dumper を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    make distclean
    tools/config.py examples/ini_dumper
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate として 500000 bps を設定しています。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

9.2.3. 動作確認

シリアルターミナルを開いて、ini_dumper コマンドを実行します。

  1. シリアルターミナルを起動します。

    以下は、minicom ターミナルを使用する例です。 シリアルポートとして /dev/ttyUSB0 を、baudrate として 115200 bps を設定しています。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から ini_dumper コマンドを実行します。

    このサンプルコマンドは、引数にiniファイルのパスを指定することで、そのファイルをパースして表示してくれます。
    このチュートリアルでは、以下のコマンドで、まずは、/mnt/spif/sample.iniを作成し、それをパースしてみます。

    nsh> echo [System] > /mnt/spif/sample.ini
    nsh> echo Board = Spresense >> /mnt/spif/sample.ini
    nsh> echo  >> /mnt/spif/sample.ini
    nsh> echo [Information] >> /mnt/spif/sample.ini
    nsh> echo ProvidedBy = Sony Semiconductor Solutions >> /mnt/spif/sample.ini

    上記コマンドで/mnt/spifにsample.iniが作られているかcatコマンドで確認します。 無事にファイルが作られていれば、以下の様なメッセージが出力されます。

    nsh> cat /mnt/spif/sample.ini
    [System]
    Board = Spresense
    
    [Information]
    ProvidedBy = Sony Semiconductor Solutions

    ファイルが作られていることが確認できたら、サンプルコマンドを使ってそのファイルをパースします。

    nsh> ini_dumper /mnt/spif/sample.ini
    
    ------ --------------- ------------- ---------------------------
     line      section          key                 value
    ------ --------------- ------------- ---------------------------
     2      System          Board         Spresense
     5      Information     ProvidedBy    Sony Semiconductor Solutions
    ------ --------------- ------------- ---------------------------
    ini_parse() exited with 0

9.3. pdcurses サンプルアプリケーション

この章では、NuttXの標準サンプルである、pdcursesに関するサンプルアプリケーションの動作手順を示します。 このサンプルは、オープンソースのPDCursesをNuttXにポーティングされた PDCursesをNuttXにポーティングされたものを利用しています。

このサンプルには、
charset, newdemo, testcurs, worm, firework, rain, tui, xmas
という8つのデモが含まれています。

9.3.1. ソースコードパス

このサンプルのソースコードは、 sdk/apps/examples/pdcurses 以下にあります。
また、PDCursesのポーティングされたソースコードは、 sdk/apps/graphics/pdcurs34 以下にあります。

9.3.2. ビルド手順

CLI 版を使ったビルド手順について書かれていますが、IDE 版でも同様のコンフィグレーションを選択することにより本サンプルアプリケーションをビルドすることができます。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、コンフィグレーションツールのTab補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. コンフィグレーションとビルドを行います。

    引数に examples/pdcurses を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    make distclean
    tools/config.py examples/pdcurses
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate として 500000 bps を設定しています。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

9.3.3. 動作環境

このサンプルを動作させるには、以下のハードウェアを使う前提となっています。

Spresense Main Board
Spresense Extension Board
Arduino UNO LCD Connector board
ILI9341 2.2inch LCD

9.3.4. 動作確認

このサンプルには、PDCursesを使った複数のサンプルデモコマンドが用意されています。 シリアルターミナルを開いて、各コマンドを実行します。

  1. シリアルターミナルを起動します。

    以下は、minicom ターミナルを使用する例です。 シリアルポートとして /dev/ttyUSB0 を、baudrate として 115200 bps を設定しています。

    minicom -D /dev/ttyUSB0 -b 115200
    
9.3.4.1. NuttShell から 各サンプルのコマンドを実行します。
  1. charset の実行

    charset サンプルコマンドは、PDCursesで扱う文字をLCD画面中央に表示し終了します。

    nsh> charset
  2. newdemo の実行

    newdemo サンプルコマンドは、PDCursesを使って様々なテキストウィンドウを表示したり、 文字を動かしたりします。このコマンドは一度実行すると終了せずに動きっぱなしになります。 別のサンプルコマンドを実行したい場合は、Spresemseメインボードのリセットボタンを押して再起動してください。

    nsh> newdemo
  3. worm の実行

    worm サンプルコマンドは、赤、青、緑のワーム(ミミズの様なもの)がLCD上をうねうねします。 このコマンドは一度実行すると終了せずに動きっぱなしになります。 別のサンプルコマンドを実行したい場合は、Spresemseメインボードのリセットボタンを押して再起動してください。

    nsh> worm
  4. firework の実行

    firework サンプルコマンドは、PDCursesを用いて花火の様なグラフィックを表示します。 このコマンドは一度実行すると終了せずに動きっぱなしになります。 別のサンプルコマンドを実行したい場合は、Spresemseメインボードのリセットボタンを押して再起動してください。

    nsh> firework
  5. rain の実行

    rain サンプルコマンドは、PDCursesを用いて雨の雫が落ちた様なグラフィックを表示します。 このコマンドは一度実行すると終了せずに動きっぱなしになります。 別のサンプルコマンドを実行したい場合は、Spresemseメインボードのリセットボタンを押して再起動してください。

    nsh> rain
  6. tui の実行

    tui サンプルコマンドは、PDCursesを用いてテキストベースのユーザインターフェイスを表示します。 このコマンドは一度実行すると終了せずに動きっぱなしになります。 別のサンプルコマンドを実行したい場合は、Spresemseメインボードのリセットボタンを押して再起動してください。

    nsh> tui
  7. xmas の実行

    xmas サンプルコマンドは、PDCursesを用いクリスマスっぽいアニメーションを表示します。

    nsh> xmas

9.4. embedlog サンプルアプリケーション

この章では、NuttXの標準サンプルである、embedlogに関するサンプルアプリケーションの動作手順を示します。 このサンプルは、組み込み向けの非常に軽いオープンソースのログライブラリ、 embedlogを利用しています。

ビルド時にembedlogをwgetにてダウンロードされるため、wgetをインストールしておく必要があります。

9.4.1. ソースコードパス

このサンプルのソースコードは、 sdk/apps/examples/embedlog 以下にあります。
また、ダウンロードされるオープンソースembedlogは、 sdk/apps/system/embedlog 以下にダウンロードされます。

9.4.2. ビルド手順

CLI 版を使ったビルド手順について書かれていますが、IDE 版でも同様のコンフィグレーションを選択することにより本サンプルアプリケーションをビルドすることができます。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、コンフィグレーションツールのTab補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. コンフィグレーションとビルドを行います。

    引数に examples/embedlog を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    make distclean
    tools/config.py examples/embedlog
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate として 500000 bps を設定しています。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

9.4.3. 動作確認

シリアルターミナルを開いて、embedlog コマンドを実行します。

  1. シリアルターミナルを起動します。

    以下は、minicom ターミナルを使用する例です。 シリアルポートとして /dev/ttyUSB0 を、baudrate として 115200 bps を設定しています。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から embedlog コマンドを実行します。

    実行すると、以下の様に、サンプルコードの内容にしたがって、様々なフォーマットでのログ出力を確認することができます。

    nsh> embedlog
    i/Right after init, embedlog will print to stderr with just log level information - these are default settings.
    We can disable information about log level
    message still will be filtered by log level
    but there is no way to tell what level message is
    [24] As every respected logger, we also have timestamps
    [24] which work well with time from time()
    [8] or CLOCK_MONOTONIC from POSIX
    [1970-01-01 00:00:24] we also have long format that works well with time()
    [1970-01-01 00:00:24] if higher precision is needed we can use CLOCK_REALTIME
    [24] we can also mix REALTIME with short format
    [24] and if you don't need high resolution
    [24] you can disable fractions of seconds to save space!
    [24.878] or enable only millisecond resolution
    [24.879011] or enable only microsecond resolution
    [24.879255804] or enable only nanosecond resolution (not that it makes much sense on nuttx)
    no time information, if your heart desire it
    [embedlog_main.c:134] log location is very useful for debugging
    [1970-01-01 00:00:24.880201831][embedlog_main.c:139] f/Different scenarios need different options
    [1970-01-01 00:00:24.880690103][embedlog_main.c:140] a/So we can mix options however we want
    [1970-01-01 00:00:24.888532972][embedlog_main.c:143] f/you can also remove printing new line to join el_oprint and el_oputs in a singld
    [1970-01-01 00:00:24.901472180][embedlog_main.c:150] d/And if we have
    [1970-01-01 00:00:24.909162464][embedlog_main.c:151] i/modern terminal
    [1970-01-01 00:00:24.916822231][embedlog_main.c:152] n/we can enable colors
    [1970-01-01 00:00:24.924543032][embedlog_main.c:153] w/to spot warnings
    [1970-01-01 00:00:24.929822473][embedlog_main.c:154] e/or errors
    [1970-01-01 00:00:24.937543274][embedlog_main.c:155] c/with a quick
    [1970-01-01 00:00:24.945203041][embedlog_main.c:156] a/glance into
    [1970-01-01 00:00:24.950482482][embedlog_main.c:157] f/log file
    [1970-01-01 00:00:24.958142249][embedlog_main.c:160] i/embedlog: you can also use prefixes
    [1970-01-01 00:00:24.965954601][embedlog_main.c:161] i/embedlog: to every message you send
    [1970-01-01 00:00:24.973766953][embedlog_main.c:164] i/set prefix to null to disable it
    [1970-01-01 00:00:24.984020665][embedlog_main.c:196] i/print whole ASCII table
    [1970-01-01 00:00:24.991802500][embedlog_main.c:197] i/0x0000  00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f  ................
    [1970-01-01 00:00:25.002319292][embedlog_main.c:197] i/0x0010  10 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f  ................
    [1970-01-01 00:00:25.015258500][embedlog_main.c:197] i/0x0020  20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f   !"#$%&'()*+,-./
    [1970-01-01 00:00:25.028228225][embedlog_main.c:197] i/0x0030  30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f  0123456789:;<=>?       [1970-01-01 00:00:25.038695556][embedlog_main.c:197] i/0x0040  40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f  @ABCDEFGHIJKLMNO       [1970-01-01 00:00:25.051604247][embedlog_main.c:197] i/0x0050  50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f  PQRSTUVWXYZ[\]^_
    [1970-01-01 00:00:25.064573972][embedlog_main.c:197] i/0x0060  60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f  `abcdefghijklmno
    [1970-01-01 00:00:25.075041303][embedlog_main.c:197] i/0x0070  70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f  pqrstuvwxyz{|}~.
    [1970-01-01 00:00:25.087888960][embedlog_main.c:199] i/print memory region that contains string with NULL chars
    [1970-01-01 00:00:25.098356291][embedlog_main.c:201] i/0x0000  73 6f 6d 65 20 6d 65 73 73 61 67 65 00 74 68 61  some message.tha
    [1970-01-01 00:00:25.111264982][embedlog_main.c:201] i/0x0010  74 20 63 6f 6e 74 61 69 6e 73 00 6e 75 6c 6c 20  t contains.null
    [1970-01-01 00:00:25.121701796][embedlog_main.c:201] i/0x0020  63 68 61 72 61 63 74 65 72 73 00                 characters.
    [1970-01-01 00:00:25.134457902][embedlog_main.c:203] i/print the same region but this time with nice ascii table
    [1970-01-01 00:00:25.144772648][embedlog_main.c:205] i/------  -----------------------------------------------  ----------------
    [1970-01-01 00:00:25.157620305][embedlog_main.c:205] i/offset  hex                                              ascii
    [1970-01-01 00:00:25.167935051][embedlog_main.c:205] i/------  -----------------------------------------------  ----------------
    [1970-01-01 00:00:25.180874259][embedlog_main.c:205] i/0x0000  73 6f 6d 65 20 6d 65 73 73 61 67 65 00 74 68 61  some message.tha
    [1970-01-01 00:00:25.191341590][embedlog_main.c:205] i/0x0010  74 20 63 6f 6e 74 61 69 6e 73 00 6e 75 6c 6c 20  t contains.null
    [1970-01-01 00:00:25.204250281][embedlog_main.c:205] i/0x0020  63 68 61 72 61 63 74 65 72 73 00                 characters.
    [1970-01-01 00:00:25.214595544][embedlog_main.c:205] i/------  -----------------------------------------------  ----------------

10. System tools 一覧

Spresense SDKでは、NuttShell から 各種 System tools を利用することができます。

カテゴリ System tool名 説明

LOG

setlogmask

ログレベルを動的に変更します。

logdump

BackupSRAMに保存されたロギング情報をダンプします。

logsave

BackupSRAMに保存されたロギング情報をSPI-Flashに保存します。

GPIO

gpio

Pin情報を取得/設定します。

gpioint

GPIO割り込みを確認するためのテストコマンドです。

I2C

i2c

I2Cデバイスとの通信を確認するためのユーティリティツールです。

PMIC

pmic

PMIC(PowerManagement IC)を制御するためのユーティリティツールです。

USB

usbmsc

USB MSC機能を使用するためのコマンドです。

cdcacm

USB CDC/ACM機能を使用するためのコマンドです。

Zmodem

zmodem

Zmodem転送を使用するためのコマンドです。

Stack

stackmonitor

Stack使用量をモニタするためのツールです。

Network

lte_daemon

LTEのネットワークデーモンを開始/停止するためのコマンドです。

11. USB MSC 機能を使う

USB MSC (Mass Storage Class) 機能を使うためのユーティリティコマンドについて説明します。
USB MSC 機能を有効にするとホスト PC からSpresense ボード上の SD カードへ直接アクセスすることができます。

11.1. ビルド手順

ここではコマンドラインによるビルド手順を示します。
IDE を使用してビルドする場合、以下に示すコンフィグレーション情報を参考にしてください。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に feature/usbmsc を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    tools/config.py feature/usbmsc
    make
    

    SD カードを USB MSC としてマウントするので SD カード機能も有効化しています。

  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

11.2. 動作確認

拡張ボードに SD カードが挿入されている状態で、拡張ボードの USB 端子とホスト PC とを USB ケーブルで接続します。

  1. シリアルターミナルを起動します。

    シリアルポートに /dev/ttyUSB0 を、baudrate に 115200 bps を指定して、 minicom ターミナルを使用する例を示します。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. USB MSC 機能を開始する場合、NuttShell から msconn コマンドを実行します。

    nsh> msconn
    mcsonn_main: Creating block drivers
    mcsonn_main: Configuring with NLUNS=1
    mcsonn_main: handle=d038d50
    mcsonn_main: Bind LUN=0 to /dev/mmcsd0
    mcsonn_main: Connected

    ホスト PC に新たなリムーバブルディスクが認識され、 ホスト PC から拡張ボードの SD カードの内容にアクセスすることができます。

  3. USB MSC 機能を終了する場合、NuttShell から msdis コマンドを実行します。

    nsh> msdis
    msdis: Disconnected

12. USB CDC/ACM 機能を使う

USB CDC/ACM 機能を使うためのユーティリティコマンドについて説明します。
USB CDC/ACM 機能を有効にすると拡張ボードの USB をシリアルポートとして使用することができます。

12.1. ビルド手順

ここではコマンドラインによるビルド手順を示します。
IDE を使用してビルドする場合、以下に示すコンフィグレーション情報を参考にしてください。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に feature/usbcdcacm を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    tools/config.py feature/usbcdcacm
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

12.2. 動作確認

拡張ボードの USB 端子とホスト PC とを USB ケーブルで接続します。

  1. シリアルターミナルを起動します。

    シリアルポートに /dev/ttyUSB0 を、baudrate に 115200 bps を指定して、 minicom ターミナルを使用する例を示します。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. USB CDC/ACM 機能を開始する場合、NuttShell から sercon コマンドを実行します。

    nsh> sercon
    sercon: Registering CDC/ACM serial driver
    sercon: Successfully registered the CDC/ACM serial driver

    Spresense ボード上に /dev/ttyACM0 が追加され、ホスト PC には新たな COM ポートが見つかります。 そのポートを使って、USB 経由でシリアル通信をすることができるようになります。

  3. USB CDC/ACM 機能を終了する場合、NuttShell から serdis コマンドを実行します。

    nsh> serdis
    serdis: Disconnected

13. Zmodem を使ったファイル転送

この章では、Zmodem 転送を利用して HostPC と Spresense ボードとの間でファイルを送受信する方法について示します。

13.1. ビルド手順

ここではコマンドラインによるビルド手順を示します。
IDE を使用してビルドする場合、以下に示すコンフィグレーション情報を参考にしてください。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に feature/zmodem を指定してコンフィグレーションを実行します。
    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが生成されます。

    tools/config.py feature/zmodem
    make
    
  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

13.2. 動作手順

Zmodem 転送機能に対応したシリアルターミナルを使用してください。

ここでは、minicom を例にとって説明します。
minicom や lrzsz がインストールされていない場合は事前にインストールしてください。

sudo apt install minicom lrzsz

minicom を起動します。

minicom -D /dev/ttyUSB0 -b 115200

NuttShell から Zmodem の rz (受信), sz (送信) コマンドを使用することができます。

rz コマンドの使い方
tutorial zmodem1 rz
sz コマンドの使い方
tutorial zmodem1 sz

13.2.1. HostPC から Spresense ボードへのファイル転送

HostPC から Spresense ボードへファイルを転送する手順を以下に示します。

  1. minicom 上で CTRL-a を押下した後に z キーを押してメニューを開きます。(このショートカットキーの割り当てはユーザー側で変更可能です。詳細は minicom のマニュアルを参照してください。)
    続けて s キーを押して Send files (ファイル送信) を選択します。

    tutorial zmodem2 menu
  2. カーソルキーで zmodem を選択して Enter キーで実行します。

    tutorial zmodem2 upload
  3. カーソルキーとスペースキーでフォルダを移動をして転送したいファイルを選択します。
    カーソルキーでフォルダを選びスペースキーを2回押すとフォルダへ移動できます。
    カーソルキーでファイルを選びスペースキーで選択した後に Enter キーを押すと転送を開始します。

    tutorial zmodem2 dir

    もしくは、Enter キーを押してファイル名を入力して転送を実行することもできます。

    tutorial zmodem2 file
  4. ファイル転送が始まり、Transfer complete と表示されれば転送完了です。

    tutorial zmodem2 complete
  5. Spresense ボード上のファイルの転送先は、CONFIG_SYSTEM_ZMODEM_MOUNTPOINT で変更することができます。
    デフォルトのコンフィギュレーションでは、Flash 上の /mnt/spif 以下にファイルが転送されます。

TeraTerm を使用する場合は、TeraTerm メニューから ファイル → 転送 → ZMODEM → 送信 から選択したファイルを送信することができます。

13.2.2. Spresense ボードから HostPC へのファイル転送

Spresense ボードから HostPC へファイルを転送する手順を以下に示します。

  1. NuttShell 上で、sz コマンドの引数に転送したいファイルを指定して実行します。
    ファイル名は / から始まるフルパス名を入力してください。
    以下の例は、-x 1 バイナリ転送オプションを付けています。

    nsh> sz -x 1 /mnt/spif/test00.dat
  2. ファイル転送が始まり、Transfer complete と表示されれば転送完了です。

    tutorial zmodem3 complete
  3. HostPC 上の minicom を実行したフォルダにファイルが転送されます。

TeraTerm を使用する場合は、NuttShell から sz コマンドを入力した後に、ファイル → 転送 → ZMODEM → 受信 によりファイルを受信することができます。HostPC 側のファイル受信ディレクトリは、ファイル → ディレクトリを変更 によって指定可能です。

14. アプリケーションの自動起動方法

この章では、電源投入時に NuttShell プロンプトではなくユーザーアプリケーションを自動的に起動する方法について記述します。 NuttShellでは、簡単なシェルスクリプトを実行することが出来、かつ、特定のスクリプトを起動時に実行する機能を持っています。 この章では、その機能を用いた、自動起動について解説します。

NuttShell 上で利用できる基本的なコマンドや、if, whileといった制御構文については、 NuttShell (NSH) documentation を参照してください。

14.1. Spresense SDK でのスタートアップスクリプトの使い方

NuttX で自動起動スクリプトを利用するには、コンフィグでその機能を有効にする必要があります。 Spresense SDK では、自動起動を有効にするためのデフォルトとなるコンフィグを提供しています。

この章での例としては、"hello" ビルドインコマンドを自動起動スクリプトを使って、 起動後、3秒おきにhelloを表示させるスクリプトを作成してみます。

14.1.1. コンフィグレーション

まずは、今回の例で使用する "hello" ビルドインコマンドと、自動起動を有効にするデフォルトコンフィグを使って、 SDKのコンフィグを行います。
spresense/sdk ディレクトリに移動して、以下のようにconfig.pyに2つのパラメータを指定してを実行してください。

./tools/config.py examples/hello feature/startup_script

一つ目のパラメータ examples/hello は "hello" ビルドインコマンドを有効にするオプションで、2つ目のパラメータ feature/startup_script は、自動起動の仕組みを有効にするオプションになります。

このように、Spresense SDK の config.py では、オプションに色々と追加していくことでSDKとして用意しているデフォルトコンフィグを追加していく、ということが出来るようになっています。

14.1.2. ビルドとフラッシュ

コンフィグが完了したら、同じ spresense/sdk ディレクトリ下で、以下のコマンドを実行して nuttx.spk を実機に書き込みます。

make
tools/flash.sh -c /dev/ttyUSB0 nuttx.spk
>>> Install files ...
install -b 115200
Install nuttx.spk
|0%-----------------------------50%------------------------------100%|
######################################################################

xxxxx bytes loaded.
Package validation is OK.
Saving package to "nuttx"
updater# sync
updater# Restarting the board ...
reboot

14.1.3. 動作確認(自動起動なし)

nuttx.spk を書き込んだだけでは、自動的に起動することはありません。 ここでは、まずは書き込んだ nuttx.spk が正しく "hello" ビルドインコマンドを含んでいるか、 確認してみます。 まず、適当なターミナルソフト(以下の例は minicom を使用しています)を使って、実機のUARTポートに接続します。この例では、実機のポートは、 /dev/ttyUSB0 としていますが、お使いの環境に合わせて設定してください。

minicom -D /dev/ttyUSB0 -b 115200

実機に接続すると、以下のメッセージが出て、 nsh> プロンプトが表示されます。

No /mnt/spif/init.rc.

NuttShell (NSH) NuttX-8.2
nsh>
ターミナルによっては、接続時にボードにリセットをかけないものもあるようです。上記のメッセージはリセット直後に表示されるものなので、表示されないような場合は、ターミナルは接続したまま、Spresenseボードのリセットを押してみてください。

この状態で "help" と叩くと以下のように Builtin Apps: の中に hello があることが確認できます。

nsh> help
help usage:  help [-v] [<cmd>]

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

Builtin Apps:
  hello  nsh
nsh>

ここで、 hello を実行して、動作を確認します。

nsh> hello
Hello, World!!
nsh>

これで、 hello が動作することは確認できました。 次に、これを3秒おきに実行するスクリプトを作成して、実機で動作させます。

14.1.4. 動作確認(自動起動)

前の節で hello の動作を確認したら、一度ターミナルから抜け、スクリプトファイルを作成します。

スクリプトファイル名は、 init.rc としてください。 以下のようなスクリプトを作成します。

  1. init.rc

    while true
    do
      sleep 3
      hello
    done

シンプルなスクリプトですが、 while true で無限ループを作り、 sleep 3 で3秒待ち、 hello を実行する、というのを延々と繰り返すスクリプトになります。

このスクリプトをSpresenseメインボードのSPIフラッシュに書き込みます。 init.rc が spresense/sdk ディレクトリ内にあるとして、spresense/sdk ディレクトリ内で、以下のようなコマンドを実行してください。

./tools/flash.sh -w init.rc
xmodem
>>> Install files ...
nsh> xmodem /mnt/spif/init.rc
Install init.rc
|0%-----------------------------50%------------------------------100%|
######################################################################

nsh>

flash.sh は、 -w オプションを指摘することで、その後の引数で指定されたファイルを、実機のSPIフラッシュに書き込みを行います。

flash.shを -w で実行すると、nuttx.spk を再度書き込む必要が出てきます。 すでにビルド済みの nuttx.spk が spresense/sdk にあるので、それを再度書き込みます。

tools/flash.sh -c /dev/ttyUSB0 nuttx.spk
>>> Install files ...
install -b 115200
Install nuttx.spk
|0%-----------------------------50%------------------------------100%|
######################################################################

xxxxx bytes loaded.
Package validation is OK.
Saving package to "nuttx"
updater# sync
updater# Restarting the board ...
reboot

この状態で再度ターミナルに接続してみます。

Run /mnt/spif/init.rc.
sh [8:100]

NuttShell (NSH) NuttX-8.2
nsh> Hello, World!!
Hello, World!!
Hello, World!!
Hello, World!!
Hello, World!!

繋ぐと、3秒おきに、意図した通り、 "Hello, World!!" というメッセージが表示されることが確認できます。

14.2. TIPS: Application エントリーポイント

スタートアップスクリプトとは別に CONFIG_USER_ENTRYPOINT を変更するという方法もあります。

デフォルトのコンフィギュレーションでは、CONFIG_USER_ENTRYPOINT=spresense_main となっています。

これを例えば hello_main に変更すると、起動時に hello アプリケーションを起動するように変更できます。

tutorial autostart entrypointv200
エントリーポイントの関数名は、サンプルコードのMakefileで定義している PROGNAME 変数に入っている文字列に、_main を付けたものになります。例:spresense/sdk/apps/examples/hello/Makefileに、PROGNAMEの定義が $(CONFIG_EXAMPLES_HELLO_PROGNAME) となっています。これは、Kconfigのパラメータで名前が確定しており、spresense/sdk/apps/examples/Kconfigを見ると、config EXAMPLES_HELLO_PROGNAME の欄に、default "hello" と記載されています。この場合、PROGNAMEがhelloとなるため、 "hello_main"がエントリー関数名となります。
起動時にアプリケーションの初期化処理が必要です。以下を参考に、#include <sys/boardctl.h> を追加し、ユーザーエントリーポイント関数の中から boardctl(BOARDIOC_INIT, 0); を呼び出してください。
#include <sys/boardctl.h>

int main(int argc, FAR char *argv[])
{
  /* Initialize apllication */
  boardctl(BOARDIOC_INIT, 0);

  printf("Hello, World!!\n");
  return 0;
}

15. ローダブルELFチュートリアル

ローダブルELFとは、OSとアプリケーションを別々のバイナリで作成し、動作時にアプリケーションをロードして実行できる機能です。

アプリケーションをローダブルELFとして作成すると、必要に応じてメモリにロードすることが可能になるため、実行時の総メモリ量を抑えたり、アプリケーションを単独で更新することができるようになります。ただし、アプリケーションの起動時間が伸びたり、ロード/アンロードを繰り返す事によるメモリの断片化が発生する可能性もあるため注意が必要です。

ASMP ELFとの互換性はありません。起動するアプリケーションはメインコアでのみ実行されます。

このチュートリアルでは、アプリケーションのELFファイルの格納場所にSDカードを使用します。

15.1. ビルド手順

ここではコマンドラインによるビルド手順を示します。
IDE を使用してビルドする場合、以下に示すコンフィグレーション情報を参考にしてください。

  1. sdk ディレクトリへ移動します。

    build-env.sh スクリプトを読み込むことで、config.py ツールの Tab 補完機能が有効になります。

    cd spresense/sdk
    source tools/build-env.sh
    
  2. SDK のコンフィグレーションとビルドを行います。

    引数に feature/loadable device/sdcard を指定してコンフィグレーションを実行します。

    tools/config.py feature/loadable device/sdcard
    tools/config.py -m
    

    メニューコンフィグを開き、Hello, World! example を有効にします。この時、Hello, World! exampleM となるように設定するとそのアプリケーションがローダブルELFとしてビルドされます。

    [Application Configuration]
      [Examples]
        ["Hello, World!" example] => M

    コンフィグレーションが完了したらビルドします。

    make
    

    ビルドに成功すると sdk フォルダ直下に nuttx.spk ファイルが、sdk/apps/bin 以下に ELFファイル hello がそれぞれ生成されます。hello は別途SDカードにコピーしてください。

  3. nuttx.spk を Spresense ボードへ書き込みます。

    この例では シリアルポートとして /dev/ttyUSB0 を、書き込み速度の baudrate に 500000 bps を設定しています。お使いの環境に合わせて変更してください。

    tools/flash.sh -c /dev/ttyUSB0 -b 500000 nuttx.spk
    

15.2. 動作確認

シリアルターミナルを開いて、hello アプリケーションを実行します。

  1. シリアルターミナルを起動します。

    シリアルポートに /dev/ttyUSB0 を、baudrate に 115200 bps を指定して、 minicom ターミナルを使用する例を示します。

    minicom -D /dev/ttyUSB0 -b 115200
    
  2. NuttShell から hello アプリケーションを実行します。

    SDカードにある hello ELFファイルまでのフルパスを指定します。

    nsh> /mnt/sd0/hello
    Hello, World!!

15.3. PATH変数を使用する

NuttShellでは、bashの環境変数と同様 PATH 変数を用いてELFファイルを検索するパスの設定ができます。 feature/loadable にはこれを使用するための設定が含まれていますが、実際に使用するパスはユーザー自身で設定する必要があります。 メニューコンフィグを開いて PATH 変数にSDカードのパスを設定します。この設定を行うことでSDカードの直下に置かれているアプリケーションはフルパスを指定しなくても実行することができるようになります。

[Binary Loader]
  [Initial PATH Value] => "/mnt/sd0"

ビルドして nuttx.spk を書き込んでください。起動後、NuttShellから hello とタイプするだけでSDカード上の hello アプリケーションを起動することができるようになります。

nsh> hello
Hello, World!!