1. 程式人生 > >STM32 之 標準外設版 USB 驅動 + MSC(Host) + Fatfs 移植

STM32 之 標準外設版 USB 驅動 + MSC(Host) + Fatfs 移植

寫在前面

  • 現在,網上關於STM32的USB的文章數不勝數。寫這篇文章僅僅是對於自我學習的一個記錄。主要是對實際學習中遇到的一些棘手問題做個備忘錄。使用的晶片為STM32F407VG
  • 目前,ST的USB驅動有兩套,一套是早期的獨立版USB驅動,官方培訓文件中稱為Legacy library,最新版為2.2.0;一套為針對其Cube系列的驅動,根據晶片不同可能有區別,具體見對應晶片的Cube驅動包,官方培訓文件中稱為Cube library。 本文使用的為Legacy libraryUSB驅動。更詳細的請參考博文STM32 之 USB IP(USB模組) 詳解
  • HAL庫 + Legacy library USB庫兩個混用
  • 目前,Fatfs 驅動最新版為R0.13a 。
  • 本文多出自於ST的官方文件,讀者也可以直接去ST官網查閱相關文件。
  • 本文主要涉及USB Host(全速)+ MSC + Fatfs的移植。其他移植後續用到再說。

USB驅動部分

原始碼移植

  原始碼的移植相對來說比較簡單,使用時,根據需要複製相關的檔案即可。需要注意的是,整理一下原始碼的結構。這個在上一篇博文中已經由說明了。具體見下圖:
USB Host
  在移植其他部分的時候與之類似,只需要替換成對應部分的原始碼檔案即可。

  1. 原始碼中的 USB OTG部分是所有其他模組的驅動程式。
  2. usbh_msc_fatfs.c為ST提供的FatFs的diskio.c
    的具體實現檔案。在使用了該檔案後,使用者不必再自行實現FafFs的diskio.c了。

###原始碼配置
  整個USB驅動用於靈活的配置選項,且通過一個配置檔案的形式給出。這樣,使用者可以儘量少的修改的驅動原始碼。這些配置檔案均為使用者級別的檔案,通常來說置於使用者程式碼目錄下。如下如所示:
USBHostUser
  作為使用者級檔案,通常所有的使用者程式碼均在以上檔案做修改即可,只有少數特殊處理會設計到驅動程式原始碼的修改。在配置好後,一般來說,所有修改均在usbh_usr.h/.c中。

usb_config.h

  usb_config.h是USB OTG 底層驅動的配置檔案。在USB OTG的原始碼中,ST提供了usb_conf_template.h

。使用者只需要複製該檔案到自己的程式碼目錄下,修改即可。具體配置見下文的註釋部分:

/**  ******************************************************************************
  * @file    usb_conf.h
  * @author  
  * @version V2.2.0
  * @date    2017.12.27
  * @brief   USB的底層驅動配置
 ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2017 ST</center></h2>
  *
  * 
 ******************************************************************************
  */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USB_CONF__H__
#define __USB_CONF__H__

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"		/* 這裡需要包含自己使用的ST的庫的標頭檔案 */
/** @addtogroup USB_OTG_DRIVER
  * @{
  */
/** @defgroup USB_CONF
  * @brief USB 底層驅動配置檔案
  * @{
  */ 
/** @defgroup USB_CONF_Exported_Defines
  * @{
  */ 
/* USB Core and PHY interface 配置.
   Tip: To avoid modifying these defines each time you need to change the USB configuration, you can declare the needed define in your toolchain compiler preprocessor.
   */
/**** 配置檔案包含了Full Speed 和 High Speed 兩種速率的配置,使用時,從兩者選擇其一即可。****/
/****************** USB OTG FS PHY 配置 *******************************
*   USB OTG FS Core 支援 one on-chip Full Speed PHY。通常,ST晶片內部已經集成了該PHY。
*  
*  當使用了FS core時,巨集USE_EMBEDDED_PHY 需要在編譯器中定義.
*  
*******************************************************************************/
#ifndef USE_USB_OTG_FS
	#define USE_USB_OTG_FS						/* 使用 FS, 與下面的 HS 只能選一個。目前,終端只支援FS */
#endif /* USE_USB_OTG_FS */

#ifdef USE_USB_OTG_FS 
	#define USB_OTG_FS_CORE
#endif
/****************** USB OTG HS PHY 配置 *******************************
*  USB OTG HS Core 支援 兩種 PHY 介面:
*   (i)  使用外部高速PHY的ULPI 介面:  USB HS Core 工作在高速模式下
*   (ii) 片內Full Speed PHY: USB HS Core 工作在全速模式下
*  通過下面兩個巨集,選擇使用哪種PHY:
*   (i)  USE_ULPI_PHY: if the USB OTG HS Core is to be used in High speed mode 
*   (ii) USE_EMBEDDED_PHY: if the USB OTG HS Core is to be used in Full speed mode
*
*  Notes: 
*   - The USE_ULPI_PHY symbol is defined in the project compiler preprocessor as default PHY when HS core is used.
*   - On STM322xG-EVAL and STM324xG-EVAL boards, only configuration(i) is available.
*     Configuration (ii) need a different hardware, for more details refer to your  STM32 device datasheet.
*******************************************************************************/
#ifndef USE_USB_OTG_HS
	//#define USE_USB_OTG_HS
#endif /* USE_USB_OTG_HS */

#ifndef USE_ULPI_PHY
	//#define USE_ULPI_PHY
#endif /* USE_ULPI_PHY */

#ifndef USE_EMBEDDED_PHY
	//#define USE_EMBEDDED_PHY
#endif /* USE_EMBEDDED_PHY */

#ifdef USE_USB_OTG_HS 
	#define USB_OTG_HS_CORE
#endif

/*******************************************************************************
*                      FIFO Size Configuration in Device mode
*  
*  (i) Receive data FIFO size = RAM for setup packets + 
*                   OUT endpoint control information +
*                   data OUT packets + miscellaneous
*      Space = ONE 32-bits words
*     --> RAM for setup packets = 10 spaces
*        (n is the nbr of CTRL EPs the device core supports) 
*     --> OUT EP CTRL info      = 1 space
*        (one space for status information written to the FIFO along with each 
*        received packet)
*     --> data OUT packets      = (Largest Packet Size / 4) + 1 spaces 
*        (MINIMUM to receive packets)
*     --> OR data OUT packets  = at least 2*(Largest Packet Size / 4) + 1 spaces 
*        (if high-bandwidth EP is enabled or multiple isochronous EPs)
*     --> miscellaneous = 1 space per OUT EP
*        (one space for transfer complete status information also pushed to the 
*        FIFO with each endpoint's last packet)
*
*  (ii)MINIMUM RAM space required for each IN EP Tx FIFO = MAX packet size for 
*       that particular IN EP. More space allocated in the IN EP Tx FIFO results
*       in a better performance on the USB and can hide latencies on the AHB.
*
*  (iii) TXn min size = 16 words. (n  : Transmit FIFO index)
*   (iv) When a TxFIFO is not used, the Configuration should be as follows: 
*       case 1 :  n > m    and Txn is not used    (n,m  : Transmit FIFO indexes)
*       --> Txm can use the space allocated for Txn.
*       case2  :  n < m    and Txn is not used    (n,m  : Transmit FIFO indexes)
*       --> Txn should be configured with the minimum space of 16 words
*  (v) The FIFO is used optimally when used TxFIFOs are allocated in the top 
*       of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones.
*******************************************************************************/

/*******************************************************************************
*                     FIFO Size Configuration in Host mode
*  
*  (i) Receive data FIFO size = (Largest Packet Size / 4) + 1 or 
*                             2x (Largest Packet Size / 4) + 1,  If a 
*                             high-bandwidth channel or multiple isochronous 
*                             channels are enabled
*
*  (ii) For the host nonperiodic Transmit FIFO is the largest maximum packet size 
*      for all supported nonperiodic OUT channels. Typically, a space 
*      corresponding to two Largest Packet Size is recommended.
*
*  (iii) The minimum amount of RAM required for Host periodic Transmit FIFO is 
*        the largest maximum packet size for all supported periodic OUT channels.
*        If there is at least one High Bandwidth Isochronous OUT endpoint, 
*        then the space must be at least two times the maximum packet size for 
*        that channel.
*******************************************************************************/
 
/****************** USB OTG HS CONFIGURATION **********************************/
/* 以下暫不使用 */
#ifdef USB_OTG_HS_CORE
	#define RX_FIFO_HS_SIZE                          512    /* 設定高速核心的接收FIFO大小。*/
	/* 設定裝置端點的傳送FIFO大小(高速),其中0~3是要使用的端點的索引。*/
	#define TX0_FIFO_HS_SIZE                         512
	#define TX1_FIFO_HS_SIZE                         512
	#define TX2_FIFO_HS_SIZE                          0
	#define TX3_FIFO_HS_SIZE                          0
	#define TX4_FIFO_HS_SIZE                          0
	#define TX5_FIFO_HS_SIZE                          0
	#define TXH_NP_HS_FIFOSIZ                         96    /* 設定主機模式(高速)的非週期性傳送FIFO大小。 */
	#define TXH_P_HS_FIFOSIZ                          96    /* 設定主機模式(高速)的週期性傳送FIFO大小。*/

//	#define USB_OTG_HS_LOW_PWR_MGMT_SUPPORT     /* 實現高速核心(USB核心時鐘門控等)的低功耗管理。 */
//	#define USB_OTG_HS_SOF_OUTPUT_ENABLED

//	#define USB_OTG_INTERNAL_VBUS_ENABLED
	#define USB_OTG_EXTERNAL_VBUS_ENABLED

	#ifdef USE_ULPI_PHY
		#define USB_OTG_ULPI_PHY_ENABLED    /* 啟用高速核心的ULPI PHY。 */
	#endif
	#ifdef USE_EMBEDDED_PHY
		#define USB_OTG_EMBEDDED_PHY_ENABLED    /* 為高速核心啟用嵌入式FS PHY。 */
	#endif
	#define USB_OTG_HS_INTERNAL_DMA_ENABLED    /* 啟用高速核心的內部DMA功能。 */
	#define USB_OTG_HS_DEDICATED_EP1_ENABLED    /* 在高速核心中為器件模式啟用專用的端點1功能。 */
#endif

/****************** USB OTG FS CONFIGURATION **********************************/
#ifdef USB_OTG_FS_CORE
	#define RX_FIFO_FS_SIZE                          128    /* 設定全速核心的接收FIFO大小。 */
	/* 設定裝置端點的傳送FIFO大小(全速),其中0~3是要使用的端點的索引。*/
	#define TX0_FIFO_FS_SIZE                          64    
	#define TX1_FIFO_FS_SIZE                         128
	#define TX2_FIFO_FS_SIZE                          0
	#define TX3_FIFO_FS_SIZE                          0
	#define TXH_NP_FS_FIFOSIZ                         96    /* 設定主機模式(全速)的非週期性傳送FIFO大小。 */
	#define TXH_P_FS_FIFOSIZ                          96    /* 設定主機模式(全速)的週期性傳送FIFO大小。*/

//	#define USB_OTG_FS_LOW_PWR_MGMT_SUPPORT    /* 實現全速核心(USB核心時鐘門控等)的低功耗管理。 */
//	#define USB_OTG_FS_SOF_OUTPUT_ENABLED
#endif

/****************** USB OTG MISC CONFIGURATION ********************************/
//#define VBUS_SENSING_ENABLED

/****************** USB OTG MODE CONFIGURATION ********************************/
#define USE_HOST_MODE							/* 採用 Host 模式 與下面的 USE_DEVICE_MODE 和 USE_OTG_MODE 任選其一 */
//#define USE_DEVICE_MODE
//#define USE_OTG_MODE

#ifndef USB_OTG_FS_CORE
	#ifndef USB_OTG_HS_CORE
		#error  "USB_OTG_HS_CORE or USB_OTG_FS_CORE should be defined"
	#endif
#endif

#ifndef USE_DEVICE_MODE
	#ifndef USE_HOST_MODE
		#error  "USE_DEVICE_MODE or USE_HOST_MODE should be defined"
	#endif
#endif

#ifndef USE_USB_OTG_HS
	#ifndef USE_USB_OTG_FS
		#error  "USE_USB_OTG_HS or USE_USB_OTG_FS should be defined"
	#endif
#else //USE_USB_OTG_HS
	#ifndef USE_ULPI_PHY
		#ifndef USE_EMBEDDED_PHY
			 #error  "USE_ULPI_PHY or USE_EMBEDDED_PHY should be defined"
		#endif
	#endif
#endif

/****************** C Compilers dependant keywords ****************************/
/* In HS mode and when the DMA is used, all variables and data structures dealing
   with the DMA during the transaction process should be 4-bytes aligned */    
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
  #if defined   (__GNUC__)        /* GNU Compiler */
    #define __ALIGN_END    __attribute__ ((aligned (4)))
    #define __ALIGN_BEGIN         
  #else                           
    #define __ALIGN_END
    #if defined   (__CC_ARM)      /* ARM Compiler */
      #define __ALIGN_BEGIN    __align(4)  
    #elif defined (__ICCARM__)    /* IAR Compiler */
      #define __ALIGN_BEGIN 
    #elif defined  (__TASKING__)  /* TASKING Compiler */
      #define __ALIGN_BEGIN    __align(4) 
    #endif /* __CC_ARM */  
  #endif /* __GNUC__ */ 
#else
  #define __ALIGN_BEGIN
  #define __ALIGN_END   
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */

/* __packed keyword used to decrease the data type alignment to 1-byte */
#if defined (__CC_ARM)         /* ARM Compiler */
  #define __packed    __packed
#elif defined (__ICCARM__)     /* IAR Compiler */
  #define __packed    __packed
#elif defined   ( __GNUC__ )   /* GNU Compiler */                        
  #define __packed    __attribute__ ((__packed__))
#elif defined   (__TASKING__)  /* TASKING Compiler */
  #define __packed    __unaligned
#endif /* __CC_ARM */

/**
  * @}
  */ 
  /*省略*/
#endif //__USB_CONF__H__
/**
  * @}
  */ 
/**
  * @}
  */ 
/************************ (C) COPYRIGHT  *****END OF FILE****/


usbh_config.h

  usbh_config.h是USB Host 底層驅動的配置檔案。在USB OTG的原始碼中,ST提供了usbh_conf_template.h。使用者只需要複製該檔案到自己的程式碼目錄下,修改即可。具體配置見下文的註釋部分:

/**
 ******************************************************************************
  * @file    usbh_conf.h
  * @author  
  * @version V2.2.0
  * @date    2017.12.27
  * @brief   USB Host library 配置
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT 2017 </center></h2>
  *
 ******************************************************************************
  */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBH_CONF__H__
#define __USBH_CONF__H__
/* Includes ------------------------------------------------------------------*/
// #include "xxx.h"    /* 包含自己的各種標頭檔案*/
/** @addtogroup USBH_OTG_DRIVER
  * @{
  */
/** @defgroup USBH_CONF
  * @brief USB Host 底層驅動配置檔案
  * @{
  */
/** @defgroup USBH_CONF_Exported_Defines
  * @{
  */
#define USBH_MAX_NUM_ENDPOINTS				2			/* 支援端點的最大數量 1 bulk IN + 1 bulk Out */
#define USBH_MAX_NUM_INTERFACES				2			/* 支援介面的最大數量 */

#ifdef USE_USB_OTG_FS
	#define USBH_MSC_MPS_SIZE				0x40
#else
	#define USBH_MSC_MPS_SIZE				0x200
#endif
#define USBH_MAX_DATA_BUFFER				0x400

/* 錯誤資訊列印函式 重定向 這裡需要注意:該庫使用了LCD_ErrLog,需要進行重定向,否則報錯 */
/* 感覺 庫直接將 其改名為 USB_Log 或者 USB_ErrLog 最好了 */
#define LCD_ErrLog(str)    udwComSendData(COM_CONSOLE, str, strlen(str));

/*  與Fatfs對接使用 */
#define _USE_IOCTL							1
/**
  * @}
  */
/** @defgroup USBH_CONF_Exported_Types
  * @{
  */
/**
  * @}
  */
/** @defgroup USBH_CONF_Exported_Macros
  * @{
  */
/**
  * @}
  */
/** @defgroup USBH_CONF_Exported_Variables
  * @{
  */
/**
  * @}
  */
/** @defgroup USBH_CONF_Exported_FunctionsPrototype
  * @{
  */
/**
  * @}
  */

#endif //__USBH_CONF__H__

/**
  * @}
  */
/**
  * @}
  */
/************************ (C) COPYRIGHT  *****END OF FILE****/

usbh_bsp.c

  包含(在USB OTG低階驅動程式的usb_bsp.h檔案中宣告)來初始化GPIO的核心,延時方法和中斷啟用/禁用的函式的實現。在USB OTG的原始碼中,ST提供了usb_bsp_template.c。使用者只需要複製該檔案到自己的程式碼目錄下,修改即可。具體需要實現的函式在usb_bsp.h中已經定義好了,使用者不能更改介面名。見下文的註釋部分:

void USB_OTG_BSP_Init (USB_OTG_CORE_HANDLE *pdev);    /* 該介面中 實現 USB Host 使用的各種 GPIO等*/
void USB_OTG_BSP_uDelay (const uint32_t usec);		/* USB 使用的延時函式 */
void USB_OTG_BSP_mDelay (const uint32_t msec);    /* USB 使用的延時函式 */
void USB_OTG_BSP_EnableInterrupt (USB_OTG_CORE_HANDLE *pdev);    /* USB 使用的中斷 */
void USB_OTG_BSP_TimerIRQ (void);
/* 以下主要是用於 高速模式下的配置,如VBUS的過流檢測等 */
#ifdef USE_HOST_MODE
void USB_OTG_BSP_ConfigVBUS(USB_OTG_CORE_HANDLE *pdev);
void USB_OTG_BSP_DriveVBUS(USB_OTG_CORE_HANDLE *pdev,uint8_t state);
void USB_OTG_BSP_Resume(USB_OTG_CORE_HANDLE *pdev);
void USB_OTG_BSP_Suspend(USB_OTG_CORE_HANDLE *pdev);
#endif /* USE_HOST_MODE */

usbh_usr.c/.h

  包含(在USB庫的usbh_usr.h檔案中宣告)來處理來自使用者層(事件訊息)的庫事件的函式實現。需要實現的函式介面(注意:以下是針對MSC的,其他如HID的使用者介面是不同的)見下文:

void USBH_USR_Init(void);
void USBH_USR_DeInit(void);
void USBH_USR_DeviceAttached(void);
void USBH_USR_ResetDevice(void);
void USBH_USR_DeviceDisconnected (void);
void USBH_USR_OverCurrentDetected (void);
void USBH_USR_DeviceSpeedDetected(uint8_t DeviceSpeed); 
void USBH_USR_Device_DescAvailable(void *);
void USBH_USR_DeviceAddressAssigned(void);
void USBH_USR_Configuration_DescAvailable(USBH_CfgDesc_TypeDef * cfgDesc,
                                          USBH_InterfaceDesc_TypeDef *itfDesc,
                                          USBH_EpDesc_TypeDef *epDesc);
void USBH_USR_Manufacturer_String(void *);
void USBH_USR_Product_String(void *);
void USBH_USR_SerialNum_String(void *);
void USBH_USR_EnumerationDone(void);
USBH_USR_Status USBH_USR_UserInput(void);
void USBH_USR_DeviceNotSupported(void);
void USBH_USR_UnrecoveredError(void);
int USBH_USR_MSC_Application(void);

  對於MSC,使用以下回調:USBH_USR_MSC_Application()。 在類初始化結束之後,這個函式被MSC狀態機呼叫,以便向用戶提供檔案系統訪問操作。使用者最終需要在該函式中實現自己的使用者程式碼。在此回撥中,使用者可以使用FAT FS檔案系統API實現對FAT檔案系統的任何訪問(檔案開啟,檔案讀取,檔案寫入…)。 使用者還可以訪問從庫MSC類驅動程式匯出的結構變數:USBH_MSC_Param。
  其他介面是這個USB Host 狀態機一步一步執行過程的函式。使用者可以在不同的步驟新增對應的處理。最終,使用型別USBH_Usr_cb_TypeDef,將所有函式註冊進USB Host驅動。

/* USB Host 使用者介面 型別定義 */
typedef struct _USBH_USR_PROP
{
  void (*Init)(void);       /* HostLibInitialized */
  void (*DeInit)(void);       /* HostLibInitialized */  
  void (*DeviceAttached)(void);           /* DeviceAttached */
  void (*ResetDevice)(void);
  void (*DeviceDisconnected)(void); 
  void (*OverCurrentDetected)(void);  
  void (*DeviceSpeedDetected)(uint8_t DeviceSpeed);          /* DeviceSpeed */
  void (*DeviceDescAvailable)(void *);    /* DeviceDescriptor is available */
  void (*DeviceAddressAssigned)(void);  /* Address is assigned to USB Device */
  void (*ConfigurationDescAvailable)(USBH_CfgDesc_TypeDef *,
                                     USBH_InterfaceDesc_TypeDef *,
                                     USBH_EpDesc_TypeDef *); 
  /* Configuration Descriptor available */
  void (*ManufacturerString)(void *);     /* ManufacturerString*/
  void (*ProductString)(void *);          /* ProductString*/
  void (*SerialNumString)(void *);        /* SerialNubString*/
  void (*EnumerationDone)(void);           /* Enumeration finished */
  USBH_USR_Status (*UserInput)(void);
  int  (*UserApplication) (void);
  void (*DeviceNotSupported)(void); /* Device is not supported*/
  void (*UnrecoveredError)(void);

}
USBH_Usr_cb_TypeDef;
/* USB Host 使用者介面 使用示例 */
USBH_Usr_cb_TypeDef USR_cb =
{
	USBH_USR_Init,
	USBH_USR_DeInit,
	USBH_USR_DeviceAttached,
	USBH_USR_ResetDevice,
	USBH_USR_DeviceDisconnected,
	USBH_USR_OverCurrentDetected,
	USBH_USR_DeviceSpeedDetected,
	USBH_USR_Device_DescAvailable,
	USBH_USR_DeviceAddressAssigned,
	USBH_USR_Configuration_DescAvailable,
	USBH_USR_Manufacturer_String,
	USBH_USR_Product_String,
	USBH_USR_SerialNum_String,
	USBH_USR_EnumerationDone,
	USBH_USR_UserInput,
	USBH_USR_MSC_Application,
	USBH_USR_DeviceNotSupported,
	USBH_USR_UnrecoveredError
};

注意事項

  • 一旦使用了DMA( 高速模式下),所有結構體必須是四位元組對齊的。
  • 如下即可使用 USB Host
/* 定義 USB_OTG_Core */
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
  #if defined ( __ICCARM__ ) /*!< IAR Compiler */
    #pragma data_alignment=4   
  #endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN USB_OTG_CORE_HANDLE      USB_OTG_Core __ALIGN_END;
/* 定義 USB_Host */
#ifdef USB_OTG_HS_INTERNAL_DMA_ENABLED
  #if defined ( __ICCARM__ ) /*!< IAR Compiler */
    #pragma data_alignment=4   
  #endif
#endif /* USB_OTG_HS_INTERNAL_DMA_ENABLED */
__ALIGN_BEGIN USBH_HOST                USB_Host __ALIGN_END;

/****注意:在非啟用到了DMA的高速模式下, 以上兩個定義可直接簡化(不需要對齊處理)如下:
* USB_OTG_CORE_HANDLE      USB_OTG_Core;
* USBH_HOST                USB_Host;
****/

/* 初始化 USB Host 庫 */
USBH_Init( &USB_OTG_Core, 
#ifdef USE_USB_OTG_FS  
	USB_OTG_FS_CORE_ID,
#else 
	USB_OTG_HS_CORE_ID,
#endif 
	&USB_Host,
	&USBH_MSC_cb, 
	&USR_cb );

/* 最後,週期呼叫以下函式即可 */
USBH_Process(&USB_OTG_Core, &USB_Host);
  • 還需要在中斷處理檔案中,新增以下中斷(如果使用了其他功能的終端,自行新增):
/**
  * @brief  OTG_FS_IRQHandler
  *          This function handles USB-On-The-Go FS global interrupt request.
  *          requests.
  * @param  None
  * @retval None
  */
#ifdef USE_USB_OTG_FS  
void OTG_FS_IRQHandler(void)
#else
void OTG_HS_IRQHandler(void)
#endif
{
	USBH_OTG_ISR_Handler(&USB_OTG_Core);
}

Fatfs部分

原始碼移植

  目前,FatFS的最新版為R0.13a。從R0.13開始,作者將配置巨集統一為可FF_開頭。目前網上多數文章都是針對之前的,許多配置名與最新新版的原始碼是對不上。
FatfsFolder
  使用FatFs最簡單的只需要關係兩個檔案即可:ff.c/hdiskio.c/h。其中,diskio.c/h是一個模板,使用者需要自行實現與底層磁碟的讀寫。在ST提供的USB Host驅動中,已經實現了該檔案,名為usbh_msc_fatfs.c
  更進一步,在使用了其他編碼例如中文及長檔名時,則需要將ffunicode.c包含到自己的專案中。此外,在使用了系統時,還必須將ffsystem.c包含到專案中,並按照自己的系統,修改該檔案。

原始碼配置

  FatFS的配置通過一個名為ffconf.h的檔案實現。對於每個選項,模板中都有很詳細的說明。同時,為減小FatFs佔用的空間,一般只開啟需要的選項。以下僅對幾個特殊的進行註釋性說明。

/*---------------------------------------------------------------------------/
/  FatFs - Configuration file
/---------------------------------------------------------------------------*/
#define FFCONF_DEF 89352	/* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
/---------------------------------------------------------------------------*/
#define FF_FS_READONLY	0
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
/  Read-only configuration removes writing API functions, f_write(), f_sync(),
/  f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
/  and optional writing functions as well. */

#define FF_FS_MINIMIZE	0
/* This option defines minimization level to remove some basic API functions.
/
/   0: Basic functions are fully enabled.
/   1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
/      are removed.
/   2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
/   3: f_lseek() function is removed in addition to 2. */

#define FF_USE_STRFUNC	1
/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
/
/  0: Disable string functions.
/  1: Enable without LF-CRLF conversion.
/  2: Enable with LF-CRLF conversion. */

#define FF_USE_FIND		0
/* This option switches filtered directory read functions, f_findfirst() and
/  f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */

#define FF_USE_MKFS		0
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */

#define FF_USE_FASTSEEK	0
/* This option switches fast seek function. (0:Disable or 1:Enable) */

#define FF_USE_EXPAND	0
/* This option switches f_expand function. (0:Disable or 1:Enable) */

#define FF_USE_CHMOD	0
/* This option switches attribute manipulation functions, f_chmod() and f_utime().
/  (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */

#define FF_USE_LABEL	0
/* This option switches volume label functions, f_getlabel() and f_setlabel().
/  (0:Disable or 1:Enable) */

#define FF_USE_FORWARD	0
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
/* Code Page,是字元編碼的另一種說法。Code Page包含了一個表,表中的值,用於表示針對某種語言所用的字符集。更簡單點說,就是Code Page中,用一個數字編號,表示了所要採用何種字元編碼,去編解碼相應的值,用於正確顯示出相應的字元。*/
#define FF_CODE_PAGE	932
/* This option specifies the OEM code page to be used on the target system.
/  Incorrect code page setting can cause a file open failure.
/
/   437 - U.S.
/   720 - Arabic
/   737 - Greek
/   771 - KBL
/   775 - Baltic
/   850 - Latin 1
/   852 - Latin 2
/   855 - Cyrillic
/   857 - Turkish
/   860 - Portuguese
/   861 - Icelandic
/   862 - Hebrew
/   863 - Canadian French
/   864 - Arabic
/   865 - Nordic
/   866 - Russian
/   869 - Greek 2
/   932 - Japanese (DBCS)
/   936 - Simplified Chinese (DBCS)
/   949 - Korean (DBCS)
/   950 - Traditional Chinese (DBCS)
/     0 - Include all code pages above and configured by f_setcp()
*/
/* 長檔名。這個是微軟的專利!開啟後 必須包含 ffunicode.c */
#define FF_USE_LFN		0
#define FF_MAX_LFN		255
/* The FF_USE_LFN switches the support for LFN (long file name).
/
/   0: Disable LFN. FF_MAX_LFN has no effect.
/   1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
/   2: Enable LFN with dynamic working buffer on the STACK.
/   3: Enable LFN with dynamic working buffer on the HEAP.
/
/  To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
/  requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
/  additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
/  The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
/  be in range of 12 to 255. It is recommended to be set 255 to fully support LFN
/  specification.
/  When use stack for the working buffer, take care on stack overflow. When use heap
/  memory for the working buffer, memory management functions, ff_memalloc() and
/  ff_memfree() in ffsystem.c, need to be added to the project. */
/* 必須開啟 Unicode支援 */
#define FF_LFN_UNICODE	0
/* This option switches the character encoding on the API when LFN is enabled.
/
/   0: ANSI/OEM in current CP (TCHAR = char)
/   1: Unicode in UTF-16 (TCHAR = WCHAR)
/   2: Unicode in UTF-8 (TCHAR = char)
/
/  Also behavior of string I/O functions will be affected by this option.
/  When LFN is not enabled, this option has no effect. */

#define FF_LFN_BUF		255
#define FF_SFN_BUF		12
/* This set of options defines size of file name members in the FILINFO structure
/  which is used to read out directory items. These values should be suffcient for
/  the file names to read. The maximum possible length of the read file name depends
/  on character encoding. When LFN is not enabled, these options have no effect. */

#define FF_STRF_ENCODE	3
/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
/  f_putc(), f_puts and f_printf() convert the character encoding in it.
/  This option selects assumption of character encoding ON THE FILE to be
/  read/written via those functions.
/
/   0: ANSI/OEM in current CP
/   1: Unicode in UTF-16LE
/   2: Unicode in UTF-16BE
/   3: Unicode in UTF-8
*/

#define FF_FS_RPATH		0
/* This option configures support for relative path.
/
/   0: Disable relative path and remove related functions.
/   1: Enable relative path. f_chdir() and f_chdrive() are available.
/   2: f_getcwd() function is available in addition to 1.
*/
/*---------------------------------------------------------------------------/
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
#define FF_VOLUMES		1
/* Number of volumes (logical drives) to be used. (1-10) */

#define FF_STR_VOLUME_ID	0
#define FF_VOLUME_STRS		"RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
/* FF_STR_VOLUME_ID switches string support for volume ID.
/  When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
/  number in the path name. FF_VOLUME_STRS defines the drive ID strings for each
/  logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for
/  the drive ID strings are: A-Z and 0-9. */

#define FF_MULTI_PARTITION	0
/* This option switches support for multiple volumes on the physical drive.
/  By default (0), each logical drive number is bound to the same physical drive
/  number and only an FAT volume found on the physical drive will be mounted.
/  When this function is enabled (1), each logical drive number can be bound to
/  arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
/  funciton will be available. */

#define FF_MIN_SS		512
#define FF_MAX_SS		512
/* This set of options configures the range of sector size to be supported. (512,
/  1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
/  harddisk. But a larger value may be required for on-board flash memory and some
/  type of optical media. When FF_MAX_SS is larger than FF_MIN_SS,