您的位置:首页 > 其它

STM32 IAP

2015-06-17 20:18 225 查看
最近一直在看IAP的东西,总结了一写东西,但是具体的东西还没有尝试。先来说具体的问题

我想要的是可以通过无线来下载程序。思想是,首先在单片机中烧入一段程序,称之为bootloader,这段程序的目的是接收串口数据并且将数据写到flash指定的位置。但是现在我碰到了一些问题,首先是flash,不知道该如何操作,其次是如何从bootloader跳到APP。

首先来说一下如何操作内部flash

flash只能写入16位的数据,不能写8位或32的,如果写入8位的数据可以将高8位补零,凑成16位数据。并且每次写之前都要擦除一个扇区的数据,所以,如果要写的话就要先将扇区的数据存到缓冲区。然后在进行擦除。具体的代码可以参照官方例程。



再来解释一下IAP编程。

IAP简单的说就是通过第一段程序来烧录第二段程序,但是其中有些配置需要了解

第一是启动方式。先来看看STM32的三种介质启动方式

User Flash = 芯片内置的Flash。

SRAM = 芯片内置的RAM区,就是内存啦。

System Memory = 芯片内部一块特定的区域,芯片出厂时在这个区域预置了一段Bootloader,就是通常说的ISP程序,这个区域的内容在芯片出厂后没有人能够修改或擦除,即它是一个ROM区。

不同的boot设置将会由不同的启动方式

BOOT1=x  BOOT0=0  从用户闪存启动,这是正常的工作模式。
BOOT1=0  BOOT0=1  从系统存储器启动,这种模式启动的程序功能由厂家设置。(用于串口ISP)
BOOT1=1  BOOT0=1  从内置SRAM启动,这种模式可以用于调试。


下面都是针对flash的IAP编程,你也可以SRAM启动

先来上个图,看看内存映射这个主要看看各个地址,其中SRAM的起始地址为0x20000000,内部flash 是从0x0800 0000开始 到0x0801 FFFF 结束,0x0801FFFF-0x0800 0000= 0x20000 =128k 128也就是flash的大小。



下面这个图是APP和IAP在flash中的空间分配。我们12k的空间来存IAP程序,其余的空间用作存主要的功能APP。



再来看看程序是如何启动的。

下面这个图示是截过来的,用来说明程序是如何启动的

(来自http://www.openedv.com/posts/list/11494.htm



在启动后,CPU从地址0x00000000(通过映射,即使从0x08000000)获取堆栈顶的地址,并从启动存储器的0x00000004(通过映射,即使从0x08000000 + 4)指示的地址开始执行程序。这就是为什么启动代码的第一个中断向量存放的是堆栈的基地址,第二个中断向量才是复位处理函数。执行完复位函数后就来到了C的世界。

再来看看加了IAP后的程序,用来说明程序如何跳转。



其中有一点需要说明,就是关于中断的问题,如果新的程序触发了中断,那PC将会指到哪里呢。

如果CPU得到一个中断请求,PC指针仍强制跳转到地址0X08000004中断向量表处,而不是新程序的中断向量表;程序再根据我们设置的中断向量表偏移量,跳转到对应中断源新的中断服务程序中,如图标号⑤所示;在执行完中断服务程序后,程序返回main函数继续运行


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


我觉得第二种解释更能接受。我始终不明白当PC指到0X08000004中断向量表处的时候是如何得到新的程序的中断服务函数的地址的。因为在bootloader中并没有关于新程序位置的信息,我们中断向量表的偏移是在新程序设定的。所以我觉得应该就是PC本来要指向0X08000004中断向量表处,但是程序中先计算了一下,(因为我们已经设置了偏移量),然后直接指向新程序的中断向量表。尽管这么说,但是我还是不知道中断是如何找到中断服务函数的。也不知道设置不同的rom起始地址会不会改变启动代码。

那么下面看一下代码,IAP是如何跳转到APP的

/* Test if user code is programmed starting from address "ApplicationAddress" */
if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)
{ /* Jump to user application */
JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
Jump_To_Application = (pFunction) JumpAddress;
/* Initialize user application's Stack Pointer */
__set_MSP(*(__IO uint32_t*) ApplicationAddress);
Jump_To_Application();
}


if (((*(__IO uint32_t*)ApplicationAddress) & 0x2FFE0000 ) == 0x20000000)
{
}
/*
这句的意思是检查是否新程序的栈顶在0x20000000与0x2001FFFF之间,即栈顶是不是在以0x20000000开始的128K的范围内,这里便是STM32的RAM区域,虽然现在最大的只有64k
*/


JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);
/*
这句的意思是获得新程序的地址,ApplicationAddress位新程序的栈顶地址,ApplicationAddress+4即使新程序的启动地址,即复位处理函数地址。
*/


Jump_To_Application = (pFunction) JumpAddress;
/*
将启动地址转换成函数地址
*/


具体的设置可以参考原子的IAP操作
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: