最近一直利用業余時間寫自己的“基于AVR-BootLoader”,啟發是由于一次在ourAVR論壇看到了紹子陽的bootloader,聯想到公司在用AVR MCU,但每次升級程序都要花費很大的力氣車馬勞頓的跑到工程現場,而且很多機器還安裝在國外,為了升級一次程序發費了很多的人力物力財力,加上公司的機器目前大部分都配有遠程監控系統,所以本人決定寫一個具有自有產權的“AVR-BootLoader”。
特別說明:本“AVR-BootLoad”軟件代碼屬上海霜蟬版權所有,在此貢獻發布,僅限于個人免費使用不得用于商業用途,本人也不保證代碼的嚴謹性,如在升級中出現任何問題與本人無關,本人已測試過Atmega64A與Atmega128。話不多說了上源代碼,網友們和AVR愛好者可以拷貝到CodeWizardAVR V2.03.9編譯器下編譯。
需要討論或有遇到BUG的網友們可以聯系我:QQ:285247488 ?mail:shw@scicala.com?
上位機截圖:
遠程升級DTU:
遠程升級連接云平臺虛擬串口:
//? ? ? ? ??關于上海霜蟬-AVR_BootLoade_V1.00
// 1、軟件版本V1.00 編譯環境CodeWizardAVR V2.03.9 Standard;
// 2、支持本公司常用的三種AVR芯片;
// 3、支持標準Xmodem和擴展Xmodem_1K協議;
// 4、聯機握手密碼為"00",握手成功手的等待文件超時為1分鐘;
// 5、默認復位等待3S退出boot到用戶程序或循環運行boot;
// 6、支持1分鐘以內的斷網續傳;
// 7、支持連續10幀以內數據錯誤的重傳;
// 8、支持下載過程中的取消超作;
// 9、支持當收到包時,接收過程中每個字符的超時間隔為 1 秒;
// 10、支持所有的超時及錯誤事件至少重試 10 次;
// 11、支持數等待超時6S的請求;
// 12、Boot Loader - Size:1024words;
// 13、支持傳輸速度:38.400KB/S~2.400KB/S;
// 14、支持公司常用最多的三個型號ATMEGA32,64,128。
// 15、支持開門狗自定義開關,自定義時鐘頻率
/*****************************************************
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://頭文件包含
//--------------------------------------------------//
//同步密碼長度
#define?CONNECTCNT? ? ? ? ?7
//同步密碼
uchar?KEY_Data[10]?=?{"SCICALA"};
//?Declare?your?global?variables?here
//--------------------------------------------------//
//全局變量定義
ucharRX_buff[BUFSIZE];//數據拉收緩存
ucharFrame_State,SOH_Wait_cnt;//幀狀態,幀頭等待計數
uintTime_cnt,Error_cnt;//超時計數,連續幀錯誤計數
uintbuffptr,buffptr_old,buffptr_New;//數據緩存指針必須大于1024
ulongFlashAddr;//?Flash地址
ucharUpdatedSta;//升級標志
//-----------------------------------------------//
//擦除(code=0x03)和寫入(code=0x05)一個Flash頁
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可以訪問程序存儲器地址$8000?-?$FFFF?(高64K字節)
#endif
#asm("spm");//對指定Flash頁進行擦操作
}
//填充Flash緩沖頁中的一個字
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");//對指定Flash頁進行擦操作
}
//等待一個Flash頁的寫完成
voidwait_page_rw_ok(void)
{
????while(SPM_REG&0x40)
????{
????????while(SPM_REG&0x01);
????????SPM_REG=0x11;
????????#asm("spm");
????????while(SPM_REG&0x01);
????}
}
//-----------------------------------------------//
//更新一個Flash頁的完整處理
voidwrite_one_page(uchardata[])
{
uinti;
boot_page_ew(FlashAddr,0x03);//擦除一個Flash頁
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);//將緩沖頁數據寫入一個Flash頁
wait_page_rw_ok();//等待寫入完成
}
//--------------------------------------------------//
//等待串口數據1S超時自動轉為應答
unsignedcharWait1S_UART()
{
uchari=0;
do
{
#if?WDGEn
Watchdog_Reset();//喂狗
#endif
if(TIFR&0x10)//?OCF1A:?T/C1輸出比較A匹配標志位
{
TIFR|=0x10;//清除Time1定時器比較匹配標志
i++;
if(i>=4)//等待1S?250ms*4=1S
????{Frame_State=0x06;break;}//幀數據超時轉為應答請求重發數據幀
}
if(UCSRAREG(COMPORTNo)&0x80)
{
UCSRAREG(COMPORTNo)|=0x80;//清除接收完成狀態
????#if?Run_LEDEn
????Run_LED;//運行LED閃爍
????#endif
????i=100;
returnUDRREG(COMPORTNo);//讀取UDR0
}
}
while(100!=i);//等待數據||超時退出
}
//***************************************************//
//===================================================//
voidmain(void)
{
ucharpackNO,packNO_old;//包號、包號留存
uintcrc16;//接收CRC緩存
uintli;//幀計數
ucharch,cl;//包號
PORT_Init();//端口初始化
UART_Init();//串口初始化
Time1_Init();//定時器初始化250ms
#if?WDGEn
WatchDog_Enable();//打開看門狗(2S)
#else
????WatchDog_Disenable();???//禁止看門狗
#endif
#if?Wait_BootTime
Time_cnt=EEPROM_Read(EE_TimeAddr);//讀取boot運行時間
#endif
#if?SafeUpdated_En
UpdatedSta=EEPROM_Read(EE_SafeAddr);//讀取升級成功標志
#endif
#asm("cli")//關總中斷
#if?Delay_En????????????//是否延時
for(li=0;li<5000;li++)
{#asm("nop")}
#endif
//-----------------------------------------------//
//等待"握手",否則退出Bootloader程序,從0x0000處執行應用程序
Time_cnt+=WiteTimeCnt;
cl=0;
while(1)
{
if(TIFR&0x10)//?OCF1A:?T/C1輸出比較A匹配標志位
{
????TIFR|=0x10;//清除Time1定時器比較匹配標志
????????#if?Run_LEDEn
????Run_LED;//運行LED閃爍
????????#endif
????????Time_cnt--;
????if(Time_cnt==0)//等待握手超時
????{
????????#if?SafeUpdated_En
????????if(UpdatedSta)//上次升級失敗
????????????{while(1);}//復位boot
????????????else
????????????#endif
????????????{quit_boot();}//跳轉到用戶程序
????????}
????????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
}
//-----------------------------------------------//
//啟動Xmodex?CRC傳數據=字符“C”,等待控制字〈soh〉
Time_cnt=TimeOutCntC;
while(1)
{
if(TIFR&0x10)//?OCF1A:?T/C1輸出比較A匹配標志位
{
????TIFR|=0x10;//清除Time1定時器比較匹配標志
????????#if?Run_LEDEn
????Run_LED;//運行LED閃爍
????????#endif
????Send_UART(XMODEM_RWC);//發送"C"
????Time_cnt--;
????if(Time_cnt==0)//等待文件超時
????{
????????#if?SafeUpdated_En
????????if(UpdatedSta)//上次升級失敗
????????????{while(1);}//復位boot
????????????else
????????????#endif
????????????{quit_boot();}//跳轉到用戶程序
????????}//跳轉到用戶程序
}
if(UCSRAREG(COMPORTNo)&0x80)//串口有數據
{
????#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
}
//-----------------------------------------------//
//開始接收數據進入Xmodem協議接收文件
//幀的兩個時間很重要:連續出錯10次*最大幀請求間隔6S
//累計請求間隔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)//幀狀態
{
????case0x00://接受狀態幀頭與停止信號判斷
????{
????????ch=XMODEM_NUL;//清除
????????????if(UCSRAREG(COMPORTNo)&0x80)//串口有數據
????????????{ch=Wait_UART();}//讀取幀頭或停止信號
????????????if(TIFR&0x10)//?OCF1A:?T/C1輸出比較A匹配標志位
????????????{
????????????TIFR|=0x10;//清除Time1定時器比較匹配標志
????????????SOH_Wait_cnt++;//等待計時250ms
????????????????if(SOH_Wait_cnt>=24)//等待幀超時請求數據(6S*10=1min)
????????????????{
????????????????Frame_State=0x06;//要求重發數據塊
????????????????????SOH_Wait_cnt=0;//幀請求計時
????????????????????#if?Run_LEDEn
????Run_LED;//運行LED閃爍
????????????????????#endif
????????????????}
????????????}
????????????//------------------------------
????????if(ch==XMODEM_EOT)//發送結束
????????????{
????????????for(li=(buffptr_New-128);li
????{
????if((RX_buff[li++])!=0xff)break;//填充幀判斷爭強EOT抗干擾能力FF?CF
????????????????????{
????????????????????if((RX_buff[li++])!=0xcf)break;//填充幀判斷爭強EOT抗干擾能力FF?CF
????}
????????????????}
????????????????if(li==buffptr_New)
????????????????{Send_UART(XMODEM_ACK);//最后一幀應答完成
????????????????Frame_State=0x0ff;//轉為退出boot
????????????????}
????????????????else
????????????????{
????????????????Frame_State=0x06;//要求重發數據塊
????????????????????SOH_Wait_cnt=0;//幀請求計時
????????????????}
????????????}
????????????#ifdef??Xmodem
????????????if(ch==XMODEM_SOH)//?Xmodem幀頭判斷
????????????#else???//?Xmodem_1K
????????????if(ch==XMODEM_STX)//?Xmodem_1K幀頭判斷
????????????#endif
????????????{
????????????Frame_State=0x01;//轉為包號檢查
????????????????SOH_Wait_cnt=0;//清除幀頭等待計時
????????????}
????}
????break;
????case0x01://包序號校驗
????{
????????????ch=Wait1S_UART();//獲取包序號
cl=~Wait1S_UART();
????if(ch==cl)//包號對比
????????????{Frame_State=0x02;
????????????????packNO=ch;//正確保留包號
????????????}
????????????else
????????????{Frame_State=0x06;}//重發應答ANK
????}
????break;
????case0x02://進入二級CRC校驗
????{
????????for(li=0;li
????{
????RX_buff[buffptr++]=Wait1S_UART();//接收數據
????????????????//幀數據接收超時1S退出for詢環,再接收2個數據或超時1S+2S轉為應答
????????????????if(Frame_State==0x06)break;
????}
????crc16=Wait1S_UART();
????????????crc16=crc16<<8;
????crc16+=Wait1S_UART();//接收2個字節的CRC效驗字
????if(CRC16_Word(&RX_buff[buffptr-BUFFER_SIZE],BUFFER_SIZE)==crc16)//?CRC校驗驗證
????{
????????????if(packNO==packNO_old)//接收相同包不寫flash
????????????{Frame_State=0x05;//正常應答ACK
????????????????????buffptr=buffptr_old;
????????????}
????????????????else
????????????????{Frame_State=0x03;//正確應答
????????????????????buffptr_New=buffptr;//記錄當前數據指針
????????????????}
????????????}
????????????else
????????????{Frame_State=0x06;//應答NAK
????????????????buffptr=buffptr_old;//去掉錯誤數據的指針
????????????}
????}
????break;
????case0x03://校驗通過,執行寫入
????{
????????if(FlashAddr
????{
????????????????#if?BUFFER_SIZE?<?SPM_PAGESIZE??//?---
????????????????if(buffptr>=SPM_PAGESIZE)//緩沖區滿,寫入數據;否則繼續接收
????????{//接收多個幀,寫入一頁
????????write_one_page(&RX_buff[0]);//寫入緩沖區內容到Flash中
????????FlashAddr+=SPM_PAGESIZE;//修改Flash頁地址
????????buffptr=0;
????????}
????????????????#else?????//----------------------
????????????????while(buffptr>0)//接收一幀,寫入多個頁面
????????{
????????write_one_page(&RX_buff[BUFSIZE-buffptr]);
????????FlashAddr+=SPM_PAGESIZE;//修改Flash頁地址
????????buffptr-=SPM_PAGESIZE;
????????}
????????????????#endif//-----------------------
????????????}
????else//超過BootStart,忽略寫操作
????{buffptr=0;}//重置接收指針
????Frame_State=0x04;
????}
????break;
????case0x04://讀取寫入的Flash內容并和下載的緩沖區比較
????{
????????Frame_State=0x05;//轉為應答狀態
????????????buffptr_old=buffptr;//寫入正常才記錄數據指針
????????}
????break;
????case0x05://正確應答ACK
????{
????????????packNO_old=packNO;//接收完整一幀保留本次包號
????????????Send_UART(XMODEM_ACK);//認可應答
????????????//WriteCom(packNO);?????????//測試
????????????//WriteCom(FlashAddr);??????//測試
????????????//WriteCom(FlashAddr>>8);???//測試
????????????Error_cnt=0;//清除連續錯誤計數
????????????Frame_State=0x00;//轉為幀接收(請求)狀態
????}
????break;
????case0x06://錯誤=重發應答ANK
????{
????????????Send_UART(XMODEM_NAK);//要求重發數據塊
????Error_cnt++;//連續錯誤計數
????????????Frame_State=0x00;//轉為接收狀態
????}
????break;
????default://升級完成退出處理
????{
????????#if?SafeUpdated_En
????????EEPROM_Write(EE_SafeAddr,0);//寫升級成功標志0
????????#endif
????????quit_boot();//退出Bootloader
????????}
????break;
}//?switch?End
????if(Error_cnt>10)//連續出錯10次退出升級(復位)
????{
????????Send_UART(XMODEM_CAN);//撤銷傳送(無條件停止)
????????#if?SafeUpdated_En
????????EEPROM_Write(EE_SafeAddr,1);//寫升級失敗標志1
????????#endif
????while(1);//沒有升級完成重新開始
????}
????#if?WDGEn
????Watchdog_Reset();//喂狗
????#endif
}//?while?end
//-------------------------------------------------//
}//?main?end
//-----------------------------------------------//
#include?"AVR_boot.h"http://頭文件包含
//-----------------------------------------------//
//----------初始化-------------------------------//
//輸出端口初始化
voidPORT_Init()
{
//上電默認全為輸入口
//輸出口設置
#if?Run_LEDEn
DDRREG(LEDPORT)|=(1<
#endif
}
//-----------------------------------------------//
//串口初始化
voidUART_Init()
{
#if?RS485_En
DDRREG(RS485PORT)|=(1<
RX485DE_RX;//默認為接收
#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定時器設置Time1
//-----------------------------------------------//
//使用定時器1:1024分頻,CTC模式4,產生以毫秒為單位的時間
voidTime1_Init()
{
//?Timer/Counter?1?initialization
//?Clock?source:?System?Clock
//?Clock?value:?16MHz
TCCR1A=0x00;//?CTC4
TCCR1B=0x08;//?CTC4
TCCR1B|=0x03;//?clkI/O/64?(來自預分頻器)?16M=4us
OCR1A=T1_TCNT;//?250MS
}
//-----------------------------------------------//
//看門狗初始化函數2s
voidWatchDog_Enable(void)
{
//?Watchdog?Timer?initialization
//?Watchdog?Timer?Prescaler:?OSC/2048k
MCUCSR=0x00;//控制與狀態寄存器
WDTCR=0x1F;//看門狗使能500ms(D)1.0S(E)?2.0S(F)
WDTCR=0x0F;
}
//禁止看門狗
voidWatchDog_Disenable(void)//禁止看門狗
{
MCUCSR=0x00;//控制與狀態寄存器
WDTCR=0b00011111;//看門狗使能位修改使能(B4=1)?2.0S(F)
WDTCR=0b00000111;//禁止看門狗2.0S(7)
}
//喂狗
voidWatchdog_Reset(void)
{#asm("wdr")}//喂狗
//-----------------------------------------------//
//-------------子函數----------------------------//
//寫入數據到串口
voidSend_UART(unsignedchardat)
{
uchari;
#if?RS485_En
RX485DE_TX;//使能RS485發送
#endif
UDRREG(COMPORTNo)=dat;//?UDR0
//等待數據發送完成
while(!(UCSRAREG(COMPORTNo)&0x40));//等待數據發送完成Bit?6?–?TXC:?USART發送結束
UCSRAREG(COMPORTNo)|=0x40;//清除發送完成狀態
#if?RS485_En
RX485DE_RX;//使能RS485接收
#endif
}
//-----------------------------------------------//
//等待串口數據(注意是”死等“)
unsignedcharWait_UART()
{
while(!(UCSRAREG(COMPORTNo)&0x80));//等等數據到來Bit?7?–?RXC:?USART接收結束
UCSRAREG(COMPORTNo)|=0x80;//清除接收完成狀態
#if?Run_LEDEn
Run_LED;//運行LED閃爍
#endif
returnUDRREG(COMPORTNo);
}
//-----------------------------------------------//
//計算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處執行應用程序
voidquit_boot(void)
{
????MCUCR=0x00;//當IVSEL為"0“時,中斷向量位于Flash存儲器的起始地址;
????#ifdef?ATMEGA128
????RAMPZ=0x00;//0:?ELPM/SPM可以訪問程序存儲器地址$0000?-?$7FFF?(低64K字節)
????#endif
????#asm("jmp?0x0000")//跳轉到Flash的0x0000處,執行用戶的應用程序
}
//-----------------------------------------------//
//讀EEPROM一個字節
ucharEEPROM_Read(uintAddr)//?EEPROM讀1個字節操作0
{
while(EECR&0x02);//等待上一次寫操作結束
EEAR=Addr;//設置地址寄存器
EECR|=0x01;//設置EERE以啟動讀操作b0
return(EEDR);//自數據寄存器返回數據
}
//寫EEPROM一個字節
voidEEPROM_Write(uintAddr,charData)//?EEPROM寫1個字節操作
{
EEAR=Addr;//設置地址寄存器
EEDR=Data;//設置數據寄存器
//????#asm("cli")?????????????????????//?EEMPE置1,EEPE1,這兩步操作中間不能超過4個時鐘周期
EECR|=0x04;//置位EEMWE????????????b2
EECR|=0x02;//置位EEWE以啟動寫操作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;
//--------------------------------------------------//
//函數申明
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);
//--------------------------------------------------//
//內部使用的宏定義
#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發送使能
#define?????Run_LED?????????PORTREG(LEDPORT)^=?(1?<<?LEDPORTNo);????//?boot運行LED
//---------------------------------------------------//
//定義Xmoden控制字符
#define?XMODEM_NUL??????????0x00????????//?null
#define?XMODEM_SOH??????????0x01????????//?Xmodem數據頭
#define?XMODEM_STX??????????0x02????????//?Xmodem_1K數據頭
#define?XMODEM_EOT??????????0x04????????//發送結束
#define?XMODEM_ACK??????????0x06????????//認可響應
#define?XMODEM_NAK??????????0x15????????//不認可響應
#define?XMODEM_CAN??????????0x18????????//撤銷傳送
#define?XMODEM_EOF??????????0x1A????????//填充數據包
#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頁大小
#define?BootStart???????????0x3C00*2????//按字節
#define?SPM_REG?????????????SPMCR???????//?SPM寄存器
#endif
#ifdef??ATMEGA64
#define?SPM_PAGESIZE????????256?????????//?SPM頁大小
#define?BootStart???????????0x7C00*2????//按字節
#define?SPM_REG?????????????SPMCSR??????//?SPM寄存器
#endif
#ifdef??ATMEGA128
#define?SPM_PAGESIZE????????256?????????//?SPM頁大小
#define?BootStart???????????0xFC00*2????//按字節
#define?SPM_REG?????????????SPMCSR??????//?SPM寄存器
#endif
//接收緩沖區大小不能小于SPM_PAGESIZE
#if?BUFFER_SIZE?<?SPM_PAGESIZE
#define?BUFSIZE?SPM_PAGESIZE????????????//?UART數據緩存
#else
#define?BUFSIZE?BUFFER_SIZE?????????????//?UART數據緩存
#endif
//計算和定義波特率設置參數
#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
//計算T1定時器設置參數
#define?T1_TCNT?(unsigned?int)((unsigned?long)CRYSTAL*250/(64*1000));
//--------------------------------------------------------//
#endif//?_AVR_BOOT_H_
#ifndef?_CONFIG_H_
#define?_CONFIG_H_??????1
//*********************************************************//
//關于上海霜蟬-AVR_bootV1.00
//?1、軟件版本V1.00編譯環境CodeWizardAVR?V2.03.9?Standard;
//?2、支持本公司常用的三種AVR芯片;
//?3、支持標準Xmodem和擴展Xmodem_1K協議;
//?4、聯機握手密碼為"00",握手成功手的等待文件超時為1分鐘;
//?5、默認復位等待3S退出boot到用戶程序或循環運行boot;
//?6、支持1分鐘以內的斷網續傳;
//?7、支持連續10幀以內數據錯誤的重傳;
//?8、支持下載過程中的取消超作;
//?9、支持當收到包時,接收過程中每個字符的超時間隔為1秒;
//?10、支持所有的超時及錯誤事件至少重試10次;
//?11、支持數等待超時6S的請求;
//?12、Boot?Loader?-?Size:1024words;
//?13、支持傳輸速度:38.400KB/S~2.400KB/S;
//?14、支持上海霜蟬常用最多的三個型號ATMEGA32,64,128。
//?15、支持開門狗自定義開關,自定義時鐘頻率
//*********************************************************//
//注意:修改編譯器配置(char?to?int;char?is?unsigned)
//注意:填充數據必須大于兩包(>=256)
//定義芯片型號
//芯片型號選擇
//#define???ATMEGA32
#define?ATMEGA64????????????????//已測試Atmgea64L
//#define???ATMEGA128
//協議類型選擇:Xmodem或Xmodem_1K
#define?Xmodem?????????????//?Xmodex?128(CRC16)
//#define?Xmodem_1K????????????//?Xmodem?1024(CRC16)
//-----------------------------------------------//
//系統時鐘MHz
#ifndef?CRYSTAL
#define?CRYSTAL????????????16000000?????????//?16M
#endif
//波特率38400~2400
#define?BAUDRATE???????????9600
//等待密碼的超時時間=?WiteTimeCnt?*?250ms
//超時次數
#define?WiteTimeCnt????????10???????????????//?10=2.5s
//用戶設置boot駐留等待握手時間(1=250ms)+2.5S(WiteTimeCnt)
#define?Wait_BootTime??????40???????????????//?(1=250ms)+2.5S
//等待文件的超時時間=?TimeOutCntC?*?250ms
//發送'C'的最大次數
#define?TimeOutCntC????????40???????????????//?40=1min
//串口號(ATMEA32串口號為空)
#define?COMPORTNo??????????0????????????????//?UART0
//看門狗使能
#define?WDGEn??????????????1????????????????//使用看門狗
//使用485模式
#define?RS485_En???????????1????????????????//使用485使能腳
//?485控制端口和引腳
#define?RS485PORT??????????E????????????????//?PORTE
#define?RS485TXEn??????????2????????????????//?PORTE2
//使用LED指示狀態
#define?Run_LEDEn??????????1????????????????//使能boot運行LED指示
//?LED控制端口和引腳
#define?LEDPORT????????????B????????????????//?PORTB
#define?LEDPORTNo??????????6????????????????//?PORTB6
//延時用于解決串口數據出錯
#define?Delay_En???????????0
//用戶設置boot駐留等待握手時間(1=250ms)+2.5S(WiteTimeCnt)
//使此功能需要設置EEPROM
#define?Wait_BootTime??????40???????????????//?(40*250ms)+2.5S
#define?EE_TimeAddr?????????0???????????????//使用EEPROM占用1個字節
//安全升級(升級不成功不進入用戶區)
//使此功能需要設置EEPROM
#define?SafeUpdated_En?????1
#define?EE_SafeAddr????????1???????????????//使用EEPROM占用1個字節
//-----------------------------------------------//
#endif//?_CONFIG_H_
//End?of?file:?bootcfg.h