1戚炫、問題描述
使用FAT32?f_write 多次執(zhí)行寫操作時(shí)剑刑,會(huì)報(bào)FR_DISK_ERR錯(cuò)誤,而且是剛開始寫不報(bào)錯(cuò)双肤,寫幾次后會(huì)一直報(bào)錯(cuò)施掏。
設(shè)斷點(diǎn)跟蹤到HAL_SD_WriteBlocks中,在調(diào)用SDMMC_CmdWriteMultiBlock時(shí)茅糜,會(huì)報(bào)SDMMC_ERROR_TX_UNDERRUN,意思 是Transmit FIFO underrun
2七芭、原因分析
如下圖所示,SDMMC開始寫操作時(shí)蔑赘,首先要將數(shù)據(jù)寫入FIFO,然后再將FIFO中的數(shù)據(jù)取出狸驳,通過Data path寫入到SD卡预明。因?yàn)闀r(shí)鐘頻率比較快(最高可達(dá)20MHz),因此往FIFO里裝填數(shù)據(jù)必須非嘲夜浚快撰糠,否則后面從FIFO取數(shù)時(shí)就會(huì)取不到數(shù),報(bào)出Transmit FIFO underrun錯(cuò)誤辩昆。
可能原因1:
????可能是通過APB2總線往FIFO裝填數(shù)時(shí)阅酪,發(fā)生了中斷,導(dǎo)致總線被占用或其他資源被占用汁针,從而無法及時(shí)完成FIFO的裝填术辐,而后面從FIFO取數(shù)的頻率又非常快施无,導(dǎo)致無法取到數(shù)辉词。
可能原因2:
????SD卡寫的時(shí)候出現(xiàn)了壞塊,導(dǎo)致寫不成功猾骡,在寫失敗時(shí)需要重試一下瑞躺。
可能原因3:
? ? 寫速度太快,導(dǎo)致FIFO來不及裝填卓练,產(chǎn)生錯(cuò)誤隘蝎,需要降速。
3襟企、解決辦法之禁用中斷
在調(diào)用f_write之前調(diào)用? __disable_irq()? 接口關(guān)閉中斷,寫操作完成后調(diào)用? __enable_irq()接口啟用中斷:
__disable_irq()狮含;
if(FR_OK? ==f_write())
{ }
else
{}
__disable_irq() ;
優(yōu)點(diǎn):簡單
缺點(diǎn):在寫操作期間CPU無法響應(yīng)中斷
4顽悼、解決辦法之寫重試
重寫bsp_driver_sd.c文件中的BSP_SD_WriteBlocks函數(shù)是_weak 函數(shù),可以在自己的源文件myfile.c中重寫該函數(shù)几迄,當(dāng)寫發(fā)生錯(cuò)誤后蔚龙,清除錯(cuò)誤標(biāo)記,再重試幾次即可映胁,在我的單片機(jī)上木羹,一般第一次重試即可成功
uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint32_t WriteAddr, uint32_t NumOfBlocks, uint32_t Timeout)
{
int i;
for (i = 1; i <= TY_SDIO_RETRY_MAX; i ++)
{
if (HAL_SD_WriteBlocks(&hsd, (uint8_t *)pData, WriteAddr, NumOfBlocks, Timeout) == HAL_OK)
{
if (i > 1)
printf("[INFO] SDIO writing succeeded: retry %d.\n", i);
return (MSD_OK); // Succeeded
}
else
{
printf("[ERROR] SDIO writing failure: retry %d, error code %#x, addr %#x, %u blocks.\n",
i, hsd.ErrorCode, WriteAddr, NumOfBlocks);
HAL_SD_Abort(&hsd); //clear error flag
}
}
return (MSD_ERROR);
}
優(yōu)點(diǎn):上層應(yīng)用軟件不需要更改,也不需要禁用中斷
缺點(diǎn):頻率較高時(shí)(我的是30MHZ)時(shí)解孙,經(jīng)常會(huì)發(fā)生寫重試
5坑填、解決辦法之降低寫頻率(降速)
更改sdio.c中的MX_SDIO_SD_Init函數(shù),將hsd.Init.ClockDiv = 0改為hsd.Init.ClockDiv = 2弛姜,寫頻率會(huì)變成原來的1/2脐瑰,在我的單片機(jī)上降頻1/2之后,寫錯(cuò)誤將不再發(fā)生廷臼。
優(yōu)點(diǎn):非常簡單苍在;無需禁用中斷绝页;無需對(duì)上層軟件進(jìn)行修改。
缺點(diǎn):降低了寫速度
6寂恬、參考資料
1续誉、https://blog.frankvh.com/2011/12/30/stm32f2xx-stm32f4xx-sdio-interface-part-2/
2、STM32F405/415 Reference manual