老農(nóng)最近搞基于STM32F407的IAP升級(jí)固件升級(jí)功能,遇到了這樣一個(gè)問(wèn)題:IAP引導(dǎo)程序和APP程序都是基于STM32CUBEMX的程序模板生成,單獨(dú)調(diào)試運(yùn)行APP功能也都正常,但是只要采用IAP方式將APP程序的bin文件燒寫到程序存儲(chǔ)區(qū),再跳轉(zhuǎn)到APP的地址運(yùn)行就死掉了。
這個(gè)問(wèn)題困擾了老農(nóng)挺長(zhǎng)時(shí)間,后來(lái)才發(fā)現(xiàn)問(wèn)題所在:那就是STM32系列的單片機(jī)一旦完成PLL時(shí)鐘設(shè)置后,是不能再次配置的。
本例中IAP引導(dǎo)程序首先對(duì)PLL進(jìn)行了成功配置,當(dāng)跳轉(zhuǎn)到APP程序運(yùn)行后,APP程序初始化部分又對(duì)PLL進(jìn)行了一次配置,結(jié)果配置失敗,因?yàn)槌绦蚴腔赟TM32CUBEMX的模板,配置失敗后調(diào)用模板的Error_Handler()函數(shù),該函數(shù)原型如下:
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
__disable_irq();
while (1)
{
}
/* USER CODE END Error_Handler_Debug */
}
可以看到,函數(shù)內(nèi)部會(huì)先禁止中斷,然后就進(jìn)入死循環(huán)。這就是為什么程序每次跳轉(zhuǎn)到APP后死掉的原因。
搞清楚了問(wèn)題所在,就有針對(duì)性的解決方法:一是偷懶的方法,將Error_Handler()函數(shù)的內(nèi)部功能全部屏蔽,這樣即使PLL配置出錯(cuò),也能跳過(guò)去,但是必須要保證IAP引導(dǎo)程序和APP程序的時(shí)鐘配置完全一致,否則還是會(huì)出問(wèn)題。二是想辦法重新配置PLL,這樣即使IAP引導(dǎo)程序和APP程序的時(shí)鐘配置不一致,程序也能順利運(yùn)行。
要想重新配置STM32的PLL,通過(guò)查閱相關(guān)資料,發(fā)現(xiàn)STM32的PLL一旦使能后配置參數(shù)便不能更改,除非在下次重新啟動(dòng)時(shí)再次配置相關(guān)參數(shù)。這樣就成死循環(huán)了,似乎只能采用前面說(shuō)的第一種方法了。
老農(nóng)不死心,繼續(xù)研究參考手冊(cè),發(fā)現(xiàn)有這么一段話:
The three PLLs are disabled by hardware when entering Stop and Standby modes, or when
an HSE failure occurs when HSE or PLL (clocked by HSE) are used as system clock.
重點(diǎn)在第一句,在進(jìn)入停止或待機(jī)模式時(shí)PLL可以由硬件禁止。這樣的話我們就可以在APP程序的時(shí)鐘初始化之前首先設(shè)置STM32進(jìn)入停止或待機(jī)模式,然后再喚醒,并重新對(duì)PLL時(shí)鐘進(jìn)行配置。
通過(guò)研究STM32的停止模式和待機(jī)模式,可以知道其進(jìn)入和退出方式有一定差異,如下所示:
另外如果進(jìn)入待機(jī)模式,退出后除備份區(qū)域和待機(jī)電路中的寄存器外,其他SRAM和寄存器內(nèi)容全部丟失,程序?qū)凑諒?fù)位后的方式重新執(zhí)行,這個(gè)并不是我們的初衷。如果每次喚醒都相當(dāng)于重啟,那我們的程序就進(jìn)入死循環(huán)了。
老農(nóng)結(jié)合自己的實(shí)際硬件,正好在某個(gè)管腳上有一個(gè)外部I2C設(shè)備輸入方波可以用來(lái)做為喚醒源,選用停止模式。具體代碼如下:
HAL_Init();
IIC_Init(); //外部設(shè)備初始化
SetCLKOandSQW(0,F1Hz,S_1Hz); //使能外部器件方波輸出
HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); //使能方波輸入管腳中斷
HAL_PWR_EnterSTOPMode(PWR_MAINREGULATOR_ON, PWR_STOPENTRY_WFI); //進(jìn)入停止模式
Stm32_Clock_Init(168,6,2,7); //重新配置PLL并使能
HAL_NVIC_DisableIRQ(EXTI9_5_IRQn); //關(guān)閉方波輸入管腳中斷
為了驗(yàn)證效果,將Error_Handler函數(shù)中的死循環(huán)重新打開,再次燒寫新的APP程序,這次APP能夠正常運(yùn)行,這說(shuō)明通過(guò)采用進(jìn)入停止模式再重新配置PLL時(shí)鐘是可行的。
采用這種方法確實(shí)可以解決PLL的重配置,但是需要結(jié)合自己的硬件考慮是否具備喚醒停止模式或待機(jī)模式的能力。
-
鎖相環(huán)
+關(guān)注
關(guān)注
35文章
584瀏覽量
87735 -
寄存器
+關(guān)注
關(guān)注
31文章
5336瀏覽量
120230 -
STM32F407
+關(guān)注
關(guān)注
15文章
187瀏覽量
29437 -
PLL電路
+關(guān)注
關(guān)注
0文章
92瀏覽量
6403 -
stm32cubemx
+關(guān)注
關(guān)注
5文章
283瀏覽量
14791
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論