双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

对于单片机做IAP功能,首先我们要了解它的Flash大小。我们查看他的数据手册看下Flash大小。

双Bank OTA升级:N32L40X BootLoader (一)_第1张图片

由上图可知Flash为128k。

然后我们再看下Flash页分布。

 由上图可知,Flash为128k,64页每页2k。

那么我们就将Flash进行从低地址到高地址进行划分,6k为BootLoader,2k为判断升级标志位。50k为Bank1空间,50k为Bank2空间.

设置BootLoader工程Flash空间为6kb

双Bank OTA升级:N32L40X BootLoader (一)_第2张图片

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 (二):跳转链接

你可能感兴趣的:(单片机升级,stm32,嵌入式硬件,单片机)