LPC2478(22)IAP在线升级

目录

1、开发环境

2、特性

3、IAR编译器的相关文件

3.1、icf文件

3.2、IcfEditorFile文件内容

3.3、ddf文件

3.4、board文件

4、IAP相关

4.1、软件复位

4.2、bootloader程序跳转到App程序

4.3、LPC2478的bootloader程序操作注意事项

4.4、LPC2478的App程序操作注意事项

5、收获


        这次主要对STM32F103/Keil和LPC2478/IAR加了一个IAP在线升级功能,但是选择记录LPC2478/IAR,首先是因为自己对于IAR编译器没有Keil的熟悉,所以印象更加深刻,其次就是STM32F103/Keil下的IAP升级的资料实在是太多了,没有什么异常的情况,而IAR相对而言资料较少自己是根据STM32/Keil的思路一步步走下来的。

        主要记录一下自己的思路,bootloader和App代码都不写了

1、开发环境

LPC-2478STK+IAR+JINK

2、特性

       单片机只有一个程序时,可以直接从起始地址开始运行;但当系统中有两个程序时,例如带bootloader的系统,则应用程序的运行需要通过bootloader跳转,和bootloader相比,应用程序(App)的地址和中断向量表地址都发生改变,如何告诉编译器来分配bootloader和应用程序在flash中的地址以及如何告诉CPU中断表向表的位置。

3、IAR编译器的相关文件

        在编译器的选项中看到有后缀为icf文件、后缀为ddf文件、后缀为board文件、后缀为flash文件,但是这些文件中,跟IAP功能相关的只有icf文件,其他的文件在此篇中都不重要。

        程序的项目文件在此篇中也不重要

3.1、icf文件

        文件配置目录是:Options->Linker->Config->Linker configuration file

        需要换成自定义的icf文件需要勾选Override default

LPC2478(22)IAP在线升级_第1张图片

/*###ICF### Section handled by ICF editor, don't touch! ****/
/*-使用过应用层的会发现,这个a_v1_0.xml就是点击配置文件Edit出现的界面配置,我们不需要动它,它也无关紧要-*/
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml" */
/*-中断向量表的起始地址,主要设置参数-*/
define symbol __ICFEDIT_intvec_start__ = 0x00000000;
/*-Memory Regions-*/
/*-程序ROM的起始地址,主要设置参数-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x00000000;
define symbol __ICFEDIT_region_ROM_end__   = 0x0004FFFF;
/*-程序RAM的起始地址,主要设置参数-*/
define symbol __ICFEDIT_region_RAM_start__ = 0x40000000;
define symbol __ICFEDIT_region_RAM_end__   = 0x4000FFDF;
/*-Sizes-*/
/*-程序的堆栈大小,一般无需改动 -*/
define symbol __ICFEDIT_size_cstack__   = 0x400;
define symbol __ICFEDIT_size_svcstack__ = 0x100;
define symbol __ICFEDIT_size_irqstack__ = 0x100;
define symbol __ICFEDIT_size_fiqstack__ = 0x40;
define symbol __ICFEDIT_size_undstack__ = 0x10;
define symbol __ICFEDIT_size_abtstack__ = 0x10;
define symbol __ICFEDIT_size_heap__     = 0x2000;
/**** End of ICF editor section. ###ICF###*/
/* CRP区块,主要用于代码保护功能,将ROM空间最大化,一般无需改动 */
define symbol __CRP_start__   = 0x000001FC;
define symbol __CRP_end__     = 0x000001FF;
/* 下面的一般无需改动 */
/* Memory used by RealMonitor*/
define symbol __RM_start__   = 0x40000040;
define symbol __RM_end__     = 0x4000011F;

define memory mem with size = 4G;
define region ROM_region   = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__] - mem:[from  __CRP_start__ to __CRP_end__];
define region RAM_region   = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__] - mem:[from  __RM_start__ to __RM_end__];
define region CRP_region   = mem:[from  __CRP_start__ to __CRP_end__];

define symbol __region_USB_DMA_RAM_start__  = 0x7FD00000;
define symbol __region_USB_DMA_RAM_end__    = 0x7FD03FFF;
define region USB_DMA_RAM_region= mem:[from __region_USB_DMA_RAM_start__    to __region_USB_DMA_RAM_end__];

define symbol __region_EMAC_DMA_RAM_start__ = 0x7FE00000;
define symbol __region_EMAC_DMA_RAM_end__   = 0x7FE03FFF;
define region EMAC_DMA_RAM_region= mem:[from __region_EMAC_DMA_RAM_start__  to __region_EMAC_DMA_RAM_end__];

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block SVC_STACK with alignment = 8, size = __ICFEDIT_size_svcstack__ { };
define block IRQ_STACK with alignment = 8, size = __ICFEDIT_size_irqstack__ { };
define block FIQ_STACK with alignment = 8, size = __ICFEDIT_size_fiqstack__ { };
define block UND_STACK with alignment = 8, size = __ICFEDIT_size_undstack__ { };
define block ABT_STACK with alignment = 8, size = __ICFEDIT_size_abtstack__ { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };

initialize by copy { readwrite };
do not initialize  { section .noinit };
do not initialize  { section USB_DMA_RAM };
do not initialize  { section EMAC_DMA_RAM };

place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };

place in ROM_region   { readonly };
place in RAM_region   { readwrite,
                        block CSTACK, block SVC_STACK, block IRQ_STACK, block FIQ_STACK,
                        block UND_STACK, block ABT_STACK, block HEAP };
place in USB_DMA_RAM_region
                      { section USB_DMA_RAM };
place in EMAC_DMA_RAM_region
                      { section EMAC_DMA_RAM };
place in CRP_region   { section .crp };

所以说,我们在icf文件中需要设置几个参数:

1、设置中断向量表的起始地址,需要重定义到应用程序的地址0x00010000上。

define symbol __ICFEDIT_intvec_start__ = 0x00010000;

2、设置ROM的起始地址,需要重定义到应用程序的地址0x00010040上。

        存储器重新映射的部分允许在不同模式下处理中断,它包括中断向量区(32 字节)和额外的 32 字节,总共是 64 字节,这便于跳转到较远物理地址的中断处理程序。重新映射的代码位置与地址 0x0000 0000~0x0000 003F 重叠。位于 Flash 存储器中的典型用户程序可以将整个 FIQ 处理程序放置在地址 0x0000 001C 而不需要考虑存储器的边界。包含在SRAM、外部存储器和 Boot ROM 中的向量必须含有跳转到实际中断处理程序的分支或者其它执行跳转到中断处理程序的指令.

define symbol __ICFEDIT_region_ROM_start__ = 0x00010040;

 3、设置RAM的起始地址,需要重定义到应用程序的地址0x40000040上。

define symbol __ICFEDIT_region_RAM_start__ = 0x40000040;

        设置原因是因为LPC2478的中断向量表地址不像STM32一样可以直接赋值,它的中断向量表只有几个固定位置。 

LPC2478(22)IAP在线升级_第2张图片

  • 00就是程序默认的
  • 01用户Flash模式,理解为中断向量也在Flash的最底部,如果00程序在Flash效果应该是一致的
  • 10用户RAM模式,注意这里映射的得是RAM的最底部,所以RAM的起始地址需要偏移,底部存在应用程序的中断向量表。重点就是这个
  • 11用户外部存储器模式,使用SRAM这些外部RAM

4、应用程序(App)添加

memcpy((char *)0x40000000, (char*)0x00010000,16*4);   
//中断向量表设置在RAM中
MEMMAP = 0x02;    

5、编译前选择自己修改过的icf文件,烧写即可

3.2、IcfEditorFile文件内容

第一句话就是IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\a_v1_0.xml

使用过应用层的会发现,这个a_v1_0.xml就是点击配置文件Edit出现的界面配置,我们不需要动它,它也无关紧要




  
    
      __ICFEDIT_intvec_start__
      The vector table start address
    
  

  
    
      
Start:
End:
__ICFEDIT_region_ROM_start__ __ICFEDIT_region_ROM_end__ The start address of the ROM region The end address of the ROM region __ICFEDIT_region_RAM_start__ __ICFEDIT_region_RAM_end__ The start address of the RAM region The end address of the RAM region
__ICFEDIT_size_cstack__ The size of the user stack __ICFEDIT_size_svcstack__ The size of the supervisor stack __ICFEDIT_size_irqstack__ The size of the stack for the interrupt handler __ICFEDIT_size_fiqstack__ The size of the stack for the fast interrupt handler __ICFEDIT_size_undstack__ The size of the stack for the undefined instruction handler __ICFEDIT_size_abtstack__ The size of the stack for the data abort handler __ICFEDIT_size_heap__ The size of the heap

3.3、ddf文件

        在Options->Debugger->Setup->Device description file有ddf文件的信息,它也无关紧要

其中LPC2478.ddf文件内容


;; Memory information ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; Used to define address zones within the ARM address space (Memory).
;;
;;   Name      may be almost anything
;;   AdrSpace  must be Memory
;;   StartAdr  start of memory block
;;   EndAdr    end of memory block
;;   AccType   type of access, read-only (R), read-write (RW) or SFR (W)

[Memory]
;;         Name             AdrSpace    StartAdr    EndAdr      AccType   Width
Memory =  Periph1          Memory      0x3FFFC000  0x3FFFFFFF  W  
Memory =  ExtDev           Memory      0x80000000  0x83FFFFFF  W  
Memory =  ExtMem           Memory      0xA0000000  0xDFFFFFFF  RW 
Memory =  Periph2          Memory      0xE0000000  0xE01FFFFF  W  
Memory =  Periph3          Memory      0xFFE00000  0xFFFFFFFF  W  
Memory =  Flash            Memory      0x00000000  0x0007FFFF  R  
Memory =  RAM              Memory      0x40000000  0x4000FFFF  RW 
Memory =  RAMUSB           Memory      0x7FD00000  0x7FD03FFF  RW 
Memory =  RAMETH           Memory      0x7FE00000  0x7FE03FFF  RW 
Memory =  ROM              Memory      0x7FFFE000  0x7FFFFFFF  R  

TrustedRanges = true
UseSfrFilter = true

[SfrInclude]
File = iolpc2470.ddf

        就是标记了一下内存的名字,起始地址,结束地址,访问类型,以及引用iolpc2470.ddf,都是一些无需改动的东西。这个就有点类似于linux的树一样,Memory下的是LPC2478特有的属性,其他的都使用iolpc2470即可

其中iolpc2470.ddf文件内容,太长了,主要是对寄存器的位地址进行定义,截取部分:


sfr = "PLLCON"                                 , "Memory", 0xE01FC080,        4, base=16
sfr = "PLLCON.PLLE"                            , "Memory", 0xE01FC080,        4, base=16,    bitRange=0-0
sfr = "PLLCON.PLLC"                            , "Memory", 0xE01FC080,        4, base=16,    bitRange=1-1

sfr = "PCLKSEL0"                               , "Memory", 0xE01FC1A8,        4, base=16
sfr = "PCLKSEL0.PCLK_WDT"                      , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=0-1
sfr = "PCLKSEL0.PCLK_TIMER0"                   , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=2-3
sfr = "PCLKSEL0.PCLK_TIMER1"                   , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=4-5
sfr = "PCLKSEL0.PCLK_UART0"                    , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=6-7
sfr = "PCLKSEL0.PCLK_UART1"                    , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=8-9
sfr = "PCLKSEL0.PCLK_PWM0"                     , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=10-11
sfr = "PCLKSEL0.PCLK_PWM1"                     , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=12-13
sfr = "PCLKSEL0.PCLK_I2C0"                     , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=14-15
sfr = "PCLKSEL0.PCLK_SPI"                      , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=16-17
sfr = "PCLKSEL0.PCLK_RTC"                      , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=18-19
sfr = "PCLKSEL0.PCLK_SSP1"                     , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=20-21
sfr = "PCLKSEL0.PCLK_DAC"                      , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=22-23
sfr = "PCLKSEL0.PCLK_ADC"                      , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=24-25
sfr = "PCLKSEL0.PCLK_CAN1"                     , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=26-27
sfr = "PCLKSEL0.PCLK_CAN2"                     , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=28-29
sfr = "PCLKSEL0.PCLK_ACF"                      , "Memory", 0xE01FC1A8,        4, base=16,    bitRange=30-31

3.4、board文件

        在Options->Debugger->Download->Use flash loader有board file的文件信息,它也无关紧要

其中board文件内容:




   
     $TOOLKIT_DIR$\config\flashloader\NXP\FlashNXPLPC24K_CortexLL.flash
     CODE 0x00000000 0x00005FFF
   

主要内容就是引用FlashNXPLPC24K_CortexLL.flash文件,以及规定程序的大小

其中flash文件内容,这个就是flash的烧写算法,不关注,STM32的IAP也没有在Flash的烧写算法上做什么改动:




  $TOOLKIT_DIR$\config\flashloader\NXP\FlashLayout1RAM4K_Cortex.out
  512
  6 0x1000
  0x00000000
  $TOOLKIT_DIR$\config\flashloader\NXP\LPC1xxx.mac
  1
  1
  [--clock] Passes the clock frequency to the flash loader; 
value is the CPU clock speed in kHz. The default clock 
frequency value is 14,746 kHz. 

  • exe:代表引用的外部程序进行烧写
  • page:芯片的大小
  • block:块数量以及大小,不过我不明白啥意思
  • flash_base:烧写的起始地址

跟IAR编译器相关的配置文件大概就这些。

4、IAP相关

4.1、软件复位

((void(*)())0x0)(); 

4.2、bootloader程序跳转到App程序

//定义函数指针
void (*UserProgram)();
//赋值App程序地址AppAddr
UserProgram = (void (*)()) (AppAddr);
//跳转
(*UserProgram)();

4.3、LPC2478的bootloader程序操作注意事项

1、写入应用程序到Flash时,需要从RAM写入到Flash,否则IAP写入会报错,状态码为SRC_ADDR_NOT_MAPPED,描述源地址没有映射到存储器映射中。计数值必须考虑其可用性

2、如果源地址不是4的倍数,将会报错,状态码为SRC_ADDR_ERROR,描述目标地址的边界错误,比如你接收了数据,但是接收地址是4的倍数,但是有效程序地址是从下标1开始的,那么你写入将会报错。

3、写入Flash时,写入字节的数目必须是按照。应当为 256 | 512 | 1024 | 4096。但是最后一次一般都会出现不是,所以在最后一次写入时需要补全。

4、每次新写一个扇区时,必须将其先清空。

4.4、LPC2478的App程序操作注意事项

1、App程序能正常运行,但是无法进入中断,App程序开头添加,具体描述请见上文:

memcpy((char *)0x40000000, (char*)0x00010000,16*4);   
//中断向量表设置在RAM中
MEMMAP = 0x02;    

 2、App程序无法运行,需要重新编辑编译前的icf文件,重定义中断向量表和RAM的起始地址,具体描述请见上文:

/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x00010000;
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x00010040;
define symbol __ICFEDIT_region_ROM_end__   = 0x0004FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x40000040;
define symbol __ICFEDIT_region_RAM_end__   = 0x4000FFDF;

3、  IAR生成bin文件:Options->Output Converter-->Output 下的Output format格式选择Raw binary,Output file将Override default勾选 

5、收获

        主要是对于IAR编译器的熟悉加深,整个过程也是比较轻松的,因为只需要按照STM32的思路来就好了,就是

  1. 设置App的起始地址和存储空间
  2. 重定义中断向量表,
  3. 生成bin文件,烧写(烧录器直接烧写也是可以的)

        耽误了一点时间的就是因为LPC2478的芯片不熟悉,不知道需要定义当前中断向量处于的位置需要寄存器设置。

你可能感兴趣的:(LPC2478,单片机,stm32,arm)