iap.h头文件
下面展示一些 内联代码片
。
#ifndef __IAP_H__
#define __IAP_H__
/* 类型定义 */
typedef void(*iap_func_cb)(void); /* 定义一个函数类型的参数 */
/* 宏定义 */
#define M_USER_START_FLASH (1) /* 判断APP时从Flash,还是SRAM启动 */
#ifdef M_USER_START_FLASH
#define M_APP_START_ADDR (0x8008000UL) /* 从Flash启动,定义Bootloader空间为32K */
#else
#define M_APP_START_ADDR (0x2008000UL) /* 从SRAM启动,定义Bootloader空间为32K */
#endif
#define M_APP_FLASH_LEN (56320UL) /* 给应用固件定义了55K的空间 */
/* 结构体声明 */
/* 应用APP的数据结构体 */
typedef struct _iap_app_bin_st
{
unsigned char data[M_APP_FLASH_LEN]; /* app最大应用升级数据*/
unsigned short datalen; /* 长度 */
} iap_app_bin_st;
/* 函数声明 */
/* 向Flash中写入APP数据 */
void iap_write_app_bin(unsigned int app_addr, unsigned char *data, unsigned short datalen);
/* 执行APP应用程序 */
void iap_execute_app(unsigned int app_addr);
#endif
iap.c文件
#include "iap.h"
#include "stmflash/stm_flash.h"
/* 宏定义 */
#define M_FLASH_APP_MAX_DATALEN (1024UL) /* 最大写入flash数据长度 */
/* 全局变量定义 */
#if defined(__CC_ARM) /* keil编译环境 */
static iap_app_bin_st g_app_bin __attribute__((at(M_APP_START_ADDR))) = {{0}, 0};
#elif defined(__ICCARM__) /* IAR编译环境 */
static iap_app_bin_st g_app_bin = {{0}, 0};
#endif
/* flash写数据buffer,根据实际Flash块的大小去定,这里使用2K块 */
static unsigned short g_flash_app_data[M_FLASH_APP_MAX_DATALEN] = {0};
/* 函数定义 */
/**************************************************************************
* 函 数: void iap_write_app_bin(unsigned int app_addr, unsigned char *data, unsigned short datalen)
* 描 述: 向Flash中写入APP数据
* 入 参: unsigned int app_addr:应用入口地址
unsigned char *data:APP数据
unsigned short datalen:数据长度
* 出 参: void
* 返回值: void
**************************************************************************/
void iap_write_app_bin(unsigned int app_addr, unsigned char *data, unsigned short datalen)
{
unsigned short index = 0;
unsigned short temp_data = 0;
unsigned short temp_app_len = 0;
unsigned int write_start_addr = 0;
do
{
if ((NULL == data) || (M_APP_START_ADDR >= app_addr) || (0 == datalen))
{
//printf("input param is error.\r\n");
break;
}
write_start_addr = app_addr;
for (index = 0; index < datalen; index += sizeof(unsigned short))
{
/* 以16位数据进行单个数据写入 */
temp_data = (unsigned short)(data[index + 1] << 8);
temp_data += (unsigned short)data[index];
g_flash_app_data[temp_app_len++] = temp_data;
if (M_FLASH_APP_MAX_DATALEN == temp_app_len)
{
/* 填满2K数据 */
temp_app_len = 0;
/* 从起始地址开始写入2K数据 */
StmWriteFlash(write_start_addr, g_flash_app_data, M_FLASH_APP_MAX_DATALEN);
write_start_addr += sizeof(unsigned short) * M_FLASH_APP_MAX_DATALEN;
}
}
/* 最后如果不足2K,就写入剩余的数据 */
if (temp_app_len > 0)
{
StmWriteFlash(write_start_addr, g_flash_app_data, temp_app_len);
}
}
while (0);
return;
}
#if defined(__CC_ARM) /* keil编译环境 */
__asm void Set_MSR_MSP(unsigned int addr)
{
MSR MSP, r0 //set Main Stack value
BX r14
}
#elif defined(__ICCARM__) /* IAR编译环境 */
// __set_MSP(入口地址);
void Set_MSR_MSP(unsigned int addr)
{
asm("MSR MSP, r0"); //set Main Stack value
asm("BX r14");
}
#endif
/**************************************************************************
* 函 数: void iap_execute_app(unsigned int app_addr)
* 描 述: 跳转到应用入口地址,执行APP应用程序
* 入 参: unsigned int app_addr : 应用起始地址
* 出 参: void
* 返回值: void
**************************************************************************/
void iap_execute_app(unsigned int app_addr)
{
iap_func_cb jump_app_func; /* 跳转到APP的接口函数 */
/* 检测栈顶的地址,判断用户代码的堆栈地址是否落在0x2000000~0x2001ffff区间 */
if (0x20000000 == ((*(__IO unsigned int *)app_addr) & 0x2FFE0000))
{
/* 跳转到用户程序 */
jump_app_func = (iap_func_cb)(*(__IO unsigned int *)(app_addr + 4));
//设置主函数栈指针 将用户代码的栈顶地址设为栈顶指针
Set_MSR_MSP(*(__IO unsigned int *)app_addr);
//调用函数,实际失去app复位地址去执行复位操作---设置程序指针为复位地址
jump_app_func();
}
}