最近一直利用業餘時間寫自己的“基于AVR-BootLoader”,啟發是由于一次在ourAVR論壇看到了紹子陽的bootloader,聯想到公司在用AVR MCU,但每次更新程式都要花費很大的力氣車馬勞頓的跑到工程現場,而且很多機器還安裝在國外,為了更新一次程式發費了很多的人力物力财力,加上公司的機器目前大部分都配有遠端監控系統,是以本人決定寫一個具有自有産權的“AVR-BootLoader”。
特别說明:本 “AVR-BootLoad” 軟體代碼屬上海霜蟬版權所有,在此貢獻釋出,僅限于個人免費使用不得用于商業用途,本人也不保證代碼的嚴謹性,如在更新中出現任何問題與本人無關,本人已測試過Atmega64A與Atmega128。話不多說了上源代碼,網友們和AVR愛好者可以拷貝到 CodeWizardAVR V2.03.9編譯器下編譯。
需要讨論或有遇到BUG的網友們可以聯系我:QQ:285247488 mail:[email protected]
上位機截圖:
遠端更新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、支援開門狗自定義開關,自定義時鐘頻率
#include "AVR_boot.h" // 頭檔案包含 //--------------------------------------------------// //同步密碼長度 #define CONNECTCNT 7 //同步密碼 uchar KEY_Data [10 ] = { "SCICALA" } ; // Declare your global variables here //--------------------------------------------------// // 全局變量定義 uchar RX_buff [ BUFSIZE ] ; // 資料拉收緩存 uchar Frame_State , SOH_Wait_cnt ; // 幀狀态,幀頭等待計數 uint Time_cnt , Error_cnt ; // 逾時計數,連續幀錯誤計數 uint buffptr , buffptr_old , buffptr_New ; // 資料緩存指針必須大于1024 ulong FlashAddr ; // Flash位址 uchar UpdatedSta ; // 更新标志 //-----------------------------------------------// //擦除(code=0x03)和寫入(code=0x05)一個Flash頁 void boot_page_ew ( ulong p_address , char code ) { # asm ldd r26 , y +1 ; R26 LSB ldd r27 , y +2 ; R27 MSB # endasm SPM_REG = code ; // 寄存器SPMCSR中為操作碼 # asm mov r30 , r26 mov r31 , r27 # endasm #ifdef ATMEGA128 RAMPZ = ( p_address >> 16 ) ; // RAMPZ0 = 1: ELPM/SPM 可以通路程式存儲器位址$8000 - $FFFF ( 高64K 位元組) #endif # asm ( "spm" ) ; // 對指定Flash頁進行擦操作 } //填充Flash緩沖頁中的一個字 void boot_page_fill ( uint A_address , uint data ) { # asm LDD R30 , Y +2 ; R30 LSB LDD R31 , Y +3 ; R31 MSB LD R26 , Y LDD R27 , Y +1 MOV R0 , R26 MOV R1 , R27 MOV R26 , R30 MOV R27 , R31 # endasm SPM_REG = 0x01 ; //寄存器SPMCSR中為操作碼 # asm mov r30 , r26 mov r31 , r27 # endasm # asm ( "spm" ) ; //對指定Flash頁進行擦操作 } //等待一個Flash頁的寫完成 void wait_page_rw_ok ( void ) { while ( SPM_REG & 0x40 ) { while ( SPM_REG & 0x01 ) ; SPM_REG = 0x11 ; # asm ( "spm" ) ; while ( SPM_REG & 0x01 ) ; } } //-----------------------------------------------// //更新一個Flash頁的完整處理 void write_one_page ( uchar data [ ]) { uint i ; boot_page_ew ( FlashAddr , 0x03 ) ; //擦除一個Flash頁 wait_page_rw_ok ( ) ; //等待擦除完成 for ( i = 0 ; i < SPM_PAGESIZE ; i += 2 ) //将資料填入Flash緩沖頁中 按字填充 { 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逾時自動轉為應答 unsigned char Wait1S_UART ( ) { uchar i = 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 ; return UDRREG ( COMPORTNo ) ; // 讀取UDR0 } } while ( 100 != i ) ; // 等待資料||逾時退出 } // //===================================================// void main ( void ) { uchar packNO , packNO_old ; // 包号、包号留存 uint crc16 ; // 接收CRC緩存 uint li ; // 幀計數 uchar ch , 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 ) // 幀狀态 { case 0x00 : // 接受狀态 幀頭與停止信号判斷 { 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 < buffptr_New ; ) // 判斷上一幀資料尾16個正确性以決定是否重傳 { 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 ; case 0x01 : //包序号校驗 { ch = Wait1S_UART ( ) ; // 擷取包序号 cl = ~ Wait1S_UART ( ) ; if ( ch == cl ) // 包号對比 { Frame_State = 0x02 ; packNO = ch ; // 正確定留包号 } else { Frame_State = 0x06 ; } // 重發應答ANK } break ; case 0x02 : // 進入二級CRC校驗 { for ( li = 0 ; li < BUFFER_SIZE ; li ++ ) // 接收完整一幀資料 (128位元組) { 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 ; case 0x03 : // 校驗通過,執行寫入 { if ( FlashAddr < BootStart ) //避免寫入Boot區 { #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 ; case 0x04 : //讀取寫入的Flash内容并和下載下傳的緩沖區比較 { Frame_State = 0x05 ; // 轉為應答狀态 buffptr_old = buffptr ; // 寫入正常才記錄資料指針 } break ; case 0x05 : // 正确應答ACK { packNO_old = packNO ; // 接收完整一幀保留本次包号 Send_UART ( XMODEM_ACK ) ; // 認可應答 //WriteCom(packNO); // 測試 //WriteCom(FlashAddr); // 測試 //WriteCom(FlashAddr>>8); // 測試 Error_cnt = 0 ; // 清除連續錯誤計數 Frame_State = 0x00 ; // 轉為幀接收(請求)狀态 } break ; case 0x06 : // 錯誤=重發應答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" // 頭檔案包含 //-----------------------------------------------// //----------初始化-------------------------------// // 輸出端口初始化 void PORT_Init ( ) { // 上電預設全為輸入口 // 輸出口設定 #if Run_LEDEn DDRREG ( LEDPORT )| = ( 1 << LEDPORTNo ) ; // 訓示燈 #endif } //-----------------------------------------------// // 序列槽初始化 void UART_Init ( ) { #if RS485_En DDRREG ( RS485PORT )| = ( 1 << RS485TXEn ) ; // 設定(PC5)RS485方向控制引腳為輸出 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,産生以毫秒為機關的時間 void Time1_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 void WatchDog_Enable ( void ) { // Watchdog Timer initialization // Watchdog Timer Prescaler: OSC/2048k MCUCSR = 0x00 ; // 控制與狀态寄存器 WDTCR = 0x1F ; // 看門狗使能 500ms(D)1.0S(E) 2.0S(F) WDTCR = 0x0F ; } // 禁止看門狗 void WatchDog_Disenable ( void ) // 禁止看門狗 { MCUCSR = 0x00 ; // 控制與狀态寄存器 WDTCR =0 b00011111 ; // 看門狗 使能位修改 使能(B4=1) 2.0S(F) WDTCR =0 b00000111 ; // 禁止看門狗 2.0S(7) } // 喂狗 void Watchdog_Reset ( void ) { # asm ( "wdr" ) } // 喂狗 //-----------------------------------------------// //-------------子函數----------------------------// //寫入資料到序列槽 void Send_UART ( unsigned char dat ) { uchar i ; #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 } //-----------------------------------------------// //等待序列槽資料(注意是”死等“) unsigned char Wait_UART ( ) { while ( ! ( UCSRAREG ( COMPORTNo ) & 0x80 )) ; // 等等資料到來 Bit 7 – RXC: USART 接收結束 UCSRAREG ( COMPORTNo )| = 0x80 ; // 清除接收完成狀态 #if Run_LEDEn Run_LED ; // 運作LED閃爍 #endif return UDRREG ( COMPORTNo ) ; } //-----------------------------------------------// //計算CRC int CRC16_Word ( char * ptr , int count ) { int crc = 0 ; char i ; 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處執行應用程式 void quit_boot ( void ) { MCUCR = 0x00 ; //當IVSEL 為"0“ 時,中斷向量位于Flash 存儲器的起始位址; #ifdef ATMEGA128 RAMPZ = 0x00 ; //0: ELPM/SPM 可以通路程式存儲器位址$0000 - $7FFF ( 低64K 位元組) #endif # asm ( "jmp 0x0000" ) //跳轉到Flash的0x0000處,執行使用者的應用程式 } //-----------------------------------------------// // 讀EEPROM一個位元組 uchar EEPROM_Read ( uint Addr ) // EEPROM讀1個位元組操作 0 { while ( EECR & 0x02 ) ; // 等待上一次寫操作結束 EEAR = Addr ; // 設定位址寄存器 EECR | = 0x01 ; // 設定EERE 以啟動讀操作 b0 return ( EEDR ) ; // 自資料寄存器傳回資料 } // 寫EEPROM一個位元組 void EEPROM_Write ( uint Addr , char Data ) // 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 <mega32.h> #endif #ifdef ATMEGA64 #include <mega64.h> #endif #ifdef ATMEGA128 #include <mega128.h> #endif //---------------------------------------------------// typedef signed char schar ; typedef signed int sin t ; typedef signed long slong ; typedef unsigned char uchar ; typedef unsigned int uint ; typedef unsigned long ulong ; //--------------------------------------------------// // 函數申明 void UART_Init ( ) ; void PORT_Init ( ) ; void Time1_Init ( ) ; void Send_UART ( unsigned char dat ) ; unsigned char Wait_UART ( ) ; unsigned char Wait1S_UART ( ) ; void WatchDog_Disenable ( void ) ; void quit_boot ( void ) ; int CRC16_Word ( char * ptr , int count ) ; void write_one_page ( uchar data [ ]) ; void WatchDog_Enable ( void ) ; void Watchdog_Reset ( void ) ; uchar EEPROM_Read ( uint Addr ) ; void EEPROM_Write ( uint Addr , char Data ) ; //--------------------------------------------------// //内部使用的宏定義 #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 * ( unsigned long ) 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