Forum: Mikrocontroller und Digitale Elektronik STM32F407 und das SPI Modul


von holger (Gast)


Lesenswert?

Beim messen am SPI Modul vom STM32F407 kamen ein paar
merkwürdig Dinge ans Tageslicht.

Diese Routine wurde quasi nach den Beispielen aus der Periphery Library
von ST programmiert. Hier halt nur direkt über die Register.
1
uint16_t SPI2_SendReceive(uint16_t data)
2
{
3
  /*!< Loop while DR register in not empty */
4
  // hk we do not need this if we can be sure last transmission ends before
5
  while ((SPI2->SR & SPI_I2S_FLAG_TXE) == RESET);
6
7
  /*!< Send byte through the SPI2 peripheral */
8
  SPI2->DR = data;
9
10
  /*!< Wait to receive data */
11
  while ((SPI2->SR & SPI_I2S_FLAG_RXNE) == RESET);
12
13
  /*!< Return data read from the SPI bus */
14
  // there is a 500ns pause between transfers.
15
16
  return SPI2->DR;
17
}

Funktioniert auch, ABER zwischen den einzelnen Bytes ist eine ziemlich
grosse Pause von 250ns beim SPI1 und 500ns beim SPI2 zu sehen. Wo kommt 
die denn her?
Die Pause ist unabhängig von der eingestellten SPI Taktrate.

Gut, zweiter Versuch statt 8 Bit gleich 16 Bit übertragen wenn es
die Daten erlauben. Das geht, jetzt hat man nur noch eine Pause
zwischen jeweils 16 Clock Zyklen. Schön ist das aber auch nicht.

Dritter Versuch SPI_I2S_FLAG_RXNE, was wohl der Grund für die Pause ist, 
nicht mehr
abfragen wenn man nur senden möchte. Am Ende dann auf das Busy Flag 
warten.
Ich weiss das das im Datenblatt nicht empfohlen wird. Beim DMA Transfer
allerdings schon. Dazu komme ich später.
1
void SPI2_Send(uint16_t data)
2
{
3
  /*!< Loop while DR register in not empty */
4
  while ((SPI2->SR & SPI_I2S_FLAG_TXE) == RESET);
5
6
  SPI2->DR = data;
7
8
  // after last data send, use SPI2_WaitSend() to be sure transfer has finished
9
}
10
11
uint16_t SPI2_WaitSend(void)
12
{
13
  /*!< Loop while DR register in not empty */
14
  while ((SPI2->SR & SPI_I2S_FLAG_TXE) == RESET);
15
16
  /*!< Wait for transfer finished */
17
  while ((SPI2->SR & SPI_I2S_FLAG_BSY) == SET);
18
  return SPI2->DR; // this read resets SPI_I2S_FLAG_RXNE flag
19
}

Dann einfach mal einen IO Pin vor dem senden auf
High gesetzt, und wenn Busy auf 0 geht auf Low setzen.
1
 SPI2_Send(0xFF);
2
 SPI2_Send(0xFF);
3
 SPI2_WaitSend();

Auf dem Osci sieht man dann warum ST die Busy Abfrage nicht
empfiehlt. Busy geht auf Low bevor die Daten rausgetaktet wurden.
Nach Busy Low kommen noch drei oder vier Takte auf der Clock Leitung.
Na herzlichen Glückwunsch, wie soll man bei einem reinen Sendetransfer
eigentlich feststellen wann die Übertragung beendet ist? Es gibt
ausser Busy kein Flag dafür.

Kommen wir mal zu einem reinen DMA Sendetransfer. Da wird von ST
empfohlen das Busy Flag abzufragen. So wie in SPI2_WaitSend();.
Funktioniert nur nicht. Der selbe Effekt wie oben. Busy geht low
bevor der Transfer beendet ist.


Hat ST das SPI Modul wirklich so vergurkt?

von erhardd (Gast)


Lesenswert?

... ich weis nichtmehr genau wo, -aber hier hat der Autor einige , 
nennen wir sie mal , "Kuriositäten" (s.DMA) zusammengetragen.
Sehr aufschlussreich...
http://blog.frankvh.com

von holger (Gast)


Angehängte Dateien:

Lesenswert?

Hier mal der Sourcecode als Minimalprojekt.
Gleich folgen ein paar Bilder vom Osci.

von holger (Gast)


Angehängte Dateien:

Lesenswert?

Im ersten sieht man das das SPI Modul mit 42MHz läuft.
Im zweiten Bild die Pause zwischen den Übertragungen.

von holger (Gast)


Angehängte Dateien:

Lesenswert?

Hier im 16Bit Modus. Pause nur alle 16Bit.

von holger (Gast)


Angehängte Dateien:

Lesenswert?

Hier 16Bit Send Only. Das verdammte Busy geht runter bevor
die Übertragung beendet ist. Das gleiche passiert bei einer
Send Only DMA Übertragung bei der Übertragung des letzten
Elements.

von erhardd (Gast)


Lesenswert?

... ja, warum?
Nur mal eine These:
der Clock-Impuls ist etwa 23nS lang;
8 Datenimpulse auf MOSI dürften dann theor. etwa 184nS lang sein;
sind aber etwa 200nS;
Fast 1 Clock verzögert. -warum?

von erhardd (Gast)


Lesenswert?

...Frank hatte darauf hingewiesen, finde nurnicht wo...

von erhardd (Gast)


Lesenswert?

...und er hatte auch einen "workaround" dafür;

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.