SPRESENSE でスレッドを走らせてみた! [SPRESENSE]
Spresense SDK の Example を見ていると、いくつかのサンプルでスレッドを使っています。NuttX にはスレッドを生成する関数があるようです。
http://nuttx.org/Documentation/NuttxUserGuide.html#taskcreate
これを使って SPRESENSE の四つのLEDをそれぞれのスレッドでコントロールするスケッチを書いてみました。
スケッチの中でも記述していますが、スレッド内で delay() を使うことはできないようです。どうも delay関数は、busy-wait のようなのでタスクを握って離しません。Spresense SDK のサンプルでも usleep を使っていますので、usleep を使うようにしましょう。
また、プライオリティは高いほど優先度が高いようです。肝心の loop 関数の優先度がよくわからないのが困りものですが、いろいろ試してみたら 120 位のようです。
動作の様子は地味なので動画にしてませんSPRESENSEを持っている方は試してみてくださいねー。
(^^)/~
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を持っている方は試してみてくださいねー。
(^^)/~
コメント 0