基于AVR-BootLoader废累,通過(guò)霜蟬遠(yuǎn)程串口可實(shí)現(xiàn)單片機(jī)的遠(yuǎn)程升級(jí)

最近一直利用業(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.

http://www.hpinfotech.com

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

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市过牙,隨后出現(xiàn)的幾起案子寇钉,更是在濱河造成了極大的恐慌摧莽,老刑警劉巖镊辕,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件征懈,死亡現(xiàn)場(chǎng)離奇詭異卖哎,居然都是意外死亡亏娜,警方通過(guò)查閱死者的電腦和手機(jī)维贺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門虐秋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)客给,“玉大人肢簿,你說(shuō)我怎么就攤上這事池充∽菥” “怎么了咱圆?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵手幢,是天一觀的道長(zhǎng)围来。 經(jīng)常有香客問(wèn)我监透,道長(zhǎng)胀蛮,這世上最難降的妖魔是什么粪狼? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任再榄,我火速辦了婚禮困鸥,結(jié)果婚禮上窝革,老公的妹妹穿的比我還像新娘虐译。我一直安慰自己漆诽,他們只是感情好厢拭,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著楞捂,像睡著了一般趋厉。 火紅的嫁衣襯著肌膚如雪寨闹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天君账,我揣著相機(jī)與錄音繁堡,去河邊找鬼。 笑死乡数,一個(gè)胖子當(dāng)著我的面吹牛椭蹄,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播塑娇,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼劫侧!你這毒婦竟也來(lái)了埋酬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤烧栋,失蹤者是張志新(化名)和其女友劉穎写妥,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體审姓,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡珍特,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了魔吐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扎筒。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡莱找,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嗜桌,到底是詐尸還是另有隱情奥溺,我是刑警寧澤,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布骨宠,位于F島的核電站浮定,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏层亿。R本人自食惡果不足惜桦卒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望匿又。 院中可真熱鬧方灾,春花似錦、人聲如沸碌更。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)针贬。三九已至击费,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間桦他,已是汗流浹背蔫巩。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留快压,地道東北人圆仔。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蔫劣,于是被迫代替她去往敵國(guó)和親坪郭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容