STM32 USB OTG HOST 库挂起尝试使用 FatFs 创建文件

Posted

技术标签:

【中文标题】STM32 USB OTG HOST 库挂起尝试使用 FatFs 创建文件【英文标题】:STM32 USB OTG HOST Library hangs trying to create file with FatFs 【发布时间】:2016-04-21 15:05:56 【问题描述】:

我正在尝试在 USB 闪存上使用 FatFs 创建一个文件,但我的 f_open 调用尝试读取引导扇区以进行第一次文件系统挂载时挂起。

DRESULT disk_read (
                   BYTE drv,            /* Physical drive number (0) */
                   BYTE *buff,          /* Pointer to the data buffer to store read data */
                   DWORD sector,        /* Start sector number (LBA) */
                   BYTE count           /* Sector count (1..255) */
                     )

  BYTE status = USBH_MSC_OK;
  
  if (drv || !count) return RES_PARERR;
  if (Stat & STA_NOINIT) return RES_NOTRDY;
  
  
  if(HCD_IsDeviceConnected(&USB_OTG_Core))
    
    
    do
    
      status = USBH_MSC_Read10(&USB_OTG_Core, buff,sector,512 * count);
      USBH_MSC_HandleBOTXfer(&USB_OTG_Core ,&USB_Host);
      
      if(!HCD_IsDeviceConnected(&USB_OTG_Core))
       
        return RES_ERROR;
            
    
    while(status == USBH_MSC_BUSY ); // Loop which create hanging state
  
  
  if(status == USBH_MSC_OK)
    return RES_OK;
  return RES_ERROR;
  

主要问题是产生挂起状态的循环

while(status == USBH_MSC_BUSY );

所以我不知道该怎么做才能避免这种情况。使用调试器我发现状态是由结构USBH_MSC_BOTXferParam 的参数CmdStateMachine 引起的,类型USBH_BOTXfer_TypeDef 等于CMD_UNINITIALIZED_STATE 这实际上导致错过USBH_MSC_Read10 函数的switch 语句。

/**
  * @brief  USBH_MSC_Read10 
  *         Issue the read command to the device. Once the response received, 
  *         it updates the status to upper layer
  * @param  dataBuffer : DataBuffer will contain the data to be read
  * @param  address : Address from which the data will be read
  * @param  nbOfbytes : NbOfbytes to be read
  * @retval Status
  */
uint8_t USBH_MSC_Read10(USB_OTG_CORE_HANDLE *pdev,
                        uint8_t *dataBuffer,
                        uint32_t address,
                        uint32_t nbOfbytes)

  uint8_t index;
  static USBH_MSC_Status_TypeDef status = USBH_MSC_BUSY;
  uint16_t nbOfPages;
  status = USBH_MSC_BUSY;
  
  if(HCD_IsDeviceConnected(pdev))
  
    switch(USBH_MSC_BOTXferParam.CmdStateMachine)
    
    case CMD_SEND_STATE:
      /*Prepare the CBW and relevant field*/
      USBH_MSC_CBWData.field.CBWTransferLength = nbOfbytes;
      USBH_MSC_CBWData.field.CBWFlags = USB_EP_DIR_IN;
      USBH_MSC_CBWData.field.CBWLength = CBW_LENGTH;
      
      USBH_MSC_BOTXferParam.pRxTxBuff = dataBuffer;
      
      for(index = CBW_CB_LENGTH; index != 0; index--)
      
        USBH_MSC_CBWData.field.CBWCB[index] = 0x00;
      
      
      USBH_MSC_CBWData.field.CBWCB[0]  = OPCODE_READ10; 
      
      /*logical block address*/
      
      USBH_MSC_CBWData.field.CBWCB[2]  = (((uint8_t*)&address)[3]);
      USBH_MSC_CBWData.field.CBWCB[3]  = (((uint8_t*)&address)[2]);
      USBH_MSC_CBWData.field.CBWCB[4]  = (((uint8_t*)&address)[1]);
      USBH_MSC_CBWData.field.CBWCB[5]  = (((uint8_t*)&address)[0]);
      
      /*USBH_MSC_PAGE_LENGTH = 512*/
      nbOfPages = nbOfbytes/ USBH_MSC_PAGE_LENGTH;  
      
      /*Tranfer length */
      USBH_MSC_CBWData.field.CBWCB[7]  = (((uint8_t *)&nbOfPages)[1]) ; 
      USBH_MSC_CBWData.field.CBWCB[8]  = (((uint8_t *)&nbOfPages)[0]) ; 
      
      
      USBH_MSC_BOTXferParam.BOTState = USBH_MSC_SEND_CBW;
      /* Start the transfer, then let the state machine 
      manage the other transactions */
      USBH_MSC_BOTXferParam.MSCState = USBH_MSC_BOT_USB_TRANSFERS;
      USBH_MSC_BOTXferParam.BOTXferStatus = USBH_MSC_BUSY;
      USBH_MSC_BOTXferParam.CmdStateMachine = CMD_WAIT_STATUS;
      
      status = USBH_MSC_BUSY;
      
      break;
      
    case CMD_WAIT_STATUS:
      
      if((USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_OK) && \
        (HCD_IsDeviceConnected(pdev)))
       
        /* Commands successfully sent and Response Received  */       
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_OK;      
      
      else if (( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_FAIL ) && \
        (HCD_IsDeviceConnected(pdev)))
      
        /* Failure Mode */
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
      
      
      else if ( USBH_MSC_BOTXferParam.BOTXferStatus == USBH_MSC_PHASE_ERROR )
      
        /* Failure Mode */
        USBH_MSC_BOTXferParam.CmdStateMachine = CMD_SEND_STATE;
        status = USBH_MSC_PHASE_ERROR;    
      
      else
      
        /* Wait for the Commands to get Completed */
        /* NO Change in state Machine */
      
      break;
      
    default:
      break;
    
  
  return status;

这里是USBH_BOTXfer_TypeDef类型声明;

typedef struct _BOTXfer

uint8_t MSCState;
uint8_t MSCStateBkp;
uint8_t MSCStateCurrent;
uint8_t CmdStateMachine;
uint8_t BOTState;
uint8_t BOTStateBkp;
uint8_t* pRxTxBuff;
uint16_t DataLength;
uint8_t BOTXferErrorCount;
uint8_t BOTXferStatus;
 USBH_BOTXfer_TypeDef;

在调试过程中,我发现它的所有字段都是 0x00。

这是我的 FatFs 调用

int main(void)

    FATFS Fat;
    FIL file;
    FRESULT fr;
    
    RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
    
    /* Enable SWO output */
    DBGMCU->CR = 0x00000020;
    
    GPIOD->MODER=0x55000000;
    GPIOD->OTYPER = 0x00000000;
    GPIOD->OSPEEDR = 0x00000001;
    
    while(1)
       
        if (!USB_MSC_IsInitialized())
        
            USB_MSC_Initialize();
        
        
        if (USB_MSC_IsConnected())
        
            GPIOD->ODR = (1 << 15);
            
            disk_initialize(0);
            
            fr = f_mount(0, &Fat);
            
            if(fr == FR_OK)
                       
                fr = f_open(&file,"0:DP_lab8.pdf",(FA_CREATE_ALWAYS | FA_WRITE));
                
                if (fr == FR_OK)
                
                    f_close(&file);
                
                
                f_mount(0, NULL);
            
        
        else
        
            GPIOD->ODR = (1 << 14);
        
        
        USB_MSC_Main();
    

USB_MSC_IsConnected 函数是:

int USB_MSC_IsConnected(void)

    if (g_USB_MSC_HostStatus == USB_DEV_NOT_SUPPORTED)
    
        USB_MSC_Uninitialize();
    
    
    return !(g_USB_MSC_HostStatus == USB_DEV_DETACHED ||
        g_USB_MSC_HostStatus == USB_HOST_NO_INIT ||
      g_USB_MSC_HostStatus == USB_DEV_NOT_SUPPORTED);

设备状态为:

typedef enum

    USB_HOST_NO_INIT = 0,  /* USB interface not initialized */
    USB_DEV_DETACHED,      /* no device connected */
    USB_SPEED_ERROR,       /* unsupported USB speed */
    USB_DEV_NOT_SUPPORTED, /* unsupported device */
    USB_DEV_WRITE_PROTECT, /* device is write protected */
    USB_OVER_CURRENT,      /* overcurrent detected */
    USB_DEV_CONNECTED      /* device connected and ready */
 USB_HostStatus;

g_USB_MSC_HostStatus 的值由标准 USB HOST 用户回调接收。

【问题讨论】:

提供minimal reproducible example。但这可能是tl;博士。 ST 库是出了名的过时软件。如果它真的挂在那里,请检查标志设置的位置以及未清除标志的原因。可能是一个中断处理程序。使用断点和调试器。 我看不到你在哪里调用 disk_read()。您能否提供正在执行的代码示例? @Ivan Angelov:它的 HAL 级函数 fatfs 在 disio.h 文件中为其提供了接口,而不是在我们的案例中使用设备驱动程序手动实现的文件(usbh_msc_fatfs.c)中的 STM32F4 USB OTG HOST 驱动程序. FatFs 调用此函数来执行从物理设备中读取的操作,在我的情况下为 FLASH DRIVE。 你运行的是什么版本的STM固件?我有 TM32Cube_FW_F4_V1.3.0 但我没有看到 USBH_MSC_Read10(...) 函数,我只有 USBH_MSC_Read(...) 您的版本似乎较旧。您可以尝试更新 ST 固件立方体; * 文件 usbh_msc_scsi.h * 作者 MCD 应用程序团队 * 版本 V3.1.0 * 日期 2014 年 6 月 19 日 【参考方案1】:

我认为这是 ST 主机库中的错误。我已经找到了它,因为我的 USB 主机无法通过枚举阶段。修复后堆栈正常。

在“STM32Cube/Repository/STM32Cube_FW_F7_V1.13.0/Middlewares/ST/STM32_USB_Host_Library/Core/Inc”的usbh_def.h文件中有union _USB_Setup(任何芯片,不仅F7,任何版本,不仅是 V1.13.0)。它有 uint16_t bmRequestType 和 uint16_t bRequest。根据 USB 规范,这两个文件必须是 uint8_t。修复此问题使 USB 主机按需要运行。枚举阶段顺利通过,其他所有阶段也顺利通过。

【讨论】:

所有这些字段默认类型为uint8_t,但它不起作用。 好的,您的闪存驱动器是否被 USB 主机枚举?然后,设备类是否启动? 感谢您的关注,但目前我还无法使用微控制器,所以我会给您一些奖励。

以上是关于STM32 USB OTG HOST 库挂起尝试使用 FatFs 创建文件的主要内容,如果未能解决你的问题,请参考以下文章

STM32MP157A驱动开发 | 03-usb host接口的使用(U盘 )

stm32能否判断正确识别usb

stm32f407以太网及USB OTG快速开发

Stm32命名含义

STM32f107 usb重枚举

[usb]usb otg和host