接上一篇文章:双Bank 串口OTA升级:N32L40X BootLoader (一):跳转链接
什么是双Bank升级:将Flash划分为以下4个区域。
BootLoader区:程序进行升级的引导程序,根据Upade_Flag来判断程序是跳转Bank1区运行程序或是将Bank2区的程序搬运到Bank1区,然后在运行程序。
Upade_Flag区:判断BootLoader是否能跳转IAP程序的标志位。
Bank1区:用户程序区。
Bank2区:接收升级程序的备份区域,如果接收完成后就进入BootLoader将此区域的程序搬运到Bank1区。
1.芯片:N32L406CB
2.开发环境:keil5
Flash为128k,64页每页2k。那么我们就将Flash进行从低地址到高地址进行划分,6kBootLoader,2k为判断升级标志位。50k为Bank1空间,50k为Bank2空间.设置BootLoader工程Flash空间为6k。
设置IAP工程起始为0x8002000,Flash空间为50kb,
IAP升级代码如下。
#define FLASH_Updata_Flag_ADDR (0x08000000 + 3*2048)
#define FLASH_Bank1_ADDR (0x08000000 + 4*2048)
#define FLASH_Bank2_ADDR (0x08000000 + 34*2048)
#define FLASH_Page_Num (30)
#define FLASH_Page_Size (2048)
int main(void)
{
SCB->VTOR = FLASH_Bank1_ADDR;
USART1_Configuration();
USART2_Configuration();
NVIC_Uart_Configuration();
Sys_GPIO_Init();
ADC_Initial();
I2C1_GPIO_Init();
I2C1_AW9523_Init();
I2C2_GPIO_Init();
I2C2_AW9523_Init();
I2C3_GPIO_Init();
I2C3_AW9523_Init();
ALL_LED_High;
printf("Project Starting\r\n");
while (1)
{
Usart_Get_Data_Handler();
}
}
void Updata_Handler(uint8_t *data, uint16_t DataLen)
{
uint16_t i = 0;
uint32_t Data;
FLASH_Unlock();
for(i = 0; i < DataLen; i += 4)
{
Data = data[i + 0] << 0;
Data |= data[i + 1] << 8;
Data |= data[i + 2] << 16;
Data |= data[i + 3] << 24;
if (FLASH_COMPL != FLASH_ProgramWord(FLASH_Bank2_ADDR + UpgradeSoftRecvLen + i , Data))
{
while(1)
{
printf("Flash ProgramWord Error. Please Deal With This Error Promptly\r\n");
}
}
}
FLASH_Lock();
//DBG("Write ADDR = %x, DataLen = %d\r\n", FLASH_WRITE_START_ADDR +(i) + UpgradeSoftRecvLen, DataLen);
}
void DualBankDataSaveFlash(uint16_t DataLen)
{
Updata_Handler(Upgrade_Data_Buf, DataLen);
UpgradeSoftRecvLen = UpgradeSoftRecvLen + DataLen;
DBG("OTA data recv:%d,%d\r\n",UpgradeSoftRecvLen,UpgradeSoftTotalSize);
}
bool BankFlashErase(void)
{
uint8_t i = 0;
FLASH_Unlock();
for(i = 0; i < FLASH_Page_Num; i++)
{
if (FLASH_COMPL != FLASH_EraseOnePage(FLASH_Bank2_ADDR + (FLASH_Page_Size * i)))
{
while(1)
{
printf("Flash EraseOnePage Error. Please Deal With This Error Promptly\r\n");
}
}
//DBG("Erase ADDR = %x\r\n", FLASH_WRITE_START_ADDR + (FLASH_START_2k_ADDR * i));
}
FLASH_Lock();
}
void DualBankDataUpgrade(uint32_t DataLen)
{
FLASH_Unlock();
FLASH_EraseOnePage(FLASH_Updata_Flag_ADDR);
FLASH_ProgramWord(FLASH_Updata_Flag_ADDR, 0x55555555);
NVIC_SystemReset();
}