Forum: Mikrocontroller und Digitale Elektronik STM32F030C6T6 SPI DMA Alignment Problem


von Mark J. (markjo)


Angehängte Dateien:

Lesenswert?

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
}

von Andreas B. (abm)


Lesenswert?

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.

von Andreas B. (abm)


Lesenswert?

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.

von Mark J. (markjo)


Lesenswert?

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.

von Wastl (hartundweichware)


Lesenswert?

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.

von Mark J. (markjo)


Lesenswert?

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.

von Wastl (hartundweichware)


Lesenswert?

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.

von Markus M. (adrock)


Lesenswert?

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.

von Andreas B. (abm)


Lesenswert?

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?!

von Mark J. (markjo)


Lesenswert?

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.

von Mark J. (markjo)


Lesenswert?

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.

von Andreas B. (abm)


Lesenswert?

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".

von Mark J. (markjo)


Lesenswert?

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.

von Mark J. (markjo)


Lesenswert?

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).

von Foobar (asdfasd)


Lesenswert?

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.

von Andreas B. (abm)


Lesenswert?

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."

von Mark J. (markjo)


Lesenswert?

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.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.