Hallöchen, Ich programmiere seit längerem kleinere Microcontroller-Projekte hauptsächlich mit Arduino. Ich kenne mich nicht so wirklich gut mit der genauen Funktion aus, aber so wie ich es verstanden habe, geht es bei den AT-Megas und ESP32/8266 nur mit einer Loop schleife. Nun habe ich mich etwas mit STM32 beschäftigt, und bin auf interesannte Punkte gestossen. Beim SMT32 können ja Funktionen "selbständig" etwas machen, wie z.b. der ADC muss nicht dauernd abgefragt werden, sondern befüllt selbständig Variabeln. Auch beim ändern eines Pin-Levels kann eine Funktion direkt aufgerufen werden. Da diese STM32 ja sehr viele Interrupt-Pins haben (z.b. 15 Stück statt 1-2 beim AT-Mega) habe ich mich gefragt, ob es nun theoretisch möglich wäre, ein komplettes Programm ohne Loop und völlig ohne Zusammenhang zu erstellen. Also das wenn z.b. der "Button 1" gedrückt wird, führt dieser seinen zugewiesenen Code aus. Die anderen Button wissen davon z.b. garnichts. Wäre soetwas möglich? Also z.b. eine Uhr oder eine Sensorauswertung komplett ohne Loop? Und falls ja, kann mir jemand erklären, was in der Zeit wo "nichts" gemacht wird mit dem CPU passiert? Steht er still? Braucht er gleich viel Energie wie wenn er im Loop läuft? Hoffentlich habe ich verständlich erklärt was ich meine. Grüsse Janosch
Du kannst den / fast jeden µC auch nach einer Aktion in den Sleep oder Stop setzen. Dann sinkt die Stromaufnahme je nach µC auf fast 0. Die Loop musst Du trozdem rein machen, aber sie steht dann praktisch immer.
Janosch schrieb: > was in der Zeit wo "nichts" > gemacht wird mit dem CPU passiert? Steht er still? Braucht er gleich > viel Energie wie wenn er im Loop läuft? Es gibt keine Befehl damit der Proccesor dauerhaft stillsteht. Was du vermutlich meinst ist wenn due in C-Programierst quasi die main() zu verlassen. Das ist in der Regel undefiniertes verhalten. Von einfach wieder von vorne anfangen, einen Reset durchführen, sich solange im Speicher verlaufen bis was schlimmerse passiert, kann alles sein. Da must du einen genauen Blick in deinen Startupcode (ja, es gibt sowas wie eine leben vor der main:-) werfen um das abzuschätzen. Bei ARM nehme ich als Funktionsrumpf gerne sowas (in Pseudocode)
1 | main() |
2 | {
|
3 | Installiere_alles_moegliche(); |
4 | |
5 | do
|
6 | {
|
7 | if (tuewas_eins_flag) |
8 | {
|
9 | tuewas_eins(); |
10 | tuewas_eins_flag = 0; |
11 | }
|
12 | if (tuewas_zwei_flag) |
13 | {
|
14 | tuewas_zwei(); |
15 | tuewas_zwei_flag = 0; |
16 | }
|
17 | __wfe (oder __wfi) |
18 | // Schlafen bis zum naechsten Event/interrupt
|
19 | }
|
20 | while (bis zum st. nimmerleis Tag); |
21 | |
22 | }
|
23 | |
24 | irgend_ein_irq() |
25 | {
|
26 | // z.B. alle 100ms um eine Anzeige via main zu aktuallisieren
|
27 | tuewas_eins_flag = 1; |
28 | }
|
Im besten fall schläft die CPU die meiste Zeit energiesparent vor sich hin. Und selbst wenn irgend eine ander Event die "main" quasi mal weckt ohne das eine "tuewas" gesetzt ist, ist das auch Bainbruch weil nach eine paar wenigen Takten gleich wieder weiter geschlafen wird. Janosch schrieb: > wie z.b. der ADC muss nicht dauernd abgefragt werden, sondern > befüllt selbständig Variabeln. Das wäre mir neu Neu. Das ADC weis noch nichtmal was eine Variable ist, der kann keine C:-) Was du wohl meinst ist das der ADC via DMA einen zuvor definierten Bereich im RAM füllen kann (da gibt es auch schönde Events dafür wie zu 50%/75%/100% oder so gefüllt). Auf diesen Speicherbereich kannst du dann natürlich auch von deinem Programm aus zugreifen, du hast ja zuvor selbst festgelegt wo dieser liegt.
Janosch schrieb: > Wäre soetwas möglich? Also z.b. eine Uhr oder eine Sensorauswertung > komplett ohne Loop? Ja, das ist nicht einmal exotisch. Die Loop gibts dann zwar immer noch, aber sie tut nichts als warten. > Und falls ja, kann mir jemand erklären, was in der Zeit wo "nichts" > gemacht wird mit dem CPU passiert? Steht er still? Braucht er gleich > viel Energie wie wenn er im Loop läuft? Die Loop besteht in diesem Fall aus einem Befehl in Schleife, der die Befehlsausführung bis zu einem Ereignis anhält, und den Prozessor ggf in einen Strom sparenden Modus versetzt. Im passenden Modus läuft DMA weiter und Interrupts wecken ihn auf.
:
Bearbeitet durch User
Als Ergänzung noch eine Erklärung zu wfi/wfe: https://community.arm.com/developer/ip-products/processors/f/cortex-a-forum/5695/difference-between-wfi-and-wfe https://www.keil.com/support/man/docs/armasm/armasm_dom1361289926427.htm https://www.keil.com/support/man/docs/armasm/armasm_dom1361289926047.htm
Ein PC macht das übrigens ähnlich, wenngleich etwas weiter entwickelt hinsichtlich Strom sparen. Auch der hat solche eine wartende "Loop", die immer dann zum Zuge kommt, wenn er nichts zu tun hat, Die Idle-Task.
Janosch schrieb: > Wäre soetwas möglich? Also z.b. eine Uhr oder eine Sensorauswertung > komplett ohne Loop? jupp und ist auch Gang und Gebe in der embedded Entwicklung. > Und falls ja, kann mir jemand erklären, was in der Zeit wo "nichts" > gemacht wird mit dem CPU passiert? Steht er still? Braucht er gleich > viel Energie wie wenn er im Loop läuft? grob gesagt gibt es 2 Möglichkeiten. - Endlosschleife (loop) dann verbraucht er eben das was er verbraucht - wait for interrupt (WFI) mode, da ist die CPU in einer Art Standby, schläft und wartet auf einen Interrupt, das spart natürlich Energie, mittlerweile gibt es mehrere standby Stufen, die CPU kann so zu sagen noch tiefer schlafen, das spart zwar noch mehr Energie aber um so tiefer der standby ist desto länger braucht die CPU um wieder auf zu wachen, daher hängt es vom Anwdnungsfall ab wie tief die CPU schlafen kann. Weiterhin können die peripherals noch mehr, manche Busse können eine ganze Nachricht komplett empfangen, im RAM speichern (und das ganz ohne CPU) um dann erst die CPU zu wecken. spannender Ansatz das ganze noch weiter zu treiben ist das Real Time For the Masses Framework (RTFM) (C++ implementierung https://github.com/korken89/crect, rust implementierung https://rtic.rs) Dieses nutzt praktisch das Interrupt System (NVIC) des Microcontroller als einen, in hardware gegossenen, Betriebssytenm (RTOS) Kernel.
In CUBE-MX für einen STM32F303: startup_stm32f303xe.s ... /* Call the application's entry point.*/ bl main LoopForever: b LoopForever der macht alo nach der main() den Loop
Irgendwer schrieb: > ... > Bei ARM nehme ich als Funktionsrumpf gerne sowas (in Pseudocode)
1 | main() |
2 | {
|
3 | Installiere_alles_moegliche(); |
4 | |
5 | do
|
6 | {
|
7 | if (tuewas_eins_flag) |
8 | {
|
9 | tuewas_eins(); |
10 | tuewas_eins_flag = 0; |
11 | }
|
12 | if (tuewas_zwei_flag) |
13 | {
|
14 | tuewas_zwei(); |
15 | tuewas_zwei_flag = 0; |
16 | }
|
17 | __wfe (oder __wfi) |
18 | // Schlafen bis zum naechsten Event/interrupt
|
19 | }
|
20 | while (bis zum st. nimmerleis Tag); |
21 | |
22 | }
|
23 | |
24 | irgend_ein_irq() |
25 | {
|
26 | // z.B. alle 100ms um eine Anzeige via main zu aktuallisieren
|
27 | tuewas_eins_flag = 1; |
28 | }
|
> ...
Es macht keine Sinn, ein von der HW gesetztes "Interruptflag" eine
Interruptroutine aufrufen zu lassen, um darin ein Flag im RAM zu setzen,
das dann in der "Main-Loop" abgefragt wird. Das geht "direkt" einfacher.
Es gibt auch sowas wie RTOS für preemptive Multitasking oder EventQueues für kooperatives Multitasking.
Janosch schrieb: > habe ich mich gefragt, ob es nun theoretisch möglich > wäre, ein komplettes Programm ohne Loop und völlig ohne Zusammenhang zu > erstellen. Warum nicht? while(0){} und danach geht nichts mehr.
Janosch schrieb: > Wäre soetwas möglich? Ja durchaus. Aber das Programm hat dann auch nur wenig Kontrolle darüber, wann es durch andere Programmteile unterbrochen wird. Es ergeben sich komplexe Zusammenhänge, die man als Anfänger gerne unterschätzt. Erfahrene Programmierer meiden diese Methode. > Und falls ja, kann mir jemand erklären, was in der Zeit wo "nichts" > gemacht wird mit dem CPU passiert? Steht er still? In der Regel besteht das Hauptprogramm dann aus einer leeren Endlosschleife. Um Strom zu sparen, kann man die CPU anhalten. Sie wacht dann bei einem Interrupt wieder auf. Trotzdem braucht man eine Hauptschleife.
Schreibfehler. while(1){} es wird nur gemacht, was davor steht. Danach nichts.
:
Bearbeitet durch User
Maxim B. schrieb: > Schreibfehler. > while(1){} > es wird nur gemacht, was davor steht. Danach nichts. Achtung: Streng genommen muss das nicht den gewünschten Effekt haben. In C ist es erlaubt, aber in C++ ist es undefined behavoir und der Compiler darf alles damit machen, was er will. Also z.B. auch die Befehle vor der Schleife weglassen. https://stackoverflow.com/questions/16436237/is-while1-undefined-behavior-in-c
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.