13-FATFS_SDIO-Library (STM32F4)

-mit dieser Library können SD-Karten mit einem FAT-Dateisystem per SDIO-Schnittstelle und DMA vom STM32F4 verwaltet werden.
Hinweis : es gibt noch eine Library für USB-Sticks per FATFS (Nr. 32) und eine kombinierte Library SD+USB (Nr. 87)

-ich hab die OpenSource-Lib (FATFS) eingebunden und die freien Quellcodes von STM für die SDIO-Funktionen benutzt.

-die FATFS-Lib hat eine sehr gute englische Doku dabei in der alle Funktionen und die notwendigen Parameter beschrieben sind.

-Ich hab in der darüberliegenden Schicht ein paar Grundfunktionen zusammengestellt um ein Medium zu mounten, ein File zu öffnen/schließen und um Strings in das File zu schreiben bzw. aus dem File zu lesen. Mit dem BlockRead können Files Byteweise gelesen werden und mit BlockWrite kann ein Block Byteweise geschrieben werden.

-Die Geschwindigkeit beim BlockRead liegt bei ca. 2,4MByte/sec bei einem Puffer von 512 Bytes, beim BlockWrite liegt meine Karte bei ca. 500kByte/sec.

Ab Version 1.4 kann im File “stm32_ub_sdcard.h” der SDIO-Mode von 4bit auf 1bit umgestellt werden. Und falls kein Detect-Pin vorhanden ist, kann dieser hier abgeschaltet werden.

BUG HINWEIS : Torsten S. aus dem Mikrocontroller-Forum hat mich auf einen Fehler hingewiesen der mit der FATFS-Funktion “f_write” (und vermutlich auch “f_read”) zu tun hat. Wenn dieser Funktion ein File übergeben wird das größer als 512 Bytes ist, kommt es zu einem Fehler und die Datei wird nicht richtig auf die SD-Karte geschrieben/gelesen. Meine Funktionen “WriteBlock/ReadBlock” lassen einen größeren Wert als 512 gar nicht zu also gibt es hier keinen Handlungsbedarf. Ihr solltet nur sicherstellen das, wenn ihr “f_write” direkt nutzt, daran denkt.

Mögliche Hardwarefehler (possible Hardware BUGs) :

viele berichten über Probleme mit der SD-Karten Library aber nur wenige berichten (nach gefundener Lösung) was genau der Fehler war. Aus dem Grund hier eine Liste mit den häufigsten Fehlern die ich zu lesen bekomme. Bei einem Problem bitte alle Punkte prüfen :

1. Wackelkontakt an den Leitungen (loose connection)
2. Kurzschlüsse zwischen Pins (short circuit)
3. Falsche Verdrahtung (wrong wiring)
4. Defekter SD-Karten Adapter (faulty SD-Card adapter)
5. SD-Karte mit falschem Filformat (wrong file system)
6. SD-Karte wird nicht unterstützt (unsuported SD-Card)
7. Leitungen zu lange (too long wires)
8. PullUps an den Leitungen (PullUp resistors)

Beispielbild :

Benutzte Pins und DMAs :

1bit-Mode :
PC8  : SDIO_D0  = SD-Karte DAT0
PC12 : SDIO_CK  = SD-Karte Clock
PD2  : SDIO_CMD = SD-Karte CMD
Hinweis : SD-Karte Pin CD muss an Vcc angeschlossen werden !!

4bit-Mode :
PC8  : SDIO_D0  = SD-Karte DAT0
PC9  : SDIO_D1  = SD-Karte DAT1
PC10 : SDIO_D2  = SD-Karte DAT2
PC11 : SDIO_D3  = SD-Karte DAT3/CD
PC12 : SDIO_CK  = SD-Karte Clock
PD2  : SDIO_CMD = SD-Karte CMD

mit Detect-Pin :
PC0  : SD_Detect-Pin (Hi=ohne SD-Karte)

entweder  DMA2_STREAM3_CHANNEL4
oder      DMA2_STREAM6_CHANNEL4

Voraussetzungen :

Benutzte Module der CooCox-IDE : GPIO, MISC, SDIO, DMA
Benutzte Librarys : FATFS (mehrere Files)

Enumerationen :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
typedef enum {
  FATFS_OK =0,
  FATFS_NO_MEDIA,
  FATFS_MOUNT_ERR,
  FATFS_GETFREE_ERR,
  FATFS_UNLINK_ERR,
  FATFS_OPEN_ERR,
  FATFS_CLOSE_ERR,
  FATFS_PUTS_ERR,
  FATFS_SEEK_ERR,
  FATFS_RD_STRING_ERR,
  FATFS_RD_BLOCK_ERR,
  FATFS_WR_BLOCK_ERR,
  FATFS_EOF,
  FATFS_DISK_FULL
}FATFS_t;

.

1
2
3
4
5
6
typedef enum {
  F_RD =0,    // zum lesen oeffnen (nur falls File existiert)
  F_WR,       // zum schreiben oeffnen (nur falls File existiert) und Daten anhängen
  F_WR_NEW,   // zum schreiben oeffnen (und event. neu anlegen) und Daten anhängen
  F_WR_CLEAR  // zum schreiben oeffnen (alte Daten loeschen)
}FMODE_t;

Funktionen :

1
2
3
4
5
6
7
8
9
10
11
12
void UB_Fatfs_Init(void);                                            // init der FATFS-Funktionen
FATFS_t UB_Fatfs_CheckMedia(MEDIA_t dev);                            // check ob Medium eingelegt
FATFS_t UB_Fatfs_Mount(MEDIA_t dev);                                 // um das Medium zu öffnen
FATFS_t UB_Fatfs_UnMount(MEDIA_t dev);                               // um das Medium zu schließen
FATFS_t UB_Fatfs_DelFile(const TCHAR* name);                         // löscht ein File
FATFS_t UB_Fatfs_OpenFile(FIL* fp, const TCHAR* name, FMODE_t mode); // zum öffnen eines Files (zum lesen oder schreiben)
FATFS_t UB_Fatfs_CloseFile(FIL* fp);                                 // schließt ein File
FATFS_t UB_Fatfs_WriteString(FIL* fp, const TCHAR* text);            // schreibt einen String in ein offenes File
FATFS_t UB_Fatfs_ReadString(FIL* fp, char* text, int len);           // ließt einen String aus einem offenen File
uint32_t UB_Fatfs_FileSize(FIL* fp);                                 // Größe vom File auslesen
FATFS_t UB_Fatfs_ReadBlock(FIL* fp, unsigned char* buf, uint32_t len, uint32_t* read);   // File Byteweise auslesen
FATFS_t UB_Fatfs_WriteBlock(FIL* fp, unsigned char* buf, uint32_t len, uint32_t* write); // File Byteweise schreiben

Beispiel :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
//--------------------------------------------------------------
// File     : main.c
// Datum    : 06.04.2013
// Version  : 1.1
// Autor    : UB
// EMail    : mc-4u(@)t-online.de
// Web      : www.mikrocontroller-4u.de
// CPU      : STM32F4
// IDE      : CooCox CoIDE 1.7.0
// Module   : CMSIS_BOOT, M4_CMSIS_CORE
// Funktion : Demo der FATFS-SDIO-Library
// Hinweis  : Diese zwei Files muessen auf 8MHz stehen
//              "cmsis_boot/stm32f4xx.h"
//              "cmsis_boot/system_stm32f4xx.c"
//--------------------------------------------------------------
 
#include "main.h"
#include "stm32_ub_fatfs.h"
 
int main(void)
{
  FIL myFile;   // Filehandler
 
  SystemInit(); // Quarz Einstellungen aktivieren
 
  // Init vom FATFS-System
  UB_Fatfs_Init();
 
  // Check ob Medium eingelegt ist
  if(UB_Fatfs_CheckMedia(MMC_0)==FATFS_OK) {
    // Media mounten
    if(UB_Fatfs_Mount(MMC_0)==FATFS_OK) {
      // File zum schreiben im root neu anlegen
      if(UB_Fatfs_OpenFile(&myFile, "0:/UB_File.txt", F_WR_CLEAR)==FATFS_OK) {
    	// ein paar Textzeilen in das File schreiben
        UB_Fatfs_WriteString(&myFile,"Test der WriteString-Funktion");
        UB_Fatfs_WriteString(&myFile,"hier Zeile zwei");
        UB_Fatfs_WriteString(&myFile,"ENDE");
        // File schliessen
        UB_Fatfs_CloseFile(&myFile);
      }
      // Media unmounten
      UB_Fatfs_UnMount(MMC_0);
    }
  }
 
  while(1)
  {
 
  }
}

Hier die Library zum Download :

ub_stm32f4_fatfs_sdio_v104

hier eine “Testversion” mit aktiviertem Multi-Block read/write :

ub_stm32f4_fatfs_sdio_v105a

Hier der komplette CooCox-Projektordner zum Download :

Demo_13_FATFS_SDIO

111 Antworten auf 13-FATFS_SDIO-Library (STM32F4)

  1. Major sagt:

    Hallo,

    finde ich super deine Libs!

    Ich hatte ein paar Probleme am Anfang, da es immer ein SD_DATA_CRC_FAIL gab, was wahrscheinlich an den Erratas des Mikrocontrollers lag, da ich die Revision A benutze. Es wirde immer ein CRC Fail generiert, wenn die Antwort der Karte keine CRC Summe beinhaltet. Dadurch konnte die Karte nicht gemountet werden und das Ergebniss war ein FATFS_GETFREE_ERR Fehler. Was geholfen hat, war das Auskommentieren dieser Zeile:
    TransferError = SD_DATA_CRC_FAIL;
    in der Funktion SD_ProcessIRQSrc(void).

    • admin_ub sagt:

      uhh….bei dem Fehler hätte ich auch erstmal suchen müssen. Weiß gar nicht genau was ich für einen Chip-Typ habe. Ich werde das als Bemerkung in der nächsten Version mit einfügen.

      Danke für den Hinweis, das wird anderen vlt auch helfen. Gruss

  2. Ray sagt:

    klingt interessant – wie groß war denn die Datei zum ermitteln der Übertragungsgeschwindigkeit?

    • admin_ub sagt:

      ich hab aus dem Netz Testfiles mit 1k bis 10MByte runtergeladen. Der Datendurchsatz ist mit den größeren Files am besten. Beim schreibtest hab ich einfach einen 512Byte Block 2048mal in ein File geschrieben und die Zeit dafür per Timer gemessen.

  3. ANVIEX sagt:

    Datei stm32_ub_fatfs.h sollte mit __cplusplus Declaration ergänzt. Damit Libs auch zusammen mit OOP C++ Project verwendet werden kann. Sonst hängt Libs auf bein Aufruf von der Funktion UB_Fatfs_Mount(MMC_0).

    #ifdef __cplusplus
    extern “C” {
    #endif

    #ifdef __cplusplus
    }
    #endif

    • admin_ub sagt:

      ich habe in meinen Librarys absichtlich keine Defines wie “_cplusplus” oder “_AVR” oder “_PIC” drinn. Weil ich nicht alle Systeme testen kann und will.
      Gruss Uwe

  4. Joerg sagt:

    Hallo Uwe,
    ich habe Probleme die Micro SD Karte zu mounten. Kann es an der Karte oder vielleicht auch an der Toolchain liegen? In deinem Tutorial zu CoIde wird ja noch eine Version vom letzten Jahr benutzt. Ich bin für jeden Tip dankbar.

    Grüße

    Jörg

    • admin_ub sagt:

      Hi Jörg, welche Hardware benutzt du ? (falls STM32F4 Discovery-Board) kannst du das compilierte File aus dem Ordner “Demo_13/Debug/Bin” benutzen. Dieses muss funktionieren. Ansonsten poste mal die Rückgabewerte der “Init” , “CheckMedia” und “Mount”. Event. funktioniert der SD-Detect Pin nicht.

  5. Joerg sagt:

    Hallo Uwe,
    das Rätsel ist gelöst. Ich hatte einen Kurzschluss von D0 zu GND…. Ich hätte das besser gleich mal durch gemessen. Anstatt nur die einzelnen Verbindungen zu prüfen…

    Vielen Dank für deine schnelle Hilfe. Deine Seite hier ist echt super.

    Jörg

  6. Jimmy sagt:

    Hello Uwe,

    thanks for the Library. It is great, but I have a question.

    I’m using CooCox and STM32F4 Discovery Kit connected to SD card reader and 2Gb SD card. When I try to write to the card I find out it gives me a SD_COM_CRC_FAILED(stm32_ub_sdcard/SD_SelectDeselect/CmdResp1Error…)

    Do you have any idea why?

    Thanks a lot,

    Jimmy

    • admin_ub sagt:

      another user had a similar problem, please open the file “stm32_ub_sdcard.h” and change the define to “Revision A”

      1
      2
      
      #define SDIO_STM32F4_REV     0  // 0 = Revision A
      //#define SDIO_STM32F4_REV     1  // 1 = Revision Z

      leave a comment when its working

      • Jimmy sagt:

        Thanks for advice, but there should be no problem. I tried to be more precise and I tracked the error to CmdResp7Error(UB_Fatfs_Mount-f_getfree-chk_mounted-disk_initialize-MMC_disk_initialize-SD_Init-SD_PowerON-CmdResp7Error)

        To this if statement:

        1
        2
        3
        4
        5
        6
        7
        
        if ((timeout == 0) || (status & SDIO_FLAG_CTIMEOUT))
        {
        /*!< Card is not V2.0 complient or card does not support the set voltage range */
        errorstatus = SD_CMD_RSP_TIMEOUT;
        SDIO_ClearFlag(SDIO_FLAG_CTIMEOUT);
        return(errorstatus);
        }

        Do you have any idea what can cause this error? I’m using SanDisk SD 2GB, formated to Fat32, unit size 512 bytes.

        Thanks a lot,

        Jimmy

        • admin_ub sagt:

          theres a BUG in Revision-A CPUs around the CRC-Check. First, switch the define to verify thats not the same problem with your CPU. Second, try FAT16 or another card. Last, take a USB-Device :-)

  7. Jimmy sagt:

    I’m going to go through this. One more thing, is there any difference between 1b and 4b wide transfer? I built up an interface for 4b, but initialization is done in 1b mode.

    My interface STM32F4 Discovery – SD card slot:
    PC8(D0) – pin 7
    PC9(D1) – pin 8
    PC10(D2) -pin 9
    PC11(D3) – pin 1
    PC12(CLK) – pin 5
    PD2(CMD) – pin 2
    3V(VDD) – pin 4
    GND(VSS) – pins 3 and 6
    PD0(CARD DETECT) – detection pin

    + The D0, D1, D2, D3 and CMD pins have 47K pull up resistors

    Thanks,

    Jimmy

    • admin_ub sagt:

      Pinout is ok. Init in 1bit-Mode is a standard procedure. The code ist verified the failure must be in your hardware. Check all 9 lines again if connected and not shorted. Or try a new SD-Card.

  8. Alex sagt:

    Hi
    Erstmal danke für die grossartigen Libraries!
    Ich habe noch eine Frage zu dieser:
    Ist es wirklich nötig vor jedem Schreibzyklus die Karte zu mounten? Wenn ich dies nicht mache wird einfach nichts auf die Karte geschrieben. Am liebsten wäre es mir am Anfang des Programms die Karte zu mounten und am Schluss zu unmounten.
    Gruss
    Alex

    • admin_ub sagt:

      hast du “UB_Fatfs_CloseFile” aufgerufen nach dem schreiben ?

  9. Jimmy sagt:

    Hi Uwe,

    thanks for all. I have finally found the error. It was in my hardware interface. Although I had the right wiring the interface did not work. I believe it was caused by the 47k resistors, because once I have removed them it works.

    Jimmy

    • admin_ub sagt:

      good to know

    • Zouzmann sagt:

      hi jimmy ,
      i got the same problem that you have had and which you have fixed by removing the 47k resistors
      Now , i’m wiring my pins directly with out the pull-up resistors and i still have a fatfs_getfree-err . I know that my problem is in the hardware wiring and config but didn’t know where’s the problem exactly (i’m working with revezion z / my microcontroller is stm32f40vg and i’m dealing with a 4 bits mode )

      koennen sie mir helfen ?
      danke shon

      • admin_ub sagt:

        the most problems are from bugy adapters (sd->micro_sd) or not supported sd_cards. Please try another card (<=1GB) and double check your connections and cable length (short as possible)

  10. Jimmy sagt:

    I have got a question in my head. Does this have any limitations in SD card size (does it work with 32Gb card), file name length or any other?

    Thanks,

    Jimmy

    • admin_ub sagt:

      look at the specification from ChaN, Filesize 4GB, Volumesize 2TB, Filename 8 character or with LFN enabled (in ffconf.h) 255 character

  11. Jimmy sagt:

    Hi Uwe,

    what is approximately your write speed? I don´t know if it is only my problem, but it seems quite slow to me.

    Thanks

    • admin_ub sagt:

      write speed is about 500kByte/sec (with WriteBlock-Function) but i have only one card to test with.

  12. Stefan sagt:

    Hi Uwe,

    vielen Dank für die super Libs :)
    Ich habe leider auch Probleme die SD-Card zu mounten.
    Chip ist Z-Revision. Habe aber trotzdem die 2 Varianten ausprobiert bzgl CRC Fails.

    Nach f_mount() bekomm ich noch ein FR_OK.
    Bei f_getfree kommt ein FR_NOT_READY zurück.
    Dieser wird hervorgerufen durch ein SD_CMD_RSP_TIMEOUT in der Funktion static SD_Error CmdError(void)

    Hast du eine Idee woran das liegen könnte ?
    Habe die Hardware Verbindungen geprüft, die müssten passen.
    Macht es vlt ein Problem das die Leitungen 30 cm lang sind ?

    Grüße Stefan

    • admin_ub sagt:

      schwer zu sagen…30cm klingt mir etwas viel…kannst du sie nicht kürzer machen ? und keine PullUps einbauen, das war hier schonmal ein Problem. Evt. noch eine andere Karte probieren.

      • Stefan sagt:

        Hi Uwe,

        danke für die Antwort. Die länge der Kabel war nicht das Problem. Habs mit kürzeren nochmal getestet, gleiches Verhalten.

        Der Fehler war der SD Karten Sockel…
        Neuen Sockel gekauft und alles neu gelötet, jetzt funktioniert alles bestens :)

        Falls es noch jemand interessiert , hab dann auch gleich mal ein SD-Karten Kompatibilitätstest gemacht mit denen die ich rumliegen hatte.

        Folgende Modelle konnte ich erfolgreich testen
        SanDisk SD Card 2 GB
        SanDisk BE08098117240, 2GB
        SanDisk Ultra Class 10, 16 GB
        Sony SD HC Class 4, 8 GB

        Viele Grüße
        Stefan

  13. sisa sagt:

    Thank you very much. Your code was very helpful for my project.

  14. Simon sagt:

    Hallo Uwo,
    ich hab heute mal deine Bibliothek getestet,

    bei UB_FATFS_CHECKMEDIA bekomme ich noch ein FATFS_OK zurück,
    das ist ja schonmal gut, in der nächsten Funktion
    bei UB_FATFS_MOUNT bekomme ich aber ein FATFS_GETFREE_ERR
    kann man da irgendwie den Fehler eingränzen??

    Vielen dank für die Hilfe!!

    • Simon sagt:

      if(dev==MMC_0) check=f_getfree(“O:”, &fre_clust, &fs);

      Da versteh ich noch nicht genau warum als Pfad O: angegeben wird,
      oder ist willkürlich ausgewählt??

      Nochmals vielen Dank!!

      • Zouzmann sagt:

        hallo simon ,
        ich habe das problem auch !
        konnen sie mich zeigen wie hast du das konfiguration gemacht ?
        welchem revizion und welchem bits mode (1 oder 4) zu folgen ?

        danke .

    • Simon sagt:

      Ich habe es mit einer anderen SD-KArte versucht, da komme ich ein Schritt weiter:

      bei UB_FATFS_MOUNT bekomme ich jetzt FATFS_OK
      dort bekam ich vorher FATFS_ERR
      und bei der nächsten Funktion
      bei UB_FATFS_OPENFILE bekomme ich ber FATFS_OPEN_ERR

  15. Simon sagt:

    Panik zurück,
    Alles funktioniert!
    DANKE

    • Simon sagt:

      Nur noch eine Frage :)

      kann ich auch statt reinem Text Variablen mit Zeicheninhalten in ein .txt File schreiben?

      • admin_ub sagt:

        ja, du kannst “UB_Fatfs_WriteBlock” dazu benutzen. Einfach ein char Array anlegen [max 512 Byte] , mit Daten füllen und die Funktion aufrufen. Wenn du mehr Daten speichern willst, einfach die Funktion mehrmals aufrufen.

        1
        2
        3
        4
        5
        6
        
        uint32_t cnt;
        unsigned char data[10];
        data[0]=0x12;
        data[1]=0xab;
        data[2]=0x5F;
        UB_Fatfs_WriteBlock(&amp;myFile, data, 3, &amp;cnt);

        in einem Editor werden die Bytes halt dann nicht lesbar dargestellt, sondern mit sondernzeichen.

    • admin_ub sagt:

      und was war der Fehler…vlt hat jemand anderes den gleichen

  16. Simon sagt:

    Ich benutzte ein SD-Karten Adapter auf MicroSD

  17. Joerg sagt:

    Vielen Dank funktioniert prima, bis auf die Addressierung bei großen Speicherkarten. Compiler Keil MDK 5.0.
    Änderungsvorschlag:

    int MMC_disk_read(BYTE *buff, DWORD sector, BYTE count)
    {

    SD_ReadMultiBlocks(buff, sector << 9, 512, 1);

    }
    sollte wie folgt geändert werden:

    SD_ReadMultiBlocks(buff, ((uint64_t)sector) << 9, 512, 1);

    das Gleiche gilt auch für die Schreibfunktion:
    SD_WriteMultiBlocks((BYTE *)buff, ((uint64_t)sector) << 9, 512, 1);

    • admin_ub sagt:

      ok…da werd ich wohl ein update einplanen müssen.

  18. Markus sagt:

    Hallo,

    wenn ich auf
    #define SD_SDIO_DMA_STREAM6 6
    stelle, dann funktioniert es leider nicht mehr.

    if (UB_Fatfs_CheckMedia(MMC_0)==FATFS_OK) {
    UB_Uart_SendString(COM2, “Media gefunden!”, LFCR);

    funktioniert,

    if(UB_Fatfs_Mount(MMC_0)==FATFS_OK) {
    UB_Uart_SendString(COM2,”Mount OK!”,LFCR);

    funktioniert leider nicht mehr.
    Die CPU hängt sich dann auch auf.

    • admin_ub sagt:

      sorry, hab ich nicht getestet…event. ein BUG.

  19. timo sagt:

    Ich möchte Sector Size vergrößen, damit Geschwindigkeit beschleunigen.
    Deswegen 512 überall durch 2048 ersetzt, danach funktioniert nicht mehr, und zwar kann es sich nicht mehr mounten. Das Program hängt bei “SD_WaitReadOperation()” in “int MMC_disk_read(BYTE *buff, DWORD sector, BYTE count)”.

    Hat jemand Erfarungen damit???

    • admin_ub sagt:

      ja “Torsten S” aus dem Mikrocontroller-Forum (siehe BUG-Hinweis im Text oben)

  20. timo sagt:

    Problem gelöst !!!

    1. Sector Size der SD kann/darf man nicht ändern.

    2. der sogenannte Bug “Wenn dieser Funktion ein File übergeben wird das größer als 512 Bytes ist, kommt es zu einem Fehler und die Datei wird nicht richtig auf die SD-Karte geschrieben/gelesen.” liegt an der Function “int MMC_disk_read(BYTE *buff, DWORD sector, BYTE count)” in Datei “stm32_ub_sdcard.c”

    original war: “SD_ReadMultiBlocks(buff, sector << 9, 512, 1);“

    korrigiert ist nun: „SD_ReadMultiBlocks(buff, sector << 9, 512, count);“

    jetzt braucht es nur 236ms um ein 480×272 Picture aus SD lesen und gleich auf TFT Dispaly anzuzeigen statt 466ms, weil ich jedesmal 4096 Bytes auslesen statt 512 Bytes.

    • admin_ub sagt:

      Vorsicht, ich sagte doch es ist ein BUG…”Torsten” hat auch diese Änderung gemacht und danach beim schreiben von großen Dateien fehlerhafte Daten erhalten !! nur zur Info.

      • timo sagt:

        achso, weil ich bisher nur lesen gemacht habe … …

  21. Saivnct sagt:

    thank you very much for your libs
    can you help me solve this problem: I can’t read block from SD card with this functions SD_ReadBlock(uint8_t *readbuff, uint64_t ReadAddr, uint16_t BlockSize);
    SD_Error SD_ReadMultiBlocks(uint8_t *readbuff, uint64_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks);
    it gives me a error 7: SD_START_BIT_ERR
    help me please :)

    • admin_ub sagt:

      please use “UB_Fatfs_ReadBlock” instead of “SD_ReadBlock”
      if this also throw an error, double check all connections or try another SD-Card

    • miros sagt:

      Hi,
      I have the same problem. In UB_Fatfs_Mount at reading sector O with SD_ReadMultiBlocks, I always get SD_START_BIT_ERR despite CMD18 sending and response is OK. Did you find out what’s wrong?

    • miros sagt:

      Hi,
      today, I found out it’s wrong only in 4bit mode. In 1bit mode it works fine.
      When the SD_START_BIT_ERR occurs? If is not start bit on all data bits(DO-D3), or only on one of them?

    • miros sagt:

      The problem is solved. Pin D1 in micro SD card holder was unconnected. I have made temporary uSD card holder from SD to micro SD card adapter and now it works fine.

      • admin_ub sagt:

        and like always…a hardware bug :-)

  22. Fraser sagt:

    Hello I have got this working. Although when I use it within my SPI project the

    SystemInit(); –> SetSysClock(); –> following lines

    /* Select the main PLL as system clock source (issue)*/
    RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
    RCC->CFGR |= RCC_CFGR_SW_PLL;

    Interfere with my SPI1 configuration and causes it to return incorrect values. Any help would be appreciated.

    Fraser

    • admin_ub sagt:

      what kind of “interference” ?. SPI has nothing to do with the SDIO or the PLL-Settings. The SPI-Bus has its own physical Clock-Signal. Even with a wrong Clock-Speed the SPI must work (maybe slower as wanted but without failure). But you can download my SPI-LoLevel library and try this one.

      • Fraser sagt:

        Spi 8-Bit write 2x 8-Bit return

        http://i1215.photobucket.com/albums/cc520/resarf69/SPI/working_zpsd8a13efe.png

        When SDIO is implemented the SPI clock is incorrect

        http://i1215.photobucket.com/albums/cc520/resarf69/SPI/notworking_zpsb0bee42b.png

        the spi initiation code is:

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        26
        27
        28
        29
        30
        31
        32
        33
        34
        35
        36
        37
        38
        39
        40
        41
        42
        43
        44
        45
        46
        47
        48
        
        void mySPI_Init(void){
         
         
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
         
        SPI_InitTypeDef SPI_InitTypeDefStruct;
         
         
        SPI_InitTypeDefStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
        SPI_InitTypeDefStruct.SPI_Mode = SPI_Mode_Master;
        SPI_InitTypeDefStruct.SPI_DataSize = SPI_DataSize_8b;
        SPI_InitTypeDefStruct.SPI_CPOL = SPI_CPOL_High;
        SPI_InitTypeDefStruct.SPI_CPHA = SPI_CPHA_2Edge;
        SPI_InitTypeDefStruct.SPI_NSS = SPI_NSS_Soft;
        SPI_InitTypeDefStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
        SPI_InitTypeDefStruct.SPI_FirstBit = SPI_FirstBit_MSB;
         
        SPI_Init(SPI1, &amp;SPI_InitTypeDefStruct);
         
         
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOE , ENABLE);
         
        GPIO_InitTypeDef GPIO_InitTypeDefStruct;
         
        GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7 | GPIO_Pin_6;
        GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_AF;
        GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
        GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
        GPIO_Init(GPIOA, &amp;GPIO_InitTypeDefStruct);
         
        GPIO_InitTypeDefStruct.GPIO_Pin = GPIO_Pin_3;
        GPIO_InitTypeDefStruct.GPIO_Mode = GPIO_Mode_OUT;
        GPIO_InitTypeDefStruct.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitTypeDefStruct.GPIO_PuPd = GPIO_PuPd_UP;
        GPIO_InitTypeDefStruct.GPIO_OType = GPIO_OType_PP;
        GPIO_Init(GPIOE, &amp;GPIO_InitTypeDefStruct);
         
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1);
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1);
        GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1);
         
        GPIO_SetBits(GPIOE, GPIO_Pin_3);
         
         
        SPI_Cmd(SPI1, ENABLE);
         
        }

        • admin_ub sagt:

          please check your Syclock-Setting without the SDIO.
          With a correct Sysclock @168MHz the APB2 is 84MHz. And with a prescaler “SPI_BaudRatePrescaler_2″ the SPI-Clock is 42MHz ! One SPI-Frame with 8bit has a duration of only 190ns !! But in your first picture the duration is about 1us …so i think the sysclock with SDIO is ok and you should try a prescaler of 16. Then your SPI-Clock should be 5,25MHz. I hope this solves the problem.

          • Fraser sagt:

            Thank-you! Changing the pre-scaler to slow the clock down worked.

            I am having an issue with writing more than 512 bytes to a file as mentioned earlier.

            I am doing the following (“Pseudocode”) when I loop too many times the file has an error.

            How do I log lots of data in the .txt file?

            Thanks again

            Fraser

            main{

            Initiate system
            Initiate Fat-FS
            Mount
            Create file in root

            While (x>1000)
            {

            int x

            (data)

            writeblock (data)

            x++

            }

            close file

            unmount

            }

          • admin_ub sagt:

            first check your Hardawre (short connections, no external pullups)
            then try this
            [pseudocode]
            int x=0;
            char data[512]
            while(x<1000) {
            data=filldata();
            writeblock(data);
            x++
            }
            close file
            unmount

  23. Bernhard sagt:

    Hey, ich bekomme immer einen FR_INT_ERR (file ff.c line 959).
    Ich kenne mich noch aus mit Files bzw. Speichermedien.
    Kann mir bitte jemand erklären was das Problem ist!

    • admin_ub sagt:

      “Assertion failed” … hast du irgendein File von meiner Demo abgeändert ? Und wenn ja…was und warum.

      • Bernhard sagt:

        Nein, verwende eins zu eins deinen CooCox – Projekt!

        • admin_ub sagt:

          dann probier mal eine andere SD-Karte (<=1GB)

  24. Joerg B. sagt:

    Falls du mal lange Weile haben solltest. Ein Lib für die Folientastatur wäre ganz schön zu haben ;)

    • admin_ub sagt:

      schon fertig…probier sie mal aus.

  25. Joerg B sagt:

    Das war fix! Danke, ich hoffe ich komme Morgen dazu es zu testen.
    Bin ziemlich Ausgelastet die letzten Wochen. So eine Maschine, mit Mechanik und Steuerung zu bauen bringt einen ganz schön an seine Grenzen…

  26. Thierry sagt:

    Hi UWE,

    Very good job, but i have a problem when enter in SD_PowerON()
    at this place :
    /*!< CMD55 */
    SDIO_CmdInitStructure.SDIO_Argument = 0×00;
    SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD;
    SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
    SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
    SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
    SDIO_SendCommand(&SDIO_CmdInitStructure);
    errorstatus = CmdResp1Error(SD_CMD_APP_CMD);

    /*!< If errorstatus is Command TimeOut, it is a MMC card */
    /*!< If errorstatus is SD_OK it is a SD card: SD card 2.0 (voltage range mismatch)
    or SD card 1.x */
    if (errorstatus == SD_OK)

    errorstatus = SD_ILLEGAL_CMD
    Have you an idea why ?
    My SD card is a 500MB, it is formatted in FAT type under SEVEN and i work in 1bit mode
    Big thanks
    Thierry

  27. Thierry sagt:

    Hello,
    new investigation :
    I connect an oscilloscope on CMD and CLK and i don’t see modification on these pins during CmdResp1Error() !!!!
    It’s oscillogram OK for “GO_IDLE_STATE” and “SEND_IF_COND” but nothing for “CMD55″ !!
    Have you an idea ?
    Thanks

    • Thierry sagt:

      Sorry, I wrote a mistake …
      I connected an oscilloscope on CMD and CLK and i didn’t see modification on these pins during SDIO_SendCommand(&SDIO_CmdInitStructure); with CMD55 !!!!

  28. Thierry sagt:

    Sorry, another mistake.
    Oscillograms are OK, and like my first message, “SD_ILLEGAL_CMD” is returned.
    Is it a bad SD formatting ?

    • Thierry sagt:

      My CS is connected Low.
      You don’t use it ?
      Why ?

  29. Thierry sagt:

    My SD Card never response after received CMD 55 ???

    • admin_ub sagt:

      in 1bit SDIO Mode the Pin DAT3/CD should tied to Vcc not to GND !!. This Pin is ChipSelect only in SPI-Mode.

      • Thierry sagt:

        OK,
        It’s better now
        Thanks

  30. Thierry sagt:

    OK, Thanks.
    It wad an hardware error, Arduino put serial resistor in CLK and CMD.
    Now it’s ok, but i received SD_CMD_RSP_TIMEOUT …

    • Thierry sagt:

      Hi,
      It’s better without serial resistor in CS …
      I tried 3 SD, 2x500Mo & 1x1Mo.
      With 1Mo, sometimes i have timeout and when it’s OK i have a CRC_Failed in SD_Init()/SD_SelectDeselect() !!!!

      • Thierry sagt:

        In SD_Init() after that :
        /*!< Configure the SDIO peripheral */
        /*!< SDIO_CK = SDIOCLK / (SDIO_TRANSFER_CLK_DIV + 2) */
        /*!< on STM32F4xx devices, SDIOCLK is fixed to 48MHz */
        SDIO_InitStructure.SDIO_ClockDiv = SDIO_TRANSFER_CLK_DIV;
        SDIO_InitStructure.SDIO_ClockEdge = SDIO_ClockEdge_Rising;
        SDIO_InitStructure.SDIO_ClockBypass = SDIO_ClockBypass_Disable;
        SDIO_InitStructure.SDIO_ClockPowerSave = SDIO_ClockPowerSave_Disable;
        SDIO_InitStructure.SDIO_BusWide = SDIO_BusWide_1b;
        SDIO_InitStructure.SDIO_HardwareFlowControl = SDIO_HardwareFlowControl_Disable;
        SDIO_Init(&SDIO_InitStructure);

        I have no more CLK !!
        Is it a normal work ?

        • Thierry sagt:

          Hello,
          When i comment these SDIO CLK Config lines, working Good with 1x1Go and 1x500Mo µSD (but not with 500Mo SD)
          Have you an expectation about that ?
          Thanks

  31. Lurch sagt:

    wozu ist die Prozedur ‘SD_HighSpeed’?
    Wollte meine Quellen abgleichen und hatte die Prozedur übrig.

  32. Thierry sagt:

    Hello Uwe,
    Big thanks for your help,
    CoOS was intrisuve in my SD configuration, now it’s OK.
    Your code is very good working without modification.
    Thanks
    Thierry

  33. Stefan sagt:

    Hallo

    super library! Funktioniert einwandfrei bei mir.

    Das Einzige was mich stört ist die sehr niedrige Schreibgeschwindigkeit.
    Ich habe das lib mit zwei SD Karten getestet:
    – SanDisc 1G – 512Byte write – 30KByte/s
    – Panasonic SDHC 32G – 512Byte write – 46KByte/s
    was für mich nicht ausreichend ist.
    Ich habe auf diverse Foren ins Internet oft die Aussage gelesen, dass die Schreibgeschwindigkeit vom Blockgröße abhängig ist.
    Wie muss, dass Lib angepasst werden, damit man Blöcke größer als 512Byte schreiben kann, zB. 16K oder sogar 32K.

    Vielen Dank!
    Stefan

    • admin_ub sagt:

      30 bis 40kByte/s ist schon sehr langsam
      bist du sicher das die Clock-Einstellungen richtig sind ?
      probier mal die Test-Version 1.5 aus und schreib ob es damit schneller geht.
      In der Version kannst du den kompletten Block der geschrieben werden soll
      übergeben (z.B. 150kByte)

  34. Luciano sagt:

    Hallo,

    hervorragendes Beispiel. Ich ging perfekt. Vielen Dank !!.
    Derzeit muss ich auf die SD-Speicher zu schreiben ist eine Tatsache, dass in einem uint16_t variabel, wer, wie?

    Grüße.

  35. Christian sagt:

    Hallo,

    auch ich bin von den Libs begeistert. Es läuft soweit eigentlich alles. Ich möchte einen Datenlogger betreiben. Analog–>SD-Karte. Wenn ich jetzt z.B. eine Sinusspannung aufnehme habe ich immer beim Schreibzyklus ( alle 512byte) einen kurzen “hänger”. Obwohl ADC als auch SD beides mitDMA läuft. Wie kann ich einen konstanten äquidistanten Datenstrom auf eine SD-Karte erzeugen? Ziel ist es eine möglichst hohe Abtastrate zu erreichen. Wie könnte ich das erreichen?

    Danke und Gruß
    Christian

    • admin_ub sagt:

      da wirst du nicht sehr weit kommen. event. mit einem RAM-Puffer als zwischenspeicher. aber das die Karte ab und zu mal eine Pause einlegt ist normal.

  36. Marcel sagt:

    Hallo,

    gibt es bei der Lib auch die möglichkeit mehrere datein mit der Gleichen endung z.B. .mp3 aufzulisten und dann nach ein anderer die liste abzuarbeiten?

    Mfg
    Marcel

    • admin_ub sagt:

      nein, das ist kein teil einer Library sondern einer Anwendung….die must du selber programmieren.
      das MP3-Projekt macht sowas ähnliches, wie das programmiert ist kannst du da nachsehen.

  37. vasa sagt:

    Hallo!
    Können Sie mir sagen, wie Sie den freien Speicherplatz auf der SD-Karte überprüfen?
    Thank U.

    • admin_ub sagt:

      Der Quellcode ist doch komplett dabei…einfach da nachlesen.

  38. Rudy sagt:

    Hallo, gibt es eine, die ein Beispiel für das Lesen einer Datei geben kann?

    • admin_ub sagt:

      das hier sollte gehen :

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      
      char buffer[5000];
      FIL myFile;
      uint32_t rlen;
      FATFS_t check_fat;
       
      UB_Fatfs_OpenFile(&amp;myFile,"file.hex",F_RD);
      do {
        check_fat=UB_Fatfs_ReadBlock(&amp;myFile,buffer,512,&amp;rlen);
      }
      while((check_fat==FATFS_OK) &amp;&amp; (rlen&gt;0));
      UB_Fatfs_CloseFile(&amp;myFile);

  39. Michel sagt:

    I’m getting a lot of errors like this: error: unknown type name ‘uint64_t’
    I can’t seem to resolve this problem.

    I also get an error on this line: stm32_ub_sdcard.c:774:41: error: expected ‘)’ before ‘cardinfo’

    I haven’t changed anything to your code. Could you please help me?

    • admin_ub sagt:

      what kind of IDE do you use ? (and what version)
      try to include “stdint.h”

  40. Michel sagt:

    I’m sorry for the missing information. I have tested with coocox 1.72 and the newer coocox 2 version. I also tried with the newest gcc. It doesn’t changed my problem. I have used this library of yours earlier and it worked like a charm back then. but from my memory I thought there were no uint_64 declarations back then?

    • admin_ub sagt:

      with my version (1.7.4) i need to include “stdint.h” and then i can use
      “uint64_t” so try to insert this include manually.

      • Michel sagt:

        I have re-installed coocox from 1.7.2 to 1.7.8 and now it’s working again. Many thanks for your libraries. They are always of a high quality!

  41. Vasa sagt:

    Guten Tag!
    Was ist die Cluster-Größe sollte ich verwenden?
    Cluster 4 KB schreibt auf die Karte 2 GB, Fat.

    • admin_ub sagt:

      please rewrite your question in english please. i dont understand your problem.

  42. Vasa sagt:

    2GB Sd-card formatted in Fat FS with a cluster size of 4 KB. But there is an error reading and writing.
    If I use a cluster size of 16 KB, sometimes the file grows in size tenfold when adding a small line of 50 characters.
    What could it be?
    Thank you!

  43. Davide sagt:

    Incredibly good library,
    LFN added in a snap, drop in compatibility with my little project (a room ambiental data logger + digital frame for my room) and very reliable comunication:
    4 bit sdio works flawlessly with 1gb, 4gb, 16gb sdhc cards formatted either in fat16 and fat32!
    I have a question, there is a way to list all the files inside the sd card, or to open something inside a folder? Right now i’ve only accomplished to create/write/read files in the root passing “0:\file.txt” to file open, no luck with “0:\dir\file.txt” for example!

    Thank you again for your work!
    Davide

    • admin_ub sagt:

      to list all files you need a function to do this. In my “uBasic-Project” i have implemented this feature. And directorys are also possible in this project. So download this project and have a look at the sources. http://mikrocontroller.bplaced.net/wordpress/?page_id=4243
      or check the html-docu from Chan in the docu folder.

  44. StefanG. sagt:

    Hallo,

    ich versuche ebenfalls deine Lib zum laufen zu bekommen.

    Die Verdrahtung meiner Platine ist die gleiche wie du vorgibts, außer CD(weshalb ich dies im code deaktiviert habe).

    Ich benutze einen Connector von Molex (47352-1001) und habe 2 Microsd Karten mit 2 GB und eine mit 8 Gb.

    Die Funktion UB_Fatfs_CheckMedia liefert mit FATFS_OK zurück.

    Jedoch bekomme ich bei der UB_Fatfs_mount() immer ein FATFS_MOUNT_ERR zurück.

    Ich habe keine Pullups verwendet. Die Fomratierung der Microsd-Card ist Fat32.

    An welchen Ecken könnte der Fehler sein?

    Um einen Tipp wäre ich dir sehr dankbar.

    Freundliche Grüße
    Stefan

    • StefanG. sagt:

      Habe es zum laufen gebracht. Hatte einen kurzen auf meiner Platine

  45. Peter sagt:

    Hi
    Thank for the super Lib
    I have problem with the write speed. It is only about 40kB/s.
    I use the lib in my own project. F_cpu is 168 Mhz
    I tested 3 differnd SD cards ( 2, 4 and 16 GB)

    When i call the WriteBlock() function 8 times (size set to 512) i need 90ms (4kB of data)

    • admin_ub sagt:

      check sdio clock at PC12
      init : 400kHz
      read/write : 24MHz
      use short connections < 3 cm !!

      • Peter sagt:

        I will checkthe cloks if i buy a Scope.
        But my connections are now 9cm Long, I has really an impact?
        I tested another SD Card and i have 90kB/s

      • Peter sagt:

        I made some measurements

        The clocks are ok i think.
        The problem is that
        when i call UB_Fatfs_WriteBlock() then the micro wait very long in line:
        while(SD_GetStatus() != SD_TRANSFER_OK);
        in function MMC_disk_write()

        while(SD_GetStatus() != SD_TRANSFER_OK); takes over 6ms.
        What does it mean ?

        • admin_ub sagt:

          mmc cards dont have a specified response time. you can incresase the “average” speed, if you wrote more data.
          check the write speed with 1024 * 512 bytes
          it should more than 40 kb/s.

  46. vasa sagt:

    Guten Tag!
    Wie man die Daten von der CD Status Register und Karten status erhalten?
    Vielen Dank!

    • admin_ub sagt:

      ask google


Wie hat Dir dieser Artikel gefallen?

1 Stern2 Sterne3 Sterne4 Sterne5 Sterne (Noch keine Bewertungen)
Loading...

18 Antworten zu 13-FATFS_SDIO-Library (STM32F4)

  1. Michael sagt:

    Guten Abend,

    vielen Dank für die tolle Libary und Projekte.
    Kann ich diese auch für die Kompination STM32F4407 + STM32F4DIS-BB nutzen?
    Was für Einstellungen müssen vorgenommen werden?

    Vielen Dank.

    • admin_mb sagt:

      Hallo Michael,
      meinst du das STM32F4DISCOVERY extension board?
      Wenn ja, dann sollte diese Library auch damit funktionieren. Du musst halt die Benutzte Pins und DMAs entsprechend anpassen. Ich hab zwar dieses Board nicht, aber im User Manual hab ich folgendes gelesen:
      Table 2-3 MicroSD Card Interface

      Pin Signal
      1   D2
      2   D3
      3   CMD
      4   VDD (3.3V)
      5   CLK
      6   VSS (0V)
      7   D0
      8   D1
      

      Table 2-8 Pin multiplexing of CON4 extension port and STM32F4DIS-BB (auf Seite 25)
      Leider fehlt die Angabe zu PC8 und PC9;(

      PC10 : SDIO_D2  = SD-Karte DAT2 (UART4, TXD4)
      PC11 : SDIO_D3  = SD-Karte DAT3 (UART4, RXD4)
      PC12 : SDIO_CK  = SD-Karte Clock (UART5, TXD5)
      PD2  : SDIO_CMD = SD-Karte CMD (UART5, RXD5)
      PC8  : SDIO_D0  = SD-Karte DAT0
      PC9  : SDIO_D1  = SD-Karte DAT1
      

      Ciao, Manfred

      • Michael sagt:

        Hallo,

        vielen Dank für die Antwort.
        Ja genau dieses Board habe ich. Jedoch wo muss ich die benutzte Pins und DMAs entsprechend anpassen?

        Gruß
        Michael

        • admin_mb sagt:

          Hallo Michael,

          ich denke, du kannst alles unverändert übernehmen.

          Schau dir bitte zunächst einmal die Pinbelegung vom STM32F4-Discovery-Board an. Da sind alle Pins zu den SDIOs aufgelistet:

          PC8	SDIO_D0
          PC9	SDIO_D1
          PC10	SDIO_D2
          PC11	SDIO_D3
          PC12	SDIO_CK
          PD2	SDIO_CMD
          

          Der Detect-Pin (GPIO_Pin_0) wird auf PD0 gesetzt.

          Die Funktionen zur SD-Card sind im Modul stm32_ub_sdcard realisiert. Deshalb müssen Änderungen (falls notwendig) im Headerfile stm32_ub_sdcard.h gemacht werden. Hier die relevanten Stellen:

          30
          31
          32
          33
          34
          35
          36
          
          //--------------------------------------------------------------
          // SDIO-Mode
          // 4bit-Mode aktivieren oder deaktivieren
          //    1 = 4bit-Mode
          //    0 = 1bit-Mode
          //--------------------------------------------------------------
          #define   USE_SDIO_4BIT_MODE   1  // (4bit-Mode)
          39
          40
          41
          42
          43
          44
          45
          46
          47
          48
          49
          50
          51
          52
          53
          54
          55
          56
          
          //--------------------------------------------------------------
          // Detect-Pin
          // aktivieren oder deaktivieren
          //    1 = mit Detect-Pin
          //    0 = ohne Detect-Pin
          //--------------------------------------------------------------
          #define   USE_DETECT_PIN      1  // (mit Detect-Pin)
           
           
           
          //--------------------------------------------------------------
          // Detect-Pin der SD-Karte
          //--------------------------------------------------------------
          #if USE_DETECT_PIN==1
            #define SD_DETECT_PIN                    GPIO_Pin_0
            #define SD_DETECT_GPIO_PORT              GPIOC
            #define SD_DETECT_GPIO_CLK               RCC_AHB1Periph_GPIOC
          #endif
          76
          77
          78
          79
          80
          81
          82
          83
          84
          85
          86
          87
          88
          89
          90
          91
          92
          93
          94
          95
          96
          97
          98
          99
          100
          101
          102
          103
          104
          105
          106
          107
          108
          109
          
          //--------------------------------------------------------------
          // DMA Einstellung
          // Moegliche DMAs fuer SDIO :
          //   DMA2_STREAM3_CHANNEL4
          //   DMA2_STREAM6_CHANNEL4
          //--------------------------------------------------------------
           
          #define SD_SDIO_DMA                   DMA2
          #define SD_SDIO_DMA_CLK               RCC_AHB1Periph_DMA2
           
          #define SD_SDIO_DMA_STREAM3	          3
          //#define SD_SDIO_DMA_STREAM6           6
           
          #ifdef SD_SDIO_DMA_STREAM3
           #define SD_SDIO_DMA_STREAM            DMA2_Stream3
           #define SD_SDIO_DMA_CHANNEL           DMA_Channel_4
           #define SD_SDIO_DMA_FLAG_FEIF         DMA_FLAG_FEIF3
           #define SD_SDIO_DMA_FLAG_DMEIF        DMA_FLAG_DMEIF3
           #define SD_SDIO_DMA_FLAG_TEIF         DMA_FLAG_TEIF3
           #define SD_SDIO_DMA_FLAG_HTIF         DMA_FLAG_HTIF3
           #define SD_SDIO_DMA_FLAG_TCIF         DMA_FLAG_TCIF3 
           #define SD_SDIO_DMA_IRQn              DMA2_Stream3_IRQn
           #define SD_SDIO_DMA_IRQHANDLER        DMA2_Stream3_IRQHandler 
          #elif defined SD_SDIO_DMA_STREAM6
           #define SD_SDIO_DMA_STREAM            DMA2_Stream6
           #define SD_SDIO_DMA_CHANNEL           DMA_Channel_4
           #define SD_SDIO_DMA_FLAG_FEIF         DMA_FLAG_FEIF6
           #define SD_SDIO_DMA_FLAG_DMEIF        DMA_FLAG_DMEIF6
           #define SD_SDIO_DMA_FLAG_TEIF         DMA_FLAG_TEIF6
           #define SD_SDIO_DMA_FLAG_HTIF         DMA_FLAG_HTIF6
           #define SD_SDIO_DMA_FLAG_TCIF         DMA_FLAG_TCIF6 
           #define SD_SDIO_DMA_IRQn              DMA2_Stream6_IRQn
           #define SD_SDIO_DMA_IRQHANDLER        DMA2_Stream6_IRQHandler
          #endif /* SD_SDIO_DMA_STREAM3 */
          • Michael sagt:

            Hallo,
            okay so wie ich das sehe muss ich wirklich nichts verändern. Leider wird in der Bedienungsanleitung die Pins nicht wiedergegeben.

            Ich habe mit dem Debugger getestet wie weit ich im Main.c komme. Die If-Bedienung bei UB_Fatfs_Mount wird nicht erfüllt. Woran kann dies liegen? Was wird hier gepürft? Kann ich jede beliebig große SD-Karte einsetzen ? Muss ich die SD-Karte formatieren?

            Danke.

            Gruß
            Michael

          • admin_mb sagt:

            Hallo Michael,

            aber genau in dieser Bedienungsanleitung kannst du folgendes auf Seite 36 lesen:
            4.2.1 FatFs
            1. Description
            The example is located in the following folder:
            \Codes\STM32F4xx_SDIO_Example\Project\FatFs
            2. Hardware Configuration
            A MicroSD card is needed in this example and Kingston 1GB/2GB or SanDisk 2GB
            MicroSD Card is recommended. The card should be formatted before used.
            Note: Kingston 1GB/2GB and SanDisk 2GB MicroSD Card have been tested on
            DevKit407. It’s not guaranteed that all kind of MicroSD card work well on the board.

            Deine SD-Karte muss also (Fat32) formartiert sein, und sollte nicht allzu groß sein.

            Was in der Funktion UB_Fatfs_Mount genau geprüft wird, kannst du ja selbst nachsehen – du hast den Quellcode dazu. Einfach mal reinschauen (bzw. reindebuggen):

            106
            107
            108
            109
            110
            111
            112
            113
            114
            115
            116
            117
            118
            119
            120
            121
            122
            123
            124
            125
            126
            127
            128
            129
            130
            131
            132
            133
            134
            135
            136
            
            //--------------------------------------------------------------
            // Media mounten
            // dev : [MMC_0]
            // Return Wert :
            //     FATFS_OK       => kein Fehler
            //  FATFS_MOUNT_ERR   => Fehler
            //  FATFS_GETFREE_ERR => Fehler
            //--------------------------------------------------------------
            FATFS_t UB_Fatfs_Mount(MEDIA_t dev)
            {
              FATFS_t ret_wert=FATFS_MOUNT_ERR;
              FRESULT check=FR_INVALID_PARAMETER;
              DWORD fre_clust;
              FATFS	*fs;
             
              if(dev==MMC_0) check=f_mount(0, &FileSystemObject);
              if(check == FR_OK) {
                if(dev==MMC_0) check=f_getfree("0:", &fre_clust, &fs);
                if(check == FR_OK) {
                  ret_wert=FATFS_OK;
                }
                else {
                  ret_wert=FATFS_GETFREE_ERR;
                }
              }
              else {
                ret_wert=FATFS_MOUNT_ERR;
              }
             
              return(ret_wert);
            }
  2. Slacky sagt:

    Hello.

    Thanks for the library. The only working implementation. Couple of questions. If I read from the file, the last line is not displayed – returns FALSE_EOF, but the data remains in the buffer.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    if (f_OpenFile(&myFile, "0:/UB_File.txt", F_WR_CLEAR)
    					== FATFS_OK) {
    				//записать несколько строк в файл
    				f_WriteString(&myFile, "Test write");
    				f_WriteString(&myFile, "hier Zeile zwei");
    				f_WriteString(&myFile, "Kjhkjhskdjhkashdkashdkjashdkasdkjh");
    				f_WriteString(&myFile, "eoritueoritu");
    				// закрыть файл
    				f_CloseFile(&myFile);
    			}
    			if (f_OpenFile(&myFile, "0:/UB_File.txt", F_RD) == FATFS_OK) {
    				while (1) {
    					memset(buff, 0, sizeof(buff));
    					fs = f_ReadString(&myFile, buff, sizeof(buff));
    					if (fs == FATFS_OK) {
    						printf("%srn", buff);
    					} else break;
    				}
    				f_CloseFile(&myFile);
    			}

    On the last string „eoritueoritu“ returns FATFS_EOF.

    • admin_mb sagt:

      Hello Slacky,

      please have a look to the UB_Fatfs_ReadString() function. It returns FATFS_OK but also at the end of the file FATFS_EOF!
      So you have to change your Source code:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      
      while (1)
      {
        memset(buff, 0, sizeof(buff));
        fs = f_ReadString(&myFile, buff, sizeof(buff));
        if (fs != FATFS_RD_STRING_ERR)
        {
          printf("%srn", buff);
        }
        if (fs != FATFS_OK)
        {
          break;
        }
      }

      Here is the UB_Fatfs_ReadString() function:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      
      //--------------------------------------------------------------
      // String aus einem File lesen
      // File muss offen sein
      // File per &-Operator übergeben
      // text : String
      // len  : Grösse des String-Puffers
      //        es werden (len) Zeichen ausgelesen
      //        oder bis Fileende bzw. Stringende erreicht ist
      // Return Wert :
      //     FATFS_OK        => kein Fehler
      //    FATFS_EOF        => Fileende erreicht
      // FATFS_RD_STRING_ERR => Fehler
      //--------------------------------------------------------------
      FATFS_t UB_Fatfs_ReadString(FIL* fp, char* text, uint32_t len)
      {
        FATFS_t ret_wert=FATFS_RD_STRING_ERR;
        int check;
       
        f_gets(text, len, fp);
        check=f_eof(fp);
        if(check!=0) return(FATFS_EOF);
        check=f_error(fp);
        if(check!=0) return(FATFS_RD_STRING_ERR);
        ret_wert=FATFS_OK;
       
        return(ret_wert);
      }
      • Slacky sagt:

        IMHO a good idea to change the function UB_Fatfs_ReadString

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        
        FATFS_t UB_Fatfs_ReadString(FIL* fp, char* text, uint32_t len)
        {
          FATFS_t ret_wert=FATFS_RD_STRING_ERR;
          int check;
         
          check=f_eof(fp);
          if(check!=0) return(FATFS_EOF);
          f_gets(text, len, fp);
          check=f_error(fp);
          if(check!=0) return(FATFS_RD_STRING_ERR);
          ret_wert=FATFS_OK;
         
          return(ret_wert);
        }
        • admin_mb sagt:

          Sorry Slacky, this is not a good idea – besides, it’s wrong. You can check it out yourselve;)

          • Slacky sagt:

            Sorry, but before You write, I checked it out. My code.

            if (f_OpenFile(&myFile, "0:/UB_File.txt", F_WR_CLEAR)
            					== FATFS_OK) {
            				f_WriteString(&myFile, "Test write");
            				f_WriteString(&myFile, "hier Zeile zwei");
            				f_WriteString(&myFile, "Kjhkjhskdjhkashdkashdkjashdkasdkjh");
            				f_WriteString(&myFile, "eoritueoritu");
            				f_CloseFile(&myFile);
            			}
            			if (f_OpenFile(&myFile, "0:/UB_File.txt", F_RD) == FATFS_OK) {
            				printf("myFile->fsize = %d\r\n", myFile.fsize);
            				printf("myFile->fptr = %d\r\n", myFile.fptr);
            				memset(buff, 0, sizeof(buff));
            				while (f_ReadString(&myFile, buff, sizeof(buff)) == FATFS_OK) {
            						printf("buff - %s\r\n", buff);
            						printf("myFile->fptr = %d\r\n", myFile.fptr);
            						memset(buff, 0, sizeof(buff));
            				}
            				f_CloseFile(&myFile);
            			}
            
            The output from the terminal.
            
            myFile->fsize = 79
            myFile->fptr = 0
            buff - Test write
            myFile->fptr = 12
            buff - hier Zeile zwei
            myFile->fptr = 29
            buff - Kjhkjhskdjhkashdkashdkjashdkasdkjh
            myFile->fptr = 65
            buff - eoritueoritu
            myFile->fptr = 79
            

            I don’t see the error.

          • admin_mb sagt:

            Hi Slacky,
            yes, you’re right that looks better than I thought;)

  3. Andreas Wiese sagt:

    Hallo,

    vielen Dank für die Bibliothek.
    Ich bin gerade von einer anderen umgestiegen und bisher sehr zufrieden.
    Allerdings habe ich noch einen Fehler entdeckt, der vermutlich in Zusammenhang mit dem FatFS keine Auswirkung hat, mich aber bei der anderen Lib, die den gleichen Fehler hatte, etliche Stunden debugging gekostet hat, da hier echte Speicherverletzungen mit diversen Folgefehlern auftreten können.

    In der Funktion SD_ReadBlock in der Datei stm32_ub_sdcard sind zwei Zeilen vertauscht:

    in der Lib steht:
    SDIO_DMACmd(ENABLE);
    SD_LowLevel_DMA_RxConfig((uint32_t *)readbuff, BlockSize);

    korrekt ist
    SD_LowLevel_DMA_RxConfig((uint32_t *)readbuff, BlockSize);
    SDIO_DMACmd(ENABLE);

    Da der Fehler in SD_ReadMultiBlock korrigiert ist (im Gegensatz zu meiner anderen Lib) sollte der Fehler bei Nutzung von FatFs vermutlich keine Auswirkung haben.

    Viele Grüße
    Andreas

    • admin_mb sagt:

      Hallo Andreas Wiese,
      vielen Dank für dein Feedback und den Korrekturhinweis.
      Ich habe alle stm32_ub_sdcard.c Module korrigiert und die entsprechenden Zipfiles neu hochgeladen:

      • Demo_20_FATFS_Picture.zip
      • ub_stm32f4_fatfs_picture_v103.zip
      • Demo_47_MP45DT02.zip
      • ub_stm32f4_mp45dt02_v100.zip
      • Show_04_Webserver_SD.zip
      • Demo_13_FATFS_SDIO.zip
      • ub_stm32f4_fatfs_sdio_v104.zip
      • Demo_87_DUAL_FATFS.zip
      • ub_stm32f4_dual_fatfs_v105.zip
      • STM32F429_Basic_V100_Light.zip
      • f429_fatfs_mmc.zip
      • F429Board_SDIO.zip

      LG, Manfred

  4. Johannes sagt:

    Hallo,

    wir setzen die Bibliothek in einem komerziellen Produkt ein. Vielen Dank dafür und es funktioniert eigentlich auch ganz gut.

    Uns ist aufgefallen, dass die Timeout-Konstante SD_DATATIMEOUT in der Datei stm32_ub_sdcard.h ziemlich groß ist (0xFFFFFFFF). Das entspricht auf unserem Controller ca. 25 Minuten.
    Hier wäre ein Hinweis in der Doku sinnvoll, dass man da einen passenden Wert eintragen sollte.

    Diese Konstante wird im Source-Code unterschiedlich verwendet. Zum einen wird das Register SDIO_DTIMER im SDIO-Interface damit geladen, zum anderen wird der Schleifenzähler in mehreren while() -Schleifen damit initialisiert.
    Das müssten aber nach meinem Verständnis verschiedene Zahlenwerte sein, wenn man die gleichen Timeout-Zeiten erreichen möchte.

    Am besten wäre es, im header zwei Konstanten zu definieren, also eine für den Hardware-Timeout und eine als Schleifenzähler und beide ganz an den Anfagn zu stellen, so dass man sofort sieht, dass der Anwender diese auf einen für ihn passenden Wert einstellen sollte.

  5. ali sagt:

    Hallo @admin_mb,
    vielen Dank für dieses tolle Bibliothek.

    Sie funktioniert leider bei mir irgendwie zu langsam.
    Ich messe bei Block-read nur ca 516 kb/s im 4bit-Mode .

    Habe so Einiges ausprobiert,aber das höchste waren nur 5 Bilder /s .

    Wäre Es möglich die messung vom Block-read ins Demo (über USART) zu integrieren ?

    Meine Messung ist folgendermasen:

    // ———————————————————————————-
    void Print_SDIO_BMP(char*Image){

    // COUNTER_START_ms
    uint32_t stop=0x00 ;UB_Systick_Counter1(COUNTER_START_ms);

    UB_LCD_SetCursor2Draw(0,0);
    UB_Fatfs_OpenFile(&your_File,Image,F_RD);
    //——————————————————————————
    for(int s=0;s<(300) ;s++){ UB_Fatfs_ReadBlock(&your_File,Puffer_512,512,&rlen);

    for(int z=0;z<(512) ;z=z+2){ LCD_RAM=(Puffer_512 [z]<<8)+Puffer_512 [z+1];}}
    // Zeitmessung
    stop= UB_Systick_Counter1(COUNTER_CHECK);Send_UART_32("stop :",stop);}
    // ——————————————————————————–

  6. Michael sagt:

    Sorry, No-Go.

    Funktioniert keineswegs.

  7. Markus sagt:

    Guten Tag,

    kurze Frage.

    Die Funktion
    UB_Fatfs_ReadString(&myFile, text, len);
    liefert einen char pointer zurück.

    In den meisten Fällen aber nützt dies herzlich wenig,
    da man in anderen Funktionen den gelesenen Text
    ja auswerten muss.

    Dies geschieht meisst so, indem man die einzelnen Zeichen nach und nach
    auswertet und dann Fallunterscheidungen anwedet.

    Wie kann man hier den Char *text
    in ein indexierbares Array konvertieren ?

    Danke im Voraus !

    Markus

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert