program boot loader atmega 8
TRANSCRIPT
-
7/27/2019 Program Boot Loader Atmega 8
1/23
Program boot loader atmega 8
Hardware
Basically AVRUSBBoot can be used with all circuits which are supported by the AVR USB driver. Toswitch between the bootloader and the application, an aditional jumper is necessary. Here is anexample (Here the levels on the data lines are 5V which doesn't meet the USB specification! Thesupply voltage should be regulated to 3,3V - 3,6V):
;----------------------------------------------------------------------------------------;; Program: Bootloader_Mega8.asm;; Writer: Herbert Dingfelder, DL5NEG; for contact information visit WWW.DL5NEG.DE;; Based on: AVR-Freaks Design Note #32;; Function: Bootloader for ATmega8, Works via the UART with thenormal; AVRProg PC-Software;; Hardware: ATmega8 with a 7.3728MHz crystal;; History:;; 13.07.2004 - Source code adapted for Mega8, assembles withouterrors;
-
7/27/2019 Program Boot Loader Atmega 8
2/23
; 15.07.2004 - Used crystal is not 7.3 but 3.686 MHz -> UARTsetting adapted; - LED on LEDport/LEDbit is switched onwithin the boot section,; tested in Hardware and works -> processorstarts correctly
; within the boot section; 18.07.2004 - Problem how to download the bootloader is solved:Simply use; the AVRProg in the "mega8" mode, not in"mega8boot" mode.; Since the Intel-Hex Format contains theaddress for the code; in each line, the programmers recognizesthat the code has to; go to the bootrom part of the flash(provide that the; ".org MY_BOOTSTART" is put at thebeginning of the source code)
; - UART communication between bootloader andhost PC works; (echo mode and character recognitiontested and works); - Crystal changed to 7.3728MHz in an attemptto fight "flushing"; problems in AVRProg (without success),UART setting adapted; - AVRProg is able to read the flashcorrectly (tested, works); - Reading and writing to EEPROM on hostcommands 'D' and 'd' works.; - Flash erase did not work in the NRWRsection (the last 1024; words of the flash) The original versionfrom DesignNote #32; was for ATmega163 which does not haveRWR/NRWR sections.; Problem solved by implementing thewait_for_spm function that; makes sure that a new SPM does only startwhen the previous one; is completed. (tested, works now); - function to reenable the RWW sectionimplemented ->; loading data into the application sectiontested and works fine; (Still some problems with sync on theinterface between AVRProg; and the boot loader, messagebox "flushing"appears, fuse bits are; read differently many times and softwaredownload needs to be; started twice sometimes. As it is knownthat AVRProg is very sensible; command/answer sync, this does not pointtowards real bootloader problems.; It has to be tracked on the interface.); -> Good enough to work with temporarily,Version 1.0 released.; - Startup-function implemented for 10 secondwait after power-on. If
-
7/27/2019 Program Boot Loader Atmega 8
3/23
-
7/27/2019 Program Boot Loader Atmega 8
4/23
-
7/27/2019 Program Boot Loader Atmega 8
5/23
;; The Fuse bits must be programmed before programming the Lockbits.;;; AVRProg Commands as defined by Atmel
;; Host Writes; ID; Enter Programming Mode 'P'; Auto Increment Address 'a' dd; Set Address 'A' ah al; Write Program Memory, Low Byte 'c' dd; Write Program Memory, High Byte 'C' dd 13d; Issue Page Write 'm'; Read Lock Bits 'r' dd; Read Program Memory 'R' 2*dd; Read EEPROM Memory 'd' dd; Write EEPROM Memory 'D' dd
; Chip Erase 'e'; Write Lock Bits 'l' dd; Read Fuse Bits 'F' dd; Read High Fuse Bits 'N' dd; Read Extended Fuse Bits 'Q' dd; Leave Programming Mode 'L'; Select Device Type 'T' dd; Read Signature Bytes 's' 3*dd; Return Supported Device Codes 't' n*dd 00d; Return Software Identifier 'S' s[7]; Return Software Version 'V' dd dd; Return Hardware Version 'v'; Return Programmer Type 'p' dd; Set LED 'x' dd; Clear LED 'y' dd; Exit Bootloader 'E'; Check Block Support 'b' 'Y' 2*dd; Start Block Flash Load 'B' 2*dd'F' 13d (not implemented);; Start Block EEPROM Load 'B' 2*dd 'E' 13d;; Start Block Flash Read 'g' 2*dd'F' n*dd (not implemented); Start Block EEPROM Read 'g' 2*dd 'E' n*dd; Universal Command (3 data bytes) ':' 3*dd dd 13d; New Universal Command (4 data bytes)'.' 4*dd dd 13d;
;-------------------------definition and includes ---------------------------------------
.INCLUDE "m8def.inc" ; Include Register/BitDefinitions for the mega8.def tmp_r = r18 ; Use Reg. R18 fortemporary stuff.def pa_10ms = r19 ; used for selectingthe pause time in steps of 10ms
.def uni_cmd1 = r20 ; Universal command':' send three bytes. These
-
7/27/2019 Program Boot Loader Atmega 8
6/23
.def uni_cmd2 = r21 ; are stored forfuther usage in r20, r21, r28.def uni_cmd3 = r10
.equ VER_H = '1' ; bootloader softwareversion higher number
.equ VER_L = '3' ; bootloader softwareversion lower number
.equ VERH_H = '1' ; bootloader hardwareversion higher number.equ VERH_L = '0' ; bootloader hardwareversion lower number
.equ DT = 0x76 ; Device Type = 0x76(ATmega8)
.equ SB1 = 0x07 ; Signature byte 1
.equ SB2 = 0x93 ; Signature byte 2
.equ SB3 = 0x1e ; Signature byte 3
.equ ESC = 27 ; Ascii 27 = Escape
;LR*****************************************************.equ fCK = 7372800 ;X-tal frequency *.equ BaudR=19200 ;Baud rate *.equ Tr_Sp=0 ;Transmission speed (U2X) *.equ UBR=-1+(5+10*fCK/(16*BaudR-8*BaudR*Tr_Sp))/10 ; *.equ presc=1024 ; *.equ fTmr=100 ;freq. of Timer 0 (1/10ms=100) *.equ TmrLoad=256-(fCK/(presc*fTmr)) ; *.equ CR = 13 ; *
; *;Pin for LED and Boot escape definition: *.equ LEDport =PORTc ; *.equ LEDdir =DDRc ; *.equ LEDbit =1 ; *
; *.equ TestPort =PINC ; *.equ TestBit =1 ; *
; *.equ ActiveStatLED=0 ;0=low, 1=high active stat *.if ActiveStatLED ; *.macro set_led ; *
sbi LEDport,LEDbit ; *.endm ; *
; *.macro clr_led ; *
cbi LEDport,LEDbit ; *.endm ; *.else ; *.macro set_led ; *
cbi LEDport,LEDbit ; *.endm ; *
; *.macro clr_led ; *
sbi LEDport,LEDbit ; *.endm ; *.endif ; *
; *
-
7/27/2019 Program Boot Loader Atmega 8
7/23
;LR*****************************************************
.equ MY_BOOTSTART = THIRDBOOTSTART ; here we define where the bootloaderstarts in the flash
;----------------------------- here we go ---------------------------------
--------------
.org MY_BOOTSTART ; bootstart address according to .equ above
; ---------------------------------- Boot Escape ------------------------------------------;LR***********************************
in tmp_r,TestPort ; *sbrc tmp_r,TestBit ; *rjmp FLASHEND+1 ; *
;LR***********************************; ----------------------------------- init stackpointer ---------------------------------
ldi R24, low(RAMEND) ; SP = RAMENDldi R25, high(RAMEND)out SPL, R24out SPH, R25
ldi tmp_r, 0b00000101 ; set prescaler to 1024out TCCR0, tmp_r
; ---------------------------------- init UART ------------------------------------------;LR***********************************.if Tr_Sp ; *
sbi UCSRA,U2x ; *.else ; *
cbi UCSRA,U2x ; *.endif ; *;LR***********************************
ldi tmp_r, LOW(UBR)out UBRRL, tmp_r
.if HIGH(UBR)ldi tmp_r, HIGH(UBR)out UBRRH, tmp_r
.endifldi tmp_r,(1
-
7/27/2019 Program Boot Loader Atmega 8
8/23
start_wait:clr_led ; switch off the LEDrcall pause200 ; wait a momentsbic UCSRA,RXCrjmp Char_Rec0 ; check for incoming
data (if RXC==1)
st_wait2:set_led ; switch on the LEDrcall pause200 ; wait a momentsbic UCSRA,RXC ; check for incoming
data (if RXC==1)rjmp Char_Rec1 ; check for incoming
data (if RXC==1)
dec R17 ; decremente the loopcounter
brne start_wait ; and leave loop ifcounter has reached zero
clr_led ; switch off the LEDrjmp FLASHEND+1 ; Start theapplication program
;--- some character was received ---Char_Rec0:
set_led ; switch on the LEDChar_Rec1:
in R16,UDR ; fetchreceived character and put it into R16
cpi R16, ESC ; if the receivedcharacter was ESC
brne No_ESC ; start thebootloader main loop;--------------------------------- start of main loop -----------------------------------;-------------------- wait for a character from UART other than ESC ---------------------L10:
rcall uartGet ; repeat (R16 =uartGet)
cpi R16, ESC ; while (R16 ==ESCAPE)
breq L10No_ESC:;--------- Command 'E' leaves the bootloader mode and starts theapplication ------------
cpi R16, 'E' ; if(R16=='E') 'E' =Exit bootloader
brne L11;LR********************************
ldi R16,CRrcall uartSend
TstUDRE: sbis UCSRA,UDRE ; wait for empty transmitbuffer (until UDRE==1)
rjmp TstUDRETstTXC: sbis UCSRA,TXC ; wait for USART Transmit Complete (untilTXC==1)
rjmp TstTXC;LR********************************
rcall pause200
-
7/27/2019 Program Boot Loader Atmega 8
9/23
clr_led ; switch off the LEDrjmp FLASHEND+1 ; Start the
application program;
(flashend+1) = Address 0;--------- Command 'a' is question from host for autoimcrement capability--
--------------; simple anser is 'Y' for yes, autoincrementis doneL11:
cpi R16, 'a' ; if(R16=='a') 'a' =Autoincrement?
brne L12
ldi R16,'Y' ; Yes, autoincrementis quicker
rjmp L70 ;uartSend(R16) Send the 'Y' and go up for next command
;--------- Command 'A' is setting the address for the next operation --------------------; two bytes (in total) for high and low address are sent fromthe hostL12:
cpi R16,'A' ; else if(R16=='A')write address
brne L14
rcall uartGetmov R27,R16 ; address high byte
is stored in R27
rcall uartGetmov R26,R16 ; address low byte is
stored in R26
lsl R26 ;address=address
-
7/27/2019 Program Boot Loader Atmega 8
10/23
rjmp L68 ;uartSend('\r') send CR and go up for next command
;--------- Command 'C' is write high byte to program memory -----------------------------
; together with the (already received) low byte, the highbyte is writen tothe flashes; page buffer. When the page buffer is completely written, it can betransfered into; the real flash by the "page write" command.;; If only SPMEN is written, the following SPM instruction will store thevalue in R1:R0; in the temporary page buffer addressed by the Z pointer.
L16:
cpi R16,'C' ; else if(R16=='C')
write program memory,high bytebrne L18
rcall uartGet ; read the high bytefrom the host
mov R23,R16 ; store the data highbyte in R23
movw ZL,R26 ; load the Z pointerwith the current address
movw R0,R22 ; transfer the dataword (data high and low byte)
; intoregisters R0 and R1
rcall wait_for_spm ; make sure SPM isready to accept a new task
ldi R24, (1
-
7/27/2019 Program Boot Loader Atmega 8
11/23
; the loop that has to be performed to clear the application
section is:; for(address=0; address < (2*MY_BOOTSTART); address +=
(2*PAGESIZE)); the "address" variable to be used are the registers R26 and R27
clr R26 ; start withaddress 0
clr R27
rjmp L24 ; continue theloop at the check for
;"end-criteria reached"
;......... beginning of erase loop ............L20:
; If the PGERS bit is written to one at the same time as SPMEN, the nextSPM; instruction within four clock cycles executes page erase. The pageaddress; is taken from the high part of the Z pointer.
rcall wait_for_spm ; make sure SPM isready to accept a new task
movw ZL,R26 ; load the Z-pointerwith the address of the
; pageto be erased
ldi R24, (1
-
7/27/2019 Program Boot Loader Atmega 8
12/23
; ..... remember the number of flash-erases in the EEPROM .....
ldi R26,low( E2END -1) ; increment ChipErase Counter located
ldi R27,high(E2END -1) ; at address E2END-1movw R22,R26 ; Save Chip Erase
Counter Address in R22ldi R17,1 ; read EEPROMrcall EepromTalkmov R24,R16 ; R24 = Chip Erase
Counter low bytercall EepromTalkmov R25,R16 ; R25 = Chip Erase
Counter high byteadiw R24,1 ; counter ++out EEDR,R24 ; EEDR = R24 Chip
Erase Counter low bytemovw R26,R22 ; R26 = Chip Erase
Counter Address
ldi R17,6 ; write EEPROMrcall EepromTalkout EEDR,R25 ; EEDR = R25 Chip
Erase Counter high bytercall EepromTalk
; ..........................................................
rcall wait_for_spm ; make sure SPM isready to accept a new task
rcall enable_rww ; reenable theRWW section so it can be accessed again
rjmp L68 ;uartSend('\r') send CR and go up for next command
;---------------------------- Command 'm' is write page ---------------------------------; To execute page write, set up the address in the Z pointer, write'X0000101' to SPMCR; and execute SPM within four clock cycles after writing SPMCR. The data inR1 and R0; is ignored. The page address must be written to PCPAGE. Other bits in theZ pointer will; be ignored during this operation.L28:
cpi R16,'m' ; else if(R16== 'm')Write page
brne L34
rcall wait_for_spm ; make sure SPM isready to accept a new task
movw ZL,R26 ; load Z-pointer withaddress
ldi R24, (1
-
7/27/2019 Program Boot Loader Atmega 8
13/23
nop
rcall enable_rww ; reenable theRWW section so it can be accessed again
L32: rjmp L68 ;uartSend('\r') send CR and go up for next command
;--------------------- Command 'P' is enter programming mode ----------------------------; nothing is done here, only the command is confirmed to host by sending CRL34:
cpi R16,'P' ; else if(R16=='P')Enter programming mode
breq L32 ;uartSend('\r') Send CR to host and go up for next command
;--------------------- Command 'L' is leave programming mode ----------------------------; nothing is done here, only the command is confirmed to host by sending CR
cpi R16,'L' ; else if(R16=='L')Leave programming mode
breq L32 ;uartSend('\r') Send CR to host and go up for next command
;--------------------- Command 'p' is Return programmer type ----------------------------; simply return an 'S' to indicate to host that this is a serial programmer
cpi R16,'p' ; else if (R16=='p')Return programmer type
brne L38
ldi R16,'S' ; uartSend('S')Serial
rjmp L70 ;uartSend(R16) and go up for next command;--------------------- Command 'R' is "Read one word from program memory" ---------------; reads one word from the 'current' address that is stored in R26 andincrements R26L38:
cpi R16,'R' ; else if(R16=='R')Read program memory
brne L40
movw ZL,R26 ; load Z-pointer withaddress of memory to be read
lpm R24,Z+ ; read programmemory LSB; store LSB in R24 and Z pointer ++
lpm R16,Z+ ; read programmemory MSB; store MSB in R16 and Z pointer ++
rcall uartSend ; uartSend(R16) writeback MSB to host
-
7/27/2019 Program Boot Loader Atmega 8
14/23
movw R26,ZL ; increment the
'current' address += 2
mov R16,R24 ; LSB stored in R16
rjmp L70 ;uartSend(R16) write back the LSB to host and go; up for next command
;--------------------- Command 'D' is "write data to EEPROM" ----------------------------L40:
cpi R16,'D' ; else if (R16=='D')Write data to EEPROM
brne L41rcall uartGet ; fetch the data to
write from the UARTout EEDR,R16 ; EEDR = uartGet()
ldi R17,6 ; write EEPROMrcall EepromTalkrjmp L68 ;
uartSend('\r') Confirm the command to host with CR
;--------- Command 'b' is question from host for block mode capability----------------; simple anser is 'N' 'N', no bootloader does not supportblockmodeL41:
cpi R16, 'b' ; if(R16=='b') 'b' =Blockmode?
brne L42
ldi R16,'N' ; send 'N'rcall uartSend
ldi R16,'N' ; send 'N'rjmp L70 ;
uartSend(R16) Send the 'N' and go up for next command
;--------------------- Command 'd' is "read data from EEPROM -----------------------------L42:
cpi R16,'d' ; else if (R16=='d')Read data from EEPROM
brne L43ldi R17,1 ; read EEPROMrcall EepromTalk ; R16 = EEPROM datarjmp L70 ;
uartSend(R16)
;-------------------------- Command ':' is universal command ----------------------------; Host sends 3 more bytes which must be used to determine the requiredaction. AVRProg; uses the ':' with parameters to do things that could simply be done byr/F/N.; We have to map recognized parameters to the refering action.
-
7/27/2019 Program Boot Loader Atmega 8
15/23
L43:
cpi R16,':' ; else if(R16==':')Universal Command
brne L44
;.............. read in the parameters...............................
rcall uartGet ; R16 = uartGet()mov uni_cmd1, r16 ; store the read byte
rcall uartGet ; R16 = uartGet()mov uni_cmd2, r16 ; store the read byte
rcall uartGet ; R16 = uartGet()mov uni_cmd3, r16 ; store the read byte
;.....................................................................
clr r16 ; preset r16with zero, if parameters are not
;recognized, zero will be returned to host
;.....................................................................
cpi uni_cmd1, 0x58 ; check if 1stparamter is 0x58
brne cmd1_not_0x58
cpi uni_cmd2, 0x00 ; check if 2ndparamter is 0x00
brne cmd2_not_0x00_1
; -> 58 00 is read lock bits,ldi ZL,1 ; Z pointer =
0001 (-> readFuseAndLock will read lock)rcall readFuseAndLock ; go get the requested bits
cmd2_not_0x00_1:
cpi uni_cmd2, 0x08 ; check if 2ndparamter is 0x08
brne cmd2_not_0x08
; -> 58 08 is read fuse high bits,ldi ZL,3 ; Z pointer =
0003 (-> readFuseAndLock will read high fuse)rcall readFuseAndLock ; go get the requested bits
cmd2_not_0x08:
cmd1_not_0x58:
cpi uni_cmd1, 0x50 ; check if 1stparamter is 0x50
brne cmd1_not_0x50
-
7/27/2019 Program Boot Loader Atmega 8
16/23
cpi uni_cmd2, 0x00 ; check if 2nd
paramter is 0x00brne cmd2_not_0x00_2
; -> 50 00 is read fuse bits,
clr ZL ; Z-pointer =0000 (-> readFuseAndLock will read fuse)rcall readFuseAndLock ; go get the requested bits
cmd2_not_0x00_2:
cmd1_not_0x50:
rcall uartSend ; uartSend(bits) sendthe read lock/fuse bits
rjmp L68 ;uartSend('\r') and go up for next command
;--------------------- Command 'F' is "read fuse bits" ----------------------------------L44:
cpi R16,'F' ; else if(R16=='F')Read fuse bits
brne L46clr ZL ; Z-pointer =
0000 (-> readFuseAndLock will read fuse)rjmp L50 ; rcall
readFuseAndLock
;--------------------- Command 'r' is "read lock bits" ----------------------------------L46:
cpi R16,'r' ; else if(R16=='r')Read lock bits
brne L48ldi ZL,1 ; Z pointer =
0001 (-> readFuseAndLock will read lock)rjmp L50 ; rcall
readFuseAndLock
;--------------------- Command 'N' is "read fuse high bits" -----------------------------L48:
cpi R16,'N' ; else if(R16=='N')Read high fuse bits
brne L52ldi ZL,3 ; Z-pointer =
0003 (-> readFuseAndLock will read high fuse)
;-------- for all previous commands F,r,N hear we call the readFuseAndLock--------------; function that will read the bits that are indicated by theZ-registerL50:
-
7/27/2019 Program Boot Loader Atmega 8
17/23
rcall readFuseAndLockrjmp L70 ;
uartSend(R16)
;--------------------- Command 't' is Return supported devices code -------
--------------; obviously we return only the device code ofthe mega8 hereL52:
cpi R16,'t' ; else if(R16=='t')Return supported devices code
brne L54
ldi R16,DT ; Device Typercall uartSend ; uartSend(DT) send
Device Type of Mega8
clr R16 ; command set
of AVRProg requires the termination of ; thet-command with a \0 not with a CR as other commands
rjmp L70 ; uartSend(0)and go up for next command
; ---------------- ignored commands that are not sensible for boot loader ---------------; The following 4 commands only make sense for a general programmer, notfor a bootloader.; As theres commands come with an additional byte as parameter, with haveto fetch that; byte from the UART to avoid messing up the UART reading.L54:
cpi R16,'l' ; 'l' = Write BootLoader lockbits
breq L56
cpi R16,'x' ; 'x' = Set LEDbreq L56
cpi R16,'y' ; 'y' = Clear LEDbreq L56
cpi R16,'T' ; 'T' = Select devicetype
brne L60
L56:rcall uartGet ; R16 = uartGet()rjmp L68 ;
uartSend('\r') and go up for next command
;--------------------- Command 'S' is Return software identifier ------------------------L60:
cpi R16,'S' ; else if(R16=='S')Return software identifier
brne L62
-
7/27/2019 Program Boot Loader Atmega 8
18/23
ldi ZL,low(2*Soft_Id) ; load address of String intoZ-Register
ldi ZH,high(2*Soft_Id)
L61:lpm R16,Z+ ; read one
character of the string and increment string pointer
tst R16breq L72 ; exit the
character output loop charcter was '\0'
rcall uartSend ; send the readcharacter via the UART
rjmp L61 ; go to startof loop for next character
;--------------------- Command 'V' is Return software Version ---------------------------L62:
cpi R16,'V' ; else if (R16=='V')Return Software Version
brne L63
ldi R16, VER_H ; send bootloadersoftware version higher number
rcall uartSend
ldi R16, VER_L ; send bootloadersoftware version lower number
rjmp L70 ; uartSend andgo up for next command
;--------------------- Command 'v' is Return hardware Version ---------------------------L63:
cpi R16,'v' ; else if (R16=='v')Return hardware Version
brne L64
ldi R16, VERH_H ; send bootloadersoftware version higher number
rcall uartSend
ldi R16, VERH_L ; send bootloadersoftware version lower number
rjmp L70 ; uartSend andgo up for next command
;--------------------- Command 's' is Return Signature Byte -----------------------------L64:
cpi R16,'s' ; else if (R16=='s')Return Signature Byte
brne L65
ldi R16,SB1 ; uartSend(SB1)Signature Byte 1
-
7/27/2019 Program Boot Loader Atmega 8
19/23
rcall uartSend
ldi R16,SB2 ; uartSend(SB2)Signature Byte 2
rcall uartSend
ldi R16,SB3 ; uartSend(SB3)Signature Byte 3rjmp L70 ; uartSend and
go up for next command
;--------------------- Command '.' is new universal command -----------------------------; this command will be ignored, only the inteface will be handled correctlyL65:
cpi R16,'.' ; else if (R16=='.')New Universal Command
brne L66
;.............. read in the 4 parameters...............................
rcall uartGet ; R16 = uartGet()rcall uartGet ; R16 = uartGet()rcall uartGet ; R16 = uartGet()rcall uartGet ; R16 = uartGet()
;......................................................................
clr R16 ; uartSend(/0)rcall uartSend
rjmp L68 ;uartSend('\r') and go up for next command
;++++++++++++++ handling the different command till here++++++++++++++++++++++++++++++++; only general completion for all commands below
;---------------------- failed commands can end up here ---------------------------------; an '?' is send via the UART to indicate fail host, then main loopstarts again
L66:ldi R16,'?' ; else uartSend('?')rjmp L70 ;
uartSend(R16)
;--------- successfully completed commands without return value can end uphere ---------; an CR is sent via the UART to confirm execution to host, then mainloop starts again
L68:ldi R16,13 ;
uartSend('\r')
-
7/27/2019 Program Boot Loader Atmega 8
20/23
;------------ successfully completed commands with return value can end uphere ---------; the return value is sent via the UART to confirm execution to host; then main loop startsagain
L70: rcall uartSend ; uartSend(R16)
L72:rjmp L10 ; jump up to
beginning of main loop
;-------------------------- end of main loop --------------------------------------------
;================= end of main program, only subroutines from here on
===================
;------------------ reads fuse or lock bits (depending on Z-Reg.) -------------readFuseAndLock:
; An LPM instruction within three cycles after BLBSET and SPMEN areset in the SPMCR
; Register, will read either the Lock bits or the Fuse bits; (depending on Z0 in the Z pointer) into the destination register.
rcall wait_for_spm ; make sure SPM isready to accept a new task
clr ZH ; Z pointerhigh byte = 0
ldi R24,(1
-
7/27/2019 Program Boot Loader Atmega 8
21/23
L90:sbic EECR,EEWE ; wait until EEWE ==
0rjmp L90in R16,EEDR ; R16 = EEDR
ret
;---------------- send one character via UART (parameter is r16) --------------uartSend:
sbis UCSRA,UDRE ; wait for emptytransmit buffer (until UDRE==1)
rjmp uartSendout UDR,R16 ; UDR = R16, start
transmission
ret
;---------------- read one character from UART (returned in r16) --------------uartGet:
sbis UCSRA,RXC ; wait for incomingdata (until RXC==1)
rjmp uartGetin R16,UDR ; return
received data in R16
ret
;-------------------- wait for SPM to be ready for new tasks ------------------; while( SPMCR_REG & (1
-
7/27/2019 Program Boot Loader Atmega 8
22/23
; If this is not done, all addresses will read $FF even if they containother values.enable_rww:
rcall wait_for_spm ; make sure SPM isready to accept a new task
ldi r16, (1
-
7/27/2019 Program Boot Loader Atmega 8
23/23
:101E3000809BFBCF0F2EC5950694E9F72397269636:101E400068F7EA35F20550F3F797F695E7952F0115:101E5000CAE0E6EBFFE10590002031F078D00016F3:101E6000D1F3CA9591F0F5CF06EA8AD070D0E1F7A8:101E70000AEA86D06CD0F1F76AD0F1F3F101E89468:101E80000430F0F059F1063018F422BA21BAB8C083
:101E900031F45DD05CD0672859F331010FC00730B1:101EA00059F455D019F453D0005821F00590001280:101EB0006894F7CF1EF0DCCF07EADBCF0BEAD9CF6F:101EC000ECEBFFE1C0E0EC0FF21DC4910150D8F73C:101ED00008EA56D00591C150E0F7CACFA0E6B0E0BD:101EE000ED0135D021F433D00058689431F0E894F6:101EF0000D93A03204E0B007A1F7AC17BD0731F194:101F0000A0E2B4E0E054FC4F10E232971E900E9035:101F100001E015D01A95C9F7E0301EE1F107A8F4E9:101F200003E00DD005E009D0AC17BD0769F776F0E6:101F3000E054FC4F09EA24D0D4CF01D001E107BF1F:101F4000E89507B700FDFDCF0895B8CF91CF809BEE:101F5000FECF8099FECF18E0C2019695879523D0D9
:101F600021D006958099006807FD642676946794D1:101F700008F4642608F475261A9591F7053A089531:101F800011D09198149119E0009500C000C00AD0BA:101F9000069518F40000919802C0919A00C01A9515:101FA000A1F70895C2010497F0F78D3F18F011F0E2:101FB0008F3F01F00895506564610000030107033D:0A1FC00003C0041E930704001E0076:00000001FF