- 编写bootloader程序
/*
划分flash区域
*/
/* BootLoader macro and functions ------------------------------------------------------- */
//这次使用复旦微mcu其flash 128k
#define BootLoaderAddress (0x0000) //16K 编译后可以根据bin文件大小修改划分bootloader大小
//根据不同MCU确认flash起始地址,像stm32是0x80000
#define ApplicationAddress (0x4000) //54K APP地址
#define Save_Updata_Address (ApplicationAddress + 1024*54) //54K 存储升级APP地址
#define Ota_flag_Address (Save_Updata_Address + 54*1024) // 存储Ota标志位地址
#define Ota_Bin_Size_Address (Ota_flag_Address + 4)//存储bin文件大小地址
typedef void (*pFunction)( void );
#define PAGE_SIZE (0x200) /* 复旦微芯片512B 为一页 具体设置多少看数据手册修改 */
#define Read( address ) (*( (volatile unsigned long *) (address) ) ) //读取flash数据 address为地址
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
unsigned long OTA_flag = 0; //ota标志位
unsigned long Bin_Size = 0;//bin文件大小
* @brief 计算bin文件的页数
* @param Size: The image size
* @retval 返回页数
*/
uint32_t FLASH_PagesMask( __IO uint32_t Size )
{
uint32_t pagenumber = 0x0;
uint32_t size = Size;
if ( (size % PAGE_SIZE) != 0 )
{
pagenumber = (size / PAGE_SIZE) + 1;
}
else
{
pagenumber = size / PAGE_SIZE;
}
return (pagenumber);
}
//跳转程序,更新完跳转到APP区域
//这函数不需要改什么
void JumpToApplication( void )
{
uint32_t Stack_Addr;
uint32_t ResetVector;
pFunction Jump_To_Application;
Stack_Addr = *(__IO uint32_t *) ApplicationAddress;
ResetVector = *(__IO uint32_t *) (ApplicationAddress + 4);
/* Test if user code is programmed starting from address "ApplicationAddress" */
if ( (Stack_Addr & 0x2FFC0000) == 0x20000000 )
{
/* Initialize user application's Stack Pointer */
__set_MSP( Stack_Addr );
/* Jump to user application */
Jump_To_Application = (pFunction) ResetVector;
Jump_To_Application();
}
}
```c
/**
******************************************************************************
* @file Templates_LL/Src/main.c
* @author FMSH AS Embedded Software Team
* @brief Main program body through the LL API
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT(c) 2020 FMSH Microelectronics</center></h2>
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of FMSH Microelectronics nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "bsp.h" //硬件
#include "flash.h"
/** @addtogroup FM15L0XX_LL_Examples
* @{
*/
/** @addtogroup Templates_LL
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Constants used by Serial Command Line Mode */
#define CMD_STRING_SIZE 128
/* BootLoader macro and functions ------------------------------------------------------- */
#define BootLoaderAddress (0x0000) //16K
#define ApplicationAddress (0x4000) //54K APP地址
#define Save_Updata_Address (ApplicationAddress + 1024*54) //54K 存储升级APP地址
#define Ota_flag_Address (Save_Updata_Address + 54*1024) // 存储Ota标志位地址
#define Ota_Bin_Size_Address (Ota_flag_Address + 4)//存储bin文件大小地址
typedef void (*pFunction)( void );
#define PAGE_SIZE (0x200) /* 512 byte */
#define Read( address ) (*( (volatile unsigned long *) (address) ) ) //读取flash数据 address为地址
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
unsigned long OTA_flag = 0;
unsigned long Bin_Size = 0;
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
uint32_t FlashDestination,RamSource;
/**
* @brief Initialize the IAP: Configure RCC, USART and GPIOs.
* @param None
* @retval None
*/
void IAP_Init( void )
{
uart_init( EVAL_COM0 );
}
void NVIC_init( void )
{
NVIC_EnableIRQ( FLASH_IRQn );
}
/**
* @brief Main program
* @param None
* @retval None
*/
/**
* @brief Calculate the number of pages
* @param Size: The image size
* @retval The number of pages
*/
uint32_t FLASH_PagesMask( __IO uint32_t Size )
{
uint32_t pagenumber = 0x0;
uint32_t size = Size;
if ( (size % PAGE_SIZE) != 0 )
{
pagenumber = (size / PAGE_SIZE) + 1;
}
else
{
pagenumber = size / PAGE_SIZE;
}
return (pagenumber);
}
int main( void )
{
/* 功能说明:IAP boot功能
* 硬件配置:无
* 测试流程:无
*/
uint32_t iap_size = 0;
uint32_t erase_page = 0;
/*UART Init and Key Button Init*/
bsp_init(); //初始化串口和flash的GPIO
NVIC_init();//初始化flash的中断源
IAP_Init();//初始化串口
OTA_flag = Read( Ota_flag_Address ); //读取OTA标志
// iap_size = Read( Ota_Bin_Size_Address);//读取bin大小
if ( OTA_flag )//判断到OTA标志
{
/* Execute the IAP driver in order to re-program the Flash */
iap_size= Read( Ota_Bin_Size_Address );//读取Bin的大小
printf( "\r\n======================================================================" );
printf( "\r\n= COPYRIGHT(c) 2021 FMSH Microelectronics =" );
printf( "\r\n= =" );
printf( "\r\n= In-Application Programming Application =" );
printf( "\r\n= =" );
printf( "\r\n= By AS Embedded Software Team =" );
printf( "\r\n======================================================================" );
printf( "\r\n\r\n" );
FlashDestination = ApplicationAddress; //应用程序地址
RamSource = Save_Updata_Address; //存储升级程序地址
erase_page = FLASH_PagesMask( iap_size ); //计算bin文件所占页的个数
for (uint32_t EraseI = 0; EraseI < erase_page; EraseI++ )
{//flash要先擦才能写, 把app区域全都擦掉
flash_erase( LL_FLASH_ERTYPE_SECTOR, FlashDestination + (PAGE_SIZE * EraseI) );
}
for (uint32_t j = 0; (j < iap_size) && (FlashDestination < Save_Updata_Address + iap_size); j += 4 )
{
/* Program the data received into FM15L02x Flash */
//将存储升级数据的区域 一一写到应用区
flash_program( FlashDestination, *(uint32_t *) RamSource );
//判断写入的值是否一致
if ( *(uint32_t *) FlashDestination != *(uint32_t *) RamSource )
{
printf("ota data write err\r\n");
//return;
}
FlashDestination += 4; //地址+4(四个字节) 因为复旦微mcu一次只能写入32位
RamSource += 4;
}
//升级完毕 清除标志位
OTA_flag = 0;
flash_erase(LL_FLASH_ERTYPE_PAGE, Ota_flag_Address);
flash_program(Ota_flag_Address, OTA_flag);
JumpToApplication();//跳转到应用区
}
else//没有更新跳转应用区
{
JumpToApplication();
}
/* Infinite loop */
while ( 1 )
{
}
}
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT FMSH Microelectronics *****END OF FILE****/