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

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

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

推荐阅读

第8章 自己写库-构建库函数雏形—零死角玩转STM32-F429系列

本章参考资料:《STM32F4xx 中文参考手册》、《STM32F429规格书》虽然我们上面用寄存器点亮了 LED,乍看一下好像代码也很简单,但是我们别侥幸以后就可以一直用寄存器开发。在用寄存器点亮 LED 的时候,我们会发现 STM32 的寄存器都是 32 位的,每次配置的时候都要对照着《STM32F4xx参考手册》中寄存器的说明,然后根据说明对每个控制的寄存器位写入特定参数,因此在配置的时候非常容易出错,而且代码还很不好理解,不便于维护。所以学习 STM32 最好的方法是用软件库,然后在软件库的基础上了解底层,学习遍所有寄存器。8.1 什么是STM32函数库以上所说的软件库是指"STM32标准函数库",它是
发表于 2019-09-18
第8章 自己写库-构建库函数雏形—零死角玩转STM32-F429系列

第9章 初识STM32固件库—零死角玩转STM32-F429系列

本章参考资料:《STM32F4xx参考手册》、《STM32F4xx规格书》、《Cortex-M3权威指南》, STM32标准库帮助文档:《stm32f4xx_dsp_stdperiph_lib_um.chm》。在上一章中,我们构建了几个控制GPIO外设的函数,算是实现了函数库的雏形,但GPIO还有很多功能函数我们没有实现,而且STM32芯片不仅仅只有GPIO这一个外设。如果我们想要亲自完成这个函数库,工作量是非常巨大的。ST公司提供的标准软件库,包含了STM32芯片所有寄存器的控制操作,我们直接学习如何使用ST标准库,会极大地方便控制STM32芯片。9.1 CMSIS标准及库层次关系因为基于Cortex系列芯片采用的内核都是相同
发表于 2019-09-18
第9章 初识STM32固件库—零死角玩转STM32-F429系列

第14章 启动文件详解—零死角玩转STM32-F429系列

本章参考资料《STM32F4xx 中文参考手册》第十章-中断和事件:表 46. STM32F42xxx 和 STM32F43xxx 的向量表;MDK中的帮助手册—ARM Development Tools:用来查询ARM的汇编指令和编译器相关的指令。14.1 启动文件简介启动文件由汇编编写,是系统上电复位后第一个执行的程序。主要做了以下工作:1、初始化堆栈指针SP=_initial_sp2、初始化PC指针=Reset_Handler3、初始化中断向量表4、配置系统时钟5、调用C库函数_main初始化用户堆栈,从而最终调用main函数去到C的世界14.2 查找ARM汇编指令在讲解启动代码的时候,会涉及到ARM的汇编指令
发表于 2019-09-18
第14章 启动文件详解—零死角玩转STM32-F429系列

第15章 RCC—使用HSE/HSI配置时钟—零死角玩转STM32-F429系列

本章参考资料:《STM32F4xx中文参考手册》RCC章节。学习本章时,配合《STM32F4xx中文参考手册》RCC章节一起阅读,效果会更佳,特别是涉及到寄存器说明的部分。RCC :reset clock control  复位和时钟控制器。本章我们主要讲解时钟部分,特别是要着重理解时钟树,理解了时钟树,F429的一切时钟的来龙去脉都会了如指掌。1.1 RCC主要作用—时钟部分设置系统时钟SYSCLK、设置AHB分频因子(决定HCLK等于多少)、设置APB2分频因子(决定PCLK2等于多少)、设置APB1分频因子(决定PCLK1等于多少)、设置各个外设的分频因子;控制AHB、APB2和APB1这三条总线时钟的开启、控制
发表于 2019-09-18
第15章 RCC—使用HSE/HSI配置时钟—零死角玩转STM32-F429系列

第16章 STM32中断应用概览—零死角玩转STM32-F429系列

本章参考资料《STM32F4xx 中文参考手册》第十章-中断和事件、《 ARM Cortex™-M4F 技术参考手册》-4.3 章节:NVIC和4.4章节:SCB—4.4.5的AIRCR。STM32中断非常强大,每个外设都可以产生中断,所以中断的讲解放在哪一个外设里面去讲都不合适,这里单独抽出一章来做一个总结性的介绍,这样在其他章节涉及到中断部分的知识我们就不用费很大的篇幅去讲解,只要示意性带过即可。本章如无特别说明,异常就是中断,中断就是异常,请不要刻意钻牛角尖较劲。16.1 异常类型F429在内核水平上搭载了一个异常响应系统,支持为数众多的系统异常和外部中断。其中系统异常有10个,外部中断有91个。除了个别异常的优先级被定死外
发表于 2019-09-18
第16章 STM32中断应用概览—零死角玩转STM32-F429系列

第17章 EXTI—外部中断/事件控制器—零死角玩转STM32-F429系列

本章参考资料:《STM32F4xx中文参考手册》系统配置控制器以及中断和事件章节。上一章节我们已经详细介绍了NVIC,对STM32F4xx中断管理系统有个全局的了解,我们这章的内容是NVIC的实例应用,也是STM32F4xx控制器非常重要的一个资源。学习本章时,配合《STM32F4xx中文参考手册》系统配置控制器以及中断和事件章节一起阅读,效果会更佳,特别是涉及到寄存器说明的部分。特别说明,本书内容是以STM32F42xxx系列控制器资源讲解。17.1 EXTI简介外部中断/事件控制器(EXTI)管理了控制器的23个中断/事件线。每个中断/事件线都对应有一个边沿检测器,可以实现输入信号的上升沿检测和下降沿的检测。EXTI可以实现
发表于 2019-09-18
第17章 EXTI—外部中断/事件控制器—零死角玩转STM32-F429系列

小广播

何立民专栏

单片机及嵌入式宝典

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

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