STM32
直播中

刘洋

7年用户 1259经验值
私信 关注
[问答]

怎样去设计一种APP程序

IAP的原理是什么?
如何对APP程序进行设置?
怎样去设计一种APP程序?

回帖(1)

王琳

2021-9-27 17:59:42
  1.IAP原理
  正常程序的执行流程:
  
  IAP的执行流程:
  
  IAP程序必须满足:
  1)新程序必须在IAP程序之后的某个偏移地址X开始;
  2)必须将新程序的中断向量表相应的移动,移动的偏移量为X。
  2.APP程序设置
  有两个APP程序,一个为FLASH的APP,程序运行在FLASH,另一个SRAM的APP,运行在SRAM。
  FLASH APP正常程序的起始地址为:0X0800 0000,长度为0X80000(19位,512K)。
  
  APP程序放在0X0801 0000,长度为0X70000(7*2^16,448K)。前面长度0X10000(2^16,64K,(应该是0X200,512的整数倍)),用于放Bootloader程序,所以Bootloader不应大于64K。
  SRAM APP起始地址为:0X0200 1000,长度为0XC000(12*2^12,48K)。
  
  IRAM起始地址0X0200 D000,长度0X3000(3*2^12,12K)用于存放SRAM APP的内存。
  由于偏移地址是0X10000,所以需要在SystemInit函数中设置SCB SCB-》VTOR = FLASH_BASE | 0x10000;这是设置中断向量表的起始偏移地址。SRAM APP的设置方法SCB SCB-》VTOR = SRAM_BASE | 0x1000;
  MDK生成的是.hex文件,IAP需要的是.bin文件,使用fromelf.exe功能将.axf转换成.bin,fromelf.exe的转换格式为转换工具的语法格式为:fromelf [options] input。
  通过在 MDK点击 Options for Target→User选项卡,在After Build/Rebuild栏,勾选 Run #1,并写入:
  D:toolsmdk5.14ARMARMCCbinfromelf.exe --bin -o 。.OBJRTC.bin 。.OBJRTC.axf
  (本机的fromelf.exe放在C:Keil_v5ARMARMCCbin,需要改路径为对应路径,其他文件也要改文件名)
  然后只需要将这个.bin文件发给STM32就可以执行IAP升级
  3.Bootloader程序设计
  进入接受APP程序,在接受完APP后,即可执行IAP。
  iap_write_appbin函数用于将存放在串口接收buf里面的APP程序写入到FLASH。Iap_load_app函数,用于跳转到APP程序运行,参数appxaddr为APP程序的其实地址,程序先判断栈顶地址是否合法,在得到合法的栈顶地址后,通过MSR_MSP函数,设置栈顶地址,最后通过虚拟函数jump2app跳转到APP程序执行代码,实现IAP→APP的跳转。
  usart.h中定义USART_RX_BUF数组保存接收的APP程序,长度USART_REC_LEN为55K,串口最大可接受55K,本BootLoader最大能接受APP的大小。指定USART_RX_BUF地址,使其保存在固定的RAM地址。
  Bootloader程序是正常地址的程序,需要删除掉一些无用的程序,只用于接收数据,更新程序,跳转程序等操作。
  Bootloader程序的主要流程为,上电后判断串口是否有数据,若一定时间内(例10秒)无串口数据,则自动进入跳转到之前保存的IAP APP程序,如果无合法的APP程序,则进入一个死循环或者继续等待串口接收数据都可以。这样便可以在板卡上电后自动跳转到的之前的程序,而不再需要上位机发送指令或者程序。
  如果在时间段内有数据流,则把接收到的所有数据保存到RAM中,接收完所有数据后(以时间间隔(10ms)无新数据作为判断标志,因为数据长度是不定的,没办法事前约定),判断程序数据是否合法,合法则把程序保存到指定的FLASH中,然后进行跳转到该FLASH。
  到此Bootloader程序设计完成了,需要添加一些提示信息提示当前状态。
  3.1 一定时间到自动跳转到APP程序
  
  time_count ++;
  if(time_count == 1000)//10S
  {
  time_count = 0;
  printf(“10秒时间到,开始执行FLASH APP程序。..rn”);
  run_IAP();
  }
  delay_ms(10);
  3.2 串口接收数据
  接收数据为普通的串口接收程序,在中断接收保存数据,然后在主函数或者定时器中断中判断时间间隔作为接收完成判断均可,建议在主函数中判断,不使用定时器,可以减少Bootloader程序的大小。
  3.3 更新程序
  
  if(oldcount==USART_RX_CNT)//新周期内,没有收到任何数据,认为本次数据接收完成。
  {
  applenth=USART_RX_CNT;
  oldcount=0;
  USART_RX_CNT=0;
  printf(“用户程序接收完成!rn”);
  printf(“代码长度:%dBytesrn”,applenth);
  printf(“开始更新固件。..rn”);
  if(update_IAP(applenth)==1)//更新固件
  run_IAP();
  }
  else
  {
  time_count = 0;//重新计时10秒
  oldcount=USART_RX_CNT;
  }
  在接收完程序数据后,先判断程序是否合法,合法则更新到FLASH中,然后在跳转到该APP程序。
  3.4 备注
  对跳转和更新程序进行了简单的封装如下:
  
  void run_IAP(void)
  {
  if(((*(vu32*)(FLASH_APP1_ADDR+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
  {
  iap_load_app(FLASH_APP1_ADDR);//执行FLASH APP代码
  }
  else
  {
  printf(“非FLASH应用程序,无法执行!rn”);
  }
  }
  u8 update_IAP(u16 applenth)
  {
  if(((*(vu32*)(0X20001000+4))&0xFF000000)==0x08000000)//判断是否为0X08XXXXXX.
  {
  iap_write_appbin(FLASH_APP1_ADDR,USART_RX_BUF,applenth);//更新FLASH代码
  printf(“固件更新完成!rn”);
  return 1;
  }
  else
  {
  printf(“非FLASH应用程序!rn”);
  return 0;
  }
  }
  
  4.APP程序设计
  APP程序最重要的部分就是需要保存在约定好的地址内,然后需要在程序开始前设置好保存中断服务函数起始地址的中断向量表偏移量,其他都是正常的程序。但是由于需要在APP程序运行中,根据需要可以进行在应用编程,并且我们在Bootloader程序中设计了更新代码,只需要在APP在添加复位代码,即可自动进入到Bootloader中,进行代码的更新。
  4.1 程序保存地址
  程序保存在约定的地址内,在2中已经讲解了。
  4.2 设置中断向量表偏移量
  STM32的设置中断向量表偏移量。
  SCB-》VTOR = FLASH_BASE | 0x10000; /* Vector Table Relocation in Internal FLASH. */
  4.3 远程控制软件复位
  STM32串口复位方法:
  
  APP程序的其他部分均与正常程序一致。
  5.演示
  第一次操作需要先通过ISP给板卡烧录Bootloader程序,复位板卡,在串口软件中打开对应的.bin文件,在设置好的一定时间内(10秒)发送bin文件,发送后将自动运行APP程序。
  
  在之后的程序中,一般来说程序都是在运行APP程序(并且板卡因为电源等原因复位后,也可以正常运行APP程序),这时候通过串口发送[RESTART]指令对板卡进入复位即可,然后再一定时间内发送bin文件即可在应用更新程序。
举报

更多回帖

发帖
×
20
完善资料,
赚取积分