32-USB_MSC_HOST-Library (STM32F4)

Mit dieser Library können normale USB-Sticks am USB-OTG-Port vom Discovery-Modul betrieben werden. Per FATFS-Library (die USB-Version) kann dann mit Filefunktionen darauf zugegriffen werden.
Hinweis : es gibt noch eine Library für SD-Karten per FATFS (Nr. 13) und eine kombinierte Library SD+USB (Nr. 87)

Die Library hat nur zwei Funktionen :
1. Eine “Init-Funktion”
Die muss beim start einmal aufgerufen werden.

2. Die “HOST_Do-Funktion”
Diese muss zyklisch, am besten in der while(1) aufgerufen werden. Sie liefert den Status vom Memory-Stick zurück. Dieser Status muss ausgewertet werden und erst wenn ein USB-Stick erkannt wurde, darf per FATFS darauf zugegriffen werden.

Hinweis : ich hab hier zwei USB-Sticks ausprobiert. Einmal ein 8GB-Stick von SanDisk. Mit diesem kommt es aber zu einem Fehler -> “DEVICE_NOT_SUPPORTED”. Mit dem zweiten Stick, einem 4GB Intenso kommt kein Fehler und das schreiben und lesen funktioniert ohne Probleme.

Es wird ein USB-Adapter mit Micro-USB-Stecker benötigt. (gibts bei EBay oder Amazon)

Beispielbild :

Benutzte Pins :

PA9   -> USB_OTG_VBUS
PA10  -> USB_OTG_ID
PA11  -> USB_OTG_DM
PA12  -> USB_OTG_DP
PC0   -> USB_VBUS_Enable

Voraussetzungen :

Benutzte Module der CooCox-IDE : GPIO, MISC
Benutzte Librarys : STM32_UB_FATFS (USB-Version)

Enumerationen :

typedef enum {
  USB_MSC_HOST_NO_INIT =0,   // USB-Schnittstelle noch nicht initialisiert
  USB_MSC_DEV_DETACHED,      // kein Device angeschlossen
  USB_MSC_SPEED_ERROR,       // USB-Speed wird nicht unterstützt
  USB_MSC_DEV_NOT_SUPPORTED, // Device wird nicht untersützt
  USB_MSC_DEV_WRITE_PROTECT, // Device ist schreibgeschützt
  USB_MSC_OVER_CURRENT,      // Überstrom erkannt
  USB_MSC_DEV_CONNECTED      // Device verbunden und bereit
}USB_MSC_HOST_STATUS_t;

Funktionen :

void UB_USB_MSC_HOST_Init(void);                 // zum init des USB-Host
USB_MSC_HOST_STATUS_t UB_USB_MSC_HOST_Do(void);  // zum check vom Device-Status

Beispiel :

//--------------------------------------------------------------
// File     : main.c
// Datum    : 13.04.2013
// Version  : 1.0
// 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 USB-MSC-HOST-Library
// Hinweis  : Diese zwei Files muessen auf 8MHz stehen
//              "cmsis_boot/stm32f4xx.h"
//              "cmsis_boot/system_stm32f4xx.c"
//--------------------------------------------------------------

#include "main.h"
#include "stm32_ub_led.h"
#include "stm32_ub_usb_msc_host.h"

int main(void)
{
  FIL myFile;   // Filehandler
  uint8_t write_ok=0;

  SystemInit(); // Quarz Einstellungen aktivieren

  // Init der LEDs
  UB_Led_Init();

  // Init vom USB-OTG-Port als MSC-HOST
  // (zum lesen/schreiben auf einen USB-Stick)
  UB_USB_MSC_HOST_Init();

  while(1)
  {
    // pollen vom USB-Status
    if(UB_USB_MSC_HOST_Do()==USB_MSC_DEV_CONNECTED) {
      // wenn USB-Stick erkannt wurde
      UB_Led_On(LED_GREEN);

      // wenn File noch nicht geschrieben wurde
      if(write_ok==0) {
       	write_ok=1;
       	UB_Led_On(LED_RED);
       	// Media mounten
       	if(UB_Fatfs_Mount(USB_0)==FATFS_OK) {
          // File zum schreiben im root neu anlegen
          if(UB_Fatfs_OpenFile(&myFile, "USB_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(USB_0);
        }
        UB_Led_Off(LED_RED);
      }
    }
    else {
      // wenn kein USB-Stick vorhanden
      UB_Led_Off(LED_GREEN);
    }
  }
}

Hier die Library zum Download :

ub_stm32f4_usb_msc_host_v100

Hier der komplette CooCox-Projektordner zum Download :

Demo_32_USB_MSC_HOST

43 Antworten auf 32-USB_MSC_HOST-Library (STM32F4)

  1. Christian sagt:

    Hey, der USB stick wird von mir soweit erkannt, das heisst es müsste auch alles korrekt initialisiert sein…jedoch bricht bricht mir der usb process immer bei der USBH_HandleEnum ab und weiss einfach nicht warum evtl kannst du mir weiterhelfen.

    • admin_ub sagt:

      wie ich geschrieben habe, hab ich auch einen Stick der nicht funktioniert. Ich vermute der Code ist nicht ganz Fehlerfrei…aber ich suche da keine Fehler. Versuchs mal mit einem anderen Stick oder im Netz nach einer anderen implementation.

  2. Daniel sagt:

    Hallo, bei mir funktioniert alles einwandfrei und der USB- Stick wird sofort erkannt. Allerdings frage ich mich, wie es möglich ist, dass man auf Dateien zugreifen kann, ohne ihren genauen Namen zu wissen. Ich möchte zum Beispiel die erste Datei, die auf dem Stick vorhanden ist öffnen, um daraus zum Beispiel einen mp3- Player zu realisieren. Ich bin noch ziemlicher Anfänger auf dem Gebiet, also wäre es super wenn mir jemand helfen könnte!

    • admin_ub sagt:

      ich hab schon einen MP3-Player realisiert : Show-Prj-03. Da kannst du auch nachlesen wie man per “f_readdir()” ein Direktory-Eintrag ausließt. Oder ließ in der Doku von ChaN nach, da stehen auch Beispiele drinn.

  3. Daniel sagt:

    Dieses Projekt hatte ich leider noch nicht gesehn. Es wird mir sicher sehr weiterhelfen. Danke!

  4. Thierry sagt:

    Hello,
    Very good code, i tried it with a OBD2 USB device.
    Big thanks.
    I will come back in few days to write report.

  5. Sven sagt:

    Hi,
    ich wollte mal nachfragen, was alles beim zusammenführen von USB und SDIO zu tun ist?
    Oder hast du es evtl. schon gemacht und nur vergessen upzudaten?
    Über Hilfe würde ich mich freuen.

  6. Emsila sagt:

    Hello.
    I want use USB_CDC and USB_MSC in one program. When press user taster, usb mode change state. How to use usb_cdc and usb_msc at same time?
    Best regards,
    EI

  7. Christian sagt:

    Hallo,

    bei mir erkennt das Programm meinen USB Stick nicht. Was kann es da haben? Die grüne LED leuchtet.

    Danke

    bg Christian

  8. Gary sagt:

    Hi,
    I used Google translate in my post and maybe it’s not so good, so I will write this one in english. Sorry for 2 posts!

    By the way, thanks for writing and sharing your code, it makes it easier to help things started.

    I have tested your code in my target application with the needed changes and it works OK! This was using your project in Coocox.
    However, I am using Atollic, and as you know, it’s quite similar to Coocox. I added the directory “ub_lib” to my project, and then your test code in my “main.c” file. However, it doesn’t seem to work. It always returns “USB_MSC_DEV_DETACHED”.

    Why would this work good in Coocox, but not in Atollic? Can you think of anything?

    Gary

    • admin_ub sagt:

      could be many things. check these two first :
      1. CPU clock (must be 168 MHz and USB @48MHz)
      2. Optimization should be : “O0 = none”

  9. Roy sagt:

    Hi, I’m having a problem, the demo works, I can write in the pen drive. But when I try to use the library in another project the status change to USB_MSC_DEV_DETACHED, could it be because a conflict with another libraries?
    I’m using:
    #include “stm32_ub_lcd_2x16.h”
    #include “stm32f4xx.h”
    #include “stm32f4xx_gpio.h”
    #include “stm32f4xx_rcc.h”
    #include “stm32f4xx_tim.h”
    #include “stm32f4xx_usart.h”
    #include “misc.h”
    #include “stdio.h”
    #include “stm32_ub_keymatrix.h”
    #include “stm32_ub_led.h”
    #include “stm32_ub_usb_msc_host.h”

    Also I’m using a library from the DHT11 sensor that uses USART but anothers ports.

    I created a function Copy that contains the code that it’s in the while from the demo (if(UB_USB_MSC_HOST_Do()==USB_MSC_DEV_CONNECTED) { ….)
    When I need to copy something I call Copy (inside the main).
    The clock it’s at 168MHz

    Thanks

    • admin_ub sagt:

      dont add 1000 lines of code and try to find a failure.
      Make a running version und add a single new function.
      Test the new function (and all old functions) and so on.
      Thats the only way to handle big projects.

    • admin_ub sagt:

      besides…the function “UB_USB_MSC_HOST_Do()”
      must called the whole time
      maybe you must use the Systick to do this

      • Roy sagt:

        Yes, after I wrote this I get how it works to see if it’s connected or not.
        My problem now is that it recognizes as connected, but says is unmounted. I guess I’m missing something

        • Roy sagt:

          I mean, only writes once, after that nothing, just connected but not mounted (I read a sensor and save the data, in a loop)

          • admin_ub sagt:

            try this flow :

            
            while(1) 
            {    
              if(UB_USB_MSC_HOST_Do()==USB_MSC_DEV_CONNECTED) {
                if(UB_Fatfs_Mount(USB_0)==FATFS_OK) {          
                  if(UB_Fatfs_OpenFile(&myFile, "USB_File.txt", F_WR_CLEAR)==FATFS_OK) {
                    while(UB_USB_MSC_HOST_Do()==USB_MSC_DEV_CONNECTED) {
                      // 1. read here the data from your sensor
                      // 2. write here the data to the file (with UB_FatFS_Write)
                      //
                      // if you want to exit, use "break"
                    }
                    UB_Fatfs_CloseFile(&myFile);
                  }
                  UB_Fatfs_UnMount(USB_0);
                }
              }
            }
            
            
  10. TomTom sagt:

    Funktioniert aufs erste mal flashen einwandfrei.
    Habe ebenfalls einen Intenso USB Stick mit 4GB verwendet.
    Adapterkabel gibts günstig bei Amazon oder Ebay.

    Wiedermal vielen Dank für deine Seite!

  11. Roy sagt:

    Hi,me again (I cant reply in your answer so I write here)
    The flow you gave works, but, if I need to do something else,and then go back and write data in the stick,99% fails to mount it, it’s like 1st time mounting it works, but 2nd fails (keeps connected, but unmounted). What could be the problem?

    Let’s supose in the file I have 5 lines of text, if I need to read line 1,then 2,then3,then 2 again, it’s that posible?
    There’s a f_lseek in ff.h library, should use it?

    Thanks!

    • Roy sagt:

      I think I found the problem:
      UB_Fatfs_Mount checks f_mount,f_mount checks chk_mounted. 1st time it’s ok, but after that chk_mounted returns FR_NO_FILESYSTEM ( No FAT volume is found).
      I changed the return value to FR_OK and now everytime I want to mount the USB, it works, but it shouldn’t be like that, right?

      • admin_ub sagt:

        maybe the drive needs a delay after plugin to be ready.
        try a loop until mount is ok.
        and you dont have to mount a allready mounted device.

    • admin_ub sagt:

      yes, with fseek you can skip to a position you want. but you must know
      the position. in the easiest way all lines have the same lenght.
      if not, you have to search the “carriage return” or another special byte.

  12. Frank Wolk sagt:

    Hallo,
    erstmal danke für Deine Librarys!
    Ich möchte in das Textfile Werte von meinem ADC Wandler hineinschreiben.
    Aber ich bekomm das einfach nicht hin :/ Könntest Du mir einen Tipp geben?
    Ich wäre dafür sehr dankbar!!

    UB_Fatfs_WriteString(&myFile, ADCWert);

    Dazu hab ich versucht die Funktion anzupassen (ohne Erfolg):

    FATFS_t UB_Fatfs_WriteString(FIL* fp, int Wert)
    {
    FATFS_t ret_wert=FATFS_PUTS_ERR;
    int check=0;

    check=f_puts(wert, fp);

    if(check>=0) {
    ret_wert=FATFS_OK;
    // Zeilenendekennung hinzufügen
    f_putc(‘\n’, fp);
    }
    else {
    ret_wert=FATFS_PUTS_ERR;
    }

    return(ret_wert);
    }

  13. Timo sagt:

    Hi,
    erstmal danke für Librarys.
    Obwohl ich an dem Beispielprogramm nichts verändert habe, bekomme ich beim builden folgende Fehlermeldung:

    “.\Objects\testusb.axf: Error: L6200E: Symbol USB_MSC_HOST_STATUS multiply defined (by stm32_ub_usb_msc_host.o and main.o).”

    Hast du eine Idee, wie man das Problem lösen kann?
    Danke im voraus!

  14. Alex sagt:

    Hi,

    danke für die Library.
    Die Hex-Datei funktioniert super, möchte ich jedoch das Projekt mit uVision Keil builden bekomme ich den gleichen Fehler wie Timo.

    Würde mich sehr über deine Hilfe freuen.

    • admin_ub sagt:

      vermutlich mag er die initialisierung der Variable “USB_MSC_HOST_STATUS” im H-File nicht.
      verschiebe mal die Zeile

      USB_MSC_HOST_STATUS_t USB_MSC_HOST_STATUS;

      von stm32_ub_usb_msc_host.h nach stm32_ub_usb_msc_host.c
      compiliere dann nochmal und füge bei allen C-Files die dann eine
      fehler zeigen wegen unbekannter variable diese zeile ein :

      extern USB_MSC_HOST_STATUS_t USB_MSC_HOST_STATUS;

  15. Matthias sagt:

    Here are the necessary changes for STM32F429 Discovery:
    ///// usb_bsp.h
    #define HOST_POWERSW_PORT_RCC RCC_AHB1Periph_GPIOC
    #define HOST_POWERSW_PORT GPIOC
    #define HOST_POWERSW_VBUS GPIO_Pin_4

    ///// usb_bsp.c
    //————————————————————–
    void USB_OTG_BSP_Init(USB_OTG_CORE_HANDLE *pdev)
    {
    GPIO_InitTypeDef GPIO_InitStructure;

    RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB , ENABLE);

    /* Configure SOF VBUS ID DM DP Pins */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    GPIO_PinAFConfig(GPIOB,GPIO_PinSource13,GPIO_AF_OTG2_FS);
    GPIO_PinAFConfig(GPIOB,GPIO_PinSource14,GPIO_AF_OTG2_FS);
    GPIO_PinAFConfig(GPIOB,GPIO_PinSource15,GPIO_AF_OTG2_FS);

    /* this for ID line debug */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_OTG2_FS);

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_OTG_HS, ENABLE) ;
    }

    //————————————————————–
    void USB_OTG_BSP_EnableInterrupt(USB_OTG_CORE_HANDLE *pdev)
    {
    NVIC_InitTypeDef NVIC_InitStructure;
    /* Enable USB Interrupt */
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);

    NVIC_InitStructure.NVIC_IRQChannel = OTG_HS_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    }

    //————————————————————–
    void OTG_HS_IRQHandler(void)
    {
    USBH_OTG_ISR_Handler(&USB_OTG_Core);
    }

    ///// stm32_ub_led.h
    typedef enum
    {
    LED_GREEN = 0, // LED4 auf dem STM32F4-Discovery
    LED_RED = 1, // LED5 auf dem STM32F4-Discovery
    }LED_NAME_t;

    ///// stm32_ub_led.c
    LED_t LED[] = {
    // Name ,PORT , PIN , CLOCK , Init
    {LED_GREEN ,GPIOG,GPIO_Pin_13,RCC_AHB1Periph_GPIOG,LED_OFF}, // PD12=Gruene LED auf dem Discovery-Board
    {LED_RED ,GPIOG,GPIO_Pin_14,RCC_AHB1Periph_GPIOG,LED_OFF}, // PD14=Rote LED auf dem Discovery-Board
    };

    ///// stm32_ub_usb_msc_host.c
    void UB_USB_MSC_HOST_Init(void)
    {
    USB_MSC_HOST_STATUS=USB_MSC_DEV_DETACHED;
    USBH_Init(&USB_OTG_Core, USB_OTG_HS_CORE_ID, &USB_Host, &USBH_MSC_cb, &USR_Callbacks);
    }

  16. Matthias sagt:

    Hallo,

    ich möchte diese Software auf einem Custom Board nutzen. Leider erkennt Sie dort den angeschlossenen USB Stick nicht. Auf dem Discovery gehts natürlich.

    Hast du irgendeinen Plan, wo ich beim debuggen starten kann? Muss ich die Flanken vergleichen, ob die passen? Oder soll ich in der Software nachschauen wann beide Projekte unterschiedlich laufen?

    Grüße,
    Matthias

    • Matthias sagt:

      Nachtrag: Ich habe kein VBUS Signal und kein OTG ID. Ist das problematisch? Die 5V Versorgung ist dauerhaft an.

      • admin_ub sagt:

        wenn die software auf einem anderen board läuft, warum denkst du dann es ist ein software problem ?

      • Rolf sagt:

        Hallo Matthias,

        ich stehe vor der gleichen Frage: der Stick hat ja nun mal nur vier Kontakte, DM, DP und zwei für die Versorgung. Ich vermute auch, dass die Software auf dem Vorhandensein der beiden anderen Anschlüsse basiert, habe aber noch keine Lösung gefunden. Bist Du schon weiter?

        Besten Dank
        Rolf

  17. chris sagt:

    if someone wants to use binaryfiles, is necessary to have look on:

    ff.c (4173)
    #if _USE_STRFUNC >= 2

    and

    ffconf.h (39)
    #define _USE_STRFUNC 1 /* 0:Disable or 1-2:Enable */
    /* To enable string functions, set _USE_STRFUNC to 1 or 2. */

    If _USE_STRFUNC isnt set correctly every 0xA will result in 0xD 0xA.

    Chris

  18. Manuel sagt:

    Hallo,
    blöde Frage von einem blutigen Anfänger: Wie bringe ich das Ganze in Keil uVision zum laufen?
    Habe bis jetzt mit dem STM32 MX Cube gearbeitet, und Files einfach hinzufügen geht irgendwie nicht so einfach…
    Hat jemand Tipps für mich?

    Danke und LG,
    Manuel

Hinterlasse eine Antwort

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


sechs + zwei =

Du kannst folgende HTML-Tags benutzen: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>