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 创建文件的主要内容,如果未能解决你的问题,请参考以下文章