您的位置 首页 系统

AVR之BOOTLOADER技能详解

ATmega128具备引导加载支持的用户程序自编程功能(In-SystemProgrammingbyOn-chipBootProgram),它提供了一个真正的由MCU本身自动下…

ATmega128具有引导加载支撑的用户程序自编程功用(In-System Programming by On-chipBoot Program),它供给了一个真实的由MCU本身主动下载和更新(选用读/写一起”Read-While-Write”进行的办法)程序代码的体系程序 自编程更新的机制。运用AVR的这个功用,能够完结在运用编程(IAP)以及完结体系程序的长途主动更新的运用。
IAP的实质便是,MCU能够灵敏地运转一个常驻Flash的引导加载程序(Boot Loader Program),完结对用户运用程序的在线自编程更新。引导加载程序的规划能够运用任何的可用的数据接口和相关的协议读取代码,或许从程序存储器中读取 代码,然后将代码写入(编程)到Flash存储器中。
引导加载程序有才能读写整个Flash存储器,包含引导加载程序地点的引导加载区本身。引导加载程序还能够对本身进行更新修正,乃至能够将本身删去,使系 统的自编程才能消失。引导加载程序区的巨细能够由芯片的熔丝位设置,该段程序区还供给两组确定位,以便用户挑选对该段程序区的不同等级的维护。
本节将给出一个实践的的Boot Loader程序,它能够合作Windows中的超级终端程序,选用Xmodem传输协议,经过RS232接口下载更新用户的运用程序。
5.2.1 根本规划思维
1. Boot Loader程序的规划要害
Boot Loader程序的规划是完结IAP的要害,它有必要能过经过一个通讯接口,选用某种协议正确的接纳数据,再将完好的数据写入到用户程序区中。本例Boot Loader程序的规划要害有:
(1)选用ATmega128的USART口完结与PC之间的简易RS232三线通讯;
(2) 选用Xmodem通讯协议完结与PC机之间的数据交换;
(3)用户程序更新完结后主动转入用户程序履行;
(4) Boot Loader程序选用C言语内嵌AVR汇编办法编写,阅览了解便利,可移植性强,代码小于1K字。
2. Xmodem通讯协议
Xmodem协议是一种运用拨号调制解调器的个人核算机通讯中广泛运用的异步文件运送协议。这种协议以128字节块的办法传输数据,而且每个块都运用一个 校验和进程来进行过错检测。假如接纳方关于一个块的校验和与它在发送方的校验和相一起,接纳方就向发送方发送一个认可字节。为了便于读者阅览程序,下面简 要阐明该协议的主要特点,有关Xmoden的完好的协议请参阅其它相关的材料。
(1) Xmodem的操控字符: 01H、 04H、 06H、 15H、 18H、 1AH。
(2) Xmodem传输数据块格局:”
个字节的数据块…> “。其间为开端字节;
为数据块编号字节,每次加一;是前一字节的反码;接下来是长度为128字节的数据块;最终的是128字节数据的CRC校验码,长度为2个字节。
(3)接纳端收到一个数据块并校验正确时,回送;接纳过错回送;而回送表明要发送端中止发送。
(4) 发送端收到后,可持续发送下一个数据块(packNO+1);而收到则可再次重发上一个数据块。
(5)发送端发送表明悉数数据发送完结。假如最终需求发送的数据缺乏128个字节,用填满一个数据块。
(6) 操控字符”C”有特别的效果,当发送端收到”C”操控字符时,它回重新开端以CRC校验办法发送数据块(packNO = 1)。
(7) 每发送一个新的数据块
加1,加到OxFF后下一个数据块的
为零。
(8) 校验办法选用16位CRC校验(X^16 + X^12 + X^5 + 1)。
5.2.2 源程序代码
下面给出的源程序是在ICCAVR中完结的。
/*****************************************************
选用串行接口完结Boot_load运用的实例
华东师大电子系 马 潮 2004.07
Compiler: ICC-AVR 6.31
Target: Mega128
Crystal: 16Mhz
Used: T/C0,USART0
*****************************************************/
#include
#define SPM_PAGESIZE 256 //M128的一个Flash页为256字节(128字)
#define BAUD 38400 //波特率选用38400bps
#define CRYSTAL 16000000 //体系时钟16MHz
//核算和界说M128的波特率设置参数
#define BAUD_SETTING (unsigned char)((unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1)
#define BAUD_H (unsigned char)(BAUD_SETTING>>8)
#define BAUD_L (unsigned char)BAUD_SETTING
#define DATA_BUFFER_SIZE SPM_PAGESIZE //界说接纳缓冲区长度
//界说Xmoden操控字符
#define XMODEM_NUL 0x00
#define XMODEM_SOH 0x01
#define XMODEM_STX 0x02
#define XMODEM_EOT 0x04
#define XMODEM_ACK 0x06
#define XMODEM_NAK 0x15
#define XMODEM_CAN 0x18
#define XMODEM_EOF 0x1A
#define XMODEM_RECIEVING_WAIT_CHAR C
//界说全局变量
const char startupString[]=”Type d download, Others run app.\n\r\0″;
char data[DATA_BUFFER_SIZE];
long address = 0;
//擦除(code=0x03)和写入(code=0x05)一个Flash页
void boot_page_ew(long p_address,char code)
{
asm(“mov r30,r16\n”
“mov r31,r17\n”
“out 0x3b,r18\n”); //将页地址放入Z存放器和RAMPZ的Bit0中
SPMCSR = code; //存放器SPMCSR中为操作码
asm(“spm\n”); //对指定Flash页进行操作
}
//填充Flash缓冲页中的一个字
void boot_page_fill(unsigned int address,int data)
{
asm(“mov r30,r16\n”
“mov r31,r17\n” //Z存放器中为填冲页内地址
“mov r0,r18\n”
“mov r1,r19\n”); //R0R1中为一个指令字
SPMCSR = 0x01;
asm(“spm\n”);
}
//等候一个Flash页的写完结
void wait_page_rw_ok(void)
{
while(SPMCSR & 0x40)
{
while(SPMCSR & 0x01);
SPMCSR = 0x11;
asm(“spm\n”);
}
}
//更新一个Flash页的完好处理
void write_one_page(void)
{
int i;
boot_page_ew(address,0x03); //擦除一个Flash页
wait_page_rw_ok(); //等候擦除完结
for(i=0;i//将数据填入Flash缓冲页中
{
boot_page_fill(i, data+(data[i+1]//将缓冲页数据写入一个Flash页
wait_page_rw_ok(); //等候写入完结
}
//从RS232发送一个字节
void uart_putchar(char c)
{
while(!(UCSR0A & 0x20));
UDR0 = c;
}
//从RS232接纳一个字节
int uart_getchar(void)
{
unsigned char status,res;
if(!(UCSR0A & 0x80)) return -1; //no data to be received
status = UCSR0A;
res = UDR0;
if (status & 0x1c) return -1; // If error, return -1
return res;
}
//等候从RS232接纳一个有用的字节
char uart_waitchar(void)
{
int c;
while((c=uart_getchar())==-1);
return (char)c;
}
//核算CRC
int calcrc(char *ptr, int count)
{
int crc = 0;
char i;

while (–count >= 0)
{
crc = crc ^ (int) *ptr++ //退出Bootloader程序,从0x0000处履行运用程序
void quit(void)
{
uart_putchar(O);uart_putchar(K);
uart_putchar(0x0d);uart_putchar(0x0a);
while(!(UCSR0A & 0x20)); //等候完毕提示信息回送完结
MCUCR = 0x01;
MCUCR = 0x00; //将中断向量表搬迁到运用程序区头部
RAMPZ = 0x00; //RAMPZ清零初始化
asm(“jmp 0x0000\n”); //跳转到Flash的0x0000处,履行用户的运用程序
}
//主程序
void main(void)
{
int i = 0;
unsigned char timercount = 0;
unsigned char packNO = 1;
int bufferPoint = 0;
unsigned int crc;
//初始化M128的USART0
UBRR0H = BAUD_H;
UBRR0L = BAUD_L; //Set baud rate
UCSR0B = 0x18; //Enable Receiver and Transmitter
UCSR0C = 0x0E; //Set frame. format: 8data, 2stop bit
//初始化M128的T/C0,15ms主动重载
OCR0 = 0xEA;
TCCR0 = 0x0F;
//向PC机发送开端提示信息
while(startupString!=\0)
{
uart_putchar(startupString);
i++;
}
//3秒种等候PC下发”d”,不然退出Bootloader程序,从0x0000处履行运用程序
while(1)
{
if(uart_getchar()== d) break;
if (TIFR & 0x02) //timer0 over flow
{
if (++timercount > 200) quit(); //200*15ms = 3s
TIFR = TIFR|0x02;
}
}
//每秒向PC机发送一个操控字符”C”,等候操控字〈soh〉
while(uart_getchar()!=XMODEM_SOH) //receive the start of Xmodem
{
if(TIFR & 0x02) //timer0 over flow
{
if(++timercount > 67) //wait about 1 second
{
uart_putchar(XMODEM_RECIEVING_WAIT_CHAR); //send a “C”
timercount=”0″;
}
TIFR=”TIFR” | 0x02;
}
}
//开端接纳数据块
do
{
if ((packNO == uart_waitchar()) && (packNO ==(~uart_waitchar())))
{ //核对数据块编号正确
for(i=0;i//接纳128个字节数据
{
data[bufferPoint]= uart_waitchar();
bufferPoint++;
}
crc = (uart_waitchar()//接纳2个字节的CRC效验字
if(calcrc(&data[bufferPoint-128],128)==crc) //CRC校验验证
{ //正确接纳128个字节数据
while(bufferPoint >= SPM_PAGESIZE)
{ //正确承受256个字节的数据
write_one_page(); //收到256字节写入一页Flash中
address += SPM_PAGESIZE; //Flash页加1
bufferPoint = 0;
}
uart_putchar(XMODEM_ACK); //正确收到一个数据块
packNO++; //数据块编号加1
}
else
{
uart_putchar(XMODEM_NAK); //要求重发数据块
}
}
else
{
uart_putchar(XMODEM_NAK); //要求重发数据块
}
}while(uart_waitchar()!=XMODEM_EOT); //循环接纳,直到悉数发完
uart_putchar(XMODEM_ACK); //告诉PC机悉数收到

if(bufferPoint) write_one_page(); //把剩下的数据写入Flash中
quit(); //退出Bootloader程序,从0x0000处履行运用程序
}
程序的主体部分选用C高档编写,结构性好,程序的相应部分都给出了比较具体的注释阐明,读者十分简略读懂和了解。下面再对程序做进一步的阐明。
(1) 函数”void write_one_page(void)” 完结了对ATmega128一个Flash页的完好编程处理。当程序从串口正确接纳到256个字节后,(ATmega128一个Flash页为128个 字),便调用该函数将其写入ATmega128一个Flash页中。函数先将一个指定的Flash页进行擦除;然后将数据填入Flash的缓冲页中,最终 将Flash 缓冲页的数据写入到该指定的Flash页中(具体技术细节见第二章相关内容的介绍)。
(2) 一个Flash页的擦除、写入,以及填充Flash缓冲页的函数选用内嵌AVR汇编完结,在ICCAVR中,存放器R16、R17、R18、R19用于传递一个C函数的第1、2个参数(int类型)或第1个乘数(long类型),具体参阅ICCAVR运用阐明。
(3) 函数”void quit(void)”的用处是退出Bootloader程序,从Flash的0x0000处履行用户的运用程序。在履行强行跳转指令”jmp 0x0000″前,对存放器MCUCR的操作是将中断向量地址搬迁回运用程序区的头部,因为在ICCAVR环境中编译Bootloader程序时,其主动 把中断向量地址搬迁到了Bootloader区的头部。为了保证能正确履行用户的程序,在跳转前需求把中断向量地址迁再移回运用程序区的头部。
(4)在这段Bootloader程序中运用的硬件资源为T/C0和USART0,用户在编写其运用程序时,应首要对这两个硬件资源相关的存放器重新做初始化。
(5) Bootloader程序占具并住留在Flash的最高1K字空间内,因而实践的运用程序空间为63K字(126K字节),所以用户编写的运用程序不得超 出126K字节。一起应将ATmega128的熔丝位BLB12、BLB11的状况设置为”00″,制止SPM和LPM指令对Bootloader区的读 写操作,已保证Bootloader程序不被改写和擦除。
5.2.3 IAP的完结与运用
1. Bootloader程序的编译与下载
首要在ICCAVR中新建一个工程项目,并依照生成Bootloader程序代码的要求进行正确的设置。翻开Project -> Options的Compiler Options设置选项窗口,见图5.1:
(1) 在Device Configration栏中选定器材ATMega128;
(2) 选定Use RAMPZ/ELPM项(ATMega128的Flash > 64K字节);
(3) Program Type选定为Boot Loader;
(4)Boot Size挑选1K Words。
正确设置好编译选项后输入C的源代码,然后编译生成.HEX的下载代码程序。
在下载HEX文件前还要对ATmega128芯片的熔丝位进行正确的装备:
(1) 装备M103C熔丝位,使芯片作业于ATmega128办法;
(2) 装备BOOTSZ1和BOOTSZ0熔丝位,设定BOOTLOADER区的巨细为1024个字,开端首地址为0xFC00;
(3)装备BOOTRST熔丝位,设定芯片上电起动从BOOTLOADER区的开端地址处开端,即每次RESET复位后从0xFC00处履行Bootloader程序;
(4)下载Bootloader程序的HEX文件;
(5) 装备LB2和LB1熔丝位,加密程序;
(6)装备BLB12和BLB11熔丝位,对BOOTLOADER区进行安全确定。
特别注意的是,以上对芯片熔丝位的装备以及Bootloader程序的下载,需求由ISP、或JTAG、或并行办法完结,既要完结IAP,首要还需求运用一次非IAP的编程办法来树立IAP的运用环境。
2. IAP运用
当你依照上面的办法将Bootloader程序下载完结后,就能够运用它来下载你的运用程序了。具体操作如下。
(1) 编写你的运用程序,编译生成HEX文件;
(2)运用HEX2BIN.EXE转化程序,将HEX文件转化成BIN文件;
(3)运用一般的RS232电缆将PC机的串口与ATmega128的串口衔接;
(4)翻开WINDOWS中的超级终端软件,正确设置COM口的参数:38400,1,8,无,2,无(运用2位中止位进步通讯可靠性);
(5)ATmega128上电,在PC超级终端收到”Type d download, Others run app.”的Bootloader程序发动的提示具体;
(6)3秒钟内涵PC上按下”d”键,告诉Bootloader程序转入接纳数据并更新运用程序的处理。3秒钟内没有按”d”键,PC超级终端收 到”OK”提示,Bootloader程序退出,主动转入履行芯片内原有的用户运用程序(假如有的话,不然再次发动Bootloader程序);
(7)当PC超级终端收到”C”(一秒钟一个),阐明Bootloader程序转入接纳数据和更新运用程序的处理流程,正在等候PC下发数据;
(8)在PC超级终端上的工具栏中挑选”传送->发送文件”,在发送文件窗口挑选协议”Xmodem”,文件栏中选定要下载运用程序的BIN文件,单击发送按钮;
(9) 此刻呈现文件发送窗口,显示文件发送的进程和进展,以及是否犯错;
(10)当文件悉数正确发送完结后,PC超级终端收到”OK”提示,Bootloader程序退出,主动转入履行刚更新的用户运用程序。
在ATmega128中烧入这样一个Bootloader程序,树立了IAP后,最根本的开发AVR的环境就简化成”PC+RS232电缆+方针板”。读 者在把握了Bootloader程序编写的原理后,能够编写自己的Bootloader程序,完结体系程序的主动长途网络更新等运用。
AVR的BOOTLOADER功用同其它一些芯片不同,它的BOOTLOADER程序没有固化(固定)在芯片内部(出厂为空),而是需求由用户规划完结 (实践上,你第一次下载BOOTLOADER程序还有必要运用其它的办法编程,如ISP、JTAG等),因而对一般的用户把握起来有必定的困难,不如一些其 它芯片的固化IAP运用便利。但对高手来讲,能够依据实践需求编写高档、高效、专用的BOOTLOADER程序,如从一个U盘读取数据,更新用户的运用程 序;编写一个时间炸弹,或对用户的暗码进行验证,10次不对则将体系程序毁掉等等。简略意味着运用便利,但灵敏和适应性差,而灵敏性需求你具有更高的才能 去驾御它。或许会有一天,在单片机的体系上也呈现了”病毒”程序,其原因便是运用了固化的BOOTLOADER程序。因为固化(固定)的程序选用规则揭露 (敞开)的接口,那么用一个带”病毒”的运用程序更新本来的运用程序也就垂手可得了。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qianrushi/xitong/320024.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部