新闻中心

EEPW首页>嵌入式系统>设计应用> AVR_M8 BootLoader应用范例

AVR_M8 BootLoader应用范例

作者: 时间:2016-11-13 来源:网络 收藏
//meg8bootloader
//BOOTSZ1BOOTSZ0=00
//meg8bootloader
//BOOTSZ1BOOTSZ0=00
#include
#defineSPM_PAGESIZE64//M8的一个Flash页为64字节(32字)

#defineBAUD38400//波特率采用38400bps
#defineCRYSTAL8000000//系统时钟8MHz
//计算和定义M128的波特率设置参数
#defineBAUD_SETTING(unsignedchar)((unsignedlong)CRYSTAL/(16*(unsignedlong)BAUD)-1)
#defineBAUD_H(unsignedchar)(BAUD_SETTING>>8)
#defineBAUD_L(unsignedchar)BAUD_SETTING

#defineDATA_BUFFER_SIZE128//定义接收缓冲区长度
//定义Xmoden控制字符
#defineXMODEM_NUL0x00
#defineXMODEM_SOH0x01
#defineXMODEM_STX0x02
#defineXMODEM_EOT0x04
#defineXMODEM_ACK0x06
#defineXMODEM_NAK0x15
#defineXMODEM_CAN0x18
#defineXMODEM_EOF0x1A
#defineXMODEM_RECIEVING_WAIT_CHARC
//定义 全局变量
constcharsta rtupString[]="Typeddownload,Othersrunapp.nr";
constcharloadString[]="downloadovernr";
chardata[DATA_BUFFER_SIZE];
unsignedintaddress=0;
//擦除(code=0x03)和写入(code=0x05)一个Flash页
voidboot_page_ew(unsignedintp_address,charcode)
{
asm("movr30,r16n"
"movr31,r17n"
//"out0x3b,r18n");
);//将页地址放入Z寄存器和RAMPZ的Bit0中
SPMCR=code;//寄存器SPMCSR中为操作码
asm("spmn");//对指定Flash页进行操作
}
//填充Flash缓冲页中的一个字
voidboot_page_fill(unsignedintaddress,intdata)
{
asm("movr30,r16n"
"movr31,r17n"//Z寄存器中为填冲页内地址
"movr0,r18n"
"movr1,r19n");//R0R1中为一个指令字
SPMCR=0x01;
asm("spmn");
}
//等待一个Flash页的写完成
voidwait_page_rw_ok(void)
{
while(SPMCR&0x40)
{
while(SPMCR&0x01);
SPMCR=0x11;
asm("spmn");
}
}
//更新一个Flash页的完整处理
voidwrite_two_page(void)
{
//128字节分两页
inti;
boot_page_ew(address,0x03);//擦除一个Flash页
wait_page_rw_ok();//等待擦除完成
for(i=0;i {
boot_page_fill(i,data[i]+(data[i+1]<<8));
}
boot_page_ew(address,0x05);//将缓冲页数据写入一个Flash页
wait_page_rw_ok();//等待写入完成

//写第2页
address+=SPM_PAGESIZE;//Flash页加1
boot_page_ew(address,0x03);//擦除一个Flash页
wait_page_rw_ok();//等待擦除完成
for(i=0;i {
boot_page_fill(i,data[SPM_PAGESIZE+i]+(data[SPM_PAGESIZE+i+1]<<8));
}

boot_page_ew(address,0x05);//将缓冲页数据写入一个Flash页
wait_page_rw_ok();//等待写入完成

}
//从RS232发送一个字节
void uart_putchar(charc)
{
while(!(UCSRA&0x20));
UDR=c;
}
//从RS232接收一个字节
intuart_getchar(void)
{
unsignedcharstatus,res;
if(!(UCSRA&0x80))return-1;//nodatatobereceived
status=UCSRA;
res=UDR;
if(status&0x1c)return-1;//Iferror,return-1
returnres;
}
//等待从RS232接收一个有效的字节
charuart_waitchar(void)
{
intc;
while((c=uart_getchar())==-1);
return(char)c;
}
//计算CRC
intcalcrc(char*ptr,intcount)
{
intcrc=0;
chari;

while(--count>=0)
{
crc=crc^(int)*ptr++<<8;
i=8;
do
{
if(crc&0x8000)
crc=crc<<1^0x1021;
else
crc=crc<<1;
}while(--i);
}
return(crc);
}
//退出Bootloader程序,从0x0000处执行应用程序
voidquit(void)
{
uart_putchar(O);uart_putchar(K);
uart_putchar(0x0d);uart_putchar(0x0a);
uart_putchar(0x0d);uart_putchar(0x0a);
while(!(UCSRA&0x20));//等待结束提示信息回送完成
MCUCR=0x01;
MCUCR=0x00;//将中断向量表迁移到应用程序区头部
//RAMPZ=0x00;//RAMPZ清零初始化
asm("jmp0x0000n");//跳转到Flash的0x0000处,执行用户的应用程序
}
//主程序
voidmain(void)
{
inti=0;
unsignedchartimercount=0;
unsignedcharpackNO=1;
intbufferPoint=0;
unsignedintcrc;
//初始化M128的USART0
UBRRH=BAUD_H;
UBRRL=BAUD_L;//Setbaudrate
UCSRB=0x18;//EnableReceiverandTransmitter
//UCSRC=0x06;//Setframeformat:8data,2stopbit
UCSRC=0x8e;//8位数据+2位STOP位,m8与m128的URSEL不同
//UCSRC=0x86;//8位数据+1位STOP位,m8与m128的URSEL不同
//初始化M8的T/C2,15ms自动重载
OCR2=0xEA;
TCCR2=0x0F;
//向PC机发送开始提示信息
while(startupString[i]!=)
{
uart_putchar(startupString[i]);
i++;
}
//3秒种等待PC下发“d”,否则退出Bootloader程序,从0x0000处执行应用程序

while(1)
{
if(uart_getchar()==d)break;
if(TIFR&0x80)//timer2overflow
{
if(++timercount>200)quit();//200*15ms=3s
TIFR=TIFR|0x80;
}
}
//每秒向PC机发送一个控制字符“C”,等待控制字〈soh〉
while(uart_getchar()!=XMODEM_SOH)//receivethestartofXmodem
{
if(TIFR&0x80)//timer2overflow
{
if(++timercount>67)//waitabout1second
{
uart_putchar(XMODEM_RECIEVING_WAIT_CHAR);//senda"C"
timercount=0;
}
TIFR=TIFR|0x80;
}
}
//开始接收数据块
do
{
if((packNO==uart_waitchar())&&(packNO==(~uart_waitchar())))
{//核对数据块编号正确
//SPM_PAGESIZEW
for(i=0;i<128;i++)//接收128个字节数据
{
data[bufferPoint]=uart_waitchar();
bufferPoint++;
}
crc=(uart_waitchar()<<8);
crc+=uart_waitchar();//接收2个字节的CRC效验字
if(calcrc(&data[bufferPoint-128],128)==crc)//CRC校验验证
{//正确接收128个字节数据
while(bufferPoint>=SPM_PAGESIZE)
//while(bufferPoint>=64)//(m8每页64字节)
{//正确接受128个字节的数据
//收到128字节写入2页Flash中
write_two_page();

address+=SPM_PAGESIZE;
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机全部收到
i=0;
while(loadString[i]!=)
{
uart_putchar(loadString[i]);
i++;
}

quit();//退出Bootloader程序,从0x0000处执行应用程序

}


关键词:AVRBootLoade

评论


技术专区

关闭