Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Hallo zusammen,
ich stehe vor einem Problem mit meinem STM32F030C6T6 Controller in Bezug
auf SPI DMA-Übertragungen und hoffe auf eure Unterstützung.
Ich verwende SPI DMA, um kontinuierlich Daten vom Master an einen
Slave-Controller zu senden. Die Nachricht besteht aus 12 Byte, die
jeweils in 8 Bit übertragen werden. Anfangs funktioniert alles
einwandfrei: Der Slave empfängt die Daten, verarbeitet sie und sendet
entsprechende Antworten zurück. Dies funktioniert für einige
Minuten/Sekunden bis ca. 30 min reibungslos.
Allerdings tritt dann plötzlich ein Problem auf: Die Nachricht, die der
Master sendet, scheint im SPI DMA des Slaves verschoben zu sein. Obwohl
die Daten vorhanden sind, stimmt ihre Reihenfolge nicht mehr. Dies führt
dazu, dass mein Protokoll nicht mehr korrekt funktioniert. Dieser Fehler
zieht sich dann komplett durch ich hatte schon gedacht eventuell den DMA
Pointer der auf die Memory Adresse ist zurückzusetzen, aber leider ohne
Erfolg.
Ich habe versucht, das Problem zu lösen, indem ich das FRXTH-Register
für CR2 (FIFO Reception Threshold) setze, jedoch ohne Erfolg. Selbst
wenn der Slave nur die empfangenen Daten des Masters zurücksendet, tritt
das Problem nach einer gewissen Zeit auf. Es ist nur das SPI Modul
initialisiert und keine anderen Interrupts die den Prozess behindern
können. Die Clock Polarität ist auf dem Slave und Master auch gleich.
Ich bin bereits verzweifelt und hoffe sehr, dass jemand von euch eine
Idee hat, wie ich dieses Problem lösen kann.
Anbei findet ihr eine Logic Analyzer-Datei, die zeigt, was der Master
sendet, sowie eine Debug-Datei, die die Daten im Array zeigt, in dem das
Problem auftritt.
Ich bedanke mich im Voraus für eure Hilfe und Unterstützung!
1 | void spi_init(void)
| 2 | {
| 3 | RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
| 4 | NVIC_DisableIRQ(SPI1_IRQn);
| 5 |
| 6 | SPI1->CR1 &= ~(SPI_CR1_MSTR); //SPI Slavemode
| 7 | SPI1->CR2 |= (SPI_CR2_DS_0 | SPI_CR2_DS_1 | SPI_CR2_DS_2); //8Bit Daten
| 8 |
| 9 | SPI1->CR1 &= ~SPI_CR1_CPOL; // Clock-Polarität auf 0 (Takt bei Ruhepegel 0)
| 10 | SPI1->CR1 &= ~SPI_CR1_CPHA; // Clock-Phase auf 0 (erste Flanke bei Taktbeginn)
| 11 | SPI1->CR1 &= ~SPI_CR1_LSBFIRST;
| 12 |
| 13 | SPI1->CR2 |= SPI_CR2_FRXTH;
| 14 | //SPI1->CR2 |= SPI_CR2_RXNEIE;
| 15 |
| 16 | SPI1->CR2 |= (SPI_CR2_TXDMAEN);
| 17 | SPI1->CR2 |= (SPI_CR2_RXDMAEN);
| 18 |
| 19 | SPI1->CR1 |= (SPI_CR1_SPE);
| 20 |
| 21 | }
| 22 |
| 23 |
| 24 | void DMA_SPI_Init(void)
| 25 | {
| 26 |
| 27 | RCC->AHBENR |= RCC_AHBENR_DMAEN; //Start DMA1 Clock
| 28 |
| 29 |
| 30 |
| 31 | //////////DMA SPI RX
| 32 | DMA1_Channel2->CPAR = (uint32_t)&(SPI1->DR); //PerAdress Data register
| 33 | DMA1_Channel2->CMAR = (uint32_t)&dma_SPI_RX[0]; //MemAdress
| 34 | DMA1_Channel2->CNDTR = (uint32_t)12; //Anzahl Daten Inkremente
| 35 |
| 36 | //DMA1_Channel2->CCR |= DMA_CCR_PL;
| 37 |
| 38 | DMA1_Channel2->CCR |= DMA_CCR_CIRC | DMA_CCR_MINC; //PER-MEM ; CircMode; MemInc; Per32Bit; MEM32Bit; PioMed
| 39 | //DAM IRG regestrieren
| 40 |
| 41 | DMA1_Channel2->CCR |= DMA_CCR_TCIE; //DMA Transfer Complete interrupt
| 42 |
| 43 |
| 44 | DMA1_Channel2->CCR |= DMA_CCR_EN; //DMA1 Channel1 Enable //DMA1 Channel1 Enable
| 45 |
| 46 |
| 47 |
| 48 | ////////////DMA SPI TX
| 49 | DMA1_Channel3->CPAR = (uint32_t)&(SPI1->DR); //PerAdress
| 50 | DMA1_Channel3->CMAR = (uint32_t)&dma_SPI_TX[0]; //MemAdress
| 51 | DMA1_Channel3->CNDTR = (uint32_t)12; //Anzahl Daten Inkremente
| 52 |
| 53 | DMA1_Channel3->CCR |= DMA_CCR_DIR | DMA_CCR_MINC;
| 54 |
| 55 | NVIC_SetPriority(DMA1_Channel2_3_IRQn,0);
| 56 | NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
| 57 |
| 58 | DMA1_Channel3->CCR |= DMA_CCR_TCIE; //DMA Transfer Complete interrupt
| 59 |
| 60 |
| 61 | DMA1_Channel3->CCR |= DMA_CCR_EN; //DMA1 Channel1 Enable
| 62 |
| 63 |
| 64 | }
| 65 |
| 66 | //DMA SPI RX und TX
| 67 | void DMA1_Channel2_3_IRQHandler(void)
| 68 | {
| 69 |
| 70 | //TX Interruptflag vom DMA (SPI)
| 71 | if(DMA1->ISR & DMA_ISR_TCIF3)
| 72 | {
| 73 |
| 74 |
| 75 | DMA1->IFCR |= DMA_IFCR_CTCIF3;
| 76 |
| 77 |
| 78 | }
| 79 |
| 80 |
| 81 | //RX Interruptflag vom DMA (SPI)
| 82 | if(DMA1->ISR & DMA_ISR_TCIF2)
| 83 | {
| 84 |
| 85 |
| 86 | if(spi_interface.reason_for_id_message == false)
| 87 | {
| 88 |
| 89 | SPI_Protokoll_state();
| 90 | }
| 91 | else
| 92 | {
| 93 | // Senden aus der MAIN die ID Message
| 94 | DMA1_Channel3->CCR &= ~(DMA_CCR_EN);
| 95 | DMA1_Channel3->CNDTR = (uint32_t)0x0C;
| 96 | DMA1_Channel3->CCR |= (DMA_CCR_EN);
| 97 | }
| 98 |
| 99 |
| 100 | DMA1->IFCR |= DMA_IFCR_CTCIF2;
| 101 |
| 102 | }
| 103 |
| 104 |
| 105 | }
|
Vielleicht wäre es sinnvoll, sich zuerst für EINEN Transfer-Modus zu
entscheiden: Entweder Ringpuffer-Modus oder Einzelschuss-Modus.
Beides gleichzeitig macht keinen Sinn.
NSS wird nicht benutzt?
Die 12 da mehrfach rein zu schreiben, ist keine gute Idee. Wenn die
einzelnen Nachrichten alle 12 Byte lang sind, legt man besser einen
Puffer mit genau dieser Länge an und nimmt sizeof() für die
Längenangaben. Oder zumindest eine Konstante oder ein #define für die
"Standard"-Länge.
Ach ja, für dieses Problem natürlich egal, aber die Bits in den
Registern so häppchenweise zu setzen/löschen ist schon etwas eigenartig.
Man darf auch mehr als ein Bit gleichzeitig ändern: Gleich den
kompletten gewünschten Wert zusammenstellen und in einem Rutsch ins
Register. Ausnahme nur in Einzelfällen, wenn man wirklich insgesamt nur
ein Bit ändern will.
Und für Mehrbitfelder gibt's extra die ..._Pos Makros.
Das "Per32Bit; MEM32Bit" ist doch sicher nicht richtig?!
Das IFCR ist eigentlich "write-only", ein "DMA1->IFCR |=" macht daher
keinen Sinn (auch wenn ein Lesen "zufälligerweise" 0x0 ergibt).
"DMA1->IFCR = DMA_IFCR_CTCIF2;" ist zielführender.
Hallo Andreas,
der Hardware PIN NSS wird verwendet. Mein dma_SPI_RX[] und mein
dma_SPI_TX[] Array die auf MemAdresse liegen sind 12 Felder lang da ich
ja 12 Bytes sende und auch gleichzeitig empfange quasi im Write/Read
Modus. Der DMA RX channel läuft im Circular Mode und auf Memory
Increment der Channel ist dauerhaft aktiviert weil er ja ständig auf
Daten wartet. Der TX channel läuft im direction Mode und auch memory
Increment. Was meinst du mit Ringpuffer? Der circular Mode?. Denkst du
das Problem liegt an der Konfiguration vom SPI oder eher am DMA? Komisch
ist das das Problem immer zu unterschiedlichen Zeiten auftritt manchmal
nach 1 min manchmal nach 5 oder sogar manchmal auch nach 20 min erst.
Mark J. schrieb:
> Komisch
> ist das das Problem immer zu unterschiedlichen Zeiten auftritt manchmal
> nach 1 min manchmal nach 5 oder sogar manchmal auch nach 20 min erst.
Dann hast du wahrscheinlich ein Hardware-Problem.
Aber das wollen Softwerker (die ihre Hardware selbst bauen)
nur ungern hören.
Wastl schrieb:
> Mark J. schrieb:
>> Komisch
>> ist das das Problem immer zu unterschiedlichen Zeiten auftritt manchmal
>> nach 1 min manchmal nach 5 oder sogar manchmal auch nach 20 min erst.
>
> Dann hast du wahrscheinlich ein Hardware-Problem.
>
> Aber das wollen Softwerker (die ihre Hardware selbst bauen)
> nur ungern hören.
Ich habe dann auch mal zu Testzwecken 2 developments boards von STM
miteinander nur über SPI verbinden aber fliegende Leitungen ca. 10 cm.
und das selbe Problem tritt auch auf. Den Bus habe ich auch schon auf
450 khz ca. gesetzt. An dem Master kann es ja eigentlich nicht liegen
der schickt in 1,5 ms intervallen ca einfach die gleiche Nachricht an
dem Slave. Am logic Analyzer ist auch zu sehen dass die Nachrichten
rausgesendet wurden. Das Problem liegt halt nur am Slave mit SPI DMA
dass die Daten irgendwann im RX Channel verschoben sind. Wenn ich 8 Bit
sende dann muss das SPI_CR2_FRXTH (FIFO Reception Threshold) Bit gesetzt
werden habe ich in anderen Foren gelesen und das steht auch in dem
Beispiel von ST drin, aber trotzdem ohne Erfolg.
Mark J. schrieb:
> Den Bus habe ich auch schon auf
> 450 khz ca. gesetzt.
Dann hast du noch nicht verstanden was Macken in der Hardware
alles bewirken können. Den Takt herunter setzen hilft gegen
Hardware-Macken gar nichts. Damit zeigst du nur dass du
Probleme in Hardware noch gar nicht verstanden hast.
Aber es scheint ja so zu sein, dass dort einfach Bytes beim Empfang
verloren gehen, richtig? Du schickst doch die selbe Sequenz immer
wieder.
Du schickst:
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x17
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x17
Beim Empfänger gehen dann offenbar die Bytes
1-10 verloren, und er empfängt:
0xe0, 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
Allerdings verwendest Du zum Empfang ja den Circular Mode, d.h.
eigentlich kann das nicht passieren, da es komplett in DMA abläuft. Du
darfst natürlich in Deinem Code den Empfangs-DMA nicht neu
initialisieren. Das ist nur einmal am Anfang notwendig.
Mark J. schrieb:
> der Hardware PIN NSS wird verwendet. Mein dma_SPI_RX[] und mein
Davon ist aber nichts zu sehen.
> dma_SPI_TX[] Array die auf MemAdresse liegen sind 12 Felder lang da ich
> ja 12 Bytes sende und auch gleichzeitig empfange quasi im Write/Read
> Modus. Der DMA RX channel läuft im Circular Mode und auf Memory
> Increment der Channel ist dauerhaft aktiviert weil er ja ständig auf
> Daten wartet. Der TX channel läuft im direction Mode und auch memory
??? Bezieht sich das auf den Master oder den Slave? Beim Master wartet
man nicht ständig auf Daten, denn der Master liefert den Takt, also ein
Byte raus bedeutet genau ein Byte rein, sonst kann nichts ankommen.
> Increment. Was meinst du mit Ringpuffer? Der circular Mode?. Denkst du
Ja, was sonst? Der macht hier keinen rechten Sinn, weder beim Master,
noch
beim Slave, denn beide müssen ohnehin wissen, wo die "Telegramm"-Grenzen
sind,
dann ein vollständiges Paket verarbeiten und können dann DMA fürs
nächste
Pakt scharf machen.
Gegen ein Hardwareproblem (Störungen auf der Taktleitung) spricht, dass
der Versatz immer ein Vielfaches von 8 Bits zu sein scheint.
Nochmals: Das "Per32Bit; MEM32Bit" ist doch sicher nicht richtig?!
Markus M. schrieb:
> Aber es scheint ja so zu sein, dass dort einfach Bytes beim Empfang
> verloren gehen, richtig? Du schickst doch die selbe Sequenz immer
> wieder.
>
> Du schickst:
>
> 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x17
> 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x17
>
> Beim Empfänger gehen dann offenbar die Bytes
> 1-10 verloren, und er empfängt:
>
> 0xe0, 0x17, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
>
> Allerdings verwendest Du zum Empfang ja den Circular Mode, d.h.
> eigentlich kann das nicht passieren, da es komplett in DMA abläuft. Du
> darfst natürlich in Deinem Code den Empfangs-DMA nicht neu
> initialisieren. Das ist nur einmal am Anfang notwendig.
Hallo Markus,
ja richtig ich verwende den Circular Mode da dürfte dann nichts verloren
gehen. Der master sendet aufjedenfall richtig die 12 Bytes raus das habe
ich schon bereits mit dem Logic Analyzer überprüft nur irgendwann passt
die Reihenfolge beim Slave SPI RX DMA nicht mehr. Die Frage ist jetzt
gehen wirklich die Bytes beim Slave verloren. Der Empfangs DMA wird nur
einmal initialisiert.
Andreas B. schrieb:
> Mark J. schrieb:
>> der Hardware PIN NSS wird verwendet. Mein dma_SPI_RX[] und mein
> Davon ist aber nichts zu sehen.
>
>> dma_SPI_TX[] Array die auf MemAdresse liegen sind 12 Felder lang da ich
>> ja 12 Bytes sende und auch gleichzeitig empfange quasi im Write/Read
>> Modus. Der DMA RX channel läuft im Circular Mode und auf Memory
>> Increment der Channel ist dauerhaft aktiviert weil er ja ständig auf
>> Daten wartet. Der TX channel läuft im direction Mode und auch memory
> ??? Bezieht sich das auf den Master oder den Slave? Beim Master wartet
> man nicht ständig auf Daten, denn der Master liefert den Takt, also ein
> Byte raus bedeutet genau ein Byte rein, sonst kann nichts ankommen.
>
>> Increment. Was meinst du mit Ringpuffer? Der circular Mode?. Denkst du
> Ja, was sonst? Der macht hier keinen rechten Sinn, weder beim Master,
> noch
> beim Slave, denn beide müssen ohnehin wissen, wo die "Telegramm"-Grenzen
> sind,
> dann ein vollständiges Paket verarbeiten und können dann DMA fürs
> nächste
> Pakt scharf machen.
den Code den ich hier gepostet habe bezieht sich komplett nur auf den
Slave. Der Master sendet alle 1,5 ms die Nachricht raus beim senden
gehen keine Bytes verloren das habe ich schon mit dem Logic Analyzer
übprüft. Das muss irgendwie am Slave liegen. Warum ergibt der Circular
Mode beim DMA keinen sinn beim Slave für den Empfangschannel für SPI??
WOher sollen denn Störungen kommen wenn ich 2 dev boards vom stm über
SPI verbinde. Die Leitungen sind höchstens 10 cm. Das Per32Bit und
MEM32Bit ist nicht gesetzt. stand nur noch in den kommentaren. Frage ist
es jetzt ist es eher ein Software oder Hardware Problem. Hardwareproblem
hätte ich jetzt eigentlich ausgeschlossen.
Mark J. schrieb:
> ja richtig ich verwende den Circular Mode da dürfte dann nichts verloren
> gehen. Der master sendet aufjedenfall richtig die 12 Bytes raus das habe
> ich schon bereits mit dem Logic Analyzer überprüft nur irgendwann passt
> die Reihenfolge beim Slave SPI RX DMA nicht mehr. Die Frage ist jetzt
> gehen wirklich die Bytes beim Slave verloren. Der Empfangs DMA wird nur
> einmal initialisiert.
Nochmals: Das ist eine ganz schlechte Idee. Wenn irgendwann einmal ein
Problem auftritt (hard- oder softwaremäßig), ist danach der Empfang auf
ewig außer Tritt ... Ringpuffer-Modus ist nur dann sinnvoll, wenn es
um einen "endlosen" Datenstrom geht, bei dem ein Wiederaufsetzen anhand
inhaltlicher Analyse möglich ist. Z. B. Text, wo man beim nächsten CR
oder LF neu aufsetzen kann. Dann ist zwar bei einer Störung eine oder
zwei Zeilen weg, aber danach geht's weiter.
Und stillschweigend eine absolut fehlerfreie Kommunikation anzunehmen
ist ziemlich blauäugig. Murphy's Gesetz ... Außerdem ist auch bei einem
noch so simplen Protokoll eine Fehlerprüfung (CRC oder so) oder
zumindest eine Plausibilitätskontrolle zwingend.
Übrigens: Beim SPI gibt's auch Fehler-Flags, die man prüfen könnte.
Netterweise sind die auch "sticky".
Andreas B. schrieb
> Nochmals: Das ist eine ganz schlechte Idee. Wenn irgendwann einmal ein
> Problem auftritt (hard- oder softwaremäßig), ist danach der Empfang auf
> ewig außer Tritt ... Ringpuffer-Modus ist nur dann sinnvoll, wenn es
> um einen "endlosen" Datenstrom geht, bei dem ein Wiederaufsetzen anhand
> inhaltlicher Analyse möglich ist. Z. B. Text, wo man beim nächsten CR
> oder LF neu aufsetzen kann. Dann ist zwar bei einer Störung eine oder
> zwei Zeilen weg, aber danach geht's weiter.
OK und was würdest du dann anders konfigurieren an dem DMA? Zurzeit
läuft der Empfangschannel vom DMA SPI auf Circular Mode von dem Slave
was ja nicht so sinnvoll wäre wie du sagtest.
> Und stillschweigend eine absolut fehlerfreie Kommunikation anzunehmen
> ist ziemlich blauäugig. Murphy's Gesetz ... Außerdem ist auch bei einem
> noch so simplen Protokoll eine Fehlerprüfung (CRC oder so) oder
> zumindest eine Plausibilitätskontrolle zwingend.
Ja das ist aufjedenfall klar es kann ja auch mal ein Bit kippen wenn
Störungen auftreten sollten. Aber mein Protokoll hat ja auch eine
Plausibilitätsabfrage über einen CRC vorgesehen.
> Übrigens: Beim SPI gibt's auch Fehler-Flags, die man prüfen könnte.
> Netterweise sind die auch "sticky".
Ja an Fehlerflags hatte ich auch schon gedachte der DMA hat ja auch
welche. Man müsste nur eine richtige Debugmethode finden, dass man das
Fehlerflag nicht verpasst , wenn mehrmals hintereinander gesendet wird.
Ich vermute dass bei 200 mal senden oder so es einmal kurz auftreten
könnte und dann automatisch wieder resettet wird. Entweder beim DMA
Fehlerflag oder SPI Fehlerflag.
Das sind die Modi von dem DMA
1 | Bit 7 MINC: Memory increment mode
| 2 | Defines the increment mode for each DMA transfer to the identified memory.
| 3 | In memory-to-memory mode, this bit identifies the memory source if DIR = 1 and the memory
| 4 | destination if DIR = 0.
| 5 | In peripheral-to-peripheral mode, this bit identifies the peripheral source if DIR = 1 and the
| 6 | peripheral destination if DIR = 0.
| 7 | 0: Disabled
| 8 | 1: Enabled
| 9 | Note: This bit is set and cleared by software. It must not be written when the channel is
| 10 | enabled (EN = 1). It is read-only when the channel is enabled (EN = 1).
| 11 |
| 12 | Bit 6 PINC: Peripheral increment mode
| 13 | Defines the increment mode for each DMA transfer to the identified peripheral.
| 14 | n memory-to-memory mode, this bit identifies the memory destination if DIR = 1 and the
| 15 | memory source if DIR = 0.
| 16 | In peripheral-to-peripheral mode, this bit identifies the peripheral destination if DIR = 1 and
| 17 | the peripheral source if DIR = 0.
| 18 | 0: Disabled
| 19 | 1: Enabled
| 20 | Note: This bit is set and cleared by software. It must not be written when the channel is
| 21 | enabled (EN = 1). It is read-only when the channel is enabled (EN = 1).
| 22 |
| 23 | Bit 5 CIRC: Circular mode
| 24 | 0: Disabled
| 25 | 1: Enabled
| 26 | Note: This bit is set and cleared by software. It must not be written when the channel is
| 27 | enabled (EN = 1). It is not read-only when the channel is enabled (EN = 1).
| 28 | Direct memory access controller (DMA) RM0360
| 29 | 166/775 RM0360 Rev 5
| 30 | 10.6.4 DMA channel x number of data to transfer register (DMA_CNDTRx)
| 31 | Address offset: 0x0C + 0x14 * (x - 1), (x = 1 to 5)
| 32 | Reset value: 0x0000 0000
| 33 |
| 34 | Bit 4 DIR: Data transfer direction
| 35 | This bit must be set only in memory-to-peripheral and peripheral-to-memory modes.
| 36 | 0: Read from peripheral
| 37 | – Source attributes are defined by PSIZE and PINC, plus the DMA_CPARx register.
| 38 | This is still valid in a memory-to-memory mode.
| 39 | – Destination attributes are defined by MSIZE and MINC, plus the DMA_CMARx
| 40 | register. This is still valid in a peripheral-to-peripheral mode.
| 41 | 1: Read from memory
| 42 | – Destination attributes are defined by PSIZE and PINC, plus the DMA_CPARx
| 43 | register. This is still valid in a memory-to-memory mode.
| 44 | – Source attributes are defined by MSIZE and MINC, plus the DMA_CMARx register.
| 45 | This is still valid in a peripheral-to-peripheral mode.
| 46 | Note: This bit is set and cleared by software. It must not be written when the channel is
| 47 | enabled (EN = 1). It is read-only when the channel is enabled (EN = 1).
|
Generell: bei SPI findet die Synchronisation (Byte und auch
Paket/Nachricht) zwischen Master und Slave per SS statt. Ohne SS kein
sync. Ein verlorener Takt führt zu einer Bitverschiebung die nie wieder
einrastet. Ein Antwort mit unerwarteter Länge (wg Fehler o.ä.) zu einer
Byteverschiebung. Das Error-Recovery sollte auf jeden Fall SS einmal
deaktivieren, noch besser wäre es, zwischen jedem Kommando. Ob das der
STM32 bei DMA beherrscht, weiß ich nicht.
Mark J. schrieb:
> OK und was würdest du dann anders konfigurieren an dem DMA? Zurzeit
> läuft der Empfangschannel vom DMA SPI auf Circular Mode von dem Slave
> was ja nicht so sinnvoll wäre wie du sagtest.
Beide im "normalen Modus", und beide nach jedem Telegramm neu starten.
Und immer kontrollieren, dass "transfer complete" auf beiden
DMA-Kanälen angezeigt wird.
> Ja an Fehlerflags hatte ich auch schon gedachte der DMA hat ja auch
> welche. Man müsste nur eine richtige Debugmethode finden, dass man das
> Fehlerflag nicht verpasst , wenn mehrmals hintereinander gesendet wird.
> Ich vermute dass bei 200 mal senden oder so es einmal kurz auftreten
> könnte und dann automatisch wieder resettet wird. Entweder beim DMA
> Fehlerflag oder SPI Fehlerflag.
Deswegen das 'Netterweise sind die "sticky"'. Die werden halt ganz
bewusst NICHT automatisch zurückgesetzt. Das ist doch gerade der Witz
dabei ...
"TEIFx: Channel x transfer error flag (x = 1..5)
This bit is set by hardware. It is cleared by software writing 1 to the
corresponding bit in the DMA_IFCR register."
Oder:
"Bit 6 OVR: Overrun flag
0: No overrun occurred
1: Overrun occurred
This flag is set by hardware and reset by a software sequence."
Andreas B. schrieb:
> Beide im "normalen Modus", und beide nach jedem Telegramm neu starten.
> Und immer kontrollieren, dass "transfer complete" auf *beiden*
> DMA-Kanälen angezeigt wird.
Wir reden ja nur vom Slave richtig? Der Master ist ja erstmal egal und
spielt da ja keine Rolle. Also darf ich das Bit CIRC: Circular mode beim
RX Channel nicht setzen dann bin ich ja im normalen Modus quasi
Einzelschussmodus. Darum muss ich dann nach jeden Telegram den DMA
neustarten. Der TX Channel vom Slave ist ja im Einzelschuss Modus den
Channel starte ich ja sowieso immer neu, wenn ich was übertragen will.
Eigentlich muss ich doch dann nur den RX Channel vom Slave neustarten
wenn ich was vom Master etwas empfangen habe oder? Das kann ich ja im
DMA RX Interrupt machen. Also wenn ich was empfangen habe dann direkt
neustarten oder nicht?
> Deswegen das 'Netterweise sind die "sticky"'. Die werden halt ganz
> bewusst NICHT automatisch zurückgesetzt. Das ist doch gerade der Witz
> dabei ...
> "TEIFx: Channel x transfer error flag (x = 1..5)
> This bit is set by hardware. It is cleared by software writing 1 to the
> corresponding bit in the DMA_IFCR register."
> Oder:
> "Bit 6 OVR: Overrun flag
> 0: No overrun occurred
> 1: Overrun occurred
> This flag is set by hardware and reset by a software sequence."
Das habe ich auch schon mal überprüft aber das TEIF Flag tritt
aufjedenfall beim DMA nicht auf. Das Error FLag beim SPI könnte ich
nochmal überprüfen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|