PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Der Teensy 4.0 ist fertig



Mxt
09.08.2019, 12:10
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.

HaWe
09.08.2019, 12:34
tolles Teil, zweifellos - lässt nur noch wenige Wünsche offen...

Ceos
09.08.2019, 12:57
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!!!

Mxt
09.08.2019, 13:09
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

Ceos
09.08.2019, 13:10
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*

Mxt
09.08.2019, 13:27
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.

HaWe
09.08.2019, 14:19
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) ?

Mxt
09.08.2019, 16:48
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.

HaWe
09.08.2019, 17:09
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).

Mxt
09.08.2019, 18:02
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.

HaWe
09.08.2019, 19:03
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.

Sisor
10.08.2019, 08:19
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)).

HaWe
10.08.2019, 11:08
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();
}

Klebwax
10.08.2019, 23:05
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

Ceos
11.08.2019, 10:20
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.

HaWe
11.08.2019, 11:22
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));
}
}

Ceos
11.08.2019, 11:54
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

HaWe
11.08.2019, 11:59
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, 12: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)

HaWe
11.08.2019, 12:54
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, 13:05
Na? Fühlt sich da jemand angesprochen?

HaWe
11.08.2019, 13:09
Na? Fühlt sich da jemand angesprochen?

von deinem saudummen, hohlen Geschwätz?
Da sollte sich jeder angesprochen fühlen.

Holomino
11.08.2019, 13:11
Oh, fachlich am Ende? Jetzt geht es unter der Gürtellinie weiter?

Reg Dich ab, Mann.

HaWe
11.08.2019, 13:17
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, 14: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.

HaWe
11.08.2019, 15:03
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, 16: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?

Moppi
11.08.2019, 16:37
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.

HaWe
11.08.2019, 17:14
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.

Sisor
11.08.2019, 17:44
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.

HaWe
11.08.2019, 17:54
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, 18: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?

HaWe
11.08.2019, 18:27
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, 18:32
Ja, dann trau Dich.
Du musst doch nur den Code kopieren und etwas abändern.

HaWe
11.08.2019, 19:58
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, 06: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.

Moppi
12.08.2019, 06:32
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

HaWe
12.08.2019, 08:05
@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.

Ceos
12.08.2019, 08:15
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.

Sisor
12.08.2019, 08:20
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.

HaWe
12.08.2019, 08:36
@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).

Ceos
12.08.2019, 08:59
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.

HaWe
12.08.2019, 09:19
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.

Manf
12.08.2019, 09:22
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.

Ceos
12.08.2019, 09:24
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.