IAP下載流程
一。APP程序的生成步驟
APP程序生成一個bin文件,BootLoader程序通過某一種方式進行接收,然后把bin文件放置在Flash應用程序的存儲區(qū)域中。
Flash并不是全部放APP程序,而是Flash空間一部分放置BootLoader程序,另一部分放置APP,所以對APP要設置起始地址和空間大小。在MDK中配置。
新的APP中有一個新的中斷向量表,只不過比原來的中斷向量表有一個偏移。
二。BootLoader程序講解
BootLoader程序的作用:
1. 通過某種方式接受APP的bin文件。本實驗通過串口接收,串口中斷程序接收到數(shù)據(jù)后存儲到一個緩存中
2. 把數(shù)據(jù)寫到Flash的某個區(qū)域。
void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 applen);//在指定地址appxaddr開始,寫入bin
3. 實現(xiàn)跳轉。
void iap_load_app(u32 appxaddr);//執(zhí)行flash里面以appxaddr為起始地址的的app程序
(1)串口接收數(shù)據(jù)程序(串口中斷)
//串口1中斷服務程序
//注意,讀取USARTx->SR能避免莫名其妙的錯誤
u8 USART_RX_BUF[USART_REC_LEN] __attribute__ ((at(0X20001000)));//接收緩沖,最大USART_REC_LEN個字節(jié),起始地址為SRAM中的0X20001000.注意:不能隨意寫,要給BootLoader程序和APP留有足夠的空間。
//接收狀態(tài)
//bit15,接收完成標志
//bit14,接收到0x0d
//bit13~0,接收到的有效字節(jié)數(shù)目
u16 USART_RX_STA=0;//接收狀態(tài)標記
u16 USART_RX_CNT=0;//接收的字節(jié)數(shù)
void USART1_IRQHandler(void)
{
u8 res;
#ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定義了,說明使用ucosII了.
OSIntEnter();
#endif
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//接收到數(shù)據(jù)
{
res=USART_ReceiveData(USART1);
if(USART_RX_CNT
{
USART_RX_BUF[USART_RX_CNT]=res;
USART_RX_CNT++;
}
}
#ifdef OS_CRITICAL_METHOD //如果OS_CRITICAL_METHOD定義了,說明使用ucosII了.
OSIntExit();
#endif
}
數(shù)據(jù)接收在USART_RX_BUF中,長度為:
#define USART_REC_LEN55*1024 //定義最大接收字節(jié)數(shù) 55K
因此要求APP程序不能超過55k!
(2)把接收到的數(shù)據(jù)寫到Flash的某個區(qū)域
由于需要進行Flash的操作,所以要引入stm32f10x_flash.c
iap.h
#ifndef __IAP_H__
#define __IAP_H__
#include "sys.h"
typedefvoid (*iapfun)(void);//定義一個函數(shù)類型的參數(shù).
#define FLASH_APP1_ADDR0x08010000//第一個應用程序起始地址(存放在FLASH)
//保留0X08000000~0X0800FFFF的空間為IAP使用
注:0x8010000不能隨意定義,與BootLoader程序的大小有關。
void iap_load_app(u32 appxaddr);//執(zhí)行flash里面以appxaddr為起始地址的的app程序
void iap_load_appsram(u32 appxaddr);//執(zhí)行sram里面的app程序
void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 applen);//在指定地址appxaddr開始,寫入bin
#endif
注:0x8010000不能隨意定義,與BootLoader程序的大小有關。
編譯BootLoader程序后,可以看到BootLoader程序占用了多少Flash空間:Code + RO-data,約36k
這里偏移0x10000,為64k的空間。
APP存放在Flash中的地址不能與BootLoader程序存儲的空間有沖突,會出現(xiàn)死機的情況。
(3)主程序
通過串口接收數(shù)據(jù),接收完成后顯示“用戶程序接收完成!”
掃描按鍵
KEY_UP:更新固件,執(zhí)行
iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,applenth);//更新FLASH代碼
KEY_DOWN:清除固件,設置固件長度為0
KEY_LEFT:執(zhí)行Flash中的APP代碼
三。配置APP程序
1. APP所占空間的大小:BootLoader程序為64k空間,對于戰(zhàn)艦版剩余512k-64k=448k,為0x70000,因為0x80000的數(shù)據(jù)為512k,0x80000-0x10000=0x70000
2. 偏移量:正常情況下程序從0x80000開始,APP在Flash中起始地址為0x08010000
以RTC實驗為例進行配置:
如果用ICP下載,這個程序會下載到起始地址為0x08000000的Flash空間中并執(zhí)行
現(xiàn)在用IAP下載,把這個程序下載到起始地址為0x08010000的Flash空間中,然后BootLoader跳轉到這個程序執(zhí)行
(1)配置APP的起始地址和空間大小
Start為起始地址0x8010000,Size為程序大小0x70000
點擊“OK”完成
(2)配置中斷向量表的偏移
在程序的起始的地方設置
int main(void)
{
u8 t=0;
//SCB->VTOR = 0x08000000 | 0x10000;
SCB->VTOR = FLASH_BASE | 0x10000;
delay_init();//延時函數(shù)初始化
NVIC_Configuration(); //設置NVIC中斷分組2:2位搶占優(yōu)先級,2位響應優(yōu)先級
uart_init(9600);//串口初始化為9600
LED_Init();//LED端口初始化
LCD_Init();
usmart_dev.init(SystemCoreClock/1000000);//初始化USMART
RTC_Init();//RTC初始化
FLASH_BASE是系統(tǒng)中已經(jīng)定義了的起始地址,也就是0x08000000
(3)執(zhí)行fromelf.exe,生成bin文件
點擊魔術棒
點擊文件夾,找到fromelf.exe文件
找到一個模板,然后把這里的內容復制到一個新建的txt文件中
把剛才自己找到的fromelf.exe文件路徑替換記事本中.exe文件的路徑
然后再改后面兩個地方: RTC.bin 和RTC.axf
查看自己的程序中執(zhí)行什么程序
在記事本中改好后,復制回來放在user下面:
重新編譯。
如果沒有提示錯誤,表示已經(jīng)生成了bin文件,如果有錯誤可能是剛才fromelf.exe的路徑配置錯了。
在實驗程序的obj文件夾下找到bin文件
(4)先把BootLoader程序用ICP下載到Flash中
下載完成后
通過串口把bin文件寫到Flash中
打開串口調試助手
先要設置好波特率,跟BootLoader程序中的波特率一致,為115200。
選擇打開文件,選擇剛才生成好的bin文件,然后點擊發(fā)送文件
發(fā)送完畢后,表示數(shù)據(jù)已經(jīng)保存到了數(shù)據(jù)緩存中。
按KEY_UP,把數(shù)據(jù)保存到Flash中
然后按KEY2運行保存的RTC程序
在系統(tǒng)中BootLoader程序一般都不大,接收文件,寫到Flash的某個區(qū)域,然后再跳轉。真正的功能都在APP程序中實現(xiàn)。