www.mikrocontroller.net

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


Important announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Arne F. (-arne-)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht 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):
   // enable the SPI GPIO clock
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

   // disable card's CS before enabling pin to avoid pulses/glitches
   GPIO_SetBits (SD_GPIO, SD_PIN_NSS);

   GPIO_InitTypeDef  GPIO_InitStructure;

   // set MISO as Input with pull-up enabled
   GPIO_InitStructure.GPIO_Pin = SD_PIN_MISO;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(SD_GPIO, &GPIO_InitStructure);

   // set SCK and MOSI as alternate function output (push/pull)
   GPIO_InitStructure.GPIO_Pin = SD_PIN_SCK | SD_PIN_MOSI;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(SD_GPIO, &GPIO_InitStructure);

   // set NSS as output push/pull
   GPIO_InitStructure.GPIO_Pin = SD_PIN_NSS;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(SD_GPIO, &GPIO_InitStructure);

   // init SPI with approx. 280KHz clock
   RCC_APB2PeriphClockCmd (RCC_APB2Periph_SPI1, ENABLE);
   SPI_InitTypeDef SPI_InitStructure;
   SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
   SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
   SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
   SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
   SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
   SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
   SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
   SPI_InitStructure.SPI_CRCPolynomial = 7; // ?
   SPI_Init (SPI1, &SPI_InitStructure);

   // enable SPI
   SPI_Cmd(SPI1, ENABLE);

   // wait 1ms after power on
   delay_ms(1);

   // ----- wait more than 74 clock cycles while card is disabled
   uint8_t res;
   uint32_t i;
   for (i=0; i<10000; ++i) //todo: reset to 10 again...
   {
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
      SPI_I2S_SendData(SPI1, 0xff);
   }

   uint32_t retries = 0;
   uint32_t timeout = 0;
   do
   {

      // ----- wait for transmission complete and enable card CS
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
      GPIO_ResetBits (SD_GPIO, SD_PIN_NSS);

      // ----- send CMD0
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
      SPI_I2S_SendData(SPI1, 0x40);
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
      SPI_I2S_SendData(SPI1, 0x00);
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
      SPI_I2S_SendData(SPI1, 0x00);
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
      SPI_I2S_SendData(SPI1, 0x00);
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
      SPI_I2S_SendData(SPI1, 0x00);
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
      SPI_I2S_SendData(SPI1, 0x95);

      // ----- read R1 response
      timeout = 0;
      do
      {
         while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
         SPI_I2S_ReceiveData (SPI1); // clear RNXE
         SPI_I2S_SendData(SPI1, 0xff); // start transmission
         while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET); // wait for data
         res = SPI_I2S_ReceiveData (SPI1);
      }
      while ((res == 0xff) && (++timeout<100));

      // ----- wait for transmission complete and disable card CS
      while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET);
      GPIO_SetBits (SD_GPIO, SD_PIN_NSS);
      SPI_I2S_SendData(SPI1, 0xff); // 8 clock cycles while card is not selected to finish operation
   }
   while ((res == 0xff) && (++retries<100));

   SDC_TRACE_DEBUG(("SD: CMD0 returned %u, retries:%u, timeout:%u", res, retries, timeout));


   while (1);

Autor: Arne F. (-arne-)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht 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 ;-)

Autor: Markus Weber (Firma: guloshop.de) (m-w)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht 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

Autor: Arne F. (-arne-)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht 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.

Autor: Philipp (Gast)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht 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

Autor: Arne F. (-arne-)
Datum:

Diesen Beitrag bewerten:
lesenswert
nicht 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...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel




Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder GIF-Format hochladen.
Siehe Bildformate
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken erkennst du die Nutzungsbedingungen an.

webmaster@mikrocontroller.netImpressumNutzungsbedingungenWerbung auf Mikrocontroller.net