 |

|
Elektronika.lt portalo forumas
Jūs esate neprisijungęs lankytojas. Norint dalyvauti diskusijose, būtina užsiregistruoti ir prisijungti prie forumo.
Prisijungę galėsite kurti naujas temas, atsakyti į kitų užduotus klausimus, balsuoti forumo apklausose.
Administracija pasilieka teisę pašalinti pasisakymus bei dalyvius,
kurie nesilaiko forumo taisyklių.
Pastebėjus nusižengimus, prašome pranešti.
Dabar yra 2025 08 31, 06:11. Visos datos yra GMT + 2 valandos.
|
|
|
 |
Forumas » Elektronika žaliems » ATmega64 BootLoader
|
Jūs negalite rašyti naujų pranešimų į šį forumą Jūs negalite atsakinėti į pranešimus šiame forume Jūs negalite redaguoti savo pranešimų šiame forume Jūs negalite ištrinti savo pranešimų šiame forume Jūs negalite dalyvauti apklausose šiame forume
|
|
|
 |
 |
 |
ATmega64 BootLoader |
Parašytas: 2012 02 24, 17:24 |
|
|
|
Sveiki, nuriu paklausti, kaip reikia rašyti bootloader'į. Turiu tokį asm source, kurio šiap pakanka, tačiau abar reiktų galimybės source atnaujint SMS žinute į modemą ir jį nuskaityti iš serverio, gal kas yra tai darę ar žino, kur galėčiau rasti jau padaryta kažką panašaus arba bent patarimo, kaip tai daryti.
Kaip minėjau turiu kitų žmonių parašytą tokį kodą:
;----------------------------------------------------------------------------------------
;
; 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 the normal
; AVRProg PC-Software
;
; Hardware: ATmega8 with a 7.3728MHz crystal
;
; History:
;
; 13.07.2004 - Source code adapted for Mega8, assembles without errors
;
; 15.07.2004 - Used crystal is not 7.3 but 3.686 MHz -> UART setting adapted
; - Red LED on PORTB 0 is switched on within the boot section,
; tested in Hardware and works -> processor starts 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 the address for the code
; in each line, the programmers recognizes that the code has to
; go to the bootrom part of the flash (provided that the
; ".org MY_BOOTSTART" is put at the beginning of the source code)
; - UART communication between bootloader and host PC works
; (echo mode and character recognition tested and works)
; - Crystal changed to 7.3728MHz in an attempt to fight "flushing"
; problems in AVRProg (without success), UART setting adapted
; - AVRProg is able to read the flash correctly (tested, works)
; - Reading and writing to EEPROM on host commands 'D' and 'd' works.
; - Flash erase did not work in the NRWR section (the last 1024
; words of the flash) The original version from DesignNote #32
; was for ATmega163 which does not have RWR/NRWR sections.
; Problem solved by implementing the wait_for_spm function that
; makes sure that a new SPM does only start when the previous one
; is completed. (tested, works now)
; - function to reenable the RWW section implemented ->
; loading data into the application section tested and works fine
; (Still some problems with sync on the interface between AVRProg
; and the boot loader, messagebox "flushing" appears, fuse bits are
; read differently many times and software download needs to be
; started twice sometimes. As it is known that AVRProg is very sensible
; command/answer sync, this does not point towards 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 second wait after power-on. If
; no ASCII(27) is received via UART within that time, the application starts.
; If the application section is empty (all cells are $FF) e.g. directly
; after uploading the bootloader itself, then software will wait forever
; for a ESC via the UART to start the bootloader software
; (while waiting for the ESC the LED blinks)
; - Function pause implemented for delays in steps of 10ms (tested works)
; - Command 'E' implemented for leaving the bootloader mode and start the
; application
; - With that entry end exit function the bootloader is fully usable, starting
; the downloaded application is tested and works perfectly
; -> Version 1.1 released
; - Still known problem: the above mentioned sync problem in combination
; with AVRProg have to be identified and solved.
; - Only 2 Words are left in the bootloader memory. If Bugfixing needs more,
; the erease counter within the EEPROM can be skipped
;
; 24.07.2004 - Debug Session with Andy, DG9NDZ to find why AVRProg 1.37 still has some
; problems with the bootloader, especially in the "Advanced" Window.
; - Command 'v' for Hardware Version was not implemented -> fixed
; - Command ':' for tranparent command setting was not implemented
; -> is now implemented in simple version, always returning \0
; By monitoring the PC/AVR interface it was found that AVRProg1.37 does
; not use the defined commands r/F/N for reading the lock and fuse bits,
; but uses the universal command ':' to send the programming instructions
; directly. Additionally the calibration byte is read by the ':' command.
; - Command 'b' is send by AVRProg1.37 but is not implemented. It was found that
; it is fatal for the programming mode to implement 'b' to return 'Y'.
; To simply leave it out (returns ? for unknow command) works perfectly.
;
; 25.07.2004 - To implement all improvements found on 24.07.2004 without skipping lots of
; of other code made it necessary to increase the boot loader size to 512words
; (=1kByte). Code adapted.
; - Command ':' enlarged to map r/F/N functionality
; - Tested, current status: Works well in AVRProg both for flash reading and writing
; and also in the Advance window the lock and fuse bits are display correctly.
; Only week point remaining to press "write" in advance window, that causes a
; loose of sync between host and bootloader. No harm is done to the target device.
; -> Version 1.2 released.
;
; 26.07.2004 - Monitoring of interface from host reveals the root cause of the sync problem when
; writing the the lock and fuse bits. AVRProg1.37 uses the "new universal command"
; which is "." + 4 data bytes. This command was not implemented. As changing the
; fuse bits is dangerous when the device is remote (one could lock himself out
; forever), the command is now implemented simply to ignore the inputs but correctly
; serve the interface to the host to avoid sync problems. Tested and works perfectly.
; -> Version 1.3 released
;
; 07.04.2005 - The code contained the "call" command, which is not supported by ATmega8. Obviously
; the AVR implementation is in a way that lets the software work anyhow. All "call"
; commands are now replaced by the supported "rcall" command now.
; - The definition of E2END was missing in the mega8 definition file of the old
; assembler, so it was included within this source file. Now the definition is
; available in the include file, so it is taken out of this file.
; - Intended Assembler Version is now:
; AVR macro assembler 2.0.28 (build 121 Jan 11 2005 10:28:51)
; - Configuration block implemented for easier user-defining of parameters like
; the number of wait cycles at power on or the LED pin.
; - Code and Comments clean up
; - Version 1.4 decleared which will be used for testing on hardware together with
; AVRProg Version 1.40.
;
; 09.04.2005 - Goodbye-Message implemented to inform user via UART that bootloader is left
; when command 'E' was sent
; - Tests on hardware successful
; -> Version 2.0 released
;
; 27.10.2005 - Minor bug corrected, LED pin was not correctly switched as output
;
; 21.04.2006 - Bug corrected, on command 'b' there was on 'N' returned to many
;
;
;
;
; Before or after programming a new ATmega8 with this Boot Loader the fuse bits must
; be set like this:
;
; The ATmega8 Fuse High bits must be programmed to configure the Boot size to 512 words
; and to move the Reset Vector to word address 0xE00. (BOOTSZ1=0, BOOTSZ0=1)
;
; I.e. set the check box for BOOTRST in AVR-Prog-Advanced and set the
; selector to 512 words, then press "write". It is important that this selected
; size of the bootrom fits to the .org command within this source code, otherwise
; the processor will not correctly start at the first line of this code after reset.
; (Settings can be checked now or later with "read").
;
; Optional:
;
; The Lock bits can be programmed to 0xEF to protect the Boot Flash Section from
; unintentional changes and to allow accessing the Application Flash Section.
;
; I.e. the setting for BLB0 and BLB1 in AVR-Prog-Advance:
;
; BLB0 (sets the protection for the application section) must be set to
; Mode 1 (no protection) to allow full access of LPM and SPM commands within
; the application section.
;
; BLB1 (sets the protection for the boot loader section) can be set to Mode 2
; (SPM cannot write to boot section) or can be left to Mode 1 (no protection).
;
; The Fuse bits must be programmed before programming the Lock bits.
;
;
; AVRProg Commands as defined by Atmel
;
; Host Writes Host Reads
; ID Data Data
; Enter Programming Mode 'P' 13d (implemented to ignore)
; Auto Increment Address 'a' dd (fully implemented)
; Set Address 'A' ah al 13d (fully implemented)
; Write Program Memory, Low Byte 'c' dd 13d (fully implemented)
; Write Program Memory, High Byte 'C' dd 13d (fully implemented)
; Issue Page Write 'm' 13d (fully implemented)
; Read Lock Bits 'r' dd (fully implemented)
; Read Program Memory 'R' 2*dd (fully implemented)
; Read EEPROM Memory 'd' dd (fully implemented)
; Write EEPROM Memory 'D' dd 13d (fully implemented)
; Chip Erase 'e' 13d (implemented, erases appl. area only)
; Write Lock Bits 'l' dd 13d (implemented to ignore)
; Read Fuse Bits 'F' dd (fully implemented)
; Read High Fuse Bits 'N' dd (fully implemented)
; Read Extended Fuse Bits 'Q' dd (not implemented)
; Leave Programming Mode 'L' 13d (implemented to ignore)
; Select Device Type 'T' dd 13d (implemented to ignore)
; Read Signature Bytes 's' 3*dd (fully implemented)
; Return Supported Device Codes 't' n*dd 00d (implemented, returns only Mega8)
; Return Software Identifier 'S' s[7] (fully implemented)
; Return Software Version 'V' dd dd (fully implemented)
; Return Hardware Version 'v' (fully implemented)
; Return Programmer Type 'p' dd (fully implemented)
; Set LED 'x' dd 13d (implemented to ignore)
; Clear LED 'y' dd 13d (implemented to ignore)
; Exit Bootloader 'E' {13d} (implemented 'E' is not confirmed)
; Check Block Support 'b' 'Y' 2*dd (implemented to return no)
; Start Block Flash Load 'B' 2*dd 'F' 13d (implemented)
; n*dd
; Start Block EEPROM Load 'B' 2*dd 'E' 13d (implemented)
; n*dd
; Start Block Flash Read 'g' 2*dd 'F' n*dd (implemented)
; Start Block EEPROM Read 'g' 2*dd 'E' n*dd (implemented)
; Universal Command (3 data bytes) ':' 3*dd dd 13d (implemented to ignore)
; New Universal Command (4 data bytes)'.' 4*dd dd 13d (implemented to ignore)
;
;------------------------------- Macros -------------------------------------------------
.macro RXdata
;sbi ddrb,dirpin;
;sbi portb,dirpin; Rx from Server
.endmacro;
.macro TXdata
;sbi ddrb,dirpin;
;cbi portb,dirpin; Tx to Server
.endmacro;
;------------------------------- definition and includes --------------------------------
;- pritaikyta plokstei KTE-V1
.INCLUDE "m64def.inc" ; Include Register/Bit Definitions for the mega8
.def dummy = r18 ; Use Reg. R18 for temporary stuff
.def pa_10ms = r19 ; used for selecting the pause time in steps of 10ms
.def uni_cmd1 = r20 ; Universal command ':' send three bytes. These
.def uni_cmd2 = r21 ; are stored for futher usage in r20, r21, r28
.def uni_cmd3 = r10
.equ VER_H = '2' ; bootloader software version higher number
.equ VER_L = '1' ; bootloader software version lower number
.equ VERH_H = '1' ; bootloader hardware version higher number
.equ VERH_L = '0' ; bootloader hardware version lower number
.equ DT = 0x45 ; Device Type = 0x76 (ATmega8)
.equ SB1 = 0x02 ; Signature byte 1
.equ SB2 = 0x96 ; Signature byte 2
.equ SB3 = 0x1e ; Signature byte 3
;.equ UBR = 35 ; Baud rate = 19.2 kbps with fCK = 11.059 MHz
.equ UBR = 5 ; Baud rate = 115.2 kbps with fCK = 11.059 MHz
.equ ESC = 27 ; Ascii 27 = Escape
.equ BLOCK_SIZE = 256 ; 256
; .equ E2END = 1FF ; This definition is missing in the m8def.inc file
; that came with the older Assembler. In "Assembler2"
; it is correct, so it is not required any more.
.equ MY_BOOTSTART = THIRDBOOTSTART ; here we define where the bootloader starts in the flash
;------------------------------ configuration parameters --------------------------------
.equ STUP_WT_CKL = 30 ; number of waiting loops (LED flashes) at power on
; before the main application starts automatically
.equ LED_PORT = PORTB ; Port B is used for the LED
.equ LED_DIR = DDRB ; Direction register for LED Port is DDRB
;.equ LED_PIN = 5; ; LED is connected to pin 1 of Port B
;.equ dirpin = 4; ; Direction;
.equ GLED_PIN = 7 ; ; LED is connected to pin 1 of Port B
.equ RLED_PIN = 6; ; Direction;
.equ ComSel1 = 5; ; LED is connected to pin 1 of Port B
.equ ComSel0 = 4; ; Direction;
.equ xGledpin = 2;
.equ xRledpin = 3;
.equ CTSpin = 1;
.equ RTSpin = 0;
.equ DTRpin = 5;
.equ DSRpin = 4;
.equ MDpin = 7;
.equ RSTpin = 6;
;------------------------------------- here we go ---------------------------------------
.org MY_BOOTSTART ; The code of this bootloader has to be located in
; the bootloader area at the end of the flash. With
; this .org it can be loaded into the device just
; like any other software (normal ATmega8 setting).
; ------------------------------- init stackpointer -------------------------------------
; lsr R27 ; word addr --> byte addr
; ror R26
ldi R24, low(RAMEND) ; SP = RAMEND
ldi R25, high(RAMEND)
out SPL, R24
out SPH, R25
sbi ddrc,MDpin;
sbi portc,MDpin;
sbi ddrc,RSTpin;
sbi portc,RSTpin;
cbi ddrc,DSRpin;
sbi portc,DSRpin;
cbi ddrc,DTRpin;
sbi portc,DTRpin;
cbi ddrc,RTSpin;
sbi portc,RTSpin;
cbi ddrc,CTSpin;
sbi portc,CTSpin;
sbi ddrb,ComSel0;
sbi ddrb,ComSel1;
; Com1
; cbi portb,ComSel0;
; cbi portb,ComSel1;
; sbi portc,1;
; Lan
cbi portb,ComSel0;
sbi portb,ComSel1;
cbi portc,CTSpin;
;
rcall pause
ldi R28,low(2*PAGESIZE)
ldi R29,high(2*PAGESIZE)
rcall pause;
cbi portc,RSTpin;
rcall pause
; ---------------------------------- init UART ------------------------------------------
clr R24;
; out UBRR0H,R24;
sts UBRR0H,R24;
ldi R24, UBR ; Baud rate = 19.2 bps
out UBRR0L, R24
ldi R24,(1<<RXEN0)|(1<<TXEN0) ; Enable receiver & transmitter, 8-bit mode
out UCSR0B,R24
ldi R24, (0<<UMSEL0 | 0<<USBS0 | 0<<UPM00 | 3<<UCSZ00)
; out UCSR0C,R24
sts UCSR0C,R24
; -------------------------- check for action on UART -----------------------------------
; After power-on, the processor starts with the bootloader section. Ususally the user
; want the application to start automatircally. Only in special cases, a software update
; is required. So if no ESC (ASCII(27)) is received within the defined number of wait
; cycles after power-on, the application starts.
sbi LED_DIR, GLED_PIN ; Switch PortB to output to drive an LED (active low)
ldi R17, STUP_WT_CKL ; Preset the number of LED-flashes (=number of loops)
RXdata; ; for the waiting periode
start_wait:
sbi LED_PORT, GLED_PIN ; switch off the LED
ldi pa_10ms, 250
rcall pause ; wait a moment
cbi LED_PORT, GLED_PIN ; switch on the LED
ldi pa_10ms, 250
rcall pause ; wait a moment
sbis UCSR0A,RXC0 ; check for incoming data (if RXC==1)
rjmp Lwait ; if not, continue at Lwait
;--- some character was received ---
in R16, UDR0 ; fetch received character and put it into R16
cpi R16, ESC ; if the received character was ESC
breq bootload_start ; start the bootloader main loop
rjmp start_wait ; LED stays switched on (all other incomming characters
; are simply ignored)
Lwait:
dec R17 ; decrement the loop counter
brne start_wait ; and leave loop if counter has reached zero
sbi LED_PORT, GLED_PIN ; switch off the LED
rjmp start_wait
;rjmp FLASHEND+1 ; Start the application program
; (flashend+1) = Address 0
;------------------- here starts the real bootloader functionality ----------------------
bootload_start:
;TXdata;
rcall pause;
; To indicate to the user that the attemt to start the bootloader functionality
; was successful, we send a message back on the UART.
/*
ldi ZL,low(uart_msg<<1) ; load the start-address of the startup message
ldi ZH,high(uart_msg<<1) ; into the Z-Register
str_output:
lpm R16,Z+ ; read one character of the string and increment
; string pointer (the Z-register)
cpi R16,0
breq L10
nop;
nop;
nop; ; exit the character output loop if character was '\0'
rcall uartSend
nop;
nop; ; send the read character via the UART
nop;
rjmp str_output ; go to start of loop for next character
*/
rjmp L10
;---------------------------------- 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 L10
;--------- Command 'E' leaves the bootloader mode and starts the application ------------
cpi R16, 'E' ; if(R16=='E') 'E' = Exit bootloader
brne L11
; ldi R16,13
; rcall uartSend
; rjmp leave_bootloader
; Send goodbye-message on UART
ldi ZL,low( 2*goodbye_msg) ; load the start-address of the startup message
ldi ZH,high(2*goodbye_msg) ; into the Z-Register
goodbye_output:
lpm R16,Z+ ; read one character of the string and increment
; string pointer (the Z-register)
tst R16
breq leave_bootloader ; exit the character output loop if character was '\0'
rcall uartSend ; send the read character via the UART
rjmp goodbye_output ; go to start of loop for next character
leave_bootloader:
sbi LED_PORT, GLED_PIN ; switch off the LED
rjmp 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, autoincrement is done
L11:
cpi R16, 'a' ; if(R16=='a') 'a' = Autoincrement?
brne L12
ldi R16,'Y' ; Yes, autoincrement is 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 from the host
L12:
cpi R16,'A' ; else if(R16=='A') write address
brne L14
rcall uartGet
mov R27,R16 ; address high byte is stored in R27
rcall uartGet
mov R26,R16 ; address low byte is stored in R26
lsl R26 ; address=address<<1
rol R27 ; convert from byte address to word address
rjmp L68 ; uartSend('\r') send CR and go up for next command
;--------- Command 'c' is write low byte to program memory ------------------------------
; the low byte is simply stored in a register, the actual writing to the flashes
; page-buffer is done later, after the high byte was received
L14:
cpi R16,'c' ; else if(R16=='c') write program memory, low byte
brne L16
rcall writeLowByte
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 to the flashes
; page buffer. When the page buffer is completely written, it can be transfered into
; the real flash by the "page write" command.
;
; If only SPMEN is written, the following SPM instruction will store the value 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 byte
brne L18
rcall writeHighByte
rjmp L68 ; uartSend('\r') send CR and go up for next command
;-------------------------- Command 'e' is chip erase -----------------------------------
; "chip erase" for the boot loader means to erase all flash pages othen than the
; boot loader sector itself
L18:
cpi R16,'e' ; else if(R16=='e') Chip erase
brne L28
; 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 with address 0
clr R27
rjmp L24 ; continue the loop 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 next SPM
; instruction within four clock cycles executes page erase. The page address
; is taken from the high part of the Z pointer.
rcall wait_for_spm ; make sure SPM is ready to accept a new task
movw ZL,R26 ; load the Z-pointer with the address of the
; page to be erased
ldi R24, (1<<PGERS) | (1<<SPMEN); simultaniously set PGERS and SPMEN in SPMCR
; out SPMCR,R24 ; to prepare for the page_erase
sts SPMCR,R24
spm ; Store program memory
nop
subi R26,low(-2*PAGESIZE) ; increment the address by the size of a page
sbci R27,high(-2*PAGESIZE)
; this is the check for end-criteria reached, i.e. has the address already
; reached the beginning of the boot-loader section
L24:
ldi R24,low( 2*MY_BOOTSTART) ; load R24, R25 with the address where the boot-loader
ldi R25,high(2*MY_BOOTSTART) ; section starts
cp R26,R24 ; do a word-compare to check if the address is still
cpc R27,R25 ; smaller than the address where the bootloader starts
brlo L20 ; if that is the case, go to the beginning of the erase loop
; ..... remember the number of flash-erases in the EEPROM .....
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
; ..........................................................
rcall wait_for_spm ; make sure SPM is ready to accept a new task
rcall enable_rww ; reenable the RWW 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 in R1 and R0
; is ignored. The page address must be written to PCPAGE. Other bits in the Z pointer will
; be ignored during this operation.
L28:
cpi R16,'m' ; else if(R16== 'm') Write page
brne L34
rcall writePage
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 CR
L34:
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') for type is 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 and increments R26
L38:
cpi R16,'R' ; else if(R16=='R') Read program memory
brne L40
rcall readFlashWord
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 L41
rcall writeEEPROM
rjmp L68 ; uartSend('\r') Confirm the command to host with CR
;--------- Command 'b' is question from host for block mode capability-------------------
; simple anser is 'N', no bootloader does not support blockmode
L41:
cpi R16, 'b' ; if(R16=='b') F = Blockmode?
brne L42
ldi R16,'Y' ; send 'N' for No block support
rcall uartSend ; uartSend(R16)
ldi R16,High(BLOCK_SIZE); send block size HIGH
rcall uartSend ; uartSend(R16)
ldi R16,Low(BLOCK_SIZE) ; send block size LOW
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 L43
rcall readEEPROM
rjmp L70 ; uartSend(R16)
;-------------------------- Command ':' is universal command ----------------------------
; Host sends 3 more bytes which must be used to determine the required action. AVRProg
; uses the ':' with parameters to do things that could simply be done by r/F/N.
; We have to map recognized parameters to the refering action.
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 r16 with zero, if parameters are not
; recognized, zero will be returned to host
;.....................................................................
cpi uni_cmd1, 0x58 ; check if 1st paramter is 0x58
brne cmd1_not_0x58
cpi uni_cmd2, 0x00 ; check if 2nd paramter 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 2nd paramter 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 1st paramter is 0x50
brne cmd1_not_0x50
cpi uni_cmd2, 0x00 ; check if 2nd paramter is 0x00
brne 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) send the 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 L46
clr 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 L48
ldi 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 L52
ldi ZL,3 ; Z-pointer = 0003 (-> readFuseAndLock will read high fuse)
;-------- for all previous commands F,r,N hear we rcall the readFuseAndLock --------------
; function that will read the bits that are indicated by the Z-register
L50:
rcall readFuseAndLock
rjmp L70 ; uartSend(R16)
;--------------------- Command 't' is Return supported devices code ---------------------
; obviously we return only the device code of the mega8 here
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 of Mega8
clr R16 ; command set of AVRProg requires the termination of
; the t-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, not for a bootloader.
; As theres commands come with an additional byte as parameter, with have to fetch that
; byte from the UART to avoid messing up the UART reading.
L54:
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()
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
ldi ZL,low(2*Soft_Id) ; load address of String into Z-Register
ldi ZH,high(2*Soft_Id)
L61:
lpm R16,Z+ ; read one character of the string and increment string pointer
tst R16
breq L72 ; exit the character output loop charcter was '\0'
rcall uartSend ; send the read character via the UART
rjmp L61 ; go to start of 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 bootloader software version higher number
rcall uartSend
ldi R16, VER_L ; send bootloader software version lower number
rjmp L70 ; uartSend and go 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 bootloader software version higher number
rcall uartSend
ldi R16, VERH_L ; send bootloader software version lower number
rjmp L70 ; uartSend and go 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
rcall uartSend
ldi R16,SB2 ; uartSend(SB2) Signature Byte 2
rcall uartSend
ldi R16,SB3 ; uartSend(SB3) Signature Byte 3
rjmp L70 ; uartSend and go up for next command
;--------------------- Command '.' is new universal command -----------------------------
; this command will be ignored, only the inteface will be handled correctly
L65:
cpi R16,'.' ; else if (R16=='.') New Universal Command
brne L73
;.............. 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 commands is done 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 loop starts again
L66:
ldi R16,'?' ; else uartSend('?')
rjmp L70 ; uartSend(R16)
;--------- successfully completed commands without return value can end up here ---------
; an CR is sent via the UART to confirm execution to host, then main loop starts again
L68:
ldi R16,13 ; uartSend('\r')
;------------ successfully completed commands with return value can end up here ---------
; the return value is sent via the UART to confirm execution to host
; then main loop starts again
L70:
rcall uartSend ; uartSend(R16)
L72:
rjmp L10 ; jump up to beginning of main loop
;-------------------------- Block Load --------------------------------------------
L73:
clt ; Begin Low Byte
cpi R16,'B' ; else if (R16=='B')
brne L74
rcall uartGet
mov R15,R16
rcall uartGet
mov R14,R16
rcall uartGet
mov R13,R16
cpi R16,'F'
breq L73_LOOP; jei 'F' palikti word addr
lsr R27 ; word addr --> byte addr
ror R26
L73_LOOP:
mov R16,R14
cpi R16,0
brne L73_NODEC
mov R16,R15
cpi R16,0
breq L73_EXT
dec R15
L73_NODEC:
dec R14
; rcall uartGet
; push R16
mov R16,R13
cpi R16,'F'
; pop R16 ; Write memory
brne L73_EEP
brts L73_HighByte
rcall writeLowByte
set
rjmp L73_FlW
L73_HighByte:
rcall writeHighByte
clt
rjmp L73_FlW
L73_EEP:rcall writeEEPROM
; ldi R16,13 ; uartSend('\r')
; rcall uartSend ; uartSend(R16)
rjmp L73_LOOP
L73_FlW:
sbiw R28,1
brne L73_LOOP_inc_adr
ldi R28,low(2*PAGESIZE)
ldi R29,high(2*PAGESIZE)
sbiw R26,2 ; address=address+2
rcall writePage
adiw R26,2 ; address=address+2
L73_LOOP_inc_adr:
; adiw R26,2 ; address=address+2
rjmp L73_LOOP
L73_EXT:
mov R16,R13
cpi R16,'F'
brne L68
rcall writePage
rjmp L68 ; Exit Block Load
;-------------------------- Block Read --------------------------------------------
L74:
cpi R16,'g' ; else if (R16=='g')
brne L66
rcall uartGet
mov R25,R16
rcall uartGet
mov R24,R16
rcall uartGet
mov R13,R16
cpi R16,'F'
breq L74_LOOPa; jei 'F' palikti word addr
lsr R27 ; word addr --> byte addr
ror R26
L74_LOOPa:
clr R16
mov R15,R16
mov R14,R16
L74_LOOP:
mov R16,R15
cp R16,R25 ; read block size HIGH
brne L74_SEND
mov R16,R14
cp R16,R24 ; read block size LOW
brne L74_SEND
rjmp L72 ; Exit Block Read
L74_SEND:
; push R24
mov R16,R13 ; Read memory
cpi R16,'F'
brne L74_EEP
rcall readFlashByte
rjmp L74_FlW
L74_EEP:
rcall readEEPROM
L74_FlW:
rcall uartSend
; pop R24
inc R14
brne L74_LOOP
inc R15
rjmp L74_LOOP
;-------------------------- end of main loop --------------------------------------------
;================= end of main program, only subroutines from here on ===================
;------------------ write Low Byte -------------
writeLowByte:
rcall uartGet ; read the byte to be written from host
mov R22,R16 ; store data low byte in R22
ret
;------------------ write High Byte -------------
writeHighByte:
rcall uartGet ; read the high byte from the host
mov R23,R16 ; store the data high byte in R23
movw ZL,R26 ; load the Z pointer with the current address
movw R0,R22 ; transfer the data word (data high and low byte)
; into registers R0 and R1
rcall wait_for_spm ; make sure SPM is ready to accept a new task
ldi R24, (1<<SPMEN) ; set SPMEN in SPMCR
; out SPMCR,R24 ; page load (fill temporary buffer)
sts SPMCR,R24 ; page load (fill temporary buffer)
spm ; Store program memory
adiw R27:R26,2 ; address=address+2
ret
;------------------ write Page -------------
writePage:
rcall wait_for_spm ; make sure SPM is ready to accept a new task
movw ZL,R26 ; load Z-pointer with address
ldi R24, (1<<PGWRT) | (1<<SPMEN); set PGWRT and SPMEN in SPMCR to prepare for Write page
; out SPMCR,R24
sts SPMCR,R24
spm ; Store program memory
nop
rcall enable_rww ; reenable the RWW section so it can be accessed again
ret
;------------------ read Flash Byte -------------
readFlashByte:
movw ZL,R26 ; load Z-pointer with address of memory to be read
; 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) write back MSB to host
nop
nop
nop
nop
movw R26,ZL ; increment the 'current' address += 2
; mov R16,R24 ; LSB stored in R16
ret ; required uartSend(R16)
;------------------ read Flash Word -------------
readFlashWord:
movw ZL,R26 ; load Z-pointer with address of memory to be read
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) write back MSB to host
movw R26,ZL ; increment the 'current' address += 2
mov R16,R24 ; LSB stored in R16
ret ; required uartSend(R16)
;------------------ write EEPROM -------------
writeEEPROM:
rcall uartGet ; fetch the data to write from the UART
out EEDR,R16 ; EEDR = uartGet()
ldi R17,6 ; write EEPROM
rcall EepromTalk
ret
;------------------ read EEPROM -------------
readEEPROM:
ldi R17,1 ; read EEPROM
rcall EepromTalk ; R16 = EEPROM data
ret ; required uartSend(R16)
;------------------ reads fuse or lock bits (depending on Z-Reg.) -------------
readFuseAndLock:
; An LPM instruction within three cycles after BLBSET and SPMEN are set 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 is ready to accept a new task
clr ZH ; Z pointer high byte = 0
ldi R24,(1<<BLBSET)|(1<<SPMEN) ; set BLBSET and SPMEN in SPMCR
; out SPMCR,R24 ; read fuse and lock
sts SPMCR,R24
lpm R16,Z ; read program memory
ret
;------------- does an read or write on the EEPROM (depending on R17) ---------
; if R17 == 6 then Write, if R17 == 1 then Read
EepromTalk:
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
;---------------- send one character via UART (parameter is r16) --------------
uartSend:
;txdata;
sbis UCSR0A,UDRE0 ; wait for empty transmit buffer (until UDRE==1)
rjmp uartSend
out UDR0,R16
nop; ; UDR = R16, start transmission
nop;
nop;
nop;
nop;
ret
;---------------- read one character from UART (returned in r16) --------------
uartGet:
;rxdata;
sbis UCSR0A,RXC0 ; wait for incoming data (until RXC==1)
rjmp uartGet
in R16,UDR0 ; return received data in R16
ret
;-------------------- wait for SPM to be ready for new tasks ------------------
; while( SPMCR_REG & (1<<SPMEN) )
wait_for_spm:
lds r16, SPMCR
; in r16, SPMCR ; read the content of SPMCR into register
andi r16, (1<<SPMEN) ; check if bit SPMEN is set
brne wait_for_spm ; and do more loops if bit not yet cleared
Wait_ee:
sbic EECR, EEWE ; check that no EEPROM write access is present
rjmp Wait_ee
ret
; ---------------------------- re-enable the RWW section ----------------------
; When programming (page erase or page write) to the RWW section, the RWW section
; is blocked for reading (the RWWSB will be set by hardware). To re-enable the RWW
; section, the user software must wait until the programming is completed (SPMEN will be
; cleared). Then, if the RWWSRE bit is written to one at the same time as SPMEN, the
; next SPM instruction within four clock cycles re-enables the RWW section.
; If this is not done, all addresses will read $FF even if they contain other values.
enable_rww:
rcall wait_for_spm ; make sure SPM is ready to accept a new task
ldi r16, (1<<RWWSRE) | (1<<SPMEN) ; set rwwsre and spmen in SPMCR to prepare
; out SPMCR, r16 ; for reenabling the rww section
sts SPMCR,R16
spm ; initiate the reenabling
ret
;---------------------------------- Pause -------------------------------------
; Delays the CPU the selected periode, parameter pa_10ms is in 10ms steps
pause:
;ret;
ldi dummy, 0b00000101 ; set prescaler to 1024
out TCCR0, dummy
ldi dummy, 184 ; preset the counter for 72 remaining
out TCNT0, dummy ; cycles till overflow
in dummy, TIFR ; reset the overflow flag
sbr dummy, (1<<TOV0)
out TIFR, dummy
pw: in dummy, TIFR ; check if overflow flag is set
sbrs dummy, TOV0
rjmp pw ; if not, wait more
;--- do this 10ms as often as requested in parameter pa_10ms
dec pa_10ms ; decrement the counter
brne pause ; and do the loop again if not zero yet
ret
;-------------------------- data for identifier string ----------------------------------
Soft_Id:
.db "AVR_M64", 0
/*
;--------------- data for message on UART when bootloader starts ------------------------
uart_msg:
.db "+--------------------------------------------------+",10,13
.db "| Bootloader for ATmega8, Version ", VER_H, '.',VER_L, " by DL5NEG |",10,13
.db "| Use AVRProg to download new software. |",10,13
.db "| Press E to leave the bootloader and to start the |",10,13
.db "| application software from the flash memory. |",10,13
.db "+--------------------------------------------------+ ",10,13,10,13,0
*/
;------------- data for message on UART when leaving the bootloader ---------------------
goodbye_msg:
; .db "Thanks for using DL5NEGs bootloader. ",10,13,10,13,0
; .db 13,"Thanks for using DL5NEGs bootloader.",10,13,10,13,0
.db 13,13,13,0 |
|
|
|
|
 |
 |
|
 |
|
 |
Google paieška forume |
|
 |
Naujos temos forume |
|
 |
FS25 Tractors
Farming Simulator 25 Mods,
FS25 Maps,
FS25 Trucks |
 |
ETS2 Mods
ETS2 Trucks,
ETS2 Bus,
Euro Truck Simulator 2 Mods
|
 |
FS22 Tractors
Farming Simulator 22 Mods,
FS22 Maps,
FS25 Mods |
 |
VAT calculator
VAT number check,
What is VAT,
How much is VAT |
 |
Dantų protezavimas
All on 4 implantai,
Endodontija mikroskopu,
Dantų implantacija |
 |
FS25 Mods
FS25 Maps,
FS25 Cheats,
FS25 Install Mods |
 |
FS25 Mods
Farming Simulator 25 Mods,
FS25 Maps |
 |
ATS Trailers
American Truck Simulator Mods,
ATS Trucks,
ATS Maps |
 |
Fun football drills
Football Training Equipment,
Defending drills football,
Kids football training kit |
|

|
 |