首页 > 学院 > 开发设计 > 正文

串口 IAP

2019-11-06 08:44:49
字体:
来源:转载
供稿:网友

这里写图片描述 这里写图片描述 APP程序的生成步骤: ①设置APP程序的起始地址和存储空间大小 ② 设置中断向量表偏移量 设置SCB->VTOR的值即可。 ③ 设置MDK编译后运行fromelf.exe,生成.bin文件. 通过在MDK User选项卡,设置编译后调用fromelf.exe,根据.axf文件生 成.bin文件,用于IAP更新。 bootloader作用: 1.通过某种串口下载.bin文件 2.写入Flash的某个区域 3.跳转执行

查看 SYSTEM–usart.c

u8 USART_RX_BUF[USART_REC_LEN] __attribute__ ((at(0X20001000)));//接收缓冲,最大USART_REC_LEN个字节,起始地址为0X20001000.查看定义(usart.h)得到buf的宽度#define USART_REC_LEN 120*1024 //定义最大接收字节数 120K(1024BYTE(字节)=1KB)

查看 IAP–iap.c–iap.h

void iap_load_app(u32 appxaddr); //跳转到APP程序执行void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 applen); //在指定地址开始,写入bin

iap_write_appbin

iapfun jump2app; u32 iapbuf[512]; //2K字节缓存,4x512=2K//appxaddr:应用程序的起始地址//appbuf:应用程序CODE.//appsize:应用程序大小(字节).void iap_write_appbin(u32 appxaddr,u8 *appbuf,u32 appsize){ u32 t; u16 i=0; u32 temp; u32 fwaddr=appxaddr;//当前写入的地址 u8 *dfu=appbuf; for(t=0;t<appsize;t+=4) { temp=(u32)dfu[3]<<24; temp|=(u32)dfu[2]<<16; temp|=(u32)dfu[1]<<8; temp|=(u32)dfu[0]; dfu+=4;//偏移4个字节 u8转换为u32 iapbuf[i++]=temp; if(i==512) { i=0; STMFLASH_Write(fwaddr,iapbuf,512); fwaddr+=2048;//偏移2048 512*4=2048 } } if(i)STMFLASH_Write(fwaddr,iapbuf,i);//将最后的一些内容字节写进去. }

iap_load_ap

//跳转到应用程序段//appxaddr:用户代码起始地址.void iap_load_app(u32 appxaddr){ if(((*(vu32*)appxaddr)&0x2FFE0000)==0x20000000) //检查栈顶地址是否合法. { jump2app=(iapfun)*(vu32*)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址) MSR_MSP(*(vu32*)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址) jump2app(); //跳转到APP. }}

main.c

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(30,210,240,210+16,WHITE);//清除显示 } } key=KEY_Scan(0); if(key==WKUP_PRES) //WK_UP按键按下 { if(applenth) { printf("开始更新固件.../r/n"); LCD_ShowString(30,210,200,16,16,"Copying APP2FLASH..."); if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX. { iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,applenth);//更新FLASH代码 LCD_ShowString(30,210,200,16,16,"Copy APP Successed!!"); printf("固件更新完成!/r/n"); }else { LCD_ShowString(30,210,200,16,16,"Illegal FLASH APP! "); printf("非FLASH应用程序!/r/n"); } }else { printf("没有可以更新的固件!/r/n"); LCD_ShowString(30,210,200,16,16,"No APP!"); } clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示 } if(key==KEY1_PRES) //KEY1按下 { if(applenth) { printf("固件清除完成!/r/n"); LCD_ShowString(30,210,200,16,16,"APP Erase Successed!"); applenth=0; }else { printf("没有可以清除的固件!/r/n"); LCD_ShowString(30,210,200,16,16,"No APP!"); } clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示 } if(key==KEY2_PRES) //KEY2按下 { printf("开始执行FLASH用户代码!!/r/n"); if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX. { iap_load_app(FLASH_APP1_ADDR);//执行FLASH APP代码 }else { printf("非FLASH应用程序,无法执行!/r/n"); LCD_ShowString(30,210,200,16,16,"Illegal FLASH APP!"); } clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示 } if(key==KEY0_PRES) //KEY0按下 { printf("开始执行SRAM用户代码!!/r/n"); if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x20000000)//判断是否为0X20XXXXXX. { iap_load_app(0X20001000);//SRAM地址 }else { printf("非SRAM应用程序,无法执行!/r/n"); LCD_ShowString(30,210,200,16,16,"Illegal SRAM APP!"); } clearflag=7;//标志更新了显示,并且设置7*300ms后清除显示 } } }

APP程序的生成 ①设置APP程序的起始地址和存储空间大小 这里写图片描述

②中断向量表的偏移量设置方法 APP存放在FLASH中的设置方法 SCB->VTOR = FLASH_BASE | 0x10000;

APP存放在SRAM中的设置方法 SCB->VTOR = SRAM_BASE | 0x1000; 这里写图片描述 ③设置MDK编译后运行fromelf.exe,生成.bin文件 B:/MDK5/ARM/ARMCC/bin/fromelf.exe –bin -o ../OBJ/RTC.bin ../OBJ/RTC.axf 其他的程序修改可以在output查看

这里写图片描述

打开 C:/Users/84329/Desktop/实验15 RTC实时时钟实验/OBJ 可以查找有bin文件 打开串口调试助手 波特率 设为460800 打开文件RTC.bin 发送文件

实验现象: 本实验开机的时候先显示提示信息,然后等待串口输入接收APP程序(无校验,一次性接收),在串口接收 到APP程序之后,即可执行IAP。如果是SRAM APP,通过按下KEY0即可执行这个收到的SRAM APP程序。如果 是FLASH APP,则需要先按下KEY_UP按键,将串口接收到的APP程序存放到STM32的FLASH,之后再按KEY1即 可以执行这个FLASH APP程序。通过KEY2按键,可以手动清除串口接收到的APP程序。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表