Hallo miteineander,
ich habe eine Frage bezüglich des STM32F103.
Ich versuche Daten von der SPI an den TIM 1 zu senden. Dazu werden
Dummybytes über den DMA1CH3 Kanal gesendet und über DMA1CH2 empfangen
bzw. in den Speicher des STM kopiert. Dort werden sie verarbeitet und
über DMA1CH5 an den TIM1 gesendet (in das CCR1 Register) Hier soll eine
PWM erzeugt werden deren Dutycicle sich eben durch die im Speicher
stehenden Daten ändern lässt (Ausioausgabe).
Wenn die Daten gleich im internen Speicher stehen (DMA1 CH2&3 aus) geht
alles wunderbar (Testsinus im Speicher). Werden DMA1 CH2&3 aktiviert
bekomme ich immer nur einen Teil meiner Daten durchsetzt von langen
Nullvollgen am Ausgang des TIM1CH1. Schalte ich, nachdem DMA1Ch3 meinen
internen Puffer gefüllt habe DMA1CH2&3 ab habe ich das selbe
unbrauchbare Ergebnis. Als liegt es auch nicht an der Busauslastung.
Weiß jemand wie das mit dem Updaten des TIM1 per DMA geht? Das
Datenblatt und die Appnotes brauchten bisher keine Erleuchtung. Gerne
sende ich hilfsbereiten Usern auch Teile des Codes. Bitte heltm mir ...
Erwähnenswert.
USART und USB sind auch aktiv wurde aber auch schon deaktiviert - ohne
Erfolg.
Vielen Dank
Simon
Hier mal Teilausschnitte des Codes:
DMA1CH5
Irgendwie liest sich dein Posting so, als ob du erklärtermassen ein
Problem mit DMA 2/3 hast und zwecks besserem Verständnis nur den Code
zum DMA 5 postest.
Alerdings habe ich deine Beschreibung auch nicht wirklich verstanden.
Also beispielsweise, ob die Daten falsch vom SPI im Speicher ankommen
oder falsch im Timer ankommen oder zwischendrin mysteriös
verschwinden...
Ehrlich gesagt hab ich keine Ahnung wo das Problem liegt.
Im Bild ist folgendes zu sehen:
DMA1CH5 holt sich Daten aus dem Flash des STM32. Dort liegt wie zu sehen
ein Sinus.
Diese werden an den Timer gesendet der daraus ein PWM generiert.
Hole ich nun die Daten über einen weiteren DMA Kanal (DMA1CH2) von der
SPI1 ab (dazu muss ich über DMA1CH3 aber erst ein Dummybyte
rausschreiben zwecks Clocksignal) kommen an meinem PWM Pin nur noch 40
bis 80 PWM Zyklen gefolgt von einem langen Pause an. Dies wirdeholt sich
bis das File (Die Daten im externen Flash) zu Ende sind.
Folgendes habe ich versucht:
DMA Kanal und Timer gewechselt zwecks Laust auf der Bridge. - Erfolglos
-
Füllen meines internen Puffers mit DMA1 CH2/3 dann abschalten der Kanäle
2/3
also quasi immer den selben Datensatz auslesen - Erfolglos -
-> also dürfte es ja nicht an CH 2/3 liegen oder
Ich habe alle peripheren Gerätschaften bis auf DMA1CH5 deaktiviert
(Clock aus EN raus usw. - das Signal bleibt zerhackt -
Noch mal zum Verständnis.
DMA1CH3 Dummy raus DMA1CH5
SPI <-------------> interner Puffer ----> TIM1UPDATE
DMA1CH2 Daten rein
Daten von der SPI werden in zwei 256k langen Puffern gespeichert -je
nachdem welcher gerade Frei ist - diese werden verarbeitet (ich muss
die wave Daten erst mal PWM tauglich machen da die wav Daten pos und neg
sind. Außerdem muss ich die Quantisierung reduzieren, da der TIM1 für
44,1Khz und 16Bit zu langsam ist. Die verarbeiteten Daten werden in eine
512k breiten Puffer geschrieben der im Cicle mode von DMA1CH5 an den
TIM1 gesendet wird. Getriggert wird hierbei auf das Update-Event des
Timers.
Im 512k breiten Puffer kommen die Daten richtig an.
An die Außenwelt gelangt aber nur ein Teil.
Wie gesagt nachdem mein Ausgangspuffer ein mal richtig beschrieben wurde
habe ich auch schon DMA1CH2/3 abgeschalten und diese Daten endlos
ausgeben lassen - diese sind auch von Unterbrechungen durchsetzt.
Ich habe auch schon eine Methode mit nur einem Puffer versucht.
Da es sich hierbei um meine Bachelorarbeit handelt und ich noch
lediglich 3 Wochen Zeit habe freue ich mich über jede Art von Hilfe.
Einen Dank schon mal an A.K. für die Hilfe.
Grüße
Simon
Bei externem Speicher gibt es ein klitzekleines Problem in Verbindung
mit DMA. Siehe Errata Sheet unter 2.13: "Multimaster access on the FSMC
memory map".
Kurz gesagt: DMA ist über FSMC effektiv nicht nutzbar.
PS: ... nur bedingt nutzbar. Darf eben immer nur einer drauf zugreifen.
Ich fürche aber, das ist nicht genau das, was du dir unter double
buffering mit DMA vorgestellt hattest.
Ich hoffe du findest einen Weg, mit dem internen Speicher auszukommen.
So wie ich das in den ERRATA Sheets verstanden habe kann ich per DMA
nichts von einer Peripherieadresse an eine andere Peripherieadresse
senden, da der Cortex Kern dann nicht Prüft ob diese zwei Geräte gerade
die Bridge nutzen wenn er selbst darauf schreiben will.
Bekomme ich in solch einem Fall nicht immer einen BUS ERROR?
Der Tritt nämlich nicht auf?
Bedeutet das jetzt im Umkehrschluss, dass der Controller dem gleichen
Bug unterworfen ist wenn man von der Peripherie ins interne Memory
schreibt.
(Beitrag "STM32 DMA und externes RAM")
Gibt es da irgend eine Lösung?
Ich werde mal damit beginnen die Daten der SPI auf normelem Wege
abzurufen.
Ich verstehe nicht warum die Sinustestfunktion dann korrekt ausgegeben
wird.
Wie beschrieben kann ich den Puffer ein mal mit Hilfe der Kanäle 2/3
Füllen lassen. Nach abschalten der Kanäle bleibt der Fehler jedoch
erhalten?
Warum, es greift dann doch nichts mehr auf den Bus zu was sich da
verheddern könnte oder?
Gibt es irgend welche Lösungsansätze bzw wie kann ich den per sw checken
ob etwas andes auf den Bus zugreift?
Ich habe noch keine geschickte Möglichkeit gefunden die DMA bzw. den
Verkehr auf den Bridges zu debuggen. Ist das irgendwie möglich. Oder
anders herum, wie soll ich den Bridge-Zugriff überwachen wenn ich ihn
nicht sehe?
Grüße und vielen Dank
Simon
SImon schrieb:> So wie ich das in den ERRATA Sheets verstanden habe kann ich per DMA> nichts von einer Peripherieadresse an eine andere Peripherieadresse> senden, da der Cortex Kern dann nicht Prüft ob diese zwei Geräte gerade> die Bridge nutzen wenn er selbst darauf schreiben will.
Peripherie zu Peripherie kann der DMA überhaupt nicht. Nur P<=>M und
M<=>M. Der externe Speicher zählt hierbei als Speicher, nicht als
Periphierie.
Ich lese das allerdings anders. Wenn mehrere Bus-Master (CPU/DMA1/DMA2)
um den vom FSMC verwalteten Speicher konkurrieren, dann kann es es Mist
geben. Bus Error oder Schrott. Wie oft, ob selten oder häufig, steht
nicht da.
Der dargestellte Workaround heisst, dass die CPU nicht in dem externen
Speicher rumfroschen sollte, wenn zwischendurch DMA stattfinden kann.
Allerdings tritt der DMA-Controller vermutlich nicht mit sich selbst in
Konkurrenz, jedenfalls nicht auf der kritischen Ebene, so dass mehrere
aktive Kanäle auf dem gleichen DMA-Controller zulässig sein dürften. Nur
darf eben nicht parallel dazu die CPU auf den externen Speicher
zugreifen wollen.
> Ich verstehe nicht warum die Sinustestfunktion dann korrekt ausgegeben> wird.
Es muss auch nicht bedeuten, dass dieser Bug wirklich dein Problem ist.
Ausserdem sind uns die exakten internen Randbedingungen dieses Bugs
nicht bekannt.
> Gibt es irgend welche Lösungsansätze bzw wie kann ich den per sw checken> ob etwas andes auf den Bus zugreift?
DMA abschalten bevor die CPU auf den Speicher zugreift und danach wieder
einschalten. Wenn das nicht geht (klingt auch recht schaurig), dann hast
du ein ernstes Problem.
Zu deinem Problem:
Guck mal im Reference Manual unter 10.3.7.
Ich glaube du verwendest Peripherie die auf dem gleichen Channels liegt
(TIM1_CH1, SPI1_RX auf Ch2).
Er schreibt zwar per DMA in TIM1.CH1, nutzt aber als DMA-Trigger das
Update Event, und das liegt auf DMA1.CH5.
Allerdings vemisse ich TIM_SelectCCDMA, denn laut Referenz ist CR2 per
Default auf CC-DMA statt Update-DMA konfiguriert.
Wobei ich freilich den Eindruck habe, dass diese Funktion in V3.3.0
genau das Gegenteil dessen tut was sie suggeriert. Name/Beschriebung
suggeriert, dass mit ENABLE auf CC-DMA und mit DISABLE auf Update-DMA
konfiguriert wird. Wenn die Register-Referenz korrekt ist, dann passiert
aber genau das Gegenteil.
Generell: Die FwLib ist eine zusätzliche potentielle Fehlerquelle. Bei
Problemen immer kontrollieren, ob in den Peripherieregistern wirklich
das drinsteht, was man dort entsprechen der der Referenz vorzufinden
hofft.
Zwischenfrage:
Ich nutze die SPI mit der von ST bereitgestellten Lib.
Dazu befindet sich auf meinem Board ein M25P64 (8MBit Flash)
Greife ich hierbei auf den FSMC Controller zu?
Ich habe mir das mit den Channels angesehen.
Ich habe drei unterschiedlich Kanäle der DMA1
CH2 SPI1_RX leitet SPI Daten an einen internen Puffer
CH3 SPI1_TX Clockt ein Dummybyte raus um den SPI Takt zu generieren
CH5 TIM1_UP leitet die Daten aus dem internen Puffer an den Timer1
Events:
CH2 TIM1_RX
CH3 ?? gute Frage
CH5 TIM1_UP
TIM_SelectCCDMA(TIM1, ENABLE); wurde in die TIM1 init implementiert -
ohne Änderung der Funktion - was macht diese Abschnitt?
Ich hab schon den Kommentar in der Lib nicht ganz verstanden.
Zu den Bildern:
tek0002: Unterbrochenes PWM Signal nach aktivieren der DMA1CH2/3 um neue
Daten von der SPI in den Puffer zu laden.
tek0004: Ausgabe zweier Sinusfunktionen, je eine Periode aus den
internen Puffer. Dies Funktioniert.
Hat jemand eine Idee was diese aussetzer verursachen könnte?
Ich habe die gesammte Peripherie nach auftreten diese Fehlers
deaktiviert - der Fehler bleibt -
Code für CH2/3:
1
voidStartDMATransferToBuffer(uint16_tu16Titel)
2
{
3
/**
4
Test wie man Daten über die DMA Schnittstelle vom Mem an die SPI sendet
5
DMA SPI1 TX -> DMA1 CH3
6
kann nur 16 Bit sein wenn SPI auch 16 bit empfangen kann !!!
In den Anhang habe ich mein gesammtes Projekt gepackt.
Die betreffenden Passagen befinden sich in:
DMA_user.c
Timer_PWM.c
Da ich z.Z. sehr viel im Code versucht habe gibt es einige
#ifdef´s und auskommentierte Passagen.
Die Ausgabe des Testsinus funktioniert, die Ausgabe eines wav Files
nicht.
Vielen Dank im Voraus
Denkt daran ich bin kein pro.
Den Cortex programiere ich das erste mal
Simon
Simon schrieb:> TIM_SelectCCDMA(TIM1, ENABLE); wurde in die TIM1 init implementiert -> ohne Änderung der Funktion - was macht diese Abschnitt?> Ich hab schon den Kommentar in der Lib nicht ganz verstanden.
Wirst nicht darum herum kommen, dir die Steuerregister des Timers direkt
anzusehen, sowohl die Referenz als auch den tatsächlichen Zustand nach
der Initialisierung, insbesondere das DMA-Steuerbit im CR2. Und den
Quellcode der Funktion(en). Die Doku der Fwlib allein ist nicht
ausreichend. Nochmal: Nicht auf Fehlerfreiheit der FWlib vertrauen!