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を持っている方は試してみてくださいねー。
(^^)/~