###SPRESENSE購入しました!
ARMのコアを6つも搭載しているということで、折角ならコア数を活かしたいと思い、SPRESENSE SDKを使って開発しています。
今回はマルチスレッドを試してみました。
この記事を見るだけで、プロジェクト作成、ソースコード作成、書き込み、実行までの一連の流れを追えるようになっています。
この記事では、
- pthreadの使い方
- Spresenseに搭載している4つのLEDの点滅
を説明しています。
前提
- SPRESENSE SDK
tag v1.1.1
-
Spresense SDKの使い方 の
1.5. シリアルターミナル上での動作確認
まで動作確認しています。
プロジェクト作成
フォルダ作成
sdkフォルダ内で下記コマンドを実行します。
$ tools/mkappsdir.py test
spresense
フォルダにtest
というフォルダが作成されます。
次に、アプリを追加します。sdkフォルダで以下を実行します。
$ tools/mkcmd.py -d test test_app "My test application"
testフォルダ以下にtest_appフォルダが作られます。
その中のtest_app_main.c
を修正していきますが、まずはこのままspresenseに書き込んでみます。
Build
$ make clean
$ tools/config.py -k release
$ tools/config.py -m
test
を選択し、 [] My test application.
でY
を押し、登録する。
$ make buildkernel
$ make
登録したtest_app
がビルドされます。
(略)
$ make[1]: Entering directory '(SPRESENSE_PATH)/spresense/test'
$ make[2]: Entering directory '(SPRESENSE_PATH)/spresense/test/test_app'
$ Register: test_app
$ make[2]: Leaving directory '(SPRESENSE_PATH)/spresense/test/test_app'
$ make[1]: Leaving directory '(SPRESENSE_PATH)/spresense/test'
(略)
※(SPRESENSE_PATH)はSpresenseSDKをcloneしたフォルダ
書き込み
$ tools/flash.sh nuttx.spk
プロジェクト作成から書き込みまでの一連の流れを実行しました。
次は肝心のプログラムです。
スレッドを使ってみる
今回作るプログラムは、
- スレッドA: 1秒ごとにLED0を点滅
- スレッドB: 2秒ごとにLED1を点滅
を実装します。なお、SPRESENSEにはLEDが4個搭載されています。
#include <sdk/config.h>
#include <stdio.h>
#include <arch/board/board.h>
#include <arch/chip/pin.h>
#define PIN_LED0 PIN_I2S1_BCK
#define PIN_LED1 PIN_I2S1_LRCK
#define PIN_LED2 PIN_I2S1_DATA_IN
#define PIN_LED3 PIN_I2S1_DATA_OUT
const int led_pin[4] = {
PIN_LED0,
PIN_LED1,
PIN_LED2,
PIN_LED3
};
void toggle_led(uint32_t pin){
board_gpio_write(pin, board_gpio_read(pin) == 0 ? 1 : 0);
}
void* task_A(void *arg)
{
for(int i = 0; i < 10; i++)
{
toggle_led(led_pin[0]);
sleep(1);
}
return NULL;
}
void* task_B(void *arg)
{
for(int i = 0; i < 10; i++)
{
toggle_led(led_pin[1]);
sleep(2);
}
return NULL;
}
#ifdef CONFIG_BUILD_KERNEL
int main(int argc, FAR char *argv[])
#else
int test_app_main(int argc, char *argv[])
#endif
{
printf("thread test.\n");
for(int i = 0; i < 4; i++){
board_gpio_config(led_pin[i], 0, true, true, PIN_FLOAT); // GPIOの設定
}
pthread_t thread_A, thread_B;
pthread_create(&thread_A, NULL, task_A, NULL);
pthread_create(&thread_B, NULL, task_B, NULL);
pthread_join(thread_A, NULL);
pthread_join(thread_B, NULL);
return 0;
}
nuttxではPOSIX環境で使われた関数がそのまま使えるため、POSIX thread
などで調べるとたくさん使用例が出てきます!
board_gpio_write
などのGPIOに関する関数は、
Spresense SDK Library Documentation
の右上の検索にgpio
と入力すると使い方を調べられます。
LEDのピン名は、
Spresense SDK 開発ガイド 11.2.3. Pin specification
のリストに定義の記述があります。
あるいは、上記ページにも書かれていますが、(SPRESENSE_PATH)/spresense/sdk/bsp/include/arch/chip/pin.h
に定義されています。
Pin Name: sdk/bsp/include/arch/chip/pin.h に、PIN_XXX という形式で定義されています
実行
sdk
フォルダで
$ make
$ tools/flash.sh nuttx.spk
$ minicom
$ minicom -s
で、minicomのポート名を/dev/ttyUSB0
(Spresenseが接続されているポート名)、ボーレートを115200にしておくと、minicom
と入力するだけで接続できます。
NuttShellが起動したら、
test_app
と入力すると、プログラムが再生されます。
- LED0:1 → 0 → 1 → 0 → 1 → 0 →・・・
- LED1:1 → 1 → 0 → 0 → 1 → 1 →・・・
のように1秒ずつ点滅すればOK!
次回はセマフォについてまとめます。