背景:项目中使用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()是动态增加存储,也就是说不是每次切换读写设备都要链接一次。而是系统增加磁盘时链接,拔出磁盘时断开链接。实现动态磁盘管理的目的。 -
经过以下修改,完美运行
- 系统识别到NOR FLASH和U盘时,FATFS_LinkDriver(),并挂载
- 以后每次插入U盘 ,FATFS_LinkDriver(),并挂载。U盘拔出时FATFS_UnLinkDriver(acUSBPath);并且取消挂载
USB磁盘IO读写代码
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;
}
#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
修改前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++)
{
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)
{
eRet = f_mount(NULL, acUSBPath, 0);
return FALSE;
}
}
else
{
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);
}
eRet = f_mount(NULL, acUSBPath, 0);
return eRet == FR_OK ? TRUE : FALSE;
}
修改后USB拷贝部分
static BOOLEAN bCopyOneLogFile(void)
{
UINT dwReadedByteNum = 0;
UINT dwWrittenByteNum = 0;
FRESULT eRet = FR_OK;
BOOLEAN bRet = FALSE;
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;
}
BOOLEAN LOG_bCopy2USB(void)
{
BOOLEAN bRet = FALSE;
FRESULT eRet = FR_OK;
bRet = bCopyOneLogFile();
if (bRet)
{
vSwitchCurLogFile();
bRet = bCopyOneLogFile();
vSwitchCurLogFile();
}
eRet = f_mount(NULL, acUSBPath, 1);
FATFS_UnLinkDriver(acUSBPath);
return bRet && (FR_OK == eRet);
}
|