Moin,
der Code meines Bastelprojektes (GPS Logger für Auto) wächst und wächst
und leider auch die Probleme. Über die Geschichte mit dem NVIC habe ich
mir nämlich bisher keine gedanken gemacht und gebe zu, dass ich ihn auch
nicht wirklich verstehe, was diese Geschichte mit den Prioritäten
angeht. Ich merke nur, dass die CPU so langsam an ihre Grenzen kommt,
die LED für den Timer 3 1s Takt wird schon immer unruhiger, weil der
Interrupt zu oft verdrängt oder unterbrochen wird. DenBetrieb mit 12Mhz
wegen der Batterieversorgung kann ich jedenfalls vergessen, aktuell
wieder auf 48Mhz, schluckt gleich 20mA mehr.
Wenn da jetzt noch die SD Karte mit dazu kommt bricht die CPU wohl ganz
in die Knie :-(
Ich habe an Ints
UART1 9600 baud: Da laufen im 1s Takt ca 200 Bytes NMEA Daten ein und
lösen RX_NE und RX_IDLE aus. Bytes werden in einen Ringpuffer
geschaufelt, mehr nicht. Bisher manuell um DMA drücke ich mich noch
herum, da die Datensätze nicht immer gleich lang sind. 9600baud kosten
jedenfalls ne Menge CPU Zeit
RTC: 1s Takt mit Unix Time um die Uhrzeit zu berechnen mit localtime.
Timer 3: 1/10s Takt: Alle 0,5s liest er über I2c den ADXL345 aus, dauert
genau 0,5ms das Auslesen der paar Bytes. 1/10s brauche ich für LED
Blitzen.
Systick: 1/1000 Sekunde, das Teil brauche ich eigentlich gar nicht, ich
benutze den DWT Timer der Debug Unit als Zeitbasis.
Prio 1 muss die UART haben, da sollte nix verloren gehen.
RTC ist eher unwichtig, die zählt eh allein weiter, auf ne Sekunde kommt
es nicht an
Timer 3: Wichtig! 0,5s sind ein erprobtes Raster für die
Bewegungserkennung.
Könnte sich vielleicht der A.K. mal erbarmen da Licht hinein zu bringen,
die ich die Prios der Teile setzen muss? Setze ich die Prio des I2C Ints
auf 15 kommt der jedenfalls kaum mehr zum Zuge. Auf 0 immer aber dann
fehlen Bytes in den UART Sätzen.
1
SysTick_Config(RCC_Clocks.SYSCLK_Frequency/1000);// Systick für 1ms
MaWin schrieb im Beitrag #6631799:
> Ich würde den ganzen Quatsch lassen und einen AVR Tiny13 nehmen und in> Assembler programmieren. Alles andere ist Blödsinn und Zeitverschwendung
C-hater bist dus?
Christian J. schrieb:> 9600baud kosten> jedenfalls ne Menge CPU Zeit
Nein, weil er nur bei einem empfangenen Byte einen IRQ auslöst während
des Empfangens kann die CPU anderes tun.
Die Prios sind relativ straight forward, je niedriger die Nummer desto
mehr Priorität, sprich höher priorisierte IRQ können andere IRQ
unterbrechen.
Alles in allem hast du nichts was den µC wirklich an die Grenze bringt,
das ist alles mehr als human. Ich würde sagen das du irgendwo anders ein
Problem hast.
Kevin M. schrieb:> Alles in allem hast du nichts was den µC wirklich an die Grenze bringt,> das ist alles mehr als human. Ich würde sagen das du irgendwo anders ein> Problem hast.
Nee, sieht grad wüst aus auf dem Schreibtisch. u-center für die GPS
Konfig und den F103 am Debugger in der IDE. Ich habe testweise mal das
UART_IT_ORE Flag (Overrun) auf ne LED gelegt. Ist schon so, dass der
UART Int den Timer 3 voll platt macht, da kommen 3 NMEA Sätze a 82 Bytes
in einem Rutsch. Habe in jedem Int halt ne LED angesteuert, da sieht man
das ganz gut.
Gefühlt kann es natürlich sein, dass der UART int deutlich öfter gefired
wird als ich es sehe. Das Teil hat ja ne Menge Bits im NVIC.
Die ChanFat hängt auch am Systick mit dran bei 1/1000, die braucht das
scheinbar. Und die RTC brauche ich für die Zeitstempel der Dateien. Ist
aber noch nicht aktiviert alles.
Setze ich den Timer 3 auf Prio High geht trotzdem kein Byte mehr
verloren, wenn ich die Baudrate auf 4800 zurücknehme. Das reicht total
aus. Bei 9600 leider sind einige rote LED Blinker dabei.
Ich werde spasseshalber die Sache trotzdem auf DMA umschreiben. Aber
heute nicht mehr .... gähn...
Christian J. schrieb:> Ist schon so, dass der> UART Int den Timer 3 voll platt macht, da kommen 3 NMEA Sätze a 82 Bytes> in einem Rutsch.
Dann sind deine UART-Routinen absoluter Murks.
Zeig doch mal!
9600 Baud ist selbst bei Dauerfeuer wirklich nix, was einen F103 ins
Schwitzen bringen könnte. (Wenn man es richtig macht)
MaWin schrieb im Beitrag #6631799:
> Ich würde den ganzen Quatsch lassen und einen AVR Tiny13 nehmen und in> Assembler programmieren. Alles andere ist Blödsinn und Zeitverschwendung
Wer's mit einem STM32 @12MHz nicht gebacken bekommt, schafft's auch
nicht mit einem AVR8 @8MHz.
Nö, man muss nicht die Hardware wechseln, sondern den Programmierer.
Im Übrigen: Einen ATtiny13 würde ich ganz sicher nicht nehmen, wenn die
Aufgabe ist, über UART, I2C und SPI zu kommunizieren und dabei mit wenig
Energie auszukommen, allerdings ganz sicher auch keinen STM32F103.
Dafür würde ich einen ATtiny814 nehmen. Und, na klar: Assembler.
c-hater schrieb:> Nö, man muss nicht die Hardware wechseln, sondern den Programmierer.
Auch schon deswegen weil er Prioritys nicht korrekt schreiben kann.
"dauert genau 0,5ms das Auslesen der paar Bytes."
Zeig mal deine Routinen. Wenn es 0,5ms am Stück dauert und du da
irgendwo wartest/Zeit verbrätst dann hast du schon dein Problem gefunden
Harry L. schrieb:> Dann sind deine UART-Routinen absoluter Murks.>> Zeig doch mal!
PS: I2C dauert 0,5ms... am Logger gemessen, 6 Bytes holen bei 200khz
Takt.
Christian J. schrieb:> if (ADXL345_Read())> SetBoardLED(ENABLE);
Langsame I2C Komm im Timer 3 IRQ Handler ist sicher keine gute Idee.
Aber bei 9600 Baud für den USART kommt gerade mal ein IRQ jede ms
(1,04ms). Das sollte soviel Luft nach oben lassen, das man die ISR in
der Priorität auch runtersetzen kann.
Christian J. schrieb:> Ich werde spasseshalber die Sache trotzdem auf DMA umschreiben. Aber> heute nicht mehr .... gähn...
Herr lass Hirn regnen. Wem ein UART Interrupt bei 9600baud aus der Bahn
wirft, der sollte ernsthaft anfangen über seinen Code nachzudenken und
nicht über die Taktfrequenz der CPU...
Einen Punkt soll/muss man aber noch abprüfen. Manche Interupts können
mehrfach ausgelöst werden, wenn die Interuptroutine so früh verlassen
wird, dass das Reseten der Flags in der Peripherie noch nicht angekommen
ist. Das ist eine Stolperfalle bei der die AVR Jünger häufig vom Glauben
abfallen, aber sie existiert.
Christian J. schrieb:> Wenn da jetzt noch die SD Karte mit dazu kommt bricht die CPU wohl ganz> in die Knie
Wenn du eine SD Karte intensiv nutzt, brauchst du dir um die
Stromaufnahme des Mikrocontroller keine Gedanken mehr machen, weil die
SD Karte mehr brauchen wird. Da sind Werte um 200mA durchaus normal.
Die Auflistung deiner Interrupts klingt nach wenig Last. Untersuche mal,
wo dein Programm die meiste Zeit verbringt, vermutlich in Wartschleifen
für I/O.
Du könntest jeder ISR einen Ausgang zuweisen, denn du am Anfang auf High
und am Ende wieder auf Low setzt. An diese Ausgänge schließt du dann
einen Logic Analyzer oder ein Oszilloskop an, dann siehst du sofort, wo
die meiste Zeit drauf geht.
Matthias S. schrieb:> Aber bei 9600 Baud für den USART kommt gerade mal ein IRQ jede ms> (1,04ms). Das sollte soviel Luft nach oben lassen, das man die ISR in> der Priorität auch runtersetzen kann.
So wie sich das darstellt wird der Int ununterbrochen aufgerufen bis das
IDLE kommt. Da stimmt nochwas nicht. Es kann echt sein, dass da das
gleiche Problem auftaucht, wie vor einigen Monaten mal mit dem Togglen
von Pins: Set und Reset liefen im Debugger durch aber nicht mehr in der
optimierten Release Version. Nicht, weil der Code wegoptimiert wurde,
was wegen der volatile Dekl. aller Register eh nicht passiert sondern
weil das Set gar nicht ankam und sofort vom reset plattgemacht wurde.
Ich habe damals Befehle wie _DMB etc eingefügt, die dafür wohl gemacht
worden sind.
Checke das heute abend mal mit einem Counter in der ISR.... 9600 sind
echt nicht viel, so ein blöder Arduino packt ja schon 115.000.
Stefan ⛄ F. schrieb:> Die Auflistung deiner Interrupts klingt nach wenig Last. Untersuche mal,> wo dein Programm die meiste Zeit verbringt, vermutlich in Wartschleifen> für I/O.>> Du könntest jeder ISR einen Ausgang zuweisen, denn du am Anfang auf High> und am Ende wieder auf Low setzt. An diese Ausgänge schließt du dann> einen Logic Analyzer oder ein Oszilloskop an, dann siehst du sofort, wo> die meiste Zeit drauf geht.
Stefan, Du bist echt die Sonne dieses Forums! Einfach mal ein Lob für
deine fundierten Antworten und auch deine klasse Webseite, die zu meinen
Stammseiten gehört neben der von Diller.
Bevor ich hier frage studiere ich natürlich fremden Code im Netz. Leider
sind auch diese Code of sehr fehlerhaft, und sei es nur UART1 in der
Init aber UART3 als ISR... da fragt man sich schon ob derjenige das
jemals am Laufen hatte oder einfach nur kompiliert und hochgeladen.
Viele ISR haben am Anfang, so wie meine Timer 3 einen Müllsammler. Raus
bei allen False Positives und nur rein bei meinen INTS. Das erinnert
mich etwas daran Arrays 1 größer als nötig zu machen... nur als Vorsicht
damit man bloss die Grenzen nicht überschreitet. for;i<x; i++... ist i
nun als letztes x-1 oder x? Oder doch sogar x+1?
Default sind ja alle Ints deaktiviert aber trotzdem scheine sich einige
nicht darauf zu verlassen.
Christian J. schrieb:> Das erinnert mich etwas daran Arrays 1 größer als nötig zu machen
Ich sage mal so: Wenn du zu viele Daten in ein Array schreibst, dann
können das durchaus auch mehr als 1 Byte sein. Dagegen kann dich die
Programmiersprache C nicht schützen.
user934394 schrieb:> Effizienter gehts kaum noch ...
Kenne ich, habe einiges vom dem benutzt früher, vor allem Grafik für den
F429 Disco. Tolle Ausarbeitung über die Uart und DMA. Aber auch sehr
viele Fälle, die es zu berücksichtigen gilt. Ich versuche es erstmal
selbst ohne DMA und halte es klein. Verstehe dafür alles und laufe in
jede Falle selbst rein.
Christian J. schrieb:> /* Clear IRQ Flag */> TIM_ClearITPendingBit(TIM3, TIM_IT_Update);> }
Das taucht wiederholt in der ISR auf, wobei es am Ende der ISR voll
daneben ist. Deine TIM3-ISR ruft unbekannte Funktionen auf und ist ganz
schlecht strukturiert.
Da kann man keine Laufzeit abschätzen.
m.n. schrieb:> Das taucht wiederholt in der ISR auf, wobei es am Ende der ISR voll> daneben ist. Deine TIM3-ISR ruft unbekannte Funktionen auf und ist ganz> schlecht strukturiert.
Was genau stört da? Es wird ein I2C Leseprozess aufgerufen und ein paar
LEDs.
Zudem ein paar RETFI mit Flag Bereinigung. Hätte auch if-then-else draus
machen können. RETFI ist aber nicht unüblich. Packt der Compiler.
Zeit genug ist dafür da. Klar, kannste auch im Main die Lesungen machen,
wenn ein Flag gesetzt wird vom Ints, viele Wege führen nach ROM. I2C
kann beliebig unterbrochen werden.
Darüber hinaus wird jeder INT, der nicht ein Reload ist sofort
rausgeworfen. (könnte ja sein...) Und am Ende lösche ich das Pending
Flag... sehe da jetzt die Bäume nicht. Und was ist da "ganz schlecht"?
ISR die Peripherie auslesen sind ja keine Seltenheit.
Kläre mich mal auf.
Christian J. schrieb:> Moin,>> der Code meines Bastelprojektes (GPS Logger für Auto) wächst und wächst> und leider auch die Probleme. Über die Geschichte mit dem NVIC habe ich> mir nämlich bisher keine gedanken gemacht und gebe zu, dass ich ihn auch> nicht wirklich verstehe, was diese Geschichte mit den Prioritäten> angeht. Ich merke nur, dass die CPU so langsam an ihre Grenzen kommt,> die LED für den Timer 3 1s Takt wird schon immer unruhiger, weil der> Interrupt zu oft verdrängt oder unterbrochen wird. DenBetrieb mit 12Mhz> wegen der Batterieversorgung kann ich jedenfalls vergessen, aktuell> wieder auf 48Mhz, schluckt gleich 20mA mehr.
Wenn der Stromverbrauch ein Problem werden sollte, dann kannst Du Dir da
recht einfach Erleichterung verschaffen:
Anstelle des STM32F103 nimmst Du einen STM32F411, den gibt es auch als
xxxPill.
Der 411 nimmt bei 100MHz weniger als die Hälfte des Stroms auf, den ein
103 bei 72MHz aufnimmt.
Christian J. schrieb:> Was genau stört da? Kläre mich mal auf.http://stefanfrings.de/stm32/stm32f1.html#ivektoren
"Innerhalb der ISR muss man das Flag auch zurück setzen, aber ein
bisschen früher als ganz zum Schluss!"
Weil sonst die nächste Flanke nicht mehr zuverlässig erkannt wird. Denn
bis der zurücksetzen-Befehl im Interruptcontroller ankommt, dauert es
ein paar Takte.
Dr. MCU schrieb:> Anstelle des STM32F103 nimmst Du einen STM32F411, den gibt es auch als> xxxPill.https://blog.adafruit.com/2021/03/05/new-product-stm32f411-blackpill-development-board
Seufz.... bloss gibt es für den keine StdPeriph Libs mehr, da die schon
total veraltet sind. Alles nur noch mit HAL... und für Hobby... naja,
der Umstieg ist nicht so die Welt, ich schreibe oft HAL Sachen fix um,
liest sich ja vieles sehr gleich.
Der Druck wächst... hoffe die neue EmBitz 2.0 Version wird die HAL mit
drin haben, bisher muss man die manuell dazu fügen und auch CMSIS
austauschen. Ich frickel das auch manuell zusammen, da die eingebaute
SPL nicht die letzte ist, die es gab.
Stefan ⛄ F. schrieb:> Weil sonst die nächste Flanke nicht mehr zuverlässig erkannt wird. Denn> bis der zurücksetzen-Befehl im Interruptcontroller ankommt, dauert es> ein paar Takte.
Weist du zufällig, ob man da mit dem Data Memory Barrier Befehlen
weiterkommen könnte? Die sind ja sehr tief in der Hardware wirksam, zu
tief für jemanden, der nicht mit dem Teil ins Bett geht.
Christian J. schrieb:> Weist du zufällig, ob man da mit dem Data Memory Barrier Befehlen> weiterkommen könnte?
Sie wurden mir damals empfohlen, als ich das Problem hatte, dass Flanken
nicht erkannt wurden und dadurch die ganze Kommunikation stecken blieb.
Ich habe sie aber nicht ausprobiert, sondern mich an Beispielen von ST
orientiert, wo die Flags immer echt früh in der ISR zurück gesetzt
werden.
Christian J. schrieb:> Gefühlt kann es natürlich sein, dass der UART int deutlich öfter gefired> wird als ich es sehe. Das Teil hat ja ne Menge Bits im NVIC.
Wie sich Interrupts "gefühlt" verhalten ist irrelevant. Wichtig ist, was
wirklich passiert ;-)
Es wurde bereits der Weg über einen IO angesprochen, der beim Eintritt /
Verlassen der ISR toggelt. Ein Debugger sollte das aber auch ohne den
Umweg über einen GPIO können, sofern man beim STM32F103 SWD+SWO als
Debug-Interface nutzt.
Stichwort: Timeline, bzw. Interrupt Log
z.B.
https://www.iar.com/knowledge/learn/debugging/interrupt-logging/https://www.segger.com/products/development-tools/systemview/
SystemView scheint eine Instrumentierung des Codes zu benötigen aber
eventuell gibt es auch eine Alternative von Segger, die Interrupts und
deren Timing ohne zusätzlichen Code zeigt. Hier könnte Til S.
wahrscheinlich mehr Licht ins Dunkel bringen...
Gruß,
Michael
Christian J. schrieb:> Dr. MCU schrieb:>>> Anstelle des STM32F103 nimmst Du einen STM32F411, den gibt es auch als>> xxxPill.>> https://blog.adafruit.com/2021/03/05/new-product-stm32f411-blackpill-development-board> Seufz.... bloss gibt es für den keine StdPeriph Libs mehr, da die schon> total veraltet sind.
Stimmt überhaupt nicht. Die 401er und 411er arbeiten hervorragend mit
den StdPeriph Libs aus Embitz 1.x.
Beispiel: WordClock mit WS2812. Diese SW arbeitet sowohl mit
STM32F103, STM32F401 und STM32F411. Alles kompiliert mit EmBitz.
Übrigens findest Du in der SW auch UART-Treiber, für die auch 115200 Bd
auch ein Kinderspiel sind. Fifos sind selbstverständlich integriert.
MaWin schrieb im Beitrag #6631799:
> Ich würde den ganzen Quatsch lassen und einen AVR Tiny13 nehmen und in> Assembler programmieren. Alles andere ist Blödsinn und Zeitverschwendung
Was soll das, Mustermann? Jetzt auch noch als MaWin posieren geht nun
wirklich zu weit. Keiner glaubt, dass MaWin so blöd ist.
Michael F. schrieb:> SystemView scheint eine Instrumentierung des Codes zu benötigen aber> eventuell gibt es auch eine Alternative von Segger, die Interrupts und> deren Timing ohne zusätzlichen Code zeigt. Hier könnte Til S.> wahrscheinlich mehr Licht ins Dunkel bringen...
Ja, richtig, für SystemView muss der Code instrumentiert sein was aber
jetzt nicht das Problem sein sollte. Das embOS ist zum Beispiel bereits
instrumentiert, so das in der Timeline alle embOS API Aufrufe und
Interrupts sichtbar sind. Wäre eine Überlegung embOS in dem Projekt
einzusetzen. Das vereinfacht die ganzen Timing Probleme weil man
Aufgaben in Tasks oder Software Timer auslagern kann.
Ansonsten bin ich da eher old school und benutze auch gerne Port Pins
und das Oszilloskop.
Der NVIC des Cortex-M mit den ganzen Prioritäten kann schon verwirrend
sein aber ist eigentlich nicht so kompliziert. Dazu gibt es haufenweise
gute Artikel online.
Bastian schrieb:> Keiner glaubt, dass MaWin so blöd ist.
Ich schon.
Christian J. schrieb:> Weist du zufällig, ob man da mit dem Data Memory Barrier Befehlen> weiterkommen könnte?
MaWin schrieb im Beitrag #6631799:
> Ich würde den ganzen Quatsch lassen und einen AVR Tiny13 nehmen> und in> Assembler programmieren. Alles andere ist Blödsinn und Zeitverschwendung
Full ACK, nur dass ich einen Atmega8 nehmen würde.
m.n. schrieb:> __ISB();
Instruction Synchronization Barrier flushes the pipeline in the
processor,
so that all instructions following the ISB are fetched from cache or
memory, after the instruction has been completed
Und damit läuft das Moped?
Christian J. schrieb:> m.n. schrieb:>> __ISB();>> Und damit läuft das Moped?
Na klar. Du brauchst das nur an möglichst vielen, beliebig gewählten
Stellen im Code einzusetzen.
LOL
Ok, das Problem dürfte gefunden sein:
Keine 2s Sekunden nach Start zeigte ein volatile Zähler 32 Bit im UART
ISR diesen Wert an, der schoss nur so hoch.
Ok, haben wir was zu suchen.... kein Wunder dass die CPU für nichts
anderes mehr Zeit hat.
PS: Übeltäter ist die Sektion für UART_RX_IDLE, die wird dauernd
angesprungen, RX und ORE normal, bzw. letzteress gar nicht. Kaum enabled
geht es schon los und bleibt auch auf Dauerfeuer.
https://community.st.com/s/question/0D50X00009XkfxzSAB/idle-interrupt-on-stm32f0-fires-when-enabling-it
Gibt noch sehr viel mehr über dieses Problem.
Ok, erledigt, alles klappt jetzt. Für die Nachwelt.. sind wohl schon
etliche drauf reingefallen.
Da fast alle anderen Bits dieses Registers auch so gelöscht werden
klappt es auch mit den beiden Readout am Ende der Routine. Lässt man die
restlichen 3 Zeilen weg klappt es immer noch. Denn ClearPendingBit hat
nur wenige zulässige Flags und die sind es nicht. Mein Fehler, wieder
was im Netz abgeschrieben ohne es geprüft zu haben :-(
USART1->SR;
USART1->DR;
USART_ClearITPendingBit(USART1, USART_IT_IDLE);
USART_ClearITPendingBit(USART1, USART_IT_ORE_RX);
USART_ClearITPendingBit(USART1, USART_IT_RXNE);
Christian J. schrieb:> Ok, erledigt, alles klappt jetzt. Für die Nachwelt.. sind wohl schon> etliche drauf reingefallen.
Tja, es hat schon Vorteile, das DB eines µC zu lesen, bevor man ihn
verwendet. Das gilt völlig unabhängig vom konkreten µC...
PS: Bevor ich es vergesse: Ich reagiere grundsätzlich nicht mehr auf
"Gastkommentare", da diese fast immer zu 99% Müll sind, lese sie nicht
einmal mehr. Nicht unhöflich gemeint, nur halt Mülltrennung.
Christian J. schrieb:> PS: Bevor ich es vergesse: Ich reagiere grundsätzlich nicht mehr auf> "Gastkommentare", da diese fast immer zu 99% Müll sind, lese sie nicht> einmal mehr. Nicht unhöflich gemeint, nur halt Mülltrennung.
So what. Andere (weniger zur Realitätsverweigerung veranlagte) lesen es.
Und nehmen dann vielleicht tatsächlich den ATtiny814 (oder besser 1614,
wenn SD-Cards in's Spiel kommen). Und stellen fest: absolut kein Problem
und viel weniger Energiebedarf als ein STM32F103...
Sogar schon in C und erst recht in Assembler...
Soviel zum Thema: 99% Müll...
Christian J. schrieb:> Nicht unhöflich gemeint, nur halt Mülltrennung.
Ganz schön unverschämt!
Zur Müllvermeidung solltest Du hier besser keine Fragen mehr stellen.