【Wio Terminal】Wi-Fi use on the FreeRTOS sub-thread
Wi -Fi とFreeRTOS の両立について進展があった
夫れ
しかしこの時点では、loop()
に隔離していました。
例
このプログラムは先の記事を投稿した日(2024/7/27)に作成・編集されていたものです。SSIDのみ隠しているものの、コメント含め当時のまま載せています。
/*
実際の審らかなる状態こそ知らね
setup()に於ける使用は赦され
他のThreadに於ける使用は赦されざる結果を得しより
WiFiはsetup()とloop()に幽閉すれば次の如く結果を得
******************************
Program start
******************************
Thread A Started
Thread A Hi
Thread B Started
Thread B Hello?
Wifi set mode
Wifi done settings
scan start
Thread A Hi
Thread A Hi
Thread B Hello?
Thread A Hi
Thread A Hi
Thread B Hello?
scan done
33 networks found
1: ⋯スキャンされたSSID名⋯ (-34)*
2: ⋯スキャンされたSSID名⋯ (-62)*
3: ⋯スキャンされたSSID名⋯ (-67)*
4: ⋯スキャンされたSSID名⋯ (-68)*
5: ⋯スキャンされたSSID名⋯ (-68)*
6: ⋯スキャンされたSSID名⋯ (-72)*
7: ⋯スキャンされたSSID名⋯ (-81)*
8: ⋯スキャンされたSSID名⋯ (-81)*
9: ⋯スキャンされたSSID名⋯ (-81)*
10: ⋯スキャンされたSSID名⋯ (-84)*
11: ⋯スキャンされたSSID名⋯ (-84)*
12: ⋯スキャンされたSSID名⋯ (-84)*
13: ⋯スキャンされたSSID名⋯ (-85)*
14: ⋯スキャンされたSSID名⋯ (-86)*
15: ⋯スキャンされたSSID名⋯ (-87)*
16: ⋯スキャンされたSSID名⋯ (-87)*
17: ⋯スキャンされたSSID名⋯ (-87)*
18: ⋯スキャンされたSSID名⋯ (-87)*
19: ⋯スキャンされたSSID名⋯ (-87)*
20: ⋯スキャンされたSSID名⋯ (-87)*
21: ⋯スキャンされたSSID名⋯ (-87)*
22: (-88)*
23: ⋯スキャンされたSSID名⋯ (-89)*
24: ⋯スキャンされたSSID名⋯ (-89)*
25: ⋯スキャンされたSSID名⋯ (-90)*
26: (-90)*
27: ⋯スキャンされたSSID名⋯ (-91)*
28: ⋯スキャンされたSSID名⋯ (-91)*
29: ⋯スキャンされたSSID名⋯ (-92)*
30: ⋯スキャンされたSSID名⋯ (-92)*
31: ⋯スキャンされたSSID名⋯ (-93)*
32: ⋯スキャンされたSSID名⋯ (-96)*
33: ⋯スキャンされたSSID名⋯ (-99)*
Thread A Hi
Thread A Hi
Thread B Hello?
Thread A Hi
*/
#include "rpcWiFi.h"
#define STACK_SIZE 256
using namespace erpc;
static void ThreadA(void* pvParameters) {
(void) pvParameters;
Serial.println("Thread A\tStarted");
while (1) {
Serial.println("Thread A\tHi");
delay(1000);
}
}
static void ThreadB(void* pvParameters) {
(void) pvParameters;
Serial.println("Thread B\tStarted");
while (1) {
for (int i = 0; i < 10; i++) {
Serial.println("Thread B\tHello?");
delay(2000);
}
}
}
void setup() {
Serial.begin(115200);
/* 起動時にUSBドライバーが故障しないようにする */
vNopDelayMS(1000);
while(!Serial);
Serial.println("\n******************************");
Serial.println(" Program start ");
Serial.println("******************************\n");
Thread TaskA(
&ThreadA,
configMAX_PRIORITIES - 10,
STACK_SIZE,
"Task A"
);
Thread TaskB(
&ThreadB,
configMAX_PRIORITIES - 11,
STACK_SIZE,
"Task B"
);
Thread* tasksArray[2] = {&TaskA, &TaskB};
for (Thread* t : tasksArray) {
t -> start();
}
Serial.println("Wifi\tset mode");
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
Serial.println("Wifi\tdone settings");
}
void loop() {
//Serial.println("loop");
Serial.println("scan start");
int n = WiFi.scanNetworks();
Serial.println("scan done");
if (n == 0) {
Serial.println("no networks found");
} else {
Serial.print(n);
Serial.println(" networks found");
for (int i = 0; i < n; ++i) {
Serial.print(i + 1);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(")");
Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");
delay(10);
}
}
Serial.println("");
delay(5000);
}
ThreadA
とThreadB
とが
static void ThreadA(void* pvParameters) {
(void) pvParameters;
Serial.println("Thread A\tStarted");
while (1) {
Serial.println("Thread A\tHi");
delay(1000);
}
}
static void ThreadB(void* pvParameters) {
(void) pvParameters;
Serial.println("Thread B\tStarted");
while (1) {
for (int i = 0; i < 10; i++) {
Serial.println("Thread B\tHello?");
delay(2000);
}
}
}
初期設定を除き、全てloop()
にあります。
void loop() {
//Serial.println("loop");
Serial.println("scan start");
int n = WiFi.scanNetworks();
Serial.println("scan done");
if (n == 0) {
Serial.println("no networks found");
} else {
Serial.print(n);
Serial.println(" networks found");
for (int i = 0; i < n; ++i) {
Serial.print(i + 1);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(")");
Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");
delay(10);
}
}
Serial.println("");
delay(5000);
}
/*
︙
他のThreadに於ける使用は赦されざる結果を得しより
WiFiはsetup()とloop()に幽閉すれば次の如く結果を得
︙
*/
その結果の記録は残っておらず仔細は未詳ですが、「
loop()
を使うのでは、折角のマルチスレッドが台無しになるような感がありました。とはいえ、動くか否か定かでない(しかも当時は動かないと判断していた)方法は、動くことが確かめられた方法に及びません。そうしてこのような不格好な方法を取ってきました。
main -thread を別の事に使いたくなった
扨、いつか困るだろうと危惧していたことが起こりました。
しかし
-
-thread でないsafe - バージョン
7.0.2
は について公式情報が無いFreeRTOS
※Wio 用のライブラリーTerminal Seeed_Arduino_LvGL
におけるバージョンは7.0.2
一応
実はこの裏で、一度
|
|
---|---|
|
本題
一つ主観から意外であった結果を挙げると、排他制御を要することすらなかったという点でありましょう。何らかの制約が下でしか使えない可能性も覚悟していましたが、寧ろ望ましいことです。
スキャンする
最も簡単なのは、接続も通信もせず、周辺のアクセスポイント(
プログラム
プログラム
#include "rpcWiFi.h"
constexpr uint16_t STACK_SIZE = 4096;
void setup() {
Serial.begin(115200);
vNopDelayMS(1000); // 故障対策
while(!Serial); // シリアルモニターが開かれるまで待機する
vSetErrorSerial(&Serial); // エラー出力を有効にする
WiFi.mode(WIFI_STA); // station mode
WiFi.disconnect(); // 切断状態にする
delay(100);
erpc::Thread taskA(
&ThreadA,
configMAX_PRIORITIES - 10,
STACK_SIZE,
"Task A"
);
erpc::Thread taskB(
&ThreadB,
configMAX_PRIORITIES - 11,
STACK_SIZE,
"Task B"
);
erpc::Thread* tasks[] = {&taskA, &taskB};
for (erpc::Thread* pTask : tasks) {
pTask -> start();
}
}
void loop() {}
static void ThreadA(void* pvParameters) {
(void) pvParameters;
Serial.println("ThreadA\tbegin");
int iValue = 1;
while (1) {
Serial.printf("ThreadA\tvalue: %d\n", iValue);
if (iValue % 5 == 0) {
uint16_t n = WiFi.scanNetworks();
if (n == 0) {
Serial.println("ThreadA\tno networks found");
} else {
Serial.printf("ThreadA\t%d networks found\n", n);
}
}
vTaskDelay(1000);
iValue++;
}
}
static void ThreadB(void* pvParameters) {
(void) pvParameters;
Serial.println("ThreadB\tbegin");
while (1) {
Serial.println("ThreadB\tdelay 1sec");
vTaskDelay(1000);
}
}
実行結果
実行結果
ThreadA begin
ThreadA value: 1
ThreadB begin
ThreadB delay 1sec
ThreadA value: 2
ThreadB delay 1sec
ThreadA value: 3
ThreadB delay 1sec
ThreadA value: 4
ThreadB delay 1sec
ThreadA value: 5
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadA 31 networks found
ThreadB delay 1sec
ThreadA value: 6
ThreadB delay 1sec
ThreadA value: 7
ThreadB delay 1sec
ThreadA value: 8
ThreadB delay 1sec
ThreadA value: 9
ThreadB delay 1sec
ThreadA value: 10
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadA 32 networks found
ThreadB delay 1sec
ThreadA value: 11
接続する
次はアクセスポイント、つまるところ自宅の
プログラム
当然乍らアクセスポイントの名前(
プログラム
#ifndef __SSID_AND_PASSWORD__
#define __SSID_AND_PASSWORD__
/* WPA3-Personalのものには繋がらない */
#define WIFI_SSID "~~SSID~~"
#define WIFI_PASSWORD "~~password~~"
#endif
#include "rpcWiFi.h"
#include "SsidAndPassword.h"
constexpr uint16_t STACK_SIZE = 4096;
void setup() {
Serial.begin(115200);
vNopDelayMS(1000); // 故障対策
while(!Serial); // シリアルモニターが開かれるまで待機する
vSetErrorSerial(&Serial); // エラー出力を有効にする
WiFi.mode(WIFI_STA); // station mode
WiFi.disconnect(); // 切断状態にする
delay(100);
erpc::Thread taskA(
&ThreadA,
configMAX_PRIORITIES - 10,
STACK_SIZE,
"Task A"
);
erpc::Thread taskB(
&ThreadB,
configMAX_PRIORITIES - 11,
STACK_SIZE,
"Task B"
);
erpc::Thread* tasks[] = {&taskA, &taskB};
for (erpc::Thread* pTask : tasks) {
pTask -> start();
}
}
void loop() {}
static void ThreadA(void* pvParameters) {
(void) pvParameters;
Serial.println("ThreadA\tbegin");
int iValue = 1;
while (1) {
Serial.printf("ThreadA\tvalue: %d\n", iValue);
if (iValue % 5 == 0) {
Serial.println("ThreadA\tbegin Wi-Fi");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
vTaskDelay(500);
Serial.println("ThreadA\tConnecting..");
}
Serial.println("ThreadA\tConnected");
IPAddress ipAddress = WiFi.localIP();
Serial.println(ipAddress);
WiFi.disconnect();
Serial.println("ThreadA\tDisconnected");
vTaskDelay(100);
}
vTaskDelay(1000);
iValue++;
}
}
static void ThreadB(void* pvParameters) {
(void) pvParameters;
Serial.println("ThreadB\tbegin");
while (1) {
Serial.println("ThreadB\tdelay 1sec");
vTaskDelay(1000);
}
}
実行結果
実行結果
ThreadA begin
ThreadA value: 1
ThreadB begin
ThreadB delay 1sec
ThreadA value: 2
ThreadB delay 1sec
ThreadA value: 3
ThreadB delay 1sec
ThreadA value: 4
ThreadB delay 1sec
ThreadA value: 5
ThreadA begin Wi-Fi
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadA Connected
192.168.128.145
ThreadA Disconnected
ThreadB delay 1sec
ThreadA value: 6
ThreadB delay 1sec
ThreadA value: 7
ThreadB delay 1sec
ThreadA value: 8
ThreadB delay 1sec
ThreadA value: 9
ThreadB delay 1sec
ThreadA value: 10
ThreadA begin Wi-Fi
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadA Connected
192.168.128.145
ThreadA Disconnected
ThreadB delay 1sec
ThreadA value: 11
ThreadB delay 1sec
ThreadA value: 12
ThreadB delay 1sec
ThreadA value: 13
ThreadB delay 1sec
ThreadA value: 14
ThreadB delay 1sec
ThreadA value: 15
ThreadA begin Wi-Fi
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadA Connected
192.168.128.145
ThreadA Disconnected
ThreadB delay 1sec
ThreadB delay 1sec
ThreadA value: 16
ThreadB delay 1sec
ThreadA value: 17
ThreadB delay 1sec
ThreadA value: 18
ThreadB delay 1sec
ThreadA value: 19
ThreadB delay 1sec
ThreadA value: 20
ThreadA begin Wi-Fi
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadA Connected
192.168.128.145
ThreadA Disconnected
ThreadB delay 1sec
ThreadA value: 21
ThreadB delay 1sec
ThreadA value: 22
ThreadB delay 1sec
ThreadA value: 23
ThreadB delay 1sec
ThreadA value: 24
ThreadB delay 1sec
ThreadA value: 25
ThreadA begin Wi-Fi
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadA Connected
192.168.128.145
ThreadA Disconnected
ThreadB delay 1sec
ThreadB delay 1sec
ThreadA value: 26
ThreadB delay 1sec
ThreadA value: 27
通信する
最後に、
プログラム
プログラム
#ifndef __SSID_AND_PASSWORD__
#define __SSID_AND_PASSWORD__
/* WPA3-Personalのものには繋がらない */
#define WIFI_SSID "~~SSID~~"
#define WIFI_PASSWORD "~~password~~"
#endif
#include "rpcWiFi.h"
#include "SsidAndPassword.h"
constexpr uint16_t STACK_SIZE = 4096;
// Wio Terminalが送信時に使うポート番号
constexpr uint16_t LOCAL_UDP_PORT = 2390;
// NTPサーバーの情報
const char* const NTP_SERVER = "time.nist.gov";
constexpr uint16_t NTP_PORT = 123;
// NTPパケットのうち日時を知るためには先頭48バイトあればよい
constexpr uint16_t NTP_PACKET_SIZE = 48;
void setup() {
Serial.begin(115200);
vNopDelayMS(1000); // 故障対策
while(!Serial); // シリアルモニターが開かれるまで待機する
vSetErrorSerial(&Serial); // エラー出力を有効にする
WiFi.mode(WIFI_STA); // station mode
WiFi.disconnect(); // 切断状態にする
delay(100);
erpc::Thread taskA(
&ThreadA,
configMAX_PRIORITIES - 10,
STACK_SIZE,
"Task A"
);
erpc::Thread taskB(
&ThreadB,
configMAX_PRIORITIES - 11,
STACK_SIZE,
"Task B"
);
erpc::Thread* tasks[] = {&taskA, &taskB};
for (erpc::Thread* pTask : tasks) {
pTask -> start();
}
}
void loop() {}
static void ThreadA(void* pvParameters) {
(void) pvParameters;
Serial.println("ThreadA\tbegin");
int iValue = 1;
byte packetBuffer[NTP_PACKET_SIZE];
WiFiUDP wifiUdp;
uint64_t ntpTime;
while (1) {
Serial.printf("ThreadA\tvalue: %d\n", iValue);
if (iValue % 5 == 0) {
Serial.println("ThreadA\tbegin Wi-Fi");
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
vTaskDelay(500);
Serial.println("ThreadA\tConnecting..");
}
Serial.println("ThreadA\tConnected");
IPAddress ipAddress = WiFi.localIP();
Serial.println(ipAddress);
if (WiFi.status() == WL_CONNECTED) {
Serial.println("ThreadA\tbegin UDP");
wifiUdp.begin(ipAddress, LOCAL_UDP_PORT);
Serial.println("ThreadA\tcreate data (UDP packet)");
for (int i = 0; i < NTP_PACKET_SIZE; ++i) {
packetBuffer[i] = 0;
}
packetBuffer[0] = 0b11100011; // Leap Indicator, Version Number, Mode
packetBuffer[1] = 0; // Stratum
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
packetBuffer[12] = 49; // Reference ID
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
Serial.println("ThreadA\tsend data");
wifiUdp.beginPacket(NTP_SERVER, NTP_PORT);
wifiUdp.write(packetBuffer, NTP_PACKET_SIZE);
wifiUdp.endPacket();
vTaskDelay(1000);
if (wifiUdp.parsePacket()) {
Serial.println("ThreadA\treceived data");
wifiUdp.read(packetBuffer, NTP_PACKET_SIZE);
uint64_t highWord = word(packetBuffer[40], packetBuffer[41]);
uint64_t lowWord = word(packetBuffer[42], packetBuffer[43]);
uint64_t rowNtpData = highWord << 16 | lowWord;
Serial.printf("ThreadA\trow data: %lu\n", rowNtpData);
}
Serial.println("ThreadA\tstop UDP");
wifiUdp.stop();
}
WiFi.disconnect();
Serial.println("ThreadA\tDisconnected");
vTaskDelay(100);
}
vTaskDelay(1000);
iValue++;
}
}
static void ThreadB(void* pvParameters) {
(void) pvParameters;
Serial.println("ThreadB\tbegin");
while (1) {
Serial.println("ThreadB\tdelay 1sec");
vTaskDelay(1000);
}
}
実行結果
実行結果
ThreadA begin
ThreadA value: 1
ThreadB begin
ThreadB delay 1sec
ThreadA value: 2
ThreadB delay 1sec
ThreadA value: 3
ThreadB delay 1sec
ThreadA value: 4
ThreadB delay 1sec
ThreadA value: 5
ThreadA begin Wi-Fi
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadA Connected
192.168.128.145
ThreadA begin UDP
ThreadA create data (UDP packet)
ThreadA send data
ThreadB delay 1sec
ThreadA received data
ThreadA row data: 3954038511
ThreadA stop UDP
ThreadA Disconnected
ThreadB delay 1sec
ThreadB delay 1sec
ThreadA value: 6
ThreadB delay 1sec
ThreadA value: 7
ThreadB delay 1sec
ThreadA value: 8
ThreadB delay 1sec
ThreadA value: 9
ThreadB delay 1sec
ThreadA value: 10
ThreadA begin Wi-Fi
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadB delay 1sec
ThreadA Connected
192.168.128.145
ThreadA begin UDP
ThreadA create data (UDP packet)
ThreadA send data
ThreadB delay 1sec
ThreadA received data
ThreadA row data: 3954038523
ThreadA stop UDP
ThreadA Disconnected
ThreadB delay 1sec
ThreadA value: 11
ThreadB delay 1sec
ThreadA value: 12
ThreadB delay 1sec
ThreadA value: 13
ThreadB delay 1sec
ThreadA value: 14
一応、これらの値が正しいものなのか計算してみましょう。
最後に得られた値である3954038523
を用います。唯の計算なので
>>> data = 3954038523
>>> epoch = data - 2208988800
>>> epoch
1745049723
>>> jst = epoch + 32400
>>> jst
1745082123
2208988800
を引くことで
日本標準時にするには、更に32400
を足します。
こちらの計算サイトで確認してみましょう。
時差を考慮してくれる場合はepoch
の方(1745049723
)を使う
しっかりした情報が出てきました。
ついでに
epoch
の方を使えば済みます。jst
の方を使うと未来の日時になってしまいました。
>>> from datetime import datetime
>>> jst
1745082123
>>> epoch
1745049723
>>> dt = datetime.fromtimestamp(jst)
>>> dt.strftime('%Y年%m月%d日 %H時%M分%S秒')
'2025年04月20日 02時02分03秒'
>>> dt2 = datetime.fromtimestamp(epoch)
>>> dt2.strftime('%Y年%m月%d日 %H時%M分%S秒')
'2025年04月19日 17時02分03秒'
対して
時差を考慮してくれない場合はjst
の方(1745082123
)を使う
このために、わざわざ自分で時差を調整した値を算出する必要があったのです。
更なる検証
動かなかったプログラム
#include "rpcWiFi.h"
#define STACK_SIZE 256
using namespace erpc; // for dump_tasks()
TaskHandle_t taskHandlerA,
taskHandlerB;
static void ThreadA(void* pvParameters) {
(void) pvParameters;
Serial.println("Thread A\tStarted");
while (1) {
Serial.println("Thread A\tHi");
delay(1000);
}
}
static void ThreadB(void* pvParameters) {
(void) pvParameters;
Serial.println("Thread B\tStarted");
for (int i = 0; i < 10; i++) {
Serial.println("Thread B\tHello");
dump_tasks(); // fault
delay(2000);
}
Serial.println("Thread B\tBye");
vTaskDelete(NULL);
}
void setup() {
Serial.begin(115200);
vNopDelayMS(1000);
while(!Serial);
Serial.println("\n******************************");
Serial.println(" Program start ");
Serial.println("******************************\n");
Thread TaskA(
&ThreadA,
configMAX_PRIORITIES - 10,
STACK_SIZE,
"Task A"
);
Thread TaskB(
&ThreadB,
configMAX_PRIORITIES - 11,
STACK_SIZE,
"Task B"
);
Thread* tasksArray[2] = {&TaskA, &TaskB};
for (Thread* t : tasksArray) {
t -> start();
}
}
void loop() {}
過去に動かないことを確認していたプログラムが、此度動きました。
こちらのスクラップから引用しています。dump_tasks()
を実行したところで停止していました。
先ずは動いたものを示します。
動くもの
#include "rpcWiFi.h"
constexpr uint16_t STACK_SIZE = 4096;
void setup() {
Serial.begin(115200);
vNopDelayMS(1000); // 故障対策
while(!Serial); // シリアルモニターが開かれるまで待機する
vSetErrorSerial(&Serial); // エラー出力を有効にする
erpc::Thread taskA(
&ThreadA,
configMAX_PRIORITIES - 10,
STACK_SIZE,
"Task A"
);
erpc::Thread taskB(
&ThreadB,
configMAX_PRIORITIES - 11,
STACK_SIZE,
"Task B"
);
erpc::Thread* tasks[] = {&taskA, &taskB};
for (erpc::Thread* pTask : tasks) {
pTask -> start();
}
}
void loop() {}
static void ThreadA(void* pvParameters) {
(void) pvParameters;
Serial.println("Thread A\tStarted");
while (1) {
Serial.println("Thread A\tHi");
delay(1000);
}
}
static void ThreadB(void* pvParameters) {
(void) pvParameters;
Serial.println("Thread B\tStarted");
for (int i = 0; i < 10; i++) {
Serial.println("Thread B\tHello");
dump_tasks(); // fault
delay(2000);
}
Serial.println("Thread B\tBye");
vTaskDelete(NULL);
}
Thread A Started
Thread A Hi
Thread B Started
Thread B Hello
Task B X 8 972 6
runClient R 7 5062 2
IDLE R 0 129 3
runServer B 8 1965 1
Task A B 8 990 5
Tmr Svc B 2 45 4
Thread A Hi
Thread A Hi
Thread B Hello
Task B X 8 794 6
runClient R 7 5062 2
IDLE R 0 129 3
runServer B 8 1965 1
Task A B 8 990 5
Tmr Svc B 2 45 4
Thread A Hi
Thread A Hi
Thread B Hello
Task B X 8 794 6
runClient R 7 5062 2
IDLE R 0 129 3
runServer B 8 1965 1
Task A B 8 990 5
Tmr Svc B 2 45 4
Thread A Hi
Thread A Hi
Thread B Hello
Task B X 8 794 6
runClient R 7 5062 2
IDLE R 0 129 3
runServer B 8 1965 1
Task A B 8 990 5
Tmr Svc B 2 45 4
Thread A Hi
Thread A Hi
Thread B Hello
Task B X 8 794 6
runClient R 7 5062 2
IDLE R 0 129 3
runServer B 8 1965 1
Task A B 8 990 5
Tmr Svc B 2 45 4
Thread A Hi
Thread A Hi
Thread B Hello
Task B X 8 794 6
runClient R 7 5062 2
IDLE R 0 129 3
runServer B 8 1965 1
Task A B 8 990 5
Tmr Svc B 2 45 4
Thread A Hi
Thread A Hi
Thread B Hello
Task B X 8 794 6
runClient R 7 5062 2
IDLE R 0 129 3
runServer B 8 1965 1
Task A B 8 990 5
Tmr Svc B 2 45 4
Thread A Hi
Thread A Hi
Thread B Hello
Task B X 8 794 6
runClient R 7 5062 2
IDLE R 0 129 3
runServer B 8 1965 1
Task A B 8 990 5
Tmr Svc B 2 45 4
Thread A Hi
Thread A Hi
Thread B Hello
Task B X 8 794 6
runClient R 7 5062 2
IDLE R 0 129 3
runServer B 8 1965 1
Task A B 8 990 5
Tmr Svc B 2 45 4
Thread A Hi
Thread A Hi
Thread B Hello
Task B X 8 794 6
runClient R 7 5062 2
IDLE R 0 129 3
runServer B 8 1965 1
Task A B 8 990 5
Tmr Svc B 2 45 4
Thread A Hi
Thread A Hi
Thread B Bye
Thread A Hi
Thread A Hi
Thread A Hi
元のプログラムとの主な違いは二点あります。
-
TaskHandle_t
型変数の宣言TaskHandle_t taskHandlerA, taskHandlerB;
これは通常
を使う際に必要なものですが、FreeRTOS erpc::Thread
を使う場合には不要になるため、使用していません。なお、この宣言の有無は関係ありませんでした。
-
サイズstack 元のプログラムでは
しかないのに対して、動く方では256 配当しています。4096 動いたプログラムにおいて
constexpr uint16_t STACK_SIZE = 256;
と変更したところ、記憶の通り停止しました。エラーコード( の点滅回数)はLED 、即ち4 Hard でした。Fault Hard であるためなのか、シリアルモニターへのエラー出力はありませんでした。Fault
つまり、このように停止する問題の中には、
跋
以上をまとめると、「
これで、
Discussion