IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> Fatfs文件系统二次f_open返回值为FR_DISK_ERR的问题 -> 正文阅读

[嵌入式]Fatfs文件系统二次f_open返回值为FR_DISK_ERR的问题

背景:项目中使用ST的fatfs驱动,驱动U盘和NOR FLASH
目的:系统往NOR FLASH写日志,插入U盘后导出日志到U盘中
问题现象:每次进去拷贝函数bCopyOneLogFile(),打开pacCurOutFile文件对象时都会报FR_DISK_ERR错误。
分析过程:

  • 经查阅,FR_DISK_ERR是磁盘IO读写错误。故给USBH_read,USBH_write 返回错误处都加断点,进行调试。可是出现FR_DISK_ERR时未进USB读写断点。

  • 很明显不是磁盘IO读写错误,若是磁盘IO读写错误。为什么第一次调用bCopyOneLogFile()时未出现?又为何没进USBH_read,USBH_write 返回错误断点?

  • 遇事不决查手册

    dm00105259-developing-applications-on-stm32cube-with-fatfs-stmicroelectronics-zh.pdf

  • 手册中说FATFS_LinkDriver()是动态增加存储,也就是说不是每次切换读写设备都要链接一次。而是系统增加磁盘时链接,拔出磁盘时断开链接。实现动态磁盘管理的目的。

  • 经过以下修改,完美运行

    1. 系统识别到NOR FLASH和U盘时,FATFS_LinkDriver(),并挂载
    2. 以后每次插入U盘 ,FATFS_LinkDriver(),并挂载。U盘拔出时FATFS_UnLinkDriver(acUSBPath);并且取消挂载

USB磁盘IO读写代码

/**
 * @brief  Reads Sector(s)
 * @param  lun : lun id
 * @param  *buff: Data buffer to store read data
 * @param  sector: Sector address (LBA)
 * @param  count: Number of sectors to read (1..128)
 * @retval DRESULT: Operation result
 */
DRESULT USBH_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
{
  BYTE status = USBH_OK;
  usb_core_driver *udev = (usb_core_driver *)usb_host_msc.data;

  if (!count)
  {
    return RES_PARERR;
  }

  if (Stat & STA_NOINIT)
  {
    return RES_NOTRDY;
  }

  if (udev->host.connect_status)
  {
    do
    {
      status = usbh_msc_read(&usb_host_msc, lun, sector, buff, count);

      if (!udev->host.connect_status)
      {
        return RES_ERROR;
      }
    } while (status == USBH_BUSY);
  }

  if (status == USBH_OK)
  {
    return RES_OK;
  }

  return RES_ERROR;
}
/**
 * @brief  Writes Sector(s)
 * @param  lun : lun id
 * @param  *buff: Data to be written
 * @param  sector: Sector address (LBA)
 * @param  count: Number of sectors to write (1..128)
 * @retval DRESULT: Operation result
 */
#if _USE_WRITE == 1
DRESULT USBH_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
{
  BYTE status = USBH_OK;
  usb_core_driver *udev = (usb_core_driver *)usb_host_msc.data;

  if (!count)
  {
    return RES_PARERR;
  }

  if (Stat & STA_NOINIT)
  {
    return RES_NOTRDY;
  }

  if (Stat & STA_PROTECT)
  {
    return RES_WRPRT;
  }

  if (udev->host.connect_status)
  {
    do
    {
      status = usbh_msc_write(&usb_host_msc, lun, sector, (BYTE *)buff, count);

      if (!udev->host.connect_status)
      {
        return RES_ERROR;
      }
    } while (status == USBH_BUSY);
  }

  if (status == USBH_OK)
  {
    return RES_OK;
  }

  return RES_ERROR;
}
#endif /* _USE_WRITE == 1 */

修改前USB拷贝部分

BOOLEAN LOG_bCopy2USB(void)
{
   UNSIGNED32 dwLogSize = 0;  /**< 日志大小*/
   UINT dwReadedByteNum = 0;  /**< 实际读取字节*/
   UINT dwWrittenByteNum = 0; /**< 实际写入字节*/
   FRESULT eRet = FR_OK;
   UNSIGNED8 i = 0;

   for (i = 0; i < LOG_FILE_NUM; i++)
   {
      /**< 打开2个拷贝文件*/
      if (FATFS_LinkDriver(&SNORDISK_Driver, acFlashPath) == 0)
      {
         eRet = f_open(&sLogFile, (TCHAR const *)&acLogFilePath[i][0], FA_READ);
         if (FR_OK != eRet)
         {
            return FALSE;
         }
         dwLogSize = f_size(&sLogFile);
         dwLogSize = dwLogSize;
      }
      else
      {
         return FALSE;
      }
      if (FATFS_LinkDriver(&USBH_Driver, acUSBPath) == 0)
      {
         eRet = f_open(&sOutFile, (TCHAR const *)&acOutFilePath[i][0], FA_OPEN_ALWAYS | FA_WRITE);
         if (FR_OK != eRet)
         {
            /**< 打开失败取消U盘挂载*/
            eRet = f_mount(NULL, acUSBPath, 0);
            return FALSE;
         }
      }
      else
      {
         /**< 链接失败取消U盘挂载*/
         eRet = f_mount(NULL, acUSBPath, 0);
         return FALSE;
      }
      /**< 进行拷贝*/
      while (FR_OK == eRet)
      {
         if (FATFS_LinkDriver(&SNORDISK_Driver, acFlashPath) == 0)
         {
            eRet = f_read(&sLogFile, acCopyBuff, (UINT)sizeof(acCopyBuff), &dwReadedByteNum);
            if (FR_OK != eRet || dwReadedByteNum == 0)
            {
               break;
            }
         }
         else
         {
            break;
         }

         if (FATFS_LinkDriver(&USBH_Driver, acUSBPath) == 0)
         {
            eRet = f_write(&sOutFile, acCopyBuff, dwReadedByteNum, (void *)&dwWrittenByteNum);
            if (FR_OK != eRet || dwWrittenByteNum < dwReadedByteNum)
            {
               break;
            }
         }
         else
         {
            break;
         }
      }
      /**< 关闭文件*/
      eRet = f_close(&sOutFile);
      eRet = f_close(&sLogFile);
   }
   /**< 拷贝完成取消U盘挂载*/
   eRet = f_mount(NULL, acUSBPath, 0);

   return eRet == FR_OK ? TRUE : FALSE;
}

修改后USB拷贝部分

/**
 * @brief 拷贝一个日志文件
 *
 * @param [in] void
 * @return 是否成功
 * @retval
 * @retval
 *
 * @see
 * @note
 * @warning
 */
static BOOLEAN bCopyOneLogFile(void)
{
   UINT dwReadedByteNum = 0;  /**< 实际读取字节*/
   UINT dwWrittenByteNum = 0; /**< 实际写入字节*/
   FRESULT eRet = FR_OK;      /**< 便于调试,不要优化*/
   BOOLEAN bRet = FALSE;

   /**< 打开2个拷贝文件*/

   eRet = f_open(&sLogFile, (TCHAR const *)pacCurLogFile, FA_OPEN_ALWAYS | FA_READ);
   if (FR_OK != eRet)
   {
      return bRet;
   }

   eRet = f_open(&sOutFile, (TCHAR const *)pacCurOutFile, FA_OPEN_ALWAYS | FA_WRITE);
   if (FR_OK != eRet)
   {
      eRet = f_close(&sLogFile);
      return bRet;
   }

   /**< 进行拷贝*/
   while (FR_OK == eRet)
   {

      eRet = f_read(&sLogFile, acCopyBuff, (UINT)sizeof(acCopyBuff), &dwReadedByteNum);
      if (FR_OK != eRet)
      {
         break;
      }
      else if (FR_OK == eRet && dwReadedByteNum == 0)
      {
         // 说明拷贝完成了
         bRet = TRUE;
         break;
      }

      eRet = f_write(&sOutFile, acCopyBuff, dwReadedByteNum, (void *)&dwWrittenByteNum);
      eRet = f_sync(&sLogFile);
      if (FR_OK != eRet)
      {
         break;
      }
      else if (FR_OK == eRet && dwWrittenByteNum < dwReadedByteNum)
      {
         // 说明文件写不下了
         bRet = TRUE;
         break;
      }
   }
   /**< 关闭文件*/

   eRet = f_close(&sLogFile);
   eRet = f_close(&sOutFile);
   return bRet;
}
/**
 * @brief 导出日志到U盘
 *
 * @param [in] void
 * @return 拷贝日志结果
 * @retval TRUE:成功
 * @retval FALSE:失败
 *
 * @see
 * @note
 * @warning
 */
BOOLEAN LOG_bCopy2USB(void)
{
   BOOLEAN bRet = FALSE;
   FRESULT eRet = FR_OK; /**< 便于调试,不要优化*/

   bRet = bCopyOneLogFile();
   if (bRet)
   {
      vSwitchCurLogFile(); // 切换日志对象
      // vTaskDelay(pdMS_TO_TICKS(10));
      bRet = bCopyOneLogFile();
      vSwitchCurLogFile(); // 还原日志对象
   }
   /**< 无论拷贝是否完成取消U盘挂载*/
   eRet = f_mount(NULL, acUSBPath, 1);
   FATFS_UnLinkDriver(acUSBPath);

   return bRet && (FR_OK == eRet);
}
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 11:35:52  更:2022-05-05 11:39:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 3:48:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码