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

📄 m16_boot.asm

📁 Eversmith_-_AVRSMS for pdu mode
💻 ASM
字号:

;**********  B O O T   L O A D E R   F O R   A T m e g a 1 6 3  **********
;* File          : AVRBoot2.asm  (Include chip erase counter)
;* Version       : 1.3
;* Compiler      : AVR Studio
;* Target        : ATmega163
;* Output size   : 412 bytes

; code by:
; Mariano Barr髇 Ruiz
; ispbarum@sb.ehu.es

; changes/comments by Martin Thomas, eversmith@heizung-thomas.de
; - works fine with ATmega16 from AVRStudio 4.07 AVRProg, 
;   thanks Mariano
; - .INCLUDE changed to m16def.inc, added .nolist,.list
; - make start condition configurable, bootloader startes if pin 
;   is grounded (pulled low) on Device-Reset, enable internal pull-ups 
;   to avoid external resistor
; - disabled cycle counter
; - baud-rate configureable
; - changed device type to ATmega16
; - fuse-settings:
;	BOOTRST - programmed   (0, checked   in Ponyprog2000)
;	BOOTZ1  - unprogrammed (1, unchecked in Ponyprog2000)
;	BOOTZ0  - programmed   (0, checked   in Ponyprog2000)

;.INCLUDE "m163def.inc"   ; Include Register/Bit Definitions for the ATmega163
; - mt
.nolist
.INCLUDE "m16def.inc"   ; Include Register/Bit Definitions for the ATmega16
.list

 .equ clock_boot  = 8000000 	; MHz
 .equ baud_boot   = 19200

; boot code will be enabled if the pin boot_pin on port boot_port
; is pulled low during device-reset - mt
.equ BTDDR    = DDRA
.equ BTPORT   = PORTA
.equ BTPIN    = PINA
.equ BTPINPX  = PINA7

;.equ DT      = 0x66      ; Device Type = 0x66  (ATmega163)
;.equ SB1     = 0x02      ; Signature byte 1
;.equ SB2     = 0x94      ; Signature byte 2
;.equ SB3     = 0x1e      ; Signature byte 3

; mt - for ATMega16
; see souce code and Excel-Workbook to App-Note 109 for Type
; see uC Manual for Signatures
.equ DT      = 0x74      ; Device Type = 0x74  (ATmega16) - mt
.equ SB1     = 0x03      ; Signature byte 1 for ATmega16 - mt
.equ SB2     = 0x94      ; Signature byte 2
.equ SB3     = 0x1e      ; Signature byte 3


.equ UBRBT   = (clock_boot/(16*baud_boot))-1 ; - mt

.org  SECONDBOOTSTART    ; ($1F00) second boot. Block size is 512B
;        sbic PINC,PINC0   ; Skip next instruction if PINC0 cleared
;        rjmp FLASHEND+1   ; else normal execution from Reset (FLASHEND+1 = Address 0000)

		clr	r24	
		out BTDDR,r24		; port as input
		ser r24
		out BTPORT,r24		; enable internal pull-ups 
		nop	; sync
		nop	; sync more
		nop	; sync even more
		nop	; ...
		sbic BTPIN,BTPINPX
		; skip next instruction if the pin is cleared (=pulled down)
		rjmp FLASHEND+1		; else normal execution from Reset (FLASHEND+1 = Address 0000)
		
; Programming mode
BOOTLSTART:
        ldi R24,low(RAMEND)
        ldi R25,high(RAMEND)
        out SPL,R24
        out SPH,R25       ; SP = RAMEND

        ldi R24,UBRBT     ; Baud rate 
        out UBRR,R24
        ldi R24,(1<<RXEN)|(1<<TXEN)
        out UCSRB,R24     ; Enable receiver & transmitter, 8-bit mode

;       data    -> R22,R23
;       address -> R26,R27

L10:    rcall uartGet     ; repeat (R16 = uartGet)
        cpi R16,27        ; while  (R16 == ESCAPE)
        breq L10

        cpi R16,'a'       ; if(R16=='a') 'a' = Autoincrement?
        brne L12
        ldi R16,'Y'       ; Autoincrement? Yes, autoincrement is quicker
        rjmp L70          ; uartSend(R16)

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 word address to byte address
        rjmp L68          ; uartSend('\r')

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 L68          ; uartSend('\r')

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<<SPMEN); page load (fill temporary buffer)
        rcall Do_SPM      ; do fill temporary buffer
        adiw R26,2        ; address=address+2
        rjmp L68          ; 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
L20:    movw R30,R26      ; Z pointer <= address
        ldi R24,(1<<PGERS)|(1<<SPMEN)
        out SPMCR,R24     ; page_erase
        rcall Do_SPM      ; do page_erase
        ldi R24,(1<<ASRE)|(1<<SPMEN) ; Re-Enable the RWW section
        rcall Do_SPM      ; do Enable RWW section
        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
;        ldi R27,high(E2END-1); at address 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 L68          ; uartSend('\r')

L28:    cpi R16,'m'       ; else if(R16== 'm')  Write page
        brne L34
        movw R30,R26      ; Z pointer <- address
        ldi R24,(1<<PGWRT)|(1<<SPMEN) ; Write page
        rcall Do_SPM      ; do Write page
        ldi R24,(1<<ASRE)|(1<<SPMEN) ; Re-Enable the RWW section
        rcall Do_SPM      ; do Enable RWW section
L32:    rjmp L68          ; 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')

        cpi R16,'p'       ; else if (R16=='p') Return programmer type
        brne L38
        ldi R16,'S'       ; uartSend('S')  Serial
        rjmp L70          ; uartSend(R16)

L38:    cpi R16,'R'       ; else if(R16=='R') Read program memory
        brne L40
        movw R30,R26      ; Z pointer <= address
        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 ++
        rcall uartSend    ; uartSend(R16) MSB
        movw R26,R30      ; address += 2
        mov R16,R24       ; LSB stored in R16
        rjmp L70          ; uartSend(R16) LSB

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 L68          ; uartSend('\r')

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:    cpi R16,'F'       ; else if(R16=='F') Read fuse bits
        brne L46
        clr R30           ; Z pointer = 0000
        rjmp L50          ; rcall readFuseAndLock

L46:    cpi R16,'r'       ; else if(R16=='r')  Read lock bits
        brne L48
        ldi R30,1         ; Z pointer = 0001
        rjmp L50          ; rcall readFuseAndLock

L48:    cpi R16,'N'       ; else if(R16=='N') Read high fuse bits
        brne L52
        ldi R30,3         ; Z pointer = 0003
L50:    rcall readFuseAndLock
        rjmp L70          ; uartSend(R16)

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)

L54:                      ; else if ((R16=='l')||(R16=='x')||(R16=='y')||(R16=='T'))
        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
        cpi R16,'T'       ; 'T' = Select device type
        brne L60
L56:    rcall uartGet     ; R16 = uartGet()
                  ; YOU CAN INSERT LEDs CODE  HERE
        rjmp L68          ; uartSend('\r')

L60:    cpi R16,'S'       ; else if (R16=='S') Return software identifier
        brne L62
        ldi R30,low(2*Soft_Id)
        ldi R31,high(2*Soft_Id)
L61:    lpm R16,Z+
        tst R16
        breq L72          ; branch is end of string  ((Z) == 0)
        rcall uartSend    ; else send char
        rjmp L61

L62:    cpi R16,'V'       ; else if (R16=='V') Return Software Version
        brne L64
        ldi R16,'1'       ; uartSend('1')
        rcall uartSend
        ldi R16,'3'       ; uartSend('3')
        rjmp L70          ; uartSend(R16)

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)

L66:    ldi R16,'?'       ; else uartSend('?')
        rjmp L70          ; uartSend(R16)
L68:    ldi R16,13        ; uartSend('\r')
L70:    rcall uartSend    ; uartSend(R16)
L72:    rjmp L10

readFuseAndLock:
        clr R31           ; Z pointer high byte = 0
        ldi R24,9         ; SPMCR = 0x09
        out SPMCR,R24     ; read fuse and lock
        lpm R16,Z         ; read program memory
        ret

EepromTalk:               ; if R17 = 6 write, if R17 = 1 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

Do_SPM:                   ; check for previous SPM complete
Wait_SPM:                 ; wait until page erase (or page write) is completed
        in R20,SPMCR      ; SPMEN==0 after page erase or page write completed
        sbrc R20,SPMEN    ; skip if bit SPMEN in SPMCR is cleared
        rjmp Wait_SPM
L92:    sbic EECR,EEWE    ; wait until EEWE == 0
        rjmp L92          ; check that no EEPROM write access is running
        out  SPMCR,R24
        spm               ; store program memory
        .dw  0xffff       ; ensure proper instruction pipelining after
        nop               ; programming (mega163, mega323, ...)
        ret


uartSend:                 ; send R16
        sbis UCSRA,UDRE   ; wait for empty transmit buffer (until UDRE==1)
        rjmp uartSend
        out UDR,R16       ; UDR = R16, start transmission
        ret

uartGet:
        sbis UCSRA,RXC    ; wait for incoming data (until RXC==1)
        rjmp uartGet
        in R16,UDR        ; return received data in R16
        ret

;Soft_Id: .DB "AVRB163", 0
; -mt
Soft_Id: .DB "AVRBm16", 0

; END of BOOT LOADER PROGRAM

⌨️ 快捷键说明

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