1 ATMega48 Bootloader的软件实现方法
Mega48在硬件上不支持Bootloader功能,不能像其他产品那样通过编程来设置相应的熔丝位以实现Bootloader,只能通过软件来实现。在Mega48上实现Bootloader的关键在于通过软件实现程序存储器空间划分。复位后,BOOT区获得MCU控制权,自编程结束后MCU控制权返还给APP区.以下将详细介绍本文提出的两种新方法。
1.1 跳转保存法
本方法的核心在于跳转和保存,因此命名为跳转保存法。跳转指上电后MCU跳转至BOOT区,MCU控制权被BOOT区获得。保存指对APP区程序复位地址的保存,只有保存了该地址才能保证MCU控制权正常返还给APP区。
跳转保存法采用一般分区方式,即APP区位于程序存储器空间的低地址处,BOOT区在高地址处。因本文使用的上位机软件为AVROSP,BOOT区需占用1 KB。此外,由于ATMega48不支持通过熔丝位修改程序的复位向量,故需多划分给BOOT区4个页面大小的空间。
为提高程序的可移植性,可使用预定义语句来划分BOOT区大小,具体实现如下:
#define PAGESIZE 64
//每个页面由64个字节组成
#define APP_PAGES ((4*1024/PAGESIZE) - ((1*1024+256)/PAGESIZE))
//APP区的页面数
#define APP_END APP_PAGES*PAGESIZE
//APP区共占用的字节数
在编译过程中,由于ICCAVR编译器只支持标准的BOO了区大小设置,即256/512/1024/2048 KB。故使用下面方法定义BOOT区大小;
#pragma text:mytext
voidboot()...
#pragma text;text
编译过程中,在ProjectOptions→Target的Other Options中,添加“-bmytext;0x????”,其中0x????为BOOT区开始的地址。这样就可以根据实际需要设定BOO了区大小。这对于整个程序空间只有4 KB的ATMcga48来说,是非常适合的。程序具体流程如图1所示。
如图1所示,BOOT区程序块的第一步就是读取EEPROM中的APP区原复位地址,以便单片机在执行BOOT区程序条件不成立时,跳转到APP区执行程序。
EEPROM_READ(0xfe,AppReset);
当执行BOOT区程序条件成立时,单片机将执行BOOT区程序来更新APP区中的内容。这里特别要注意对即将更新到APP区内程序复位地址的处理:保存该程序中复位地址到RAM中,并修改该地址为BOOT区人口地址。这个工作必须在页面填充前完成,否则在更新后,单片机复位运行不会首先跳转到BOOT区。
if(address==o){
AppReset=data;
data=BootReset; //BOOT区的入口
BootReset=0x1300
}
BOOT区程序块最后一步是对APP区程序复位地址的保存。只有通过上电复位才能移交MCU控制权给APP区,这将导致RAM被清零。为了保存RAM中的原APP区程序复位地址,需上电复位前,将这个地址保存到EEPROM中。
EEPROM_WRITE(Oxfe,APPReset);
值得一提的是,在第一次运行时,程序并不能直接跳转到BOOT区首地址,所以第一次运行时,APP区内容应为空。这样,当单片机上电运行时,程序指针(PC)会自增向下运行到第一句可执行代码,即BOOT区中的首行代码。同样,第一次运行时也不可能读取出正确的返回APP区的入口地址(取出值为0xFF),所以第一次运行时必须保证执行BOOT区程序条件成立,否则将无法正确跳回到APP区。只有执行了BOOT区程序,才能写入正确的APP返回地址到EEPROM中,从而为以后的运行做好准备。
跳转保存法遵循了Bootloader的常规实现流程,但它的MCU控制权交接处理比较复杂,下文将提到的倒置法就很好地解决了这个问题。
1.2 倒置法
一般来说,程序存储区的上部为NPP区,下部为BOOT区,这也是常规方法所采取的分区方法。这种分区方法由支持Bootloader功能的芯片程序存储区中RWW和NRWW的划分方式所决定的。针对Mega48,它的程序存储区没有RWW区和NRWW区之分,SPM指令可以在整个Flash区中执行,所以大可不必拘泥于一般规律,完全可以把APP区和BOOT区倒置,即把程序存储区的上部划分为BOOT区,下部划分为APP区。本文中将这种分区方法称为倒置分区方法。
倒置法背弃了常规分区形式,创新地采用倒置分区法对程序存储区进行分区。这样,在每次上电后,BOOT区自动获得MCU控制权,而不需修改和保存用户程序复位向量,这比跳转保存法简便。BOOT区大小划分仍使用预定义语句,具体实现如下:
#define PAGESIZE 64
#define APP_PAGES((4096/PAGESIZE)-(1024/PAGESIZE))
#define APP_END APP_PAGES*PAGESIZE
在对APP区程序编译时,编译器的配置方法类似于常规方法中对BOOT区程序编译时的配置.倒置法流程如图2所示。
如图2所示,当执行BOOT区程序条件不成立时,程序跳转至APP区入口处,该地址是固定的(4096~1024)。
具体实现如下:
Asm(“jmp 0x0C00\n”);
//跳转到APP区开始执行
需要注意的是,中断向量空间在程序存储器的低地址上,这正好位于BOOT区中,故为了增加APP区和B00T区两部分程序的独立性,可在APP区中人为构建除复位向量以外的其他中断向量空间。在自编程过程中,实施页写入时,不是按常规方法的顺序从第一个页开始更新,因为需更新的是APP区所在的页面,而不是BOOT区所在的,所以要从APP区所在的页面处开始更新。
倒置法打破了常规的分区模式,大大简化了对MCU控制权的处理,但其页面更新处理较为繁琐。跳转保存法则因沿袭了常规处理方式,所以页面更新无需做特别处理,并能很好地兼容硬件实现Bootloader的程序。用户可以根据实际需要来选择方法。
2 硬件测试原理图及结果
调试硬件原理图如图3所示。图3中的ISP接口是用来完成第一次非Bootloadcr的编程方式,从而建立Bootloader的应用环境。这以后的每次编程均可以通过串口直接完成,不需要任何其他设备。
在本文中使用的编译环境为ICCAVR DEMO版,通过使用AVR单片机的井口下载线完成BOOT区程序的首次写入。 自编程过程中使用的上位机软件为AVROSP。经测试两种方法均能可靠运行。
结 语
综上所述,本文研究并实现了Mega48的Bootloader功能,提出了两种软件实现方法,并分别在硬件上成功实现,为基于Mcga48编写高效,专用的Bootloader程序奠定了基础。