Probleme mit SPI - STM32F2

Gast #3122620
Lesenswert?

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.
#3125403
Lesenswert?

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
#3125431
Lesenswert?

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 #3129995
Lesenswert?

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 ?
Gast #3130378
Lesenswert?

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 #3130448
Lesenswert?

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 #3130457
Lesenswert?

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 #3130527
Lesenswert?

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 #3131175
Lesenswert?

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 #3131220
Lesenswert?

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
}
#3131236
Lesenswert?

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 #3131237
Lesenswert?

@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 #3131576
Lesenswert?

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 #3132167
Lesenswert?

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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren