⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 megabootloaderblips.asm

📁 butterfly avrisp for atmel atmega
💻 ASM
📖 第 1 页 / 共 3 页
字号:
.endif


; AVR chip dependent {in/lds} versus {out/sts} automatic selection macros
;   The device include file must be used to define SRAM_START
; usage: InReg reg, addr
.macro INREG
    .if @1 < 0x40
        in @0, @1
    .elif ((@1 >= 0x60) && (@1 < SRAM_START))
        lds @0,@1
    .else
       .error "InReg: Invalid I/O register address"
    .endif
.endmacro

; usage: OutReg addr, reg
.macro OUTREG
    .if @0 < 0x40
        out @0, @1
    .elif ((@0 >= 0x60) && (@0 < SRAM_START))
        sts @0,@1
    .else
       .error "OutReg: Invalid I/O register address"
    .endif
.endmacro




.LISTMAC   ; expand macros in assembler output listing



.CSEG
.org	MYORG	; defined in one of the processor-dependent blocks, above

boot_reset:

;--- init stack
		ldi 	R24,low(RAMEND)		; constant is in the include file
		ldi 	R25,high(RAMEND)
		out 	SPL,R24
		out 	SPH,R25 			; SP = RAMEND

;--- init uart

		;ldi		R24,(1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0)	; 8 bits, 1 stop, async mode
		;out		UCSRC,R24
		
		; UBRRH is zero after a reset so no code here
		ldi 	R24,UBRRLval	; R24,(clock - 8 * bootldr_baud) / (16 * bootldr_baud) 	; Baud rate 
		OUTREG		BAUDL,R24
		; enable tx and rx
		ldi 	R24,UARTENA
		OUTREG 	UARTC,R24 			; Enable receiver & transmitter, 8-bit mode

.ifdef	LED_DDR
		ldi	R24,(1 << LED_BITNO)
		OUTREG	LED_PORT,R24			; LED port and bit, LED will illuminate now
.endif

;--- following waits for esc char, if not received within a given period, jump to application code 
;--- about 1.5 seconds 	@ 7.3728 clock 
;--- delete or chose your own way of entering bootstrap code

		clr	R23		; used for PC timeout counters
		clr	R24		; R23:24 are a 16 bit counter incrementing R25 each roll-over (65536 iterations)
		ldi	R25,PCTIMEOUT		; R25 is increments up to PCTIMEOUT

; LOOP until a character other than <escape> is received or until too much time has elapsed.
;  Then go to user program at location 0.

boot_esc_lp:	
							;;rcall	nada		; kill some time
		dec		R23
		brne	boot_r_1
		dec		R24
		brne	boot_r_1		; 16 bit counter loop

.ifdef	LED_DDR
		OUTREG		LED_PORT,R25			; this makes LED blink visibly
.endif	
		dec		R25
		brne	boot_r_1

; --- TIMED OUT, STARTUP USER PROGRAM
boot_r_0:
		clr		R30				; ensure 0 if jump here from elsewhere
		clr		R31
		OUTREG	UARTC,R30			; disable UART
		ijmp					; timeout, jump to address zero

boot_r_1:
		INREG	R16,USTAT
		sbrs 	R16,URXC 			; Skip if UART byte has arrived
		rjmp 	boot_esc_lp			; not yet, loop

		INREG	R16,UDATA 			; get received data in R16
		cpi		R16,0x1b			; ESC?
		breq	boot_esc_lp			; 
		rjmp	L10					; decode 1st received char that's not an ESCAPE

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

b_main: rcall 	uartGet 			; repeat (R16 = uartGet)
		cpi 	R16,0x1B			; while (R16 == ESCAPE)
		breq 	b_main

L10:	cpi		R16,'a'				; if(R16=='a') 'a' = inquiry: Autoincrement supported?
		brne 	L12
		ldi 	R16,'Y' 			; Reply with Yes, autoincrement is quicker
		rjmp 	L70 				; uartSend(R16)


L12: 	cpi 	R16,'A' 			; else if(R16=='A') set write address
		brne 	L12x1

;--- get word address from UART, convert to byte address
		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 to word address; save bit 15 to carry

.ifdef RAMPZ
		; added this bst instruction for large flash support (stevech)
		clr		R16					; Carry unchanged by clr
		rol		R16					; get carry from previous ROL R27 into bit 0
		out		RAMPZ,R16			; bit 0 is word address bit 15
.endif
		rjmp 	send_cr 			; uartSend('\r')

; --- Block write command inquiry added June 2006 Steve Childress
L12x1:	cpi		R16,'b'				; block mode suport inquiry by host
		brne	L13

		ldi		R16,'Y'
		rcall	uartSend
		ldi		R16,high(PAGESIZE*2); this chip's flash buffer size in bytes
		rcall	uartSend
		ldi		R16,low(PAGESIZE*2)	
		rjmp	L70					; send and continue


L13:	cpi		R16,'B'				; 'B' is write block of EEPROM or FLASH data
		brne	L14

; --- Block write command added June 2006 Steve Childress
		rcall	L13x4				; get block size then E or F command
		cpi		R16,'F'
		brne	L13x5

	; R26:27 have byte address from assumed previous 'A' command
	; R28:29 have block size in bytes
L13x2:	rcall	uartGet				; get upper byte of flash word
		mov		R0,R16	
		rcall	uartGet
		mov		R1,R16				; word is now in R1:R0
		movw	R30,R26				; Z register must hold byte addr from the 'A' command       
		ldi		R19,(1<< SPMEN)		; setup for write to flash buffer
		OUTREG	SPMCSR,R19				; must set this bit 
		spm							; store r0:r1 to chip's special flash buffer
		adiw	r26,2				; byte address
		sbiw	r28,2				; block size counter
		brne	L13x2				; loop for all bytes in the block
	; Write block - R30:31 have last used addr within block
		rjmp	L30					; do the page write and reply to PC

	; subroutine common to 'B' and 'g' commands. 
	; get block size from uart, but in R28:29. Get next uart byte in R16 and return
L13x4:		
		rcall 	uartGet				; block size high order byte
		mov		R29,R16
		rcall 	uartGet				; block size low order byte
		mov		R28,R16				;  have block size
		rjmp 	uartGet				; next is 'F' for Flash data or 'E'


L13x5:	
;;; Block mode EEPROM not supported (makes bootloader smaller)
;;;		cpi		R16,'E'				; 'E' for block mode EEPROM data
;;;		brne	L14				; 
;;;		rjmp	cmdUnknown			; NOT IMPLEMENTED - will wind up at cmdUnknown
	

L14: 	cpi 	R16,'c' 			; else if(R16=='c') write program memory, low byte
		brne 	L16
;---  get program memory low byte from UART
		rcall 	uartGet
		mov 	R22,R16 			; R22 = data low byte, keep for use for the next "C" command
		rjmp 	send_cr 			; uartSend('\r')

;---  get program data high byte from UART and store in on-chip buffer 
L16: 	cpi 	R16,'C' 			;else if(R16=='C') write program memory,high byte
		brne 	L17

		rcall 	uartGet
		mov 	R23,R16 			; R23 = data high byte. R22 has low byte from the "c" command

		movw 	R30,R26 			; Z pointer = byte address
		movw 	R0,R22 				; R0&R1 = data
	
		ldi 	R24,1 				; SPMCR = 0x01
		OUTREG	SPMCSR,R24			; page load (fill temporary buffer)
		spm 						; Store program memory

		adiw 	R26,2 				; address+=2   A new "A" command should come after addr rollover to 0
		rjmp 	send_cr 			; uartSend('\r')

L17:
		cpi		R16,'g'				; read block?
		brne	L18


; --- 'g' comamnd read flash block added. Steve Childress June 2006
		rcall	L13x4				; get block size
		cpi		R16,'F'				; flash?
		brne	L17x6
		movw	R30,R26				; get address in R30:31 (Z)
L17x2:
.ifdef RAMPZ						; chips with more than 64K Bytes of
		elpm 	R16,Z+ 				; read program memory MSB; store MSB in R16 and Z pointer ++
		; this reads just one block so if Z rolls over to 0 it doesn't matter as there's a "A" command every block
		rcall 	uartSend 			; uartSend(R16) MSB
		elpm 	R16,Z+ 				; read program memory LSB
.else
		lpm 	R16,Z+ 				; read program memory MSB; store MSB in R16 and Z pointer ++
		rcall 	uartSend 			; uartSend(R16) MSB
		lpm		R16,Z+				; read program memory LSB
.endif
		rcall 	uartSend 			; uartSend(R16) LSB+
		sbiw	R28,2				; R28:29 is counter based on block size
		brne	L17x2				; loop while using Z register

		movw	R26,R30				; update for auto-incrm
		rjmp	b_main				; wait for another command like 'g'

L17x6:
;;;		cpi		R16,'E'				; 'E' for block mode EEPROM data			; 
;;;		rjmp	cmdUnknown			; NOT IMPLEMENTED - will wind up at cmdUnknown


;--- chip erase?
L18: 	cpi 	R16,'e' 			; else if(R16=='e') Chip erase
		brne 	L28
		
;  erase all flash, page at a time

		clr		zl					; word address 0
		clr		zh
L19:
		lsl		zl					; get byte address within 64KByte space of flash
		rol		zh
.ifdef RAMPZ
		clr		R16					; doesn't affect carry
		rol		R16					; get 16th bit of word addr from carry to bit 0
		out		RAMPZ,R16			; and to bit 0 of RAMPZ
		ror		R16					; put it back into carry
.endif 				
		ldi		R17,( (1<<PGERS) | (1<<SPMEN) )	  ; page_erase
		OUTREG	SPMCSR,R17 
		spm
		rcall	wait_spm			; wait for done; preserving C bit
		ror		zh					; back to word addr, C held 16th word addr bit
		ror		zl						
								
		subi 	zl,low(-(PAGESIZE)) 		; address +=  ; PAGESIZE is in words
		sbci 	zh,high(-(PAGESIZE))		; subtract negative PAGESIZE in words = add

		ldi		R24,low(MYORG)		; is a word addr
		ldi		R25,high(MYORG)
		cp		zl,R24				; compare 16 bit word addr in Z, spans 128KByte Flash
		cpc		zh,R25
		brlo	L19	
		rjmp 	send_cr				; uartSend('\r')

;===========================================
#ifdef	NONESUCH	; old version not right for 128KB flash
		clr 	R26 				; start at addr 0
		clr 	R27
		rjmp	L24				; test for end

L20: 	movw 	R30,R26 			; Z-pointer = byte address
		ldi 	R24,3 				; SPMCR = 0x03
		WRITEPMCR 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)		; subtract negative PAGESIZE = add

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -