Datum:
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); |
Datum:
hm, niemand eine Idee oder ein ähnliches Problem? Na, dann sind die zwei neuen ALDI Karten wohl für die Tonne (bzw. die Digitalkamera ;-)
Datum:
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
Datum:
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.
Datum:
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
Datum:
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...