datasheet

STM32的在应用编程(IAP)快速学习

2019-05-24来源: eefocus关键字:STM32  应用编程  IAP

1.IAP介绍

IAP(In Application Programming)即在应用编程,IAP 是用户自己的程序在运行过程中对 Flash 部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。实现 IAP 功能时,需要在设计固件程序时编写两个项目代码,第一个项目程序不执行正常的功能操作,而只是通过某种通信方式(如 USB、USART )接收程序或数据,执行对第二部分代码的更新;第二个项目代码才是真正的功能代码。这两部分项目代码都同时烧录在Flash 中,当芯片上电后,首先是第一个项目代码开始运行,它作如下操作:


1.检查是否需要对第二部分代码进行更新

2.如果不需要更新则转到4

3.执行更新操作

4.跳转到第二部分代码执行

我们将第一个项目代码称之为 Bootloader 程序,第二个项目代码称之为 APP 程序,他们存放在 STM32 FLASH 的不同地址范围,一般从最低地址区开始存放 Bootloader,紧跟其后的就是 APP 程序(注意,如果FLASH 容量足够,是可以设计很多APP 程序的,本章我们只讨论一个APP 程序的情况)


Note: 

- 代码第一个字( 4bytes )为栈顶地址指向 RAM,RAM起始地址为 0x20000000 

- 代码第二个字( 4bytes )为程序开始地址


代码内多处使用以上两个地址进行正确与否的判断,故希望读者可以先了解一下,代码中具有详细的讲解 

篇幅有限,只贴出相对较为重要的代码,文章末尾有完整代码的链接可供下载


2.Bootloader程序

2.1. main.c

/*

**************************************************************

** 

** 功能介绍: 上电启动3 秒内未收到APP 更新数据

**                         自动跳转至APP 运行,如果3 秒内收到

**                         APP 更新数据,接收完成后将APP 代码

**                         复制到指定地址并开始执行新的APP

**

** CPU     : STM32F103ZET6

** FLASH  : 512K 0x08000000起

** SRAM   : 64K  0x20000000起

**

**************************************************************

*/

int main( void ) 

{   


    u16 oldcount = 0;

    u16 applenth = 0;

    u16 time = 0;

    Stm32_Clock_Init(9);

    delay_init(72);     

    uart_init(72,256000);


    LED_Init();       

    LCD_Init();

    KEY_Init();


    POINT_COLOR=RED;

    LCD_ShowString(50,50,200,16,16,"BootLoader program");   

    LCD_ShowString(50,80,200,16,16,"Update app program? ");

    LCD_ShowString(50,100,200,16,16,"Yes->Updata");

    LCD_ShowString(50,120,200,16,16,"N o->APP");

    POINT_COLOR=BLUE;


    while(1)

    {


        if(USART_RX_CNT)

        {

            time = 0;

            if( oldcount==USART_RX_CNT )

            {

                applenth=USART_RX_CNT;

                oldcount=0;

                USART_RX_CNT=0;

                printf("rnAPP 接收完成rn");

                printf("APP SIZE = %dBytesrn",applenth);

                printf("更新 APP...rn");    

                /*

                **  1.判断新程序地址是否在FLASH 地址

                **   2.USART_RX_BUF定义时也可以不指定地址,判断时使用k 与0xFF000000 与运算

                **  3.k = (((u32)USART_RX_BUF[7])<<24)|(((u32)USART_RX_BUF[6])<<16)|(((u32)USART_RX_BUF[5])<<8)|(((u32)USART_RX_BUF[4]));

                */

                if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)

                {    

                    iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,applenth);

                    printf("更新完成...rn");  

                }

                if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)

                {    

                    printf("APP 运行中...rn");

                    iap_load_app(FLASH_APP1_ADDR);

                }


            }

            else 

                oldcount=USART_RX_CNT;          

        }else/* 3s 内未收到APP 更新程序自动跳转*/

        {

            time++;

            if( time>300 )

            {

                if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)

                {    

                    printf("APP 运行中...rn");

                    iap_load_app(FLASH_APP1_ADDR);

                }else

                {

                    printf("无APP..rn");

                }

            }

        }


        delay_ms( 10 );            

    }    

}



2.2. iap.h

#ifndef __IAP_H__

#define __IAP_H__

#include "sys.h"  


typedef  void (*iapfun)(void);              /* 定义函数指针*/

#define FLASH_APP1_ADDR     0x08005000      /* 定义APP 程序在FLASH 中的存放地址*/


void iap_load_app(u32 appxaddr);        

void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 applen);  

#endif


2.3. iap.c

iapfun jump2app; 

u16 iapbuf[1024];   

/*

***********************************************************

** appxaddr : 应用程序起始地址

** appbuf : 应用程序代码

** appsize : 应用程序大小,字节数

***********************************************************

*/

void iap_write_appbin( u32 appxaddr,u8 *appbuf,u32 appsize ){

    u16 t;

    u16 i = 0;

    u16 temp;

    u32 fwaddr = appxaddr;

    u8 *dfu = appbuf;

    for( t=0;t

        temp=(u16)dfu[1]<<8;

        temp+=(u16)dfu[0];    

        dfu+=2;

        iapbuf[i++]=temp;       

        if( i==1024 ){

            i=0;

            STMFLASH_Write( fwaddr,iapbuf,1024 );   

            fwaddr+=2048;

        }

    }

    if( i )

        STMFLASH_Write( fwaddr,iapbuf,i );

}


/*

***************************************************

** appxaddr : 跳转到appxaddr 地址的代码运行

**

** note : appxaddr 存放的是用户程序Flash 的首

**          地址, (*(volatile u32*)appxaddr)的意

**          思是取用户程序首地址里面的数据

**          ,这个数据就是用户代码的栈顶地址

**          栈顶地址指向RAM,而RAM的起始地址

**          是0x20000000,因此上面的判断语句执行

**          判断用户代码的栈顶地址是否落在

**          0x20000000~0x2001FFFF 区间中,这个区间的

**          大小为128K,一般情况下,我们使用的芯

**         片较多的落在<128K RAM 的区间

** 注意: 例程中判断栈顶位置是否合法使用的是

**              与0x2FFE0000 进行与运算, 笔者认为使用

**              0xFFFE0000 运算会更加严谨一些, 故修改

**             

***************************************************

*/

void iap_load_app(u32 appxaddr) {


    if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000){ /* 检查栈顶位置是否合法*/

jump2app=(iapfun)*(vu32*)(appxaddr+4); /* 用户代码区第二个字为程序

[1] [2]

关键字:STM32  应用编程  IAP

编辑:什么鱼 引用地址:http://www.eeworld.com.cn/mcu/ic462814.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:STM32的ETR引脚计数功能
下一篇:STM32的FLASH模拟EEPROM

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM32 FSMC 外部使用SRAM

数据,以及与硬盘等外部存储器交换的数据。只要计算机在运行中,CPU就会把需要运算的数据调到内存中进行运算,当运算完成后CPU再将结果传送出来,内存的运行也决定了计算机的稳定运行。SRAM怎么用:使用STM32的FSMC功能,将SRAM映射为单片机的的内部地址,进行指针操作。图中 A0~A18为地址线(即 2^19=512K,1K=1024); IO0~15 为数据线,总共 16根数据线, CS2 和 CS1 都是片选信号,不过 CS2 是高电平有效CS1 是低电平有效; OE 是输出使能信号( 读信号); WE 为写使能信号; UB 和LB 分别为高字节控制和低字节控制信号。 (1)FSMC-外部SRAM 编程流程分析
发表于 2019-06-17
STM32 FSMC 外部使用SRAM

STM32F042 基于CubeMX HAL库CAN的配置

"stm32f0xx_hal.h" CAN_HandleTypeDef hcan;  CAN_FilterConfTypeDef  sFilterConfig;static CanTxMsgTypeDef        TxMessage;static CanRxMsgTypeDef        RxMessage; void SystemClock_Config(void);static void MX_GPIO_Init(void);static void
发表于 2019-06-17
STM32F042 基于CubeMX HAL库CAN的配置

STM32F407 SPI flash

STM32F407 SPI接口:STM32F4XX时钟计算HCLK=168M PCLK1 =HCLK/4 =42M PCLK2 =HCLK/2 =84MSPI2、SPI3在PCLK1,最大时钟为42MSPI1在PCLK2,最大时钟为84MSTM32F4 支持的最大SPI时钟为37.5Mbits/s 因此需要分频。例程选择SPI2 分频后为21M串行Flash W25Q64BVSSIG (最高支持80MHz)。测试:全部写入0XAA 数据长度8192K 擦除:20.798 写入耗时42.599S 读:9.008S百度的参照时间擦除:8.9S 写入22.5S 读出 1.8S  校验时间1.8S 芯片特点
发表于 2019-06-17
STM32F407 SPI flash

STM32F4 USART1 TX RX FIFO

。***********************************************************************************************************///#include "stm32f4xx.h"#include "bspdebug_usartbsp_debug_uart.h"#include "bsp.h"#include <stdio.h>#define  debug_uart_tx_buf_size  1*1024#define  debug_uart_rx_buf_size  1*1024static uint8_t g_TxBuf
发表于 2019-06-17

STM32 SRAM内存管理

; 者: 硬石嵌入式开发团队  * 版    本: V1.0  * 编写日期: 2015-10-04  * 功    能: 动态内存分配管理实现  ******************************************************************************  * 说明:  * 本例程配套硬石stm32开发板YS-F1Pro使用。  *   * 淘宝:  * 论坛:http://www.ing10bbs.com  *  
发表于 2019-06-17

STM32F03开发板--系统时钟设置SysTick

首先我先分析下startup_stm32f0xx.s启动代码,其中/* Call the clock system intitialization function.*/  bl  SystemInit/* Call the application's entry point.*/  bl main发现开发板上电启动过程中,先调用了SystemInit()函数,再进入main()函数。SystemInit()函数在文件system_stm32f0xx.c中,它的作用是设置系统时钟SYSCLK。下面是SystemInit()源码:void SystemInit (void){ 
发表于 2019-06-17
STM32F03开发板--系统时钟设置SysTick

小广播

何立民专栏

单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2019 EEWORLD.com.cn, Inc. All rights reserved