📄 megabootloaderblips.asm
字号:
L24: ldi R24,low(2*MYORG)
ldi R25,high(2*MYORG)
cp R26,R24 ; address < Boot Flash address(byte address) 0x3E00 ?
cpc R27,R25
brlo L20 ; loop for all flash blocks up to the bootloader area
#endif
;===========================================
;=======
#ifdef EEPROM_ERASE_e ; this legacy code doesn't loop, doesn't work, isn't useful
; erase EEPROM
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')
#endif
;=======
;--- command: page write for byte-at-a-time mode
L28: cpi R16,'m' ; else if(R16== 'm') Write page
brne L34
movw R30,R26 ; Z-pointer = address
; !!note: 'B' command shares this code too
L30: ldi R17,5 ; SPMCR = 0x05 Write page
OUTREG SPMCSR,R17
spm ; Store program memory
rcall wait_spm
L32: rjmp send_cr ; uartSend('\r')
;--- enter programming mode
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')
;--- Exit boot loader to user program
cpi R16, 'E' ; leave bootloader
brne L36
;ldi R16,(1<<UTXC) ; not necessary per data sheet on TXC status but
;OUTREG USTAT,R16
ldi R16,0x0D ; uartSend('\r')
rcall uartSend ; uartSend(R16)
L35: INREG R16,USTAT
sbrs R16,UTXC ; wait for char to have been transmitted (see Data Sheet on TXC bit)
rjmp L35
rjmp boot_r_0 ; EXECUTE USER PROGRAM
L36:
;--- return programing type
cpi R16,'p' ; else if (R16=='p') Return programmer type
brne L38
ldi R16,'S' ; uartSend('S') Serial
rjmp L70 ; uartSend(R16)
;--- read program memory for byte-at-a-time mode
L38: cpi R16,'R' ; else if(R16=='R') Read program memory
brne L40
movw R30,R26 ; Z-pointer <= address
.ifdef RAMPZ
elpm R24,Z+ ; read program memory LSB; store LSB in R24 and Z pointer ++
elpm R16,Z+ ; read program memory MSB; store MSB in R16 and Z pointer ++
.else
lpm R24,Z+ ; read program memory LSB; store LSB in R24 and Z pointer ++
lpm R16,Z+ ; read program memory MSB; store MSB in R16 and Z pointer ++
.endif
rcall uartSend ; uartSend(R16) MSB
movw R26,R30 ; address from Z register (incremented now)
mov R16,R24 ; LSB stored in R16
rjmp L70 ; uartSend(R16) LSB
;--- eeprom write for byte-at-a-time mode
L40: cpi R16,'D' ; else if (R16=='D') Write data to EEPROM
brne L42
rcall uartGet
out EEDR,R16 ; EEDR = uartGet()
ldi R17,6 ; write EEPROM
rcall EepromTalk
rjmp send_cr ; uartSend('\r')
;--- eeprom read for byte-at-a-time mode
L42: cpi R16,'d' ; else if (R16=='d') Read data from EEPROM
brne L44
ldi R17,1 ; read EEPROM
rcall EepromTalk ; R16 = EEPROM data
rjmp L70 ; uartSend(R16)
L44:
;--- read fuse bits
#ifdef ENABLE_READFUSEANDLOCK
cpi R16,'F' ; else if(R16=='F') Read fuse bits
brne L46
clr R30 ; Z-pointer = 0000
rjmp L50 ; rcall readFuseAndLock
;--- read lock bits
L46: cpi R16,'r' ; else if(R16=='r') Read lock bits
brne L48
ldi R30,1 ; Z pointer = 0001
rjmp L50 ; rcall readFuseAndLock
;--- read high fuse bits
L48: cpi R16,'N' ; else if(R16=='N') Read high fuse bits
brne L52
ldi R30,3 ; Z-pointer = 0003
;--- read fuse and lock bits
L50: rcall readFuseAndLock
rjmp L70 ; uartSend(R16)
#endif
;--- return supported devices
L52: cpi R16,'t' ; else if(R16=='t') Return supported devices code
brne L54
ldi R16,DT ; Device Type
rcall uartSend ; uartSend(DT) send Device Type
clr R16
rjmp L70 ; uartSend(0)
;--- grab another char and ignore
L54: ; else if ((R16=='l')||(R16=='x')||(R16=='y')||(R16=='T'))
#ifdef NONESUCH
cpi R16,'l' ; 'l' = Write Boot Loader lockbits
breq L56
cpi R16,'x' ; 'x' = Set LED
breq L56
cpi R16,'y' ; 'y' = Clear LED
breq L56
#endif
cpi R16,'T' ; 'T' = Select device type (ignored)
brne L60
L56: rcall uartGet ; R16 = uartGet()
; YOU CAN INSERT LEDs CODE HERE
rjmp send_cr ; uartSend('\r')
;--- send return software id
L60: cpi R16,'S' ; else if (R16=='S') Return software identifier
brne L62
boot_id:ldi R30,low(2*Soft_Id)
ldi R31,high(2*Soft_Id)
L61:
; Send ID string on uart from flash
.ifdef RAMPZ ; as on mega128
ldi R16,(1 << RAMPZ0) ; 128MB Flash
out RAMPZ,R16 ; string is in 2nd 64K block
elpm R16,Z+
.else
lpm R16,Z+
.endif
tst R16
breq L72 ; branch is end of string ((Z) == 0)
rcall uartSend ; else send char
rjmp L61
;--- send version
L62: cpi R16,'V' ; else if (R16=='V') Return Software Version
brne L64
ldi R16,'1' ; uartSend('1')
rcall uartSend
ldi R16,'2' ; uartSend('2')
rjmp L70 ; uartSend(R16)
;--- send signature bytes
L64: cpi R16,'s' ; else if (R16=='s') Return Signature Byte
brne L66
ldi R16,SB1 ; uartSend(SB1) Signature Byte 1
rcall uartSend
ldi R16,SB2 ; uartSend(SB2) Signature Byte 2
rcall uartSend
ldi R16,SB3 ; uartSend(SB3) Signature Byte 3
rjmp L70 ; uartSend(R16)
;;; Unsupported command received
cmdUnknown:
L66: ldi R16,'?' ; else uartSend('?')
rjmp L70 ; uartSend(R16)
;--- send cr
send_cr: ldi R16,13 ; uartSend('\r')
;--- send byte via uart
L70: rcall uartSend ; uartSend(R16)
L72: rjmp b_main
#ifdef ENABLE_READFUSEANDLOCK
readFuseAndLock:
clr R31 ; Z pointer high byte = 0
ldi R24,9 ; SPMCR = 0x09
WRITEPMCR R24 ; read fuse and lock
lpm R16,Z ; read program memory
ret
#endif
; --- EEPROM I/O
EepromTalk: ; if R17 == 6 then Write, if R17 == 1 then Read
out EEARL,R26 ; EEARL = address low
out EEARH,R27 ; EEARH = address high
adiw R26,1 ; address++
sbrc R17,1 ; skip if R17 == 1 (read Eeprom)
sbi EECR,EEMWE ; EEMWE = 1 (write Eeprom)
out EECR,R17 ; EECR = R17 (6 write, 1 read)
L90: sbic EECR,EEWE ; wait until EEWE == 0
rjmp L90
in R16,EEDR ; R16 = EEDR
ret
; --- UART I/O
; ==== UART Send Byte
uartSend: ; send R16
INREG R2,USTAT
sbrs R2,UTXE ; wait for empty transmit buffer (until UDRE==1)
rjmp uartSend
OUTREG UDATA,R16 ; UDR = R16, start transmission
ret
; ==== UART Get Byte
uartGet:
INREG R16,USTAT
sbrs R16,URXC ; wait for incoming data (until RXC==1)
rjmp uartGet
INREG R16,UDATA ; return received data in R16
ret
; --- Wait for previous SPM operation to finish
; then send SPM for RWWSRE
; then do another SPM
; must preserve Carry bit
wait_spm:
INREG R16,SPMCSR
sbrc R16,SPMEN ; skip if bit is clear
rjmp wait_spm
ldi R16,(1<<RWWSRE) | (1<<SPMEN)
OUTREG SPMCSR,R16
spm
ret
Soft_Id:
BOOTIDSTRING ; macro
; END OF CODE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -