Archiv verlassen und diese Seite im Standarddesign anzeigen : Der Teensy 4.0 ist fertig
Hallo,
um das Forum mal etwas zu beleben, hier eine kleine Neuigkeit.
Die kleinen Teensy Boards gehören ja schon seit einiger Zeit zu den schnellsten Arduino kompatiblen Boards.
Nachdem z.B. Adafruit mit einigen SAMD51 basierten Boards leistungsmäßig näher gerückt war, stellt der Teensy 4.0 den Abstand wieder ziemlich deutlich her.
https://www.pjrc.com/store/teensy40.html
Damit gibt es jetzt auch Arduino kompatible Boards mit Cortex M7 und einer FPU, die auch Berechnungen mit doppelter Genauigkeit beschleunigt.
tolles Teil, zweifellos - lässt nur noch wenige Wünsche offen...
oh freude oh freude, gleich mal in die microPython Codes gucken, wie weit der Weg für einen Port wird.
Leider hab ich da auf die schnelle keine Schematics gefunden, kann wer was über den USB sagen, läuft der nativ vom Controller oder ist eines der kleinen Käfer auf der Platine wieder ein USB-Serial Chip?!
edit: okay da steht USB Host ... aber gilt das auch für den bestückten Port oder ist das nur über die Pins nutzbar?!
Bei der Leistung und dem Speicher ist das für mich (persönlich, meine Anwendungen) ganz klar ein Pi Zero Ersatz!!!
Schematics kommen noch, steht im Forum.
An microPython für den 3.x waren auch schon andere Leute dran. Da war mal was im Forum, kann mich nicht mehr genau erinnern. Sollte dann mit 4.x ähnlich gehen.
Zum USB siehe die technischen Daten:
2 USB ports, both 480 MBit/sec
die USB-Host Library vom 3.6 wurde wohl schon angepasst. Nur der Hardwareanschluss ist wohl komplizierter, da müsste noch ein IC in die 5V Leitung.
- - - Aktualisiert - - -
edit: okay da steht USB Host ... aber gilt das auch für den bestückten Port oder ist das nur über die Pins nutzbar?!
Ne, die Host Lib geht nur mit dem zweiten unbestückten Port.
Hier schon mal die Schaltplanseite, ohne 4.0
https://www.pjrc.com/teensy/schematic.html
ja für das Power Handling, deswegen hatte ich ja gefragt ob da ein klassischer usb serial wandler bei ist wie bei den STM NUCLEOS (gott haben die mir die Tour verhagelt XD ) oder ob das was für den USB oder einfach nur ein Spannungswandler ist ... deiner Aussage nach sind es wohl nur gammelige Wandler, schade ...
Host wollte ich jetzt zwar nicht spielen aber ich würde gerne Gadget Mode auf Arduino/µPy Basis machen ... bisher mache ich das mit Pi Zeros und Raspbian, weil ich die Teensys bisher zu Leistungsschwach finde aber die Boot Time der Pi Zeros ist schon echt zum brechen und für µPy sind die anderen Teensys zu klein im Flash um auch die Gadget Library einzubinden :(
Pi = Kanone auf Spatzen
Teensy < 4.0 = zu kleines Kaliber für die Kugel
Teensy 4.0 klingt da sher vielversprechend
---------------
Ne, die Host Lib geht nur mit dem zweiten unbestückten Port.
dann geht das ja trotzdem noch theoretisch *freu*
dann geht das ja trotzdem noch theoretisch *freu*
Ja, für USB Eigenentwicklungen sind die Boards ziemlich gut. Man kann ja so ziemlich alles mit dem Controller machen, er hat ja keinen eigenen Bootloader, der sitzt in einem von den kleinen ICs. Selbst wenn man den USB total verproggt, kann man das Ding weiter programmieren.
ist teensythread auf dem 4.0 verfügbar, echt preemptiver scheduler, mit unterschiedlich konfigurierbaren thread prios (wie pthread/std::thread auf Pi oder std::thread auf ESP32) ?
ist teensythread auf dem 4.0 verfügbar, echt preemptiver scheduler, mit unterschiedlich konfigurierbaren thread prios (wie pthread/std::thread auf Pi oder std::thread auf ESP32) ?
Da müsste man mal den 159-seitigen Betatest-Thread im Teensy Forum durchkämmen. Leider ist die Suchfunktion da nicht so nützlich.
Alternativ im Verzeichnis nachschauen, wenn in Kürze die Teensy Software 1.47 kommt. Da sollte alles drin sein, was es bisher gibt. Meine Vermutung ist, dass TeensyThreads nur eine Anpassung der bisherigen Version ist. Ist das nicht kooperatives Multitasking ? Ich weiß, dass es die Lib gibt, benutzt habe ich die noch nicht.
Da müsste man mal den 159-seitigen Betatest-Thread im Teensy Forum durchkämmen. Leider ist die Suchfunktion da nicht so nützlich.
Alternativ im Verzeichnis nachschauen, wenn in Kürze die Teensy Software 1.47 kommt. Da sollte alles drin sein, was es bisher gibt. Meine Vermutung ist, dass TeensyThreads nur eine Anpassung der bisherigen Version ist. Ist das nicht kooperatives Multitasking ? Ich weiß, dass es die Lib gibt, benutzt habe ich die noch nicht.
ich meine auch, dass es nur kooperatives MT ist, und läuft ja außerdem auch nur auf 1 core (ESP32: 2 cores).
Auf einem Teensy kann auch viel über DMA erledigt werden, das läuft dann weitgehend unabhängig vom Prozessorkern. Manche Libs machen das intern, von manchen gibt es Varianten mit DMA, selber machen ist leider mit viel Lernaufwand verbunden.
Um Dinge zyklisch mit hoher Priorität parallel zum normalen Programm abzuarbeiten, eignen sich auf dem Teensy vor allem die Timer, z.B. hiermit
https://www.pjrc.com/teensy/td_timing_IntervalTimer.html
Hier ein paar Hintergründe zum Thema
https://forum.pjrc.com/threads/28714...ll=1#post73823
bezogen auf den 3.1, die größeren haben von manchen Timer Sorten ein paar mehr. Beim 4.0 sind wohl ein paar Unterschiede mehr, aber die wichtigen Libs sind darauf angepasst.
der Nachteil von Timern ist, dass sie üblicherweise nicht multiple langdauernde, ununterbrochene Operationen zulassen. Selbst kooperatives MT funktioniert nicht mehr, wenn einzelne Threads plötzlich in einer langen Berechnung (exemplarisch: fibonacci(43) rekursiv) hängen oder blockieren.
Preemptives MT dagegen kann einfach die Zeitscheibe nach Sichern aller Variablen und Register etc unterbrechen und dann die nächste Zeitscheibe für den nächsten Prozess starten (round robin), auch wenn kein yield() drin war und die Berechnungen oder die Datenübertragung noch nicht fertig sind.
Ein temporäres oder dauerhaftes Blockieren oder ununterbrochene Aktivitäten von einem oder auch mehreren Threads verhindern daher nicht die weitere Ausführung der übrigen Threads.
Daher ist für mich ein preemptives MT unverzichtbar, wie es bei Raspberry Pi (C/pthread), ESP32 (C++/std::thread auf RTOS Basis, etwas eingeschränkt) oder Lego Mindstorms (RCX/NQC, NXT/NXC, EV3/C/pthread) möglich ist.
Daher ist für mich ein preemptives MT unverzichtbar, wie es bei Raspberry Pi (C/pthread), ESP32 (C++/std::thread auf RTOS Basis, etwas eingeschränkt) oder Lego Mindstorms (RCX/NQC, NXT/NXC, EV3/C/pthread) möglich ist.
Anmerkung: Für den ESP32 ist eine Minimalimplementation von pthread (https://github.com/espressif/esp-idf/blob/f1b8723996d299f40d28a34c458cf55a374384e1/components/pthread/pthread.c) verfügbar. Diese basiert auf FreeRTOS's Tasksystem (https://www.freertos.org/a00106.html). Std::thread, std::async etc. wiederum sind ein Abstraktionslayer basierend auf pthread (Quelle (https://github.com/espressif/arduino-esp32/issues/472)).
Anmerkung: Für den ESP32 ist eine Minimalimplementation von pthread (https://github.com/espressif/esp-idf/blob/f1b8723996d299f40d28a34c458cf55a374384e1/components/pthread/pthread.c) verfügbar. Diese basiert auf FreeRTOS's Tasksystem (https://www.freertos.org/a00106.html). Std::thread, std::async etc. wiederum sind ein Abstraktionslayer basierend auf pthread (Quelle (https://github.com/espressif/arduino-esp32/issues/472)).
ja, das ist das was ich oben gemeint habe, ich kenne und nutze es beim ESP32 auch bereits. Man kann thread prios von 0-5 definieren, für potentiell blockierende threads empfiehlt sich 0, und es funktioniert sehr gut bis jetzt. Ich hatte hier auch schon ein Beispielprogramm gepostet zu Testzwecken:
https://www.roboternetz.de/community/threads/73446-std-thread-f%C3%BCr-ESP32-unter-Arduino-IDE-zum-Laufen-zu-kriegen?p=653989&viewfull=1#post653989
- - - Aktualisiert - - -
PS
korrigiert:
sogar auch std::mutex ist für ESP32 vorhanden
#include <mutex>
std::mutex print_mutex;
void mtxPrintln(String str) // String: Arduino API // C++: std::string
{
print_mutex.lock();
Serial.println(str);
print_mutex.unlock();
}
der Nachteil von Timern ist, dass sie üblicherweise nicht multiple langdauernde, ununterbrochene Operationen zulassen. Selbst kooperatives MT funktioniert nicht mehr, wenn einzelne Threads plötzlich in einer langen Berechnung (exemplarisch: fibonacci(43) rekursiv) hängen oder blockieren.
Das verstehe ich nicht. Wenn ich einen Timer verwende, löst der einen Interrupt aus, der selbstverständlich das laufende Programm unterbricht.
Preemptives MT dagegen kann einfach die Zeitscheibe nach Sichern aller Variablen und Register etc unterbrechen und dann die nächste Zeitscheibe ...
Das wird von einem Timer und seinem Interrupt gesteuert. Wie sollte sonst der Scheduler auf die nächste Task umschalten können?
Die hardwarenahen Systeme, die ich so baue, haben alle entweder einen dediziert laufenden Timer mit Interrupt oder hängen an einem für die Hardware notwendigen Timer, z.B. dem PWM Timer eines Motors. Dazu kommen dann noch die Interrupte der übrigen Peripherie. Das gibt mir ausreichend Nebenläufigkeit, daß ich Threads und den dazu gehörenden Scheduler bisher nicht vermisst habe.
Auch würde mir ein preemptives System gar nicht passen. Wenn ich schnell reagieren muß z.B. einen PID Regler vor dem nächsten PWM-Takt fertigrechnen oder ein CRC bevor das Transmit Register leer ist, darf mir kein Scheduler dazwischen funken. Und sollte einer meiner Interrupthandler hängen, hat meine SW einen grundlegenden Bug. Dann wird mein PID Regler nie richtig funktionieren oder das CRC nie richtig berechnet werden.
Der Vergleich zwischen einem PI mit einem Multitasking System wie Linux/Unix (wo man in jeder Task natürlich auch noch mal lightweight Tasks aka Threads haben kann) und einem Teensy mit einerm Arduino Framework hinkt an allen Ecken und Kanten.
MfG Klebwax
Wenn ich bei 2MHZ Sample Rate ein 800kHz Signal sampeln will, kann ich bequem nebenbei noch eine UI steuern, solange ich DMAs damit beschäftige die Daten zu schaufeln ohne dass ich auch nur die Bohne Threading benötige.
Und wenn mein System zyklsich und Azyklisch arbeiten muss, dann lege ich den zyklischen Part auf die CPU und gestalte ihn so als Statemachine, dass ich ihn über die Interrupts steuern kann ohne auch nur einmal einen Thread nutzen zu müssen. Das ist meine Vorstellung vom "Bare Metal" (Klar benötigt man Controller spezifische API Librarys aber das ist trotzdem Bare Metal! Da brauche ich keine Layer 3 Sprache für, Layer 2 reicht vollkommen aus und ist deterministisch im Gegensatz zu Layer 3, wo man nur begrenzt deterministrisch sein kann. (RT auf dem Pi >>typisch<< 270nS war das oder? Auf Bare Metal kann ich es auf den Takt genau ausrechnen wann ich eine Reaktion auf meinem Code zu erwarten habe)
Es ist schlicht eine Frage der Anwendung wie exakt es sein muss, für den einen reicht eine RT Thread Library aus, für mich oder Klebwax Anwendung eben nicht
Rleativierung: Gerade beim Thema DMA muss man aber Vorsichtig sein, das ist teilweise vom Zustand der Peripherie abhängig, ein Atmel-SAMD DMA braucht zwischen ~12 und 27 Takten bevvor ein Byte übertragen wird und manchmal sogar noch länger. Die ERfahrung musste ich auch schonmal machen und deswegen aus einem Projekt verbannen weil ich nur stabil 200kHz sampeln (timestamp + daten, DMA im quasi interleave, echten gibts bei dem nicht) konnte :(
So hatte ich dann wieder einen XMega eingebaut, weil der bei 32Mhz bis 1Mhz DMA Samplerate und echten interleave unterstützt.
ich sehe schon, ihr versteht teilw (?) nicht den Sinn und die Vorteile von preemptivem MT.
Lasst mal parallel laufen, ohne yields und ohne delays, als Simulations/Testprogramm:
1.) fibonacci(41) unmittelbar hintereinander in einer Endlosschleife berechnen, Ausgabe seriell
2.) abwechselnd nacheinander fibonacci(38 ), fibonacci(39) und fibonacci(40) direkt hintereinander in einer Endlosschleife berechnen, Ausgabe seriell
3.) Bildschirmausgabe (TFT) von unmittelbat hintereinander 1000 gefüllten Kreisen verschiedener Größe und Position, danach immer komplett Bildschirm löschen, in einer Endlosschleife,
4.) array int[1000] per random initialisieren, dann unmittelbar Quicksort des arrays, dann unmittelbar sortierte Ausgabe des arrays seriell, in einer Endlosschleife
5.) in einer Endlosschleife direkt hintereinander die analog-Ports A0 bis A3 eines ads1115 i2c Sensors schnellstmöglich auslesen und addieren, jeden 100.000sten Summen-Wert (als double) seriell ausgeben
6.) in einer Endlosschleife direkt hintereinander schnellstmöglich die digital-Ports D10 auslesen und D11 damit schreiben und D12 toggeln, jeden 100.000sten Schleifencounter und dazu die dann aktuellen D10/D11/D12 Werte seriell ausgeben.
hier der fibonacci-Code:
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));
}
}
1.) nicht meine Anwendung, brauche ich nicht
2.) siehe 1.
3.) kann ich wunderbar ohne Threads, DMA + Timer + Statemachine +ISR
4.) warum sollte ich sowas machen wollen? siehe 1.)
5.) da hast du dir gerade selber ins Bein geschossen, weil du scheinbar wieder nicht gelesen hast was ich schreibe, ich wäre schneller als du in dem Fall, deutlich!
6.) siehe 5.
Q.E.D.
nochmal nachträglich für dich "ES KOMMT AUF DIE ANWENDUNG AN"
genauer gesagt, während ich 5ten und 6tens per DMA und ISR löse, könnte ich 3tens vermutlich sogar noch parallel ausführen
du löst mit Threading Probleme, die ich mit ISR und Peripherie garnicht habe, meine CPU langweilt sich während die Peripherie die Hauptarbeit macht
was du brauchst, interessiert nicht, es geht um den Simulations/Testaufbau an sich, bei dem sowohl schnelle als auch langdauerne Prozesse laufen (nur dafür ist es ja auch gedacht, nicht für Killefit).
Holomino
11.08.2019, 13:48
Die Ursache Eurer Probleme liegt nicht in der Sache.
Die liegt in Euch selbst.
(Wobei ich mindestens einem der Beteiligten mal unterstelle, von der Gegenposition absolut keine Ahnung zu haben. Hat er selber auch mehrfach hier im Forum angemerkt, dass er damit nix anfangen kann)
Die Ursache Eurer Probleme liegt nicht in der Sache.
Die liegt in Euch selbst.
(Wobei ich mindestens einem der Beteiligten mal unterstelle, von der Gegenposition absolut keine Ahnung zu haben. Hat er selber auch mehrfach hier im Forum angemerkt, dass er damit nix anfangen kann)
typischer Schwätzer-Post, wie schon so oft hier in diesem Forum.
Holomino
11.08.2019, 14:05
Na? Fühlt sich da jemand angesprochen?
Na? Fühlt sich da jemand angesprochen?
von deinem saudummen, hohlen Geschwätz?
Da sollte sich jeder angesprochen fühlen.
Holomino
11.08.2019, 14:11
Oh, fachlich am Ende? Jetzt geht es unter der Gürtellinie weiter?
Reg Dich ab, Mann.
Oh, fachlich am Ende? Jetzt geht es unter der Gürtellinie weiter?
Reg Dich ab, Mann.
sei du mal ganz ruhig mit deiner OT Dummschwätzerei.
Ich habe - sachlich - versucht, an einem Simulationsbeispiel die Vorteile von preemptivem MT zu verdeutlichen, aber DU warst es, der - unsachlich - irgendwelche anfeindende blasierte Plattitüden von sich gegeben hat.
Holomino
11.08.2019, 15:01
1.) lässt Du aufm Controller in der main laufen
2.) Geht quasikonstant im Timer Interrupt
3.) Geht geteilt im Timer-Interrupt über ne kleine State-Machine
4.) dito
5.) AD-Interrupt
6.) Port-ISR
Sollte sich alles mithilfe eines seriellen Fifos parallel auf'm ATXMega erledigen lassen, wobei ich den Verdacht hege, die Serielle wird mit 112kBaud ein Nadelöhr.
Nein, ich würde dafür auf'm Controller kein Mutithreading verwenden. Einfach, weil es bei Deinen Simulationsbedingungen nicht die kleinste wirkliche Asynchronität gibt. Sprich, es geht nur um die 100%ige Auslastung des Controllers, die ist mit dem Anteil in der main() gegeben.
aha, also doch wieder zurück zur Sachlichkeit...
die kurzdauernden (5+6) sind ntl nicht das Problem - du weisst aber schon, wie lange die fibonacci loops, die Sort Funktion und die TFT-Ausgabe einzeln dauern und wie du es sicherstellst, dass du sie ohne yields auch simultan nebeneinander ausführen kannst?
(Also z.B. Kreise nacheinander auf dem TFT, während die fibonaccis und die Sortfunktionen parallel ihr Ding schnellstmöglich weiterrechnen)
Die fibonaccis sollen unvorhergesehene zufällige oder auch temporäre Funktions-Blockierungen simulieren, daher dürfen hier keine yield() quasi als willkürliche "Sollbruchstellen" eingebaut werden, gleiches gilt für die Sort-Funktion. Alles muss parallel konsekutiv weiterlaufen, genau wie die analog/digital Pin Funktionen.
Ansonsten könnte man ja stattdessen auch kooperatives MT verwenden.
- - - Aktualisiert - - -
ich habe hier ein abgespecktes Testprogramm nach dem obigen Schema (ohne TFT, da zu individuell/speziell, kein ADC, und nur 1 fibonacci thread neben GPIO, blink, sort und main counter)
// std::thread for ESP32, Arduino IDE
// ver 0.0.7 fibonacci, GPIO, blink, sort und main counter
#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(int n) {
if(n == 0){
return 0;
} else if(n == 1) {
return 1;
} else {
return (fibonacci(n-1) + fibonacci(n-2));
}
}
void shellsort(int size, int* A)
{
int i, j, increment;
int temp;
increment = size / 2;
while (increment > 0) {
for (i = increment; i < size; i++) {
j = i;
temp = A[i];
while ((j >= increment) && (A[j-increment] > temp)) {
A[j] = A[j - increment];
j = j - increment;
}
A[j] = temp;
}
if (increment == 2)
increment = 1;
else
increment = (unsigned int) (increment / 2.2);
}
}
#define tpin1 11 // GPIO test pins digitalWrite
#define tpin2 12 // GPIO test pins digitalWrite
#define tpin3 13 // GPIO test pins digitalRead
int32_t test_GPIO() { //
volatile static bool w=false, r;
uint32_t y;
for (y=0; y<100000; y++) {
digitalWrite(tpin1, w);
w=!w;
r=digitalRead(tpin3);
digitalWrite(tpin2, w&!r);
}
return 1;
}
void blinker_loop() {
thread_local uint32_t counter = 0;
vTaskPrioritySet(NULL,0);//set Priority
Serial.println((String)"blinker_loop Current priority :" + uxTaskPriorityGet(NULL)+"\n");
while(true) {
digitalWrite(LED_BUILTIN, HIGH);
Serial.println((String)"\nblinker_loop (HIGH) counter: "+ counter+"\n");
std::this_thread::sleep_for(one_sec);
digitalWrite(LED_BUILTIN, LOW);
Serial.println((String)"\nblinker_loop (LOW) counter: "+ counter+"\n");
std::this_thread::sleep_for(std::chrono::milliseco nds(500));
counter++;
}
}
void fibonacci_loop() {
thread_local uint32_t counter = 0, i=0;
vTaskPrioritySet(NULL,0);//set Priority
Serial.println((String)"fibonacci_loop Current priority :" + uxTaskPriorityGet(NULL)+"\n");
while(true) {
for(i=25; i<41; i++) { // limits: test, debug
Serial.println( (String)"\nfibonacci of "+i+"="+fibonacci(i)+"\n");
}
Serial.println((String)"\nfibonacci_loop counter: "+counter+"\n");
counter++;
}
}
void sort_loop() {
static int array[1000];
thread_local uint32_t counter = 0, i=0;
vTaskPrioritySet(NULL,0);//set Priority
Serial.println((String)"sort_loop Current priority :" + uxTaskPriorityGet(NULL)+"\n");
while(true) {
Serial.println((String)"\nsort_loop counter: "+counter+"\n");
for(i=0; i<1000; i++) {
array[i]= random(0,65000);
}
shellsort(1000, array);
for(i=0; i<1000; i+=50) { // abgekürzte Ausgabe da Serial sehr langsam
Serial.println((String)i + "="+array[i]+"\n");
}
counter++;
}
}
void GPIO_loop() {
thread_local uint32_t counter = 0, i=0;
vTaskPrioritySet(NULL,0);//set Priority
Serial.println((String)"GPIO_loop Current priority :" + uxTaskPriorityGet(NULL)+"\n");
while(true) {
Serial.println((String)"\nGPIO_loop counter: "+counter);
test_GPIO();
Serial.println((String)"\ntpin1="+digitalRead(tpin1)+" tpin2="+digitalRead(tpin2)+" tpin3="+digitalRead(tpin3)+"\n"); counter++;
}
}
std::thread *thread_1;
std::thread *thread_2;
std::thread *thread_3;
std::thread *thread_4;
void setup() {
Serial.begin(115200);
delay(1000);
thread_1 = new std::thread(blinker_loop);
thread_2 = new std::thread(fibonacci_loop);
thread_3 = new std::thread(sort_loop);
thread_4 = new std::thread(GPIO_loop);
}
void loop() {
static uint32_t main_loop_counter = 0;
Serial.println((String)"\nmain loop: " + main_loop_counter);
delay(500);
main_loop_counter++;
}
Ausgabe:
blinker_loop Current priority :0
blinker_loop (HIGH) counter: 0
fibonacci_loop Current priority :0
main loop: 0
sort_loop Current priority :0
GPIO_loop Current priority :0
GPIO_loop counter: 0
sort_loop counter: 0
0=47
50=3401
100=6494
150=9200
200=12602
250=15104
300=18709
350=21672
400=24936
450=28729
500=32708
550=36046
600=38724
650=41079
700=44079
750=47881
800=51269
850=55340
900=58959
950=61237
sort_loop counter: 1
0=31
50=3240
fibonacci of 25=75025
100=6167
150=9226
200=12476
250=16259
300=19595
350=22311
400=24962
450=28504
500=31248
550=33950
600=37461
650=40990
700=44589
750=48565
800=51690
850=54884
900=58992
950=61841
sort_loop counter: 2
0=85
50=3614
100=7593
150=9998
200=13500
250=17407
300=21212
350=24726
400=27557
450=31493
500=35173
550=38203
600=41474
650=43718
700=46819
750=49960
800=53049
850=55882
900=58694
950=61681
sort_loop counter: 3
0=32
50=2884
100=5900
150=9364
200=12685
250=15686
300=19131
350=22143
400=26652
450=30404
500=33546
550=36739
600=39421
650=42451
700=45692
750=48909
800=51979
850=55377
900=58377
950=61291
sort_loop counter: 4
fibonacci of 26=121393
0=23
50=3417
100=6372
150=9815
200=13157
250=16378
300=19956
350=24929
400=29314
450=32064
500=36147
550=38833
600=41834
650=44373
700=47775
750=50541
800=53487
850=55937
900=58256
950=62152
sort_loop counter: 5
0=21
50=3777
100=7573
150=10470
200=13651
250=17484
300=21170
350=24277
400=27199
450=30090
500=33422
550=37681
600=40515
650=43048
700=45831
750=49012
800=51715
850=55653
900=58929
950=62488
sort_loop counter: 6
0=58
50=4002
100=7346
150=11323
200=14634
250=17455
300=20254
350=23791
400=26801
450=29955
500=32977
550=36702
600=39832
650=43339
700=47006
750=50022
800=53666
850=56557
900=59515
950=62182
sort_loop counter: 7
tpin1=1 tpin2=0 tpin3=0
GPIO_loop counter: 1
0=25
50=3367
100=6883
150=9945
200=12616
250=15747
300=19383
350=22444
400=25189
450=28261
500=30761
550=33859
600=38202
650=41193
700=44616
750=48756
800=51567
850=54838
900=58684
950=61818
sort_loop counter: 8
fibonacci of 27=196418
0=14
50=3213
100=6315
150=9496
200=12298
250=15056
300=18474
350=21427
400=24765
450=28508
500=32159
550=35123
600=37756
650=41279
700=43700
750=47581
800=51230
850=55155
900=58612
950=61459
sort_loop counter: 9
0=54
50=3242
100=6332
150=10021
200=13402
250=16271
300=18935
350=21827
400=25257
450=28839
500=32319
550=35307
600=38867
650=42698
700=45640
750=48829
800=51474
850=55274
900=58318
950=62063
sort_loop counter: 10
0=31
50=3668
100=6844
150=9505
200=12960
250=16353
300=19288
350=22669
400=25977
450=28841
500=31891
550=35351
600=38795
650=41469
700=45038
750=49333
800=53061
850=56511
900=59260
950=61956
sort_loop counter: 11
0=23
50=3912
100=7161
150=10004
200=13607
250=16769
300=19444
350=22614
400=26006
450=29348
500=32627
550=35392
600=38864
650=42603
700=45691
750=48845
800=52706
850=55246
900=59006
950=61816
sort_loop counter: 12
0=156
50=3186
100=6290
150=9624
200=12412
250=16238
300=20889
350=23442
400=26736
450=29771
500=32166
550=35207
600=39200
650=41996
700=45267
750=47830
800=51229
850=55060
900=57451
950=61013
sort_loop counter: 13
0=20
50=3955
100=7809
150=10342
200=13140
250=16675
300=20082
350=23340
400=26285
450=28638
500=31700
550=34713
600=38145
650=40684
700=43643
750=47112
800=51263
850=55144
tpin1=1 tpin2=0 tpin3=0
GPIO_loop counter: 2
900=59030
950=62064
sort_loop counter: 14
0=36
50=3153
100=6841
150=10460
200=13863
250=16668
300=19456
350=22546
400=26209
450=29438
500=32652
550=35381
600=40102
650=42992
700=46808
750=49132
800=52439
850=54690
900=57698
950=61615
sort_loop counter: 15
0=52
50=3195
fibonacci of 28=317811
100=6875
150=9995
200=12672
250=16315
300=18959
350=21972
400=24566
450=27421
500=31476
550=34933
600=37703
650=41639
700=44685
750=47837
800=50874
850=53744
900=57251
950=60798
sort_loop counter: 16
0=3
50=2682
100=6417
150=9210
200=12330
250=15666
300=19283
350=22212
400=24626
450=28222
500=31403
550=34776
600=37535
650=40324
700=43660
750=46752
800=50320
850=54408
900=58989
950=62075
sort_loop counter: 17
0=48
50=4136
100=7497
150=10838
200=14725
250=18552
300=22112
350=24721
400=27468
450=30392
500=33306
550=36051
600=38820
650=41688
700=45254
750=48275
800=51622
850=54967
900=58827
950=62104
sort_loop counter: 18
0=13
50=3359
100=7690
150=10581
200=13676
250=17342
300=21613
350=25427
400=28414
450=32038
500=34613
550=37752
600=40842
650=43854
700=47496
750=50824
800=53635
850=56736
900=59698
950=62445
sort_loop counter: 19
0=21
50=3563
100=6870
150=10723
200=14048
250=17403
300=19397
350=22491
400=26267
450=28880
500=32349
550=35393
600=39202
650=43213
700=46400
750=48519
800=51736
850=54825
900=57940
950=61719
sort_loop counter: 20
0=74
50=3586
100=6693
tpin1=1 tpin2=0 tpin3=0
GPIO_loop counter: 3
150=9680
200=13023
250=15931
300=19417
350=22329
400=26050
450=28463
500=31279
550=33823
600=37466
650=41267
700=44214
750=48308
800=51883
850=54933
900=57934
950=61872
sort_loop counter: 21
main loop: 1
0=10
50=2491
100=5715
150=8923
200=12372
250=15935
300=18583
350=22027
400=25992
450=29238
500=32473
550=35568
600=39301
650=41946
700=45252
750=48172
800=52316
850=55143
900=58266
950=61734
sort_loop counter: 22
0=5
50=3626
100=7261
150=10654
200=13539
250=16869
300=19860
350=23319
400=26040
450=29171
500=33005
550=35951
600=39020
650=42070
700=44999
750=48503
800=51445
850=54671
900=58717
950=61778
sort_loop counter: 23
0=79
50=3686
100=7159
150=10059
200=12844
250=15452
300=18720
350=21683
400=24907
450=27838
500=32109
550=34816
600=37621
650=40847
700=44406
750=48096
800=51082
850=54802
900=59264
950=62076
sort_loop counter: 24
0=7
50=2389
100=5400
150=8584
200=12265
250=15313
300=18368
350=21222
400=24869
450=28233
500=32326
550=35823
600=39901
650=43226
700=46595
750=49747
800=53441
850=56519
900=59553
950=62211
sort_loop counter: 25
0=3
50=2838
100=6138
150=8701
200=11448
250=14149
300=17238
350=21169
400=24938
450=28913
500=31875
550=35744
600=38682
650=41620
700=44902
750=48263
800=51704
850=55207
900=58432
950=62282
sort_loop counter: 26
0=5
50=3642
100=7343
150=10375
200=13817
250=17377
300=20976
350=24217
400=26999
450=30150
500=32947
550=35708
600=38768
650=42428
tpin1=1 tpin2=0 tpin3=0
GPIO_loop counter: 4
700=45189
750=48109
800=52016
850=55648
900=58089
950=61870
sort_loop counter: 27
fibonacci of 29=514229
0=187
50=3028
100=7087
150=9878
200=12656
250=16048
300=18666
350=21445
400=24498
450=28448
500=32173
550=36069
600=39231
650=42453
700=46108
750=49846
800=53025
850=55752
900=58985
950=61996
sort_loop counter: 28
0=17
50=3728
100=6881
150=10344
200=13685
250=15967
300=18798
350=21723
400=24772
450=28667
500=31838
550=34906
600=38476
650=41853
700=45483
750=49001
800=52355
850=55767
900=58742
950=61445
sort_loop counter: 29
0=2
50=3985
100=7072
150=10485
200=13131
250=16474
300=20604
350=23114
400=26688
450=29576
500=32757
550=36503
600=39560
650=41960
700=45876
750=48758
800=52338
850=55405
900=58631
950=61763
sort_loop counter: 30
0=76
50=3113
100=6469
150=9155
200=12130
250=15147
300=18166
350=20999
400=25045
450=29087
500=32848
550=35471
600=38567
650=41777
700=44789
750=48269
800=51203
850=55225
900=58299
950=61798
sort_loop counter: 31
0=101
50=3848
100=7503
150=10969
200=13740
250=17424
300=21095
350=25391
400=28536
450=31166
500=33995
550=36963
600=40208
650=43553
700=46312
750=49905
800=53035
850=55831
900=58797
950=61885
sort_loop counter: 32
0=17
50=2644
100=5983
150=10137
200=12459
250=15556
300=18461
350=21403
400=25231
450=28569
500=32149
550=35056
600=37551
650=40026
700=44112
750=47933
800=51077
850=54073
900=57371
950=60732
sort_loop counter: 33
0=88
50=3811
100=6423
150=9794
tpin1=1 tpin2=0 tpin3=0
GPIO_loop counter: 5
200=12413
250=16173
300=19313
350=23311
400=26771
450=30249
500=33728
550=36496
600=40395
650=42909
700=45926
750=48600
800=52329
850=55344
900=58750
950=61537
sort_loop counter: 34
0=72
50=3646
100=6892
150=10249
200=13834
250=16610
300=19694
350=22818
400=26045
450=29951
500=33002
550=35403
600=38726
650=42263
700=45620
750=49044
800=52093
850=55443
900=59079
950=62274
sort_loop counter: 35
0=31
50=3142
100=6435
150=9944
200=12891
250=15256
300=18262
350=21185
400=23906
450=27481
500=31161
550=34402
600=37642
650=41306
700=44539
750=47298
800=50364
850=54413
900=57671
950=61519
sort_loop counter: 36
0=50
50=3153
100=6587
150=8796
200=11687
250=15092
300=19257
350=22800
400=25969
450=29183
500=32539
550=36620
600=40852
650=43557
700=46519
750=49473
800=52333
850=55237
900=59164
950=61924
sort_loop counter: 37
0=100
50=2720
100=5802
150=9246
200=12239
250=14888
300=17778
350=20814
400=23873
450=27148
500=30690
550=33762
600=38272
650=40900
700=43896
750=47422
800=50635
850=54162
900=57805
950=61711
sort_loop counter: 38
0=48
50=3587
100=6313
150=9571
200=12908
250=16586
300=19556
350=22745
400=25697
450=28761
500=32203
550=35521
600=38277
650=42362
700=46539
750=49429
800=52880
850=56087
900=59819
950=61937
sort_loop counter: 39
0=31
50=3039
100=6329
150=10899
200=14383
250=17143
300=20356
350=23493
400=26809
450=29980
500=32914
550=35632
600=39095
650=42221
700=46074
750=49772
tpin1=1 tpin2=0 tpin3=0
GPIO_loop counter: 6
800=52953
850=56241
900=59034
950=62053
sort_loop counter: 40
0=56
50=3629
100=6654
150=9381
200=12406
250=16100
300=19585
350=22758
400=25860
450=29489
500=32737
550=35959
600=38986
650=41973
700=45662
750=49048
800=52565
850=55601
900=59183
950=62470
sort_loop counter: 41
0=173
50=3782
100=6682
150=10617
200=13712
250=16162
300=19432
350=22010
400=25606
450=28994
500=32246
550=36011
600=39079
650=42013
700=45532
750=48877
800=52854
850=55738
900=59006
950=62358
sort_loop counter: 42
0=59
50=3165
100=6734
150=9879
200=12713
250=17278
300=21146
350=24763
400=27629
450=30653
500=33302
550=37050
600=41002
650=43729
700=47078
750=49720
800=53084
850=56547
main loop: 2
blinker_loop (LOW) counter: 0
900=59407
950=62392
sort_loop counter: 43
0=2
hier sieht man einigermaßen klar, wie die verschiedenen Threads mit einander verzahnt - asynchron - parallel laufen.
Holomino
11.08.2019, 17:26
Das ist alles schön und gut, aber jetzt mach doch mal bitte Folgendes:
Greif doch mal als zusätzliche Task mit pThread für eine Sekunde einen (von nem Arduino erzeugten) 50kHz-Takt ab. Steht da die Zeitmessung nach 10000 Flankenwechseln zuverlässig auf 1000ms?
Das Teil ist auf bestimmte Anwendungsgebiete ausgerichtet, aber von Multitasking war nicht die Rede. Deswegen hat der so viele AD-Eingänge und Interruptmöglichkeiten an Board.
Meine Meinung.
Das ist alles schön und gut, aber jetzt mach doch mal bitte Folgendes:
Greif doch mal als zusätzliche Task mit pThread für eine Sekunde einen (von nem Arduino erzeugten) 50kHz-Takt ab. Steht da die Zeitmessung nach 10000 Flankenwechseln zuverlässig auf 1000ms?
das war bisher nicht die Aufgabe, die ich zeigen wollte: sehr kurze Aktionen nach festem Zeittakt zu machen
- sondern sehr viele lange Threads ungestört so schnell wie möglich simultan+asynchron, auch wenn einer oder mehrere irgendwann "hängen". Das ist der Grund, weshalb preemptives MT für mich (als Basis-Architektur) unverzichtbar ist.
In DEINEM Falle würde ich ZUSÄTZLICH zum MT einen festen Takt per ESP32-timer programmieren: der läuft dann fest per 50kHz (oder was auch immer), und der Rest läuft trotzdem per MT unabhängig, simultan + asynchron. Dies könnte u.U sowohl per IRQ als auch per high-prio-thread geschehen, wäre aber nicht unbedingt zwingend aufs eine oder andere festgelegt.
Mit Timern alleine aber kriegt man langdauernde Threads per MT + asynchron nicht hin.
Ohne preemptives MT ist der teensy also unbrauchbar für mich, es sei denn, TeensyThread wäre dazu auch imstande (was ich bezweifle, nach allem was ich von Stoffregen gelesen habe); ESP32 und Raspi aber können es (und es sind ja auch darüberhinaus dual- bzw. quad-cores)
PS
wenn du mir hier einen Arduino-kompatiblen (!!) Code postest, wie dein 50kHz Problem zu programmieren ist (ISR mit ESP32-kompatibler Syntax, single-thread), dann kann ich ja mal sehen, wie man das per MT zusätzlich einbinden könnte.
das war bisher nicht die Aufgabe, die ich zeigen wollte: sehr kurze Aktionen nach festem Zeittakt zu machen
- sondern sehr viele lange Threads ungestört so schnell wie möglich simultan+asynchron, auch wenn einer oder mehrere irgendwann "hängen". Das ist der Grund, weshalb preemptives MT für mich (als Basis-Architektur) unverzichtbar ist.
In DEINEM Falle würde ich ZUSÄTZLICH zum MT einen festen Takt per ESP32-timer programmieren: der läuft dann fest per 50kHz (oder was auch immer), und der Rest läuft trotzdem per MT unabhängig, simultan + asynchron. Dies könnte u.U sowohl per IRQ als auch per high-prio-thread geschehen, wäre aber nicht unbedingt zwingend aufs eine oder andere festgelegt.
Mit Timern alleine aber kriegt man langdauernde Threads per MT + asynchron nicht hin.
Ohne preemptives MT ist der teensy also unbrauchbar für mich, es sei denn, TeensyThread wäre dazu auch imstande (was ich bezweifle, nach allem was ich von Stoffregen gelesen habe); ESP32 und Raspi aber können es (und es sind ja auch darüberhinaus dual- bzw. quad-cores)
Naja, die Aufgabe war einen externen Takt zuverlässig zu lesen / Flanken zählen. Dafür wären Hardware-Pulsecounter das Mittel der Wahl. Und das geht mit und ohne MT.
Ansonsten stimme ich dir größtenteils zu, würde es aber so formulieren: Präemptives Multitasking ist kein Muss für jede Aufgabe. Aber für paralleles Abarbeiten von mehreren (rechenintensiven) Aufgaben ist man ohne ziemlich aufgeschmissen. Daher ist der Teensy mit seinen 600Mhz für mich auch erst interessant, wenn er softwaremäßig mit FreeRTOS (dem Quasistandard für MT auf Microcontrollern) kommt. Ob darüber hinaus pThread und std::thread implementiert sind, interessiert mich nur sekundär.
natürlich nicht für jede Aufgabe - wer behauptet das?
Aber für jede Aufgabe braucht man auch keinen M7 oder M4 oder ESP32 und keine single- oder double fpu.
Pinstates habe ich aber selber schon mit Arduino Due und Raspi gelesen (100us bzw. 500ns-1us- Takt), da sehe ich keine Einschränkung - bei preemptivem MT und diesen großen cpus aber sehr wohl (und auf kleineren ntl erst recht).
FreeRTOS ist nur die Basis, auf der ESP32 das std:thread und pthread implementiert hat, analog zu std::thread und pthread auf Linux - Teensy hat da andere, aber entfernt ähnliche Libs wie RTOS.
Mich interessiert hierbei allerdings weder wie Linux funktioniert noch wie RTOS funktioniert, ich nutze nur die reinen C99/C++14 API Libs.
Holomino
11.08.2019, 19:22
PS
wenn du mir hier einen Arduino-kompatiblen (!!) Code postest, wie dein 50kHz Problem zu programmieren ist (ISR mit ESP32-kompatibler Syntax, single-thread), dann kann ich ja mal sehen, wie man das per MT zusätzlich einbinden könnte.
https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
Portabfrage und Zählen in der ISR bekommst Du alleine hin?
https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
Portabfrage und Zählen in der ISR bekommst Du alleine hin?
habe ich noch nie gemacht, weder für ESP32 noch für M4 oder AVRs, besser also du gibts mir fertigen ISR-single-thread-code, ich kann dann versuchen auf MT zu portieren. Wäre aber ein Erstlingswerk für mich, absolut unbekanntes Gelände.
Holomino
11.08.2019, 19:32
Ja, dann trau Dich.
Du musst doch nur den Code kopieren und etwas abändern.
Ja, dann trau Dich.
Du musst doch nur den Code kopieren und etwas abändern.
poste am besten den vollständigen fertigen Code, dann kann ich sehen was man daraus machen kann.
edit:
ich sehe in dem Link nur die if-Abfrage in einer main() loop, ohne weitere zusätzliche Funktionsaufrufe (Rechenfunktionen, GPIO r/w, ...).
Zusätzliche Funktionsaufrufe brauchen aber Rechenzeit, die dann nach if() auf diese weiteren Funktionen verteilt werden kann, bevor die if() Abfrage sich wiederholt.
Wieviel Gesamt-Rechenzeit haben denn die anderen Funktionen zur Verfügung, zwischen 2 if() in aufeinanderfolgenden main() loops?
Hier müsstest du ja dann auch fibonacci, GPIO r/w, sort, Blink und die alte 500ms-delay main loop bei dir mit rein kriegen.
Bei MT müsste dann deine Timerfunktion diese dazwischenliegende Zeit reservieren - ich muss also wissen, wieviel.
ggf 100us?
Das könnte ich probieren...
- - - Aktualisiert - - -
deine Abfrage in loop() würde ich dann ZUSÄTZLICH zu meinen 5 Threads so formulieren:
volatile static int interruptCounter;
volatile static int totalInterruptCounter;
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
void IRAM_ATTR onTimer() {
portENTER_CRITICAL_ISR(&timerMux);
interruptCounter++;
portEXIT_CRITICAL_ISR(&timerMux);
}
std::thread *thread_1;
std::thread *thread_2;
std::thread *thread_3;
std::thread *thread_4;
std::thread *thread_5;
// meine threads und Hilfsfunktionen 1-4 wie bisher
void timer_loop() {
vTaskPrioritySet(NULL,4);//set Priority
Serial.println((String)"\ntimer_loop Current priority :" + uxTaskPriorityGet(NULL)+"\n");
while(true) {
if (interruptCounter > 0) {
portENTER_CRITICAL(&timerMux);
interruptCounter--;
portEXIT_CRITICAL(&timerMux);
totalInterruptCounter++;
Serial.println( (String)"\nAn interrupt as occurred. Total number: " + totalInterruptCounter +"\n");
}
std::this_thread::sleep_for(std::chrono::microseco nds(100));
}
}
void setup() {
Serial.begin(115200);
delay(1000);
timer = timerBegin(0, 80, true);
timerAttachInterrupt(timer, &onTimer, true);
timerAlarmWrite(timer, 1000000, true);
timerAlarmEnable(timer);
thread_1 = new std::thread(blinker_loop);
thread_2 = new std::thread(fibonacci_loop);
thread_3 = new std::thread(sort_loop);
thread_4 = new std::thread(GPIO_loop);
thread_5 = new std::thread(timer_loop);
}
void loop() {
// meine void loop wie bisher
}
Ich habe allerdings überhaupt keine Idee, was
void IRAM_ATTR onTimer() {},
hw_timer_t * timer = NULL;
portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
machen und wie sie funktionieren, genausowenig, was die settings in setup dafür bedeuten - wie gesagt, IRQs habe ich bisher nie benutzt, kann sie also nur 1:1 übernehmen.
Und wie sähe aber dann DEIN Gesamt-Programm aus, in dem du alle Funktionen (meine 5 threads + deinen Timer) gemeinsam unterbringst? Würdest du das überhaupt schaffen? ;)
Holomino
12.08.2019, 07:05
Oh, oh, da klaffen aber Lücken.
Nö, ehrlich gesagt ist da meine Hilfsbereitschaft Dir gegenüber gerade etwas runter. Meinetwegen kannste dumm sterben. Erst dreist werden und dann betteln müssen kommt halt nicht gut.
Ihr scheint nicht wirklich irgendwann mal ein Multitaskingbetriebssystem erstellt und damit dann auch gearbeitet zu haben. Das ist jetzt nicht böse gemeint oder abwertig, aber die Argumente, die hier oft dafür genannt werden, sprechen eigentlich genau dagegen.
In DEINEM Falle würde ich ZUSÄTZLICH zum MT einen festen Takt per ESP32-timer programmieren: der läuft dann fest per 50kHz (oder was auch immer), und der Rest läuft trotzdem per MT unabhängig, simultan + asynchron. Dies könnte u.U sowohl per IRQ als auch per high-prio-thread geschehen, wäre aber nicht unbedingt zwingend aufs eine oder andere festgelegt.
Mit Timern alleine aber kriegt man langdauernde Threads per MT + asynchron nicht hin.
Auf einem Single-CPU-System wird das über Timer gelöst, das ist Standardvorgehen, um dort die verschachtelte Ausführung zu erreichen. Einmal eine Codeumschaltung per Timer zu haben und noch eine oben drauf zu setzen, vernichtet noch mehr Rechenzeit.
Ein kooperatives Multitasking ist für sehr rechenintensive Aufgaben eher das Mittel der Wahl.
Programmabarbeitung im Multithreading bringt mit sich dass, ein Programm auf das andere warten muss. Je öfter eine zeitintensive Aufgabe unterbrochen wird, die erst erledigt sein muss, umso länger warten andere Programmteile. Nicht zwingend ist deswegen ein dauerndes Umschalten der Programmcodes sinnvoll, wo dann auch ständig Register gesichert und wieder hergestellt werden müssen. Solches auf Single-CPUs timergesteuertes Programmwechseln kann das Hauptprogramm daher wesentlich verlangsamen. Mit kooperativem Verhalten erreicht man auf Single-CPU-Systemen eigentlich genau das, was benötigt wird. Ein schnelles Abarbeiten der einzelnen Aufgaben nebeneinander, wobei das Ergebnis möglichst schnell zur Verfügung steht.
Einen Punkt kann man gelten lassen:
Wenn fest steht dass, dauernd Aufgaben nebeneinander her laufen, die keinen Leerlauf beinhalten. Also beispielsweise 5mal derselbe Programmcode nebeinander ausgeführt wird. Aber dafür ist die sequentielle Abarbeitung besser geeignet, da schneller, weil hier die eingestreuten Taktzyklen fehlen, die für Dinge benötigt werden, die nicht dem Hauptzweck entsprechen.
Auf jeden Fall sollte man sich damit erst einmal im Detail grundlegend auseinandersetzen bevor man meint, man könnte auf etwas nicht verzichten. Sonst bleibt nur, die Nachteile mit noch mehr MHz zu erschlagen.
MfG
@Moppi:
du hast auch echt nicht verstanden, worum es eigentlich geht. Lies noch mal oben alles genau nach und versuche mal selber mit einem "hängenden Thread" bei einem kooperativen MT Programm heraus zu kommen. Was du schreibst, entbehrt wirklich jeglicher Grundlage.
Ich arbeite seit 20 Jahren mit Multithreading-Programmen auf single- und multicore-cpus, auch mit kooperativen, danach aber überwiegend mit preemptiven und selbstverständlcih inzwischen auch mit Linux (multiuser-mulititasking OS). ich glaube, DU hast keine Ahnung von Multithreading-Programmierung, insbesondere nicht mit preemptiver.
Holomino aber schießt mal wieder den Vogel ab:
Oh, oh, da klaffen aber Lücken.
Nö, ehrlich gesagt ist da meine Hilfsbereitschaft Dir gegenüber gerade etwas runter. Meinetwegen kannste dumm sterben. Erst dreist werden und dann betteln müssen kommt halt nicht gut.
Holomino, du bist doch echt ein A******ch - da kommt nun doch wieder deine bekannte beleidigende Trollnatur zum Vorschein.
Ich habe nicht vor, dir deine Programme zu schreiben, ich hatte um nichts "gebettelt" und ich hatte nicht vor, dich um irgendeine "Hilfsbereitschaft" zu bitten
DU warst es, der wollte, dass ich deinen Code in meinen integriere - ich hatte lediglich deinen von dir verlinkten Code portiert und in mein voriges MT-Programm integriert, um zu zeigen dass es grundsätzlich geht.
Bei mir selber für meine Zwecke stehen keine Timer zur Debatte, sondern nur teilweise landauernde, asynchron parallel laufende Threads mit unterschiedlicher Priorität, das hatte ich bereits vorher eindeutig klargestellt.
Du warst es andererseits, der behauptet hatte, er käme ganz ohne MT für das gesamte Programm aus - nur zeigen hast du es nicht können, hast wohl den Mund gehörig zu voll genommen.
deine bekannte beleidigende Trollnatur zum Vorschein
Du merkst nicht wie undankbar deine art zu schreiben ist ... jemand macht die einen Vorschlag für einen alternativen Weg und von dir kommt A) eine Abwertende Bemerkung dass deine Lösung soweiso besser ist oder B) sofort die Frage nach compile fertigem Code ... wenn das nicht Trollig ist, ist es mindestens Uneinsichtig
Du provozierst mit deiner Art solche Reaktionen und bist dir dessen scheinbar noch nicht mal bewusst. Aber du nutzt die Reaktion um deinen Standpunkt zu verteidigen.
Skank Hunt (Southpark) wäre echt stolz auf dich. Das wäre genau seine Methode, Leute mit abwertenden Komentaren in eine explodierende Diskussion locken und dann mit dem Finger auf sie zeigen.
Ihr scheint nicht wirklich irgendwann mal ein Multitaskingbetriebssystem erstellt und damit dann auch gearbeitet zu haben. Das ist jetzt nicht böse gemeint oder abwertig, aber die Argumente, die hier oft dafür genannt werden, sprechen eigentlich genau dagegen.
...
Auf jeden Fall sollte man sich damit erst einmal im Detail grundlegend auseinandersetzen bevor man meint, man könnte auf etwas nicht verzichten. Sonst bleibt nur, die Nachteile mit noch mehr MHz zu erschlagen.
Zwei Semester Betriebssysteme und ein Semester Echtzeitsysteme reichen nicht? Du vermutest hier ziemlich ins Blaue.
Und was meinst du mit Hauptprogramm? Auf dem Esp32 'endet' die main() im Scheduler, loop() ist nur eine Task.
[Im Folgenden beziehen sich die Aussagen Multitasking betreffend auf FreeRTOS]
Der einzige Nachteil der Nutzung eines präemptiven Multitaskings, den ich sehe, ist, dass auch wenn nur eine Task mit der gerade höchsten aktiven Priorität läuft, sie trotzdem im Scheduler-Takt unterbrochen wird, um zu sehen, ob eine andere Task dran ist. Wenn einem diese kleine Unterbrechung nicht passt, kann man den Scheduler suspenden oder einen kritischen Bereich definieren.
Wenn ich Nebenläufigkeit mit Zeitscheiben will, gebe ich den entprechenden Tasks eine gleiche Priorität, sonst nicht.
Und ich behaupte nicht, nicht auf etwas verzichten zu KÖNNEN, sondern zu WOLLEN. Es ist am Ende eine Frage des Entwicklungszeit. Ich will das Rad nicht jedesmal neu erfinden. Oder mein Design umstellen, wenn ich merke, dass ich Nebenläufigkeit mit Zeitscheiben brauche. Ich will eine API, die ich kenne, und deren Funktionalität getestet und dokumentiert ist.
Wie gesagt: Wenn ich das Multitasking nicht brauche, oder es stört, schalte ich sie aus.
Und das Vorhandensein / die Nützlichkeit von Queues, Semaphoren, Software-Timern, Gruppenevents etc. in diesem Kontext habe ich noch nicht einmal erwähnt... Alles Dinge, die man für gutes Design von System mit Nebenläufigkeit braucht.
@Ceos:du kannst auch nur immer dieselben hohlen und bornierten Statements wiederholen - ich war nicht derjenige, der hier von vornherein beleidigend war - das war eindeutig Holomino.
Mein Statement war lediglich: für MICH ist preemptives MT unverzichtbar.
Wie gesagt: Wenn ich das Multitasking nicht brauche, oder es stört, schalte ich sie aus.
genau so sehe ich es auch.
Viele meiner Programme laufen im single-task mode.
Aber von einer leistungsfähigen cpu erwarte ich, dass sie AUCH eine API für preemptives MT bietet, und "leistungsfähig" beginnt für mich bei ARM Cortex (M0/M3, spätestens M4).
Den Ansatz Threads zu nutzen ist Verschwendung von Controller Peripherie, da kann man auch einen ARM ohne großartig Peripehrie mit hoher Taktzahl nehmen.
Eine Aufgabe für die man einen 100Mhz+ ARM braucht weil man mit Threads arbeitet um Peripherie damit zu emulieren kann man auch auf einem 32Mhz µC erledigen.
Eine komplizierte Berechnung, welche fast garkeinen Input über Peripherie benötigt auf einem µC zu packen ist ein Layer 8 (erweitertes OSI) Problem.
Die Darstellung von Inhalt auf einem Display und die gleichzeitige Berechnung von komplizierten Parallelen Aufgaben teilt man dann einfach am besten auf, ein 100+MHZ ARM mit Threads der einen ATTiny oder Mega oder XMega mit grafischen Befehlen versorgt der dann seine ganze reiche Peripherie dafür aufbringt und die begrenzte Rechenzeit der CPU zum organisieren und kommunizieren nutzt.
die Eier legende Wollmilchsau ist der dritte Weg, aber nur wenn man beide Parts nutzen kann auch wirklich Sinnvoll. Das war zumindest der Kern meiner Aussagen.
by the way
ich sehe schon, ihr versteht teilw (?) nicht den Sinn und die Vorteile von preemptivem MT.
war der Punkt an dem du deine Lösung mal wieder über die Lösung anderer gestellt hast was der Kern meines letzen Post war ...
daraufhin habe ich deiner listenartigen typischen Ansprüche genüge getan und erklärt wie ich in meinem Fall damit umgehe und selber behauptet dass meine Lösung besser als deine ist (das war anmaßend, gebe ich zu, aber deine Art triggert mich immer so)
Abschließend hatte ikch argumentiert dass es eine Frage der Problemstellung ist und jede Art ihre Vor- und Nachteile hat
aber dich interssierte auch nach der Argumentation anderer nur dass deine Lösung überlegen wäre indem du Situationen kontruierst die es nur bei dir gibt. Ich muss keinen "hängenden Thread preemtiv verlassen" (wobei das mit der Timer Lösung eigentlich sehr eindeutig regelbar ist) weil es bei mir keine hängenden Prozesse gibt! Eine ordentlich geschriebene Statemachine ist DETERMINISTISCH, d.h. zu jedem Zeitpunkt stabil udn man weis immer wo man sich befindet und es gibt keine unerwarteten Situationen.
Alles unerwartete ist ein Programmierfehler oder schlechtes Desgin. Wenn man per Design erwartet dass etwas unerwartetes passieren kann, muss man eben CPU Zeit und Deterministisches Verhalten opfern und Threads nutzen.
Den Ansatz Threads zu nutzen ist Verschwendung von Controller Peripherie, da kann man auch einen ARM ohne großartig Peripehrie mit hoher Taktzahl nehmen.
Eine Aufgabe für die man einen 100Mhz+ ARM braucht weil man mit Threads arbeitet um Peripherie damit zu emulieren kann man auch auf einem 32Mhz µC erledigen.
Eine komplizierte Berechnung, welche fast garkeinen Input über Peripherie benötigt auf einem µC zu packen ist ein Layer 8 (erweitertes OSI) Problem.
Die Darstellung von Inhalt auf einem Display und die gleichzeitige Berechnung von komplizierten Parallelen Aufgaben teilt man dann einfach am besten auf, ein 100+MHZ ARM mit Threads der einen ATTiny oder Mega oder XMega mit grafischen Befehlen versorgt der dann seine ganze reiche Peripherie dafür aufbringt und die begrenzte Rechenzeit der CPU zum organisieren und kommunizieren nutzt.
die Eier legende Wollmilchsau ist der dritte Weg, aber nur wenn man beide Parts nutzen kann auch wirklich Sinnvoll. Das war zumindest der Kern meiner Aussagen.
by the way
war der Punkt an dem du deine Lösung mal wieder über die Lösung anderer gestellt hast was der Kern meines letzen Post war ...
daraufhin habe ich deiner listenartigen typischen Ansprüche genüge getan und erklärt wie ich in meinem Fall damit umgehe und selber behauptet dass meine Lösung besser als deine ist (das war anmaßend, gebe ich zu, aber deine Art triggert mich immer so)
Abschließend hatte ikch argumentiert dass es eine Frage der Problemstellung ist und jede Art ihre Vor- und Nachteile hat
aber dich interssierte auch nach der Argumentation anderer nur dass deine Lösung überlegen wäre indem du Situationen kontruierst die es nur bei dir gibt. Ich muss keinen "hängenden Thread preemtiv verlassen" (wobei das mit der Timer Lösung eigentlich sehr eindeutig regelbar ist) weil es bei mir keine hängenden Prozesse gibt! Eine ordentlich geschriebene Statemachine ist DETERMINISTISCH, d.h. zu jedem Zeitpunkt stabil udn man weis immer wo man sich befindet und es gibt keine unerwarteten Situationen.
Alles unerwartete ist ein Programmierfehler oder schlechtes Desgin. Wenn man per Design erwartet dass etwas unerwartetes passieren kann, muss man eben CPU Zeit und Deterministisches Verhalten opfern und Threads nutzen.
Wieder nur hohles Gerede, ohne Nachweis durch Code und Fakten.
mach doch einfach mal mein Programmbeispiel (eine Simulation), das ich oben gepostet habe, mit deinen Methoden nach.
https://www.roboternetz.de/community/threads/73884-Der-Teensy-4-0-ist-fertig?p=654263&viewfull=1#post654263
Ich bin gespannt, wie weit du kommst.
Statemachines aber sind das unterste Ende von Programmiersprachen-Grammatiken, für simpeltste Anwendungen. Wenn dir das reicht, ok, dann brauchst du keine höheren Grammatiken und/oder Architekturen.
Ich habe schon mitgelesen und viele interessante technische Aspekte gesehen.
Eigentlich ist es Energieverschwendung sich von anderen abheben zu wollen wenn man sich gleichzeitig mit ihnen austauschen möchte. Das ist wohl der interessante nichttechnische Aspekt an der Diskussion.
Ich überlege, dass wenn ich über die Situation und die Beteiligten urteilen will, dann kann ich mich das nächste man nicht unbefangen an anderen Diskussion beteiligen.
Deshalb sollten wir diese Diskussion zum Thema "Der Teensy 4.0 ist fertig" auch erst einmal abschließen.
Vielleicht kann man ja bei Gelegenheit noch mehr praktische Einsatzmöglichkeiten für das System ansprechen.
Wieder nur hohles Gerede, ohne Nachweis durch Code und Fakten.
mach doch einfach mal mein Programmbeispiel (eine Simulation), das ich oben gepostet habe, mit deinen Methoden nach.
Machs dir selbst Herr Dr.
https://www.roboternetz.de/community...l=1#post654263 (https://www.roboternetz.de/community/threads/73884-Der-Teensy-4-0-ist-fertig?p=654263&viewfull=1#post654263)
Ich bin gespannt, wie weit du kommst.
Eine komplizierte Berechnung, welche fast garkeinen Input über Peripherie benötigt auf einem µC zu packen ist ein Layer 8 (erweitertes OSI) Problem.
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.