本人開發(fā)stm32g030和g070都遇到過擦除flash失敗的問題,HAL庫中按照例程方式擦除存在擦除失敗問題。例程基本流程如下:
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS) ;
HAL_FLASHEx_Erase(&pEraseInit,&PageError);
HAL_FLASH_Lock() ;
按照這種方式其實(shí)很容易擦除失敗。網(wǎng)上多數(shù)是說中斷問題等,還有些是看門狗喂狗問題。
以上問題之外,本人遇到的是FLASH_FLAG_CFGBSY一直被置位,導(dǎo)致擦除函數(shù)里判斷等待超時(shí)以后就略過去了。
嘗試注釋掉這一部分的話,會(huì)在執(zhí)行擦除時(shí)之后觸發(fā)硬件錯(cuò)誤中斷。所以該方法不可取。作者開始尋找在擦除前通過某些操作把FLASH_SR_CFGBSY標(biāo)志位給置0,由于該標(biāo)志位是硬件置位的,軟件沒法置0,因此只能通過其他方式。
作者在嘗試了諸多方法都沒法把FLASH_SR_CFGBSY標(biāo)志置0,想換個(gè)方式解決,就是找到發(fā)生該標(biāo)志被置1的原因,結(jié)果發(fā)現(xiàn)本人的項(xiàng)目是因?yàn)榇?的發(fā)送執(zhí)行之后,F(xiàn)LASH_SR_CFGBSY就被置1了。
調(diào)用串口1發(fā)送前下圖:
調(diào)用串口1發(fā)送后下圖:
本人項(xiàng)目對(duì)打印日志的需求還是很需要的,所以不可能將就不使用打印的,于是又是在網(wǎng)上漫長(zhǎng)地尋找答案。某些論壇上也遇到同病相憐的開發(fā)者發(fā)表了一樣CFGBSY標(biāo)志置1不恢復(fù)的問題,沒人給出合適的答案。
偶然間自己嘗試通過iar的debug強(qiáng)制修改字符結(jié)果神奇的事情發(fā)生。
隨便寫個(gè)‘1’
?
按下回車鍵確定,發(fā)生如下圖的結(jié)果:
?CFGBSY置0了,同時(shí)報(bào)了3個(gè)錯(cuò)誤標(biāo)志來。
作者由此得來靈感,在unlock前,判斷CFGBSY是否置位1,如果在flash代碼區(qū)域中在自己覺得沒用的區(qū)域執(zhí)行寫入操作,就能夠把CFGBSY置0,同時(shí)報(bào)其他flash錯(cuò)誤標(biāo)記,然后通過清除這些標(biāo)記的手段實(shí)現(xiàn)擦除動(dòng)作。具體代碼參考如下:
#define FLASH_FLAG_ALL_ERRORS (FLASH_FLAG_OPERR | FLASH_FLAG_PROGERR | FLASH_FLAG_WRPERR | \
FLASH_FLAG_PGAERR | FLASH_FLAG_SIZERR | FLASH_FLAG_PGSERR | \
FLASH_FLAG_MISERR | FLASH_FLAG_FASTERR | \
FLASH_FLAG_OPTVERR | FLASH_FLAG_ECCC | FLASH_FLAG_ECCD)
uint8_t lc_flash_ram_to_rom(void)
{
FLASH_EraseInitTypeDef pEraseInit ;
uint32_t PageError = 0;
pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES ;
pEraseInit.Page = WORK_STORE_TABLE_PAGE ;
pEraseInit.NbPages = 1 ;
// pEraseInit.Banks = FLASH_BANK_1 ;
again:
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_CFGBSY) != 0x00U)
{
*(uint32_t *)(WORK_STORE_TABLE_ADDR+240) = 12323;//flash隨意寫入一個(gè)值,使flash觸發(fā)錯(cuò)誤
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS) ;
}
if(HAL_FLASH_Unlock() != HAL_OK)
{
goto again ;
}
FLASH_WaitForLastOperation(10) ;//等待一下,提升擦除成功率
HAL_FLASHEx_Erase(&pEraseInit,&PageError);
if(PageError != 0xFFFFFFFF) {
DEBUG_printf("\r\nerase fail\r\n") ;
goto again ;//失敗時(shí)重新執(zhí)行
}
uint32_t flash_unit_n = (sizeof(work_store_table) / FLASH_UNIT_VALUE) + 1 ;
uint64_t * flash_pdata = (uint64_t *)(&work_store_table) ;
for(uint32_t i = 0 ; i < flash_unit_n ; ++i) {
HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD,WORK_STORE_TABLE_ADDR+i*8,*(flash_pdata+i)) ;
}
HAL_FLASH_Lock() ;
return 1 ;
}
? ? ? 關(guān)鍵代碼:
??*(uint32_t *)(WORK_STORE_TABLE_ADDR+240) = 12323
該方法只是隨意在flash塊中在自己想要擦除的地方隨意寫一個(gè)值。文章來源:http://www.zghlxwxcb.cn/news/detail-499654.html
通過多次測(cè)試,成功率100%,認(rèn)為已經(jīng)解決該問題,至于該工程的串口1為什么會(huì)觸發(fā)CFGBSY置位,已經(jīng)不用關(guān)系。雖然找不到根本原因,但是只要能解決問題的話作者已經(jīng)不在深究。文章來源地址http://www.zghlxwxcb.cn/news/detail-499654.html
到了這里,關(guān)于【問題】STM32G0芯片擦除flash失敗,發(fā)現(xiàn)死在FLASH_SR_CFGBSY一直為1(已解決)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!