Hallo zusammen,
für ein größeres Projekt benötige ich relativ viel Peripherie meines
STM32F303.
Das Ganze läuft aber nicht so ganz wie es soll.
Das System ist folgendermaßen aufgebaut:
TIM1 erzeugt 6 PWM Signale @ 20kHz
ADC1 und ADC2 laufen im Dualmode
Die ADCs werden werden durch TRGO2 des TIM1 getriggert.
Die gesampelten Werte der beiden ADCs werden durch DMA1_Channel1
abgeholt und in ein Array gespeichert.
Im DMA1_Channel1_IRQHandler Interrupt werden die Daten dann verarbeitet.
Soweit läuft alles perfekt. Die Verarbeitung der Daten im
DMA1_Channel1_IRQHandler Interrupt dauert nicht zu lange und wird lange
vor dem nächsten Interrupt fertig abgearbeitet.
Jetzt möchte ich zusätzlich Daten per USART1 empfangen und versenden.
USART1 ist so konfiguriert, dass empfangene Daten automatisch im
Hintergrund von DMA1_Channel5 abgeholt werden, sprich ich habe keinen
USART Rx Interrupt.
Versendet werden die Daten folgendermaßen:
Versendet werden die Daten aus der while(1) Schleife in der main -
Funktion, also asynchron zu meiner Datenverarbeitung im
DMA1_Channel1_IRQHandler.
Es funktioniert auch alles eine Zeit lang: Es werden PWM Signale
erzeugt, ADC Werte richtig gemessen und der DMA1_Channel1_IRQHandler
Interrupt im richtigen Zeitpunkt ausgeführt und die Kommunikation per
USART1 läuft auch. Alles per Scope nachgemessen.
Wenn die USART Kommunikation allerdings aktiv ist, hört der uC nach
einer unbestimmten, zufälligen Zeit (ca 1 - 120s) auf, den
DMA1_Channel1_IRQHandler Interrupt aufzurufen, sprich der Rumpf des
Interrupts wird irgendwann nicht mehr betreten. Die while(1) Schleife in
der main - Funktion läuft allerdings weiter und die USART Kommunikation
funktioniert weiterhin.
Der "Absturz" des Interrupts erfolgt viel schneller wenn ich per USART
Variablen versende, welche auch im DMA1_Channel1_IRQHandler Interrupt
manipuliert werden. Diese habe ich aber natürlich als volatile
deklariert.
Zu sagen wäre noch, dass der uC mit dem internen RC Glied und PLL @
64MHz läuft. Die Clock habe mit dem von ST gelieferten
"STM32F30x_Clock_Configuration_V1.0.0.xls" konfiguriert.
Als IDE verwende ich CooCox.
Habt ihr allgemeine Ideen, warum das Problem auftritt oder hatte
vielleicht jemand das gleiche Problem?
Viele Grüße
Andreas
Ich glaube aber nicht, dass das das Problem ist. Eher hast du Probleme
mit simultane Zugriff auf globale Variabelen. Sie nur als volatile
deklarieren reicht da nicht aus. Stichworte: critcial section, mutual
exclusion (mutex).
Eric B. schrieb:> Probleme mit simultane Zugriff auf globale Variabelen
Auch wenn ich die Variablen, die im Interrupt bearbeitet werden, im
USART nicht berühre, tritt das Problem auf. Oder kann es trotzdem zu
Problemen kommen?
Eric B. schrieb:> Aber im Mainloop noch mal blockierend warten ist bestimmt Nicht Gut[TM]
Da hast du natürlich recht, das ganze wird später auf state machine
umgestellt :-)
Ich hatte ein ähnliches Problem als ich externe Signale per Interrupt
abgefragt hatte, ein
Timer lief und UART per Interrupt gearbeitet hat. Nachdem UART nicht
mehr über Interrupt lief hatte ich keine Probleme. Ist das eine Option
dies zu testen?
Andreas schrieb:> Jetzt möchte ich zusätzlich Daten per USART1 empfangen und versenden.> USART1 ist so konfiguriert, dass empfangene Daten automatisch im> Hintergrund von DMA1_Channel5 abgeholt werden, sprich ich habe keinen> USART Rx Interrupt.> Versendet werden die Daten folgendermaßen:> ...> Versendet werden die Daten aus der while(1) Schleife in der main
Das ist m.E. ein schlimmer Entwurfsfehler. Wozu soll ein DMA für den
USART-betrieb denn gut sein? Um nicht nur mit dem USART zu tun zu
haben,sondern auch mit dem DMA? Nein, USART Rx und Tx sollen per
Interrupt gefahren werden, wobei der Treiber die asynchron anfallenden
Daten in beiden Richtungen zwischenspeichern muß und der I/O-Verkehr aus
den höheren Schichten der Firmware nur über diese Puffer geht. Der
Interrupt dazu braucht keine hohe Priorität, ich würde ihn eine Stufe
über dem System-Tick ansiedeln. Aber Rx per DMA und Tx per Grundschleife
ist dumm, denn du versaust dir dabei den Status des USART jedesmal.
ist schon komisch: ich hatte doch in den letzten Tagen jemand anderem
nen Komplett-Treiber für die U(S)ART's im STM32F30x gepostet.
W.S.
verarbeitung der Daten im DMA interrupt..
versuche dort mal einen DMA overrun error abzufangen ...
dann würde ich das auch auslagern ...
die ISR gibt nur ein signal zum verarbeiten
Habe ein ähnliches Problem mit dem gleichzeitigen Betrieb von 2
DMA-Kanälen gehabt. Möchte mich W.S. anschließen, den Uart mit Interrupt
zu betreiben.
Grüsse
Hallo zusammen,
Dev P. schrieb:> Nachdem UART nicht> mehr über Interrupt lief hatte ich keine Probleme
Per Interrupt läuft bei mir die Datenverarbeitung, nicht der USART
W.S. schrieb:> Wozu soll ein DMA für den> USART-betrieb denn gut sein?
Damit meine CPU nicht wegen jedem Byte einen Kontext Wechsel machen
muss. Warum gibt es dann deiner Meinung nach einen DMA Channel zum Rx
des USART? Der DMA erledigt für die von dir beschriebene Pufferung der
Daten.
W.S. schrieb:> denn du versaust dir dabei den Status des USART jedesmal
Das könnte wirklich sein, mein Problem ist allerdings dass der
Timer+ADC+DMA(Interrupt) nicht mehr läuft.
hust schrieb:> dann würde ich das auch auslagern ...> die ISR gibt nur ein signal zum verarbeiten
Ist grundsätzlich natürlich besser, aber kann es etwas mit meinem
Problem zu tun haben? Der USART läuft ja ungestört weiter.
Bei der Datenverarbeitung im Interrupt des DMA (Timer+ADC+DMA) handelt
es sich um eine FOC Motorregelung @ 20kHz. Ein Durchlauf des
Regelungsalgorithmus dauert ca 30uS. Der Mikrocontroller ist also
alleine schon mit der Regelung ca 60% seiner Rechenzeit beschäftigt.
Wenn ich jetzt einen USART mit 115200Baud/s per Interrupt laufen lasse,
wird meine FOC Regelung total zerhackt, weil ich ständige USART Rx
Interrupts habe.
Habt Ihr noch weitere Ideen, wie der USART meinen ADC+DMA Interrupt
stören kann?
Gruß
Andreas
Andreas schrieb:> Damit meine CPU nicht wegen jedem Byte einen Kontext Wechsel machen> muss.Andreas schrieb:> Per Interrupt läuft bei mir die Datenverarbeitung, nicht der USARTAndreas schrieb:> Habt Ihr noch weitere Ideen, wie der USART meinen ADC+DMA Interrupt> stören kann?
Du bist mir schon ein recht Seltsamer.
Erstens gibt es bei einem Interrupt keinen Kontextwechsel (sowas ist ein
Begriff aus der Multitasking-Welt), sondern eben lediglich einen
Interrupt.
Zweitens solltest du mal erklären wie du dir den Rx-Betrieb per DMA denn
so vorgestellt hast - einschließlich des Tx-Betriebes in der
Grundschleife. So ein DMA kann m.W. lediglich Daten von einem Register
in einen linearen Puffer schreiben (oder umgekehrt oder mem-to-mem). Er
kann nicht wirklich mit einem Ringpuffer umgehen, weil dies eben auch
eine geordnete Abfrage ( if(IsCharAvailable()) ...;) beinhalten muß und
auch den Pufferüberlauf sinnvoll vermeiden muß.
Warum so ein USART überhaupt an den DMA-Core angeschlossen ist, kann man
ganz leicht beantworten: Weil diese USART's für weitaus mehr als nur den
asynchronen Datenverkehr auf einer seriellen Strippe geeignet sind und
es dort auch Modi gibt, die paketweise arbeiten. Was meinst du, wehalb
manche USART-Cores mit Adreßerkennungen usw. ausgestattet sind? Eben
deshalb.
Wenn bei dir die Datenverarbeitung im Interrupt läuft und nicht in der
Grundschleife, dann hast du entweder ein eher exotisches Problem oder du
machst etwas GANZ GANZ falsch. Ich könnte mir bestenfalls ne
Signalverarbeitung denken, also Filterung, digitale Mischerei und
Dekodiererei im Interrupt, aber das läuft dann eher mit einer
Interruptrate von 48 kHz oder gar 96 kHz. Bei solchen Interruptraten muß
man sich sehr genau überlegen, ob man damit den µC nicht zustopft.
Obendrein muß man sich bei sowas überlegen, ob man dort Gleitkomma
verwenden will oder nicht, denn die FPU-Register müßten dann je nach
Verwendung ebenfalls auf den Stack und das kostet Zeit.
Ob ich noch weitere Ideen hab? Na klar. Ich sag nur soviel: Mach's
richtig. Und versuche nicht, mit deinen bereits gefaßten Vorsätzen durch
die Wand rennen zu wollen. Du holst dir nur ne Beule am Kopf. Nimm
stattdessen nen Rat an: "geh nen Schritt zur Seite, dort ist ne Tür und
die ist offen".
W.S.
W.S. schrieb:> Du bist mir schon ein recht Seltsamer.> ...
Nun entspann dich etwas und bleib bitte sachlich.
Wenn ich in der Interrupt Routine nur eine einzige Variable um 1 erhöhe
und sonst nichts mache, habe ich genau den gleichen Fehler, dass es
irgendwann plötzlich keine DMA Interrupts mehr kommen.
Gruß
Andreas
Andreas schrieb:> Nun entspann dich etwas und bleib bitte sachlich.
Ich hab damit kein Problem. Aber du hast eines: Deine Firmware läuft
nämlich nicht und du überschaust jetzt die ganze Sache nicht mehr. Ich
hab dir ne ganze Reihe guter Ratschläge gegeben, jetzt ist es deine
Sache, was du tust. Jetzt kannst du dir denken "ich bin ja so toll und
die anderen sind mir zu doof" oder du nimmst den einen oder anderen Rat
eben an. Ist deine Sache und dein Problem - nicht meines.
W.S.