移植fatfs上电复位前两次不能正确打开文件解决方法
生活随笔
收集整理的這篇文章主要介紹了
移植fatfs上电复位前两次不能正确打开文件解决方法
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
最近移植了fatfs到stm32,昨晚寫(xiě)進(jìn)了第一個(gè)txt文件,然后就睡覺(jué)了,以為移植差不多了,今晚試了一下,發(fā)現(xiàn)不好用了,
res = f_open(&file, "text.txt", FA_OPEN_ALWAYS ?| FA_READ | FA_WRITE); ?但是復(fù)位兩次就可以用了,跟蹤發(fā)現(xiàn)的確是正好兩次;
查網(wǎng)上有人說(shuō)把MISO改為上拉,我試了下沒(méi)有效果,決定自己跟蹤找錯(cuò)誤;
跟蹤發(fā)現(xiàn) ? f_open? res返回1,對(duì)應(yīng)FR_DISK_ERR 底層驅(qū)動(dòng)錯(cuò)誤
繼續(xù)跟蹤發(fā)現(xiàn)是f_open調(diào)用的chk_mounted的這一句fmt = check_fs(fs, bsect);檢查文件系統(tǒng)錯(cuò)誤;
繼續(xù)跟蹤發(fā)現(xiàn)?check_fs里的第一句if (disk_read(fs->drv, fs->win, sect, 1) != RES_OK) return 3;直接錯(cuò)誤返回3;
繼續(xù)跟蹤disk_read發(fā)現(xiàn)是讀扇區(qū)函數(shù)res = MSD_ReadSingleBlock(sector, buff); 返回res=1
繼續(xù)跟蹤MSD_ReadSingleBlock發(fā)現(xiàn)是
.......................................
............................
r1 = _send_command(CMD17, sector, 0);//獨(dú)一塊命令 if(r1 != 0x00)//r1!=0x00,則接收命令錯(cuò)誤 { return 1;//返回寫(xiě)塊錯(cuò)誤 } // Start read and return the result r1 = _read_buffer(buffer, MSD_BLOCKSIZE, RELEASE);//讀MSD_BLOCKSIZE(512)個(gè)字節(jié)數(shù)據(jù)到buffer,讀完后release
.................................
............................................
就是讀數(shù)據(jù)時(shí)候錯(cuò)誤返回1;
而當(dāng)我想跟蹤_read_buffer的時(shí)候發(fā)現(xiàn)只要跟蹤進(jìn)去,就不會(huì)返回錯(cuò)誤1,正確的返回0,很是頭大,然后仔細(xì)想一想,在 r1 = _read_buffer這里設(shè)置斷點(diǎn) 跟蹤就沒(méi)錯(cuò)誤,應(yīng)該是和這里的時(shí)序有關(guān),因?yàn)檎{(diào)試和實(shí)際運(yùn)行直接時(shí)間的差別;
然后看了下 _send_command(CMD17, sector, 0)時(shí)序圖
斷點(diǎn)設(shè)置的是畫(huà)紅圈的那里,說(shuō)明延長(zhǎng)這個(gè)時(shí)間,問(wèn)題就會(huì)解決;
_read_buffer里是通過(guò)以下一段延時(shí)的
.......................................
............................
for(retry=0; retry<2000; retry++) { r1 = _spi_read_write(DUMMY_BYTE); if(r1 == 0xFE)//成功 { ? retry = 0;//成功標(biāo)志 break; } }
// Timeout return超時(shí) if(retry == 2000) { _card_disable();//關(guān)片選 ? return 1;//返回超時(shí)錯(cuò)誤 }
.......................................
............................
程序?yàn)閞etry自加到2000就返回r1超時(shí)錯(cuò)誤,設(shè)置斷點(diǎn)在 return 1;//返回超時(shí)錯(cuò)誤 這一句,也的確會(huì)執(zhí)行到這里;
于是把程序改為for(retry=0; retry<4000; retry++),錯(cuò)誤解決了,后來(lái)跟蹤發(fā)現(xiàn)這里復(fù)位次retry都會(huì)自加到0x855(2133),正好超出2000!
整個(gè)錯(cuò)誤按理說(shuō)應(yīng)該很好查,但是由于是復(fù)位前兩次,而且錯(cuò)誤和時(shí)序有關(guān),設(shè)置斷點(diǎn)的位置會(huì)影響錯(cuò)誤存在與否,所以每一次調(diào)試都要斷電,上電,打開(kāi)調(diào)試,設(shè)置斷點(diǎn),所以跟蹤到這個(gè)錯(cuò)誤非常麻煩,也用了我一晚上的時(shí)間,寫(xiě)下這個(gè),希望其他人有類似的錯(cuò)誤可以參考下。
還有不明白的地方是:
1.為什么只在復(fù)位前兩次出現(xiàn)這個(gè)問(wèn)題?
2.chk_mounted里兩次調(diào)用?check_fs,也就是兩次調(diào)用disk_read,同樣就是兩次調(diào)用_read_buffer,跟蹤發(fā)現(xiàn)總是第二次才出現(xiàn)這個(gè)錯(cuò)誤,第一次和第二次唯一的區(qū)別是第一次讀的是物理0扇區(qū),第二次讀的是物理8192扇區(qū)(我的8G SDHC,邏輯0扇區(qū)在物理扇區(qū)的8192扇區(qū)),是不是因?yàn)樯葏^(qū)地址大,尋址時(shí)間長(zhǎng)了?那同樣讀更大的扇區(qū)會(huì)不會(huì)耗時(shí)更長(zhǎng)?
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
res = f_open(&file, "text.txt", FA_OPEN_ALWAYS ?| FA_READ | FA_WRITE); ?但是復(fù)位兩次就可以用了,跟蹤發(fā)現(xiàn)的確是正好兩次;
查網(wǎng)上有人說(shuō)把MISO改為上拉,我試了下沒(méi)有效果,決定自己跟蹤找錯(cuò)誤;
跟蹤發(fā)現(xiàn) ? f_open? res返回1,對(duì)應(yīng)FR_DISK_ERR 底層驅(qū)動(dòng)錯(cuò)誤
繼續(xù)跟蹤發(fā)現(xiàn)是f_open調(diào)用的chk_mounted的這一句fmt = check_fs(fs, bsect);檢查文件系統(tǒng)錯(cuò)誤;
繼續(xù)跟蹤發(fā)現(xiàn)?check_fs里的第一句if (disk_read(fs->drv, fs->win, sect, 1) != RES_OK) return 3;直接錯(cuò)誤返回3;
繼續(xù)跟蹤disk_read發(fā)現(xiàn)是讀扇區(qū)函數(shù)res = MSD_ReadSingleBlock(sector, buff); 返回res=1
繼續(xù)跟蹤MSD_ReadSingleBlock發(fā)現(xiàn)是
.......................................
............................
r1 = _send_command(CMD17, sector, 0);//獨(dú)一塊命令 if(r1 != 0x00)//r1!=0x00,則接收命令錯(cuò)誤 { return 1;//返回寫(xiě)塊錯(cuò)誤 } // Start read and return the result r1 = _read_buffer(buffer, MSD_BLOCKSIZE, RELEASE);//讀MSD_BLOCKSIZE(512)個(gè)字節(jié)數(shù)據(jù)到buffer,讀完后release
.................................
............................................
就是讀數(shù)據(jù)時(shí)候錯(cuò)誤返回1;
而當(dāng)我想跟蹤_read_buffer的時(shí)候發(fā)現(xiàn)只要跟蹤進(jìn)去,就不會(huì)返回錯(cuò)誤1,正確的返回0,很是頭大,然后仔細(xì)想一想,在 r1 = _read_buffer這里設(shè)置斷點(diǎn) 跟蹤就沒(méi)錯(cuò)誤,應(yīng)該是和這里的時(shí)序有關(guān),因?yàn)檎{(diào)試和實(shí)際運(yùn)行直接時(shí)間的差別;
然后看了下 _send_command(CMD17, sector, 0)時(shí)序圖
斷點(diǎn)設(shè)置的是畫(huà)紅圈的那里,說(shuō)明延長(zhǎng)這個(gè)時(shí)間,問(wèn)題就會(huì)解決;
_read_buffer里是通過(guò)以下一段延時(shí)的
.......................................
............................
for(retry=0; retry<2000; retry++) { r1 = _spi_read_write(DUMMY_BYTE); if(r1 == 0xFE)//成功 { ? retry = 0;//成功標(biāo)志 break; } }
// Timeout return超時(shí) if(retry == 2000) { _card_disable();//關(guān)片選 ? return 1;//返回超時(shí)錯(cuò)誤 }
.......................................
............................
程序?yàn)閞etry自加到2000就返回r1超時(shí)錯(cuò)誤,設(shè)置斷點(diǎn)在 return 1;//返回超時(shí)錯(cuò)誤 這一句,也的確會(huì)執(zhí)行到這里;
于是把程序改為for(retry=0; retry<4000; retry++),錯(cuò)誤解決了,后來(lái)跟蹤發(fā)現(xiàn)這里復(fù)位次retry都會(huì)自加到0x855(2133),正好超出2000!
整個(gè)錯(cuò)誤按理說(shuō)應(yīng)該很好查,但是由于是復(fù)位前兩次,而且錯(cuò)誤和時(shí)序有關(guān),設(shè)置斷點(diǎn)的位置會(huì)影響錯(cuò)誤存在與否,所以每一次調(diào)試都要斷電,上電,打開(kāi)調(diào)試,設(shè)置斷點(diǎn),所以跟蹤到這個(gè)錯(cuò)誤非常麻煩,也用了我一晚上的時(shí)間,寫(xiě)下這個(gè),希望其他人有類似的錯(cuò)誤可以參考下。
還有不明白的地方是:
1.為什么只在復(fù)位前兩次出現(xiàn)這個(gè)問(wèn)題?
2.chk_mounted里兩次調(diào)用?check_fs,也就是兩次調(diào)用disk_read,同樣就是兩次調(diào)用_read_buffer,跟蹤發(fā)現(xiàn)總是第二次才出現(xiàn)這個(gè)錯(cuò)誤,第一次和第二次唯一的區(qū)別是第一次讀的是物理0扇區(qū),第二次讀的是物理8192扇區(qū)(我的8G SDHC,邏輯0扇區(qū)在物理扇區(qū)的8192扇區(qū)),是不是因?yàn)樯葏^(qū)地址大,尋址時(shí)間長(zhǎng)了?那同樣讀更大的扇區(qū)會(huì)不會(huì)耗時(shí)更長(zhǎng)?
《新程序員》:云原生和全面數(shù)字化實(shí)踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀
總結(jié)
以上是生活随笔為你收集整理的移植fatfs上电复位前两次不能正确打开文件解决方法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: stm32Flash模拟eeprom心得
- 下一篇: stm32 sdio acmd41 无响