-
so, ich habe es hin bekommen:
man muss die thread prios unter die von main loop setzen, damit der watch dog von main gefüttert wird.
Da main immer prio=1 by default hat, müssen die threads bei prio 0 laufen, damit sie nicht blockieren können:
Code:
// std::thread for ESP32, Arduino IDE
// ver 0.0.6 fibonacci
#include <Arduino.h>
#include <thread>
#include <freertos/task.h>
#ifndef LED_BUILTIN
#define LED_BUILTIN 13
#endif
const auto one_sec = std::chrono::seconds
{
1
};
uint32_t fibonacci(uint32_t n) {
if(n == 0){
return 0;
} else if(n == 1) {
return 1;
} else {
return (fibonacci(n-1) + fibonacci(n-2));
}
}
void blinker_loop() {
thread_local uint32_t counter = 0;
Serial.println((String)"blinker_loop Current priority :" + uxTaskPriorityGet(NULL));
vTaskPrioritySet(NULL,0);//set Priority
Serial.println((String)"blinker_loop Current priority :" + uxTaskPriorityGet(NULL));
while(true) {
digitalWrite(LED_BUILTIN, HIGH);
Serial.println((String)"blinker_loop (HIGH) counter: "+ counter);
std::this_thread::sleep_for(one_sec);
digitalWrite(LED_BUILTIN, LOW);
Serial.println((String)"blinker_loop (LOW) counter: "+ counter);
std::this_thread::sleep_for(one_sec);
counter++;
}
}
void fibonacci_loop() {
thread_local uint32_t counter = 0, i=0;
Serial.println((String)"fibonacci_loop Current priority :" + uxTaskPriorityGet(NULL));
vTaskPrioritySet(NULL,0);//set Priority
Serial.println((String)"fibonacci_loop Current priority :" + uxTaskPriorityGet(NULL));
while(true) {
for(i=30; i<41; i++) { // limits: test, debug
Serial.println( (String)"Fibbonacci of "+i+"="+fibbonacci(i));
}
Serial.println((String)"fibonacci_loop counter: "+counter);
counter++;
}
}
std::thread *thread_1;
std::thread *thread_2;
void setup() {
Serial.begin(115200);
delay(1000);
thread_1 = new std::thread(blinker_loop);
thread_2 = new std::thread(fibonacci_loop);
}
void loop() {
delay(500);
static uint32_t main_loop_counter = 0;
Serial.println((String)"main loop: " + main_loop_counter);
delay(5000);
main_loop_counter++;
}
Code:
blinker_loop Current priority :5
blinker_loop Current priority :0
fibonacci_loop Current priority :5
blinker_loop (HIGH) counter: 0
fibonacci_loop Current priority :0
Fibbonacci of 30=832040
main loop: 0
Fibbonacci of 31=1346269
blinker_loop (LOW) counter: 0
Fibbonacci of 32=2178309
blinker_loop (HIGH) counter: 1
Fibbonacci of 33=3524578
blinker_loop (LOW) counter: 1
blinker_loop (HIGH) counter: 2
Fibbonacci of 34=5702887
blinker_loop (LOW) counter: 2
main loop: 1
blinker_loop (HIGH) counter: 3
blinker_loop (LOW) counter: 3
blinker_loop (HIGH) counter: 4
Fibbonacci of 35=9227465
blinker_loop (LOW) counter: 4
blinker_loop (HIGH) counter: 5
blinker_loop (LOW) counter: 5
main loop: 2
blinker_loop (HIGH) counter: 6
blinker_loop (LOW) counter: 6
Fibbonacci of 36=14930352
blinker_loop (HIGH) counter: 7
blinker_loop (LOW) counter: 7
blinker_loop (HIGH) counter: 8
main loop: 3
blinker_loop (LOW) counter: 8
blinker_loop (HIGH) counter: 9
blinker_loop (LOW) counter: 9
blinker_loop (HIGH) counter: 10
blinker_loop (LOW) counter: 10
Fibbonacci of 37=24157817
blinker_loop (HIGH) counter: 11
main loop: 4
blinker_loop (LOW) counter: 11
blinker_loop (HIGH) counter: 12
blinker_loop (LOW) counter: 12
blinker_loop (HIGH) counter: 13
blinker_loop (LOW) counter: 13
main loop: 5
blinker_loop (HIGH) counter: 14
blinker_loop (LOW) counter: 14
blinker_loop (HIGH) counter: 15
blinker_loop (LOW) counter: 15
blinker_loop (HIGH) counter: 16
blinker_loop (LOW) counter: 16
main loop: 6
blinker_loop (HIGH) counter: 17
blinker_loop (LOW) counter: 17
Fibbonacci of 38=39088169
blinker_loop (HIGH) counter: 18
blinker_loop (LOW) counter: 18
blinker_loop (HIGH) counter: 19
main loop: 7
blinker_loop (LOW) counter: 19
blinker_loop (HIGH) counter: 20
blinker_loop (LOW) counter: 20
blinker_loop (HIGH) counter: 21
blinker_loop (LOW) counter: 21
blinker_loop (HIGH) counter: 22
main loop: 8
blinker_loop (LOW) counter: 22
blinker_loop (HIGH) counter: 23
blinker_loop (LOW) counter: 23
blinker_loop (HIGH) counter: 24
blinker_loop (LOW) counter: 24
main loop: 9
blinker_loop (HIGH) counter: 25
blinker_loop (LOW) counter: 25
blinker_loop (HIGH) counter: 26
blinker_loop (LOW) counter: 26
blinker_loop (HIGH) counter: 27
blinker_loop (LOW) counter: 27
main loop: 10
blinker_loop (HIGH) counter: 28
blinker_loop (LOW) counter: 28
blinker_loop (HIGH) counter: 29
Fibbonacci of 39=63245986
blinker_loop (LOW) counter: 29
blinker_loop (HIGH) counter: 30
main loop: 11
blinker_loop (LOW) counter: 30
blinker_loop (HIGH) counter: 31
blinker_loop (LOW) counter: 31
blinker_loop (HIGH) counter: 32
blinker_loop (LOW) counter: 32
blinker_loop (HIGH) counter: 33
main loop: 12
blinker_loop (LOW) counter: 33
blinker_loop (HIGH) counter: 34
blinker_loop (LOW) counter: 34
blinker_loop (HIGH) counter: 35
blinker_loop (LOW) counter: 35
main loop: 13
blinker_loop (HIGH) counter: 36
blinker_loop (LOW) counter: 36
blinker_loop (HIGH) counter: 37
blinker_loop (LOW) counter: 37
blinker_loop (HIGH) counter: 38
blinker_loop (LOW) counter: 38
main loop: 14
blinker_loop (HIGH) counter: 39
blinker_loop (LOW) counter: 39
blinker_loop (HIGH) counter: 40
blinker_loop (LOW) counter: 40
blinker_loop (HIGH) counter: 41
main loop: 15
blinker_loop (LOW) counter: 41
blinker_loop (HIGH) counter: 42
blinker_loop (LOW) counter: 42
blinker_loop (HIGH) counter: 43
blinker_loop (LOW) counter: 43
blinker_loop (HIGH) counter: 44
main loop: 16
blinker_loop (LOW) counter: 44
blinker_loop (HIGH) counter: 45
blinker_loop (LOW) counter: 45
blinker_loop (HIGH) counter: 46
blinker_loop (LOW) counter: 46
main loop: 17
blinker_loop (HIGH) counter: 47
Fibbonacci of 40=102334155
fibonacci_loop counter: 0
Fibbonacci of 30=832040
blinker_loop (LOW) counter: 47
Fibbonacci of 31=1346269
blinker_loop (HIGH) counter: 48
Fibbonacci of 32=2178309
blinker_loop (LOW) counter: 48
Fibbonacci of 33=3524578
blinker_loop (HIGH) counter: 49
blinker_loop (LOW) counter: 49
main loop: 18
Fibbonacci of 34=5702887
blinker_loop (HIGH) counter: 50
blinker_loop (LOW) counter: 50
blinker_loop (HIGH) counter: 51
Fibbonacci of 35=9227465
blinker_loop (LOW) counter: 51
blinker_loop (HIGH) counter: 52
main loop: 19
blinker_loop (LOW) counter: 52
blinker_loop (HIGH) counter: 53
blinker_loop (LOW) counter: 53
blinker_loop (HIGH) counter: 54
Fibbonacci of 36=14930352
blinker_loop (LOW) counter: 54
blinker_loop (HIGH) counter: 55
main loop: 20
blinker_loop (LOW) counter: 55
ntl nur der jetzige Stand, möglicherweise erscheinen doch wieder irgendwann neue Erkenntnisse... ;) 8)
-
Jetzt mal eine ganz ernsthafte Frage. Wozu soll denn so ein Overhead bei den Winzig-Programmen, die normal in der Arduino-IDE verfasst werden, gut sein?
Was versuchst Du denn da, mit tausend Blinkern? ;)
MfG
-
ein Test-Setup zum Simulieren von preemptivem Multithreading mit plötzlich hängenden Einzel-Threads.
Bisher hat der Scheduler nicht preemptiv gearbeitet, weil bei nicht angepassten prios der RTOS watchdog blockiert und resetted wird, dadurch kommt es zum Programmabsturz und Neustart.
Jetzt können die Threads, wenn einer von ihnen blockiert, ungestört weiterlaufen, unter Beobachtung und mit Notfall-Maßnahmen.
Beispiel:
Autonomer Robot, fährt momentan geradeaus. Plötzlich blockiert der Thread, der die i2c-Distanzsensoren ausgelesen hat (oder irgendein anderer wichtiger Kontroll- oder Mess-Thread).
Folge: Robot fährt weiter und crasht, weil der Fehler nicht rechtzeitig erkannt wird.
Jetzt kann per Timestamp-Watcher jeder Thread kontrolliert werden, und wenn einer hängt, kann das System geregelt zum Stoppen gebracht werden, evtl. sogar autonome Reparaturversuche - vorher ging noch nicht mal mehr eine Kontrolle.
Wir hatten dieses Problem auch schon für die Raspi-Plattform in C mit pthread diskutiert.
-
Ich habe schon eine grafische, kooperative Multitasking-Oberfläche in der Vergangenheit in Assembler umgesetzt. Für PC. Daher kenne ich die Probleme.
Die Idee, die Du ansprichst ist daher nicht neu, sondern tauchte damals auch auf. Ich habe dann genau so etwas umgesetzt. Nämlich eine Kontrolle der Bibliotheken im Speicher mit Reparaturfunktion, indem Bibliotheken, deren Prüfsumme nicht mehr stimmte, nachgeladen wurden. Das Ende der Sache war mehr Overhead (also verlorene Rechenleistung) und der Nutzen dummerweise = Null. Das resultierte daraus, dass die Idee zwar gut, aber es nie zu diesen angenommenen Ausnahmen kam. Wenn, dann waren es Einzelfälle, wo ein Programmier- oder Denkfehler zugrunde lag. Ähnlich war es mit der implementierten Stapelüberwachung. Das brachte zumindest was, weil sich bei manchen Programmen nicht gut abschätzen lies, wieviel Stapelspeicher tatsächlich benötigt wird. Nach ein wenig Erfahrung hatte sich dieses Thema aber auch wieder erledigt. So war diese Funktion auch nur während der Entwicklungsphase von Applikationen gut, damit zumindest zwischendurch nicht dauernd das gesamte System hängen blieb.
Fehler beheben ist bsesser, als sich auf solche Funktionen zu verlassen, die dann die Rechenleistung stehlen.
MfG
-
natürlich ist die Idee nicht neu, ich habe preemptives MT sogar schon seit fast 20 Jahren bei Lego RCX, NXT und EV3 benutzt.
Aber bei Arduinos gibt es üblicherweise weder pthread noch std::thread - alles andere ist entweder Murks oder man muss freeRTOS selber implementieren, konfigurieren und compilieren, was extrem kompliziert ist.
Für ESP32 aber ist jetzt std::thread auch in der Arduino IDE verfügbar, und jetzt funktioniert es ja auch! 8)