本文通过对
8051
单片机的特点分析,提出了一种低成本的方法,使其软件可以利用系统已有的通信链路在
线升级。
1
基本原理
类似于其他引导装载升级程序的方法,在系统中必须始终存在一段用于程序装载的代码(
bootloader
),该
代码在启动时被运行。其基本功能是根据外部条件来判断是运行现有版本的程序还是从主机下载新程序。
8051
具有选择执行片内或者片外程序的功能,而对片内
E2PROM
编程过程相对比较复杂,因此这里将程序引导装载
代码烧结在内部程序空间中,并不准备改变;而将系统应用程序存放在片外一编程相对简单和独立的
E2PROM
内,是随时可以更新的部分。通过外围电路的支持,单片机上电复位时首先执行片内的装载程序,如图
1
所示。
该装载代码将应用程序从
E2PROM
拷贝到外部存储器(
RAM
)中以备执行,同时还通过通信接口监系统程序装
载执行过程听主机命令。当收到主机更新程序的请求后,立即接收新的应用程序内容,并在最终确认后写入扩
展
E2PROM
内。当片内程序执行完毕后,系统软件复位并执行片外
RAM
中的程序,而
RAM
的内容正是由装
载所决定的。如果
CPU
再次复位,那么将重复上述装载执行过程。
图
1
值得注意的是,在对外部程序存储器访问时,
8051
单片机只提供读指令(
MOVC
)而并不具备写指令。但
是从单片机对外部程序和数据存储器的访问时序上看具有一致性,不同的是读代码使用
PSEN
信号而读数据使
用
RD
信号。同时,单片机的
PSEN
﹑
RD
和
WR
信号不会同时有效,因此将
PSEN
和
RD
逻辑合并后,可以使
程序和数据合二为一读写成为可能。这样同一个地址单元
RD
、
WR
(
MOVX
)和
PSEN
(
MOVC
)均可以进行
访问。单片机可以使用
MOVX
写指令来更改相当于其外部程序空间中的内容。特别要注意的是,当程序和数据
共存于一片
RAM
中时,
必须使用编译器提供的相关连接命令使数据区偏离代码可能占用的区域,
否则会导致系
统混乱。
2
硬件电路
硬件参考电路如图
2
所示。
系统加电后,
由于
C3
两端电压不能瞬变,
使
D
触发器置
1
端保持一短暂低电平,
强制将单片机
EA
信号置高。在
U4
看门狗上电复位信号撤销后,单片机开始从内部程序空间
0
地址起执行。内
部装载程序先通过
P1.4
、
P1.5
模拟
I2C
总线时序从
E2PROMU3
中将应用程序代码拷贝到片外
RAM
从
0
地址起
的空间中。如果到代码拷贝结束串行口一直没有收到预定的程序下载命令,则通过软件置低
P1.6
口触发看门狗
芯片对单片机复位,
在复位脉冲的上升沿,
D
触发器锁存其输出的信号使
EA
电平翻转为低电平。
待复位信号撤
销后,单片机开始执行位于外部程序空间的系统应用程序代码。在执行外部程序时,如果看门狗再次复位,
EA
将会恢复高电平并重新执行内部装载程序。
图
2
引导装载电路
当上位机欲更改终端设备程序时,可通过串口向其发送特定的握手字符串,无论片外程序还是片内程序最
好都能识别该字符串并且复位单片机(如果是正在运行外部程序)执行内部装载程序。装载程序就绪后向上位
机发送确认回应,
并接收来自上位机的程序代码。
单片机通过置低
P1.3
允许
E2PROM
写操作,
将新的内容写入
E2PROM
中,完成程序的更新。
3
软件设计
装载程序主要有两个功能,其一是要将
E2PROM
的内容拷贝到片外
RAM
中;其二是要响应上位机的更新
程序命令并接收代码内容更新
E2PROM
。
#define
uchar
unsigned
char
#define
uintunsigned
int
sbit
WDI=P1^7;
sbit
RESET=P1^6;/*
声明外部
I2C
读写函数
*/
extern
void
I2c_wr(uchar
addh,uchar
addl,uchar
buf[],uchar
num,bit
wr);
void
main(void)
{
uchar
data
addh,addl;
uchar
data
buf[16];
uchar
j;
uint
I=0;
XBYTE[0x1fff]=0;/*
清除程序拷贝好标志
*/
WDI=~WDI;
/*
喂狗
*/
system_init();
/*
初始化
*/
for(addh=0;addh<0x10;addh++)
{
for(addl=0;addl<0xf0;addl+=16)
{/*
读入
E2PROM
地址
addh:addl16
字节内容到
buf*/
I2c_wr(addh,addl,buf,16,1);
for(j=0;j<16;j++)/*
将代码写入外部绝对地址
*/
XBYTE[I++]=buf[j];
}
I2c_wr(addh,0xf0,buf,16,1);
for(j=0;j<16;j++)
XBYTE[I++]=buf[j];
WDI=~WDI;
}
if(shake_hand==1)
{/*shake_hand
由串口中断收到握手命令后置
1*/
rcv_data();
/*
该函数负责从上位机获取程序
*/
}
XBYTE[0x1fff]=0xaa;/*
置程序拷贝好标志
*/
RESET=0;/*
复位单片机并执行外部
RAM
内的程序
*/
while(1);
}
为了确保程序在装载完全正确后才开始执行,
装载程序使用了外部
RAM
0x1fff
地址内容作为装载成功的标
志。那么相应的应用程序应判断此标志后再执行。
调试结束的装载程序烧结在单片机中,而实际的系统应用程序则存储于外部
E2PROM
内。应用中,将单片
机直接焊装在电路板上,而编程者只需通过串口或者其他形式的通信链路甚至无线的方式来更改升级目标应用
程序。
4
几点讨论
在实际应用中,最好使用严格的校验及复查方法来确保程序拷贝无误。
另外,
在从上位机下载程序时应
该制定一个可靠的通信协议,
从而保证获取的程序完全正确。
单片机在接收到上位机的代码数据时,不要急
于写入外部
E2PROM
,
而应先全部放在外部
RAM
区内,
待代码获取完毕并且通过校验检查后再把
RAM
的内容
一次性写入
E2PROM
。这样防止在获取程序的时候通信异常中断而
E2PROM
内将没有一个可以执行的程序。
从原理上看,如果片外
RAM
是非易失的,就可以不再使用
E2PROM
。但是这样系统成本变高且可靠性降
低,因为当单片机程序跑飞时很容易产生
MOVX
指令而改变
RAM
区的内容,造成程序永久性不可恢复。而在
程序跑飞的情况下,很难产生符合外部
E2PROM
接口的
I2C
写时序,同时
E2PROM
还有写保护功能。
虽然上述方法能使
8051
单片机系统具有远程升级代码的能力,但是程序装载过程将使系统的启动时间延长
数秒,在对启动时间要求较短的场合不能应用本文中介绍的方法。