做亚马逊美国卖什么产品好

IAP(In Application Programming)即在应用编程,IAP是用户自己的程序在运行过程中对User Flash的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级。&通常实现IAP功能时,即用户程序运行中作自身的更新操作,需要在设计固件程序时编写两个项目代码,
第一个项目程序不执行正常的功能操作,而只是通过某种通信方式(如USB、USART)接收程序或数据,执行对第二部分代码的更新;第二个项目代码才是真正的功能代码。这两部分项目代码都同时烧录在User Flash中,当芯片上电后,首先是第一个项目代码开始运行,它作如下操作:&  
1)检查是否需要对第二部分代码进行更新&  
2)如果不需要更新则转到4)&  
3)执行更新操作&  
4)跳转到第二部分代码执行&  
第一部分代码必须通过其它手段,如JTAG或ISP烧入;第二部分代码可以使用第一部分代码IAP功能烧入,也可以和第一部分代码一起烧入,以后需要程序更新是再通过第一部分IAP代码更新。& 
我们将第一个项目代码称之为Bootloader程序,第二个项目代码称之为APP程序,他们存放在STM32 FLASH的不同地址范围,一般从最低地址区开始存放Bootloader,
紧跟其后的就是APP程序(注意,如果FLASH容量足够,是可以设计很多APP程序的,本章我们只讨论一个APP程序的情况)。这样我们就是要实现2个程序:Bootloader和APP。 
STM32的APP程序不仅可以放到FLASH里面运行,也可以放到SRAM里面运行,本章,我们将制作两个APP,一个用于FLASH运行,一个用于SRAM运行。
我们先来看看STM32正常的程序运行流程,如图48.1.1所示:
图48.1.1 STM32正常运行流程图
&&&&&&&STM32的内部闪存(FLASH)地址起始于0x,一般情况下,程序文件就从此地址开始写入。此外STM32是基于Cortex-M3内核的微控制器,其内部通过一张“中断向量表”
来响应中断,程序启动后,将首先从“中断向量表”取出复位中断向量执行复位中断程序完成启动,而这张“中断向量表”的起始地址是0x,当中断来临,STM32的内部硬
件机制亦会自动将PC指针定位到“中断向量表”处,并根据中断源取出对应的中断向量执行中断服务程序。
&&&&&&&在图48.1.1中,STM32在复位后,先从0X地址取出复位中断向量的地址,并跳转到复位中断服务程序,如图标号①所示;在复位中断服务程序执行完之后,会跳转到我们
的main函数,如图标号②所示;而我们的main函数一般都是一个死循环,在main函数执行过程中,如果收到中断请求(发生重中断),此时STM32强制将PC指针指回中断向量表处,如图标号③所示;然后,根据中断源进入相应的中断服务程序,如图标号④所示;在执行完中断服务程序以后,程序再次返回main函数执行,如图标号⑤所示。
&&&&&&&当加入IAP程序之后,程序运行流程如图48.1.2所示:
&&&&&&&在图48.1.2所示流程中,STM32复位后,还是从0X地址取出复位中断向量的地址,并跳转到复位中断服务程序,在运行完复位中断服务程序之后跳转到IAP的main函数,
如图标号①所示,此部分同图48.1.1一样;在执行完IAP以后(即将新的APP代码写入STM32的FLASH,灰底部分。新程序的复位中断向量起始地址为0X;N+M),跳转至
新写入程序的复位向量表,取出新程序的复位中断向量的地址,并跳转执行新程序的复位中断服务程序,随后跳转至新程序的main函数,如图标号②和③所示,同样main函数为一个
死循环,并且注意到此时STM32的FLASH,在不同位置上,共有两个中断向量表。
&&&&&&&在main函数执行过程中,如果CPU得到一个中断请求,PC指针仍强制跳转到地址0X中断向量表处,而不是新程序的中断向量表,如图标号④所示;程序再根据我们设置
的中断向量表偏移量,跳转到对应中断源新的中断服务程序中,如图标号⑤所示;在执行完中断服务程序后,程序返回main函数继续运行,如图标号⑥所示。
&&&&&&&通过以上两个过程的分析,我们知道IAP程序必须满足两个要求:
1)&&新程序必须在IAP程序之后的某个偏移量为x的地址开始;
2)&&必须将新程序的中断向量表相应的移动,移动的偏移量为x;
本章,我们有2个APP程序,一个为FLASH的APP,程序在FLASH中运行,另外一个位SRAM的APP,程序运行在SRAM中,图48.1.2虽然是针对FLASH APP来说的,但是在
SRAM里面运行的过程和FLASH基本一致,只是需要设置向量表的地址为SRAM的地址。
1.APP程序起始地址设置方法
随便打开一个之前的实例工程,点击Options for TargetàTarget选项卡,如图48.1.3所示:
图48.1.3 FLASH APP Target选项卡设置
&&&&&&&默认的条件下,图中IROM1的起始地址(Start)一般为0X,大小(Size)为0X80000,即从0X开始的512K空间为我们的程序存储(因为我们的STM32F103ZET6的
FLASH大小是512K)。而图中,我们设置起始地址(Start)为0X,即偏移量为0X10000(64K字节),因而,留给APP用的FLASH空间(Size)只有0X00=0X70000
(448K字节)大小了。设置好Start和Szie,就完成APP程序的起始地址设置。
&&&&&&&这里的64K字节,需要大家根据Bootloader程序大小进行选择,比如我们本章的Bootloader程序为22K左右,理论上我们只需要确保APP起始地址在Bootloader之后,
并且偏移量为0X200的倍数即可(相关知识,请参考:)。这里我们选择64K(0X10000)字节,留了一些余量,方便Bootloader以后的升级修改。
&&&&&&&这是针对FLASH APP的起始地址设置,如果是SRAM APP,那么起始地址设置如图48.1.4所示:
图48.1.4 SRAM APP Target选项卡设置
&&&&&&&这里我们将IROM1的起始地址(Start)定义为:0X,大小为0XA000(40K字节),即从地址0X偏移0X1000开始,存放APP代码。因为整个STM32F103ZET6的
SRAM大小为64K字节,所以IRAM1(SRAM)的起始地址变为0Xx;0xA000=0X),大小只有0X5000(20K字节)。这样,整个STM32F103ZET6的SRAM
分配情况为:最开始的4K给Bootloader程序使用,随后的40K存放APP程序,最后20K,用作APP程序的内存。这个分配关系大家可以根据自己的实际情况修改,不一定和我们这里的设
置一模一样,不过也需要注意,保证偏移量为0X200的倍数(我们这里为0X1000)。
&&&&&&&2.中断向量表的偏移量设置方法
&&&&&&&之前我们讲解过,在系统启动的时候,会首先调用systemInit函数初始化时钟系统,同时systemInit还完成了中断向量表的设置,我们可以打开systemInit函数,看看函数体的结尾处有这样几行代码:
#ifdef VECT_TAB_SRAM
SCB-&VTOR = SRAM_BASE | VECT_TAB_OFFSET;
&/* Vector Table Relocation in Internal SRAM. */
SCB-&VTOR = FLASH_BASE | VECT_TAB_OFFSET;
/* Vector Table Relocation in Internal FLASH. */
从代码可以理解,VTOR寄存器存放的是中断向量表的起始地址。默认的情况VECT_TAB_SRAM是没有定义,所以执行SCB-&VTOR = FLASH_BASE | VECT_TAB_OFFSET;&&
对于FLASH APP,我们设置为FLASH_BASE+偏移量0x10000,所以我们可以在FLASH APP的main函数最开头处添加如下代码实现中断向量表的起始地址的重设:
SCB-&VTOR = FLASH_BASE | 0x10000;
&&&&&&&以上是FLASH APP的情况,当使用SRAM APP的时候,我们设置起始地址为:SRAM_bASE+0x1000,同样的方法,我们在SRAM APP的main函数最开始处,添加下面代码:
SCB-&VTOR = SRAM_BASE | 0x1000;
&&&&&&&这样,我们就完成了中断向量表偏移量的设置。
通过以上两个步骤的设置,我们就可以生成APP程序了,只要APP程序的FLASH和SRAM大小不超过我们的设置即可。不过MDK默认生成的文件是.hex文件,并不方便我
们用作IAP更新,我们希望生成的文件是.bin文件,这样可以方便进行IAP升级(至于为什么,请大家自行百度HEX和BIN文件的区别!)。这里我们通过MDK自带的格式转换
工具fromelf.exe,来实现.axf文件到.bin文件的转换。该工具在MDK的安装目录\ARM\BIN40文件夹里面。
fromelf.exe转换工具的语法格式为:fromelf [options] input_file。其中options有很多选项可以设置,详细使用请参考光盘《mdk如何生成bin文件.pdf》.
本章,我们通过在MDK点击Options for TargetàUser选项卡,在Run User Programs After Build/Rebuild&栏,勾选Run#1和DOS16,并写入:D:\Keil3.80a\ARM\BIN40\fromelf.exe&&--bin -o&&..\OBJ\TEST.bin ..\OBJ\TEST.axf&,如图48.1.6所示:
&&&&&&&通过这一步设置,我们就可以在MDK编译成功之后,调用fromelf.exe(注意,我的MDK是安装在D:\Keil3.80A文件夹下,如果你是安装在其他目录,请根据你
自己的目录修改fromelf.exe的路径),根据当前工程的TEST.axf(如果是其他的名字,请记住修改,这个文件存放在OBJ目录下面,格式为xxx.axf),生成一个
TEST.bin的文件。并存放在axf文件相同的目录下,即工程的OBJ文件夹里面。在得到.bin文件之后,我们只需要将这个bin文件传送给单片机,即可执行IAP升级。
&&&&&&&最后再来APP程序的生成步骤:
1)&设置APP程序的起始地址和存储空间大小
对于在FLASH里面运行的APP程序,我们可以按照图48.1.3的设置。对于SRAM里面运行的APP程序,我们可以参考图48.1.4的设置。
2)&设置中断向量表偏移量
这一步按照上面讲解,重新设置SCB-&VTOR的值即可。
3)&设置编译后运行fromelf.exe,生成.bin文件.
通过在User选项卡,设置编译后调用fromelf.exe,根据.axf文件生成.bin文件,用于IAP更新。&
以上3个步骤,我们就可以得到一个.bin的APP程序,通过Bootlader程序即可实现更新。
大家可以打开我们光盘的两个APP工程,熟悉这些设置。
本章实验(Bootloader部分)功能简介:开机的时候先显示提示信息,然后等待串口输入接收APP程序(无校验,一次性接收),在串口接收到APP程序
之后,即可执行IAP。如果是SRAM APP,通过按下KEY0即可执行这个收到的SRAM APP程序。如果是FLASH APP,则需要先按下WK_UP按键,将串口接
收到的APP程序存放到STM32的FLASH,之后再按KEY2既可以执行这个FLASH APP程序。通过KEY1按键,可以手动清除串口接收到的APP程序。DS0用于指示程序运行状态。
本实验用到的资源如下:
1)&&指示灯DS0
2)&&四个按键(KEY0/KEY1/KEY2/WK_UP)
4)&&TFTLCD模块
这些用到的硬件,我们在之前都已经介绍过,这里就不再介绍了。
本章,我们总共需要3个程序:1,Bootloader;2,FLASH APP;3)SRAM APP;其中,我们选择之前做过的RTC实验(在第二十章介绍)来做为FLASH APP程序
(起始地址为0X),选择触摸屏实验(在第三十一章介绍)来做SRAM APP程序(起始地址为0X)。Bootloader则是通过TFTLCD显示实验(在第
十八章介绍)修改得来。本章,关于SRAM APP和FLASH APP的生成比较简单,我们就不细说,请大家结合光盘源码,以及48.1节的介绍,自行理解。本章软件设计仅针对Bootloader程序。
打开本实验工程,可以看到我们增加了IAP组,在组下面添加了iap.c文件以及其头文件isp.h。打开iap.c,&代码如下:
#include &sys.h&
#include &delay.h&
#include &usart.h&
#include &stmflash.h&
#include &iap.h&&&&&&&
iapfun jump2
u16 iapbuf[1024];
//appxaddr:应用程序的起始地址
//appbuf:应用程序CODE.
//appsize:应用程序大小(字节).
void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 appsize)
&&&&&&&u16
&&&&&&&u16 i=0;
&&&&&&&u16
&&&&&&&u32 fwaddr=//当前写入的地址
&&&&&&&u8 *dfu=
&&&&&&&for(t=0;t&t+=2)
&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&temp=(u16)dfu[1]&&8;
&&&&&&&&&&&&&&temp+=(u16)dfu[0];&&&&&&&
&&&&&&&&&&&&&&dfu+=2;//偏移2个字节
&&&&&&&&&&&&&&iapbuf[i++]=&&&&&
&&&&&&&&&&&&&&if(i==1024)
&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&i=0;
&&&&&&&&&&&&&&&&&&&&&STMFLASH_Write(fwaddr,iapbuf,1024);&&&
&&&&&&&&&&&&&&&&&&&&&fwaddr+=2048;//偏移*8.所以要乘以2.
&&&&&&&&&&&&&&}
&&&&&&&if(i)STMFLASH_Write(fwaddr,iapbuf,i);//将最后的一些内容字节写进去.&
//跳转到应用程序段
//appxaddr:用户代码起始地址.
void iap_load_app(u32 appxaddr)
&&&&&&&if(((*(vu32*)appxaddr)&0x2FFE0000)==0x)&&&&&&//检查栈顶地址是否合法.
&&&&&&&&&&&&&&jump2app=(iapfun)*(vu32*)(appxaddr+4);&&&&&&&&
//用户代码区第二个字为程序开始地址(复位地址)&&&&&&&&&
&&&&&&&&&&&&&&MSR_MSP(*(vu32*)appxaddr);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
&&&&&&&&&&&&&&jump2app();&&&&//跳转到APP.
&&&&&&&该文件总共只有2个函数,其中,iap_write_appbin函数用于将存放在串口接收buf里面的APP程序写入到FLASH。iap_load_app函数,则用于跳转到APP程序运行,
其参数appxaddr为APP程序的起始地址,程序先判断栈顶地址是否合法,在得到合法的栈顶地址后,通过MSR_MSP函数(该函数在sys.c文件)设置栈顶地址,
最后通过一个虚拟的函数(jump2app)跳转到APP程序执行代码,实现IAPàAPP的跳转。
&&&&&&&打开iap.h代码如下:
#ifndef __IAP_H__
#define __IAP_H__
#include &sys.h&&&&
typedef&&void (*iapfun)(void);&&&&&//定义一个函数类型的参数.&&
#define FLASH_APP1_ADDR&&&&&&&&&&&&0x&&&&&&
//第一个应用程序起始地址(存放在FLASH)
//保留0XX0800FFFF的空间为Bootloader使用&&&&&
void iap_load_app(u32 appxaddr);&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&//跳转到APP程序执行
void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 applen);&&&//在指定地址开始,写入bin
&&&&&&&这部分代码比较简单,。本章,我们是通过串口接收APP程序的,我们将usart.c和usart.h做了稍微修改,在usart.h中,我们定义USART_REC_LEN为55K字节,
也就是串口最大一次可以接收55K字节的数据,这也是本Bootloader程序所能接收的最大APP程序大小。然后新增一个USART_RX_CNT的变量,用于记录接收到
的文件大小,而USART_RX_STA不再使用。打开usart.c,可以看到我们修改USART1_IRQHandler部分代码如下:
//串口1中断服务程序
//注意,读取USARTx-&SR能避免莫名其妙的错误&&&&&&&
u8 USART_RX_BUF[USART_REC_LEN] __attribute__ ((at(0X)));
//接收缓冲,最大USART_REC_LEN个字节,起始地址为0X.&&&
//接收状态
//bit15,&接收完成标志
//bit14,&接收到0x0d
//bit13~0,&&&&&接收到的有效字节数目
u16 USART_RX_STA=0;&&&&&&&&&&&&&&//接收状态标记&&&&&&
u16 USART_RX_CNT=0;&&&&&&&&&&&&&&&&&&&//接收的字节数&&&&&&
void USART1_IRQHandler(void)
&&&&&&&u8&&&&
#ifdef OS_CRITICAL_METHOD
//如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.
&&&&&&&OSIntEnter();&&&
&&&&&&&if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//接收到数据
&&&&&&&{&&&&
&&&&&&&&&&&&&&res=USART_ReceiveData(USART1);
&&&&&&&&&&&&&&if(USART_RX_CNT&USART_REC_LEN)
&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&USART_RX_BUF[USART_RX_CNT]=
&&&&&&&&&&&&&&&&&&&&&USART_RX_CNT++;&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&}
#ifdef OS_CRITICAL_METHOD&&&&&&
//如果OS_CRITICAL_METHOD定义了,说明使用ucosII了.
&&&&&&&OSIntExit();&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&这里,我们指定USART_RX_BUF的地址是从0X开始,该地址也就是SRAM APP程序的起始地址!然后在USART1_IRQHandler函数里面,将串口发
送过来的数据,全部接收到USART_RX_BUF,并通过USART_RX_CNT计数。代码比较简单,我们就不多说了。
最后我们看看main函数如下:
int main(void)
{&&&&&&&&&&&
&&&&&&&u8 t,
&&&&&&&u16 oldcount=0;&&&&&//老的串口接收数据值
&&&&&&&u16 applenth=0;&&&&&//接收到的app代码长度
&&&&&&&u8 clearflag=0;
&&&&&&&uart_init(256000);&&&&&&//串口初始化为256000
&&&&&&&delay_init();&&&&&&&&&&&&&&&//延时初始化
&&&&&&&LCD_Init();&&&&&&&&&&&&//液晶初始化
&&&&&&&LED_Init();&&&&&&&&&&&&&&&&&//初始化与LED连接的硬件接口
&&&&&&KEY_Init();&&&&&&&&&&&&&&&&&&//按键初始化&&&&&&&
POINT_COLOR=RED;//设置字体为红色
&&&&&&&LCD_ShowString(60,50,200,16,16,&Warship STM32&);&&&&
&&&&&&&LCD_ShowString(60,70,200,16,16,&IAP TEST&);&&&&&
&&&&&&&LCD_ShowString(60,90,200,16,16,&ATOM@ALIENTEK&);
&&&&&&&LCD_ShowString(60,110,200,16,16,&&);&
&&&&&&&LCD_ShowString(60,130,200,16,16,&WK_UP:Copy APP2FLASH&);
&&&&&&&LCD_ShowString(60,150,200,16,16,&KEY1:Erase SRAM APP&);
&&&&&&&LCD_ShowString(60,170,200,16,16,&KEY0:Run SRAM APP&);
&&&&&&&LCD_ShowString(60,190,200,16,16,&KEY2:Run FLASH APP&);
&&&&&&&POINT_COLOR=BLUE;
&&&&&&&//显示提示信息
&&&&&&&POINT_COLOR=BLUE;//设置字体为蓝色&&
&&&&&&&while(1)
&&&&&&&&&&&&&if(USART_RX_CNT)
&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&if(oldcount==USART_RX_CNT)
//新周期内,没有收到任何数据,认为本次数据接收完成.
&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&applenth=USART_RX_CNT;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&oldcount=0;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&USART_RX_CNT=0;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&printf(&用户程序接收完成!\r\n&);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&printf(&代码长度:%dBytes\r\n&,applenth);
&&&&&&&&&&&&&&&&&&&&&}else oldcount=USART_RX_CNT;&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&t++; delay_ms(10);
&&&&&&&&&&&&&&if(t==30)
&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&LED0=!LED0; t=0;
&&&&&&&&&&&&&&&&&&&&&if(clearflag)
&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&clearflag--;
&&&&&&&&&&&&&&&&&&&&&&&&&&&&if(clearflag==0)LCD_Fill(60,210,240,210+16,WHITE);//清除显示
&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&}&&&&&&&&&&&&
&&&&&&&&&&&&&&key=KEY_Scan(0);
&&&&&&&&&&&&&&if(key==KEY_UP)
&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&if(applenth)
&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&printf(&开始更新固件...\r\n&);&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&LCD_ShowString(60,210,200,16,16,&Copying APP2FLASH...&);
&&&&&&&&&&&&&&&&&&&&&&&&&&&if(((*(vu32*)(0X;4))&0xFF000000)==0x)
//判断是否为0X08XXXXXX.
&&&&&&&&&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&
iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,
applenth); //更新FLASH代码&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&LCD_ShowString(60,210,200,16,16,&Copy APP Successed!!&);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&printf(&固件更新完成!\r\n&);&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&}else
&&&&&&&&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&LCD_ShowString(60,210,200,16,16,&Illegal FLASH APP!&&&);&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&printf(&非FLASH应用程序!\r\n&);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&}else
&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&printf(&没有可以更新的固件!\r\n&);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&LCD_ShowString(60,210,200,16,16,&No APP!&);
&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示&&&&&&&&&
&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&if(key==KEY_DOWN)
&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&if(applenth)
&&&&&&&&&&&&&&&&&&&&&{&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&printf(&固件清除完成!\r\n&);&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&LCD_ShowString(60,210,200,16,16,&APP Erase Successed!&);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&applenth=0;
&&&&&&&&&&&&&&&&&&&&&}else
&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&printf(&没有可以清除的固件!\r\n&);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&LCD_ShowString(60,210,200,16,16,&No APP!&);
&&&&&&&&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&&&&&&&&clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&if(key==KEY_LEFT)
&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&printf(&开始执行FLASH用户代码!!\r\n&);
&&&&&&&&&&&&&&&&&&&&&if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x)
//判断是否为0X08XXXXXX.
&&&&&&&&&&&&&&&&&&&&&{&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&iap_load_app(FLASH_APP1_ADDR);//执行FLASH APP代码
&&&&&&&&&&&&&&&&&&&&&}else
&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&printf(&非FLASH应用程序,无法执行!\r\n&);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&LCD_ShowString(60,210,200,16,16,&Illegal FLASH APP!&);&&&&&&
&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示&&
&&&&&&&&&&&&&&}
&&&&&&&&&&&&&&if(key==KEY_RIGHT)
&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&printf(&开始执行SRAM用户代码!!\r\n&);
&&&&&&&&&&&&&&&&&&&&&if(((*(vu32*)(0X;4))&0xFF000000)==0x)
//判断是否为0X20XXXXXX.
&&&&&&&&&&&&&&&&&&&&&{&&&&
&&&&&&&&&&&&&&&&&&&&&&&&&&&&iap_load_app(0X);//SRAM地址
&&&&&&&&&&&&&&&&&&&&&}else
&&&&&&&&&&&&&&&&&&&&&{
&&&&&&&&&&&&&&&&&&&&&&&&&&&&printf(&非SRAM应用程序,无法执行!\r\n&);
&&&&&&&&&&&&&&&&&&&&&&&&&&&&LCD_ShowString(60,210,200,16,16,&Illegal SRAM APP!&);&&&&&&&
&&&&&&&&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&&&clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示
&&&&&&&&&&&&&&}&&&&&&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
&&&&&&&}&&&&&&&&&&&&&
&&&&&&&该段代码,实现了串口数据处理,以及IAP更新和跳转等各项操作。Bootloader程序就设计完成了,但是一般要求bootloader程序越小越好(给APP省空间嘛),
所以,本章我们把一些不需要用到的.c文件全部去掉,最后得到工程截图如图48.3.1所示:
图48.3.1 Bootloader&工程截图
&&&&&&&从上图可以看出,虽然去掉了一些不用的.c文件,但是Bootloader大小还是有22K左右,比较大,主要原因是液晶驱动和printf占用了比较多的flash,如果大家
想进一步删减,可以去掉LCD显示和printf等,不过我们在本章为了演示效果,所以保留了这些代码。
&&&&&&至此,本实验的软件设计部分结束。
&&&&&&&FLASH APP和SRAM APP两部分代码,我们在实验目录下提供了两个实验供大家参考,不过要提醒大家,根据我们的设置,FLASH APP的起始地址必须是0X,而SRAM APP的起始地址必须是0X。
在代码编译成功之后,我们下载代码到ALIENTEK战舰STM32开发板上,得到,如图48.4.1所示:
图48.4.1 IAP程序界面
此时,我们可以通过串口,发送FLASH APP或者SRAM APP到战舰STM32开发板,如图48.4.2所示:
图48.4.2&串口发送APP程序界面
&&&&&&&先用串口调试助手的打开文件按钮(如图标号1所示),找到APP程序生成的.bin文件,然后设置波特率为256000(为了提高速度,Bootloader程序将波特率被设置为256000了),
最后点击发送文件(图中标号3所示),将.bin文件发送给战舰STM32开发板。
&&&&&&&在收到APP程序之后,我们就可以通过KEY0/KEY2运行这个APP程序了(如果是FLASH APP,则先需要通过WK_UP将其存入对应FLASH区域)。&&
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:708次
排名:千里之外查看: 32225|回复: 426
他妈的ST32 IAP 功能, 要让所有的人都可以轻松搞定
高手请直接跳过!
理论上的东西就不写了,自己在论坛上看看! 这里直接讲如何操作的问题!
IAP 应用,首先把FLASH分两个区, 一个iap BOOT区, 一个用户APP应用区.
IAP BOOT区就是 IAP升级程序的大小, 如果你不用STM32 的FLASH做别的应用(如E2PROM),那么剩下的空间都可以作为APP应用程序区!
所以,一个完整带IAP的项目,我们要写两个单片机程序和一个PC升级程序(如果你想用PC对APP升级的话)!
本示例是IAP BOOT用串口接收PC发过来的BIN文件对STM32的APP进行升级!
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
首先,我们要完成IAP BOOT单片机程序, 这个程序很简单,你就当是STM32对自己内部的FLASH的擦写操作!
既然我们要在IAP BOOT中读写FLASH,那么我们先要设置FLASH的大小,我们把STM32的0x之后的地址都作为FLASH(那么IAP BOOT程序要小于12K)
#define ApplicationAddress& & & & & & & && && && && && &&&0x&&& & & & & & & & //APP应用程序起始地址(存放在FLASH前12K)& & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & & && && && && && && && && && && && && && && && && && && &//保留0Xx的空间为IAP使用
#define USER_FLASH_SIZE& & & & & & & & & & & & 42& & & & & & & & & & & & //用户APP flashROM大小, 42 PAGE& & & & & & & & & & & &
#define FLASH_PAGE_SIZE& & & & & & & & & & & & & & & & & & & & //FLASH 页大小
主程序很简单:
第一步当然是配置系统时钟
第二步: 根据系统时钟频率设置FLASH读写周期:
第三步: 就是初始化串口(uart_init();)
这里串口的发送及接收都是用的阻塞方式,说白了就是死等!
第四步: 单片机向PC上位机发送联机请求: (规定,单片机与上位机通讯一帧数据是260个字节,也就是说,单片机如果要对上位机发送数据就必须是260个字节,接收也是260个字节, 小于260个字节的数据将被抛弃)
/*&&上位机与单片机通讯协议如下(一帧数据是260个字节,第一个字节是字头, 第二个字节是命令字, 3~258个字节是要发送的数据, 第259个字节是结束符,最后一个字节是校验字节):& &*/
1. 下位机请求与上位机联机:
上位机发送: 0x55 , 'C' .....后面的258个字节可以不管
程序中定义:
#define COM_BUF_SIZE& & & & & & & & 256+4
uint8_t ComBuf[COM_BUF_SIZE];& & & & //0字头0x55/1命令/
数据发送及接收都用ComBuf存储
单片机请求联机::
//联机结果
第五步: 单片机带超时(比如10s)等待上位机命令(没有等到PC消息就跳到APP区运行程序, 有消息就在IAP BOOT区中运行程序):
第六步,擦除FLASH(APP应用区):
第七步: 写FLASH(APP应用 BIN 文件)
呵呵,从上面看,IAP BOOT就两步而已, 一 、擦除FLASH& && &二 、写FLASH!
MDK都不用设置,编译OK后,把HEX文件下载到FLASH里就OK了!
////////////////////////////////////////////////////////////////////////////////////////
只要注意 #define ApplicationAddress& & & & & & & && && && && && &&&0x
就可以了,这个地址我们在APP应用程序中要用到!
/////////////////////////////////////////////////////////////////////////////////////////
本帖子中包含更多资源
才可以下载或查看,没有帐号?
来个IAP升级演示视频:
本帖子中包含更多资源
才可以下载或查看,没有帐号?
IAP主要讲究的是生产以后,便于升级固件的。MDK的下载那是ICP,属于量产或者调试阶段通过jlink之类的链路来下载。IAP可以是串口,usb,can,网络,等等
有兴趣的话,可以研究下支持多种升级模式,并且代码尺寸尽量小
好像很厉害的样子
标记。不错。
本帖最后由 skype 于
16:02 编辑
App应用程序设置:
呵呵,这个简单了,是人都会写了
还记得IAP BOOT中的这个地址吗?
#define ApplicationAddress& & & & & & & & 0x
就它了&&0x3000& & !
APP&&三个设置就可以搞定!
1、FLASH偏移量
2、输出BIN文件,把它写入stm32 flash(从ApplicationAddress开始写)
3、 要让APP在应用区(ApplicationAddress)跑起来,一定要加上
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x3000);
其他注意事项:::无无无
APP 文件下载
本帖子中包含更多资源
才可以下载或查看,没有帐号?
正在学,收藏了
最近要做这个功能,谢谢LZ分享
支持楼主了
好东西当然要收藏了
好像很強大
请问这个和官方的那个&&串口下载程序有什么区别嘛??
本帖子中包含更多资源
才可以下载或查看,没有帐号?
这个,上位机都不用写, 偶们用超级终端。
收藏先,我弄的时候,步骤是跟你一样的
呵呵,杯具了!
mark之,mark之,mark之
就是过来顶的,话说3年前我曾因前辈做的一个双U的板子升级程序而感到神秘,互相升级,很方便!
一直想自己弄一下,到现在都没着手,哈哈现在被楼主给晒出来了!
是呀,资料上把简单的东西搞得复杂了,好像很神秘,其实它就是很简单。
ST发布的AN2557就是一个完整的bootloader,好处是直接用YMODEM协议,上位机直接使用超级终端或者其它支持YMODEM的软件,一个数据包1024字节,速度快。目前我们修改了AN2557,支持AES128加密,这样升级固件就可以放在网站上让用户自己去下载。
AN2557配合PW5(Procomm Plus Connection Manager)软件的脚本功能,实现了全自动灌录固件和测试。
AN2557不是用stm32内部预先固化的那个loader,而是完全源码自己扩展的一个loader,目前加上了AES128,仅仅占0x2000空间。
楼主给的也是好东西,原理步骤一目了然。
通讯中没有校验?错一个bit整个就挂了啊
Appcat 发表于
ST发布的AN2557就是一个完整的bootloader,好处是直接用YMODEM协议,上位机直接使用超级终端或者其它支持YM ...
这个只是个架构,如果认为下载比较慢的话,就把数据帧缓冲加大就可以了!
#define COM_BUF_SIZE& & & & & & & & 256+4
uint8_t ComBuf[COM_BUF_SIZE];& & & & //0字头0x55/1命令/
你认为太小的话,
#define COM_BUF_SIZE& & & & & & & & 1024+4& &&&//或改成
uint8_t ComBuf[COM_BUF_SIZE];& & & & //0字头0x55/1命令/
这样就可以了,怎么改,相信拿到源码的人都会改!
呵呵,总之,速度不是问题!
wukongli 发表于
通讯中没有校验?错一个bit整个就挂了啊
你自己加吧!
好像很強大
谢谢楼主分享。
想搞个u盘升级,参考下
好安逸的!
这是牛啊,下载来学习一下。
既然都这么说了,我还是记一下了。
回去试试,行的回来再顶~~~
Mark Mark Mark
Mark Mark Mark
正在用,谢谢
搬凳子学习
增加DOS控制台代码,可以把内存中的BIN文件打印出来,也可以打印数据流,方便连机调试:
本帖子中包含更多资源
才可以下载或查看,没有帐号?
我测试成功,楼主高人
本帖最后由 skype 于
12:31 编辑
呵呵,目的就是让所有人可以成功实现IAP, 不要向我刚开始学IAP一样,走了很多弯路,说实话,把时间浪费在IAP这个功能上很不值得!
Mark Mark MarkMark Mark Mark
好好学习。支持楼主。
支持楼主,我有个产品使用DTU,一直想弄远程升级
skype 发表于
呵呵,目的就是让所有人可以成功实现IAP, 不要向我刚开始学IAP一样,走了很多弯路,说实话,把时间浪费在IA ...
MFC中&&if ((rx.New_cnt &= 260) && (rx.buffer[0] = 0x55))& &这里应该是&&rx.buffer[0] == 0x55& &吧
<font color="#2502587 发表于
MFC中&&if ((rx.New_cnt &= 260) && (rx.buffer[0] = 0x55))& &这里应该是&&rx.buffer[0] == 0x55& &吧 ...
谢谢,我应该写成 0x55 == rx.buffer[0]
关心下,上位机程序!
对啊,干脆上位机程序也开源吧
操,都已开源,是你没有仔细看!
skype 发表于
这个只是个架构,如果认为下载比较慢的话,就把数据帧缓冲加大就可以了!
我记得这样做了之后,中断的初始地址需要更改的?
非常好,很详细,谢谢!
Appcat 发表于
ST发布的AN2557就是一个完整的bootloader,好处是直接用YMODEM协议,上位机直接使用超级终端或者其它支持YM ...
ST 的 AN2557 不錯
楼主讲的很通俗啊。。。
本帖最后由 skype 于
14:45 编辑
Nexus 发表于
我记得这样做了之后,中断的初始地址需要更改的?
#define BIN_Len& & & & & & & & 256& && && && && && && && && &//代替上下位机程序中的256
#define Protocol_Len& & & & & & & & 4+BIN_Len& && && && && && &//代替上下位机程序中的260
以后你要加大缓冲区这样改就可以:
这样的话,一帧数据是256还是1024你自己定就可以了
本帖子中包含更多资源
才可以下载或查看,没有帐号?
skype 发表于
#define BIN_Len& & & & & & & & 256& && && && && && && && && &//代替上下位机程序中的256
#define Protocol_Len& & & & & & & & 4+B ...
好像是有个4B的空隙。。。后面再试试。。。
其中4BYTE是给你做协议用的,比如加字头,做CRC校验!
呵呵,你懂的!!
skype 发表于
#define BIN_Len& & & & & & & & 256& && && && && && && && && &//代替上下位机程序中的256
#define Protocol_Len& & & & & & & & 4+B ...
楼主APP里面那个 little_os 还有点意思。自己写的么?
stely 发表于
楼主APP里面那个 little_os 还有点意思。自己写的么?
是的,无聊的时候玩玩就可以了!不要太执着自己写OS!
skype 发表于
操,都已开源,是你没有仔细看!
确实没仔细看,人才。
skype 发表于
增加DOS控制台代码,可以把内存中的BIN文件打印出来,也可以打印数据流,方便连机调试:
这个方法好& &调试的时候很烦方便
下载收藏。谢谢。
很强大~~~关注
mark mark,以后有用。
很有用的东西。mark
不错,谢谢楼主
谢谢楼主了,前段时间有个产品需要这个IAP功能,正好研究研究。
jackwang123 发表于
谢谢楼主了,前段时间有个产品需要这个IAP功能,正好研究研究。
希望对你的项目有参考价值!
wukongli 发表于
通讯中没有校验?错一个bit整个就挂了啊
嗯,的确应该增加一个校验功能。否则如果出错会死机的。
值的学习,收藏
ANDR0ID 发表于
嗯,的确应该增加一个校验功能。否则如果出错会死机的。
本贴目的是如何简单快速实现IAP,请不要在此讨论这种如果的问题!
要想丰衣足食,那只有自动手了!
谢谢 学习了 呵呵
好···有一个usmart 的 东西,大家也可以参考一下··
MARK 非常感谢!
加上GPRS模块,可以实现远程升级了的吧
加上GPRS模块,可以实现远程升级了的吧
就是要远程升级才搞IAP
顶楼主,希望更多人看到
好好学习一下
这个简单实用就好,可以以此为基础版本,大家有更好的想法可以在上面扩充
是很好的学习模块。
STM32第一次运行后要给FLASH设置读禁止:
& & & & OB_TypeDef obT
void ReadinfoByte(void)
& & & & un_
& & & & uint32_t ChipUniqueID[3];
& & & & uint32_t OptionBytes[4];
& & & & FlagStatus readoutstatus = RESET;
& & & & readoutstatus = FLASH_GetReadOutProtectionStatus();
& & & & if (SET == readoutstatus)
& & & & {&&//已写读保护
& & & & & & & & ComBuf[0]= 0x55;
& & & & & & & & ComBuf[1]= 'b';
& & & & & & & & USART_string(ComBuf, COM_BUF_SIZE);
& & & & & & & & ZeroMemory(ComBuf, COM_BUF_SIZE);
& & & & else
& & & & & & & & obTmp = *OB;
& & & & & & & & FLASH_Unlock();
& & & & & & & & FLASH_EraseOptionBytes();
& & & & & & & & FLASH_ReadOutProtection(ENABLE);
& & & & & & & & FLASH_ProgramOptionByteData((u32)(&(OB-&Data0)), 0x1e);&&//0x1ffff804
& & & & & & & & //恢复其它的option bytes
& & & & & & & & FLASH_ProgramOptionByteData((u32)(&(OB-&RDP)), obTmp.RDP);&&//0x1ffff800
& & & & & & & & FLASH_ProgramOptionByteData((u32)(&(OB-&USER)), obTmp.USER);&&//0x1ffff802
& & & & & & & & FLASH_ProgramOptionByteData((u32)(&(OB-&Data1)), obTmp.Data1);&&//0x1ffff806
& & & & & & & & FLASH_ProgramOptionByteData((u32)(&(OB-&WRP0)), obTmp.WRP0);&&//0x1ffff808
& & & & & & & & FLASH_ProgramOptionByteData((u32)(&(OB-&WRP1)), obTmp.WRP1);&&//0x1ffff80a
& & & & & & & & FLASH_ProgramOptionByteData((u32)(&(OB-&WRP2)), obTmp.WRP2);&&//0x1ffff80c
& & & & & & & & FLASH_ProgramOptionByteData((u32)(&(OB-&WRP3)), obTmp.WRP3);&&//0x1ffff80e
& & & & & & & & FLASH_Lock();
& & & & & & & & obTmp = *OB;
& & & & & & & & //96bits ID& & & & & & & &
& & & & & & & & ChipUniqueID[0] = *(__IO u32*)(0X1FFFF7E8);&&& & & & // & & & & H
本帖子中包含更多资源
才可以下载或查看,没有帐号?
谢谢分享!!!
mark&&IAP STM32
厉害!学习了!
不错,学习一下
也是刚开始学STM32,对它的FLASH特性还不是很了解,这次就在IAP上测试了一下!
呵呵,这次给出的IAP架构还是很强大地!!
本帖子中包含更多资源
才可以下载或查看,没有帐号?
试试看,不错的
好,正需要这个。修改下。哈哈。多谢。
学习了,用得上
阿莫电子论坛, 原"中国电子开发网"}

我要回帖

更多关于 亚马逊上买什么比较好 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信