ich möchte eine SD Karte über das SDIO Interface (nicht SPI) lesen und schreiben. Dazu habe ich in mbed ein Blockdevice angelegt und den Code aus einem BSP von einem STM32 board genommen: https://os.mbed.com/teams/ST/code/BSP_DISCO_F469NI/file/3cdfcc4f7c9d/Drivers/BSP/STM32469I-Discovery/stm32469i_discovery_sd.c/ Das Lesen der SD funktioniert schon einigermassen, ich bekomme das root Dir und ich kann eine Datei öffnen und korrekt lesen. Jetzt hakt es aber beim Schreiben, ich komme bis in den HAL Layer in WriteBlocks und erhalte da einen CRC Fehler. Hat hier jemand Erfahrung mit den SDIO Funktionen in der HAL? https://github.com/ARMmbed/mbed-os/blob/d311a96061ff3526bc805e20eb35774885ace1ec/targets/TARGET_STM/TARGET_STM32F4/device/stm32f4xx_hal_sd.c#L688 noch einen Leidensgenossen gefunden: https://community.st.com/s/question/0D50X00009fEfUeSAK/about-sdio-and-hal-read-write-functions
wenn ich den Transfertakt runterdrehe dann klappts, werde mich wohl mehr mit der Initialisierung beschäfftigen müssen.
1 | uSdHandle.Init.ClockDiv = 8; // SDIO_TRANSFER_CLK_DIV; |
Hat hier jemand Erfahrung mit dem SDIO vom F4? Ich habe nochmal die Initialisierung näher betrachtet. Das Board ist ein STM32F407VET6 "Black", das ist wegen günstig recht verbreitet. Der SDIO clock divider muss hier >=3 sein, damit ist der Takt 48 / 5 MHz = 9,6 MHz. Beim nächstkleineren Teiler und 12 MHz bekomme ich CRC Fehler beim Schreiben. Ich vermute das der Takt auch von der SDC abhängt, aber wie soll man den Einstellen wenn man verschiedene Karten hat? Geht das aus der SDC class oder einer der Infos die man lesen kann hervor?
SD Spec gibt die 25 MHz fest vor - die müssten also alle SD Karten können. Setzt aber halbwegs brauchbares Layout voraus, z.B. kurze Leiterbahnen zwischen Karte und µC. Schau mal lieber nach Deiner Pin Config, nicht dass die SDIO Pins zuwenig drive strength bekommen und daher die Flanken nicht steil genug sind.
ok, danke, da habe ich noch nicht nachgesehen bzw. sollte der HAL code das machen. Für das Board gibt es auch einen Arduino core, da wird mit 24 MHz initialisiert und das scheint auch zu funktionieren. Das könnte ich zum Test auch noch ausprobieren. so sieht der init aus:
1 | /* Common GPIO configuration */ |
2 | gpio_init_structure.Mode = GPIO_MODE_AF_PP; |
3 | gpio_init_structure.Pull = GPIO_PULLUP; |
4 | gpio_init_structure.Speed = GPIO_SPEED_HIGH; |
5 | gpio_init_structure.Alternate = GPIO_AF12_SDIO; |
6 | |
7 | /* GPIOC configuration */ |
8 | gpio_init_structure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; |
Der Cube code initialisert mit GPIO_SPEED_FREQ_VERY_HIGH, habe ich geändert aber das Ergebnis ist gleich, max. 12 MHz für lesen, 9,6 MHz für lesen/schreiben. Hardware Pullups von 10k sind auch vorhanden, ich habe auch GPIO_PULLUP und NOPULLUP probiert.
1 | /* Enable SDIO clock */ |
2 | __HAL_RCC_SDIO_CLK_ENABLE(); |
3 | |
4 | /* Enable DMA2 clocks */ |
5 | __DMAx_TxRx_CLK_ENABLE(); |
6 | |
7 | /* Enable GPIOs clock */ |
8 | __HAL_RCC_GPIOC_CLK_ENABLE(); |
9 | __HAL_RCC_GPIOD_CLK_ENABLE(); |
10 | |
11 | /* Common GPIO configuration */ |
12 | gpio_init_structure.Mode = GPIO_MODE_AF_PP; |
13 | gpio_init_structure.Pull = GPIO_PULLUP; |
14 | gpio_init_structure.Speed = GPIO_SPEED_FREQ_VERY_HIGH; |
15 | gpio_init_structure.Alternate = GPIO_AF12_SDIO; |
16 | |
17 | /* GPIOC configuration */ |
18 | gpio_init_structure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12; |
19 | |
20 | HAL_GPIO_Init(GPIOC, &gpio_init_structure); |
21 | |
22 | /* GPIOD configuration */ |
23 | gpio_init_structure.Pin = GPIO_PIN_2; |
24 | HAL_GPIO_Init(GPIOD, &gpio_init_structure); |
Es funktioniert, danke Hilfe von stevestrong vom stm32duino Forum. Für die Nachwelt: Zum SDIO gibt es einige Errata, z.B. funktionert hardware flow control mit dem Datenfifo nicht. Im debug build macht der HAL Code zuviele Funktionsaufrufe und der Sendefifo läuft leer. Im release build werden die wegoptimiert und der Datentransfer läuft mit vollen 24 MHz im 4 Bit mode.
Darf ich mal 'was einwerfen? Ich lese hier jede Woche von schwierigen Problemen mit STM32, die am Ende mit Verweis auf die Errata behoben werden. Auch ich hatte gleich an meinem ersten Wochenende zwei unerwartete Probleme: Beim ersten Problem war die Konfiguration des Taktgeber (made by Cube MX) so falsch, dass der µC sich während dessen aufhing. Daher versuchte ich die Programmierung ohne HAL - übrigens mit Erfolg. Direkt danach funktionierte die I²C Schnittstelle nicht, obwohl ich mich an die krude Sequenz aus der Application Note hielt. Ursache war ein Bug, der im Errata beschrieben war. Daraus lerne ich: Dass Errata Dokument und die Application Notes sind bei STM32 offensichtlich Pflichtlektüre. Nicht nur bei mir. Ich weiß, dass es für AVR auch Errata gibt. Aber die habe ich in 10 Jahren noch nie gebraucht. Ich hatte nur einmal aus Neugier herein geschaut und dabei bemerkt, dass die für mich relevanten Fehler bereits vor vielen Jahren behoben wurden. Bei STM32 scheinen zahlreiche Fehler hingeben lange zu bestehen. Und bei jedem neuen Modell werden die Errata Dokumente gefühlt länger statt kürzer. Dennoch heißt es hier immer wieder, man solle Anfängern nicht die AVR µC empfehlen, weil bei STM32 ja alles einfacher und besser sei. Wo ist die Logik darin?
Stefanus F. schrieb: > Dennoch heißt es hier immer wieder, man solle Anfängern nicht die AVR µC > empfehlen, weil bei STM32 ja alles einfacher und besser sei. Wo ist die > Logik darin? die STM32 sind nicht unbedingt einfacher, das behaupte ich schon nicht mehr. Aber sie (und andere Cortex-M natürlich auch) haben deutlich komplexere und leistungsfähigere Peripherie. Einige Probleme scheinen daher zu kommen das da verschiedene Clockdomains zusammenarbeiten und die Synchronisation zickig ist. Das sowas schon bei 'simplen' Sachen wie SPI zuschlägt macht es für Anfänger nicht einfach. Daher empfehle ich gerne die LPC von NXP (bin nicht mit denen verwandt oder verschwägert) weil die Peripherie viel mehr 32 Bit breite nutzt und irgendwie intuitiver zu programmieren ist. Die STM32 haben für mich die Nase in Sachen Grafik vorne und das STM32F407VE Board bekommt man für ca. 10€ und für noch einen 10er gibts ein TFT dazu das man nur aufstecken braucht. Ansteuerung per FSMC sauschnell. Da gibt es zur Zeit nichts vergleichbares. In mbed wird für STM die HAL verwendet und deshalb habe ich das jetzt auch genutzt. Da diese SW auch von ST kommt sehe ich das als Referenz und Erratas sollten darin auch berücksichtigt sein. Ob das immer so ist weiss ich allerdings nicht. Und bei diesem letzten Fehler war das Problem der sonst saubere Aufbau mit mehreren Schichten, nur im Debug build zu langsam. Ich weiss das über HAL viel gemeckert wird, wenn ich da so blödsinnige Abfragen sehen verstehe ich auch warum, aber so ein SDC interface würde ich nicht in 3 Tagen aus Datenblättern zusammenschreiben.
1 | if((Timeout == 0U)||((HAL_GetTick()-tickstart) >= Timeout)) |
Also wenn die Funktion ein Timeout 0 übergeben bekommt wird immer ein Fehler gemeldet, auch wenn es kein Timeout gab. Die Jungs von stm32duino haben im libmaple core das ohne HAL hinbekommen, aber da haben die sicher ein paar Stunden an der Implementierung gesessen.
ich habe noch ein Problem mit dem SDIO Interface: wenn ich eine Sequenz
1 | init_sdio(); // ok |
2 | deinit_sdio(); // ok |
3 | init_sdio(); // not ok |
habe dann funktioniert das erste Initalisieren, aber folgende schlagen fehl. Im Init wird der 4 Bit SDIO mode aktiviert, dazu wird in der HAL das SCR abgefragt ob die Karte das unterstützt. Beim ersten Aufruf nach einem Reset liefert das SCR Lesen korrekte Werte, bei folgenden hängt der call SD_Find_SCR() in einer Endlosscheife und bekommt nicht die abgefragten Flags. Find_SCR löst ein Kommando 51 aus. https://github.com/ARMmbed/mbed-os/blob/a5b757312d875521a06de42d898d5d00a86b1a0e/targets/TARGET_STM/TARGET_STM32F4/device/stm32f4xx_hal_sd.c#L2789 Wenn ich wie hier vorgeschlagen https://blog.frankvh.com/2011/09/04/stm32f2xx-sdio-sd-card-interface/ das Find_SCR() einfach weglasse und in den WideBus Mode umschalte dann funtioniert auch alles. Was mich eben nur wurdert das es nach dem Reset ok ist, also müsste das init etwas verstellen das ein zweites init fehlschlägt (deinit kann ich auch weglassen, gleicher Fehler). Kennt jemand das Problem? Fragen zu dem Problem habe ich schon gefunden, aber noch keine guten Antworten. Das deinit() macht ein SD PowerOff, das init() ein PowerOn, damit müsste die Karte doch resettet werden?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.