IAR环境下STM32+IAP方案的实现

发布者:脑洞飞翔最新更新时间:2021-04-21 来源: eefocus关键字:IAR环境  STM32  IAP方案 手机看文章 扫描二维码
随时随地手机看文章

一、什么是IAP,为什么要IAP


IAP即为In Application Programming(在应用中编程),一般情况下,以STM32F10x系列芯片为主控制器的设备在出厂时就已经使用J-Link仿真器将应用代码烧录了,如果在设备使用过程中需要进行应用代码的更换、升级等操作的话,则可能需要将设备返回原厂并拆解出来再使用J-Link重新烧录代码,这就增加了很多不必要的麻烦。站在用户的角度来说,就是能让用户自己来更换设备里边的代码程序而厂家这边只需要提供给用户一个代码文件即可。


而IAP却能很好的解决掉这个难题,一片STM32芯片的Code(代码)区内一般只有一个用户程序。而IAP方案则是将代码区划分为两部分,两部分区域各存放一个程序,一个叫bootloader(引导加载程序),另一个较user application(用户应用程序)。bootloader在出厂时就固定下来了,在需要变更user application时只需要通过触发bootloader对userapplication的擦除和重新写入即可完成用户应用的更换。如图1-1所示

图 1-1


在程序执行初始进入bootloader,在bootloader里面检测条件是否被触发(可通过按键是否被按下、串口是否接收到特定的数据、U盘是否插入等等),如果有则进行对user application进行擦除和重新写入操作,如果没有则直接跳转到user application执行应用;如果有则进行擦除用户代码并重新写入新的用户代码。


二、STM32F103ZET6硬件条件


STM32F103ZET6的启动方式有三种:内置FLASH启动、内置SRAM启动、系统存储器ROM启动,通过BOOT0和BOOT1引脚的设置可以选择从哪中方式启动,这里选择内置的FLASH启动。其FLASH的地址为0x08000000—0x0807ffff,共512KB,这些都能从芯片数据手册中直接得到。而这里首要的一个问题是中断的问题。正常情况下发生中断的过程为:发生中断(中断请求)à到中断向量表查找中断函数入口地址à跳转到中断函数à执行中断函数à中断返回。也就是说在STM32的内置的Flash中有一个中断向量表来存放各个中断服务函数的入口地址,内置Flash的分配情况大致如下图2-1。

图2-1


在只有一个程序的情况下,程序执行的走向应该如图2-2所示(借用网友的原图)。

图2-2


STM32F10x有一个中断向量表,这个中断向量表存放在代码开始部分的后4个字节处(即0x08000004),代码开始的4个字节存放的是堆栈栈顶的地址,当发生中断后程序通过查找该表得到相应的中断服务程序入口地址,然后再跳到相应的中断服务程序中执行。上电后从0x08000004处取出复位中断向量的地址,然后跳转到复位中断程序的入口(标号①所示),执行结束后跳转到main函数中(标号②所示)。在执行main函数的过程中发生中断,则STM32强制将PC指针指回中断向量表处(标号③所示),从中断向量表中找到相应的中断函数入口地址,跳转到相应的中断服务函数(标号④所示),执行完中断函数后再返回到main函数中来(标号⑤所示)。


若在STM32F103x中使用IAP方案,则内置的Flash分配情况大致如下图2-3。



图2-3


在内置的Flash里面添加一个BootLoader程序,BootLoader程序和userapplication各有一个中断向量表,假设BootLoader程序占用的空间为N+M字节,则程序的走向应该如图2-2所示(借用网友的原图并做改动,其中虚线部分为原图步骤④⑤的走向,本人改为指向灰色部分)。


图2-2


上电初始程序依然从0x08000004处取出复位中断向量地址,执行复位中断函数后跳转到IAP的main(标号①所示),在IAP的main函数执行完成后强制跳转到0x08000004+N+M处(标号②所示),最后跳转到新的main函数中来(标号③所示),当发生中断请求后,程序跳转到新的中断向量表中取出新的中断函数入口地址,再跳转到新的中断服务函数中执行(标号④⑤所示),执行完中断函数后再返回到main函数中来(标号⑥所示)。


对于步骤④⑤,网友认为是:“在main执行的过程中,如果CPU得到一个中断请求,PC指针仍强制跳转到地址0x08000004中断向量表处,而不是新的中断向量表,如图标号④所示,程序再根据我们设置的中断向量表偏移量,跳转到对应中断源新的中断服务程序中,如图标号⑤所示”。我对此的理解是:“当发生中断后,程序从0x08000004(旧)处的中断向量表中得到相应的中断服务函数入口地址,继而跳转到相应的中断服务程序”。但是旧的中断向量列表里边存放的是IAP程序中断函数的入口地址,它是如何得到user程序中断函数的入口地址呢?所以我觉得此种说法是错误的。“当发生中断时PC指针强制会跳转到0x08000004处”这种说法并没有错,只是忽略了后续的一些知识要点而导致这个说法出现矛盾。


对于步骤④⑤我认为的是,在main函数的执行过程中,如果CPU得到一个中断请求,PC指针本来应该跳转到0x08000004处的中断向量表,由于我们设置了中断向量表偏移量为N+M,因此PC指针被强制跳转到0x08000004+N+M处的中断向量表中得到相应的中断函数地址(待求证),再跳转到相应新的中断服务函数,执行结束后返回到main函数中来。


三、实现过程


STM32F103ZET6的Flash地址为0x08000000—0x0807ffff共512KB,把这512KB的空间分为两块,第一块大小为32KB存放BootLoader程序,剩余的空间存放用户程序(根据实际情况分配这两块空间的大小,BootLoader程序占用的空间越小越好,则BootLoader地址为0x08000000—0x08007fff,用户程序地址为0x08008000—0x0807ffff。BootLoader流程图大致应该如下:


1、初始化时钟。


2、初始化中断向量表地址。


3、初始化按键。(使用按键触发方式,上电时如果按键被按下则进行用户程序更新操作)


4、初始化串口。


5、检测按键是否被按下,是则执行步骤6,否则执行步骤10。


6、擦除用户程序(擦除0x08008000—0x0807ffff地址空间Flash)。


7、从串口读取新的用户代码数据,把代码写入用户程序空间。


8、检测串口数据接收完毕?是则执行步骤9,否则跳回步骤7。


9、用户程序更新完毕,等待重新上电或硬件复位。


10、跳转到用户程序(强制将PC指针跳转到0x08008000+4处)。


到这里首先要解决的问题就有:


1、如何进行对STM32的Flash进行擦除和写入操作。


2、中断向量表偏移如何设置。


3、如何改变代码存放的地址空间(因为BootLoader要存放在0x08000000处,用户程序要存放在0x08008000处,而默认的代码存放的地址空间为0x08000000)。


4、怎么进行PC指针的强制跳转,跳转时需要做些什么。


5、串口接收的用户代码数据是什么样的代码数据,是一种什么样的文件。


问题的解决:


1、使用STM32的固件库函数,只需调用几个库函数即可轻松解决,使用的固件库为stm32f10x_flash.c文件,对Flash的操作过程简要为:Flash解锁àFlash擦除àFlash写入àFlash上锁。(对Flash编程的更详细操作参考STM32F10xxx闪存编程手册)


①解锁:


FLASH_Unlock();//解锁Flash


FLASH_SetLatency(FLASH_Latency_2);//因为系统时钟为72M所以要设置两个时钟周期的延时


②擦除:


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


{


if(FLASH_ErasePage(FLASH_ADDR+i*2048)!= FLASH_COMPLETE)//一定要判断是否擦除成功


returnERROR;


}


说明:FLASH_ErasePage(uint32_t Page_Address)即为Flash擦除操作,按页擦除,每页2KB,Page_Address为页的起始地址,如0x08000000是第一页起始地址,0x08000800为第二页起始地址,这里的操作擦除了0x08008000—0x0807ffff地址空间的Flash。


③写入:


unsignedchar buf[1024];//假设待写入的代码数据


unsigned short temp;//临时数据


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


{


temp = (buf[2*i+1]<<8) | buf[2*i];//2个字节整合为1个半字


if(FLASH_ProgramHalfWord(ADDR,temp) != FLASH_COMPLETE)//判断是否写入成功


{


Return ERROR;


}


ADDR +=2;//地址要加2,因为每次写入的是2个字节(1个半字)


}


说明:因为STM32的Flash写入为双字节(1个半字)写入,FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)函数即为对地址为Address写入1个半字的Data,每次写入完成后地址要加2。


④上锁:


FLASH_Lock();//Flash上锁,一个固件库函数即可实现。


2、关于中断向量表的偏移设置,对于BootLoader程序只需设置中断向量表的指向在0x08000000处,对于用户程序需要设置中断向量表的指向在0x08008000处即可。


①在BootLoader程序的中断向量表指向设置中应有这么一句:


NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);//设置中断向量表指向


其中NVIC_VectTab_FLASH是个宏定义,的值为0x08000000。


②在用户程序的中断向量表指向设置用应有这么一句:


NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x8000);//设置中断向量表指向


3、确认代码存放的地址空间,在IAR和在Keil中的设置是不同的,网上有在Keil中设置的方法,设立介绍在IAR软件环境下的设置方法。


①在固件库目录STM32F10x_StdPeriph_Lib_V3.5.0ProjectSTM32F10x_StdPeriph_TemplateEWARM下找到一个stm32f10x_flash.icf文件,将其复制到工程目录中来,在打开IAR工程,将配置文件添加到工程中,如下图3-2所示



图3-1


②在工程中打开stm32f10x_flash.icf该文件,修改两个参数即可改变代码存放的地址空间,图下图3-2所示。


图3-2


4、关于PC指针的强制跳转,想在BootLoader程序中将PC指针跳转到用户代码处,可选择下面的操作


typedefvoid (*pFunction)(void);


pFunctionJump_To_Application;


uint32_tJumpAddress;


#defineApplicationAddress0x08008000


if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)//--------①


{


JumpAddress= *(__IO uint32_t*) (ApplicationAddress + 4);//--------②


Jump_To_Application= (pFunction) JumpAddress;//--------③


__set_MSP(*(__IOuint32_t*) ApplicationAddress);//--------④


Jump_To_Application();//--------⑤


}


①因为用户程序开始位置(0x08008000处)的前4个字节存放的是堆栈的地址,堆栈地址必定是指向RAM空间的,而STM32的RAM空间起始地址为0x20000000,所以要进行判断。


②程序跳转地址的确认,前面已经说过0x08008004处的4个字节存放的是复位函数的入口地址,该句的意思为获得(ApplicationAddress + 4)地址处的数据,即为获得新的复位函数入口地址。


③令Jump_To_Application这个函数指针指向复位函数入口地址。


④堆栈的初始化,重新设定栈顶代地址,把栈顶地址设置为用户代码指向的栈顶地址。


⑤跳转到新的复位函数。


5、通过串口来接收代码数据,就是PC机通过串口将代码数据发送到STM32中去。这里就涉及到两个问题:


①数据怎么得来。


②数据传输的过程需要遵循的协议,什么时候开始,什么时候结束。


解决①:一般我们就将*.hex文件使用JFlash-ARM打开再通过Jlink仿真器烧录到STM32芯片中,但是*.hex文件里边包含的数据不纯粹是代码数据还有一些别的东西,而*.bin文件数据就全部是代码数据。


在IAR软件环境中打开一个用户工程,先设置好中断向量表偏移和代码存放的地址空间后(前面已介绍过这两种方法)。设置工程如下图3-3所示,确认后重新编译工程,在工程的DebugExe目录下会相应生成一个xxx.bin文件,这就是所需要的代码文件。


图3-3


②数据通过串口来传输文件常用的协议有XModem、YModem、ZModem这三种协议,在PC端使用这些协议传输文件只需要PC的超级终端或者终端工具SecureCRT即可,但是在STM32这边的编程会增加一些困难(因为要先去读懂、解析这些协议,在通过编程来实现)。也可选择自己定义一套简单的传输协议,但同样会有一些困难(因为要在PC端进行文件和串口编程)。总之不管通过什么办法都行,只要能将xxx.bin文件数据通过串口全部发送到STM32并且STM32能够全部接收到这些数据并写入Flash即可(我选择后者,自定义传输协议并用VC进行文件和串口编程)。


四、结束语


总的来说STM32的IAP方案实现需要在进行用户程序之前加一段Bootloader程序,BootLoader程序的作用就是:


①什么都不做,直接跳转到用户程序。


②删除原有的用户程序,读取*.bin文件数据并将数据重新写入新的用户程序。


对于用户程序相比普通的编程只需要做三步改动即可


①改变中断向量表。


②改变代码存放的地址空间


③修改生成*.bin文件


使用通过UART的IAP方案并不是很好的选择,这只是IAP方案的一个机制,因为能使用PC机通过串口升级程序,同样能通过Jlink烧写程序,并且自定义的串口通讯协议在没有校CRC校验的情况下不能及时发现数据传输过程发生的错误。这里推荐使用SD卡(或U盘)进行用户程序更新,将*.bin文件复制到SD卡(或U盘)中,STM32再通过读取SD卡(或U盘)的*.bin文件进行用户程序更新,这也避免了STM32与PC笨重的通讯,只需插一个SD卡(或U盘)更显得人性化一些,但需要去弄懂STM32如何与SD卡(或U盘)的通讯。

关键字:IAR环境  STM32  IAP方案 引用地址:IAR环境下STM32+IAP方案的实现

上一篇:STM32 PWM 输出
下一篇:基于STM32 MCU的太阳能:LED街灯解决方案

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

RTOS为什么要搞两种API?
本文以FreeRTOS为例,如果我们自己在官网下载源码然后手动移植代码就是使用FreeRTOS的原生API接口,如果我们使用STM32CubeMX来配置工程就是使用的CMSIS-API接口,是对FreeRTOS的原生API接口进行了封装。 一、RTOS为什么要搞两种API? CMSIS-RTOS API是ARM公司为RTOS内核制定的一套通用接口协议,它提供了一套「标准的API接口」,可以移植到各种各样的RTOS上,使得上层的软件、中间件、库以及其他组件在不同的RTOS之上都可以正常工作。 简单的说就是:STM32是ARM内核的,这大家都知道。FreeRTOS是一种免费的开源的嵌入式操作系统。那它肯定就不属于ARM公司的对不对
[单片机]
RTOS为什么要搞两种API?
STM32——粗谈通信接口设备
在STM32中,其通信接口共有5个,分别是:用于IC间通信的SPI接口和I2C接口、用于控制局域网通信的CAN 总线接口、与PC通信的 USB接口、还有最常见的通用同步/异步串口USART。下面我们来详细介绍一下这5个通信接口在STM32中分别所起的作用。 1. 用于IC间通信的SPI接口 在STM32中,为了能够与其他 IC进行通信,其配备2个SPI接口,并提供高达18 MHz的全双工SPI通信。在这两个SPI接口上,其中有一个SPI设备接口是位于满速为72 MHz的APB2高速总线上,而另外一个SPI设备接口则是位于满速为36 MHz的APB1低速总线上。用户可以对每个 SPI 设备的时钟极性和相位进行定制,其发送数据
[单片机]
基于STM32、FreeRTOS 实现硬件看门狗+软件看门狗监测多任务的方法
我们都知道硬件看门狗的目的:是用来监测系统,防止系统死机,并在死机的情况下使系统复位重启。 在RTOS操作系统中,如果任务(线程)较多,出现高优先级任务长时间占用CPU资源,低优先级任务长时间得不到执行这种想象,那么我们的系统就是具有Bug的系统。 如上描述,假如我们的线程没有死机,只是长时间得不到执行。在这种异常情况下,我们又不希望系统复位,只希望执行特定代码,那我们该如何来避免这种问题呢? Ⅰ关于看门狗 硬件看门狗:利用一个定时器计数电路,其定时输出连接到电路的复位端,程序在一定时间范围内对定时“喂狗”。 因此程序正常工作时,定时器总不能溢出,也就不能产生复位信号。如果程序出现故障,不在定时周期内喂狗,就使得看门
[单片机]
基于<font color='red'>STM32</font>、FreeRTOS 实现硬件看门狗+软件看门狗监测多任务的方法
两个IGBT为什么会出现同时导通的情况呢?
什么是死区时间? 数据手册的参数 如何计算合理的死区时间? STM32中配置死区时间 什么是死区时间? PWM是脉冲宽度调制,在电力电子中,最常用的就是整流和逆变。这就需要用到整流桥和逆变桥。 对三相电来说,就需要三个桥臂。以两电平为例,每个桥臂上有两个电力电子器件,比如IGBT。大致如下图所示; 这两个IGBT不能同时导通,否则就会出现短路的情况,从而对系统造成损害。 那为什么会出现同时导通的情况呢? 因为开关元器件的和严格意义并不是相同的。 所以在驱动开关元器件门极的时候需要增加一段延时,确保另一个开关管完全关断之后再去打开这个开关元器件,通常存在两种情况; 上半桥关断后,延迟一段时间再打开下半桥; 下半桥关断后,延迟一段
[单片机]
两个IGBT为什么会出现同时导通的情况呢?
STM32 FreeRTOS Keil环境搭建
由于FreeRTOS的官方已经支持STM32F1X系列的Cortex-M3的移植,所以只需要在Keil IDE中设置相关即可了; 在Keil中新建一工程,在工程中新建3个组,分别对应3个目录用来存放:user、rtos、stmlib user中添加用户自己的代码和头文件; rtos中添加rots的文件主要有:list.c、task.c、queue.c、head_2.c、port.c stmlib中添加STM32官方提供的STM32操作的lib库(注意stm32f10x_md.s中的内容和替换为FreeRTOS Demo 中的STM32F10X.s否则系统调度不能正常工作) 另外需要把FreeRTOS/source/inc
[单片机]
STM32的RTC晶振不起振的可能原因?
最近做的几块板子也用到了STM32的RTC,前后两版一共做了大概6片,幸运的是并未遇到晶振不起振的现象。而我采用的是3毛钱一个的普通晶振,并未选用传说中低负载高精度晶振。。。后来在另外一片实验性质的板子上首次遇到了晶振不起振的问题,而且做了2片都不起振,这才让我意识到这个问题的严重性。 从上述现象来看,我认为对RTC晶振起振影响最大的因素应该是PCB的布线。但是遇到问题时通常是PCB已做好,甚至已经做了几百块,没有回头路了。于是大家更关注的问题似乎就是“如何补救”了。在网上搜索一下,你就会发现世界是如此美好!每个人的经验和建议都不一样,甚至是完全相反的!这种现象告诉我们,除了PCB布线,对晶振起振影响最大的似乎不是电气参数,而
[单片机]
STM32的DAC加TIMER应用演示
现在有如下图所示的这样一个需求,希望使用 STM32 芯片 来实现。 横轴表示时间,纵轴表示电压【3.3v为限】,不同时刻的电压输出不一样、持续时间也不尽相同。 此问题源于某高校STM32学习时的习题,这里拿出来一起交流探讨下。方法不是唯一的,尤其基于不同STM32系列。这里尽量使用通用、常规的方法,算是抛砖引玉。 显然,我们可以考虑使用STM32的 DAC 加 TI MER以及片内其它资源加以实现。 对于这个实现我们可以分两种方式完成,每一种方式同时也体现不同难度。 我们可以考虑下面两种应用情形: 第一种方式: MCU 除了做这一件事外,还做点别的,比方做按键响应、 ADC 采样这些,整体上没有太复杂的功能和要求。【中断
[单片机]
<font color='red'>STM32</font>的DAC加TIMER应用演示
基于STM32的多种printf用法 你都知道吗?
在调试代码的时候,最常用的就是使用printf函数来输出一些打印信息,提示自己代码的执行情况。 如果你的UART串口不够用,还要用printf,此时该怎么办? 方法其实是有的,那就是:使用SWO/SWV。 SWO:Serial Wire Output,串行线输出 SWD:Serial Wire Viewer,串行线查看器 一、常见printf输出 1.UART打印 这种使用UART串口输出,需要占用一个 硬件 串口。 2. Keil MDK- ARM Viewer输出 3.IAR EWARM终端输出 4.ST-LINK U ti lity SWV输出 这后面三种不占用硬件UART,使用ITM机制。 二、UA
[单片机]
基于<font color='red'>STM32</font>的多种printf用法 你都知道吗?
热门资源推荐
热门放大器推荐
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

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

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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