Forum: Mikrocontroller und Digitale Elektronik SD-Karte am STM32 sendet keine Antwort auf CMD0


von Arne F. (-arne-)


Lesenswert?

Hallo,

ich nehme gerade SD-Karten an einem STM32F103RBT6 (Evalboard 
ET-STM32F103) über SPI in Betrieb. Das klappt auch mit den meisten 
meiner Karten (32MB MMC bis 8GB SDHC), einige andere (z.B. Medion und 
eine SanDisk) reagieren jedoch partout nicht auf einen 
Initialisierungsversuch mittels CMD0. Mit denselben Karten hatte ich 
früher auch bereits an einem Atmel Probleme.
SPI Takt liegt unter 400kHz, interner Pull-up an MISO ist aktiv. Ich 
kann auch mit etlichen Wiederholungen (s. Code unten) keine Reaktion an 
MISO erkennen (auch Oszi triggert nicht).

In den diversen Diskussionen um CMD0-Probleme hier im Forum habe ich 
keine brauchbare Erklärung gefunden. Hat jemand eine Idee?
Gibt es entgegen aller Behauptungen evtl. doch Karten, die SPI nicht 
unterstützen? Oder wo liegt mein (Denk-)Fehler?


Hier mein Codefragment (auf's Wesentliche reduziert und mittlerweile um 
etliche Wiederholungen angereichert):
1
   // enable the SPI GPIO clock
2
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
3
4
   // disable card's CS before enabling pin to avoid pulses/glitches
5
   GPIO_SetBits (SD_GPIO, SD_PIN_NSS);
6
7
   GPIO_InitTypeDef  GPIO_InitStructure;
8
9
   // set MISO as Input with pull-up enabled
10
   GPIO_InitStructure.GPIO_Pin = SD_PIN_MISO;
11
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
12
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
13
   GPIO_Init(SD_GPIO, &GPIO_InitStructure);
14
15
   // set SCK and MOSI as alternate function output (push/pull)
16
   GPIO_InitStructure.GPIO_Pin = SD_PIN_SCK | SD_PIN_MOSI;
17
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
18
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
19
   GPIO_Init(SD_GPIO, &GPIO_InitStructure);
20
21
   // set NSS as output push/pull
22
   GPIO_InitStructure.GPIO_Pin = SD_PIN_NSS;
23
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
24
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
25
   GPIO_Init(SD_GPIO, &GPIO_InitStructure);
26
27
   // init SPI with approx. 280KHz clock
28
   RCC_APB2PeriphClockCmd (RCC_APB2Periph_SPI1, ENABLE);
29
   SPI_InitTypeDef SPI_InitStructure;
30
   SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
31
   SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
32
   SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
33
   SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
34
   SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
35
   SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
36
   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
37
   SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
38
   SPI_InitStructure.SPI_CRCPolynomial = 7; // ?
39
   SPI_Init (SPI1, &SPI_InitStructure);
40
41
   // enable SPI
42
   SPI_Cmd(SPI1, ENABLE);
43
44
   // wait 1ms after power on
45
   delay_ms(1);
46
47
   // ----- wait more than 74 clock cycles while card is disabled
48
   uint8_t res;
49
   uint32_t i;
50
   for (i=0; i<10000; ++i) //todo: reset to 10 again...
51
   {
52
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
53
      SPI_I2S_SendData(SPI1, 0xff);
54
   }
55
56
   uint32_t retries = 0;
57
   uint32_t timeout = 0;
58
   do
59
   {
60
61
      // ----- wait for transmission complete and enable card CS
62
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
63
      GPIO_ResetBits (SD_GPIO, SD_PIN_NSS);
64
65
      // ----- send CMD0
66
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
67
      SPI_I2S_SendData(SPI1, 0x40);
68
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
69
      SPI_I2S_SendData(SPI1, 0x00);
70
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
71
      SPI_I2S_SendData(SPI1, 0x00);
72
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
73
      SPI_I2S_SendData(SPI1, 0x00);
74
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
75
      SPI_I2S_SendData(SPI1, 0x00);
76
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
77
      SPI_I2S_SendData(SPI1, 0x95);
78
79
      // ----- read R1 response
80
      timeout = 0;
81
      do
82
      {
83
         while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
84
         SPI_I2S_ReceiveData (SPI1); // clear RNXE
85
         SPI_I2S_SendData(SPI1, 0xff); // start transmission
86
         while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); // wait for data
87
         res = SPI_I2S_ReceiveData (SPI1);
88
      }
89
      while ((res == 0xff) && (++timeout<100));
90
91
      // ----- wait for transmission complete and disable card CS
92
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
93
      GPIO_SetBits (SD_GPIO, SD_PIN_NSS);
94
      SPI_I2S_SendData(SPI1, 0xff); // 8 clock cycles while card is not selected to finish operation
95
   }
96
   while ((res == 0xff) && (++retries<100));
97
98
   SDC_TRACE_DEBUG(("SD: CMD0 returned %u, retries:%u, timeout:%u", res, retries, timeout));
99
100
101
   while (1);

von Arne F. (-arne-)


Lesenswert?

hm, niemand eine Idee oder ein ähnliches Problem?
Na, dann sind die zwei neuen ALDI Karten wohl für die Tonne (bzw. die 
Digitalkamera ;-)

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Arne F. schrieb:
> hm, niemand eine Idee oder ein ähnliches Problem?
> Na, dann sind die zwei neuen ALDI Karten wohl für die Tonne (bzw. die
> Digitalkamera ;-)

Soll ich dir meine Adresse schicken? ;-)

Ich kann mir vorstellen, dass es an den Pullups ligen könnte. Laut 
SD-Spezifikationen sollen die ca. 50 bis 100 kOhm haben. Bin mir jetzt 
nicht mehr ganz sicher.

Aber schalte doch mal die internen Pullups aus und häng 
51-kOhm-Widerstände hin.

Ah, grad wieder gefunden: Such hier mal nach "pullup":
http://elm-chan.org/docs/mmc/mmc_e.html

von Arne F. (-arne-)


Lesenswert?

sollte mit dem internen Pull-up von ca. 40kOhm eigentlich passen. In 
einer SanDisk Spec habe ich sogar was von 10..100kOhm gefunden. Ist aber 
auf jeden Fall eine Idee, die ich demnächst mal ausprobieren werde.

von Philipp (Gast)


Lesenswert?

Hallo,
also ich habe meinen Treiber für SD Karten am STM32 auch selbst 
geschrieben und bin gerade am FAT32+LFN dran, aber ich kann dir eines 
sagen, nicht alle Karten verstehen SPI Mode. Vor allem die NoName können 
es nicht und solche die bei Geräten dabei sind (Medion). SanDisk, 
Platinum, Kingston, ... die verstehen SPI-Mode.

lg

von Arne F. (-arne-)


Lesenswert?

bin heute zufällig drauf gestoßen:
Es handelt sich um Micro-SD Karten. Das Problem waren nicht die Karten 
selbst, sondern die Adapter. Mit einem anderen Micro-SD -> SD Adapter 
funktioniert's. Is schon merkwürdig...

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.