引言
在传统的单片机应用开发中,用户将调试好的软件通过编程器、ISP等方式烧写至单片机中,然后投入到工业现场、无人值守等场合使用。在某些情况下,对单片机内部软件的升级在所难免,且往往需要对单片机产品进行回收才能实现。这对于产品众多,分布区域广的单片机产品软件升级将耗费大量的人力和物力。
随着单片机技术的发展,越来越多的大容量单片机支持IAP(InApplication Programming)功能,使得软件远程升级成为了可能。结合新兴的嵌入式Internet技术,在以RTL8010AS为网卡控制器,以P89V51RD2为MCU的硬件平台上,验证了该方案的可行性和可靠性。系统方案如图1所示。
图1 系统方案
1 P89V51RD2芯片简介
P89V51RD2是Philips公司推出的一款80C51微控制器,内置64 KB的Flash和1 024字节的RAM;选择其X2方式(每个机器周期包含6个时钟)的时钟频率运行,可在相同时钟频率下获得2倍的吞吐量;内置的Flash程序存储器支持并行、串行ISP和IAP,允许随时对Flash程序存储器重新配置,即使应用程序正在运行时也不例外;同时,还支持软件复位SWR和看门狗定时器WDT,为软件升级带来了很大的便利。
1.1 Flash存储器结构
P89V51RD2单片机内部有2块Flash: Block0为64 KB,用来存储用户代码;Block1为8 KB,用来存储由Philips公司提供的ISP/IAP代码,地址空间与Block0重叠。Block0 Flash将64 KB分为512个扇区,每个扇区含有512字节,如图2所示。
图2 P89V51RD2 Flash存储器结构
1.2 IAP与相关寄存器
P89V51RD2的IAP通过R1、ACC、DPTR等寄存器来传递参数,其中R1传递命令参数。P89V51RD2的IAP命令参数如表1所列。
P89V51RD2的IAP是通过FCF(B1H)来配置的。通过清零FCF寄存器的BSEL(FCF.0)位来访问IAP程序。 通过将FCF寄存器的SWR(FCF.1)从0变为1来实现软件复位。软件复位后,程序计数器指〖3〗向0000H地址。除FCF.1和WDTC.2外,所有SFR寄存器都被设置成各自的复位值。
表1 IAP编程命令
2IAP的软件实现
Philips 公司针对P89V51RD2 的IAP功能在Block1中提供了封装好的子程序,只要用正确的方法调用此子程序就能够实现IAP 操作。
2.1 IAP的汇编实现
这里笔者用汇编语言调用IAP命令,代码如下:
?PR?_write_IAP?rwIAPSEGMENTCODE
?PR?_erase_IAP?rwIAPSEGMENTCODE
PUBLIC _write_IAP
PUBLIC_erase_IAP
FCFEQU0B1H
CMD_WRITEEQU02H
CMD_EREASEEQU08H
IAP_ENTRYEQU1FF0H
RSEG?PR?_write_IAP?rwIAP
_write_IAP:
PUSHIE
CLREA
;禁止中断,防止切换至Block1时中断程序无法正确返回
MOV R1, #CMD_WRITE;调用写命令
MOV DPH, R6
MOV DPL, R7
MOV A, R5
ANL FCF, #0FCH;切换至Block1
LCALL IAP_ENTRY
ORL FCF, #01H;返回Block0
MOV R7, A;由R7返回是否成功
POP IE
RET
RSEG?PR?_erase_IAP?rwIAP
_erase_IAP:
PUSH IE
MOVR1, #CMD_EREASE ;调用扇区擦除命令
MOVDPH, R6
MOVDPL, R7
ANLFCF, #0FCH ;切换至Block1
LCALLIAP_ENTRY
ORLFCF, #01H;返回Block0
MOVR7, A;由R7返回是否成功
POPIE
RET
END
由于执行“ANL FCF, #0FCH”语句后,FCF的BSEL、SWR位被清零,Block0中低位地址0000H~1FFFH被Block1覆盖(见图2),因此为了能够让程序正常返回用户程序,需要子程序定位在2000H代码段之上。Keil uVision3的链接器BL51/LX51提供了非常方便的代码定位设置,在BL51 Locate选项卡“Code”中填入PR?_erase_IAP?rwIAP(0x3000),?PR?_write_IAP?rwIAP(0x3015)即可。Keil的代码定位详见参考文献[1]。
2.2 IAP与主程序接口
本方案将用户代码置于3000H(sector24)之上:
#define IAP_ADDR0x3000
主程序均采用C语言编写,对IAP函数声明如下:
extern uchar write_IAP(uint, uchar);
extern uchar erase_IAP(uint);
与IAP相关部分代码如下:
for (i=24; i<512; i++) {
/*擦除3000H地址以上的所有扇区*/
erase_IAP(i*512);
}
for (i=0; i<tcp_len; i++) {
/*tcp_len为hex文件长度*/
write_IAP(3000+i; tcp_buf[i]);
/*将更新的hex文件烧入Flash中*/
}
((void (code *)(void))IAP_ADDR) ( );
/*跳转至应用程序地址空间*/
Keil中C语言与汇编语言的调用详见参考文献[1]。
3 嵌入式TCP/IP
图3 软件流程
单片机软件升级的远程化是通过将单片机接入Internet来实现的。目前将嵌入式设备接入Internet有多种方式,其中将一个精简的嵌入式TCP/IP协议栈固化在MCU内部更具有经济性。考虑到单片机内部资源有限,只实现了ARP、ICMP(ping)、IP、TCP等基本的网络协议。该协议栈参照了UIP[2]的实现方式。软件流程如图3所示。
嵌入式TCP/IP协议栈提供了下列函数接口:
◆ 网卡RTL8019驱动:rtl8019_receive()、rtl8019_send()。
◆ ARP(Address Resolution Protocol)处理:arp_in()、arp_out()。
◆ IP、ICMP、TCP协议的封装和分用[3]处理:tcp_process()。
全局缓冲tcp_buf[tcp_len]用于存放网卡驱动函数已接收或待发送的数据帧。tcp_process()主要完成TCP连接的建立和终止与TCP数据的传输[3]。TCP连接建立之后,客户端通过本地TCP连接传送更新的hex文件至远程单片机中,此时IAP函数erase_IAP()、write_IAP()在tcp_process()中被调用完成系统应用程序的升级。再将SWR(FCF.1)位清零后置位软件复位系统,从而切换至更新的应用程序运行。
4 用户应用程序的设计
嵌入式TCP/IP协议栈占用了Block0中底端10 KB左右的空间,升级的用户应用程序需要的代码定位在IAP_ADDR(0x3000)之上。用户的应用程序设计需要注意以下几点:
① 在Keil中,将“BL51 Locate”“Code Range:”中设置为0x30000xFFFF。
② 由于Keil的输出文件为Hex80,格式为 :NNAAAARRDD..DDCC<crlf>[4] ,不能直接烧录至Flash中。为减轻下位机的负担,可以使用hexbin2.exe[5]将hex文件转化成bin文件。
③ 用系统自带的“超级终端”建立TCP/IP(Winsock)连接,“发送文本文件”将bin文件远程传送至远程单片机中。具体操作方法见参考文献[6]。
结语
虽然本方案仅在Philips公司的P89V51RD2单片机上获得验证,但同样适用于大多数IAP单片机。另外,TCP/IP是一种面向连接[3]的可靠传输协议,其可靠性和传输效率都有较好的保证。这种基于TCP/IP的单片机软件远程升级的方案简单、便捷,为产品后期的维护和升级提供了一种较好的解决途径。