/********************************************************************
* 名称: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.3.2 IAP编程期间的中断管理
LPC2114片上Flash在擦除/编程期间绝不可被中断打断。但Bootloader中定时和串口接收又使用了中断,因此必须在擦除/编程之前禁止总中断,待操作完成后再使能总中断。Bootloader运行在用户模式下,不具有禁止/使能中断的权力,所以在本设计中使用软中断禁止/使能总中断。Keil 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
}
}
更改启动代码,挂接软中断入口:
;软中断入口
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}^
在程序中,如果想禁止中断,只需使用DisableIrq();若是能中断,只需使用EnableIrq()。
3.3.3 使用分散加载机制精确定位入口地址
应用程序接收到升级指令后,会跳转到0x00000400处执行Bootloader升级程序。因此Bootloader程序的入口地址必须精确定位到0x00000400处。这可以使用Keil 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)
}
}
这段代码显示出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
由于Keil MDK提供的启动代码中使用条件编译指令,所以,要想正确的执行中断向量重映射,还需要在Keil MDK编译器工程设置Options for target“你的工程目标名”下的Asm标签中找到Define编辑框,在编辑框中键入“REMAP RAM_MODE”。如图3-2所示
图3-2
注意:在擦除/编程Flash的时候还应该禁止PLL、存储器加速模块。
3.4 用户程序的设计
用户程序运行在高区(扇区8~13)或者低区(扇区1~7),用于实现数据的采集、处理和上传等等,用户程序除本身功能的要求外,还需要注意:
使用分散加载机制,将程序入口精确定位到0x00010000(高区)或0x00008000(低区)。
进行中断向量重映射,映射到RAM最底处。
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域的说明。
CC 是效验和域,表示记录的效验和,计算方法是将本条记录冒号开始的所有字母(包括校验字节)相加之后等于0x00。
一个Intel HEX文件必须有一个文件结束记录,这个记录的类型域必须是01,
一个EOF记录总是这样:
:00000001FF
00是记录中数据字节的数目
0000这个地址对于EOF记录来说无任何意义
01记录类型是01(文件结束记录标示)
4.2 对上位机软件的要求
上位机具备解析重组Intel HEX文件的能力.
上位机软件应能识别分站发来的应答信号并做出正确的响应。
上位机应能够检验代码的完整性。
上位机能根据分站发出的程序所在高区或低区标志,自动判别当前升级程序是否和升级区域相对应。
5 实验数据
为验证升级程序的稳定性,对分站进行重上电、复位、远程升级等一些列实验,实验记录及如下。
5.1 测试程序跳转功能.
程序在上电或复位之后,应顺利跳转到用户程序。
5.2 测试Bootloader(一)
上位机发送升级命令但不发送升级数据包,程序应能进入Bootloader并发送当前程序所在的区域(高区或者低区代号),10S后程序应跳转到用户程序。
5.3 测试Bootloader(二)
上位机发送升级命令,发送升级数据包,但发送到一半时停止发送。程序在10S后应能跳转到用户程序区。
5.4 测试Bootloader(三)
上位机发送升级命令,发送升级数据包,但发送中途给分站断电,重新上电后,应还能执行原来的程序。
5.5 测试Bootloader(四)
上位机发送升级命令,发送完成升级数据包。程序应能接收升级数据包并编程Flash,完成用户程序的更新,更新用户程序后,跳转到新的用户程序。
6.总结
本次升级方案虽然是以LPC2114为基础的,但任何具有IAP功能的单片机、ARM都可使用本设计方案。
设计的重点在于如何保证升级的安全性,分站采取了一些列校验、超时处理以及看门狗等措施,一是保障升级数据包的正确传送,二是即使升级失败也能退回原升级程序。上位机的校验措施需相关部门配合。从实验数据来看,进行了几十次的远程升级,未有一例失败,安全性能可以得到保证。
7.参考文献
周立功等 ARM微控制器基础与实战(第二版) 北京航空航天大学出版社 2005
LPC2114/2124/2212/2214 使用指南.Pdf 广州周立功单片机发展有限公司
韦文祥 朱志杰 车琳娜 郭宝泉 基于LPC21 24的一个远程系统软件升级方案 单片机与嵌入式系统应用 2006第三期
许文杰 丁志冈 张 泉基于ARM 处理器的IAP设计及应用 计算机应用与软件 2009第3期
姜晓梅 李祥和 任朝荣 姚明基于ARM的IAP在线及远程升级技术 计算机应用 2008第二期
RealView 编译工具-编译器参考指南.pdf ARM Limited 2009.3
RealView Compilation Tools(连接器用户指南).pdf ARM Limited 2009.3
RealView 编译工具-编译器用户指南.pdf ARM Limited 2009.1
RealView 编译工具-链接器参考指南.pdf ARM Limited 2008.9
Intel HEX文件格式
LPC2000 secondary bootloader for code update using IAP NXP Semiconductors 2009.5.26
8.后记
8.1 后记1
分散加载文件,软中断,中断向量表重映射,变量对齐,精确定位变量等等这些东西的详细讲解在我的参考资料上都能找的到,发现问题并能解决它,是件很美妙的事情,所以我没打算也没时间详细写这些东西的用法。
需要说的是,我在设计的时候走了一个弯路,现在想想还觉得挺可笑。我以为上面讲的东西要在一个工程里面实现才好,这样才能生成一个.hex可烧录文件,可以一次性的将用户程序、Bootloader程序烧写进处理器,我想弯了。正确的做法是建四个工程:跳转程序、Bootloader、用户低区程序、用户高区程序。如果你懂了.hex文件的格式,就完全可以将跳转程序、Bootloader和用户低区程序(或者跳转程序、Bootloader和用户高区程序)这三个工程生成的.hex文件合成一个。灵活多变的处理问题,这是我最大的收获。
8.2 后记2
很多同学看完后都希望得到源码,这种心情我是理解的,最初的时候我也希望有一套别人的源码的,毕竟这样可以进行的快点.所以我将一个远程升级的例子放在下面的链接里,大家想看看的就去下载吧,这个不是我产品中用到的,因为我的代码毕竟是含有公司的一些信息.如果我最近有时间,会把其中的英文文档翻译一下的.
链接:http://download.csdn.net/detail/zhzht19861011/3618966
8.3 后记3
补充一个隐含的Bug,从Bootloader跳转到应用程序前,应该使处理器进入特权模式,否则用户程序可能出现堆栈错误。----2012.12.10
8.4 后记4
重新编排了文章格式。本来这篇文章是在Word中书写的,排版十分清晰,但是从Word复制csdn博客,很多word格式csdn并不支持,因此版面很是凌乱,这一凌乱一下就持续了四年多。
以前写博客是为了给自己看,每当有个心得,记下来以便以后查阅。后来发现自己写的很多文章会有比较高的访问量,很多网友会留言说“xx文章对我帮助很大”,这让我意识到原来我可以帮助很多人。既然有人看,那么对我而言,有两个方面需要特别考虑:一是要准确,二是要清晰。准确源于平时积累,书写成文字必须多考证;清晰不仅要求文章内容逻辑上要清晰,而且文章排版也要清晰。这是我重新排版的原因。
因为各种原因,我的文章可能不总是准确,如果读者发现错误,请正面留言告诉我。CSDN博客有个功能, 如果你觉得这篇文章很好,可以在文章最后点“顶”,反之你觉得这篇文章误导了你,你可以点“踩”。这篇文章就被人点了“踩”,但并没有反馈为什么点踩。如果你不告诉我点踩的原因,比如里面有错误,那么不仅我没有进步,别人也可能会继续看到错误的东西。所以,如果你发现了任何错误或者不满,正面告诉我,对我以及以后看文章的网友都是件好事。 Copyright © 2023 leiyu.cn. All Rights Reserved. 磊宇云计算 版权所有 许可证编号:B1-20233142/B2-20230630 山东磊宇云计算有限公司 鲁ICP备2020045424号
磊宇云计算致力于以最 “绿色节能” 的方式,让每一位上云的客户成为全球绿色节能和降低碳排放的贡献者