SSブログ

SPRESENSE でスレッドを走らせてみた! [SPRESENSE]

Spresense SDK の Example を見ていると、いくつかのサンプルでスレッドを使っています。NuttX にはスレッドを生成する関数があるようです。


nuutx.png
http://nuttx.org/Documentation/NuttxUserGuide.html#taskcreate
#include <sched.h>
int task_create(char *name, int priority, int stack_size, main_t entry, char * const argv[])
Input Parameters
name:The name of the new task
priority:The priority of the new task
stack_size:The size (in bytes) of the stack needed
entry:The entry point of a new task
argv:A pointer to an array of input parameters. The array should be terminated with a NULL argv[] value. If no parameters are required, argv may be NULL.
Returned Value
Returns the non-zero task ID of the new task or ERROR if memory is insufficient or the task cannot be created (errno is not set).


これを使って SPRESENSE の四つのLEDをそれぞれのスレッドでコントロールするスケッチを書いてみました。


#include <sched.h> /*** for task_create **/
#include <stdlib.h>  /*** for atoi ***/

#define MAXLOOP 60
static int gMainLoop = 0;

// Thread
static int led_thread(int argc, char* argv[]) {
  if (argc != 4) {
    Serial.println("Invalid argument number at led0_thread: " + String(argc));
    return;
  }
  
  String func = String(argv[0]);
  int led       = atoi(argv[1]);
  int durationH = atoi(argv[2]);
  int durationL = atoi(argv[3]);

  Serial.println("========================================");
  Serial.println("Task name : " + func);
  Serial.println("LED" + String(led) + " blink interval");
  Serial.println("High duration: " + String(durationH) + " msec");
  Serial.println("Low  duration: " + String(durationL) + " msec");
  Serial.println("========================================\n");

  if (led > 3 || led < 0) {
    Serial.println("Error: number of LED is " + String(led));
    return -1;
  }
  
  int pin_num = 0;
  
  switch(led) {
  case 0: pin_num = LED0; break;
  case 1: pin_num = LED1; break;
  case 2: pin_num = LED2; break;
  case 3: pin_num = LED3;
  }
  
  while (gMainLoop < MAXLOOP) {
    digitalWrite(pin_num, HIGH);
    usleep(durationH * 1000); // msec to usec
    digitalWrite(pin_num, LOW);
    usleep(durationL * 1000); // msec to usec
    /* You cannot use "delay(msec)" because it is  * 
     *  a busywait that will not yield the process */
  }

  Serial.println("Exit " + func);
  return 0;
}


void setup() {
  char* param[4];
  String str[3];
  int i;

  Serial.begin(115200);

  pinMode(LED0, OUTPUT);
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  
  str[0] = String("0");   /* LED number */
  str[1] = String("100"); /* LED HIGH duration in msec */
  str[2] = String("200"); /* LED LOW duration in msec */
  for (i = 0; i < 3; ++i) {
    param[i] = str[i].c_str();
  }
  param[3] = NULL; // the last array must NULL terminatz
  task_create("led0 thread", 130, 1024, led_thread, param);

  str[0] = String("1");   /* LED number */
  str[1] = String("200"); /* LED HIGH duration in msec */
  str[2] = String("200"); /* LED LOW duration in msec */
  for (i = 0; i < 3; ++i) {
    param[i] = str[i].c_str();
  }
  param[3] = NULL; // the last array must NULL terminate
  task_create("led1 thread", 130, 1024, led_thread, param); 

  str[0] = String("2");   /* LED number */
  str[1] = String("500"); /* LED HIGH duration in msec */
  str[2] = String("100"); /* LED LOW duration in msec */
  for (i = 0; i < 3; ++i) {
    param[i] = str[i].c_str();
  }
  param[3] = NULL; // the last array must NULL terminate
  task_create("led2 thread", 130, 1024, led_thread, param);

  str[0] = String("3");   /* LED number */
  str[1] = String("100"); /* LED HIGH duration in msec */
  str[2] = String("500"); /* LED LOW duration in msec */
  for (i = 0; i < 3; ++i) {
    param[i] = str[i].c_str();
  }
  param[3] = NULL; // the last array must NULL terminate
  task_create("led3 thread", 130, 1024, led_thread, param);

}

void loop() {
  ++gMainLoop;
  Serial.println("MainLoop: " + String(gMainLoop));
  sleep(1);

  if (gMainLoop >= MAXLOOP) {
    sleep(1); // wait for the end of all processes
    Serial.println("End of all processes");
    while (1);
  }
}


スケッチの中でも記述していますが、スレッド内で delay() を使うことはできないようです。どうも delay関数は、busy-wait のようなのでタスクを握って離しません。Spresense SDK のサンプルでも usleep を使っていますので、usleep を使うようにしましょう。

また、プライオリティは高いほど優先度が高いようです。肝心の loop 関数の優先度がよくわからないのが困りものですが、いろいろ試してみたら 120 位のようです。

動作の様子は地味なので動画にしてませんSPRESENSEを持っている方は試してみてくださいねー。
(^^)/~



DSC_0001_BURST20191019170915259.JPG








nice!(29)  コメント(0) 
共通テーマ:趣味・カルチャー

nice! 29

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。