1、什么是IAP?
IAP是In Application Programming的缩写,即在应用编程,IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。 可以通过串口、USB、网络、无线等方式进行升级数据的传输。
2、IAP要点
(1)程序分两部分,BOOT和APP分别编写; (2)flash空间划分(flash空间足够大的情况下,可以分成APP1和APP2进行备份升级);
本文Boot使用0x08000000-0x08003000空间,共12k存放Boot代码(可以根据Boot程序的大小,调整空间),剩下空间存放App代码。 (3)flash可编程(读、写、擦除),本文使用GD32f303,使用以下三个函数完成flash的编程操作。
代码语言:javascript复制void FlashWrite(uint16_t len,uint8_t *data,uint32_t addr_start)
{
uint16_t i;
uint16_t temp;
fmc_state_enum fmc_state=FMC_READY;
fmc_unlock();
fmc_flag_clear(FMC_FLAG_BANK0_END);
fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
for(i=0;i<len/2;i )
{
fmc_state=fmc_halfword_program(addr_start, *(uint16_t*)data);
if(fmc_state!=FMC_READY)
{
return;
}
fmc_flag_clear(FMC_FLAG_BANK0_END);
fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
data = 2;
addr_start = 2;
}
if(len % 2)
{
temp = *data | 0xff00;
fmc_state=fmc_halfword_program(addr_start,temp);
}
fmc_lock();
}
void FlashRead(uint16_t len,uint8_t *outdata,uint32_t addr_start)
{
uint32_t addr;
uint16_t i;
addr = addr_start;
for(i=0;i<len;i )
{
*outdata = *(uint8_t*) addr;
addr = addr 1;
outdata ;
}
}
void FlashErase(uint32_t start, uint32_t end)
{
uint32_t EraseCounter;
fmc_state_enum fmc_state=FMC_READY;
/* unlock the flash program/erase controller */
fmc_unlock();
/* clear all pending flags */
fmc_flag_clear(FMC_FLAG_BANK0_END);
fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
/* erase the flash pages */
while(start < end)
{
EraseCounter = start/FLASH_PAGE_SIZE;
fmc_state=fmc_page_erase(EraseCounter*FLASH_PAGE_SIZE);
if(fmc_state!=FMC_READY)
{
return;
}
fmc_flag_clear(FMC_FLAG_BANK0_END);
fmc_flag_clear(FMC_FLAG_BANK0_WPERR);
fmc_flag_clear(FMC_FLAG_BANK0_PGERR);
start = FLASH_PAGE_SIZE;
}
/* lock the main FMC after the erase operation */
fmc_lock();
}
(4)从BOOT跳转到APP的时候需要,关闭中断,判断栈顶地址、设置栈指针。
代码语言:javascript复制 if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FF30000 ) == 0x20000000)
/*判断栈顶地址是否在合法范围内,*/
{
JumpAddress = *(__IO uint32_t*) (ApplicationAddress 4);
/* Jump to user application */
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) ApplicationAddress);//设置栈指针
Jump_To_Application();
}
ApplicationAddress
为跳转后App的flash首地址,前面4字节存放的正是栈顶地址。一般arm cortex m内核的cpu,ram起始地址为0x20000000,本文使用的GD32F303VC,ram为48k,范围为0x20000000-0x2000C000,所以要跳转到app之前先检查,确保栈顶地址在0x20000000-0x2000C000范围内。
(5)APP程序编译设置
在编译器里面设置,App程序的flash起始地址,flash空间大小。 (6)App程序设置(中断开和中断向量位置设置)
代码语言:javascript复制nvic_vector_table_set(NVIC_VECTTAB_FLASH,0x8003000); //设置向量表起始位置