Forum: Mikrocontroller und Digitale Elektronik STM32: Mass-Storage Beispiel (USB-FS Device Lib)


von Mehmet K. (mkmk)


Lesenswert?

Servus allerseits

Wenn wir jetzt mal jene dummen Fehler ausblenden, die ja die meiste Zeit 
verschlucken, ging die Umsetzung des Mass-Storage Beispiels aus der 
USB-Library recht flott.

Nur: Arbeitet die Bibliothek überhaupt mit SDHC ? Nachdem ich mich 
ohne Ergebnis lange am Kopf gekratzt hatte, setzte ich eine normale SD 
Karte (128MB) ein, die prompt erkannt wurde.
Bei der SDHC haengt die Initialisierung beim Befehlt 
SD_CMD_SEND_OP_COND.

Die Geschwindigkeit betraegt bei einer 22 MB grossen Datei:
Bei 9MHz SPI-Takt
schreiben: 170 kBytes/sec
lesen: 250kBytes/sec

Bei 18MHz SPI-Takt
schreiben: 198 kBytes/sec
lesen: 270kBytes/sec

Der MCU selbst arbeitet mit 72MHz.

In meinem Projekt ist diese langsame Schreibgeschwindigkeit überhaupt 
kein Problem.
Aber die Speicherkarte muss min. 8 GB gross sein und das Lesen sollte 
schon 500kB/s oder mehr betragen. Okay, die momentan verwendete Karte 
ist 'ne uralte Kodak Karte. Aber ich glaube, dass eine neueren Datums 
den Kohl auch nicht fetter machen wird.

Wie geht Ihr vor, wenn Ihr schnell von einer SD-Karte lesen müsst?

von Mehmet K. (mkmk)


Lesenswert?

Jetzt habe ich es mit einer neueren 2GB Karte versucht. Das Schreiben 
geht noch langsamer:

Schreiben: 90 kBytes/s
Lesen: 260kBytes /s

von Jim M. (turboj)


Lesenswert?

> Nur: Arbeitet die Bibliothek überhaupt mit SDHC ?
Ob eine SD Bibliothek SDHC unterstützt, erkennt man recht leicht an der 
"Sektor lesen" Routine. Die muss nämlich die Adresse bei SD und SDHC 
unterschiedlich behandeln, SD hat die Addresse in Bytes während SDHC 
ganze Sektoren - also 512 Byte - addressiert.

> Bei der SDHC haengt die Initialisierung beim Befehlt
> SD_CMD_SEND_OP_COND.

Welches Argument wird da übergeben? Bei "0" gibts keinen SDHC Support, 
die möchten da das HCS Bit haben.

Deine Übertragungsraten ergeben sich, wenn man den "Single sector read" 
Befehl erst dann ausführt, wenn man die Daten versenden will. Dann 
wartet man nämlich auf die SD, versendet die Daten über USB, dann wieder 
warten auf SD, usw. => mehr Wartezeit als Übertragungszeit.

Will man über USB 12MBit auch nur in die Nähe der 500kB/s kommen, muss 
man parallel arbeiten, d.h. während man einen Sektor über USB ausgibt, 
liesst man den nächsten via SPI ein. Nachteil: Deutlich komplexerer Code 
mit einer gerne mal fehleranfälligen Synchronisation. Keine Ahnung ob es 
das als Open Source gibt, ich hab das selber geschrieben.

Aber für SDHC brauchst Du wohl auch eine andere Bibliothek - und FAT32.

von Mehmet K. (mkmk)


Lesenswert?

Danke für die Infos. Habe heute mich auch dazu entschieden, das Ganze 
selber zu schreiben.
Mal schauen .... :)

von Bernhard S. (menecken)


Lesenswert?

Hat jemand von euch ein funktionierendes USB-Beispiel für - oder sogar 
eine Projektdatei - für CooCox CoIDE? Ich wäre euch wirklich unendlich 
dankbar!

Viele Grüße

von Jan B. (berge)


Lesenswert?


von gnuopfer (Gast)


Lesenswert?

Hallo,

Die Geschwindigkeit ist bei 72 Mhz durch die CPU-Leistung beschränkt.
Hier ein paar Werte die mit einem STM32F103@72Mhz erzeugt wurden:

2 Mb Datei Schreiben : 173 kb/s
2 Mb Datei Lesen:     1900 kb/s

Die Anbindung der SDCard war dabei über 18Mhz SPI, nicht SDIO.
Es wurde die emFile Lib von Segger verwendet. Die Grösse & Speedklasse
der SDCard hatte auf die Werte kaum Einfluss. Die höhere 
Lesegeschwindigkeit
kommt vermutlich vom read-ahead cache der Segger lib.


mfg

von greg (Gast)


Lesenswert?

gnuopfer schrieb:
> Die Geschwindigkeit ist bei 72 Mhz durch die CPU-Leistung beschränkt.
> Hier ein paar Werte die mit einem STM32F103@72Mhz erzeugt wurden:

Sieht eher so aus, als wäre die Lesegeschwindigkeit durch SPI beschränkt 
und die Schreibgeschwindigkeit durch zu wenig Buffering?

von Bernhard S. (menecken)


Lesenswert?

Hey Jan,

tausend Dank dir für den Link. Versuche grade das Beispiel auf den 
STM32F103 zu portieren - du hast nicht zufällig den gleiche link für 
STM32F1x?

Tausend Dank nochmals!

von Jan B. (berge)


Lesenswert?

Sorry, nein, mir ist keine ähnliche Seite für den STM32F1x bekannt.

Im Mibgration und compatibility Guide 
(http://www.st.com/web/en/resource/technical/document/application_note/DM00024853.pdf) 
steht, dass die SW compatibility "Full" ist. Eigentlich dürftest du 
daher nichts an den SPI Routinen ändern müssen. Aber andere (z.B. GPIO) 
erfordern ein paar Änderungen.

von gnuopfer (Gast)


Lesenswert?

greg schrieb:

> Sieht eher so aus, als wäre die Lesegeschwindigkeit durch SPI beschränkt
> und die Schreibgeschwindigkeit durch zu wenig Buffering?

OK, falsche Wortwahl. Mit "CPU" meine den Controller selbst, nicht die 
SDCard.
Intern ist der der SPI-Bus der limitierende Faktor, mit 4bit-SDIO get es 
ca. 2.5x so schnell. Die Schreibewerte gelten für synchrones, 
sektorweises Schreiben ohne Cache. Anders zu schreiben macht m.E. keine 
Sinn wenn der User die SDCard jederzeit rausnehmen kann.
Es ist schon einige Zeit her, dass ich mich damit beschäftigt habe, kann 
mich aber erinnern dass die Lese-Werte recht nach am physikalisch 
möglichen Durchsatz des SPI interfaces waren (bei 18Mhz SPI Clock).


mfg

von Bernhard S. (menecken)


Lesenswert?

Versuche grade das USART Projekt zu portieren (Demo_31)

Meine Änderungen
- Alle stm32f4xx_XXX durch stm32f10x_XXX ersetzen (includes wie Dateien)
- Für core_cm4_simd.h ist mir kein Äquivalent bekannt.
- Geänderte codezeilen (usb_bsp.c)
1
  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA , ENABLE);
 zu
1
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
- Sowie (usb_bsp.c)
1
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_11 | GPIO_Pin_12;
2
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
3
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
4
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
5
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
6
  GPIO_Init(GPIOA, &GPIO_InitStructure);
zu
1
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_11 | GPIO_Pin_12;
2
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
3
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
4
  GPIO_Init(GPIOA, &GPIO_InitStructure);
- Mit folgendem wusste ich nichts anzufangen, da das Datenblatt (S. 163) 
nicht viel dazu hergibt
1
  GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_OTG1_FS) ;
2
  GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_OTG1_FS) ;
3
  GPIO_PinAFConfig(GPIOA,GPIO_PinSource11,GPIO_AF_OTG1_FS) ;
4
  GPIO_PinAFConfig(GPIOA,GPIO_PinSource12,GPIO_AF_OTG1_FS) ;
- ID line Debug habe ich auch weggelassen, nachdem der Port auf meinem 
Board (Olimexino STM32) nicht mit der USB-Buchse verbunden ist
1
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_10;
2
  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
3
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;  
4
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
5
  GPIO_Init(GPIOA, &GPIO_InitStructure);  
6
  GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_OTG1_FS) ;
7
 
8
  RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_OTG_FS, ENABLE) ;
- Kommentieren von
1
 NVIC_InitStructure.NVIC_IRQChannel = OTG_FS_IRQn;
da der betreffende Bereich in der stm32f10x.h per define nur für
1
#ifdef STM32F10X_CL
2
  ...
3
  OTG_FS_IRQn                 = 67      /*!< USB OTG FS global Interrupt                          */
4
#endif /* STM32F10X_CL */
 (was der STM32F103RB nicht ist) aktiv ist. Was kann man hier statt 
dessen nehmen?

Compilen geht - aber Flashen kann ich mir sparen... Das KANN nicht 
gehen.

Hat jemand noch Ratschläge? Wenn's laufen sollte, poste ich 
selbstverständlich das Projekt für die anderen.

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.