什么是双Bank升级:将Flash划分为以下4个区域。
BootLoader区:程序进行升级的引导程序,根据Upade_Flag来判断程序是跳转Bank1区运行程序或是将Bank2区的程序搬运到Bank1区,然后在运行程序。
Upade_Flag区:判断BootLoader是否能跳转IAP程序的标志位。
Bank1区:用户程序区。
Bank2区:接收升级程序的备份区域,如果接收完成后就进入BootLoader将此区域的程序搬运到Bank1区。
1.芯片:N32L406CB(国名技术)
2.开发环境:keil5
对于单片机做OTA功能,首先我们要了解它的Flash大小。我们查看他的数据手册看下Flash大小。
由上图可知Flash为128k。
然后我们再看下Flash页分布。
由上图可知,Flash为128k,64页每页2k。
那么我们就将Flash进行从低地址到高地址进行划分,6k为BootLoader,2k为判断升级标志位。50k为Bank1空间,50k为Bank2空间.
设置BootLoader工程Flash空间为6kb
BootLoader升级代码如下。
#include "main.h"
#include "n32l40x_flash.h"
typedef void (*pFunction)(void);
pFunction Jump_To_Application;
uint32_t JumpAddress;
#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)
uint8_t Buff[FLASH_Page_Size] = {0};
void Jump_To_App(uint32_t address)
{
if (((*(__IO uint32_t*)address) & 0x2FFE0000) == 0x20000000)
{
JumpAddress = *(__IO uint32_t*) (address + 4);
Jump_To_Application = (pFunction) JumpAddress;
__set_MSP(*(__IO uint32_t*) address);
Jump_To_Application();
}
}
void Read_Flash_Data(u8* pBuffer, u32 NumToRead, u32 ReadAddr)
{
u32 i;
for (i = 0; i < NumToRead; i++)
{
*((u8*)pBuffer + i) = *((u8*)ReadAddr + i);
}
}
void Write_Flash_Data(uint8_t *data, uint16_t DataLen, uint32_t DstAddr)
{
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(DstAddr + i, Data))
{
}
//DBG("DstAddr + i %x\r\n", DstAddr + i);
}
FLASH_Lock();
}
bool BankFlashErase(u32 Bank_Addr, uint8_t Page)
{
uint8_t i = 0;
FLASH_Unlock();
for(i = 0; i < Page; i++)
{
if (FLASH_COMPL != FLASH_EraseOnePage(Bank_Addr + FLASH_Page_Size * i))
{
}
//DBG("Bank_Addr = %x\r\n", Bank_Addr + FLASH_Page_Size * i);
}
FLASH_Lock();
}
int main(void)
{
int i = 0;
#ifdef USE_USART
USART2_Configuration();
#endif
Read_Flash_Data(Buff, 1, FLASH_Updata_Flag_ADDR);
if(Buff[0] == 0x55)
{
BankFlashErase(FLASH_Updata_Flag_ADDR, 1);
#ifdef USE_USART
printf("cheeck Bank2 Data\r\n");
#endif
BankFlashErase(FLASH_Bank1_ADDR, FLASH_Page_Num);
for(i = 0; i < FLASH_Page_Num; i++)
{
Read_Flash_Data(Buff, FLASH_Page_Size, FLASH_Bank2_ADDR + FLASH_Page_Size * i);
Write_Flash_Data(Buff, FLASH_Page_Size, FLASH_Bank1_ADDR + FLASH_Page_Size * i);
}
#ifdef USE_USART
printf("data move successful\r\n");
#endif
}
else
{
#ifdef USE_USART
printf("Jump_To_App = %x\r\n", FLASH_Bank1_ADDR);
#endif
}
while (1)
{
Jump_To_App(FLASH_Bank1_ADDR);
}
}
双Bank 串口OTA升级:N32L40X APP (二):跳转链接