Probleme mit SPI - STM32F2

Gast #3122620
Hallo,

ich habe folgendes Problem mit der SPI Kommunikation auf dem STM32F2.
Um von einem Flashspeicher die ID auszulesen führe ich folgende 
Funktionen aus.
1
    // Read ID
2
    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE)==RESET);
3
    SPI_I2S_SendData(SPIx, 0xAB);
4

5
    // Dummy byte
6
    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE)==RESET);
7
    SPI_I2S_SendData(SPIx, 0x0);
8

9
    // Dummy byte
10
    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE)==RESET);
11
    SPI_I2S_SendData(SPIx, 0x0);
12

13
    // Dummy byte
14
    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE)==RESET);
15
    SPI_I2S_SendData(SPIx, 0x0);
16

17
    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE)==RESET);
18
    SPI_I2S_SendData(SPIx, 0x0);
19

20
    // Read byte
21
    while ( SPI_I2S_GetFlagStatus( SPIx, SPI_I2S_FLAG_RXNE ) == RESET );
22
    ReadID = SPI_I2S_ReceiveData(SPIx);

Beim ersten mal erscheint nicht die gewünscht ID. Beim zweiten mal wird 
die korrekte ID in die Variable ReadID abgelegt.

Was müsste getan werden, damit beim ersten mal die ID in der Variable 
abgelegt wird ?

In der Initialisierungsroutine habe ich auch schon folgendes getestet.
1
    //Dummy-Read zum Entleeren des Rx-Buffers
2
    if(SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_RXNE) == SET)
3
      SPI_I2S_ReceiveData(SPIx);

Der Fehler tritt nach wie vor auf.
Gast
Was für einen Flashspeicher benutzt du denn genau?
Braucht der vielleicht eine gewisse Zeit oder bestimmte Anzahl an Takten 
auf dem CLK-Signal zum Initialisieren?
Hallo EmbeddedUser,

ich habe das so gemacht:
1
uint8_t spi2_putc(uint16_t data) {
2
  FPGA_DESELECT();
3
  // make sure the transmit buffer is free
4
  while (SPI_I2S_GetFlagStatus(SPI2_PORT, SPI_I2S_FLAG_TXE) == RESET);
5
  SPI_I2S_SendData(SPI2, data);
6
  // and then be sure it has been sent over the wire
7
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
8
  data=SPI_I2S_ReceiveData(SPI2);
9

10
  while (SPI_I2S_GetFlagStatus(SPI2_PORT, SPI_I2S_FLAG_TXE) == RESET);
11
  SPI_I2S_SendData(SPI2, 0);
12
  // and then be sure it has been sent over the wire
13
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
14
  data=SPI_I2S_ReceiveData(SPI2);
15

16
  while (SPI_I2S_GetFlagStatus(SPI2_PORT, SPI_I2S_FLAG_TXE) == RESET);
17
  SPI_I2S_SendData(SPI2, 0);
18
  // and then be sure it has been sent over the wire
19
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
20
  data=SPI_I2S_ReceiveData(SPI2);
21

22
  while (SPI_I2S_GetFlagStatus(SPI2_PORT, SPI_I2S_FLAG_TXE) == RESET);
23
  SPI_I2S_SendData(SPI2, 0);
24
  // and then be sure it has been sent over the wire
25
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
26
  data=SPI_I2S_ReceiveData(SPI2);
27

28
  while (SPI_I2S_GetFlagStatus(SPI2_PORT, SPI_I2S_FLAG_TXE) == RESET);
29
  SPI_I2S_SendData(SPI2, 0);
30
  // and then be sure it has been sent over the wire
31
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
32
  data=SPI_I2S_ReceiveData(SPI2);
33

34

35
  FPGA_SELECT();
36
  return data;

vielleicht hilft es dir weiter...

viele grüße Tobias
So... hab es nochmal ein wenig "hübscher" gestaltet.
1
uint8_t spi_Read_ID(uint8_t data) {
2
  EPCS_SELECT();
3

4
  // Send Operation Code
5
  // make sure the transmit buffer is free
6
  while (SPI_I2S_GetFlagStatus(SPI2_PORT, SPI_I2S_FLAG_TXE) == RESET);
7
  SPI_I2S_SendData(SPI2, data);
8
  // and then be sure it has been sent over the wire
9
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
10
  data=SPI_I2S_ReceiveData(SPI2);
11

12
  // Send 3 Dummy bytes and 1 to Read the ID
13
  for (uint8_t i=0; i!=4; i++){
14
  // make sure the transmit buffer is free
15
  while (SPI_I2S_GetFlagStatus(SPI2_PORT, SPI_I2S_FLAG_TXE) == RESET);
16
  SPI_I2S_SendData(SPI2, 0);
17
  // and then be sure it has been sent over the wire
18
  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
19
  data=SPI_I2S_ReceiveData(SPI2);
20
  }
21

22
  EPCS_DESELECT();
23
  return data;
24
}

viele grüße
Gast
Guten Morgen Tobias S.,

vielen Dank für deine Beiträge.

Mit welcher Datei von Quartus || wird der EPCS Flash Controller 
beschrieben ? Ist es womöglich die Datei mit der Endung jic ?
Ab welcher Adresse soll der EPCS Flash Controller beschrieben werden ?
Hallo EmbeddedUser,

hmm... wenn du das EPCS wirklich seriell mit einen µC beschreiben 
möchtest. bleibt eigentlich "nur" das "Raw binare File". Dieses File 
muss 1:1 ab der Adresse 0x000000 in das EPCS geladen werden.

Das "jic"-File wäre JTag.

Viele Grüße Tobias
Gast
Hallo Tobias S.,

ich kann in dem Projekt kein Bin-File sehen. Muss ich dieses File mit 
einem zusätzlichen Tool erzeugen ?

Ich habe bezüglich dem EPCS Flash Controller noch eine weiteres Problem.
Wie beschreibst du die Sectoren ? Das seitenweise (256 Bytes) 
beschreiben des EPCS Flash Controller funktioniert soweit.
Gast
Die Write_Page Funktion sieht bei mir so aus:
1
int Write_Page(char *data, int len, unsigned long addr)
2
{
3
    ChipSEL();
4

5
    SendOpCode(0x02); // Operation Code = 0x02
6

7
    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE)==RESET);
8
    SPI_I2S_SendData(SPIx, (unsigned char)(addr>>16));
9

10
    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE)==RESET);
11
    SPI_I2S_SendData(SPIx, (unsigned char)(addr>>8));
12

13
    while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE)==RESET);
14
    SPI_I2S_SendData(SPIx, (unsigned char)(addr));
15

16
    // Data
17
    for(int i=0; i<Length; i++)
18
    {
19
      while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE)==RESET);
20
      SPI_I2S_SendData(SPIx, *Data);
21
      Data++;
22
    }
23

24
    Sleep(7); // delay time = 7 ms
25

26
    ChipDESEL();
27

28
    return 1;
29
}

Bevor ich diese Funktion ausführe wird ein Write_Enable ausgeführt. Nach 
Write_Page wird ein Write_Disable durchgeführt. Sobald ich einen Sektor 
beschreiben möchte (256 Pages) wird das Debugging automatisch 
unterbrochen. Ich kann den Fehler nicht finden.
Gast
Ja meinst du nun das *.rpd oder das *.rbf File. Das *.rpd File kann so 
wie es aussieht nur mit dem Tool SRunner benutzt werden. Also ich meine 
es müsste das *.rbf (Raw binary file) File sein
Gast
Wie müsste der genauere Ablauf aussehen, wenn ein Sektor beschrieben 
werden soll ? Irgendwas stimmt ja bei mir nicht ganz. Der Debugger bzw. 
Mikrocontroller hängt sich bei mir auf.
Gast
Ich warte bevor ich ein Byte versende ob das Flag "SPI_I2S_FLAG_TXE" 
wieder zurückgesetzt wird.
1
while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE)==RESET);

Wenn ich eine Page beschreibe dann habe ich keine Probleme.
Gast
Hier ist ein Auszug aus meiner Applikation:

1
void main(void)
2
{  
3
  Time = Get_Time();
4

5
  id = ReadID();
6
  _delay();
7

8
  for(int i=0; i<256; i++)
9
  {
10
    EpcsData[i] = 0xAA;
11
  }
12
  
13
  Write_Enable();
14
  _delay();
15
  Erase_Bulk();
16
  _delay();
17
  Write_Disable();
18
  _delay();
19

20
  while (1)
21
  {
22
    if ( Time_Passed(&Time) )
23
    {
24
      for(int i = 256; i<256; i++)
25
      {
26
        Write_Enable();
27
        Sleep(5); // 5 ms
28
        Write_Page(EpcsData,256,i*0x00100); // 1. Paramter=Daten, 2. Paramter=Länge der Daten, 3. Parameter= Adresse
29
        Sleep(5); // 5 ms
30
        WriteDisable();
31
        _delay();
32
      }
33
      // 1. Paramter=Daten und 2. Parameter=Länge (werden noch nicht an die Applikation weitergereicht), 3. Parameter= Adresse
34
      Read_Page(0,0,0x00500);  
35
      _delay();
36
      
37
      Time = Get_Ahead_Time(1000); // 1 sec  
38
    }
39
  }
40
}
Gast
Guten Morgen Tobias S.,

EpcsData ist 256 Byte groß. Die for Schleife ist natürlich falsch.
Die for Schleife sieht natürlich so aus:
1
for(int i = 0; i<256; i++)
2
{
3
 ....
4
}
Gast
Es muss an dieser for Schleife liegen. Wie kann mit dem STM32 256 Bytes 
per SPI versendet werden, ohne dass der Mikrocontroller sich aufhängt ? 
Es muss doch möglich sein. Ich habe soeben auch die Interrupt Variante 
ausprobiert. Da passiert es auch.

1
for(int i=0; i<256; i++)
2
{
3
  while (SPI_I2S_GetFlagStatus(SPIx, SPI_I2S_FLAG_TXE)==RESET);
4
  SPI_I2S_SendData(SPIx, DATEN_BYTE);
5
}
Anbei mein Code, aber ich bin auch noch am Programmieren... Also keine 
Garantie ;)
1
void spi_Write_Page(char *data, uint32_t adr){
2
  char  Write_in_Prog = 3;
3

4
  spi_Write(1);
5
  EPCS_SELECT();
6
  spi_send_Bytes(0x02,0,0);
7
  spi_send_Bytes(adr>>16,0,0);
8
  spi_send_Bytes(adr>>8,0,0);
9
  spi_send_Bytes(adr,0,0);
10

11
  for(int i=0; i!=0x100; i++){
12
    // make sure the transmit buffer is free
13
       while (SPI_I2S_GetFlagStatus(SPI2_PORT, SPI_I2S_FLAG_TXE) == RESET);
14
       SPI_I2S_SendData(SPI2, *data);
15
       // and then be sure it has been sent over the wire
16
       while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
17
       data++;
18
    }
19
  EPCS_DESELECT();
20

21
  while (Write_in_Prog==3){
22
    Write_in_Prog=spi_Read_Status();
23
    }
24
}
25

26
void spi_Write_Sektor(char *data, char len){
27
  for (uint16_t i=0; i!=len; i++){
28
    spi_Write_Page(data,i*0x00100);
29
    data=data+0x100;
30
    }
31
}
Gast
@EmbeddedUser

In deiner WritePage Funktion fehlt die Abfrage, ob das Flash ready ist. 
Dazu das Status-Register auslesen und das entsprechende Bit auswerten. 
Am einfachsten ist es, diese Abfrage vor jedem Löschen, Schreiben und 
Lesen zu machen, kostet nur so eine µs. Und die ganzen delays raus aus 
dem Programm.

MfG Klaus
Gast
Wo müsste genau müsste in der for Schleife die Abfrage erfolgen und 
welches Bit ? Damit auf den Speciher geschrieben werden kann, müsste 
laut Datenblatt das Bit 0 vom Status Register 0 sein.
Gast
EmbeddedUser schrieb:
> Damit auf den Speciher geschrieben werden kann, müsste
> laut Datenblatt das Bit 0 vom Status Register 0 sein.

Ich benutze eine andere CPU, die Bedeutung deiner SPI Register kenne ich 
nicht.

Ich mache die Abläufe so:

Vor jedem Löschen, Schreiben oder Lesen warte ich, bis Bit 0 vom Status 
Register des Flashs 0 ist.

Das kann man so machen: READ STATUS Kommando senden und ein Byte 
zurücklesen. Dann CS wieder auf 1. Bit 0 von dem Byte auswerten und 
nochmal von vorne, wenn nicht 0;

Oder CS auf low, READ STATUS senden und solage Bytes lesen, bis Bit 0 
nicht mehr gesetzt ist. Dann CS wieder auf high.

Feiglinge setzen noch einen Loopcounter als Timeout darüber ;-) kann 
aber beim Löschen ganz schön lange dauern (500ms pro Sektor wenn ich 
mich recht erinnere)

Danach kann man alles machen, z.B. READ und Startadresse ausgeben (4 
Byte) und lesen bis der Flash zuende ist. Delays sind nirgenwo 
erforderlich, die Bits bekommt man auch mit 25 MHz ohne Pause.

So macht das das FPGA, 0x03 0x00 0x00 0x00 ausgeben und Bytes eintakten 
bis fertig.

MfG Klaus

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 13 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.