STM32F4-IAP学习笔记(二)

原创 2017年01月03日 19:21:27

啰嗦两句

之前我们分析了IAP的基本工作原理和编程应该注意的细节问题,接着上篇,我们来看看具体的编码问题。

正文

上篇基本将IAP工作的机理和程序组成以及运行路程分析过了,所以我们只看看关键模块的编码。
首先分析IAP,关键模块有三部分:通讯,FLASH操作,引导跳转。

一、通讯

我们先来谈谈通讯问题。可以将,无论什么通讯,都可以完成代码的传输,USART也好,USB也好,CAN也好,等等,只要是通讯外设,你都可以用来传输外设,但是考虑到实用性,也许USART是简单也是最最常用的。我们以就以USART为例来讲通讯。
文件的传输一定要稳定,传输过程中不可以丢数据,否则传输的文件就有问题,导致最后的APP程序存在问题。所以我们使用USART时需要选择合适波特率,要尽量大保证传输速率,但又不能太大导致丢帧。然后开启中断在中断将接收到的数据存放到一个数组里即可,随后处理即可。编码相信大家都会,就不在这里复述了。

二、FLASH操作

我们需要将接受到的APP程序写到合适的FLASH地址,以便后面引导启动。
首先应该明确STM32F4的FLASH地址为0x08000000-0x080FFFFF,若果越过这个空间写肯定是有问题的。下面我们看看FLASH写入的步骤。

1.校验写入地址有效性

//写入地址必须处于FLASH区间并且地址为4的倍数【按字写入】

if(WriteAddr < FLASH_BASEADDR || WriteAddr%4)   //addr error
        return ;

2.FLASH解锁,缓冲区除能

//必须要解锁FLASH并保证数据缓存处于关闭状态才可以进行FLASH写入

FLASH_Unlock();                         //ready to clear sector
FLASH_DataCacheCmd(DISABLE);

3.判断是否要擦除缓冲区

//当指定地址内数据不为OXFFFFFFFF时,我们需要擦除这个地址内的内容以便我们重新写入,这里要注意的是我们擦除的时候是以整个扇区为单位擦除的,所在扇区内容都会消失,这就是我们之前为什么建议大家将伪BOOT放在单独的扇区进行处理的原因

if(FLASH_ReadWord(AddStart) != 0XFFFFFFFF)
{
    FlashStatus = FLASH_EraseSector(FLASH_GetFlashSector(AddStart), VoltageRange_3);// vcc = 2.7~3.6v
    if(FlashStatus != FLASH_COMPLETE)
        break;//error
}

4.重写【我们通过串口或其他外设接收到的数据为八位,而FLASH操作要求按字写入,所以这块一定要注意数据的转化】

//调用系统函数重新将数据按字写入

while(WriteAddr < AddEnd)
    {
        if(FLASH_ProgramWord(WriteAddr, *pBuffer)!= FLASH_COMPLETE)
            break;//error

        WriteAddr += 4;
        pBuffer++;
    }           

4.失能缓存,FLASH上锁,完成写入操作


FLASH_DataCacheCmd(ENABLE);                     //write flash finsh
FLASH_Lock();

到这里我们的FLASH写入模块算是完成了,主要抓住FLASH操作的核心便可以完成FLASH的写入操作。

三、引导跳转

引导跳转的核心步骤有两步:

1.地址空间有效性校验

if(((*(vu32*) LoadAddr)&0x2FFE0000) == 0x20000000)      //check the addr of StackTop
  • 我们来分析一下这句代码。LoadAddr为我们伪BOOT接收到的代码数据的第一个字,我们会想一下上篇文章提到的,正常下载一个程序到FLASH后存储在0x08000000的是一个什么数据?用户堆栈地址!对!就是用户堆栈地址。我们的LoadAddr也是接收到用户程序代码的第一个字,本来也是存放在0x08000000地址空间内的,只不过现在被我们接收进行处理了,所以我们的LoadAddr就是接收到的程序的用户地址空间那么这句话很显然了,取LoadAddr空间内存放的数据,这是什么?这就是用户地址空间栈顶指针 然后&0x2FFE0000和0x20000000判等。我们先来看看为什么要用栈顶指针和0x2FFE0000。上篇文章我们提到过STM32F4的SRAM空间范围为0x20000000-0X2001FFFF共128KB,当用栈顶指针&0x2FFE0000后,我们忽略了低十六位,我们只关心栈顶指针高十六位是否在0x2000-0x2002之间,也就是SRAM空间。这就是栈顶指针的校验。换句话说,让程序的栈顶指针在SRAM时,我们便可以认为这是有效的栈顶指针。

2.保存复位中断向量

typedef void(*LoadAddrFunVar)(void);
//...
LoadAddrFunVar StartLoad;
//...
StartLoad = (LoadAddrFunVar)*(vu32*)(LoadAddr+4);   //load the addr
  • 我们知道栈顶指针往后偏移四个字节便是复位中断向量的位置,这行代码的意思就是定义一个函数指针,并将这个函数指针指向复位中断向量,我们通过调用函数的调用便可以实现复位中断的执行,进而进行程序复位。

3.将用户堆栈指针指向用户堆栈栈顶

//set Main Stack value
__asm void MSR_MSP(u32 addr) 
{
    MSR MSP, r0             
    BX LR
}
//...
MSR_MSP(*(vu32*)LoadAddr);  
  • 这里调用了ARM的汇编指令,通过MSP指令将刚才校验过的堆栈栈顶地址赋值给用户堆栈寄存器MSP,然后返回。这一步很关键,相当于对新APP的用户堆栈重新构建,保证堆栈的正确性。

4.引导跳转

StartLoad();                                        //start
  • 即调用刚才的函数,使程序跳转到复位中断,执行系统复位操作。如此一来,系统便会复位重新启动,只不过此时不再加载0X08000000处的代码,而是加载你刚才制定地址的代码,此刻我们就完成了IAP的引导工作。

那么,我们的APP程序该怎么编写呢?
其实我们的APP程序和我们平时写的程序没有任何区别,唯独要增加两个工作:

  1. 设置对应的ROM空间
  2. 中断向量表重定向

我们首先需要通过KEIL->Options->Target->IROM1设置我们的APP程序需要写入的FLASH空间
这里写图片描述

一般来讲,这个空间可以设置成为我们之前的引导程序所占空间之外其余的任何FLASH空间,但是我们设置的时候需要考虑:

  1. 避免烧写到引导程序所在扇区
  2. 地址必须为0X200倍数【76个中断向量所占空间的扩展到2的整数次幂,否则覆盖某个APP中断向量代码空间】
  3. APP大小

比如图中我将APP写入到了扇区1【引导后面的扇区】,Size设置成剩余的FLASH大小。这是没有问题的。

还有很重要的一步便是中断向量表重定向,原因在上篇文章里已经讲过,这里我们看看具体怎么操作。
STM32提供了中断向量表的偏移设置寄存器SCB->VTOR,我们可以在程序开始的时候调用它完成重定向,也可以调用函数NVIC_SetVectorTable()完成中断向量表的重定向。

SCB->VTOR = (FLASH_BASE |0x4000);
//or
NVIC_SetVectorTable(FLASH_BASE,0x4000);

这里的0x4000就是我代码写入FLASH地址0x08004000相对于FLASH_BASE[0x08000000]的偏移量。

那么我们的APP程序写好了,如何传输呢?
这里要强调一下我们需要使用keil自带的fromelf.exe,将编译连接后生成的axf文件转化为可以直接写入FLASH的二进制数据文件——.bin文件。只有将程序转化为存储器中直接存储的二进制文件,才能不经过任何处理写入到存储器后运行,而hex和axf文件则不满足要求。如何使用fromelf.exe呢?我们点击option->User->After Build/Rebuild,勾选RUN#1,后面输入

//根据实际情况修改keil安装目录和链接输出文件夹位置
keil安装目录\KEIL\ARM\ARMCC\bin\fromelf.exe --bin -o  ..\OBJ\FileName.bin ..\OBJ\FileName.axf

这样我们在build或者rebuild后会执行这段代码,使用fromelf工具将axf转化为bin文件。然后通过串口助手将bin文件发送到开发板就ok啦。

这样,我们整个IAP从boot到APP都基完成啦~

总结一哈

以上就是IAP的完整的学习笔记啦~笔记1主要分享了IAP的工作和引导机理,笔记2主要进行了关键代码解析。写完这两篇,个人对STM32的启动,程序加载,存储器存储有了更深的了解,相信大家也对学到了不少知识。以上内容纯属个人见解,如果大家发现有什么不对的地方,欢迎指正哈~

最后,贴上自己的IAP程序,依靠USART控制,亲测可行。http://download.csdn.net/detail/zat907943815/9728130

版权声明:本文为博主原创文章,未经博主允许不得转载。

STM32F4-IAP学习笔记(一)

啰嗦两句花了断断续续两天时间在STM32上面写了一个IAP(In Application Programing)Boot,期间多多少少还是遇到的了不少问题。现在就花点时间把这两天写的东西整理一下,就当...

STM32IAP升级------IAP升级功能编写初期的一些困惑与疑问---完成功能后的总结

IAP升级功能编写初期的一些困惑与疑问---完成功能后的总结 一,网上下载的例程,跳转部分的代码有差异,尤其是用的汇编那句 二,关于跳转部分的代码的理解(转) 三,关于跳转时能否不用按键,用软件标志位...

STM32IAP升级-----编写IAP升级遇到的问题总结

编写IAP升级遇到的问题总结 一,串口通信问题 二,FLASH问题 三,数组越界问题 四,关于APP与IAP互跳之间的中断处理问题 五,总结一下在IAP升级中APP程序的中断向量表的偏移...

STM32 IAP 在线升级详解

一、在进入主题之前我们先了解一些必要的基础知识----stm32系列芯片的种类和型号: startup_stm32f10x_cl.s 互联型的器件,STM32F105xx,STM32F107xx ...

怎么使用stm32写IAP的bootloader和APP

Stm32的bootloader和App的编写注意事项 1、 怎么分配bootloader和app的空间 2、 怎么得到数据和写入flash 3、 怎么从bootloader跳转到app 4、...

STM32F4串口IAP固件更新

STM32F4串口IAP固件更新操作过程: 修改ST官方IAP程序,使之能在自己的开发板跑起来,关键是串口、按键和led。在程序运行前,建议按下按键,程序进入IAP程序。当超级终端上显示选项时,选...

记录一次stm32F429 IAP跳转到SDRAM内执行程序的DEBUG过程

stm32在sdram内运行用户程序
  • lrmlrm
  • lrmlrm
  • 2016年05月12日 11:20
  • 3274

基于STM32F429的IAP升级(HAL库/RS485)

最近一周一直在基于STM32F429项目的IAP工程,耗时4天才完成,得空记录下来。文章主要涵盖了以下几点: 1. IAP是什么? 2. bin文件和hex文件的差别 3. ymodem协议介绍及其缺...

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

STM32F0xx IAP实现之中断向量表重定义

在STM32F103等cortex-m3/m4内核的单片机上可以通过设置SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET;该寄存器的值来实现中断向量表的重定义。但在ST...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:STM32F4-IAP学习笔记(二)
举报原因:
原因补充:

(最多只允许输入30个字)