最近一直利用業(yè)余時(shí)間寫自己的“基于AVR-BootLoader”邑滨,啟發(fā)是由于一次在ourAVR論壇看到了紹子陽(yáng)的bootloader掖看,聯(lián)想到公司在用AVR MCU哎壳,但每次升級(jí)程序都要花費(fèi)很大的力氣車馬勞頓的跑到工程現(xiàn)場(chǎng)归榕,而且很多機(jī)器還安裝在國(guó)外刹泄,為了升級(jí)一次程序發(fā)費(fèi)了很多的人力物力財(cái)力循签,加上公司的機(jī)器目前大部分都配有遠(yuǎn)程監(jiān)控系統(tǒng)县匠,所以本人決定寫一個(gè)具有自有產(chǎn)權(quán)的“AVR-BootLoader”乞旦。
特別說(shuō)明:本“AVR-BootLoad”軟件代碼屬上海霜蟬版權(quán)所有兰粉,在此貢獻(xiàn)發(fā)布玖姑,僅限于個(gè)人免費(fèi)使用不得用于商業(yè)用途焰络,本人也不保證代碼的嚴(yán)謹(jǐn)性闪彼,如在升級(jí)中出現(xiàn)任何問(wèn)題與本人無(wú)關(guān)畏腕,本人已測(cè)試過(guò)Atmega64A與Atmega128把夸。話不多說(shuō)了上源代碼扎即,網(wǎng)友們和AVR愛好者可以拷貝到CodeWizardAVR V2.03.9編譯器下編譯谚鄙。
需要討論或有遇到BUG的網(wǎng)友們可以聯(lián)系我:QQ:285247488 ?mail:shw@scicala.com?
上位機(jī)截圖:
遠(yuǎn)程升級(jí)DTU:
遠(yuǎn)程升級(jí)連接云平臺(tái)虛擬串口:
//? ? ? ? ??關(guān)于上海霜蟬-AVR_BootLoade_V1.00
// 1、軟件版本V1.00 編譯環(huán)境CodeWizardAVR V2.03.9 Standard;
// 2傻盟、支持本公司常用的三種AVR芯片;
// 3娘赴、支持標(biāo)準(zhǔn)Xmodem和擴(kuò)展Xmodem_1K協(xié)議;
// 4、聯(lián)機(jī)握手密碼為"00",握手成功手的等待文件超時(shí)為1分鐘;
// 5隅肥、默認(rèn)復(fù)位等待3S退出boot到用戶程序或循環(huán)運(yùn)行boot;
// 6腥放、支持1分鐘以內(nèi)的斷網(wǎng)續(xù)傳;
// 7秃症、支持連續(xù)10幀以內(nèi)數(shù)據(jù)錯(cuò)誤的重傳;
// 8种柑、支持下載過(guò)程中的取消超作;
// 9莹规、支持當(dāng)收到包時(shí),接收過(guò)程中每個(gè)字符的超時(shí)間隔為 1 秒;
// 10欢际、支持所有的超時(shí)及錯(cuò)誤事件至少重試 10 次;
// 11损趋、支持?jǐn)?shù)等待超時(shí)6S的請(qǐng)求;
// 12浑槽、Boot Loader - Size:1024words;
// 13、支持傳輸速度:38.400KB/S~2.400KB/S;
// 14镊靴、支持公司常用最多的三個(gè)型號(hào)ATMEGA32,64,128偏竟。
// 15踊谋、支持開門狗自定義開關(guān),自定義時(shí)鐘頻率
/*****************************************************
This?program?was?produced?by?the
CodeWizardAVR?V2.03.9?Standard
Automatic?Program?Generator
?Copyright?1998-2008?Pavel?Haiduc,?HP?InfoTech?s.r.l.
Project ?????:?AVR_BootLoader
Version?????:?V1.00
Date ? ????? :?2014-7-19
Author??????:?Sui?Hongwei
Company?: SCICALA
Comments:
Chip?type ? ? ? ? ? ? ? ? ??:?ATmega64L
Program?type ? ? ? ? ? ? :?Boot?Loader?-?Size:1024words
AVR?Core?Clock?frequency:?16.000000?MHz
Memory?model????????????:?Small
External?RAM?size???????:?0
Data?Stack?size ? ? ? ? ??:?1024
*****************************************************/
#include?"AVR_boot.h"http://頭文件包含
//--------------------------------------------------//
//同步密碼長(zhǎng)度
#define?CONNECTCNT? ? ? ? ?7
//同步密碼
uchar?KEY_Data[10]?=?{"SCICALA"};
//?Declare?your?global?variables?here
//--------------------------------------------------//
//全局變量定義
ucharRX_buff[BUFSIZE];//數(shù)據(jù)拉收緩存
ucharFrame_State,SOH_Wait_cnt;//幀狀態(tài),幀頭等待計(jì)數(shù)
uintTime_cnt,Error_cnt;//超時(shí)計(jì)數(shù)嫌褪,連續(xù)幀錯(cuò)誤計(jì)數(shù)
uintbuffptr,buffptr_old,buffptr_New;//數(shù)據(jù)緩存指針必須大于1024
ulongFlashAddr;//?Flash地址
ucharUpdatedSta;//升級(jí)標(biāo)志
//-----------------------------------------------//
//擦除(code=0x03)和寫入(code=0x05)一個(gè)Flash頁(yè)
voidboot_page_ew(ulongp_address,charcode)
{
#asm
????lddr26,y+1;R26LSB
????lddr27,y+2;R27MSB
#endasm
SPM_REG=code;//寄存器SPMCSR中為操作碼
#asm
????movr30,r26
????movr31,r27
#endasm
#ifdef??ATMEGA128
????RAMPZ=(p_address>>16);//?RAMPZ0?=?1:?ELPM/SPM可以訪問(wèn)程序存儲(chǔ)器地址$8000?-?$FFFF?(高64K字節(jié))
#endif
#asm("spm");//對(duì)指定Flash頁(yè)進(jìn)行擦操作
}
//填充Flash緩沖頁(yè)中的一個(gè)字
voidboot_page_fill(uintA_address,uintdata)
{
#asm
????LDDR30,Y+2;R30LSB
????LDDR31,Y+3;R31MSB
????LDR26,Y
????LDDR27,Y+1
????MOVR0,R26
????MOVR1,R27
????MOVR26,R30
????MOVR27,R31
????#endasm
????SPM_REG=0x01;//寄存器SPMCSR中為操作碼
????#asm
????movr30,r26
????movr31,r27
????#endasm
????#asm("spm");//對(duì)指定Flash頁(yè)進(jìn)行擦操作
}
//等待一個(gè)Flash頁(yè)的寫完成
voidwait_page_rw_ok(void)
{
????while(SPM_REG&0x40)
????{
????????while(SPM_REG&0x01);
????????SPM_REG=0x11;
????????#asm("spm");
????????while(SPM_REG&0x01);
????}
}
//-----------------------------------------------//
//更新一個(gè)Flash頁(yè)的完整處理
voidwrite_one_page(uchardata[])
{
uinti;
boot_page_ew(FlashAddr,0x03);//擦除一個(gè)Flash頁(yè)
wait_page_rw_ok();//等待擦除完成
for(i=0;i
{
????boot_page_fill(i,(uint)data[i]+(data[i+1]<<8));
????wait_page_rw_ok();
}
boot_page_ew(FlashAddr,0x05);//將緩沖頁(yè)數(shù)據(jù)寫入一個(gè)Flash頁(yè)
wait_page_rw_ok();//等待寫入完成
}
//--------------------------------------------------//
//等待串口數(shù)據(jù)1S超時(shí)自動(dòng)轉(zhuǎn)為應(yīng)答
unsignedcharWait1S_UART()
{
uchari=0;
do
{
#if?WDGEn
Watchdog_Reset();//喂狗
#endif
if(TIFR&0x10)//?OCF1A:?T/C1輸出比較A匹配標(biāo)志位
{
TIFR|=0x10;//清除Time1定時(shí)器比較匹配標(biāo)志
i++;
if(i>=4)//等待1S?250ms*4=1S
????{Frame_State=0x06;break;}//幀數(shù)據(jù)超時(shí)轉(zhuǎn)為應(yīng)答請(qǐng)求重發(fā)數(shù)據(jù)幀
}
if(UCSRAREG(COMPORTNo)&0x80)
{
UCSRAREG(COMPORTNo)|=0x80;//清除接收完成狀態(tài)
????#if?Run_LEDEn
????Run_LED;//運(yùn)行LED閃爍
????#endif
????i=100;
returnUDRREG(COMPORTNo);//讀取UDR0
}
}
while(100!=i);//等待數(shù)據(jù)||超時(shí)退出
}
//***************************************************//
//===================================================//
voidmain(void)
{
ucharpackNO,packNO_old;//包號(hào)琅拌、包號(hào)留存
uintcrc16;//接收CRC緩存
uintli;//幀計(jì)數(shù)
ucharch,cl;//包號(hào)
PORT_Init();//端口初始化
UART_Init();//串口初始化
Time1_Init();//定時(shí)器初始化250ms
#if?WDGEn
WatchDog_Enable();//打開看門狗(2S)
#else
????WatchDog_Disenable();???//禁止看門狗
#endif
#if?Wait_BootTime
Time_cnt=EEPROM_Read(EE_TimeAddr);//讀取boot運(yùn)行時(shí)間
#endif
#if?SafeUpdated_En
UpdatedSta=EEPROM_Read(EE_SafeAddr);//讀取升級(jí)成功標(biāo)志
#endif
#asm("cli")//關(guān)總中斷
#if?Delay_En????????????//是否延時(shí)
for(li=0;li<5000;li++)
{#asm("nop")}
#endif
//-----------------------------------------------//
//等待"握手"紊扬,否則退出Bootloader程序泻帮,從0x0000處執(zhí)行應(yīng)用程序
Time_cnt+=WiteTimeCnt;
cl=0;
while(1)
{
if(TIFR&0x10)//?OCF1A:?T/C1輸出比較A匹配標(biāo)志位
{
????TIFR|=0x10;//清除Time1定時(shí)器比較匹配標(biāo)志
????????#if?Run_LEDEn
????Run_LED;//運(yùn)行LED閃爍
????????#endif
????????Time_cnt--;
????if(Time_cnt==0)//等待握手超時(shí)
????{
????????#if?SafeUpdated_En
????????if(UpdatedSta)//上次升級(jí)失敗
????????????{while(1);}//復(fù)位boot
????????????else
????????????#endif
????????????{quit_boot();}//跳轉(zhuǎn)到用戶程序
????????}
????????if(UCSRAREG(COMPORTNo)&0x80)
????????{
????ch=Wait_UART();
????????????if(ch==KEY_Data[cl])
????{cl++;}
????else
????{cl=0;}
????????????//WriteCom(ch);?????????//密碼回傳
????????}
????????if(cl==CONNECTCNT)break;
}
????#if?WDGEn
????Watchdog_Reset();//喂狗
????#endif
}
//-----------------------------------------------//
//啟動(dòng)Xmodex?CRC傳數(shù)據(jù)=字符“C”,等待控制字〈soh〉
Time_cnt=TimeOutCntC;
while(1)
{
if(TIFR&0x10)//?OCF1A:?T/C1輸出比較A匹配標(biāo)志位
{
????TIFR|=0x10;//清除Time1定時(shí)器比較匹配標(biāo)志
????????#if?Run_LEDEn
????Run_LED;//運(yùn)行LED閃爍
????????#endif
????Send_UART(XMODEM_RWC);//發(fā)送"C"
????Time_cnt--;
????if(Time_cnt==0)//等待文件超時(shí)
????{
????????#if?SafeUpdated_En
????????if(UpdatedSta)//上次升級(jí)失敗
????????????{while(1);}//復(fù)位boot
????????????else
????????????#endif
????????????{quit_boot();}//跳轉(zhuǎn)到用戶程序
????????}//跳轉(zhuǎn)到用戶程序
}
if(UCSRAREG(COMPORTNo)&0x80)//串口有數(shù)據(jù)
{
????#ifdef??Xmodem
????if(Wait_UART()==XMODEM_SOH)//XMODEM命令開始0x01
????????#else???//?Xmodem_1K
????????if(Wait_UART()==XMODEM_STX)//XMODEM命令開始0x02
????????#endif
????????break;
}
????#if?WDGEn
????Watchdog_Reset();//喂狗
????#endif
}
//-----------------------------------------------//
//開始接收數(shù)據(jù)進(jìn)入Xmodem協(xié)議接收文件
//幀的兩個(gè)時(shí)間很重要:連續(xù)出錯(cuò)10次*最大幀請(qǐng)求間隔6S
//累計(jì)請(qǐng)求間隔10*6S=1min
packNO=1;//?Xmodem起始為0x01
packNO_old=0;
buffptr=0;
buffptr_old=0;
Error_cnt=0;
FlashAddr=0;
Frame_State=0x01;//第一幀不判斷幀頭
while(1)
{
switch(Frame_State)//幀狀態(tài)
{
????case0x00://接受狀態(tài)幀頭與停止信號(hào)判斷
????{
????????ch=XMODEM_NUL;//清除
????????????if(UCSRAREG(COMPORTNo)&0x80)//串口有數(shù)據(jù)
????????????{ch=Wait_UART();}//讀取幀頭或停止信號(hào)
????????????if(TIFR&0x10)//?OCF1A:?T/C1輸出比較A匹配標(biāo)志位
????????????{
????????????TIFR|=0x10;//清除Time1定時(shí)器比較匹配標(biāo)志
????????????SOH_Wait_cnt++;//等待計(jì)時(shí)250ms
????????????????if(SOH_Wait_cnt>=24)//等待幀超時(shí)請(qǐng)求數(shù)據(jù)(6S*10=1min)
????????????????{
????????????????Frame_State=0x06;//要求重發(fā)數(shù)據(jù)塊
????????????????????SOH_Wait_cnt=0;//幀請(qǐng)求計(jì)時(shí)
????????????????????#if?Run_LEDEn
????Run_LED;//運(yùn)行LED閃爍
????????????????????#endif
????????????????}
????????????}
????????????//------------------------------
????????if(ch==XMODEM_EOT)//發(fā)送結(jié)束
????????????{
????????????for(li=(buffptr_New-128);li
????{
????if((RX_buff[li++])!=0xff)break;//填充幀判斷爭(zhēng)強(qiáng)EOT抗干擾能力FF?CF
????????????????????{
????????????????????if((RX_buff[li++])!=0xcf)break;//填充幀判斷爭(zhēng)強(qiáng)EOT抗干擾能力FF?CF
????}
????????????????}
????????????????if(li==buffptr_New)
????????????????{Send_UART(XMODEM_ACK);//最后一幀應(yīng)答完成
????????????????Frame_State=0x0ff;//轉(zhuǎn)為退出boot
????????????????}
????????????????else
????????????????{
????????????????Frame_State=0x06;//要求重發(fā)數(shù)據(jù)塊
????????????????????SOH_Wait_cnt=0;//幀請(qǐng)求計(jì)時(shí)
????????????????}
????????????}
????????????#ifdef??Xmodem
????????????if(ch==XMODEM_SOH)//?Xmodem幀頭判斷
????????????#else???//?Xmodem_1K
????????????if(ch==XMODEM_STX)//?Xmodem_1K幀頭判斷
????????????#endif
????????????{
????????????Frame_State=0x01;//轉(zhuǎn)為包號(hào)檢查
????????????????SOH_Wait_cnt=0;//清除幀頭等待計(jì)時(shí)
????????????}
????}
????break;
????case0x01://包序號(hào)校驗(yàn)
????{
????????????ch=Wait1S_UART();//獲取包序號(hào)
cl=~Wait1S_UART();
????if(ch==cl)//包號(hào)對(duì)比
????????????{Frame_State=0x02;
????????????????packNO=ch;//正確保留包號(hào)
????????????}
????????????else
????????????{Frame_State=0x06;}//重發(fā)應(yīng)答ANK
????}
????break;
????case0x02://進(jìn)入二級(jí)CRC校驗(yàn)
????{
????????for(li=0;li
????{
????RX_buff[buffptr++]=Wait1S_UART();//接收數(shù)據(jù)
????????????????//幀數(shù)據(jù)接收超時(shí)1S退出for詢環(huán)旁趟,再接收2個(gè)數(shù)據(jù)或超時(shí)1S+2S轉(zhuǎn)為應(yīng)答
????????????????if(Frame_State==0x06)break;
????}
????crc16=Wait1S_UART();
????????????crc16=crc16<<8;
????crc16+=Wait1S_UART();//接收2個(gè)字節(jié)的CRC效驗(yàn)字
????if(CRC16_Word(&RX_buff[buffptr-BUFFER_SIZE],BUFFER_SIZE)==crc16)//?CRC校驗(yàn)驗(yàn)證
????{
????????????if(packNO==packNO_old)//接收相同包不寫flash
????????????{Frame_State=0x05;//正常應(yīng)答ACK
????????????????????buffptr=buffptr_old;
????????????}
????????????????else
????????????????{Frame_State=0x03;//正確應(yīng)答
????????????????????buffptr_New=buffptr;//記錄當(dāng)前數(shù)據(jù)指針
????????????????}
????????????}
????????????else
????????????{Frame_State=0x06;//應(yīng)答NAK
????????????????buffptr=buffptr_old;//去掉錯(cuò)誤數(shù)據(jù)的指針
????????????}
????}
????break;
????case0x03://校驗(yàn)通過(guò),執(zhí)行寫入
????{
????????if(FlashAddr
????{
????????????????#if?BUFFER_SIZE?<?SPM_PAGESIZE??//?---
????????????????if(buffptr>=SPM_PAGESIZE)//緩沖區(qū)滿,寫入數(shù)據(jù)耕餐;否則繼續(xù)接收
????????{//接收多個(gè)幀,寫入一頁(yè)
????????write_one_page(&RX_buff[0]);//寫入緩沖區(qū)內(nèi)容到Flash中
????????FlashAddr+=SPM_PAGESIZE;//修改Flash頁(yè)地址
????????buffptr=0;
????????}
????????????????#else?????//----------------------
????????????????while(buffptr>0)//接收一幀,寫入多個(gè)頁(yè)面
????????{
????????write_one_page(&RX_buff[BUFSIZE-buffptr]);
????????FlashAddr+=SPM_PAGESIZE;//修改Flash頁(yè)地址
????????buffptr-=SPM_PAGESIZE;
????????}
????????????????#endif//-----------------------
????????????}
????else//超過(guò)BootStart,忽略寫操作
????{buffptr=0;}//重置接收指針
????Frame_State=0x04;
????}
????break;
????case0x04://讀取寫入的Flash內(nèi)容并和下載的緩沖區(qū)比較
????{
????????Frame_State=0x05;//轉(zhuǎn)為應(yīng)答狀態(tài)
????????????buffptr_old=buffptr;//寫入正常才記錄數(shù)據(jù)指針
????????}
????break;
????case0x05://正確應(yīng)答ACK
????{
????????????packNO_old=packNO;//接收完整一幀保留本次包號(hào)
????????????Send_UART(XMODEM_ACK);//認(rèn)可應(yīng)答
????????????//WriteCom(packNO);?????????//測(cè)試
????????????//WriteCom(FlashAddr);??????//測(cè)試
????????????//WriteCom(FlashAddr>>8);???//測(cè)試
????????????Error_cnt=0;//清除連續(xù)錯(cuò)誤計(jì)數(shù)
????????????Frame_State=0x00;//轉(zhuǎn)為幀接收(請(qǐng)求)狀態(tài)
????}
????break;
????case0x06://錯(cuò)誤=重發(fā)應(yīng)答ANK
????{
????????????Send_UART(XMODEM_NAK);//要求重發(fā)數(shù)據(jù)塊
????Error_cnt++;//連續(xù)錯(cuò)誤計(jì)數(shù)
????????????Frame_State=0x00;//轉(zhuǎn)為接收狀態(tài)
????}
????break;
????default://升級(jí)完成退出處理
????{
????????#if?SafeUpdated_En
????????EEPROM_Write(EE_SafeAddr,0);//寫升級(jí)成功標(biāo)志0
????????#endif
????????quit_boot();//退出Bootloader
????????}
????break;
}//?switch?End
????if(Error_cnt>10)//連續(xù)出錯(cuò)10次退出升級(jí)(復(fù)位)
????{
????????Send_UART(XMODEM_CAN);//撤銷傳送(無(wú)條件停止)
????????#if?SafeUpdated_En
????????EEPROM_Write(EE_SafeAddr,1);//寫升級(jí)失敗標(biāo)志1
????????#endif
????while(1);//沒有升級(jí)完成重新開始
????}
????#if?WDGEn
????Watchdog_Reset();//喂狗
????#endif
}//?while?end
//-------------------------------------------------//
}//?main?end
//-----------------------------------------------//
#include?"AVR_boot.h"http://頭文件包含
//-----------------------------------------------//
//----------初始化-------------------------------//
//輸出端口初始化
voidPORT_Init()
{
//上電默認(rèn)全為輸入口
//輸出口設(shè)置
#if?Run_LEDEn
DDRREG(LEDPORT)|=(1<
#endif
}
//-----------------------------------------------//
//串口初始化
voidUART_Init()
{
#if?RS485_En
DDRREG(RS485PORT)|=(1<
RX485DE_RX;//默認(rèn)為接收
#endif
UCSRAREG(COMPORTNo)=0x00;
UCSRBREG(COMPORTNo)=0x18;//?Enable?Receiver?and?Transmitter
UCSRCREG(COMPORTNo)=0x0E;//?Set?frame.?format:?8data,?2stop?bit
//通信速率
UBRRHREG(COMPORTNo)=BAUD_H;//?0X00
UBRRLREG(COMPORTNo)=BAUD_L;//?Set?baud?rate???16M?9600?0x0067
}
//?250ms定時(shí)器設(shè)置Time1
//-----------------------------------------------//
//使用定時(shí)器1:1024分頻,CTC模式4亚隅,產(chǎn)生以毫秒為單位的時(shí)間
voidTime1_Init()
{
//?Timer/Counter?1?initialization
//?Clock?source:?System?Clock
//?Clock?value:?16MHz
TCCR1A=0x00;//?CTC4
TCCR1B=0x08;//?CTC4
TCCR1B|=0x03;//?clkI/O/64?(來(lái)自預(yù)分頻器)?16M=4us
OCR1A=T1_TCNT;//?250MS
}
//-----------------------------------------------//
//看門狗初始化函數(shù)2s
voidWatchDog_Enable(void)
{
//?Watchdog?Timer?initialization
//?Watchdog?Timer?Prescaler:?OSC/2048k
MCUCSR=0x00;//控制與狀態(tài)寄存器
WDTCR=0x1F;//看門狗使能500ms(D)1.0S(E)?2.0S(F)
WDTCR=0x0F;
}
//禁止看門狗
voidWatchDog_Disenable(void)//禁止看門狗
{
MCUCSR=0x00;//控制與狀態(tài)寄存器
WDTCR=0b00011111;//看門狗使能位修改使能(B4=1)?2.0S(F)
WDTCR=0b00000111;//禁止看門狗2.0S(7)
}
//喂狗
voidWatchdog_Reset(void)
{#asm("wdr")}//喂狗
//-----------------------------------------------//
//-------------子函數(shù)----------------------------//
//寫入數(shù)據(jù)到串口
voidSend_UART(unsignedchardat)
{
uchari;
#if?RS485_En
RX485DE_TX;//使能RS485發(fā)送
#endif
UDRREG(COMPORTNo)=dat;//?UDR0
//等待數(shù)據(jù)發(fā)送完成
while(!(UCSRAREG(COMPORTNo)&0x40));//等待數(shù)據(jù)發(fā)送完成Bit?6?–?TXC:?USART發(fā)送結(jié)束
UCSRAREG(COMPORTNo)|=0x40;//清除發(fā)送完成狀態(tài)
#if?RS485_En
RX485DE_RX;//使能RS485接收
#endif
}
//-----------------------------------------------//
//等待串口數(shù)據(jù)(注意是”死等“)
unsignedcharWait_UART()
{
while(!(UCSRAREG(COMPORTNo)&0x80));//等等數(shù)據(jù)到來(lái)Bit?7?–?RXC:?USART接收結(jié)束
UCSRAREG(COMPORTNo)|=0x80;//清除接收完成狀態(tài)
#if?Run_LEDEn
Run_LED;//運(yùn)行LED閃爍
#endif
returnUDRREG(COMPORTNo);
}
//-----------------------------------------------//
//計(jì)算CRC
intCRC16_Word(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處執(zhí)行應(yīng)用程序
voidquit_boot(void)
{
????MCUCR=0x00;//當(dāng)IVSEL為"0“時(shí)套像,中斷向量位于Flash存儲(chǔ)器的起始地址夺巩;
????#ifdef?ATMEGA128
????RAMPZ=0x00;//0:?ELPM/SPM可以訪問(wèn)程序存儲(chǔ)器地址$0000?-?$7FFF?(低64K字節(jié))
????#endif
????#asm("jmp?0x0000")//跳轉(zhuǎn)到Flash的0x0000處柳譬,執(zhí)行用戶的應(yīng)用程序
}
//-----------------------------------------------//
//讀EEPROM一個(gè)字節(jié)
ucharEEPROM_Read(uintAddr)//?EEPROM讀1個(gè)字節(jié)操作0
{
while(EECR&0x02);//等待上一次寫操作結(jié)束
EEAR=Addr;//設(shè)置地址寄存器
EECR|=0x01;//設(shè)置EERE以啟動(dòng)讀操作b0
return(EEDR);//自數(shù)據(jù)寄存器返回?cái)?shù)據(jù)
}
//寫EEPROM一個(gè)字節(jié)
voidEEPROM_Write(uintAddr,charData)//?EEPROM寫1個(gè)字節(jié)操作
{
EEAR=Addr;//設(shè)置地址寄存器
EEDR=Data;//設(shè)置數(shù)據(jù)寄存器
//????#asm("cli")?????????????????????//?EEMPE置1,EEPE1,這兩步操作中間不能超過(guò)4個(gè)時(shí)鐘周期
EECR|=0x04;//置位EEMWE????????????b2
EECR|=0x02;//置位EEWE以啟動(dòng)寫操作b1
//#asm("sei")
}
//-----------------------------------------------//
//-------------------------------------------------------//
#ifndef?_AVR_BOOT_H_
#define?_AVR_BOOT_H_??????1
//配置文件包含
#include?"Config.h"
//------------------------------------------------------//
#ifdef????ATMEGA32
#include?
#endif
#ifdef??ATMEGA64
#include?
#endif
#ifdef??ATMEGA128
#include?
#endif
//---------------------------------------------------//
typedefsignedcharschar;
typedefsignedintsint;
typedefsignedlongslong;
typedefunsignedcharuchar;
typedefunsignedintuint;
typedefunsignedlongulong;
//--------------------------------------------------//
//函數(shù)申明
voidUART_Init();
voidPORT_Init();
voidTime1_Init();
voidSend_UART(unsignedchardat);
unsignedcharWait_UART();
unsignedcharWait1S_UART();
voidWatchDog_Disenable(void);
voidquit_boot(void);
intCRC16_Word(char*ptr,intcount);
voidwrite_one_page(uchardata[]);
voidWatchDog_Enable(void);
voidWatchdog_Reset(void);
ucharEEPROM_Read(uintAddr);
voidEEPROM_Write(uintAddr,charData);
//--------------------------------------------------//
//內(nèi)部使用的宏定義
#define?CONCAT(a,?b)???????a?##?b
#define?CONCAT3(a,?b,?c)???a?##?b?##?c
//端口以及位定義
#define?PORTREG(No)????????CONCAT(PORT,?No)
#define?PINREG(No)?????????CONCAT(PIN,?No)
#define?DDRREG(No)?????????CONCAT(DDR,?No)
#define?UDRREG(No)?????????CONCAT(UDR,?No)
//串口初始化需要寄存器
#define?UCSRAREG(No)???????CONCAT3(UCSR,?No,?A)
#define?UCSRBREG(No)???????CONCAT3(UCSR,?No,?B)
#define?UCSRCREG(No)???????CONCAT3(UCSR,?No,?C)
#define?UBRRHREG(No)???????CONCAT3(UBRR,?No,?H)
#define?UBRRLREG(No)???????CONCAT3(UBRR,?No,?L)
//---------------------------------------------------//
//端口定義
#define?????RX485DE_RX??????PORTREG(RS485PORT)&=~(1?<<?RS485TXEn);??//?SCI接收使能
#define?????RX485DE_TX??????PORTREG(RS485PORT)|=(1?<<?RS485TXEn);???//?SCI發(fā)送使能
#define?????Run_LED?????????PORTREG(LEDPORT)^=?(1?<<?LEDPORTNo);????//?boot運(yùn)行LED
//---------------------------------------------------//
//定義Xmoden控制字符
#define?XMODEM_NUL??????????0x00????????//?null
#define?XMODEM_SOH??????????0x01????????//?Xmodem數(shù)據(jù)頭
#define?XMODEM_STX??????????0x02????????//?Xmodem_1K數(shù)據(jù)頭
#define?XMODEM_EOT??????????0x04????????//發(fā)送結(jié)束
#define?XMODEM_ACK??????????0x06????????//認(rèn)可響應(yīng)
#define?XMODEM_NAK??????????0x15????????//不認(rèn)可響應(yīng)
#define?XMODEM_CAN??????????0x18????????//撤銷傳送
#define?XMODEM_EOF??????????0x1A????????//填充數(shù)據(jù)包
#define?XMODEM_RWC??????????'C'?????????//?CRC16-128
//-------------------------------------------------------//
#ifdef??Xmodem_1K
#define?BUFFER_SIZE?????????1024
#else??//?Xmodem
#define?BUFFER_SIZE?????????128
#endif
//-----------------------------------------------------//
#ifdef??ATMEGA32
#define?SPM_PAGESIZE????????128?????????//?SPM頁(yè)大小
#define?BootStart???????????0x3C00*2????//按字節(jié)
#define?SPM_REG?????????????SPMCR???????//?SPM寄存器
#endif
#ifdef??ATMEGA64
#define?SPM_PAGESIZE????????256?????????//?SPM頁(yè)大小
#define?BootStart???????????0x7C00*2????//按字節(jié)
#define?SPM_REG?????????????SPMCSR??????//?SPM寄存器
#endif
#ifdef??ATMEGA128
#define?SPM_PAGESIZE????????256?????????//?SPM頁(yè)大小
#define?BootStart???????????0xFC00*2????//按字節(jié)
#define?SPM_REG?????????????SPMCSR??????//?SPM寄存器
#endif
//接收緩沖區(qū)大小不能小于SPM_PAGESIZE
#if?BUFFER_SIZE?<?SPM_PAGESIZE
#define?BUFSIZE?SPM_PAGESIZE????????????//?UART數(shù)據(jù)緩存
#else
#define?BUFSIZE?BUFFER_SIZE?????????????//?UART數(shù)據(jù)緩存
#endif
//計(jì)算和定義波特率設(shè)置參數(shù)
#define?BAUD_SETTING?(unsigned?char)((unsigned?long)CRYSTAL/(16*(unsignedlong)BAUDRATE)-1)
#define?BAUD_H?((unsigned?char)(BAUD_SETTING>>8))
#define?BAUD_L?(unsigned?char)BAUD_SETTING
//計(jì)算T1定時(shí)器設(shè)置參數(shù)
#define?T1_TCNT?(unsigned?int)((unsigned?long)CRYSTAL*250/(64*1000));
//--------------------------------------------------------//
#endif//?_AVR_BOOT_H_
#ifndef?_CONFIG_H_
#define?_CONFIG_H_??????1
//*********************************************************//
//關(guān)于上海霜蟬-AVR_bootV1.00
//?1舅桩、軟件版本V1.00編譯環(huán)境CodeWizardAVR?V2.03.9?Standard;
//?2江咳、支持本公司常用的三種AVR芯片;
//?3、支持標(biāo)準(zhǔn)Xmodem和擴(kuò)展Xmodem_1K協(xié)議;
//?4爹土、聯(lián)機(jī)握手密碼為"00",握手成功手的等待文件超時(shí)為1分鐘;
//?5胀茵、默認(rèn)復(fù)位等待3S退出boot到用戶程序或循環(huán)運(yùn)行boot;
//?6琼娘、支持1分鐘以內(nèi)的斷網(wǎng)續(xù)傳;
//?7脱拼、支持連續(xù)10幀以內(nèi)數(shù)據(jù)錯(cuò)誤的重傳;
//?8熄浓、支持下載過(guò)程中的取消超作;
//?9赌蔑、支持當(dāng)收到包時(shí)娃惯,接收過(guò)程中每個(gè)字符的超時(shí)間隔為1秒;
//?10趾浅、支持所有的超時(shí)及錯(cuò)誤事件至少重試10次;
//?11潮孽、支持?jǐn)?shù)等待超時(shí)6S的請(qǐng)求;
//?12、Boot?Loader?-?Size:1024words;
//?13佛舱、支持傳輸速度:38.400KB/S~2.400KB/S;
//?14请祖、支持上海霜蟬常用最多的三個(gè)型號(hào)ATMEGA32,64,128肆捕。
//?15慎陵、支持開門狗自定義開關(guān),自定義時(shí)鐘頻率
//*********************************************************//
//注意:修改編譯器配置(char?to?int;char?is?unsigned)
//注意:填充數(shù)據(jù)必須大于兩包(>=256)
//定義芯片型號(hào)
//芯片型號(hào)選擇
//#define???ATMEGA32
#define?ATMEGA64????????????????//已測(cè)試Atmgea64L
//#define???ATMEGA128
//協(xié)議類型選擇:Xmodem或Xmodem_1K
#define?Xmodem?????????????//?Xmodex?128(CRC16)
//#define?Xmodem_1K????????????//?Xmodem?1024(CRC16)
//-----------------------------------------------//
//系統(tǒng)時(shí)鐘MHz
#ifndef?CRYSTAL
#define?CRYSTAL????????????16000000?????????//?16M
#endif
//波特率38400~2400
#define?BAUDRATE???????????9600
//等待密碼的超時(shí)時(shí)間=?WiteTimeCnt?*?250ms
//超時(shí)次數(shù)
#define?WiteTimeCnt????????10???????????????//?10=2.5s
//用戶設(shè)置boot駐留等待握手時(shí)間(1=250ms)+2.5S(WiteTimeCnt)
#define?Wait_BootTime??????40???????????????//?(1=250ms)+2.5S
//等待文件的超時(shí)時(shí)間=?TimeOutCntC?*?250ms
//發(fā)送'C'的最大次數(shù)
#define?TimeOutCntC????????40???????????????//?40=1min
//串口號(hào)(ATMEA32串口號(hào)為空)
#define?COMPORTNo??????????0????????????????//?UART0
//看門狗使能
#define?WDGEn??????????????1????????????????//使用看門狗
//使用485模式
#define?RS485_En???????????1????????????????//使用485使能腳
//?485控制端口和引腳
#define?RS485PORT??????????E????????????????//?PORTE
#define?RS485TXEn??????????2????????????????//?PORTE2
//使用LED指示狀態(tài)
#define?Run_LEDEn??????????1????????????????//使能boot運(yùn)行LED指示
//?LED控制端口和引腳
#define?LEDPORT????????????B????????????????//?PORTB
#define?LEDPORTNo??????????6????????????????//?PORTB6
//延時(shí)用于解決串口數(shù)據(jù)出錯(cuò)
#define?Delay_En???????????0
//用戶設(shè)置boot駐留等待握手時(shí)間(1=250ms)+2.5S(WiteTimeCnt)
//使此功能需要設(shè)置EEPROM
#define?Wait_BootTime??????40???????????????//?(40*250ms)+2.5S
#define?EE_TimeAddr?????????0???????????????//使用EEPROM占用1個(gè)字節(jié)
//安全升級(jí)(升級(jí)不成功不進(jìn)入用戶區(qū))
//使此功能需要設(shè)置EEPROM
#define?SafeUpdated_En?????1
#define?EE_SafeAddr????????1???????????????//使用EEPROM占用1個(gè)字節(jié)
//-----------------------------------------------//
#endif//?_CONFIG_H_
//End?of?file:?bootcfg.h