基于AVR-BootLoader,通過霜蟬遠程串口可實現單片機的遠程升級

最近一直利用業余時間寫自己的“基于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.

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://頭文件包含

//--------------------------------------------------//

//同步密碼長度

#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

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容