STM32F4:使用 FatFs 和 USB 的 SD 卡失败

Posted

技术标签:

【中文标题】STM32F4:使用 FatFs 和 USB 的 SD 卡失败【英文标题】:STM32F4: SD-Card using FatFs and USB fails 【发布时间】:2017-03-20 00:08:16 【问题描述】:

(也在SE: Electrical Engineering上提问)

在我的应用程序中,我设置了一个 STM32F4、SD 卡和 USB-CDC(都带有 CubeMX)。 我使用 PC 向 STM32 发送命令,然后它在 SD 卡上执行操作。

使用“communicationBuffer”(由我实现)处理命令,当接收到\n 字符时,它等待通过 USB、UART 等发出的命令并设置一个标志。主循环轮询此标志,如果设置了,解析器将处理该命令。到目前为止,一切顺利。

当我通过 UART 发送命令时,它工作正常,我可以获取 SD 卡上的文件列表或通过 FatFs 执行其他访问,而不会出现问题。

当我通过 USB-CDC 收到命令时,就会出现问题。解析器按预期工作,但 FatFs 在 f_opendir 中声明 FR_NO_FILESYSTEM (13)。 其他 FatFs 命令也因此错误代码而失败。

在一个失败的 USB 命令后,通过 UART 的命令也会失败。似乎 USB 以某种方式使初始化的 SD 卡驱动程序崩溃。

知道如何解决这种行为吗?还是调试的起点?


我的 USB 实现:

我使用的是CubeMX,因此使用规定的方式来初始化USB-CDC接口:

main() 调用MX_USB_DEVICE_Init(void)

usbd_conf.c 我有:

void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle)

  GPIO_InitTypeDef GPIO_InitStruct;
  if(pcdHandle->Instance==USB_OTG_FS)
  
  /* USER CODE BEGIN USB_OTG_FS_MspInit 0 */

  /* USER CODE END USB_OTG_FS_MspInit 0 */

    /**USB_OTG_FS GPIO Configuration    
    PA11     ------> USB_OTG_FS_DM
    PA12     ------> USB_OTG_FS_DP 
    */
    GPIO_InitStruct.Pin = OTG_FS_DM_Pin|OTG_FS_DP_Pin;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF10_OTG_FS;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* Peripheral clock enable */
    __HAL_RCC_USB_OTG_FS_CLK_ENABLE();

    /* Peripheral interrupt init */
    HAL_NVIC_SetPriority(OTG_FS_IRQn, 7, 1);
    HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
  /* USER CODE BEGIN USB_OTG_FS_MspInit 1 */

  /* USER CODE END USB_OTG_FS_MspInit 1 */
  

接收过程在usbd_cdc_if.c中实现如下:

static int8_t CDC_Receive_FS (uint8_t* Buf, uint32_t *Len)

  /* USER CODE BEGIN 6 */

    mRootObject->mUsbBuffer->fillBuffer(Buf, *Len);

    USBD_CDC_ReceivePacket(&hUsbDeviceFS);

    return (USBD_OK);

  /* USER CODE END 6 */ 

fillBuffer 实现如下(我对 UART 和 USB 传输使用相同的实现 - 为各自的接口使用单独的实例。mBufstd::vector<char> 类型的实例变量):

void commBuf::fillBuffer(uint8_t *buf, size_t len)

    // Check if last fill has timed out
    if(SystemTime::getMS() - lastActionTime > timeout) 
        mBuf.clear();
    
    lastActionTime = SystemTime::getMS();

    // Fill new content
    mBuf.insert(mBuf.end(), buf, buf + len);

    uint32_t done = 0;
    while(!done) 
        for(auto i = mBuf.end() - len, ee = mBuf.end(); i != ee; ++i) 
            if(*i == '\n') 
                newCommand = true;
                myCommand = std::string((char*) &mBuf[0],i - mBuf.begin() + 1);

                mBuf.erase(mBuf.begin(), mBuf.begin() + (i - mBuf.begin() + 1));
                break;
            

        
        done = 1;
    

【问题讨论】:

我诚挚邀请反对者就原因提供反馈。 【参考方案1】:

我解决了这个问题:

usb_cdc_if.c 中,#define APP_RX_DATA_SIZE 被设置为4(出于某种未知原因)。由于这小于数据包大小,因此大于 4 字节的传入数据包会覆盖我的内存。

碰巧,我内存的以下部分是指向已初始化 FATFS-Filesystem 结构的 FATFS* FatFs[] 指针列表。

因此,当 5 个或更多字节的命令到达时,此结构的地址随后被覆盖。

唷,那是一个艰难的过程。

【讨论】:

以上是关于STM32F4:使用 FatFs 和 USB 的 SD 卡失败的主要内容,如果未能解决你的问题,请参考以下文章

STM32F4 上的 USB 音频输入

无法使用 STM32F407 上的 Chan FatFs 库通过 SPI 写入 SD 卡文件

STM32F4 HAL库开发 -- USB U盘

STM32F4 HAL库开发 -- USB U盘

STM32F4 HAL库开发 -- USB U盘

STM32F4 HAL库开发 -- USB U盘