新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > 基于IAP和Keil MDK的远程升级设计

基于IAP和Keil MDK的远程升级设计

作者:时间:2016-12-19来源:网络收藏

  3.3.1.2 选择扇区

本文引用地址:http://www.eepw.com.cn/article/201612/341760.htm

  在任何擦除和编程Flash之前,必须选中扇区,可以选中一个或多个。

  /******************************************************************

  * 名称:SelSector()

  * 功能:操作扇区选择,命令代码50。

  * 入口参数:sec1 起始扇区

  * sec2 终止扇区

  * 出口参数:返回值(paramout缓冲区) CMD_SUCCESS,BUSY,INVALID_SECTOR

  *********************************************************************/

  void SelSector(uint8 sec1, uint8 sec2)

  {

  paramin[0] = _SELSECTOR; // 设置命令字

  paramin[1] = sec1; // 设置参数

  paramin[2] = sec2;

  iap_entry(paramin, paramout); // 调用IAP服务程序

  }

  代码3-2 选择扇区

  3.3.1.3 擦除扇区

  在编程Flash前必须执行擦除操作,如果某个扇区已经擦除,就不需要再次擦除。可以一次擦除一个或多个扇区。

  /******************************************************************

  * 名称:EraseSector()

  * 功能:扇区擦除,命令代码52。

  * 入口参数:sec1 起始扇区

  * sec2 终止扇区

  * 出口参数:IAP返回值(paramout缓冲区) CMD_SUCCESS,BUSY,INVALID_SECTOR ************************************************************************/

  void EraseSector(uint8 sec1, uint8 sec2)

  { paramin[0] = IAP_ERASESECTOR; // 设置命令字

  paramin[1] = sec1; // 设置参数

  paramin[2] = sec2;

  paramin[3] = Fosc/1000; // 当不使用PLL功能时,Fcclk=Fosc

  iap_entry(paramin, paramout); // 调用IAP服务程序

  代码3-3 擦除扇区

  3.3.1.4 编程扇区

  通过这个过程,数据可以从RAM中编程到片内Flash中。

  注:

  1. 数据只能从片内SRAM编程到片内Flash。

  2. 片内Flash的地址必须512字节对齐。

  3. 片内RAM应位于局部总线,即USB或以太网的SRAM不可以使用。

  4. 每一次编程字节应该是512、1024、4096、8192中的一个。

  /*********************************************************************

  * 名称:RamToFlash()

  * 功能:复制RAM的数据到FLASH,命令代码51。

  * 入口参数:dst 目标地址,即FLASH起始地址。以512字节为分界

  * src 源地址,即RAM地址。地址必须字对齐

  * no 复制字节个数,为512/1024/4096/8192

  * 出口参数:IAP返回值(paramout缓冲区) CMD_SUCCESS,SRC_ADDR_ERROR,DST_ADDR_ERROR,

  SRC_ADDR_NOT_MAPPED,DST_ADDR_NOT_MAPPED,COUNT_ERROR,BUSY,未选择扇区

  ********************************************************************/

  void RamToFlash(uint32 dst, uint32 src, uint32 no)

  { paramin[0] = IAP_RAMTOFLASH; // 设置命令字

  paramin[1] = dst; // 设置参数

  paramin[2] = src;

  paramin[3] = no;

  paramin[4] = Fosc/1000; // 当不使用PLL功能时,Fcclk=Fosc

  iap_entry(paramin, paramout); // 调用IAP服务程序

  }

  代码3-4 编程扇区

  3.3.1.5 比较数据

  通过这个函数,可以检查写入Flash中的数据和RAM中的是否相同。

  注意源地址、目标地址和字节数必须是4的倍数。可使用 MDK提供的关键字__align(n) 来指定n字节对齐。

  /********************************************************************

  * 名称:Compare()

  * 功能:校验数据,命令代码56。

  * 入口参数:dst 目标地址,即RAM/FLASH起始地址。地址必须字对齐

  * src 源地址,即FLASH/RAM地址。地址必须字对齐

  * no 复制字节个数,必须能被4整除

  * 出口参数:IAP返回值(paramout缓冲区) CMD_SUCCESS,COMPARE_ERROR,ADDR_ERROR

  ******************************************************************/

  void Compare(uint32 dst, uint32 src, uint32 no)

  { paramin[0] = IAP_COMPARE; // 设置命令字

  paramin[1] = dst; // 设置参数

  paramin[2] = src;

  paramin[3] = no;

  iap_entry(paramin, paramout); // 调用IAP服务程序

  代码3-5 比较数据

  3.3.2 IAP编程期间的中断管理

  LPC2114片上Flash在擦除/编程期间绝不可被中断打断。但Bootloader中定时和串口接收又使用了中断,因此必须在擦除/编程之前禁止总中断,待操作完成后再使能总中断。Bootloader运行在用户模式下,不具有禁止/使能中断的权力,所以在本设计中使用软中断禁止/使能总中断。 MDK提供了关键字__svc来触发软中断。

  软中断函数声明:

  __svc(0x00) void EnableIrq(void); //使能中断,软中断0

  __svc(0x01) void DisableIrq(void); //禁止中断,软中断1

  软中断函数代码:

  /*

  *********************************************************************

  * 功 能:禁止中断

  * 描 述:利用软中断实现在用户模式下调用函数关中断

  *********************************************************************/

  void DisableIrqFunc(void)

  {

  int temp;

  __asm

  {

  MRS temp,SPSR

  ORR temp,temp,#0x80

  MSR SPSR_c,temp

  }

  }

  /*

  ********************************************************************

  * 功 能:使能中断

  * 描 述:利用软中断实现在用户模式下调用函数开中断

  ********************************************************************

  */

  void EnableIrqFunc(void)

  {

  int temp;

  __asm

  {

  MRS temp,SPSR

  BIC temp,temp,#0x80

  MSR SPSR_c,temp

  }

  }

  代码3-6 禁止/使能总中断

  更改启动代码,挂接软中断入口:

  ;软中断入口

  EXPORT SWI_Handler

  extern EnableIrq1

  extern DisableIrq1

  SWI_Handler

  STMFD SP!, {R0,R12,LR} ;入栈

  LDR R0, [LR,#-4] ;取软中断指令,软中断号就包含其中

  BIC R0,R0,#0xFF000000

  CMP R0,#0 ;判断是否软中断0

  BLEQ EnableIrqFunc

  BLNE DisableIrqFunc

  LDMFD SP!,{R0,R12,PC}^

  代码3-7 挂接软中断入口

  在程序中,如果想禁止中断,只需使用DisableIrq();若是能中断,只需使用EnableIrq()。

  3.3.3 使用分散加载机制精确定位入口地址

  应用程序接收到升级指令后,会跳转到0x00000400处执行Bootloader升级程序。因此Bootloader程序的入口地址必须精确定位到0x00000400处。这可以使用 MDK提供的分散加载机制来完成。

  分散加载代码见代码3-8.

  ; *************************************************************

  ; *** Scatter-Loading Description File generated by uVision ***

  ; *************************************************************

  LR_IROM1 0x00000400 0x00001C00 { ; load region size_region

  ER_IROM1 0x00000400 0x00001C00 { ; load address = execution address

  *.o (RESET, +First)

  *(InRoot$$Sections)

  .ANY (+RO)

  }

  RW_IRAM1 0x40000040 0x00003FA0 { ; RW data

  .ANY (+RW +ZI)

  }

  }

  代码3-8 分散加载代码

  这段代码显示出Bootloader程序从0x00000400处开始执行,最多占用0x1C00字节的Flash空间。另外,该程序的RAM从0x40000040开始,长度为0x3FA0个字节。这样RAM的低64字节保留给中断向量映射使用,高32字节保留给IAP编程使用。

  3.3.4 中断向量的重映射

  Bootloader的起始地址位于0x00000400,中断向量也从这一地址开始存储。但默认情况下ARM发生异常时,会跳转到0x00000000处的64字节中断向量区域执行相应操作,所以为了使Bootloader能相应中断,必须将位于0x00000400开始的64字节中断向量表重映射到RAM的低区。LPC2114使用向寄存器MEMMAP写入0x02来完成这一过程。

  代码3-9 描述了中断向量重映射的过程。

  ; Copy Exception Vectors to Internal RAM ---------------------------------------

  ADR R8, Vectors ; 源地址

  LDR R9, =RAM_BASE ; 目标地址,这里是0x40000000

  LDMIA R8!, {R0-R7} ; 装载向量表

  STMIA R9!, {R0-R7} ; 存储向量表

  LDMIA R8!, {R0-R7} ; 装载处理程序地址

  STMIA R9!, {R0-R7} ; 存储处理程序地址

  ; Memory Mapping (when Interrupt Vectors are in RAM)

  MEMMAP EQU 0xE01FC040 ; Memory Mapping Control

  IF :DEF:REMAP

  LDR R0, =MEMMAP

  IF :DEF:EXTMEM_MODE

  MOV R1, #3

  ELIF :DEF:RAM_MODE

  MOV R1, #2

  ELSE

  MOV R1, #1

  ENDIF

  STR R1, [R0]

  ENDIF

  代码3-9 中断向量重映射

  由于Keil MDK提供的启动代码中使用条件编译指令,所以,要想正确的执行中断向量重映射,还需要在Keil MDK编译器工程设置Options for target“你的工程目标名”下的Asm标签中找到Define编辑框,在编辑框中键入“REMAP RAM_MODE”。如图3-2所示

clip_image009

 

  图3-2

  注意:在擦除/编程Flash的时候还应该禁止PLL、存储器加速模块。

  3.4 用户程序的设计

  用户程序运行在高区(扇区8~13)或者低区(扇区1~7),用于实现数据的采集、处理和上传等等,用户程序除本身功能的要求外,还需要注意:

  Ø 使用分散加载机制,将程序入口精确定位到0x00010000(高区)或0x00008000(低区)。

  Ø 进行中断向量重映射,映射到RAM最底处。

    

clip_image001[2]
4 通讯协议与上位机软件  

 

  4.1 Intel的hex格式

  Intel hex文件是记录文本行的ASCII文本文件,在Intel HEX文件中,每一行是一个HEX记录,由十六进制数组成的机器码或者数据常量。一个数据记录以一个回车和一个换行结束。

  一个Intel HEX文件可以包含任意多的十六进制记录,每条记录有五个域,下面是一个记录的格式.

  : LL AAAA TT [DD...] CC

  每一组字母是独立的一域,每一个字母是一个十六进制数字,每一域至少由两个十六进制数字组成,下面是字节的描述.

  :冒号 是每一条Intel HEX记录的开始

  LL 是这条记录的长度域,他表示数据(dd)的字节数目.

  AAAA 是地址域,他

  表示数据的起始地址

  TT 这个域表示这条HEX记录的类型,他有可能是下面这几种类型

  00 ----数据记录

  01 ----文件结束记录

  02 ----扩展段地址记录

  04 ----扩展线性地址记录

  DD 是数据域,表示一个字节的数据,一个记录可能有多个数据字节,字节数目可以查看LL域的说明。



关键词: IAP Keil

评论


相关推荐

技术专区

关闭