📄 boot2.asm
字号:
;***************************************************************************************
;*说明:
;* 1、本程序修改自Avrfreaks的Design Note #032,你可以到 http://www.avrfreaks.com 下载
;* 2、本程序支持 atmega-8 和 AVRProg (版本一定要1.37及以上)。
;* 3、Design Note #032上的程序,是为写的,在上不能正常运行。主要问题是在页写和
;* 擦除以后,不能再重新访问RWW。现在改正了这个bug!
;* 4、请确定你的 AVRProg 的版本在1.37及以上,1.37以下的是不支持 Mega8 的。
;* 5、请用等PonyProg等编程器把编译好的代码(Boot2.hex),写入到Mega8中。
;* 同时编程熔断位:BOOTSZ0 BOOTRST
;* 6、若有问题,请发邮件给我: Zhang_Lei@cnnb.net 。
;* 7、我的主页在 http://avrmcu.topcities.com 。
;***************************************************************************************
;******************** BOOT LOADER FOR ATmega8 *****************************************
;*
;* File : Boot2.asm (Include chip erase counter)
;* Version : 1.3
;* Compiler : AVR Studio
;* Target : ATmega8
;* Output size : 207 words (414 bytes)
;* Author : 张磊 ;Email-to: Zhang_Lei@cnnb.net; or zlei@21ic
;* website: http://avrmcu.topcities.com
;***************************************************************************************
;****************************************************
; 定义Mega8识别代码、电子标签字节和其它
;****************************************************
.equ DT = 0x77 ; Mega8识别代码(Mega8 bootloader)
.equ SB1 = 0x07 ; 电子标签字节 1
.equ SB2 = 0x93 ; 电子标签字节 2
.equ SB3 = 0x1e ; 电子标签字节 3
.equ E2END = $1FF ; EEEPROM尾
.equ UBR = 12 ; 波特率 = 19.200 bps ,晶振 = 4 MHz。
;AVRProg 能接受的波特率是 19200 和 115200
.nolist
.include "m8def.inc" ; 包含 mega8 器件配置文件
.list
.CSEG
.org SECONDBOOTSTART ;($0F00) 2'nd boot block size is 512
;****************************************************
; 复位并等待AVRProg发送ESC
;****************************************************
sbic PIND,PIND4 ; if (PIND4为0) then 跳到 Boot_Reset
rjmp $0000 ; else 运行用户代码(地址:$0000)
Boot_Reset:
;**** 初识化堆栈
ldi R24,low(RAMEND)
ldi R25,high(RAMEND)
out SPL,R24
out SPH,R25 ; SP = RAMEND
;**** 初识化串口
ldi R24,UBR ; 波特率
out UBRRL,R24
ldi R24,(1<<RXEN)|(1<<TXEN) ; 使能 TXEN 和 RXEN, 8位
out UCSRB,R24
L10: rcall uartGet ; repeat (R16 = uartGet)
cpi R16,27 ; while (R16 == ESCAPE)
breq L10
rjmp Boot_ID ; 若收到ESC,先显示ID,再跳到Boot_Main
Boot_Main: rcall uartGet ; repeat (R16 = uartGet)
cpi R16,0x1B ; while (R16 == ESCAPE)
breq Boot_Main
cpi R16,'a' ; if(R16=='a') 'a' = Autoincrement?
brne L12
ldi R16,'Y' ; Yes, autoincrement is quicker
rjmp L70 ; uartSend(R16)
;*********************************************************************
; 得到地址,并把字节地址(byte address)转换成字地址(word address)的形式
;*********************************************************************
L12: cpi R16,'A' ; else if(R16=='A') write address
brne L14
rcall uartGet
mov R27,R16 ; R27 = address high byte
rcall uartGet
mov R26,R16 ; R26 = address low byte
lsl R26 ; address=address<<1
rol R27 ; convert from byte address to word address
rjmp Send_CR ; uartSend('\r')
;****************************************************
; 得到 program data 低字节
;****************************************************
L14: cpi R16,'c' ; else if(R16=='c') write program memory, low byte
brne L16
rcall uartGet
mov R22,R16 ; R22 = data low byte
rjmp Send_CR ; uartSend('\r')
;****************************************************
;得到 program data 高字节,并把它存入临时缓冲区
;****************************************************
L16: cpi R16,'C' ;else if(R16=='C') write program memory,high byte
brne L18
rcall uartGet
mov R23,R16 ; R23 = data high byte
movw R30,R26 ; Z pointer = address
movw R0,R22 ; R0&R1 = data
ldi R24,1 ; SPMCR = 0x01
out SPMCR,R24 ; page load (fill temporary buffer)
spm ; Store program memory
adiw R26,2 ; address=address+2
rjmp Send_CR ; uartSend('\r')
;****************************************************
; 擦除芯片
;****************************************************
L18: cpi R16,'e' ; else if(R16=='e') Chip erase
brne L28
; for(address=0; address < (2*SECONDBOOTSTART); address += (2*PAGESIZE))
clr R26 ; page_erase();
clr R27
rjmp L24 ; test for end
L20: movw R30,R26 ; Z-pointer = address
ldi R24,3 ; SPMCR = 0x03
out SPMCR,R24 ; page_erase
spm ; Store program memory
; do the page erase
rcall wait_spm ; wait for done
subi R26,low(-2*PAGESIZE) ; address += (2*PAGESIZE)
sbci R27,high(-2*PAGESIZE)
L24: ldi R24,low(2*SECONDBOOTSTART)
ldi R25,high(2*SECONDBOOTSTART)
cp R26,R24 ; address < Boot Flash address(byte address) 0x3E00 ?
cpc R27,R25
brlo L20
ldi R26,low(E2END-1) ; increment Chip Erase Counter located at address E2END-1
ldi R27,high(E2END-1) ;
movw R22,R26 ; Save Chip Erase Counter Address in R22
ldi R17,1 ; read EEPROM
rcall EepromTalk
mov R24,R16 ; R24 = Chip Erase Counter low byte
rcall EepromTalk
mov R25,R16 ; R25 = Chip Erase Counter high byte
adiw R24,1 ; counter ++
out EEDR,R24 ; EEDR = R24 Chip Erase Counter low byte
movw R26,R22 ; R26 = Chip Erase Counter Address
ldi R17,6 ; write EEPROM
rcall EepromTalk
out EEDR,R25 ; EEDR = R25 Chip Erase Counter high byte
rcall EepromTalk
rjmp Send_CR ; uartSend('\r')
;****************************************************
; 页写( page write)
;****************************************************
L28: cpi R16,'m' ; else if(R16== 'm') Write page
brne L34
movw R30,R26 ; Z-pointer = address
ldi R24,5 ; SPMCR = 0x05 Write page
out SPMCR,R24
spm ; Store program memory
rcall wait_spm
L32: rjmp Send_CR ; uartSend('\r')
;****************************************************
;* 进入编程模式
;****************************************************
L34: cpi R16,'P' ; else if(R16=='P') Enter programming mode
breq L32 ; uartSend('\r')
cpi R16,'L' ; else if(R16=='L') Leave programming mode
breq L32 ; uartSend('\r')
;********************************************************
;返回所使用编程接口方式类型,对于串行接口的返回'S',并口的'P'.
;********************************************************
cpi R16,'p' ; else if (R16=='p') Return programmer type
brne L38
ldi R16,'S' ; uartSend('S') Serial
rjmp L70 ; uartSend(R16)
;****************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -