STM32的IAP升级方案

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();
	    }
	}
	
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值