8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SPRESENSEでthreadを使ってみる

Last updated at Posted at 2018-12-09

###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個搭載されています。

test_app_main.c

#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と入力すると使い方を調べられます。
image.png

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!

次回はセマフォについてまとめます。

8
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?