Forum: Mikrocontroller und Digitale Elektronik SD card über sdio interface mit STM32 HAL


von Johannes S. (Gast)


Lesenswert?

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

von Johannes S. (Gast)


Lesenswert?

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;

von Johannes S. (Gast)


Lesenswert?

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?

von Jim M. (turboj)


Lesenswert?

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.

von Johannes S. (Gast)


Lesenswert?

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;

von Johannes S. (Gast)


Lesenswert?

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);

von Johannes S. (Gast)


Lesenswert?

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.

von Stefan F. (Gast)


Lesenswert?

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?

von Johannes S. (Gast)


Lesenswert?

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.

von Johannes S. (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.