STM32 IAP在線升級(jí)詳解
一,在進(jìn)入主題之前我們先了解一些必要的基礎(chǔ)知識(shí)----stm32系列芯片的種類和型號(hào):
startup_stm32f10x_cl.s互聯(lián)型的器件,STM32F105xx,STM32F107xx
startup_stm32f10x_hd.s大容量的STM32F101xx,STM32F102xx,STM32F103xx
startup_stm32f10x_hd_vl.s大容量的STM32F100xx
startup_stm32f10x_ld.s小容量的STM32F101xx,STM32F102xx,STM32F103xx
startup_stm32f10x_ld_vl.s小容量的STM32F100xx
startup_stm32f10x_md.s中容量的STM32F101xx,STM32F102xx,STM32F103xx
startup_stm32f10x_md_vl.s中容量的STM32F100xx(我項(xiàng)目中用的是此款芯片stm32f100CB)
startup_stm32f10x_xl.s FLASH在512K到1024K字節(jié)的STM32F101xx,STM32F102xx,STM32F103xx(例如:像stm32f103re這個(gè)型號(hào)的芯片flash是512k的,啟動(dòng)文件用startup_stm32f10x_xl.s或者startup_stm32f10x_hd.s都可以;)
cl:互聯(lián)型產(chǎn)品,stm32f105 / 107系列
vl:超值型產(chǎn)品,stm32f100系列
xl:超高密度產(chǎn)品,stm32f101 / 103系列
ld:低密度產(chǎn)品,F(xiàn)LASH小于64K
md:中等密度產(chǎn)品,F(xiàn)LASH = 64或128
HD:高密度產(chǎn)品,F(xiàn)LASH大于128
二,在拿到ST公司官方的IAP程序后我們要思考幾點(diǎn):
1.ST官方IAP是什么針對(duì)什么芯片型號(hào)的,我們要用的又是什么芯片型號(hào);
2.我們要用官方IAP適合我們芯片的程序升級(jí)使用,要在原有的基礎(chǔ)上做那些改變;
(我的資源里有官方IAP源碼:http://download.csdn.NET/ detail / yx_l128125 / 6445811)
初略看了一下IAP源碼后,現(xiàn)在我們可以回答一下上面的2個(gè)問(wèn)題了:
1.官網(wǎng)剛下載的IAP針對(duì)的是stm32f103c8芯片的,所以他的啟動(dòng)代碼文件選擇的是startup_stm32f10x_md.s,而我的芯片是stm32f100cb,所以我的啟動(dòng)代碼文件選擇的是 startup_stm32f10x_md_lv.s
2。第二個(gè)問(wèn)題就是今天我們要做詳細(xì)分析才能回答的問(wèn)題了
(1)知道了IAP官方源碼的芯片和我們要用芯片的差異,首先我們要在源碼的基礎(chǔ)上做芯片級(jí)的改動(dòng)。
A.首先改變編譯器KEIL的芯片型號(hào)上我們要改成我們的芯片類型--- STM32F100CB;
B.在keil的選項(xiàng)中,選擇C / C ++ / PREPROMCESSOR符號(hào)的定義欄里定義,把有關(guān)STM32F10X_MD的宏定義改成:STM32F10X_MD_VL
也可以在STM32F10X.H里用宏定義
/ *根據(jù)您使用的目標(biāo)STM32設(shè)備取消下面的行注釋
應(yīng)用
* /
(STM32F10X_LD)&&!定義(STM32F10X_LD)&&!定義(STM32F10X_MD)&&!定義(STM32F10X_MD)&&!定義(STM32F10X_HD)&&!定義(STM32F10X_HDL)&&!
/ * #define STM32F10X_LD * / / *! / * #define STM32F10X_LD_VL * / / *! / * #define STM32F10X_MD * / / *! #define STM32F10X_MD_VL / *! / * #define STM32F10X_HD * / / *! / * #define STM32F10X_HD_VL * / / *! / * #define STM32F10X_XL * / / *! / * #define STM32F10X_CL * / / *! #萬(wàn)一 上面代碼說(shuō)的是如果沒(méi)有定義STM32F10X_MD_VL,則宏定義STM32F10X_MD_VL C.外部時(shí)鐘問(wèn)價(jià)在stm32f10x.h依據(jù)實(shí)際修改,原文是說(shuō)如果沒(méi)有宏定義外部時(shí)鐘HES_VALUE的值,但是宏定義了stm32f10x_cl則外部時(shí)鐘設(shè)置為25MHZ,否則外部時(shí)鐘都設(shè)置為8MHZ;我用的外部晶振是8MHZ的所以不必修改這部分代碼; #if!定義HSE_VALUE #ifdef STM32F10X_CL #define HSE_VALUE((uint32_t)25000000)//外部振蕩器的值為Hz D.做系統(tǒng)主頻時(shí)鐘的更改 system_stm32f10x.c的系統(tǒng)主頻率,依實(shí)際情況修改;我用的芯片主頻時(shí)鐘是24MHZ; #if defined(STM32F10X_LD_VL)||(定義為STM32F10X_MD_VL)||(定義為STM32F10X_HD_VL) / * #define SYSCLK_FREQ_HSE HSE_VALUE * / #define SYSCLK_FREQ_24MHz 24000000 #其他 / * #define SYSCLK_FREQ_HSE HSE_VALUE * / #define SYSCLK_FREQ_24MHz 24000000 / * #define SYSCLK_FREQ_36MHz 36000000 * / / * #define SYSCLK_FREQ_48MHz 48000000 * / / * #define SYSCLK_FREQ_56MHz 56000000 * / / *#define SYSCLK_FREQ_72MHz 72000000 * / #萬(wàn)一 E.下面是關(guān)鍵部分操作了,在說(shuō)這部分操作前我們先來(lái)說(shuō)一下內(nèi)存映射: 下圖在stm32f100芯片手冊(cè)的29頁(yè),我們只截取關(guān)鍵部分 從上圖我們看出幾個(gè)關(guān)鍵部分: 1.內(nèi)部flash是從0x0800 0000開(kāi)始到0x0801 FFFF結(jié)束,0x0801FFFF-0x0800 0000 = 0x20000 = 128k 128也就是flash的大小; 2.SRAM的開(kāi)始地址是0x2000 0000; 我們要把我們的在線升級(jí)程序IAP放到FLASH里以0x0800 0000開(kāi)始的位置,應(yīng)用程序放APP APP到達(dá)0x08003000開(kāi)始的位置,中斷向量表也放在0x0800 3000開(kāi)始的位置;如圖 所以我們需要先查看一下misc.h文件中的中斷向量表的初始位置宏定義為NVIC_VectTab_Flash 0x0800 0000 那么要就要設(shè)置編譯器keil中的目標(biāo)的選項(xiàng)選項(xiàng)中的IROM1地址為0x0800 0000大小為0x20000即128K; IRAM1地址為0x2000 0000大小為0x2000; (提示:這一項(xiàng)IROM1地址即為當(dāng)前程序下載到flash的地址的起始位置) 下面我們來(lái)分析一下修改后的IAP代碼: / ******************* ****************************** * @函數(shù)名稱主 * @函數(shù)說(shuō)明主函數(shù) * @輸入?yún)?shù)無(wú) * @輸出參數(shù)無(wú) * @返回參數(shù)無(wú) ************************************************** ************ / int main(void) { // Flash解鎖 FLASH_Unlock(); //配置PA15管腳 KEY_Configuration(); //配置串口1 IAP_Init(); // PA15是否為低電平 if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)== 0x00) { //執(zhí)行IAP驅(qū)動(dòng)程序更新的Flash程序 SerialPutString(“ r n =========================================== ===========================“); SerialPutString(“ r n =(C)COPYRIGHT 2011 Lierda =”); SerialPutString(“ r n = =”); SerialPutString(“ r n =應(yīng)用程序編程應(yīng)用程序(版本1.0.0)=”); SerialPutString(“ r n = =”); SerialPutString(“ r n =由wuguoyan =”); SerialPutString(“ r n =========================================== ===========================“); SerialPutString( “ r n r n”); 主菜單 (); } //否則執(zhí)行用戶程序 其他 { //判斷用處是否已經(jīng)下載了用戶程序,因?yàn)檎G闆r下此地址是棧地址 //若沒(méi)有這一句話,即使沒(méi)有下載程序也會(huì)進(jìn)入而導(dǎo)致跑飛。 if(((*(__ IO uint32_t *)ApplicationAddress)&0x2FFE0000)== 0x20000000) { SerialPutString(“執(zhí)行用戶程序 r n n”); //跳轉(zhuǎn)至用戶代碼 JumpAddress = *(__ IO uint32_t *)(ApplicationAddress + 4); Jump_To_Application #else pre> #define HSE_VALUE((uint32_t)8000000)//值外部振蕩器以Hz #endif / * STM32F10X_CL * /#endif / * HSE_VALUE * /