STM32速成笔记(15)—串口IAP

发布者:温暖的微风最新更新时间:2024-03-21 来源: elecfans关键字:STM32  串口IAP 手机看文章 扫描二维码
随时随地手机看文章

一、串口IAP简介

1.1 什么是IAP

IAP,英文全称In Application Programming,在应用中编程。很好理解,就是在程序运行过程中我们进行程序的烧写,或者叫升级。

1.2 STM32下载程序

我们都知道,STM32可以利用串口下载程序,这是因为ST公司在产线上就在产品中内嵌了自举程序。所谓的自举程序,实际就是支持我们通过串口下载程序的代码。自举程序被存放在系统存储区,因此如果我们需要通过串口下载程序,需要将Boot0接高电平,Boot1接低电平,让程序从系统存储器开始运行,运行自举程序。下载完成后我们再将Boot0接地,让程序从主闪存存储器开始运行。自举程序是我们用户无法修改的。

二、串口IAP有什么作用

上面我们介绍了什么是IAP,那么这个IAP到底有什么作用呢?

首先介绍两个词——Bootloader和 Application 。Bootloader实际就是一段引导程序,单片机上电后先执行Bootloader程序,然后再执行用户编写的应用程序Application。介绍完这两个词,我们来介绍一下IAP有什么作用。比如我们生产了A,B两款产品。A产品是某个精密器件的一部分,B产品是一款物联网产品。我们的产品销售范围很广,远销海外。

某天A产品的某个客户反映了一个Bug,我们编写好了程序,需要进行程序更新,或者叫升级。利用IAP,我们可以在程序运行时,通过预留的通信接口直接烧写程序。而不需要再把整个设备拆开,像我们调试时那样下载程序。甚至我们可以直接给客户邮寄一个小设备,客户直接进行傻瓜式升级。

又过了一段时间,B产品的程序出现了一个Bug,风险等级比较低,但是依旧需要全体升级程序。我们总不能挨个产品派人去升级,成本极大。这时候又轮到我们的IAP出场了。它可以在所有设备在线运行的情况下,直接通过网络下发升级程序,实现在线升级,节约了大量的人力成本。

通过上面这两个例子,大家应该能够基本了解IAP的用处,使用IAP让我们不需要再使用调试器进行下载,甚至实现设备的在线升级。

三、启动流程

在介绍如何实现IAP之前,我们先来简单了解以下STM32的启动流程。

3.1 正常启动流程

这里的正常启动流程指的是,没有添加IAP的流程。

图片

正常启动流程

程序启动时首先开辟栈空间,配置栈顶指针。然后配置堆空间。配置完成后,建立中断向量表,在中断向量表中找到复位中断,开始执行复位中断服务函数,然后跳转到main函数中,执行用户代码。当用户代码中有中断请求时,会回到中断向量表,根据中断源执行相应的中断服务函数。

3.2 加入IAP后的启动流程

下面是加入IAP之后的启动流程。

图片

加入IAP启动流程

可以看到,与上面不同的是,加入IAP后,执行完复位中断服务函数后直接进入IAP的main函数。在执行完IAP之后,跳转至新写入程序的复位向量表,取出新程序的复位中断向量的地址,并跳转执行新程序的复位中断服务程序,随后跳转至新程序的main 函数。

由上面的两个启动过程我们可以看出

  • • 新程序必须在 IAP 程序之后的某个偏移量为 x 的地址开始。

  • • 必须将新程序的中断向量表相应的移动,移动的偏移量为 x。

    四、必备知识

    44.1 修改程序运行起始地址

点击魔术棒,选择“Target”,修改运行起始地址和代码大小。

图片

修改App运行起始地址

4.2 设置中断向量表偏移

VTOR 寄存器存放的是中断向量表的起始地址。如果要设置中断向量表偏移,只需要在main函数最开始添加如下语句即可

SCB- >VTOR = FLASH BASE | 偏移量:

4.3 生成.bin文件

点击魔术棒,选择“User”,按照如下配置,输入下面的内容

fromelf --bin -o '$L@L.bin' '#L'

图片

生成.bin文件配置

点击编译,不报错就可以,去设置的输出文件夹中就可以找到对应的.bin文件。

图片

编译提示

五、串口IAP实现

本次的目标是实现一个串口IAP,也就是编写Bootloader,在程序运行过程中实现程序的下载。Bootloader程序应该可以通过串口接收上位机发来的.bin文件(App程序),检查后将.bin文件写入到Flash特定位置,然后跳转到App程序运行。


5.1 串口中断服务函数

本次的串口中断服务函数与之前不同,这里单独贴出来。需要定义一个接收数组,接收数组的起始地址限制为0X20001000。接收数组最多可以接收55K字节,可以根据需要调整。但是需要注意的是,数组的大小需要比App程序要大,而且不能超过芯片的SRAM空间大小。


/*

 *==============================================================================

 *函数名称:USART1_IRQHandler

 *函数功能:USART1中断服务函数

 *输入参数:无

 *返回值:无

 *备  注:无

 *==============================================================================

 */

u32 gReceCount = 0;   // 接收计数变量

// 接收数组

// 限制起始地址为0X20001000

// 保证偏移量为 0X200的倍数

// 是为了给App留SRAM空间

u8 gReceFifo[USART_RECE_MAX_LEN]__attribute__ ((at(0X20001000)));


void USART1_IRQHandler(void)  

{

    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)   //接收到一个字节  

    {

        if (gReceCount < USART_RECE_MAX_LEN)

        {

            gReceFifo[gReceCount++] = USART1- >DR;

        }

        else

        {

            printf ('APP code out of memory!rn');

        }

    }

}

5.2 Flash写入程序

关于Flash程序,这里就不在赘述,只是贴一下带检查的写入程序。其他具体内容可以到博主STM32速成笔记专栏查看。


/*

 *==============================================================================

 *函数名称:Med_Flash_Write

 *函数功能:从指定地址开始写入指定长度的数据

 *输入参数:WriteAddr:写入起始地址;pBuffer:数据指针;

                        NumToRead:写入(半字)数

 *返回值:无

 *备  注:对内部Flash的操作是以半字为单位,所以读写地址必须是2的倍数

 *==============================================================================

 */


// 根据中文参考手册,大容量产品的每一页是2K字节

#if STM32_FLASH_SIZE < 256

    #define STM32_SECTOR_SIZE   1024   // 字节

#else 

    #define STM32_SECTOR_SIZE   2048

#endif


// 一个扇区的内存

u16 STM32_FLASH_BUF[STM32_SECTOR_SIZE / 2];


void Med_Flash_Write (u32 WriteAddr,u16 *pBuffer,u16 NumToWrite)

{

    u32 secpos;   // 扇区地址

    u16 secoff;   // 扇区内偏移地址(16位字计算)

    u16 secremain;   // 扇区内剩余地址(16位计算)    

     u16 i;    

    u32 offaddr;   // 去掉0X08000000后的地址

    

    // 判断写入地址是否在合法范围内

    if (WriteAddr < STM32_FLASH_BASE || (WriteAddr >= (STM32_FLASH_BASE + 1024 * STM32_FLASH_SIZE)))

    {

        return;   // 非法地址

    }

    

    FLASH_Unlock();   // 解锁

    offaddr = WriteAddr - STM32_FLASH_BASE;   // 实际偏移地址

    secpos = offaddr / STM32_SECTOR_SIZE;   // 扇区地址

    secoff = (offaddr % STM32_SECTOR_SIZE) / 2;   // 在扇区内的偏移(2个字节为基本单位)

    secremain = STM32_SECTOR_SIZE / 2 - secoff;   // 扇区剩余空间大小

    

    if (NumToWrite <= secremain)

    {

        secremain = NumToWrite;   // 不大于该扇区范围

    }

    

    while (1) 

    {

        // 读出整个扇区的内容

        Med_Flash_Read(secpos * STM32_SECTOR_SIZE + STM32_FLASH_BASE,STM32_FLASH_BUF,STM32_SECTOR_SIZE / 2);

        

        // 校验数据

        for (i = 0;i < secremain;i ++)

        {

            // 需要擦除 

            if (STM32_FLASH_BUF[secoff + i] != 0XFFFF)

            {

                break; 

            }    

        }

        // 需要擦除

        if (i < secremain)

        {

            FLASH_ErasePage(secpos * STM32_SECTOR_SIZE + STM32_FLASH_BASE);   // 擦除这个扇区

            

            // 复制

            for (i = 0;i < secremain;i ++)

            {

                STM32_FLASH_BUF[i + secoff] = pBuffer[i];   

            }

            

            // 写入整个扇区

            Med_Flash_Write_NoCheck(secpos * STM32_SECTOR_SIZE + STM32_FLASH_BASE,STM32_FLASH_BUF,STM32_SECTOR_SIZE / 2);

        }

        else

        {

            // 写已经擦除了的,直接写入扇区剩余区间

            Med_Flash_Write_NoCheck(WriteAddr,pBuffer,secremain);

        }

        

        if (NumToWrite == secremain)

        {

            break;   // 写入结束了

        }

        // 写入未结束

        else

        {

            secpos ++;   // 扇区地址增1

            secoff = 0;   // 偏移位置为0   

            pBuffer += secremain;   // 指针偏移

            WriteAddr += secremain;   // 写地址偏移    

            NumToWrite -= secremain;   // 字节(16位)数递减

            if (NumToWrite > (STM32_SECTOR_SIZE / 2))

            {

                secremain = STM32_SECTOR_SIZE / 2;   // 下一个扇区还是写不完

            }

            else

            {

                secremain = NumToWrite;   // 下一个扇区可以写完了

            }

        }  

    } 

    FLASH_Lock();   // 上锁

}

5.3 IAP程序

IAP程序包含两部分,一部分是将接收到的.bin文件写入Flash,另一部分是跳转到App执行。


/*

 *==============================================================================

 *函数名称:iap_write_appbin

 *函数功能:写入.bin文件

 *输入参数:appxaddr:App程序起始地址;appbuf:缓存App程序的数组;

                        appsize:App程序大小

 *返回值:无

 *备  注:无

 *==============================================================================

 */

 // 对Flash操作的最小单位是16位

 u16 iapbuf[1024];   // 要写入Flash的内容

 

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

{

    u16 t;   // 临时循环变量

    u16 i = 0;   // 自增索引

    u16 temp;   // 临时计算变量

    

    u32 fwaddr = appxaddr;   // 当前写入的地址

    u8 *dfu = appbuf;   // 指向App代码数组首地址的指针

    

    // for循环,2K为单位进行写入

    for(t = 0;t < appsize;t += 2)

    {  

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

        temp += (u16)dfu[0];   

        dfu += 2;   // 偏移2个字节

        iapbuf[i++] = temp;     

        if(i == 1024)

        {

            i = 0;

            Med_Flash_Write (fwaddr,iapbuf,1024); 

            fwaddr += 2048;   // 偏移2048  16=2*8所以要乘以2

        }

    }

    if(i)

    {

        Med_Flash_Write (fwaddr,iapbuf,i);   // 将最后的一些内容字节写进去

    }

}

/*

 *==============================================================================

 *函数名称:iap_load_app

 *函数功能:跳转到App

 *输入参数:appxaddr:App程序起始地址

 *返回值:无

 *备  注:无

[1] [2]
关键字:STM32  串口IAP 引用地址:STM32速成笔记(15)—串口IAP

上一篇:STM32 HAL库I2C读写操作笔记
下一篇:STM32基础知识:PWM控制舵机

推荐阅读最新更新时间:2024-11-10 11:47

stm32 FSMC-外扩SRAM IS62WV51216
引脚定义 FSMC配置步骤 1.使能对应引脚GPIO时钟 2.配置GPIO引脚模式 3.使能FSMC时钟 4.FSMC初始化 5.存储器块使能 举例 #define Bank1_SRAM3_ADDR ((u32)(0x68000000)) //首地址0x60000000,每块0x40000000 void SRAM_gpio_init() { GPIO_InitTypeDef gpiof = { GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_12 | GPI
[单片机]
STM32的时钟系统分析(程序)
在 STM32 中,有五个时钟源,为HSI、HSE、LSI、LSE、PLL。   ①、HSI是高速内部时钟,RC振荡器,频率为8MHz。   ②、HSE是高速外部时钟,可接石英/陶瓷谐振器,或者接外部时钟源,频率范围为4MHz~16MHz。   ③、LSI是低速内部时钟,RC振荡器,频率为40kHz。   ④、LSE是低速外部时钟,接频率为32.768kHz的石英晶体。   ⑤、PLL为 锁相环 倍频输出,其时钟输入源可选择为HSI/2、HSE或者HSE/2。倍频可选择为2~16倍,但是其输出频率最大不得超过72MHz。   其中40kHz的LSI供独立看门狗IWDG使用,另外它还可以被选择为实时时钟RTC的时钟源。另外,
[单片机]
STM32学习 存储器和总线构架
主系统由以下部分构成: 1.四个驱动单元: Cortex-M3内核,DCode总线和系统总线(S-Bus),通用DMA1和通用DMA2 2四个被动单元 内部SRAM,内部闪存存储器,FSMC,AHB到APB的桥,它链接所有的APB设备。 程序存储器,数据存储器,寄存器和输入输出端口被组织在同一个4GB的线性地址空间内。数据字节以小端格式存放在存储器中。 可访问的存储器空间被分成8个主要块,每一个块为512M。 STM32F10XX内置64K字节的静态SRAM,它可以以字节,半字,或字访问。 SRAM的起始地址是0x2000000 Cortex-M3存储器映像包括两个位段区。这两个位段区将别外存储区中的每个字映
[单片机]
STM32单片机常用库函数 STM32单片机系统作用
STM32单机片又被称为嵌入式单机片,靠着高性能、低成本、低功耗、可裁剪吸引着大家。 系统作用 1、集成嵌入式Flash和SRAM存储器的ARM Cortex-M3内核。 2、嵌入式Flash存储器和RAM存储器 3、可变静态存储器(FSMC 4、嵌套矢量中断控制器(NVIC) 5、外部中断/事件控制器(EXTI) 6、时钟和启动 7、Boot模式 STM32单片机常用库函数 1.GPIO初始化函数 用法: voidGPIO_Configuration(void) { GPIO_InitTypeDefGPIO_InitStructure;//GPIO状态恢复默认参数 GPIO_InitStructure.GPIO_Pin=
[单片机]
STM32 USART简介-串口通讯协议简介01
通讯的方式分类: 1.并行通信:是指数据的各位同时在多根数据线上发送或接收。如下图 并行通信的特点:控制简单,传输速度快;由于传输线较多,适用于短距离通信。 2.串行通信:是指数据的各位在同一根数据线上逐位发送和接收。如下图 串行通信的特点:控制复杂,传输速度慢;只需要一根数据线,适用于远距离通信。 串行通信方式分类 在串行通信中,根据对数据流的分界、定时以及同步方案方法不同,可分为和同步串行通信方式和异步通信方式。 同步通信 同步通信是指发送端和接收端必须使用同一时钟,是一种连续传送数据的通信方式,一次通讯传送多个字符数据(一帧数据)。下图是同步串行通信帧格式: 同步串行通信方式:把许多字符组成一个信息组
[单片机]
<font color='red'>STM32</font> USART简介-<font color='red'>串口</font>通讯协议简介01
判断STM32 GPIO输入口的输入状态(高电平或低电平)
在学习STM32中的过程中,经常会遇到“高电平有效”,“低电平有效”等字眼,初看时很多时候就会从字面上理解,认为高电平有效的意思就是有效电平是高电平,低电平有效的意思就是有效电平是低电平的意思。而实际上,这样的理解是有误的。下面咱们以STM32的定时器中输出比较通道为例: 这幅图实际上就是一个pwm波产生的过程,对定时器不了解的可以去查阅相关手册,现在我们先看图中标号1的输出模式控制器,这里模式是指pwm模式,他的意思就是可以通过配置寄存器TIMx_CCMR1的OC1M两位,来选择pwm的模式,但是关于模式选择,手册中有这样一句话:在向下计数时,一旦TIMx_CNT TIMx_CCR1时通道1为无效电平(OC1REF=0),
[单片机]
判断<font color='red'>STM32</font> GPIO输入口的输入状态(高电平或低电平)
关于使用STM32 SPI3的一些总结
总结一下spi3的问题,因为spi3的nss口与JTAG有共用引脚,所以配置错误会导致SPI3无法使用。需要注意以下三点就可以了:  1.将PA15配置为普通IO口,GPIO_Mode_Out_PP  2.开启AFIO时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);  3.关闭JTAG功能,使能SWD  GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE) ; 其他的SPI口正常配置,因为板子重启后默认为JTAG模式,虽然在调试时使用了SWD,但PA15依然不是普通的IO口,当把它重新配置时,一定要开启AFIO时钟,
[单片机]
ST新款STM32微控制器:让日用品有像智能手机的图形用户界
无需增加研发成本,不影响电池续航能力,为智能物品带来更丰富的功能。 中国,2015年4月27日 横跨多重电子应用领域、全球领先的半导体供应商意法半导体(STMicroelectronics,简称ST;纽约证券交易所代码:STM)推出新款微控制器芯片,让穿戴式装置、智能家电产品等物联网(IOT, Internet of Things)应用具有出色的图形处理性能,实现像智能手机一样的直观的图形用户界面。通过整合Chrom-ART Accelerator 技术及已被广泛用于先进智能手机和平板电脑的MIPI-DSI 技术,STM32F469/479新系列微控制器的性能达到更高水平,且不会增加成本及影响电池的续航能
[单片机]
ST新款<font color='red'>STM32</font>微控制器:让日用品有像智能手机的图形用户界
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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