目录

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

/*###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一样可以直接赋值,它的中断向量表只有几个固定位置。

  • 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出现的界面配置,我们不需要动它,它也无关紧要

<?xml version="1.0" encoding="UTF-8"?><icf_annotations version="1.0"><tab name="Vector Table"><item name=".intvec start" type="Number"><symbol>__ICFEDIT_intvec_start__</symbol><tooltip>The vector table start address</tooltip></item></tab><tab name="Memory Regions"><itemHeaders><header>Start:</header><header>End:</header></itemHeaders><item name="ROM" type="Range"><symbol_1>__ICFEDIT_region_ROM_start__</symbol_1><symbol_2>__ICFEDIT_region_ROM_end__</symbol_2><tooltip_1>The start address of the ROM region</tooltip_1><tooltip_2>The end address of the ROM region</tooltip_2></item><item name="RAM" type="Range"><symbol_1>__ICFEDIT_region_RAM_start__</symbol_1><symbol_2>__ICFEDIT_region_RAM_end__</symbol_2><tooltip_1>The start address of the RAM region</tooltip_1><tooltip_2>The end address of the RAM region</tooltip_2></item></tab><tab name="Stack/Heap Sizes"><item name="CSTACK" type="Number"><symbol>__ICFEDIT_size_cstack__</symbol><tooltip>The size of the user stack</tooltip></item><item name="SVC_STACK" type="Number"><symbol>__ICFEDIT_size_svcstack__</symbol><tooltip>The size of the supervisor stack</tooltip></item><item name="IRQ_STACK" type="Number"><symbol>__ICFEDIT_size_irqstack__</symbol><tooltip>The size of the stack for the interrupt handler</tooltip></item><item name="FIQ_STACK" type="Number"><symbol>__ICFEDIT_size_fiqstack__</symbol><tooltip>The size of the stack for the fast interrupt handler</tooltip></item><item name="UND_STACK" type="Number"><symbol>__ICFEDIT_size_undstack__</symbol><tooltip>The size of the stack for the undefined instruction handler</tooltip></item><item name="ABT_STACK" type="Number"><symbol>__ICFEDIT_size_abtstack__</symbol><tooltip>The size of the stack for the data abort handler</tooltip></item><item name="HEAP" type="Number"><symbol>__ICFEDIT_size_heap__</symbol><tooltip>The size of the heap</tooltip></item></tab>
</icf_annotations>

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-1sfr = "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文件内容:

<?xml version="1.0" encoding="iso-8859-1"?><flash_board><pass><loader>$TOOLKIT_DIR$\config\flashloader\NXP\FlashNXPLPC24K_CortexLL.flash</loader><range>CODE 0x00000000 0x00005FFF</range></pass>
</flash_board>

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

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

<?xml version="1.0" encoding="iso-8859-1"?><flash_device><exe>$TOOLKIT_DIR$\config\flashloader\NXP\FlashLayout1RAM4K_Cortex.out</exe><page>512</page><block>6 0x1000</block><flash_base>0x00000000</flash_base><macro>$TOOLKIT_DIR$\config\flashloader\NXP\LPC1xxx.mac</macro><online>1</online><aggregate>1</aggregate><args_doc>[--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.</args_doc>
</flash_device>
  • 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(22)IAP在线升级相关推荐

  1. STM32F429实现USB通过IAP在线升级

    1.目标 1.实现STM32对U盘文件的读取. 2.实现STM32拓展外部SDRAM. 3.实现STM32拓展外部Flash. 4.实现内存管理. 5.实现Fatfs文件系统,读写U盘和外部Flash ...

  2. CRC校验原理及STM32 IAP在线升级程序

    CRC校验原理: 什么是CRC校验? CRC即循环冗余校验码:是数据通信领域中最常用的一种查错校验码,其特征是信息字段和校验字段的长度可以任意选定.循环冗余检查(CRC)是一种数据传输检错功能,对数据 ...

  3. 基于Ymodem协议的stm32f405rgt6+CubeMx+IAP在线升级

    基于Ymodem协议的stm32f405rgt6+CubeMx+IAP在线升级 目录 一.CubeMX的配置 1.IAP 2.APP 二.移植Ymodem官方代码 1.文件移植 2.MDK文件.路径添 ...

  4. STM32 IAP 在线升级原理全解析

    点击左上角的"关注",定期更新 STM32 最新资讯,总有你想要的信息! STM32 IAP 在线升级原理全解析 1. 什么是 IAP?    IAP(In-Application ...

  5. 51单片机IAP在线升级

    51单片机IAP在线升级 爱矽半导体E85F3325单片机IAP在线升级教程,此处可查看更新及demo下载 文章目录 前言 一.ROM资源 二.KEIL有关知识 1.BL51连接器: 2.LX51连接 ...

  6. Stm 32 IAP 在线 升级IAP 的 操作

    (扩展-IAP主要用于产品出厂后应用程序的更新作用,考虑到出厂时要先烧写IAP  再烧写APP应用程序要烧写2次增加工人劳动力基础上写了"STM32 IAP+APP ==>双剑合一&q ...

  7. STM32 IAP 在线升级详解

    (扩展-IAP主要用于产品出厂后应用程序的更新作用,考虑到出厂时要先烧写IAP  再烧写APP应用程序要烧写2次增加工人劳动力基础上写了"STM32 IAP+APP ==>双剑合一&q ...

  8. Cortex-M3单片机的IAP在线升级上位机和下位机

    最近有个项目要做在线升级功能,我也是第一次做,把学习的过程总结下,希望能够帮助到 其他人吧.本篇博客主要介绍两个部分,下位机和上位机. 首先说下要实现功能: 1.上位机能够把APP的bin文件烧写进下 ...

  9. 【genius_platform软件平台开发】第七十四讲:IAP在线升级OTA原理

    1. BootLoader知识 1.1 概述及其作用 BootLoader可以理解成是引导程序, 它的作用是启动正式的App应用程序..换言之,BootLoader是一个程序, App也是一个程序, ...

最新文章

  1. win7 安装mysql 5.7.9记录
  2. NSPredicate 谓词
  3. IOS学习笔记十八(copy、mutableCopy、NSCopying、NSMutableCopy、深复制、浅复制)
  4. 网页UTF8转换GBK后出现问号?的原因
  5. pycharm 2020 版取消鼠标悬停显示说明文档的方法
  6. 【翻译】使用PowerShell获取网站运行时数据
  7. JAVA生产者消费者的实现
  8. 使用springboot + druid + mybatisplus完成多数据源配置
  9. pb 执行insert 后return是否会自动提交_一条MySQL更新语句是怎么执行的?
  10. python水仙花数
  11. 计算机boot指令,BCDBoot 命令行选项
  12. tp3.2中前台模板中日期时间的转换
  13. 滴滴入局同城货运,一场闪电战,还是持久战?
  14. WIN2K XP 2K3 下红警不能联机的完美解决方案(转)
  15. 关于站内信的开发思路
  16. 软件测试灵魂三问,如何回怼?
  17. Windows 11 移动文件夹错误 0x800700E1 无法成功完成操作
  18. kong/kongA docker部署+汉化
  19. 牛客网项目 1.5Mybatis入门
  20. K8s落地实践之旅 —— Pod(豌豆荚)

热门文章

  1. 随机背景图php,岁月小筑随机图片API接口-随机背景图片-随机图片API
  2. viewer.scene.primitives移除所有要素报错
  3. GMOEA代码运行2--运行环境的搭建和运行
  4. 我的世界java2b2t服务器地址_Minecraft China 2b2t
  5. 条码软件如何在标签纸上插入人民币符号
  6. Python - Pandas
  7. 利用支持向量机分析乳腺癌数据集
  8. 关于一款智能安防网关系统的项目开发总结
  9. 如何使用OpenCV绘制简单的几何图形?
  10. Android后台实时定位