STM32F103C8T6单片机IAP升级

最新更新时间:2022-01-30来源: eefocus关键字:STM32F103C8T6  单片机  IAP升级 手机看文章 扫描二维码
随时随地手机看文章

关于IAP升级的方法和原理,网上已经有很多资料了,这块就不再说了,现在就将bootloader和app配置方法整理如下:


APP程序就是一个简单的LED闪烁。


APP设置为从FLASH中启动:

在这里插入图片描述

STM32F103C8T6单片机flash有64K,前20K空间留给bootloader,从20K之后开始存放APP程序。所以IROM1开始地址设置为 0x8005000,大小为20K。如果APP程序比较大的话,可以修改这个大小值。


然后在程序开始位置设置重新映射复位向量表。让程序从0x8005000位置开始执行。

APP设置为从SRAM中启动:

在这里插入图片描述

APP要从SRAM中运行,那么就要重新映射SRAM中的复位向量表。

由于在bootloader程序中设置的是接收数据代码存储从0x20001000位置开始。所以此处也要设置为程序直接从0x20001000位置处开始运行。如要要改变SRAM中的复位向量位置,那么必须要和bootloader代码同时修改,只修改其中一个的话,程序运行时可能会出错。


此处设置SRAM中起始位置为0x20001000,程序大小为10K,也就是0x2800。IRAM1的起始位置就是 0x20001000 + 0x2800 =0x20003800,大小为6k。刚好将STM32F103C8T6单片机的SRAM 20k空间分配完。由于STM32F103C8T6的SRAM空间比较小,所以设置APP从SRAM中启动时,APP代码不能太大。


APP代码要注意两个地方:一是程序开始时重新映射复位向量表起始位置。二是在选项中设置程序运行起始位置和空间大小。


下来开始配置bootloader代码,通过按键来选择接收APP程序的bin文件,然后通过按键选择从flash中启动代码。


int main ( void )

{

    u8 key;

    u16 oldcount = 0; //老的串口接收数据值

    u16 applenth = 0; //接收到的app代码长度

    SystemInit();

    NVIC_PriorityGroupConfig ( NVIC_PriorityGroup_2 ); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级

    uart_init ( 115200 ); //串口初始化为115200

    delay_init();     //延时初始化


    LED_Init();   //初始化与LED连接的硬件接口

    KEY_Init(); //初始化按键


    while ( 1 )

    {

        GPIO_SetBits ( GPIOC, GPIO_Pin_13 ); //PE.5 输出高

        delay_ms ( 1000 );

        GPIO_ResetBits ( GPIOC, GPIO_Pin_13 ); //PE.5 输出高

        delay_ms ( 1000 );

        if ( USART_RX_CNT )

        {

            if ( oldcount == USART_RX_CNT ) //新周期内,没有收到任何数据,认为本次数据接收完成.

            {

                applenth = USART_RX_CNT;

                oldcount = 0;

                USART_RX_CNT = 0;

                printf ( "用户程序接收完成!rn" );

                printf ( "代码长度:%dBytesrn", applenth );

            }

            else oldcount = USART_RX_CNT;

        }

        key = KEY_Scan ( 0 );

        if ( key == WKUP_PRES )

        {

            if ( applenth )

            {

                printf ( "开始更新固件...rn" );

                if ( ( ( * ( vu32* ) ( 0X20001000 + 4 ) ) & 0xFF000000 ) == 0x08000000 ) //判断是否为0X08XXXXXX.

                {

                    iap_write_appbin ( FLASH_APP1_ADDR, USART_RX_BUF, applenth ); //更新FLASH代码


                    printf ( "固件更新完成!rn" );

                }

                else

                {

                    printf ( "非FLASH应用程序!rn" );

                }

            }

            else

            {

                printf ( "没有可以更新的固件!rn" );

            }

        }

        if ( key == KEY2_PRES )

        {

            if ( applenth )

            {

                printf ( "固件清除完成!rn" );

                applenth = 0;

            }

            else

            {

                printf ( "没有可以清除的固件!rn" );

            }

        }

        if ( key == KEY1_PRES )

        {

            printf ( "开始执行FLASH用户代码!!rn" );

            if ( ( ( * ( vu32* ) ( FLASH_APP1_ADDR + 4 ) ) & 0xFF000000 ) == 0x08000000 ) //判断是否为0X08XXXXXX.

            {

                iap_load_app ( FLASH_APP1_ADDR ); //执行FLASH APP代码

            }

            else

            {

                printf ( "非FLASH应用程序,无法执行!rn" );

            }

        }

    }

}


通过串口将接收到的数据存到SRAM中,然后通过按键将数据从SRAM复制到FLASH中,然后再通过按键选择从FLASH中启动。

此处要注意设置数据在SRAM中的存储起始位置和在FLASH中的存储起始位置。

在这里插入图片描述

将串口接收缓冲区的起始位置设置为 SRAM中的0X20001000位置处,如果APP从SRAM中启动的话,那么这个位置也是程序开始运行的位置。

在这里插入图片描述

将FLASH中复位向量表的偏移位置设置为0x08005000,如果程序从FLASH中启动时,那么这个位置也是程序开始运行的位置。

在这里插入图片描述

下来设置bootloader程序存储地址

在这里插入图片描述

bootloader程序运行开始位置设置为0x8000000开始,大小为20K,也就是说FLASH中前面20K位置存储bootloader代码,20k–64k位置存储APP代码。


主程序中的代码比较简单,就是从串口接收数据,存储到SRAM中从0X20001000位置开始处,然后通过按键将程序拷贝到FLASH中从0x08005000位置开始处。然后通过按键选择设置程序从FLASH中0x08005000位置处开始执行。

代码中有几处判断不太好理解,这里说说自己的理解。

在这里插入图片描述

0X20001000+4 是一个数字,前面加上一级指针 ( vu32* ) ( 0X20001000 + 4 )此时将这个数字变成了地址,也就是 0X20001004这个地址,然后前面再加上二级指针 ( * ( vu32* ) ( 0X20001000 + 4 ) 此时表示的是 取 0X20001004 这个地址中存储的数值。

此时先看看内存分布图。

在这里插入图片描述

串口将程序存储到了0X20001000位置开始处,而程序开始执行时首先要复位向量表位置。也就是说0X20001004位置开始就是程序复位向量表的位置,那么这个位置存储的就是要跳转的地址。而所有程序执行都是从0x08000000位置处开始。


也就是说如果0X20001004这个地址存储的数值时程序开始执行的起始地址,就说明APP程序在SRAM中存储完成了。下来就可以开始拷贝数据了。


同理如果FLASH中存储代码开始位置+4处的值刚好是程序开始执行的地址,也就是说程序已经被拷贝到了FLASH中 FLASH中从_APP1_ADDR 位置开始处。


通过对比内存中指定位置存储的数据,是不是程序复位后的起始地址,就可以判断出数据是否拷贝完成。


下来在看第二种方法,通过串口发送指令来控制bin文件接收和APP运行。


int main ( void )

{

    u16 oldcount = 0; //老的串口接收数据值

    u16 applenth = 0; //接收到的app代码长度

u16 app_bin = 0;

u16 app_enter = 0;

    SystemInit();

    NVIC_PriorityGroupConfig ( NVIC_PriorityGroup_2 ); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级

    uart_init ( 115200 ); //串口初始化为115200

    delay_init();     //延时初始化

    while ( 1 )

    {

// 首先判断app代码的首地址是否为0x0800 000,是则进入app,否的话进行引导区。

        if ( ( ( * ( vu32* ) ( FLASH_APP1_ADDR + 4 ) ) & 0xFF000000 ) == 0x08000000 ) //判断是否为0X08XXXXXX.

        {

            iap_load_app ( FLASH_APP1_ADDR ); //执行FLASH APP代码

        }

//   判断app代码栈顶是否为0x2000 000,不是则进入升级模式,代码如下,其中 FLASH_APP1_ADDR=0x8005000;

        if ( ( ( ( * ( vu32* ) FLASH_APP1_ADDR ) & 0x2FFE0000 ) != 0x20000000 ) )

        {

            printf ( "/***** No APP! *****/ rn" );

            printf ( "stm32f103c8t6在线升级  rn" );

            printf ( "选择对应的app bin文件 rn" );

            printf ( "输入 A 发送bin文件 rn" );

            printf ( "输入 E 进入app rn" );

            while ( 1 )

            {

                if ( USART_RX_CNT )

                {

                    if ( oldcount == USART_RX_CNT ) //新周期内,没有收到任何数据,认为本次数据接收完成.

                    {

                        applenth = USART_RX_CNT;

                        oldcount = 0;

                        USART_RX_CNT = 0;

                        if ( applenth > 100 )

                        {

                            printf ( "用户程序接收完成!rn" );

                            printf ( "代码长度:%dBytesrn", applenth );

                        }

                    }

                    else 

                        oldcount = USART_RX_CNT;

                }

                delay_ms ( 10 );


                if ( USART_RX_BUF[0] == 'A' )

                {

                    if ( applenth )

                        printf ( "rn 请发送bin文件 rn" );

                    app_bin = 1;

                    applenth = 0;

                }

                else if ( app_bin )

                {

                    if ( applenth )

                    {

[1] [2]
关键字:STM32F103C8T6  单片机  IAP升级 编辑:什么鱼 引用地址:STM32F103C8T6单片机IAP升级

上一篇:STM32F103C8T6用官方bootloader实现IAP升级操作方法
下一篇:STM32+FreeRTOS+CUBEMX_学习笔记(七 )输入捕获

推荐阅读

5V供电CAN器件和3.3V供电MCU之间的通讯连接
目前市场上最常用的CAN通讯接口器件大多都是采用5V供电,而大部分的MCU供电电压却从5V降低到了3.3V供电,这样就会造成5VCAN通讯接口器件和3.3VMCU进行通讯时的接口电平不一致问题,本文针对这种应用提出几种5V供电CAN器件和3.3V供电MCU之间的连接方式,并给出了川土微电子产品的具体应用案例。CAN器件概述和MCU之间的连接CAN器件和MCU之间是通过RXD和TXD进行连接的,MCU发送的数据到CAN器件TXD后,由CAN收发器转换成CAN的隐性和显性电平发送到CAN总线,在接收数据时,CAN总线上的隐性和显性电平通过CAN收发器转换成逻辑电平由RXD输出到MCU。以川土微电子的CA-IF1051S/HS为例,对于5
发表于 2023-01-19
5V供电CAN器件和3.3V供电<font color='red'>MCU</font>之间的通讯连接
用汇编语言做一个看门狗测试
用STC的MCU的IO方式控制74HC595驱动8位数码管。; 用户可以修改宏来选择时钟频率.; 显示效果为: 显示秒计数, 5秒后不喂狗, 等复位.Fosc_KHZ EQU 22118 ;22118KHZSTACK_POIRTER EQU 0D0H ; 堆栈开始地址DIS_DOT EQU 020HDIS_BLACK EQU 010HDIS_ EQU 011HAUXR DATA 08EHP4 DATA 0C0HP5 DATA 0C8HP0M1 DATA 0x93 ;P0M0 DATA 0x94 ;P1M1 DATA 0x91 ;P1M0 DATA 0x92 ;P2M1 DATA 0x95 ;P2M0 DATA 0x96 ;P3M1
发表于 2023-01-13
用AT89C51单片机显示倒计时程序
;可设定时间的倒计时定时器,可选择5/15/20/30/35/45/50分钟倒计时;倒计时时间由四位拨码开关的2/3/4位来控制,;第2位表示5分钟,第3位表示15分钟,第4位表示30分钟,;通过不同的组合可以产生5/15/20/30/35/45/50分钟倒计时;P1.0口的外接的发光二极管为状态LED,定时未开始时LED常亮,定时过程中LED闪烁;K1为开始按钮,K2为停止按钮适用STM8S/STM8L/STM8A N76E003 脱机编程器/烧录器/下载器/SP_00【包邮】m.tb.cn/h.UlXVKiOa_bit equ 20h ;数码管个位数存放内存位置b_bit equ 21h ;数码管十位数存放内存位置temp eq
发表于 2023-01-13
基于S3C2440芯片和单片机设计压装数据采集系统的设计
引言随着经济和社会的发展,我国的工业水平和信息技术水平也得到了飞速发展。其中工业中最为常见的零部件组装和装备压装监测设备也得到了不断的改进。压装的过程其实就是按规定的技术要求将零部件进行组培和连接,使之成为半成品或者成品的工艺过程。如图1所示,就是将两个零部件进行过盈无键组装配合,使之牢固结合在一起。工业中很多机械设备都是通过这种压装方式组合到一起的,包括火车轮对、轴承、汽车发动机、变速器、底盘等关键部件。压装的质量决定了以后产品的使用质量和人民的生命财产都息息相关。我们知道压装质量的评判标准,主要是根据压装过程中压力和位移的变化曲线来确定的。而压力位移曲线的获取这就需要由良好的运行稳定的数据采集系统来提供。基于此,本文提出一种基于
发表于 2023-01-13
基于S3C2440芯片和<font color='red'>单片机</font>设计压装数据采集系统的设计
八位单片机的程序优化12项注意事项
1、采用短变量一个提高代码效率的最基本的方式就是减小变量的长度。使用 C 编程时,我们都习惯于对循环控制变量使用 int 类型,这对 8 位的单片机来说是一种极大的浪费,你应该仔细考虑你所声明的变量值可能的范围,然后选择合适的变量类型,很明显,经常使用的变量应该是unsigned char,只占用一个字节。2、使用无符号类型为什么要使用无符号类型呢?原因是8051不支持符号运算,程序中也不要使用含有带符号变量的外部代码,除了根据变量长度来选择变量类型外,你还要考虑是否变量是否会用于负数的场合。如果你的程序中可以不需要负数那么把变量都定义成无符号类型的。3、避免使用浮点指针在 8 位操作系统上使用 32 位浮点数是得不偿失的。你可以这
发表于 2023-01-13
单片机程序该如何优化?
对程序进行优化,通常是指优化程序代码或程序执行速度。优化代码和优化速度实际上是一个予盾的统一。一般是优化了代码的尺寸,就会带来执行时间的增加;如果优化了程序的执行速度,通常会带来代码增加的副作用。很难鱼与熊掌兼得,只能在设计时掌握一个平衡点。一、程序结构的优化1、程序的书写结构虽然书写格式并不会影响生成的代码质量,但是在实际编写程序时还是应该尊循一定的书写规则,一个书写清晰、明了的程序,有利于以后的维护。在书写程序时,特别是对于While、for、do…while、if…else、switch…case 等语句或这些语句嵌套组合时,应采用“缩格”的书写形式。2、标识符程序中使用的用户标识符除要遵循标识符的命名规则以外,一般不要用代数
发表于 2023-01-13

推荐帖子

Protel99SE金属槽孔做法
正确画法是Protel99SE设计长条槽采取下图,用Pad一个个孔叠加成一个长条槽。虽画时需要点时间,但这个成品就是您所要的效果,因软件自身有限请按下图规范化设计需要用PAD磊成槽,Protel99SE这个软件就是这样的,没有这个功能,只有手动一个个放PAD成形槽的。槽孔:钻槽(孔内有铜)大小范围≥0.65MM,铣槽(孔内无铜)大小范围≥0.8MM,槽孔也可简称连孔。槽刀与钻咀有何区别呢?在钻连孔时是极易断刀,如采用钻咀连孔钻孔则更易断刀。槽刀设计的特点相对钻咀来说不易断刀,因此在设计槽孔
PCBBCP PCB设计
HTC即将被谷歌收购——你用过哪款htc手机
HTC这次真要卖身了,金主爸爸谷歌要做接盘侠>>>https://mp.weixin.qq.com/s/mrLXqgaDthxs0l8LmkiqEg 宏达电(htc)昨天傍晚公告,今天将宣布重大讯息,因此申请股票暂时停牌。针对外传将「下嫁」谷歌,宏达电仅表示,对市场谣言与臆测不予评论,今天将召开发布会说明。知情人士指出,宏达电确与谷歌洽谈合作,未来宏达电只保留手机品牌、生产线与营销团队,大部分的手机研发、工程人员则由谷歌接手。 又一家老牌智能手机厂商走到了转变的十字路
eric_wang 移动便携
MSCOMM控件做串口通信程序,发送数据的格式怎么去定义啊
请教个问题:我做应用程序的,使用MSCOMM控件做了一个串口通信程序(VB),用串口调试程序测试接受和发送数据都没有问题,现在同事要在硬件那边发送数据,他用汇编,现在他说我的程序有问题,发送格式不对,说要按他的格式发送:即先发一个0X10作为帧头,然后再是数据,最后0X16做帧尾!对硬件我不怎么懂,所以有点迷惑了,在MScomm控件中怎么去做才能和他对应起来啊MSCOMM控件做串口通信程序,发送数据的格式怎么去定义啊
zhangchuang 嵌入式系统
求助:请帮忙分析一下这个电路
请帮忙分析一下这个电路,IC2用哪个芯片比较合适。求助:请帮忙分析一下这个电路
goodboy 汽车电子
一个利用激光雕刻机辅助手工焊接的创意
自己手工焊过PCB的工程师应该都有下面这种感受, 手焊最浪费时间的,是对照BOM表查找元件在PCB上的位置, 而实际真正用在焊接上的时间,一般不超过总时间的1/3, 所以便有了如下创意想法: 大家都知道,主流的PCB设计软件都可以直接导出元件的坐标, 而且现在主流的SMT也都是根据这个坐标来贴放元件的; 如此,我们便可以利用现有的激光雕刻机,配合一个简单的上位机, 通过对元件的坐标定位,实现对元件的自动定位,辅助手工焊接; 这个方案几乎可以将元件查找的时间缩短为零,让手焊时间
通宵敲代码 DIY/开源硬件专区
基于单片机控制的测压显示模块电路的设计
本帖最后由paulhyde于2014-9-1503:09编辑基于单片机控制的测压显示模块电路的设计 基于单片机控制的测压显示模块电路的设计
呱呱 电子竞赛
小广播
设计资源 培训 开发板 精华推荐

何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2023 EEWORLD.com.cn, Inc. All rights reserved