From e9af37fef0cf72981b61645cd21c025bc86c9cbe Mon Sep 17 00:00:00 2001 From: WestfW Date: Thu, 20 Sep 2018 01:19:15 -0700 Subject: [PATCH] Bumb to Version 8.0: add DO_SPM code This is not quite the same as MCUdude's code, but it has the same calling conventions. This version doesn't use do_spm from the bootloading code itself, since that recently went to some effort to use more of the standardized boot.h calls. That means that this code is a bit bigger than it really needs to be. (Still small enough to fit within the 512byte limit, given recent compilers.) Sadly, the compiler options that barely fit SUPPORT_EEPROM in 512bytes are incompatible with DO_SPM, so you have to choose. Since do_spm was supported by the MCUDude platforms, and not 512byte version of optiboot has ever supported EEPROM, the do_spm code wins, for backward compatibility! Also standardize the "makeall" shell script names, and update the release script. --- optiboot/bootloaders/optiboot/Makefile | 12 +- optiboot/bootloaders/optiboot/makeall | 32 - .../bootloaders/optiboot/makeall.arduino.sh | 32 + .../bootloaders/optiboot/makeall.mcudude.sh | 2 +- optiboot/bootloaders/optiboot/makeall.tiny.sh | 44 + optiboot/bootloaders/optiboot/optiboot.c | 78 +- .../optiboot/optiboot_atmega1280.hex | 95 +- .../optiboot/optiboot_atmega1280.lst | 809 ++++++++++-------- .../optiboot/optiboot_atmega328.hex | 60 +- .../optiboot/optiboot_atmega328.lst | 608 +++++++------ .../optiboot/optiboot_atmega644p.hex | 89 +- .../optiboot/optiboot_atmega644p.lst | 764 +++++++++-------- .../optiboot/optiboot_diecimila.lst | 584 ------------- .../bootloaders/optiboot/optiboot_lilypad.hex | 31 - .../bootloaders/optiboot/optiboot_lilypad.lst | 584 ------------- .../bootloaders/optiboot/optiboot_luminet.hex | 38 - .../bootloaders/optiboot/optiboot_luminet.lst | 634 -------------- optiboot/examples/test_dospm/test_dospm.ino | 238 ++++++ optiboot/release.sh | 18 +- 19 files changed, 1734 insertions(+), 3018 deletions(-) delete mode 100755 optiboot/bootloaders/optiboot/makeall create mode 100755 optiboot/bootloaders/optiboot/makeall.arduino.sh create mode 100755 optiboot/bootloaders/optiboot/makeall.tiny.sh delete mode 100644 optiboot/bootloaders/optiboot/optiboot_diecimila.lst delete mode 100644 optiboot/bootloaders/optiboot/optiboot_lilypad.hex delete mode 100644 optiboot/bootloaders/optiboot/optiboot_lilypad.lst delete mode 100644 optiboot/bootloaders/optiboot/optiboot_luminet.hex delete mode 100644 optiboot/bootloaders/optiboot/optiboot_luminet.lst create mode 100644 optiboot/examples/test_dospm/test_dospm.ino diff --git a/optiboot/bootloaders/optiboot/Makefile b/optiboot/bootloaders/optiboot/Makefile index def9c4c..d842df1 100644 --- a/optiboot/bootloaders/optiboot/Makefile +++ b/optiboot/bootloaders/optiboot/Makefile @@ -236,9 +236,17 @@ SS_CMD = -DSINGLESPEED=1 endif endif +HELPTEXT += "Option NO_APP_SPM=1 - disallow application call of do_spm\n" +ifdef NO_APP_SPM +ifneq ($(NO_APP_SPM),0) +APPSPM_CMD = -DAPP_NOSPM=1 +endif +endif + + COMMON_OPTIONS = $(BAUD_RATE_CMD) $(LED_START_FLASHES_CMD) $(BIGBOOT_CMD) COMMON_OPTIONS += $(SOFT_UART_CMD) $(LED_DATA_FLASH_CMD) $(LED_CMD) $(SS_CMD) -COMMON_OPTIONS += $(SUPPORT_EEPROM_CMD) $(LED_START_ON_CMD) +COMMON_OPTIONS += $(SUPPORT_EEPROM_CMD) $(LED_START_ON_CMD) $(APPSPM_CMD) COMMON_OPTIONS += $(VERSION_CMD) #UART is handled separately and only passed for devices with more than one. @@ -380,7 +388,7 @@ atmega168_isp: HFUSE ?= DD atmega168_isp: LFUSE ?= F7 ifndef BIGBOOT # 512 byte boot -atmega168_isp: EFUSE ?= 04 +atmega168_isp: EFUSE ?= FC else # 1024byte boot atmega168_isp: EFUSE ?= FA diff --git a/optiboot/bootloaders/optiboot/makeall b/optiboot/bootloaders/optiboot/makeall deleted file mode 100755 index 9288d48..0000000 --- a/optiboot/bootloaders/optiboot/makeall +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -make clean -# -# buildable platforms of somewhat questionable support level -make lilypad -make pro8 -make pro16 -make pro20 -make atmega328_pro8 -make sanguino -make mega1280 -make luminet -make diecimila -make bobuino -make wildfirev2 -make atmega1284 -make atmega32 -make atmega88 -make atmega168p - -# -# Atmel development board targets -make xplained168pb -make xplained328p -make xplained328pb - -# -# The "big three" standard bootloaders. -# These need to be built AFTER the platforms, or they'll get renamed -make atmega8 -make atmega168 -make atmega328 diff --git a/optiboot/bootloaders/optiboot/makeall.arduino.sh b/optiboot/bootloaders/optiboot/makeall.arduino.sh new file mode 100755 index 0000000..66d53f5 --- /dev/null +++ b/optiboot/bootloaders/optiboot/makeall.arduino.sh @@ -0,0 +1,32 @@ +#!/bin/bash +make clean +# +# buildable platforms of somewhat questionable support level +make lilypad $* +make pro8 $* +make pro16 $* +make pro20 $* +make atmega328_pro8 $* +make sanguino $* +make mega1280 $* +make luminet $* +make diecimila $* +make bobuino $* +make wildfirev2 $* +make atmega1284 $* +make atmega32 $* +make atmega88 $* +make atmega168p $* + +# +# Atmel development board targets +make xplained168pb $* +make xplained328p $* +make xplained328pb $* + +# +# The "big three" standard bootloaders. +# These need to be built AFTER the platforms, or they'll get renamed +make atmega8 $* +make atmega168 $* +make atmega328 $* diff --git a/optiboot/bootloaders/optiboot/makeall.mcudude.sh b/optiboot/bootloaders/optiboot/makeall.mcudude.sh index 759f55e..ce2dde8 100755 --- a/optiboot/bootloaders/optiboot/makeall.mcudude.sh +++ b/optiboot/bootloaders/optiboot/makeall.mcudude.sh @@ -193,7 +193,7 @@ do # Print out current build info echo -e " ${mcu_and_params[$i]} AVR_FREQ=${clock_and_baud[$j]} BAUD_RATE=${clock_and_baud[$j+1]} ${mcu_and_params[$i+1]} \x1B[0m" # Build - make ${mcu_and_params[$i]} AVR_FREQ=${clock_and_baud[$j]} BAUD_RATE=${clock_and_baud[$j+1]} ${mcu_and_params[$i+1]} + make ${mcu_and_params[$i]} AVR_FREQ=${clock_and_baud[$j]} BAUD_RATE=${clock_and_baud[$j+1]} ${mcu_and_params[$i+1]} $* done done diff --git a/optiboot/bootloaders/optiboot/makeall.tiny.sh b/optiboot/bootloaders/optiboot/makeall.tiny.sh new file mode 100755 index 0000000..94cf955 --- /dev/null +++ b/optiboot/bootloaders/optiboot/makeall.tiny.sh @@ -0,0 +1,44 @@ +make attiny1634at12 $* +make attiny1634at16 $* +make attiny1634at8 $* +make attiny1634at8_5v $* +make attiny1634at737 $* +make attiny1634at921 $* +make attiny1634at110 $* +make attiny1634at147 $* + +make attiny1634at12ser1 $* +make attiny1634at16ser1 $* +make attiny1634at8ser1 $* +make attiny1634at8_5vser1 $* +make attiny1634at737ser1 $* +make attiny1634at921ser1 $* +make attiny1634at110ser1 $* +make attiny1634at147ser1 $* + + +make attiny841 $* +make attiny841at184 $* +make attiny841at147 $* +make attiny841at110 $* +make attiny841at921 $* +make attiny841at737 $* +make attiny841at20 $* +make attiny841at16 $* +make attiny841at12 $* +make attiny841at8 $* +make attiny841at8_5v $* + +make attiny841at184ser1 $* +make attiny841at147ser1 $* +make attiny841at110ser1 $* +make attiny841at921ser1 $* +make attiny841at737ser1 $* +make attiny841at20ser1 $* +make attiny841at16ser1 $* +make attiny841at12ser1 $* +make attiny841at8ser1 $* + +make attiny841at20noLED $* +make attiny841at16noLED $* +make attiny841at8noLED $* diff --git a/optiboot/bootloaders/optiboot/optiboot.c b/optiboot/bootloaders/optiboot/optiboot.c index 842f8a7..2f2775f 100644 --- a/optiboot/bootloaders/optiboot/optiboot.c +++ b/optiboot/bootloaders/optiboot/optiboot.c @@ -152,6 +152,7 @@ /* handling, did MORE Makefile mods. EEPROM support now */ /* fits in 512 bytes, if you turn off LED Blinking. */ /* Various bigboot and virboot targets were fixed. */ +/* Version 8.0 adds the do_spm code callable from Apps. */ /* */ /* It would be good if versions implemented outside the */ /* official repository used an out-of-seqeunce version */ @@ -164,6 +165,10 @@ /**********************************************************/ /* Edit History: */ /* */ +/* Sep 2018 */ +/* 8.0 WestfW (and MCUDude) */ +/* Include do_spm routine callable from the app */ +/* at BOOTSTART+2, controllable with compile option */ /* July 2018 */ /* 7.0 WestfW (with much input from Others) */ /* Fix MCUSR treatement as per much discussion, */ @@ -246,7 +251,7 @@ /* 4.1 WestfW: put version number in binary. */ /**********************************************************/ -#define OPTIBOOT_MAJVER 7 +#define OPTIBOOT_MAJVER 8 #define OPTIBOOT_MINVER 0 /* @@ -396,6 +401,7 @@ typedef uint8_t pagelen_t; * supress some compile-time options we want.) */ +void pre_main(void) __attribute__ ((naked)) __attribute__ ((section (".init8"))); int main(void) __attribute__ ((OS_main)) __attribute__ ((section (".init9"))) __attribute__((used)); void __attribute__((noinline)) __attribute__((leaf)) putch(char); @@ -487,6 +493,23 @@ static addr16_t buff = {(uint8_t *)(RAMSTART)}; #endif // VIRTUAL_BOOT_PARTITION +/* everything that needs to run VERY early */ +void pre_main(void) { + // Allow convenient way of calling do_spm function - jump table, + // so entry to this function will always be here, indepedent of compilation, + // features etc + asm volatile ( + " rjmp 1f\n" +#ifndef APP_NOSPM + " rjmp do_spm\n" +#else + " ret\n" // if do_spm isn't include, return without doing anything +#endif + "1:\n" + ); +} + + /* main program starts here */ int main(void) { uint8_t ch; @@ -1158,6 +1181,59 @@ static inline void read_mem(uint8_t memtype, addr16_t address, pagelen_t length) } +#ifndef APP_NOSPM + +/* + * Separate function for doing spm stuff + * It's needed for application to do SPM, as SPM instruction works only + * from bootloader. + * + * How it works: + * - do SPM + * - wait for SPM to complete + * - if chip have RWW/NRWW sections it does additionaly: + * - if command is WRITE or ERASE, AND data=0 then reenable RWW section + * + * In short: + * If you play erase-fill-write, just set data to 0 in ERASE and WRITE + * If you are brave, you have your code just below bootloader in NRWW section + * you could do fill-erase-write sequence with data!=0 in ERASE and + * data=0 in WRITE + */ +static void do_spm(uint16_t address, uint8_t command, uint16_t data) __attribute__ ((used)); +static void do_spm(uint16_t address, uint8_t command, uint16_t data) { + // Do spm stuff + asm volatile ( + " movw r0, %3\n" + " __wr_spmcsr %0, %1\n" + " spm\n" + " clr r1\n" + : + : "i" (_SFR_MEM_ADDR(__SPM_REG)), + "r" ((uint8_t)command), + "z" ((uint16_t)address), + "r" ((uint16_t)data) + : "r0" + ); + + // wait for spm to complete + // it doesn't have much sense for __BOOT_PAGE_FILL, + // but it doesn't hurt and saves some bytes on 'if' + boot_spm_busy_wait(); +#if defined(RWWSRE) + // this 'if' condition should be: (command == __BOOT_PAGE_WRITE || command == __BOOT_PAGE_ERASE)... + // but it's tweaked a little assuming that in every command we are interested in here, there + // must be also SELFPRGEN set. If we skip checking this bit, we save here 4B + if ((command & (_BV(PGWRT)|_BV(PGERS))) && (data == 0) ) { + // Reenable read access to flash + __boot_rww_enable_short(); + } +#endif +} +#endif + + + #ifdef BIGBOOT /* * Optiboot is designed to fit in 512 bytes, with a minimum feature set. diff --git a/optiboot/bootloaders/optiboot/optiboot_atmega1280.hex b/optiboot/bootloaders/optiboot/optiboot_atmega1280.hex index 91f5c8e..4eea54a 100644 --- a/optiboot/bootloaders/optiboot/optiboot_atmega1280.hex +++ b/optiboot/bootloaders/optiboot/optiboot_atmega1280.hex @@ -1,44 +1,57 @@ :020000021000EC -:10FC0000112484B7882349F0982F9A70923029F0F4 -:10FC100081FF02C097EF94BF10D185E080938100EF -:10FC200082E08093C00088E18093C10086E08093E9 -:10FC3000C20080E18093C4008EE0EAD0279A86E07B -:10FC400020E33CEF91E0309385002093840096BB45 -:10FC5000B09BFECF1F9AA8954091C00047FD02C0FF -:10FC6000815089F7FF24F39455E0E52E61E1D62E0B -:10FC7000C3D08134C1F4C0D0C82FD0D0C23809F469 -:10FC80003AC0C13869F487E00CC0843709F482C0F7 -:10FC9000853709F0A2C0C2D08EE1A7D087E9A5D0F0 -:10FCA00083E0A3D09FC0823411F484E103C0853483 -:10FCB00019F485E0BBD096C0853579F49DD0082F26 -:10FCC0009BD0182F87FF03C08BB7816002C08BB712 -:10FCD0008E7F8BBF000F111F84C0863581F48CD0BE -:10FCE0008D3459F489D0CBB787D0C170880FC82B19 -:10FCF000CBBF81E09BD080E0D4CF83E0FBCF8436C4 -:10FD000009F0C3CF79D0C82FD0E0DC2FCC2774D036 -:10FD1000C82B72D0C82E5E01812C32E0932E6CD09D -:10FD2000F40181934F01F1E0AF1AB108C1F776D029 -:10FD300085E4C81212C0DE5F4801A12C92E0B92E02 -:10FD4000AC16BD0609F44EC0F50161915F01C40116 -:10FD500082D0FFEF8F1A9F0AF3CF83E0F80187BFAD -:10FD6000E89507B600FCFDCFA0E0B2E0F8018D9168 -:10FD70009D910C01F7BEE8951124229732962097A9 -:10FD8000B1F7F801E7BEE89507B600FCFDCFD7BE96 -:10FD9000E89528C031D0C82FD0E0DC2FCC272CD05C -:10FDA0005E01A82A29D0982E39D0E801F5E49F12E7 -:10FDB0000BC0CE0148D019D081E0A81AB108219615 -:10FDC000A114B104B1F70EC0FE018791EF010DD06F -:10FDD000E1E0AE1AB108C1F705C0813511F488E041 -:10FDE00017D01CD080E101D043CF9091C00095FF87 -:10FDF000FCCF8093C60008958091C00087FFFCCFA0 -:10FE00008091C00084FD01C0A8958091C60008952E -:10FE1000E0E6F0E098E1908380830895EDDF8032A2 -:10FE200019F088E0F5DFFFCF84E1DFCFCF93C82F53 -:10FE3000E3DFC150E9F7CF91F1CF282E80E0E8DF72 -:10FE4000E0E0FF270994F999FECF92BD81BDF89AB1 -:10FE5000992780B50895262FF999FECF1FBA92BD34 -:10FE600081BD20BD0FB6F894FA9AF99A0FBE01969B -:02FE70000895F3 -:02FFFE000007FA +:10FC000012E0A0E0B2E0ECEAFEEF01E00BBF02C0C0 +:10FC100007900D92AC39B107D9F701C021C1112469 +:10FC200084B7882369F0982F9A70923049F081FF49 +:10FC300002C097EF94BF282E80E0FDD00C94000006 +:10FC400085E08093810082E08093C00088E180930A +:10FC5000C10086E08093C20080E18093C4008EE002 +:10FC6000EAD0279A86E020E33CEF91E030938500CC +:10FC70002093840096BBB09BFECF1F9AA89540911D +:10FC8000C00047FD02C0815089F7FF24F39455E07E +:10FC9000E52E61E1D62EC3D08134C1F4C0D0C82F87 +:10FCA000D0D0C23809F43AC0C13869F488E00CC039 +:10FCB000843709F482C0853709F0A2C0C2D08EE132 +:10FCC000A7D087E9A5D083E0A3D09FC0823411F4E8 +:10FCD00084E103C0853419F485E0BBD096C0853536 +:10FCE00079F49DD0082F9BD0182F87FF03C08BB7C6 +:10FCF000816002C08BB78E7F8BBF000F111F84C045 +:10FD0000863581F48CD08D3459F489D0CBB787D027 +:10FD1000C170880FC82BCBBF81E09BD080E0D4CFCF +:10FD200083E0FBCF843609F0C3CF79D0C82FD0E071 +:10FD3000DC2FCC2774D0C82B72D0C82E5E01812C4A +:10FD400032E0932E6CD0F40181934F01F1E0AF1AB1 +:10FD5000B108C1F776D085E4C81212C0DE5F480151 +:10FD6000A12C92E0B92EAC16BD0609F44EC0F501E7 +:10FD700061915F01C4018CD0FFEF8F1A9F0AF3CF0E +:10FD800083E0F80187BFE89507B600FCFDCFA0E04F +:10FD9000B2E0F8018D919D910C01F7BEE895112418 +:10FDA000229732962097B1F7F801E7BEE89507B69B +:10FDB00000FCFDCFD7BEE89528C031D0C82FD0E0D9 +:10FDC000DC2FCC272CD05E01A82A29D0982E39D040 +:10FDD000E801F5E49F120BC0CE0152D019D081E0AA +:10FDE000A81AB1082196A114B104B1F70EC0FE0102 +:10FDF0008791EF010DD0E1E0AE1AB108C1F705C05F +:10FE0000813511F488E017D01CD080E101D043CFB8 +:10FE10009091C00095FFFCCF8093C600089580911B +:10FE2000C00087FFFCCF8091C00084FD01C0A89571 +:10FE30008091C6000895E0E6F0E098E19083808329 +:10FE40000895EDDF803219F088E0F5DFFFCF84E11F +:10FE5000DFCFCF93C82FE3DFC150E9F7CF91F1CFC8 +:10FE6000FC010A0167BFE895112407B600FCFDCF2D +:10FE7000667029F0452B19F481E187BFE895089554 +:10FE8000F999FECF92BD81BDF89A992780B5089562 +:10FE9000262FF999FECF1FBA92BD81BD20BD0FB6A6 +:0CFEA000F894FA9AF99A0FBE01960895A2 +:10FEAC0056657273696F6E3D382E30004F50544951 +:10FEBC00424F4F545F435553544F4D5645523D306E +:10FECC00004465766963653D61746D6567613132C7 +:10FEDC00383000465F4350553D313630303030308D +:10FEEC00304C00424947424F4F543D3100427569F6 +:10FEFC006C743A53657020323020323031383A30DD +:10FF0C00313A31383A343300554152543D30004285 +:10FF1C004155445F524154453D313135323030000A +:10FF2C004C45443D4237004C45445F535441525478 +:0CFF3C005F464C41534845533D330000E4 +:02FFFE000008F9 :040000031000FC00ED :00000001FF diff --git a/optiboot/bootloaders/optiboot/optiboot_atmega1280.lst b/optiboot/bootloaders/optiboot/optiboot_atmega1280.lst index 954a541..69cccc9 100644 --- a/optiboot/bootloaders/optiboot/optiboot_atmega1280.lst +++ b/optiboot/bootloaders/optiboot/optiboot_atmega1280.lst @@ -3,724 +3,795 @@ optiboot_atmega1280.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .data 00000000 00800200 0001fe72 00000306 2**0 + 0 .data 0000009c 00800200 0001feac 00000340 2**0 CONTENTS, ALLOC, LOAD, DATA - 1 .text 00000272 0001fc00 0001fc00 00000094 2**1 + 1 .text 000002ac 0001fc00 0001fc00 00000094 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 2 .version 00000002 0001fffe 0001fffe 00000306 2**0 + 2 .version 00000002 0001fffe 0001fffe 000003dc 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA - 3 .comment 0000002f 00000000 00000000 00000308 2**0 + 3 .comment 0000002f 00000000 00000000 000003de 2**0 CONTENTS, READONLY - 4 .debug_aranges 00000028 00000000 00000000 00000337 2**0 + 4 .debug_aranges 00000030 00000000 00000000 0000040d 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_info 00000632 00000000 00000000 0000035f 2**0 + 5 .debug_info 000007b5 00000000 00000000 0000043d 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_abbrev 00000286 00000000 00000000 00000991 2**0 + 6 .debug_abbrev 000002c5 00000000 00000000 00000bf2 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_line 00000385 00000000 00000000 00000c17 2**0 + 7 .debug_line 000003c0 00000000 00000000 00000eb7 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_frame 0000008c 00000000 00000000 00000f9c 2**2 + 8 .debug_frame 0000009c 00000000 00000000 00001278 2**2 CONTENTS, READONLY, DEBUGGING - 9 .debug_str 0000021e 00000000 00000000 00001028 2**0 + 9 .debug_str 0000028c 00000000 00000000 00001314 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_loc 00000421 00000000 00000000 00001246 2**0 + 10 .debug_loc 00000449 00000000 00000000 000015a0 2**0 CONTENTS, READONLY, DEBUGGING - 11 .debug_ranges 00000078 00000000 00000000 00001667 2**0 + 11 .debug_ranges 00000080 00000000 00000000 000019e9 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: -0001fc00
: +0001fc00 <__ctors_end>: + 1fc00: 12 e0 ldi r17, 0x02 ; 2 + 1fc02: a0 e0 ldi r26, 0x00 ; 0 + 1fc04: b2 e0 ldi r27, 0x02 ; 2 + 1fc06: ec ea ldi r30, 0xAC ; 172 + 1fc08: fe ef ldi r31, 0xFE ; 254 + 1fc0a: 01 e0 ldi r16, 0x01 ; 1 + 1fc0c: 0b bf out 0x3b, r16 ; 59 + 1fc0e: 02 c0 rjmp .+4 ; 0x1fc14 <__ctors_end+0x14> + 1fc10: 07 90 elpm r0, Z+ + 1fc12: 0d 92 st X+, r0 + 1fc14: ac 39 cpi r26, 0x9C ; 156 + 1fc16: b1 07 cpc r27, r17 + 1fc18: d9 f7 brne .-10 ; 0x1fc10 <__ctors_end+0x10> + +0001fc1a : +/* everything that needs to run VERY early */ +void pre_main(void) { + // Allow convenient way of calling do_spm function - jump table, + // so entry to this function will always be here, indepedent of compilation, + // features etc + asm volatile ( + 1fc1a: 01 c0 rjmp .+2 ; 0x1fc1e
+ 1fc1c: 21 c1 rjmp .+578 ; 0x1fe60 + +0001fc1e
: // SP points to RAMEND // r1 contains zero // // If not, uncomment the following instructions: // cli(); asm volatile ("clr __zero_reg__"); - 1fc00: 11 24 eor r1, r1 - * - * Code by MarkG55 - * see discusion in https://github.com/Optiboot/optiboot/issues/97 - */ -#if !defined(__AVR_ATmega16__) - ch = MCUSR; - 1fc02: 84 b7 in r24, 0x34 ; 52 -#else + 1fc1e: 11 24 eor r1, r1 +#if defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) || \ + defined(__AVR_ATmega16__) || defined(__AVR_ATmega162__) || \ + defined (__AVR_ATmega128__) ch = MCUCSR; +#else + ch = MCUSR; + 1fc20: 84 b7 in r24, 0x34 ; 52 #endif // Skip all logic and run bootloader if MCUSR is cleared (application request) if (ch != 0) { - 1fc04: 88 23 and r24, r24 - 1fc06: 49 f0 breq .+18 ; 0x1fc1a + 1fc22: 88 23 and r24, r24 + 1fc24: 69 f0 breq .+26 ; 0x1fc40 * 2. we clear WDRF if it's set with EXTRF to avoid loops * One problematic scenario: broken application code sets watchdog timer * without clearing MCUSR before and triggers it quickly. But it's * recoverable by power-on with pushed reset button. */ if ((ch & (_BV(WDRF) | _BV(EXTRF))) != _BV(EXTRF)) { - 1fc08: 98 2f mov r25, r24 - 1fc0a: 9a 70 andi r25, 0x0A ; 10 - 1fc0c: 92 30 cpi r25, 0x02 ; 2 - 1fc0e: 29 f0 breq .+10 ; 0x1fc1a + 1fc26: 98 2f mov r25, r24 + 1fc28: 9a 70 andi r25, 0x0A ; 10 + 1fc2a: 92 30 cpi r25, 0x02 ; 2 + 1fc2c: 49 f0 breq .+18 ; 0x1fc40 if (ch & _BV(EXTRF)) { - 1fc10: 81 ff sbrs r24, 1 - 1fc12: 02 c0 rjmp .+4 ; 0x1fc18 - * prevent entering bootloader. - * '&' operation is skipped to spare few bytes as bits in MCUSR - * can only be cleared. - */ -#if !defined(__AVR_ATmega16__) - MCUSR = ~(_BV(WDRF)); - 1fc14: 97 ef ldi r25, 0xF7 ; 247 - 1fc16: 94 bf out 0x34, r25 ; 52 + 1fc2e: 81 ff sbrs r24, 1 + 1fc30: 02 c0 rjmp .+4 ; 0x1fc36 + defined(__AVR_ATmega16__) || defined(__AVR_ATmega162__) || \ + defined(__AVR_ATmega128__) + // Fix missing definitions in avr-libc + MCUCSR = ~(_BV(WDRF)); #else - MCUCSR = ~(_BV(WDRF)); -#endif - } - appStart(ch); - 1fc18: 10 d1 rcall .+544 ; 0x1fe3a + MCUSR = ~(_BV(WDRF)); + 1fc32: 97 ef ldi r25, 0xF7 ; 247 + 1fc34: 94 bf out 0x34, r25 ; 52 + /* + * save the reset flags in the designated register + * This can be saved in a main program by putting code in .init0 (which + * executes before normal c init code) to save R2 to a global variable. + */ + __asm__ __volatile__ ("mov r2, %0\n" :: "r" (ch)); + 1fc36: 28 2e mov r2, r24 + + // switch off watchdog + watchdogConfig(WATCHDOG_OFF); + 1fc38: 80 e0 ldi r24, 0x00 ; 0 + 1fc3a: fd d0 rcall .+506 ; 0x1fe36 + // Note that appstart_vec is defined so that this works with either + // real or virtual boot partitions. + __asm__ __volatile__ ( + 1fc3c: 0c 94 00 00 jmp 0 ; 0x0 <__tmp_reg__> } } #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - 1fc1a: 85 e0 ldi r24, 0x05 ; 5 - 1fc1c: 80 93 81 00 sts 0x0081, r24 ; 0x800081 <__TEXT_REGION_LENGTH__+0x7e0081> - UCSRA = _BV(U2X); //Double speed mode USART - UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx - UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 - UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); -#else + 1fc40: 85 e0 ldi r24, 0x05 ; 5 + 1fc42: 80 93 81 00 sts 0x0081, r24 ; 0x800081 <__TEXT_REGION_LENGTH__+0x7e0081> + LINBTR = (1 << LDISR) | (8 << LBT0); + LINCR = _BV(LENA) | _BV(LCMD2) | _BV(LCMD1) | _BV(LCMD0); + LINDAT=0; + #else + #ifndef SINGLESPEED UART_SRA = _BV(U2X0); //Double speed mode USART0 - 1fc20: 82 e0 ldi r24, 0x02 ; 2 - 1fc22: 80 93 c0 00 sts 0x00C0, r24 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + 1fc46: 82 e0 ldi r24, 0x02 ; 2 + 1fc48: 80 93 c0 00 sts 0x00C0, r24 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + #endif UART_SRB = _BV(RXEN0) | _BV(TXEN0); - 1fc26: 88 e1 ldi r24, 0x18 ; 24 - 1fc28: 80 93 c1 00 sts 0x00C1, r24 ; 0x8000c1 <__TEXT_REGION_LENGTH__+0x7e00c1> + 1fc4c: 88 e1 ldi r24, 0x18 ; 24 + 1fc4e: 80 93 c1 00 sts 0x00C1, r24 ; 0x8000c1 <__TEXT_REGION_LENGTH__+0x7e00c1> UART_SRC = _BV(UCSZ00) | _BV(UCSZ01); - 1fc2c: 86 e0 ldi r24, 0x06 ; 6 - 1fc2e: 80 93 c2 00 sts 0x00C2, r24 ; 0x8000c2 <__TEXT_REGION_LENGTH__+0x7e00c2> - UART_SRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 1fc32: 80 e1 ldi r24, 0x10 ; 16 - 1fc34: 80 93 c4 00 sts 0x00C4, r24 ; 0x8000c4 <__TEXT_REGION_LENGTH__+0x7e00c4> -#endif -#endif + 1fc52: 86 e0 ldi r24, 0x06 ; 6 + 1fc54: 80 93 c2 00 sts 0x00C2, r24 ; 0x8000c2 <__TEXT_REGION_LENGTH__+0x7e00c2> + UART_SRL = (uint8_t)BAUD_SETTING; + 1fc58: 80 e1 ldi r24, 0x10 ; 16 + 1fc5a: 80 93 c4 00 sts 0x00C4, r24 ; 0x8000c4 <__TEXT_REGION_LENGTH__+0x7e00c4> + #endif // LIN_UART + #endif // mega8/etc +#endif // soft_uart // Set up watchdog to trigger after 1s watchdogConfig(WATCHDOG_1S); - 1fc38: 8e e0 ldi r24, 0x0E ; 14 - 1fc3a: ea d0 rcall .+468 ; 0x1fe10 + 1fc5e: 8e e0 ldi r24, 0x0E ; 14 + 1fc60: ea d0 rcall .+468 ; 0x1fe36 #if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH) || defined(LED_START_ON) /* Set LED pin as output */ LED_DDR |= _BV(LED); - 1fc3c: 27 9a sbi 0x04, 7 ; 4 - 1fc3e: 86 e0 ldi r24, 0x06 ; 6 + 1fc62: 27 9a sbi 0x04, 7 ; 4 + 1fc64: 86 e0 ldi r24, 0x06 ; 6 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 1fc40: 20 e3 ldi r18, 0x30 ; 48 - 1fc42: 3c ef ldi r19, 0xFC ; 252 + 1fc66: 20 e3 ldi r18, 0x30 ; 48 + 1fc68: 3c ef ldi r19, 0xFC ; 252 TIFR1 = _BV(TOV1); - 1fc44: 91 e0 ldi r25, 0x01 ; 1 + 1fc6a: 91 e0 ldi r25, 0x01 ; 1 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 1fc46: 30 93 85 00 sts 0x0085, r19 ; 0x800085 <__TEXT_REGION_LENGTH__+0x7e0085> - 1fc4a: 20 93 84 00 sts 0x0084, r18 ; 0x800084 <__TEXT_REGION_LENGTH__+0x7e0084> + 1fc6c: 30 93 85 00 sts 0x0085, r19 ; 0x800085 <__TEXT_REGION_LENGTH__+0x7e0085> + 1fc70: 20 93 84 00 sts 0x0084, r18 ; 0x800084 <__TEXT_REGION_LENGTH__+0x7e0084> TIFR1 = _BV(TOV1); - 1fc4e: 96 bb out 0x16, r25 ; 22 + 1fc74: 96 bb out 0x16, r25 ; 22 while(!(TIFR1 & _BV(TOV1))); - 1fc50: b0 9b sbis 0x16, 0 ; 22 - 1fc52: fe cf rjmp .-4 ; 0x1fc50 -#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega16__) + 1fc76: b0 9b sbis 0x16, 0 ; 22 + 1fc78: fe cf rjmp .-4 ; 0x1fc76 + defined(__AVR_ATmega8535__) || defined(__AVR_ATmega16__) || \ + defined(__AVR_ATmega162__) || defined(__AVR_ATmega32__) || \ + defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) LED_PORT ^= _BV(LED); #else LED_PIN |= _BV(LED); - 1fc54: 1f 9a sbi 0x03, 7 ; 3 + 1fc7a: 1f 9a sbi 0x03, 7 ; 3 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 1fc56: a8 95 wdr - * While in theory, the STK500 initial commands would be buffered + 1fc7c: a8 95 wdr * by the UART hardware, avrdude sends several attempts in rather * quick succession, some of which will be lost and cause us to * get out of sync. So if we see any data; stop blinking. */ +#ifndef LIN_UART if (UART_SRA & _BV(RXC0)) - 1fc58: 40 91 c0 00 lds r20, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - 1fc5c: 47 fd sbrc r20, 7 - 1fc5e: 02 c0 rjmp .+4 ; 0x1fc64 - 1fc60: 81 50 subi r24, 0x01 ; 1 + 1fc7e: 40 91 c0 00 lds r20, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + 1fc82: 47 fd sbrc r20, 7 + 1fc84: 02 c0 rjmp .+4 ; 0x1fc8a + 1fc86: 81 50 subi r24, 0x01 ; 1 #else // This doesn't seem to work? // if ((UART_PIN & (1< + 1fc88: 89 f7 brne .-30 ; 0x1fc6c /* * Copy data from the buffer into the flash write buffer. */ do { __boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++)); - 1fc64: ff 24 eor r15, r15 - 1fc66: f3 94 inc r15 + 1fc8a: ff 24 eor r15, r15 + 1fc8c: f3 94 inc r15 } while (len -= 2); /* * Actually Write the buffer to flash (and wait for it to finish.) */ __boot_page_write_short(address.word); - 1fc68: 55 e0 ldi r21, 0x05 ; 5 - 1fc6a: e5 2e mov r14, r21 + 1fc8e: 55 e0 ldi r21, 0x05 ; 5 + 1fc90: e5 2e mov r14, r21 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash __boot_rww_enable_short(); - 1fc6c: 61 e1 ldi r22, 0x11 ; 17 + 1fc92: 61 e1 ldi r22, 0x11 ; 17 #endif /* Forever loop: exits by causing WDT reset */ for (;;) { /* get character from UART */ ch = getch(); - 1fc6e: d6 2e mov r13, r22 + 1fc94: d6 2e mov r13, r22 if(ch == STK_GET_PARAMETER) { - 1fc70: c3 d0 rcall .+390 ; 0x1fdf8 + 1fc96: c3 d0 rcall .+390 ; 0x1fe1e unsigned char which = getch(); - 1fc72: 81 34 cpi r24, 0x41 ; 65 - 1fc74: c1 f4 brne .+48 ; 0x1fca6 - 1fc76: c0 d0 rcall .+384 ; 0x1fdf8 + 1fc98: 81 34 cpi r24, 0x41 ; 65 + 1fc9a: c1 f4 brne .+48 ; 0x1fccc + 1fc9c: c0 d0 rcall .+384 ; 0x1fe1e verifySpace(); - 1fc78: c8 2f mov r28, r24 - 1fc7a: d0 d0 rcall .+416 ; 0x1fe1c + 1fc9e: c8 2f mov r28, r24 + 1fca0: d0 d0 rcall .+416 ; 0x1fe42 /* * Send optiboot version as "SW version" * Note that the references to memory are optimized away. */ if (which == STK_SW_MINOR) { - 1fc7c: c2 38 cpi r28, 0x82 ; 130 - 1fc7e: 09 f4 brne .+2 ; 0x1fc82 - 1fc80: 3a c0 rjmp .+116 ; 0x1fcf6 + 1fca2: c2 38 cpi r28, 0x82 ; 130 + 1fca4: 09 f4 brne .+2 ; 0x1fca8 + 1fca6: 3a c0 rjmp .+116 ; 0x1fd1c putch(optiboot_version & 0xFF); } else if (which == STK_SW_MAJOR) { - 1fc82: c1 38 cpi r28, 0x81 ; 129 - 1fc84: 69 f4 brne .+26 ; 0x1fca0 + 1fca8: c1 38 cpi r28, 0x81 ; 129 + 1fcaa: 69 f4 brne .+26 ; 0x1fcc6 putch(optiboot_version >> 8); - 1fc86: 87 e0 ldi r24, 0x07 ; 7 - 1fc88: 0c c0 rjmp .+24 ; 0x1fca2 + 1fcac: 88 e0 ldi r24, 0x08 ; 8 + 1fcae: 0c c0 rjmp .+24 ; 0x1fcc8 writebuffer(desttype, buff, address, savelength); } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 1fc8a: 84 37 cpi r24, 0x74 ; 116 - 1fc8c: 09 f4 brne .+2 ; 0x1fc90 + 1fcb0: 84 37 cpi r24, 0x74 ; 116 + 1fcb2: 09 f4 brne .+2 ; 0x1fcb6 read_mem(desttype, address, length); } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 1fc8e: 82 c0 rjmp .+260 ; 0x1fd94 - 1fc90: 85 37 cpi r24, 0x75 ; 117 + 1fcb4: 82 c0 rjmp .+260 ; 0x1fdba + 1fcb6: 85 37 cpi r24, 0x75 ; 117 // READ SIGN - return what Avrdude wants to hear verifySpace(); - 1fc92: 09 f0 breq .+2 ; 0x1fc96 + 1fcb8: 09 f0 breq .+2 ; 0x1fcbc putch(SIGNATURE_0); - 1fc94: a2 c0 rjmp .+324 ; 0x1fdda - 1fc96: c2 d0 rcall .+388 ; 0x1fe1c - 1fc98: 8e e1 ldi r24, 0x1E ; 30 + 1fcba: a2 c0 rjmp .+324 ; 0x1fe00 + 1fcbc: c2 d0 rcall .+388 ; 0x1fe42 + 1fcbe: 8e e1 ldi r24, 0x1E ; 30 putch(SIGNATURE_1); - 1fc9a: a7 d0 rcall .+334 ; 0x1fdea - 1fc9c: 87 e9 ldi r24, 0x97 ; 151 - 1fc9e: a5 d0 rcall .+330 ; 0x1fdea + 1fcc0: a7 d0 rcall .+334 ; 0x1fe10 + 1fcc2: 87 e9 ldi r24, 0x97 ; 151 + 1fcc4: a5 d0 rcall .+330 ; 0x1fe10 } else { /* * GET PARAMETER returns a generic 0x03 reply for * other parameters - enough to keep Avrdude happy */ putch(0x03); - 1fca0: 83 e0 ldi r24, 0x03 ; 3 - 1fca2: a3 d0 rcall .+326 ; 0x1fdea - 1fca4: 9f c0 rjmp .+318 ; 0x1fde4 + 1fcc6: 83 e0 ldi r24, 0x03 ; 3 + 1fcc8: a3 d0 rcall .+326 ; 0x1fe10 + 1fcca: 9f c0 rjmp .+318 ; 0x1fe0a } } else if(ch == STK_SET_DEVICE) { - 1fca6: 82 34 cpi r24, 0x42 ; 66 - 1fca8: 11 f4 brne .+4 ; 0x1fcae + 1fccc: 82 34 cpi r24, 0x42 ; 66 + 1fcce: 11 f4 brne .+4 ; 0x1fcd4 // SET DEVICE is ignored getNch(20); - 1fcaa: 84 e1 ldi r24, 0x14 ; 20 + 1fcd0: 84 e1 ldi r24, 0x14 ; 20 } else if(ch == STK_SET_DEVICE_EXT) { - 1fcac: 03 c0 rjmp .+6 ; 0x1fcb4 + 1fcd2: 03 c0 rjmp .+6 ; 0x1fcda // SET DEVICE EXT is ignored getNch(5); - 1fcae: 85 34 cpi r24, 0x45 ; 69 - 1fcb0: 19 f4 brne .+6 ; 0x1fcb8 - 1fcb2: 85 e0 ldi r24, 0x05 ; 5 - 1fcb4: bb d0 rcall .+374 ; 0x1fe2c + 1fcd4: 85 34 cpi r24, 0x45 ; 69 + 1fcd6: 19 f4 brne .+6 ; 0x1fcde + 1fcd8: 85 e0 ldi r24, 0x05 ; 5 + 1fcda: bb d0 rcall .+374 ; 0x1fe52 } else if(ch == STK_LOAD_ADDRESS) { - 1fcb6: 96 c0 rjmp .+300 ; 0x1fde4 - 1fcb8: 85 35 cpi r24, 0x55 ; 85 + 1fcdc: 96 c0 rjmp .+300 ; 0x1fe0a + 1fcde: 85 35 cpi r24, 0x55 ; 85 // LOAD ADDRESS address.bytes[0] = getch(); - 1fcba: 79 f4 brne .+30 ; 0x1fcda - 1fcbc: 9d d0 rcall .+314 ; 0x1fdf8 - 1fcbe: 08 2f mov r16, r24 + 1fce0: 79 f4 brne .+30 ; 0x1fd00 + 1fce2: 9d d0 rcall .+314 ; 0x1fe1e + 1fce4: 08 2f mov r16, r24 address.bytes[1] = getch(); - 1fcc0: 9b d0 rcall .+310 ; 0x1fdf8 - 1fcc2: 18 2f mov r17, r24 - 1fcc4: 87 ff sbrs r24, 7 + 1fce6: 9b d0 rcall .+310 ; 0x1fe1e + 1fce8: 18 2f mov r17, r24 + 1fcea: 87 ff sbrs r24, 7 #ifdef RAMPZ // Transfer top bit to LSB in RAMPZ if (address.bytes[1] & 0x80) { - 1fcc6: 03 c0 rjmp .+6 ; 0x1fcce + 1fcec: 03 c0 rjmp .+6 ; 0x1fcf4 RAMPZ |= 0x01; - 1fcc8: 8b b7 in r24, 0x3b ; 59 - 1fcca: 81 60 ori r24, 0x01 ; 1 + 1fcee: 8b b7 in r24, 0x3b ; 59 + 1fcf0: 81 60 ori r24, 0x01 ; 1 } else { RAMPZ &= 0xFE; - 1fccc: 02 c0 rjmp .+4 ; 0x1fcd2 - 1fcce: 8b b7 in r24, 0x3b ; 59 + 1fcf2: 02 c0 rjmp .+4 ; 0x1fcf8 + 1fcf4: 8b b7 in r24, 0x3b ; 59 } #endif address.word *= 2; // Convert from word address to byte address - 1fcd0: 8e 7f andi r24, 0xFE ; 254 - 1fcd2: 8b bf out 0x3b, r24 ; 59 - 1fcd4: 00 0f add r16, r16 + 1fcf6: 8e 7f andi r24, 0xFE ; 254 + 1fcf8: 8b bf out 0x3b, r24 ; 59 + 1fcfa: 00 0f add r16, r16 verifySpace(); } else if(ch == STK_UNIVERSAL) { - 1fcd6: 11 1f adc r17, r17 + 1fcfc: 11 1f adc r17, r17 #ifdef RAMPZ // LOAD_EXTENDED_ADDRESS is needed in STK_UNIVERSAL for addressing more than 128kB if ( AVR_OP_LOAD_EXT_ADDR == getch() ) { - 1fcd8: 84 c0 rjmp .+264 ; 0x1fde2 - 1fcda: 86 35 cpi r24, 0x56 ; 86 - 1fcdc: 81 f4 brne .+32 ; 0x1fcfe - 1fcde: 8c d0 rcall .+280 ; 0x1fdf8 + 1fcfe: 84 c0 rjmp .+264 ; 0x1fe08 + 1fd00: 86 35 cpi r24, 0x56 ; 86 + 1fd02: 81 f4 brne .+32 ; 0x1fd24 + 1fd04: 8c d0 rcall .+280 ; 0x1fe1e // get address getch(); // get '0' - 1fce0: 8d 34 cpi r24, 0x4D ; 77 - 1fce2: 59 f4 brne .+22 ; 0x1fcfa + 1fd06: 8d 34 cpi r24, 0x4D ; 77 + 1fd08: 59 f4 brne .+22 ; 0x1fd20 RAMPZ = (RAMPZ & 0x01) | ((getch() << 1) & 0xff); // get address and put it in RAMPZ - 1fce4: 89 d0 rcall .+274 ; 0x1fdf8 - 1fce6: cb b7 in r28, 0x3b ; 59 - 1fce8: 87 d0 rcall .+270 ; 0x1fdf8 - 1fcea: c1 70 andi r28, 0x01 ; 1 - 1fcec: 88 0f add r24, r24 - 1fcee: c8 2b or r28, r24 + 1fd0a: 89 d0 rcall .+274 ; 0x1fe1e + 1fd0c: cb b7 in r28, 0x3b ; 59 + 1fd0e: 87 d0 rcall .+270 ; 0x1fe1e + 1fd10: c1 70 andi r28, 0x01 ; 1 + 1fd12: 88 0f add r24, r24 + 1fd14: c8 2b or r28, r24 getNch(1); // get last '0' - 1fcf0: cb bf out 0x3b, r28 ; 59 - 1fcf2: 81 e0 ldi r24, 0x01 ; 1 + 1fd16: cb bf out 0x3b, r28 ; 59 + 1fd18: 81 e0 ldi r24, 0x01 ; 1 // response putch(0x00); - 1fcf4: 9b d0 rcall .+310 ; 0x1fe2c - 1fcf6: 80 e0 ldi r24, 0x00 ; 0 + 1fd1a: 9b d0 rcall .+310 ; 0x1fe52 + 1fd1c: 80 e0 ldi r24, 0x00 ; 0 } else { // everything else is ignored getNch(3); - 1fcf8: d4 cf rjmp .-88 ; 0x1fca2 - 1fcfa: 83 e0 ldi r24, 0x03 ; 3 + 1fd1e: d4 cf rjmp .-88 ; 0x1fcc8 + 1fd20: 83 e0 ldi r24, 0x03 ; 3 getNch(4); putch(0x00); #endif } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 1fcfc: fb cf rjmp .-10 ; 0x1fcf4 - 1fcfe: 84 36 cpi r24, 0x64 ; 100 + 1fd22: fb cf rjmp .-10 ; 0x1fd1a + 1fd24: 84 36 cpi r24, 0x64 ; 100 // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t desttype; uint8_t *bufPtr; pagelen_t savelength; GETLENGTH(length); - 1fd00: 09 f0 breq .+2 ; 0x1fd04 - 1fd02: c3 cf rjmp .-122 ; 0x1fc8a - 1fd04: 79 d0 rcall .+242 ; 0x1fdf8 - 1fd06: c8 2f mov r28, r24 - 1fd08: d0 e0 ldi r29, 0x00 ; 0 - 1fd0a: dc 2f mov r29, r28 - 1fd0c: cc 27 eor r28, r28 - 1fd0e: 74 d0 rcall .+232 ; 0x1fdf8 + 1fd26: 09 f0 breq .+2 ; 0x1fd2a + 1fd28: c3 cf rjmp .-122 ; 0x1fcb0 + 1fd2a: 79 d0 rcall .+242 ; 0x1fe1e + 1fd2c: c8 2f mov r28, r24 + 1fd2e: d0 e0 ldi r29, 0x00 ; 0 + 1fd30: dc 2f mov r29, r28 + 1fd32: cc 27 eor r28, r28 + 1fd34: 74 d0 rcall .+232 ; 0x1fe1e savelength = length; desttype = getch(); - 1fd10: c8 2b or r28, r24 - 1fd12: 72 d0 rcall .+228 ; 0x1fdf8 - 1fd14: c8 2e mov r12, r24 + 1fd36: c8 2b or r28, r24 + 1fd38: 72 d0 rcall .+228 ; 0x1fe1e + 1fd3a: c8 2e mov r12, r24 // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t desttype; uint8_t *bufPtr; pagelen_t savelength; GETLENGTH(length); - 1fd16: 5e 01 movw r10, r28 + 1fd3c: 5e 01 movw r10, r28 savelength = length; desttype = getch(); - 1fd18: 81 2c mov r8, r1 - 1fd1a: 32 e0 ldi r19, 0x02 ; 2 - 1fd1c: 93 2e mov r9, r19 + 1fd3e: 81 2c mov r8, r1 + 1fd40: 32 e0 ldi r19, 0x02 ; 2 + 1fd42: 93 2e mov r9, r19 // read a page worth of contents bufPtr = buff.bptr; do *bufPtr++ = getch(); - 1fd1e: 6c d0 rcall .+216 ; 0x1fdf8 - 1fd20: f4 01 movw r30, r8 - 1fd22: 81 93 st Z+, r24 - 1fd24: 4f 01 movw r8, r30 - 1fd26: f1 e0 ldi r31, 0x01 ; 1 + 1fd44: 6c d0 rcall .+216 ; 0x1fe1e + 1fd46: f4 01 movw r30, r8 + 1fd48: 81 93 st Z+, r24 + 1fd4a: 4f 01 movw r8, r30 + 1fd4c: f1 e0 ldi r31, 0x01 ; 1 while (--length); - 1fd28: af 1a sub r10, r31 - 1fd2a: b1 08 sbc r11, r1 - 1fd2c: c1 f7 brne .-16 ; 0x1fd1e + 1fd4e: af 1a sub r10, r31 + 1fd50: b1 08 sbc r11, r1 + 1fd52: c1 f7 brne .-16 ; 0x1fd44 // Read command terminator, start reply verifySpace(); - 1fd2e: 76 d0 rcall .+236 ; 0x1fe1c - 1fd30: 85 e4 ldi r24, 0x45 ; 69 + 1fd54: 76 d0 rcall .+236 ; 0x1fe42 + 1fd56: 85 e4 ldi r24, 0x45 ; 69 * void writebuffer(memtype, buffer, address, length) */ static inline void writebuffer(int8_t memtype, addr16_t mybuff, addr16_t address, pagelen_t len) { switch (memtype) { - 1fd32: c8 12 cpse r12, r24 - 1fd34: 12 c0 rjmp .+36 ; 0x1fd5a - 1fd36: de 5f subi r29, 0xFE ; 254 - 1fd38: 48 01 movw r8, r16 - 1fd3a: a1 2c mov r10, r1 - 1fd3c: 92 e0 ldi r25, 0x02 ; 2 - 1fd3e: b9 2e mov r11, r25 - 1fd40: ac 16 cp r10, r28 + 1fd58: c8 12 cpse r12, r24 + 1fd5a: 12 c0 rjmp .+36 ; 0x1fd80 + 1fd5c: de 5f subi r29, 0xFE ; 254 + 1fd5e: 48 01 movw r8, r16 + 1fd60: a1 2c mov r10, r1 + 1fd62: 92 e0 ldi r25, 0x02 ; 2 + 1fd64: b9 2e mov r11, r25 + 1fd66: ac 16 cp r10, r28 case 'E': // EEPROM #if defined(SUPPORT_EEPROM) || defined(BIGBOOT) while(len--) { - 1fd42: bd 06 cpc r11, r29 - 1fd44: 09 f4 brne .+2 ; 0x1fd48 - 1fd46: 4e c0 rjmp .+156 ; 0x1fde4 - 1fd48: f5 01 movw r30, r10 + 1fd68: bd 06 cpc r11, r29 + 1fd6a: 09 f4 brne .+2 ; 0x1fd6e + 1fd6c: 4e c0 rjmp .+156 ; 0x1fe0a + 1fd6e: f5 01 movw r30, r10 eeprom_write_byte((address.bptr++), *(mybuff.bptr++)); - 1fd4a: 61 91 ld r22, Z+ - 1fd4c: 5f 01 movw r10, r30 - 1fd4e: c4 01 movw r24, r8 - 1fd50: 82 d0 rcall .+260 ; 0x1fe56 - 1fd52: ff ef ldi r31, 0xFF ; 255 - 1fd54: 8f 1a sub r8, r31 - 1fd56: 9f 0a sbc r9, r31 - 1fd58: f3 cf rjmp .-26 ; 0x1fd40 - 1fd5a: 83 e0 ldi r24, 0x03 ; 3 - 1fd5c: f8 01 movw r30, r16 - * Start the page erase and wait for it to finish. There - * used to be code to do this while receiving the data over - * the serial link, but the performance improvement was slight, + 1fd70: 61 91 ld r22, Z+ + 1fd72: 5f 01 movw r10, r30 + 1fd74: c4 01 movw r24, r8 + 1fd76: 8c d0 rcall .+280 ; 0x1fe90 + 1fd78: ff ef ldi r31, 0xFF ; 255 + 1fd7a: 8f 1a sub r8, r31 + 1fd7c: 9f 0a sbc r9, r31 + 1fd7e: f3 cf rjmp .-26 ; 0x1fd66 + 1fd80: 83 e0 ldi r24, 0x03 ; 3 + 1fd82: f8 01 movw r30, r16 * and we needed the space back. */ +#ifdef FOURPAGEERASE + if ((address.bytes[0] & ((SPM_PAGESIZE<<2)-1))==0) { +#endif __boot_page_erase_short(address.word); - 1fd5e: 87 bf out 0x37, r24 ; 55 - 1fd60: e8 95 spm - 1fd62: 07 b6 in r0, 0x37 ; 55 - 1fd64: 00 fc sbrc r0, 0 + 1fd84: 87 bf out 0x37, r24 ; 55 + 1fd86: e8 95 spm + 1fd88: 07 b6 in r0, 0x37 ; 55 + 1fd8a: 00 fc sbrc r0, 0 boot_spm_busy_wait(); - 1fd66: fd cf rjmp .-6 ; 0x1fd62 - 1fd68: a0 e0 ldi r26, 0x00 ; 0 - 1fd6a: b2 e0 ldi r27, 0x02 ; 2 - 1fd6c: f8 01 movw r30, r16 - 1fd6e: 8d 91 ld r24, X+ + 1fd8c: fd cf rjmp .-6 ; 0x1fd88 + 1fd8e: a0 e0 ldi r26, 0x00 ; 0 + 1fd90: b2 e0 ldi r27, 0x02 ; 2 + 1fd92: f8 01 movw r30, r16 + 1fd94: 8d 91 ld r24, X+ /* * Copy data from the buffer into the flash write buffer. */ do { __boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++)); - 1fd70: 9d 91 ld r25, X+ - 1fd72: 0c 01 movw r0, r24 - 1fd74: f7 be out 0x37, r15 ; 55 - 1fd76: e8 95 spm - 1fd78: 11 24 eor r1, r1 + 1fd96: 9d 91 ld r25, X+ + 1fd98: 0c 01 movw r0, r24 + 1fd9a: f7 be out 0x37, r15 ; 55 + 1fd9c: e8 95 spm + 1fd9e: 11 24 eor r1, r1 addrPtr += 2; } while (len -= 2); - 1fd7a: 22 97 sbiw r28, 0x02 ; 2 - 1fd7c: 32 96 adiw r30, 0x02 ; 2 - 1fd7e: 20 97 sbiw r28, 0x00 ; 0 + 1fda0: 22 97 sbiw r28, 0x02 ; 2 + 1fda2: 32 96 adiw r30, 0x02 ; 2 + 1fda4: 20 97 sbiw r28, 0x00 ; 0 /* * Actually Write the buffer to flash (and wait for it to finish.) */ __boot_page_write_short(address.word); - 1fd80: b1 f7 brne .-20 ; 0x1fd6e - 1fd82: f8 01 movw r30, r16 - 1fd84: e7 be out 0x37, r14 ; 55 + 1fda6: b1 f7 brne .-20 ; 0x1fd94 + 1fda8: f8 01 movw r30, r16 + 1fdaa: e7 be out 0x37, r14 ; 55 boot_spm_busy_wait(); - 1fd86: e8 95 spm + 1fdac: e8 95 spm #if defined(RWWSRE) // Reenable read access to flash __boot_rww_enable_short(); - 1fd88: 07 b6 in r0, 0x37 ; 55 - 1fd8a: 00 fc sbrc r0, 0 - 1fd8c: fd cf rjmp .-6 ; 0x1fd88 + 1fdae: 07 b6 in r0, 0x37 ; 55 + 1fdb0: 00 fc sbrc r0, 0 + 1fdb2: fd cf rjmp .-6 ; 0x1fdae } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { uint8_t desttype; GETLENGTH(length); - 1fd8e: d7 be out 0x37, r13 ; 55 - 1fd90: e8 95 spm - 1fd92: 28 c0 rjmp .+80 ; 0x1fde4 - 1fd94: 31 d0 rcall .+98 ; 0x1fdf8 - 1fd96: c8 2f mov r28, r24 - 1fd98: d0 e0 ldi r29, 0x00 ; 0 - 1fd9a: dc 2f mov r29, r28 - 1fd9c: cc 27 eor r28, r28 - 1fd9e: 2c d0 rcall .+88 ; 0x1fdf8 + 1fdb4: d7 be out 0x37, r13 ; 55 + 1fdb6: e8 95 spm + 1fdb8: 28 c0 rjmp .+80 ; 0x1fe0a + 1fdba: 31 d0 rcall .+98 ; 0x1fe1e + 1fdbc: c8 2f mov r28, r24 + 1fdbe: d0 e0 ldi r29, 0x00 ; 0 + 1fdc0: dc 2f mov r29, r28 + 1fdc2: cc 27 eor r28, r28 + 1fdc4: 2c d0 rcall .+88 ; 0x1fe1e desttype = getch(); - 1fda0: 5e 01 movw r10, r28 - 1fda2: a8 2a or r10, r24 - 1fda4: 29 d0 rcall .+82 ; 0x1fdf8 + 1fdc6: 5e 01 movw r10, r28 + 1fdc8: a8 2a or r10, r24 + 1fdca: 29 d0 rcall .+82 ; 0x1fe1e verifySpace(); - 1fda6: 98 2e mov r9, r24 - 1fda8: 39 d0 rcall .+114 ; 0x1fe1c - 1fdaa: e8 01 movw r28, r16 + 1fdcc: 98 2e mov r9, r24 + 1fdce: 39 d0 rcall .+114 ; 0x1fe42 + 1fdd0: e8 01 movw r28, r16 static inline void read_mem(uint8_t memtype, addr16_t address, pagelen_t length) { uint8_t ch; switch (memtype) { - 1fdac: f5 e4 ldi r31, 0x45 ; 69 + 1fdd2: f5 e4 ldi r31, 0x45 ; 69 #if defined(SUPPORT_EEPROM) || defined(BIGBOOT) case 'E': // EEPROM do { putch(eeprom_read_byte((address.bptr++))); - 1fdae: 9f 12 cpse r9, r31 - 1fdb0: 0b c0 rjmp .+22 ; 0x1fdc8 - 1fdb2: ce 01 movw r24, r28 - 1fdb4: 48 d0 rcall .+144 ; 0x1fe46 + 1fdd4: 9f 12 cpse r9, r31 + 1fdd6: 0b c0 rjmp .+22 ; 0x1fdee + 1fdd8: ce 01 movw r24, r28 + 1fdda: 52 d0 rcall .+164 ; 0x1fe80 } while (--length); - 1fdb6: 19 d0 rcall .+50 ; 0x1fdea - 1fdb8: 81 e0 ldi r24, 0x01 ; 1 - 1fdba: a8 1a sub r10, r24 - 1fdbc: b1 08 sbc r11, r1 - 1fdbe: 21 96 adiw r28, 0x01 ; 1 - 1fdc0: a1 14 cp r10, r1 - 1fdc2: b1 04 cpc r11, r1 - 1fdc4: b1 f7 brne .-20 ; 0x1fdb2 + 1fddc: 19 d0 rcall .+50 ; 0x1fe10 + 1fdde: 81 e0 ldi r24, 0x01 ; 1 + 1fde0: a8 1a sub r10, r24 + 1fde2: b1 08 sbc r11, r1 + 1fde4: 21 96 adiw r28, 0x01 ; 1 + 1fde6: a1 14 cp r10, r1 + 1fde8: b1 04 cpc r11, r1 + 1fdea: b1 f7 brne .-20 ; 0x1fdd8 // Since RAMPZ should already be set, we need to use EPLM directly. // Also, we can use the autoincrement version of lpm to update "address" // do putch(pgm_read_byte_near(address++)); // while (--length); // read a Flash and increment the address (may increment RAMPZ) __asm__ ("elpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address)); - 1fdc6: 0e c0 rjmp .+28 ; 0x1fde4 - 1fdc8: fe 01 movw r30, r28 - 1fdca: 87 91 elpm r24, Z+ + 1fdec: 0e c0 rjmp .+28 ; 0x1fe0a + 1fdee: fe 01 movw r30, r28 + 1fdf0: 87 91 elpm r24, Z+ #else // read a Flash byte and increment the address __asm__ ("lpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address)); #endif putch(ch); - 1fdcc: ef 01 movw r28, r30 - 1fdce: 0d d0 rcall .+26 ; 0x1fdea + 1fdf2: ef 01 movw r28, r30 + 1fdf4: 0d d0 rcall .+26 ; 0x1fe10 } while (--length); - 1fdd0: e1 e0 ldi r30, 0x01 ; 1 - 1fdd2: ae 1a sub r10, r30 - 1fdd4: b1 08 sbc r11, r1 - 1fdd6: c1 f7 brne .-16 ; 0x1fdc8 - 1fdd8: 05 c0 rjmp .+10 ; 0x1fde4 + 1fdf6: e1 e0 ldi r30, 0x01 ; 1 + 1fdf8: ae 1a sub r10, r30 + 1fdfa: b1 08 sbc r11, r1 + 1fdfc: c1 f7 brne .-16 ; 0x1fdee + 1fdfe: 05 c0 rjmp .+10 ; 0x1fe0a verifySpace(); putch(SIGNATURE_0); putch(SIGNATURE_1); putch(SIGNATURE_2); } else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */ - 1fdda: 81 35 cpi r24, 0x51 ; 81 - 1fddc: 11 f4 brne .+4 ; 0x1fde2 + 1fe00: 81 35 cpi r24, 0x51 ; 81 + 1fe02: 11 f4 brne .+4 ; 0x1fe08 // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 1fdde: 88 e0 ldi r24, 0x08 ; 8 - 1fde0: 17 d0 rcall .+46 ; 0x1fe10 - 1fde2: 1c d0 rcall .+56 ; 0x1fe1c + 1fe04: 88 e0 ldi r24, 0x08 ; 8 + 1fe06: 17 d0 rcall .+46 ; 0x1fe36 + 1fe08: 1c d0 rcall .+56 ; 0x1fe42 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 1fde4: 80 e1 ldi r24, 0x10 ; 16 - 1fde6: 01 d0 rcall .+2 ; 0x1fdea + 1fe0a: 80 e1 ldi r24, 0x10 ; 16 + 1fe0c: 01 d0 rcall .+2 ; 0x1fe10 } putch(STK_OK); - 1fde8: 43 cf rjmp .-378 ; 0x1fc70 + 1fe0e: 43 cf rjmp .-378 ; 0x1fc96 -0001fdea : - 1fdea: 90 91 c0 00 lds r25, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> +0001fe10 : + 1fe10: 90 91 c0 00 lds r25, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> } - 1fdee: 95 ff sbrs r25, 5 + 1fe14: 95 ff sbrs r25, 5 } void putch(char ch) { #ifndef SOFT_UART - while (!(UART_SRA & _BV(UDRE0))); - 1fdf0: fc cf rjmp .-8 ; 0x1fdea - UART_UDR = ch; - 1fdf2: 80 93 c6 00 sts 0x00C6, r24 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> - 1fdf6: 08 95 ret + #ifndef LIN_UART + while (!(UART_SRA & _BV(UDRE0))) { /* Spin */ } + 1fe16: fc cf rjmp .-8 ; 0x1fe10 + #else + while (!(LINSIR & _BV(LTXOK))) { /* Spin */ } + #endif -0001fdf8 : - [uartBit] "I" (UART_RX_BIT) + UART_UDR = ch; + 1fe18: 80 93 c6 00 sts 0x00C6, r24 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> + 1fe1c: 08 95 ret + +0001fe1e : : "r25" ); #else - while(!(UART_SRA & _BV(RXC0))) - 1fdf8: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - 1fdfc: 87 ff sbrs r24, 7 - 1fdfe: fc cf rjmp .-8 ; 0x1fdf8 - ; +#ifndef LIN_UART + while(!(UART_SRA & _BV(RXC0))) { /* Spin */ } + 1fe1e: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + 1fe22: 87 ff sbrs r24, 7 + 1fe24: fc cf rjmp .-8 ; 0x1fe1e if (!(UART_SRA & _BV(FE0))) { - 1fe00: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - 1fe04: 84 fd sbrc r24, 4 - 1fe06: 01 c0 rjmp .+2 ; 0x1fe0a + 1fe26: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + 1fe2a: 84 fd sbrc r24, 4 + 1fe2c: 01 c0 rjmp .+2 ; 0x1fe30 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 1fe08: a8 95 wdr + 1fe2e: a8 95 wdr * don't care that an invalid char is returned...) */ watchdogReset(); } ch = UART_UDR; - 1fe0a: 80 91 c6 00 lds r24, 0x00C6 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> + 1fe30: 80 91 c6 00 lds r24, 0x00C6 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> LED_PIN |= _BV(LED); #endif #endif return ch; } - 1fe0e: 08 95 ret + 1fe34: 08 95 ret -0001fe10 : - "wdr\n" - ); +0001fe36 : } void watchdogConfig(uint8_t x) { +#ifdef WDCE //does it have a Watchdog Change Enable? + #ifdef WDTCSR WDTCSR = _BV(WDCE) | _BV(WDE); - 1fe10: e0 e6 ldi r30, 0x60 ; 96 - 1fe12: f0 e0 ldi r31, 0x00 ; 0 - 1fe14: 98 e1 ldi r25, 0x18 ; 24 - 1fe16: 90 83 st Z, r25 - WDTCSR = x; - 1fe18: 80 83 st Z, r24 - 1fe1a: 08 95 ret + 1fe36: e0 e6 ldi r30, 0x60 ; 96 + 1fe38: f0 e0 ldi r31, 0x00 ; 0 + 1fe3a: 98 e1 ldi r25, 0x18 ; 24 + 1fe3c: 90 83 st Z, r25 +#else //then it must be one of those newfangled ones that use CCP + CCP=0xD8; //so write this magic number to CCP +#endif -0001fe1c : +#ifdef WDTCSR + WDTCSR = x; + 1fe3e: 80 83 st Z, r24 + 1fe40: 08 95 ret + +0001fe42 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) { - 1fe1c: ed df rcall .-38 ; 0x1fdf8 - 1fe1e: 80 32 cpi r24, 0x20 ; 32 - 1fe20: 19 f0 breq .+6 ; 0x1fe28 + 1fe42: ed df rcall .-38 ; 0x1fe1e + 1fe44: 80 32 cpi r24, 0x20 ; 32 + 1fe46: 19 f0 breq .+6 ; 0x1fe4e watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 1fe22: 88 e0 ldi r24, 0x08 ; 8 - 1fe24: f5 df rcall .-22 ; 0x1fe10 - 1fe26: ff cf rjmp .-2 ; 0x1fe26 + 1fe48: 88 e0 ldi r24, 0x08 ; 8 + 1fe4a: f5 df rcall .-22 ; 0x1fe36 + 1fe4c: ff cf rjmp .-2 ; 0x1fe4c while (1) // and busy-loop so that WD causes ; // a reset and app start. } putch(STK_INSYNC); - 1fe28: 84 e1 ldi r24, 0x14 ; 20 - 1fe2a: df cf rjmp .-66 ; 0x1fdea + 1fe4e: 84 e1 ldi r24, 0x14 ; 20 + 1fe50: df cf rjmp .-66 ; 0x1fe10 -0001fe2c : +0001fe52 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 1fe2c: cf 93 push r28 - 1fe2e: c8 2f mov r28, r24 + 1fe52: cf 93 push r28 + 1fe54: c8 2f mov r28, r24 do getch(); while (--count); - 1fe30: e3 df rcall .-58 ; 0x1fdf8 - 1fe32: c1 50 subi r28, 0x01 ; 1 - 1fe34: e9 f7 brne .-6 ; 0x1fe30 + 1fe56: e3 df rcall .-58 ; 0x1fe1e + 1fe58: c1 50 subi r28, 0x01 ; 1 + 1fe5a: e9 f7 brne .-6 ; 0x1fe56 verifySpace(); - 1fe36: cf 91 pop r28 - 1fe38: f1 cf rjmp .-30 ; 0x1fe1c +} + 1fe5c: cf 91 pop r28 +} +#endif -0001fe3a : +void getNch(uint8_t count) { + do getch(); while (--count); + verifySpace(); + 1fe5e: f1 cf rjmp .-30 ; 0x1fe42 -void appStart(uint8_t rstFlags) { - // save the reset flags in the designated register - // This can be saved in a main program by putting code in .init0 (which - // executes before normal c init code) to save R2 to a global variable. - __asm__ __volatile__ ("mov r2, %0\n" :: "r" (rstFlags)); - 1fe3a: 28 2e mov r2, r24 +0001fe60 : + 1fe60: fc 01 movw r30, r24 + * data=0 in WRITE + */ +static void do_spm(uint16_t address, uint8_t command, uint16_t data) __attribute__ ((used)); +static void do_spm(uint16_t address, uint8_t command, uint16_t data) { + // Do spm stuff + asm volatile ( + 1fe62: 0a 01 movw r0, r20 + 1fe64: 67 bf out 0x37, r22 ; 55 + 1fe66: e8 95 spm + 1fe68: 11 24 eor r1, r1 + 1fe6a: 07 b6 in r0, 0x37 ; 55 + ); - watchdogConfig(WATCHDOG_OFF); - 1fe3c: 80 e0 ldi r24, 0x00 ; 0 - 1fe3e: e8 df rcall .-48 ; 0x1fe10 - 1fe40: e0 e0 ldi r30, 0x00 ; 0 - // Note that appstart_vec is defined so that this works with either - // real or virtual boot partitions. - __asm__ __volatile__ ( - 1fe42: ff 27 eor r31, r31 - 1fe44: 09 94 ijmp + // wait for spm to complete + // it doesn't have much sense for __BOOT_PAGE_FILL, + // but it doesn't hurt and saves some bytes on 'if' + boot_spm_busy_wait(); + 1fe6c: 00 fc sbrc r0, 0 + 1fe6e: fd cf rjmp .-6 ; 0x1fe6a + 1fe70: 66 70 andi r22, 0x06 ; 6 +#if defined(RWWSRE) + // this 'if' condition should be: (command == __BOOT_PAGE_WRITE || command == __BOOT_PAGE_ERASE)... + // but it's tweaked a little assuming that in every command we are interested in here, there + // must be also SELFPRGEN set. If we skip checking this bit, we save here 4B + if ((command & (_BV(PGWRT)|_BV(PGERS))) && (data == 0) ) { + 1fe72: 29 f0 breq .+10 ; 0x1fe7e + 1fe74: 45 2b or r20, r21 + 1fe76: 19 f4 brne .+6 ; 0x1fe7e + 1fe78: 81 e1 ldi r24, 0x11 ; 17 + // Reenable read access to flash + __boot_rww_enable_short(); + 1fe7a: 87 bf out 0x37, r24 ; 55 + 1fe7c: e8 95 spm + 1fe7e: 08 95 ret -0001fe46 : - 1fe46: f9 99 sbic 0x1f, 1 ; 31 - 1fe48: fe cf rjmp .-4 ; 0x1fe46 - 1fe4a: 92 bd out 0x22, r25 ; 34 - 1fe4c: 81 bd out 0x21, r24 ; 33 - 1fe4e: f8 9a sbi 0x1f, 0 ; 31 - 1fe50: 99 27 eor r25, r25 - 1fe52: 80 b5 in r24, 0x20 ; 32 - 1fe54: 08 95 ret +0001fe80 : + 1fe80: f9 99 sbic 0x1f, 1 ; 31 + 1fe82: fe cf rjmp .-4 ; 0x1fe80 + 1fe84: 92 bd out 0x22, r25 ; 34 + 1fe86: 81 bd out 0x21, r24 ; 33 + 1fe88: f8 9a sbi 0x1f, 0 ; 31 + 1fe8a: 99 27 eor r25, r25 + 1fe8c: 80 b5 in r24, 0x20 ; 32 + 1fe8e: 08 95 ret -0001fe56 : - 1fe56: 26 2f mov r18, r22 +0001fe90 : + 1fe90: 26 2f mov r18, r22 -0001fe58 : - 1fe58: f9 99 sbic 0x1f, 1 ; 31 - 1fe5a: fe cf rjmp .-4 ; 0x1fe58 - 1fe5c: 1f ba out 0x1f, r1 ; 31 - 1fe5e: 92 bd out 0x22, r25 ; 34 - 1fe60: 81 bd out 0x21, r24 ; 33 - 1fe62: 20 bd out 0x20, r18 ; 32 - 1fe64: 0f b6 in r0, 0x3f ; 63 - 1fe66: f8 94 cli - 1fe68: fa 9a sbi 0x1f, 2 ; 31 - 1fe6a: f9 9a sbi 0x1f, 1 ; 31 - 1fe6c: 0f be out 0x3f, r0 ; 63 - 1fe6e: 01 96 adiw r24, 0x01 ; 1 - 1fe70: 08 95 ret +0001fe92 : + 1fe92: f9 99 sbic 0x1f, 1 ; 31 + 1fe94: fe cf rjmp .-4 ; 0x1fe92 + 1fe96: 1f ba out 0x1f, r1 ; 31 + 1fe98: 92 bd out 0x22, r25 ; 34 + 1fe9a: 81 bd out 0x21, r24 ; 33 + 1fe9c: 20 bd out 0x20, r18 ; 32 + 1fe9e: 0f b6 in r0, 0x3f ; 63 + 1fea0: f8 94 cli + 1fea2: fa 9a sbi 0x1f, 2 ; 31 + 1fea4: f9 9a sbi 0x1f, 1 ; 31 + 1fea6: 0f be out 0x3f, r0 ; 63 + 1fea8: 01 96 adiw r24, 0x01 ; 1 + 1feaa: 08 95 ret diff --git a/optiboot/bootloaders/optiboot/optiboot_atmega328.hex b/optiboot/bootloaders/optiboot/optiboot_atmega328.hex index 8e1e547..482b3e8 100644 --- a/optiboot/bootloaders/optiboot/optiboot_atmega328.hex +++ b/optiboot/bootloaders/optiboot/optiboot_atmega328.hex @@ -1,31 +1,33 @@ -:107E0000112484B7882349F0982F9A70923029F072 -:107E100081FF02C097EF94BFCCD085E080938100B2 -:107E200082E08093C00088E18093C10086E0809367 -:107E3000C20080E18093C4008EE0A6D0259A86E03F -:107E400020E33CEF91E0309385002093840096BBC3 -:107E5000B09BFECF1D9AA8954091C00047FD02C07F -:107E6000815089F7EE24E39495E0D92E21E1C22ECA -:107E70007FD0813461F47CD0182F8CD01238E9F097 -:107E8000113811F487E001C083E06BD067C0823401 -:107E900011F484E103C0853419F485E083D05EC019 -:107EA000853539F465D0C82F63D0D82FCC0FDD1FAE -:107EB00054C0863521F484E075D080E0E6CF843666 -:107EC00009F02EC055D054D0F82E52D0B82E00E074 -:107ED00011E04ED0F80181938F01FE12FACF5AD0F3 -:107EE000F5E4BF1201C0FFCF83E0FE0187BFE89534 -:107EF00007B600FCFDCFA0E0B1E0FE018D919D91A1 -:107F00000C01E7BEE89511243296FA12F7CFFE0174 -:107F1000D7BEE89507B600FCFDCFC7BEE8951EC0EA -:107F2000843771F425D024D0F82E22D033D08E019E -:107F3000F80185918F0115D0FA94F110F9CF0EC098 -:107F4000853739F427D08EE10CD085E90AD08FE04F -:107F50009CCF813511F488E017D01CD080E101D08E -:107F600087CF9091C00095FFFCCF8093C600089505 -:107F70008091C00087FFFCCF8091C00084FD01C0CC -:107F8000A8958091C6000895E0E6F0E098E190831E -:107F900080830895EDDF803219F088E0F5DFFFCFB0 -:107FA00084E1DFCFCF93C82FE3DFC150E9F7CF9152 -:0E7FB000F1CF282E80E0E8DFE0E0FF27099403 -:027FFE0000077A +:107E000001C0DCC0112484B7882361F0982F9A70D8 +:107E1000923041F081FF02C097EF94BF282E80E09E +:107E2000B8D0EEC085E08093810082E08093C000EE +:107E300088E18093C10086E08093C20080E1809356 +:107E4000C4008EE0A6D0259A86E020E33CEF91E0C6 +:107E5000309385002093840096BBB09BFECF1D9A83 +:107E6000A8954091C00047FD02C0815089F7EE24DB +:107E7000E39495E0D92E21E1C22E7FD0813461F4C4 +:107E80007CD0182F8CD01238E9F0113811F488E02A +:107E900001C083E06BD067C0823411F484E103C079 +:107EA000853419F485E083D05EC0853539F465D01A +:107EB000C82F63D0D82FCC0FDD1F54C0863521F4D6 +:107EC00084E075D080E0E6CF843609F02EC055D02E +:107ED00054D0F82E52D0B82E00E011E04ED0F80168 +:107EE00081938F01FE12FACF5AD0F5E4BF1201C080 +:107EF000FFCF83E0FE0187BFE89507B600FCFDCF0A +:107F0000A0E0B1E0FE018D919D910C01E7BEE895E6 +:107F100011243296FA12F7CFFE01D7BEE89507B6C4 +:107F200000FCFDCFC7BEE8951EC0843771F425D094 +:107F300024D0F82E22D033D08E01F80185918F0104 +:107F400015D0FA94F110F9CF0EC0853739F427D047 +:107F50008EE10CD085E90AD08FE09CCF813511F4F9 +:107F600088E017D01CD080E101D087CF9091C0006D +:107F700095FFFCCF8093C60008958091C00087FFD5 +:107F8000FCCF8091C00084FD01C0A8958091C600FF +:107F90000895E0E6F0E098E1908380830895EDDFB6 +:107FA000803219F088E0F5DFFFCF84E1DFCFCF9397 +:107FB000C82FE3DFC150E9F7CF91F1CFFC010A01EF +:107FC00067BFE895112407B600FCFDCF667029F065 +:0C7FD000452B19F481E187BFE895089566 +:027FFE00000879 :0400000300007E007B :00000001FF diff --git a/optiboot/bootloaders/optiboot/optiboot_atmega328.lst b/optiboot/bootloaders/optiboot/optiboot_atmega328.lst index f27d30c..df6e823 100644 --- a/optiboot/bootloaders/optiboot/optiboot_atmega328.lst +++ b/optiboot/bootloaders/optiboot/optiboot_atmega328.lst @@ -3,582 +3,638 @@ optiboot_atmega328.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .data 00000000 00800100 00007fbe 00000252 2**0 + 0 .data 00000000 00800100 00007fdc 00000270 2**0 CONTENTS, ALLOC, LOAD, DATA - 1 .text 000001be 00007e00 00007e00 00000094 2**1 + 1 .text 000001dc 00007e00 00007e00 00000094 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 2 .version 00000002 00007ffe 00007ffe 00000252 2**0 + 2 .version 00000002 00007ffe 00007ffe 00000270 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA - 3 .comment 0000002f 00000000 00000000 00000254 2**0 + 3 .comment 0000002f 00000000 00000000 00000272 2**0 CONTENTS, READONLY - 4 .debug_aranges 00000028 00000000 00000000 00000283 2**0 + 4 .debug_aranges 00000030 00000000 00000000 000002a1 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_info 000005c8 00000000 00000000 000002ab 2**0 + 5 .debug_info 000005fd 00000000 00000000 000002d1 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_abbrev 00000282 00000000 00000000 00000873 2**0 + 6 .debug_abbrev 000002c1 00000000 00000000 000008ce 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_line 000002f9 00000000 00000000 00000af5 2**0 + 7 .debug_line 00000334 00000000 00000000 00000b8f 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_frame 0000008c 00000000 00000000 00000df0 2**2 + 8 .debug_frame 0000009c 00000000 00000000 00000ec4 2**2 CONTENTS, READONLY, DEBUGGING - 9 .debug_str 000001fa 00000000 00000000 00000e7c 2**0 + 9 .debug_str 00000200 00000000 00000000 00000f60 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_loc 00000331 00000000 00000000 00001076 2**0 + 10 .debug_loc 00000359 00000000 00000000 00001160 2**0 CONTENTS, READONLY, DEBUGGING - 11 .debug_ranges 00000060 00000000 00000000 000013a7 2**0 + 11 .debug_ranges 00000068 00000000 00000000 000014b9 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: -00007e00
: +00007e00 : +/* everything that needs to run VERY early */ +void pre_main(void) { + // Allow convenient way of calling do_spm function - jump table, + // so entry to this function will always be here, indepedent of compilation, + // features etc + asm volatile ( + 7e00: 01 c0 rjmp .+2 ; 0x7e04
+ 7e02: dc c0 rjmp .+440 ; 0x7fbc + +00007e04
: // SP points to RAMEND // r1 contains zero // // If not, uncomment the following instructions: // cli(); asm volatile ("clr __zero_reg__"); - 7e00: 11 24 eor r1, r1 - * - * Code by MarkG55 - * see discusion in https://github.com/Optiboot/optiboot/issues/97 - */ -#if !defined(__AVR_ATmega16__) - ch = MCUSR; - 7e02: 84 b7 in r24, 0x34 ; 52 -#else + 7e04: 11 24 eor r1, r1 +#if defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) || \ + defined(__AVR_ATmega16__) || defined(__AVR_ATmega162__) || \ + defined (__AVR_ATmega128__) ch = MCUCSR; +#else + ch = MCUSR; + 7e06: 84 b7 in r24, 0x34 ; 52 #endif // Skip all logic and run bootloader if MCUSR is cleared (application request) if (ch != 0) { - 7e04: 88 23 and r24, r24 - 7e06: 49 f0 breq .+18 ; 0x7e1a + 7e08: 88 23 and r24, r24 + 7e0a: 61 f0 breq .+24 ; 0x7e24 * 2. we clear WDRF if it's set with EXTRF to avoid loops * One problematic scenario: broken application code sets watchdog timer * without clearing MCUSR before and triggers it quickly. But it's * recoverable by power-on with pushed reset button. */ if ((ch & (_BV(WDRF) | _BV(EXTRF))) != _BV(EXTRF)) { - 7e08: 98 2f mov r25, r24 - 7e0a: 9a 70 andi r25, 0x0A ; 10 - 7e0c: 92 30 cpi r25, 0x02 ; 2 - 7e0e: 29 f0 breq .+10 ; 0x7e1a + 7e0c: 98 2f mov r25, r24 + 7e0e: 9a 70 andi r25, 0x0A ; 10 + 7e10: 92 30 cpi r25, 0x02 ; 2 + 7e12: 41 f0 breq .+16 ; 0x7e24 if (ch & _BV(EXTRF)) { - 7e10: 81 ff sbrs r24, 1 - 7e12: 02 c0 rjmp .+4 ; 0x7e18 - * prevent entering bootloader. - * '&' operation is skipped to spare few bytes as bits in MCUSR - * can only be cleared. - */ -#if !defined(__AVR_ATmega16__) - MCUSR = ~(_BV(WDRF)); - 7e14: 97 ef ldi r25, 0xF7 ; 247 - 7e16: 94 bf out 0x34, r25 ; 52 + 7e14: 81 ff sbrs r24, 1 + 7e16: 02 c0 rjmp .+4 ; 0x7e1c + defined(__AVR_ATmega16__) || defined(__AVR_ATmega162__) || \ + defined(__AVR_ATmega128__) + // Fix missing definitions in avr-libc + MCUCSR = ~(_BV(WDRF)); #else - MCUCSR = ~(_BV(WDRF)); -#endif - } - appStart(ch); - 7e18: cc d0 rcall .+408 ; 0x7fb2 + MCUSR = ~(_BV(WDRF)); + 7e18: 97 ef ldi r25, 0xF7 ; 247 + 7e1a: 94 bf out 0x34, r25 ; 52 + /* + * save the reset flags in the designated register + * This can be saved in a main program by putting code in .init0 (which + * executes before normal c init code) to save R2 to a global variable. + */ + __asm__ __volatile__ ("mov r2, %0\n" :: "r" (ch)); + 7e1c: 28 2e mov r2, r24 + + // switch off watchdog + watchdogConfig(WATCHDOG_OFF); + 7e1e: 80 e0 ldi r24, 0x00 ; 0 + 7e20: b8 d0 rcall .+368 ; 0x7f92 + // Note that appstart_vec is defined so that this works with either + // real or virtual boot partitions. + __asm__ __volatile__ ( + 7e22: ee c0 rjmp .+476 ; 0x8000 } } #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - 7e1a: 85 e0 ldi r24, 0x05 ; 5 - 7e1c: 80 93 81 00 sts 0x0081, r24 ; 0x800081 <__TEXT_REGION_LENGTH__+0x7e0081> - UCSRA = _BV(U2X); //Double speed mode USART - UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx - UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 - UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); -#else + 7e24: 85 e0 ldi r24, 0x05 ; 5 + 7e26: 80 93 81 00 sts 0x0081, r24 ; 0x800081 <__TEXT_REGION_LENGTH__+0x7e0081> + LINBTR = (1 << LDISR) | (8 << LBT0); + LINCR = _BV(LENA) | _BV(LCMD2) | _BV(LCMD1) | _BV(LCMD0); + LINDAT=0; + #else + #ifndef SINGLESPEED UART_SRA = _BV(U2X0); //Double speed mode USART0 - 7e20: 82 e0 ldi r24, 0x02 ; 2 - 7e22: 80 93 c0 00 sts 0x00C0, r24 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + 7e2a: 82 e0 ldi r24, 0x02 ; 2 + 7e2c: 80 93 c0 00 sts 0x00C0, r24 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + #endif UART_SRB = _BV(RXEN0) | _BV(TXEN0); - 7e26: 88 e1 ldi r24, 0x18 ; 24 - 7e28: 80 93 c1 00 sts 0x00C1, r24 ; 0x8000c1 <__TEXT_REGION_LENGTH__+0x7e00c1> + 7e30: 88 e1 ldi r24, 0x18 ; 24 + 7e32: 80 93 c1 00 sts 0x00C1, r24 ; 0x8000c1 <__TEXT_REGION_LENGTH__+0x7e00c1> UART_SRC = _BV(UCSZ00) | _BV(UCSZ01); - 7e2c: 86 e0 ldi r24, 0x06 ; 6 - 7e2e: 80 93 c2 00 sts 0x00C2, r24 ; 0x8000c2 <__TEXT_REGION_LENGTH__+0x7e00c2> - UART_SRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 7e32: 80 e1 ldi r24, 0x10 ; 16 - 7e34: 80 93 c4 00 sts 0x00C4, r24 ; 0x8000c4 <__TEXT_REGION_LENGTH__+0x7e00c4> -#endif -#endif + 7e36: 86 e0 ldi r24, 0x06 ; 6 + 7e38: 80 93 c2 00 sts 0x00C2, r24 ; 0x8000c2 <__TEXT_REGION_LENGTH__+0x7e00c2> + UART_SRL = (uint8_t)BAUD_SETTING; + 7e3c: 80 e1 ldi r24, 0x10 ; 16 + 7e3e: 80 93 c4 00 sts 0x00C4, r24 ; 0x8000c4 <__TEXT_REGION_LENGTH__+0x7e00c4> + #endif // LIN_UART + #endif // mega8/etc +#endif // soft_uart // Set up watchdog to trigger after 1s watchdogConfig(WATCHDOG_1S); - 7e38: 8e e0 ldi r24, 0x0E ; 14 - 7e3a: a6 d0 rcall .+332 ; 0x7f88 + 7e42: 8e e0 ldi r24, 0x0E ; 14 + 7e44: a6 d0 rcall .+332 ; 0x7f92 #if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH) || defined(LED_START_ON) /* Set LED pin as output */ LED_DDR |= _BV(LED); - 7e3c: 25 9a sbi 0x04, 5 ; 4 - 7e3e: 86 e0 ldi r24, 0x06 ; 6 + 7e46: 25 9a sbi 0x04, 5 ; 4 + 7e48: 86 e0 ldi r24, 0x06 ; 6 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 7e40: 20 e3 ldi r18, 0x30 ; 48 - 7e42: 3c ef ldi r19, 0xFC ; 252 + 7e4a: 20 e3 ldi r18, 0x30 ; 48 + 7e4c: 3c ef ldi r19, 0xFC ; 252 TIFR1 = _BV(TOV1); - 7e44: 91 e0 ldi r25, 0x01 ; 1 + 7e4e: 91 e0 ldi r25, 0x01 ; 1 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - 7e46: 30 93 85 00 sts 0x0085, r19 ; 0x800085 <__TEXT_REGION_LENGTH__+0x7e0085> - 7e4a: 20 93 84 00 sts 0x0084, r18 ; 0x800084 <__TEXT_REGION_LENGTH__+0x7e0084> + 7e50: 30 93 85 00 sts 0x0085, r19 ; 0x800085 <__TEXT_REGION_LENGTH__+0x7e0085> + 7e54: 20 93 84 00 sts 0x0084, r18 ; 0x800084 <__TEXT_REGION_LENGTH__+0x7e0084> TIFR1 = _BV(TOV1); - 7e4e: 96 bb out 0x16, r25 ; 22 + 7e58: 96 bb out 0x16, r25 ; 22 while(!(TIFR1 & _BV(TOV1))); - 7e50: b0 9b sbis 0x16, 0 ; 22 - 7e52: fe cf rjmp .-4 ; 0x7e50 -#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega16__) + 7e5a: b0 9b sbis 0x16, 0 ; 22 + 7e5c: fe cf rjmp .-4 ; 0x7e5a + defined(__AVR_ATmega8535__) || defined(__AVR_ATmega16__) || \ + defined(__AVR_ATmega162__) || defined(__AVR_ATmega32__) || \ + defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) LED_PORT ^= _BV(LED); #else LED_PIN |= _BV(LED); - 7e54: 1d 9a sbi 0x03, 5 ; 3 + 7e5e: 1d 9a sbi 0x03, 5 ; 3 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 7e56: a8 95 wdr - * While in theory, the STK500 initial commands would be buffered + 7e60: a8 95 wdr * by the UART hardware, avrdude sends several attempts in rather * quick succession, some of which will be lost and cause us to * get out of sync. So if we see any data; stop blinking. */ +#ifndef LIN_UART if (UART_SRA & _BV(RXC0)) - 7e58: 40 91 c0 00 lds r20, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - 7e5c: 47 fd sbrc r20, 7 - 7e5e: 02 c0 rjmp .+4 ; 0x7e64 - 7e60: 81 50 subi r24, 0x01 ; 1 + 7e62: 40 91 c0 00 lds r20, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + 7e66: 47 fd sbrc r20, 7 + 7e68: 02 c0 rjmp .+4 ; 0x7e6e + 7e6a: 81 50 subi r24, 0x01 ; 1 #else // This doesn't seem to work? // if ((UART_PIN & (1< + 7e6c: 89 f7 brne .-30 ; 0x7e50 /* * Copy data from the buffer into the flash write buffer. */ do { __boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++)); - 7e64: ee 24 eor r14, r14 - 7e66: e3 94 inc r14 + 7e6e: ee 24 eor r14, r14 + 7e70: e3 94 inc r14 } while (len -= 2); /* * Actually Write the buffer to flash (and wait for it to finish.) */ __boot_page_write_short(address.word); - 7e68: 95 e0 ldi r25, 0x05 ; 5 - 7e6a: d9 2e mov r13, r25 + 7e72: 95 e0 ldi r25, 0x05 ; 5 + 7e74: d9 2e mov r13, r25 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash __boot_rww_enable_short(); - 7e6c: 21 e1 ldi r18, 0x11 ; 17 + 7e76: 21 e1 ldi r18, 0x11 ; 17 #endif /* Forever loop: exits by causing WDT reset */ for (;;) { /* get character from UART */ ch = getch(); - 7e6e: c2 2e mov r12, r18 + 7e78: c2 2e mov r12, r18 if(ch == STK_GET_PARAMETER) { - 7e70: 7f d0 rcall .+254 ; 0x7f70 + 7e7a: 7f d0 rcall .+254 ; 0x7f7a unsigned char which = getch(); - 7e72: 81 34 cpi r24, 0x41 ; 65 - 7e74: 61 f4 brne .+24 ; 0x7e8e - 7e76: 7c d0 rcall .+248 ; 0x7f70 + 7e7c: 81 34 cpi r24, 0x41 ; 65 + 7e7e: 61 f4 brne .+24 ; 0x7e98 + 7e80: 7c d0 rcall .+248 ; 0x7f7a verifySpace(); - 7e78: 18 2f mov r17, r24 - 7e7a: 8c d0 rcall .+280 ; 0x7f94 + 7e82: 18 2f mov r17, r24 + 7e84: 8c d0 rcall .+280 ; 0x7f9e /* * Send optiboot version as "SW version" * Note that the references to memory are optimized away. */ if (which == STK_SW_MINOR) { - 7e7c: 12 38 cpi r17, 0x82 ; 130 - 7e7e: e9 f0 breq .+58 ; 0x7eba + 7e86: 12 38 cpi r17, 0x82 ; 130 + 7e88: e9 f0 breq .+58 ; 0x7ec4 putch(optiboot_version & 0xFF); } else if (which == STK_SW_MAJOR) { - 7e80: 11 38 cpi r17, 0x81 ; 129 + 7e8a: 11 38 cpi r17, 0x81 ; 129 putch(optiboot_version >> 8); - 7e82: 11 f4 brne .+4 ; 0x7e88 - 7e84: 87 e0 ldi r24, 0x07 ; 7 + 7e8c: 11 f4 brne .+4 ; 0x7e92 + 7e8e: 88 e0 ldi r24, 0x08 ; 8 } else { /* * GET PARAMETER returns a generic 0x03 reply for * other parameters - enough to keep Avrdude happy */ putch(0x03); - 7e86: 01 c0 rjmp .+2 ; 0x7e8a - 7e88: 83 e0 ldi r24, 0x03 ; 3 - 7e8a: 6b d0 rcall .+214 ; 0x7f62 - 7e8c: 67 c0 rjmp .+206 ; 0x7f5c + 7e90: 01 c0 rjmp .+2 ; 0x7e94 + 7e92: 83 e0 ldi r24, 0x03 ; 3 + 7e94: 6b d0 rcall .+214 ; 0x7f6c + 7e96: 67 c0 rjmp .+206 ; 0x7f66 } } else if(ch == STK_SET_DEVICE) { - 7e8e: 82 34 cpi r24, 0x42 ; 66 + 7e98: 82 34 cpi r24, 0x42 ; 66 // SET DEVICE is ignored getNch(20); - 7e90: 11 f4 brne .+4 ; 0x7e96 - 7e92: 84 e1 ldi r24, 0x14 ; 20 + 7e9a: 11 f4 brne .+4 ; 0x7ea0 + 7e9c: 84 e1 ldi r24, 0x14 ; 20 } else if(ch == STK_SET_DEVICE_EXT) { - 7e94: 03 c0 rjmp .+6 ; 0x7e9c + 7e9e: 03 c0 rjmp .+6 ; 0x7ea6 // SET DEVICE EXT is ignored getNch(5); - 7e96: 85 34 cpi r24, 0x45 ; 69 - 7e98: 19 f4 brne .+6 ; 0x7ea0 - 7e9a: 85 e0 ldi r24, 0x05 ; 5 + 7ea0: 85 34 cpi r24, 0x45 ; 69 + 7ea2: 19 f4 brne .+6 ; 0x7eaa + 7ea4: 85 e0 ldi r24, 0x05 ; 5 } else if(ch == STK_LOAD_ADDRESS) { - 7e9c: 83 d0 rcall .+262 ; 0x7fa4 - 7e9e: 5e c0 rjmp .+188 ; 0x7f5c + 7ea6: 83 d0 rcall .+262 ; 0x7fae + 7ea8: 5e c0 rjmp .+188 ; 0x7f66 // LOAD ADDRESS address.bytes[0] = getch(); - 7ea0: 85 35 cpi r24, 0x55 ; 85 - 7ea2: 39 f4 brne .+14 ; 0x7eb2 - 7ea4: 65 d0 rcall .+202 ; 0x7f70 + 7eaa: 85 35 cpi r24, 0x55 ; 85 + 7eac: 39 f4 brne .+14 ; 0x7ebc + 7eae: 65 d0 rcall .+202 ; 0x7f7a address.bytes[1] = getch(); - 7ea6: c8 2f mov r28, r24 - 7ea8: 63 d0 rcall .+198 ; 0x7f70 + 7eb0: c8 2f mov r28, r24 + 7eb2: 63 d0 rcall .+198 ; 0x7f7a } else { RAMPZ &= 0xFE; } #endif address.word *= 2; // Convert from word address to byte address - 7eaa: d8 2f mov r29, r24 - 7eac: cc 0f add r28, r28 - 7eae: dd 1f adc r29, r29 + 7eb4: d8 2f mov r29, r24 + 7eb6: cc 0f add r28, r28 + 7eb8: dd 1f adc r29, r29 verifySpace(); } else if(ch == STK_UNIVERSAL) { - 7eb0: 54 c0 rjmp .+168 ; 0x7f5a + 7eba: 54 c0 rjmp .+168 ; 0x7f64 getNch(3); putch(0x00); } #else // UNIVERSAL command is ignored getNch(4); - 7eb2: 86 35 cpi r24, 0x56 ; 86 - 7eb4: 21 f4 brne .+8 ; 0x7ebe + 7ebc: 86 35 cpi r24, 0x56 ; 86 + 7ebe: 21 f4 brne .+8 ; 0x7ec8 putch(0x00); - 7eb6: 84 e0 ldi r24, 0x04 ; 4 - 7eb8: 75 d0 rcall .+234 ; 0x7fa4 + 7ec0: 84 e0 ldi r24, 0x04 ; 4 + 7ec2: 75 d0 rcall .+234 ; 0x7fae #endif } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - 7eba: 80 e0 ldi r24, 0x00 ; 0 - 7ebc: e6 cf rjmp .-52 ; 0x7e8a + 7ec4: 80 e0 ldi r24, 0x00 ; 0 + 7ec6: e6 cf rjmp .-52 ; 0x7e94 // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t desttype; uint8_t *bufPtr; pagelen_t savelength; GETLENGTH(length); - 7ebe: 84 36 cpi r24, 0x64 ; 100 - 7ec0: 09 f0 breq .+2 ; 0x7ec4 - 7ec2: 2e c0 rjmp .+92 ; 0x7f20 - 7ec4: 55 d0 rcall .+170 ; 0x7f70 + 7ec8: 84 36 cpi r24, 0x64 ; 100 + 7eca: 09 f0 breq .+2 ; 0x7ece + 7ecc: 2e c0 rjmp .+92 ; 0x7f2a + 7ece: 55 d0 rcall .+170 ; 0x7f7a savelength = length; desttype = getch(); - 7ec6: 54 d0 rcall .+168 ; 0x7f70 - 7ec8: f8 2e mov r15, r24 - 7eca: 52 d0 rcall .+164 ; 0x7f70 - 7ecc: b8 2e mov r11, r24 - 7ece: 00 e0 ldi r16, 0x00 ; 0 + 7ed0: 54 d0 rcall .+168 ; 0x7f7a + 7ed2: f8 2e mov r15, r24 + 7ed4: 52 d0 rcall .+164 ; 0x7f7a + 7ed6: b8 2e mov r11, r24 + 7ed8: 00 e0 ldi r16, 0x00 ; 0 // read a page worth of contents bufPtr = buff.bptr; do *bufPtr++ = getch(); - 7ed0: 11 e0 ldi r17, 0x01 ; 1 - 7ed2: 4e d0 rcall .+156 ; 0x7f70 - 7ed4: f8 01 movw r30, r16 - 7ed6: 81 93 st Z+, r24 - 7ed8: 8f 01 movw r16, r30 + 7eda: 11 e0 ldi r17, 0x01 ; 1 + 7edc: 4e d0 rcall .+156 ; 0x7f7a + 7ede: f8 01 movw r30, r16 + 7ee0: 81 93 st Z+, r24 + 7ee2: 8f 01 movw r16, r30 while (--length); - 7eda: fe 12 cpse r15, r30 - 7edc: fa cf rjmp .-12 ; 0x7ed2 + 7ee4: fe 12 cpse r15, r30 + 7ee6: fa cf rjmp .-12 ; 0x7edc // Read command terminator, start reply verifySpace(); - 7ede: 5a d0 rcall .+180 ; 0x7f94 - 7ee0: f5 e4 ldi r31, 0x45 ; 69 + 7ee8: 5a d0 rcall .+180 ; 0x7f9e + 7eea: f5 e4 ldi r31, 0x45 ; 69 * void writebuffer(memtype, buffer, address, length) */ static inline void writebuffer(int8_t memtype, addr16_t mybuff, addr16_t address, pagelen_t len) { switch (memtype) { - 7ee2: bf 12 cpse r11, r31 - 7ee4: 01 c0 rjmp .+2 ; 0x7ee8 - 7ee6: ff cf rjmp .-2 ; 0x7ee6 - 7ee8: 83 e0 ldi r24, 0x03 ; 3 - * Start the page erase and wait for it to finish. There - * used to be code to do this while receiving the data over - * the serial link, but the performance improvement was slight, + 7eec: bf 12 cpse r11, r31 + 7eee: 01 c0 rjmp .+2 ; 0x7ef2 + 7ef0: ff cf rjmp .-2 ; 0x7ef0 + 7ef2: 83 e0 ldi r24, 0x03 ; 3 * and we needed the space back. */ +#ifdef FOURPAGEERASE + if ((address.bytes[0] & ((SPM_PAGESIZE<<2)-1))==0) { +#endif __boot_page_erase_short(address.word); - 7eea: fe 01 movw r30, r28 - 7eec: 87 bf out 0x37, r24 ; 55 - 7eee: e8 95 spm - 7ef0: 07 b6 in r0, 0x37 ; 55 + 7ef4: fe 01 movw r30, r28 + 7ef6: 87 bf out 0x37, r24 ; 55 + 7ef8: e8 95 spm + 7efa: 07 b6 in r0, 0x37 ; 55 boot_spm_busy_wait(); - 7ef2: 00 fc sbrc r0, 0 - 7ef4: fd cf rjmp .-6 ; 0x7ef0 - 7ef6: a0 e0 ldi r26, 0x00 ; 0 - 7ef8: b1 e0 ldi r27, 0x01 ; 1 - 7efa: fe 01 movw r30, r28 - 7efc: 8d 91 ld r24, X+ + 7efc: 00 fc sbrc r0, 0 + 7efe: fd cf rjmp .-6 ; 0x7efa + 7f00: a0 e0 ldi r26, 0x00 ; 0 + 7f02: b1 e0 ldi r27, 0x01 ; 1 + 7f04: fe 01 movw r30, r28 + 7f06: 8d 91 ld r24, X+ /* * Copy data from the buffer into the flash write buffer. */ do { __boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++)); - 7efe: 9d 91 ld r25, X+ - 7f00: 0c 01 movw r0, r24 - 7f02: e7 be out 0x37, r14 ; 55 - 7f04: e8 95 spm - 7f06: 11 24 eor r1, r1 - 7f08: 32 96 adiw r30, 0x02 ; 2 + 7f08: 9d 91 ld r25, X+ + 7f0a: 0c 01 movw r0, r24 + 7f0c: e7 be out 0x37, r14 ; 55 + 7f0e: e8 95 spm + 7f10: 11 24 eor r1, r1 + 7f12: 32 96 adiw r30, 0x02 ; 2 addrPtr += 2; } while (len -= 2); - 7f0a: fa 12 cpse r15, r26 + 7f14: fa 12 cpse r15, r26 /* * Actually Write the buffer to flash (and wait for it to finish.) */ __boot_page_write_short(address.word); - 7f0c: f7 cf rjmp .-18 ; 0x7efc - 7f0e: fe 01 movw r30, r28 + 7f16: f7 cf rjmp .-18 ; 0x7f06 + 7f18: fe 01 movw r30, r28 boot_spm_busy_wait(); - 7f10: d7 be out 0x37, r13 ; 55 - 7f12: e8 95 spm + 7f1a: d7 be out 0x37, r13 ; 55 + 7f1c: e8 95 spm #if defined(RWWSRE) // Reenable read access to flash __boot_rww_enable_short(); - 7f14: 07 b6 in r0, 0x37 ; 55 - 7f16: 00 fc sbrc r0, 0 - 7f18: fd cf rjmp .-6 ; 0x7f14 + 7f1e: 07 b6 in r0, 0x37 ; 55 + 7f20: 00 fc sbrc r0, 0 + 7f22: fd cf rjmp .-6 ; 0x7f1e writebuffer(desttype, buff, address, savelength); } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - 7f1a: c7 be out 0x37, r12 ; 55 - 7f1c: e8 95 spm + 7f24: c7 be out 0x37, r12 ; 55 + 7f26: e8 95 spm uint8_t desttype; GETLENGTH(length); - 7f1e: 1e c0 rjmp .+60 ; 0x7f5c - 7f20: 84 37 cpi r24, 0x74 ; 116 - 7f22: 71 f4 brne .+28 ; 0x7f40 + 7f28: 1e c0 rjmp .+60 ; 0x7f66 + 7f2a: 84 37 cpi r24, 0x74 ; 116 + 7f2c: 71 f4 brne .+28 ; 0x7f4a desttype = getch(); - 7f24: 25 d0 rcall .+74 ; 0x7f70 + 7f2e: 25 d0 rcall .+74 ; 0x7f7a verifySpace(); - 7f26: 24 d0 rcall .+72 ; 0x7f70 - 7f28: f8 2e mov r15, r24 - 7f2a: 22 d0 rcall .+68 ; 0x7f70 + 7f30: 24 d0 rcall .+72 ; 0x7f7a + 7f32: f8 2e mov r15, r24 + 7f34: 22 d0 rcall .+68 ; 0x7f7a // while (--length); // read a Flash and increment the address (may increment RAMPZ) __asm__ ("elpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address)); #else // read a Flash byte and increment the address __asm__ ("lpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address)); - 7f2c: 33 d0 rcall .+102 ; 0x7f94 - 7f2e: 8e 01 movw r16, r28 + 7f36: 33 d0 rcall .+102 ; 0x7f9e + 7f38: 8e 01 movw r16, r28 #endif putch(ch); - 7f30: f8 01 movw r30, r16 + 7f3a: f8 01 movw r30, r16 } while (--length); - 7f32: 85 91 lpm r24, Z+ - 7f34: 8f 01 movw r16, r30 - 7f36: 15 d0 rcall .+42 ; 0x7f62 - 7f38: fa 94 dec r15 + 7f3c: 85 91 lpm r24, Z+ + 7f3e: 8f 01 movw r16, r30 + 7f40: 15 d0 rcall .+42 ; 0x7f6c + 7f42: fa 94 dec r15 read_mem(desttype, address, length); } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - 7f3a: f1 10 cpse r15, r1 - 7f3c: f9 cf rjmp .-14 ; 0x7f30 + 7f44: f1 10 cpse r15, r1 + 7f46: f9 cf rjmp .-14 ; 0x7f3a // READ SIGN - return what Avrdude wants to hear verifySpace(); - 7f3e: 0e c0 rjmp .+28 ; 0x7f5c - 7f40: 85 37 cpi r24, 0x75 ; 117 + 7f48: 0e c0 rjmp .+28 ; 0x7f66 + 7f4a: 85 37 cpi r24, 0x75 ; 117 putch(SIGNATURE_0); - 7f42: 39 f4 brne .+14 ; 0x7f52 - 7f44: 27 d0 rcall .+78 ; 0x7f94 - 7f46: 8e e1 ldi r24, 0x1E ; 30 + 7f4c: 39 f4 brne .+14 ; 0x7f5c + 7f4e: 27 d0 rcall .+78 ; 0x7f9e + 7f50: 8e e1 ldi r24, 0x1E ; 30 putch(SIGNATURE_1); - 7f48: 0c d0 rcall .+24 ; 0x7f62 - 7f4a: 85 e9 ldi r24, 0x95 ; 149 - 7f4c: 0a d0 rcall .+20 ; 0x7f62 + 7f52: 0c d0 rcall .+24 ; 0x7f6c + 7f54: 85 e9 ldi r24, 0x95 ; 149 + 7f56: 0a d0 rcall .+20 ; 0x7f6c putch(SIGNATURE_2); - 7f4e: 8f e0 ldi r24, 0x0F ; 15 - 7f50: 9c cf rjmp .-200 ; 0x7e8a + 7f58: 8f e0 ldi r24, 0x0F ; 15 + 7f5a: 9c cf rjmp .-200 ; 0x7e94 } else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */ - 7f52: 81 35 cpi r24, 0x51 ; 81 - 7f54: 11 f4 brne .+4 ; 0x7f5a + 7f5c: 81 35 cpi r24, 0x51 ; 81 + 7f5e: 11 f4 brne .+4 ; 0x7f64 // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - 7f56: 88 e0 ldi r24, 0x08 ; 8 - 7f58: 17 d0 rcall .+46 ; 0x7f88 - 7f5a: 1c d0 rcall .+56 ; 0x7f94 + 7f60: 88 e0 ldi r24, 0x08 ; 8 + 7f62: 17 d0 rcall .+46 ; 0x7f92 + 7f64: 1c d0 rcall .+56 ; 0x7f9e verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - 7f5c: 80 e1 ldi r24, 0x10 ; 16 - 7f5e: 01 d0 rcall .+2 ; 0x7f62 + 7f66: 80 e1 ldi r24, 0x10 ; 16 + 7f68: 01 d0 rcall .+2 ; 0x7f6c } putch(STK_OK); - 7f60: 87 cf rjmp .-242 ; 0x7e70 + 7f6a: 87 cf rjmp .-242 ; 0x7e7a -00007f62 : - 7f62: 90 91 c0 00 lds r25, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> +00007f6c : + 7f6c: 90 91 c0 00 lds r25, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> } - 7f66: 95 ff sbrs r25, 5 + 7f70: 95 ff sbrs r25, 5 } void putch(char ch) { #ifndef SOFT_UART - while (!(UART_SRA & _BV(UDRE0))); - 7f68: fc cf rjmp .-8 ; 0x7f62 - UART_UDR = ch; - 7f6a: 80 93 c6 00 sts 0x00C6, r24 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> - 7f6e: 08 95 ret + #ifndef LIN_UART + while (!(UART_SRA & _BV(UDRE0))) { /* Spin */ } + 7f72: fc cf rjmp .-8 ; 0x7f6c + #else + while (!(LINSIR & _BV(LTXOK))) { /* Spin */ } + #endif -00007f70 : - [uartBit] "I" (UART_RX_BIT) + UART_UDR = ch; + 7f74: 80 93 c6 00 sts 0x00C6, r24 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> + 7f78: 08 95 ret + +00007f7a : : "r25" ); #else - while(!(UART_SRA & _BV(RXC0))) - 7f70: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - 7f74: 87 ff sbrs r24, 7 - 7f76: fc cf rjmp .-8 ; 0x7f70 - ; +#ifndef LIN_UART + while(!(UART_SRA & _BV(RXC0))) { /* Spin */ } + 7f7a: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + 7f7e: 87 ff sbrs r24, 7 + 7f80: fc cf rjmp .-8 ; 0x7f7a if (!(UART_SRA & _BV(FE0))) { - 7f78: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - 7f7c: 84 fd sbrc r24, 4 - 7f7e: 01 c0 rjmp .+2 ; 0x7f82 + 7f82: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + 7f86: 84 fd sbrc r24, 4 + 7f88: 01 c0 rjmp .+2 ; 0x7f8c } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - 7f80: a8 95 wdr + 7f8a: a8 95 wdr * don't care that an invalid char is returned...) */ watchdogReset(); } ch = UART_UDR; - 7f82: 80 91 c6 00 lds r24, 0x00C6 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> + 7f8c: 80 91 c6 00 lds r24, 0x00C6 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> LED_PIN |= _BV(LED); #endif #endif return ch; } - 7f86: 08 95 ret + 7f90: 08 95 ret -00007f88 : - "wdr\n" - ); +00007f92 : } void watchdogConfig(uint8_t x) { +#ifdef WDCE //does it have a Watchdog Change Enable? + #ifdef WDTCSR WDTCSR = _BV(WDCE) | _BV(WDE); - 7f88: e0 e6 ldi r30, 0x60 ; 96 - 7f8a: f0 e0 ldi r31, 0x00 ; 0 - 7f8c: 98 e1 ldi r25, 0x18 ; 24 - 7f8e: 90 83 st Z, r25 - WDTCSR = x; - 7f90: 80 83 st Z, r24 - 7f92: 08 95 ret + 7f92: e0 e6 ldi r30, 0x60 ; 96 + 7f94: f0 e0 ldi r31, 0x00 ; 0 + 7f96: 98 e1 ldi r25, 0x18 ; 24 + 7f98: 90 83 st Z, r25 +#else //then it must be one of those newfangled ones that use CCP + CCP=0xD8; //so write this magic number to CCP +#endif -00007f94 : +#ifdef WDTCSR + WDTCSR = x; + 7f9a: 80 83 st Z, r24 + 7f9c: 08 95 ret + +00007f9e : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) { - 7f94: ed df rcall .-38 ; 0x7f70 - 7f96: 80 32 cpi r24, 0x20 ; 32 - 7f98: 19 f0 breq .+6 ; 0x7fa0 + 7f9e: ed df rcall .-38 ; 0x7f7a + 7fa0: 80 32 cpi r24, 0x20 ; 32 + 7fa2: 19 f0 breq .+6 ; 0x7faa watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 7f9a: 88 e0 ldi r24, 0x08 ; 8 - 7f9c: f5 df rcall .-22 ; 0x7f88 - 7f9e: ff cf rjmp .-2 ; 0x7f9e + 7fa4: 88 e0 ldi r24, 0x08 ; 8 + 7fa6: f5 df rcall .-22 ; 0x7f92 + 7fa8: ff cf rjmp .-2 ; 0x7fa8 while (1) // and busy-loop so that WD causes ; // a reset and app start. } putch(STK_INSYNC); - 7fa0: 84 e1 ldi r24, 0x14 ; 20 - 7fa2: df cf rjmp .-66 ; 0x7f62 + 7faa: 84 e1 ldi r24, 0x14 ; 20 + 7fac: df cf rjmp .-66 ; 0x7f6c -00007fa4 : +00007fae : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - 7fa4: cf 93 push r28 - 7fa6: c8 2f mov r28, r24 + 7fae: cf 93 push r28 + 7fb0: c8 2f mov r28, r24 do getch(); while (--count); - 7fa8: e3 df rcall .-58 ; 0x7f70 - 7faa: c1 50 subi r28, 0x01 ; 1 - 7fac: e9 f7 brne .-6 ; 0x7fa8 + 7fb2: e3 df rcall .-58 ; 0x7f7a + 7fb4: c1 50 subi r28, 0x01 ; 1 + 7fb6: e9 f7 brne .-6 ; 0x7fb2 verifySpace(); - 7fae: cf 91 pop r28 - 7fb0: f1 cf rjmp .-30 ; 0x7f94 +} + 7fb8: cf 91 pop r28 +} +#endif -00007fb2 : +void getNch(uint8_t count) { + do getch(); while (--count); + verifySpace(); + 7fba: f1 cf rjmp .-30 ; 0x7f9e -void appStart(uint8_t rstFlags) { - // save the reset flags in the designated register - // This can be saved in a main program by putting code in .init0 (which - // executes before normal c init code) to save R2 to a global variable. - __asm__ __volatile__ ("mov r2, %0\n" :: "r" (rstFlags)); - 7fb2: 28 2e mov r2, r24 +00007fbc : + 7fbc: fc 01 movw r30, r24 + * data=0 in WRITE + */ +static void do_spm(uint16_t address, uint8_t command, uint16_t data) __attribute__ ((used)); +static void do_spm(uint16_t address, uint8_t command, uint16_t data) { + // Do spm stuff + asm volatile ( + 7fbe: 0a 01 movw r0, r20 + 7fc0: 67 bf out 0x37, r22 ; 55 + 7fc2: e8 95 spm + 7fc4: 11 24 eor r1, r1 + 7fc6: 07 b6 in r0, 0x37 ; 55 + ); - watchdogConfig(WATCHDOG_OFF); - 7fb4: 80 e0 ldi r24, 0x00 ; 0 - 7fb6: e8 df rcall .-48 ; 0x7f88 - 7fb8: e0 e0 ldi r30, 0x00 ; 0 - // Note that appstart_vec is defined so that this works with either - // real or virtual boot partitions. - __asm__ __volatile__ ( - 7fba: ff 27 eor r31, r31 - 7fbc: 09 94 ijmp + // wait for spm to complete + // it doesn't have much sense for __BOOT_PAGE_FILL, + // but it doesn't hurt and saves some bytes on 'if' + boot_spm_busy_wait(); + 7fc8: 00 fc sbrc r0, 0 + 7fca: fd cf rjmp .-6 ; 0x7fc6 + 7fcc: 66 70 andi r22, 0x06 ; 6 +#if defined(RWWSRE) + // this 'if' condition should be: (command == __BOOT_PAGE_WRITE || command == __BOOT_PAGE_ERASE)... + // but it's tweaked a little assuming that in every command we are interested in here, there + // must be also SELFPRGEN set. If we skip checking this bit, we save here 4B + if ((command & (_BV(PGWRT)|_BV(PGERS))) && (data == 0) ) { + 7fce: 29 f0 breq .+10 ; 0x7fda + 7fd0: 45 2b or r20, r21 + 7fd2: 19 f4 brne .+6 ; 0x7fda + 7fd4: 81 e1 ldi r24, 0x11 ; 17 + // Reenable read access to flash + __boot_rww_enable_short(); + 7fd6: 87 bf out 0x37, r24 ; 55 + 7fd8: e8 95 spm + 7fda: 08 95 ret diff --git a/optiboot/bootloaders/optiboot/optiboot_atmega644p.hex b/optiboot/bootloaders/optiboot/optiboot_atmega644p.hex index 997a61c..e7fe71c 100644 --- a/optiboot/bootloaders/optiboot/optiboot_atmega644p.hex +++ b/optiboot/bootloaders/optiboot/optiboot_atmega644p.hex @@ -1,40 +1,53 @@ -:10FC0000112484B7882349F0982F9A70923029F0F4 -:10FC100081FF02C097EF94BFFBD085E08093810005 -:10FC200082E08093C00088E18093C10086E08093E9 -:10FC3000C20080E18093C4008EE0D5D0209A86E097 -:10FC400020E33CEF91E0309385002093840096BB45 -:10FC5000B09BFECF189AA8954091C00047FD02C006 -:10FC6000815089F7FF24F39455E0E52E61E1D62E0B -:10FC7000AED0813461F4ABD0C82FBBD0C238E9F02C -:10FC8000C13811F487E001C083E09AD096C0823475 -:10FC900011F484E103C0853419F485E0B2D08DC03D -:10FCA000853539F494D0082F92D0182F000F111FEA -:10FCB00083C0863521F484E0A4D080E0E6CF84368A -:10FCC00009F048C084D0C82FD0E0DC2FCC277FD0EB -:10FCD000C82B7DD0C82E5E01812C9924939477D0B7 -:10FCE000F40181934F01F1E0AF1AB108C1F781D05F -:10FCF00085E4C81212C0D3954801A12CBB24B3944B -:10FD0000AC16BD0609F459C0F50161915F01C4014B -:10FD10008DD0FFEF8F1A9F0AF3CF83E0F80187BFE2 -:10FD2000E89507B600FCFDCFA0E0B1E0F8018D91A9 -:10FD30009D910C01F7BEE8951124229732962097E9 -:10FD4000B1F7F801E7BEE89507B600FCFDCFD7BED6 -:10FD5000E89533C0843719F53AD0C82FD0E0DC2FAE -:10FD6000CC2735D05E01A82A32D0982E42D0E801A7 -:10FD7000F5E49F120BC0CE0151D022D081E0A81A29 -:10FD8000B1082196A114B104B1F717C0FE01859105 -:10FD9000EF0116D0E1E0AE1AB108C1F70EC0853709 -:10FDA00039F427D08EE10CD086E90AD08AE06DCFF5 -:10FDB000813511F488E017D01CD080E101D058CFF4 -:10FDC0009091C00095FFFCCF8093C600089580916C -:10FDD000C00087FFFCCF8091C00084FD01C0A895C2 -:10FDE0008091C6000895E0E6F0E098E1908380837A -:10FDF0000895EDDF803219F088E0F5DFFFCF84E170 -:10FE0000DFCFCF93C82FE3DFC150E9F7CF91F1CF18 -:10FE1000282E80E0E8DFE0E0FF270994F999FECF83 -:10FE200092BD81BDF89A992780B50895262FF9993A -:10FE3000FECF1FBA92BD81BD20BD0FB6F894FA9ACD -:08FE4000F99A0FBE0196089526 -:02FFFE000007FA +:10FC000011E0A0E0B1E0ECE7FEEF02C005900D923C +:10FC1000AC39B107D9F701C00BC1112484B78823CF +:10FC200061F0982F9A70923041F081FF02C097EFF7 +:10FC300094BF282E80E0E7D0E3C185E08093810067 +:10FC400082E08093C00088E18093C10086E08093C9 +:10FC5000C20080E18093C4008EE0D5D0209A86E077 +:10FC600020E33CEF91E0309385002093840096BB25 +:10FC7000B09BFECF189AA8954091C00047FD02C0E6 +:10FC8000815089F7FF24F39455E0E52E61E1D62EEB +:10FC9000AED0813461F4ABD0C82FBBD0C238E9F00C +:10FCA000C13811F488E001C083E09AD096C0823454 +:10FCB00011F484E103C0853419F485E0B2D08DC01D +:10FCC000853539F494D0082F92D0182F000F111FCA +:10FCD00083C0863521F484E0A4D080E0E6CF84366A +:10FCE00009F048C084D0C82FD0E0DC2FCC277FD0CB +:10FCF000C82B7DD0C82E5E01812C9924939477D097 +:10FD0000F40181934F01F1E0AF1AB108C1F781D03E +:10FD100085E4C81212C0D3954801A12CBB24B3942A +:10FD2000AC16BD0609F459C0F50161915F01C4012B +:10FD300097D0FFEF8F1A9F0AF3CF83E0F80187BFB8 +:10FD4000E89507B600FCFDCFA0E0B1E0F8018D9189 +:10FD50009D910C01F7BEE8951124229732962097C9 +:10FD6000B1F7F801E7BEE89507B600FCFDCFD7BEB6 +:10FD7000E89533C0843719F53AD0C82FD0E0DC2F8E +:10FD8000CC2735D05E01A82A32D0982E42D0E80187 +:10FD9000F5E49F120BC0CE015BD022D081E0A81AFF +:10FDA000B1082196A114B104B1F717C0FE018591E5 +:10FDB000EF0116D0E1E0AE1AB108C1F70EC08537E9 +:10FDC00039F427D08EE10CD086E90AD08AE06DCFD5 +:10FDD000813511F488E017D01CD080E101D058CFD4 +:10FDE0009091C00095FFFCCF8093C600089580914C +:10FDF000C00087FFFCCF8091C00084FD01C0A895A2 +:10FE00008091C6000895E0E6F0E098E19083808359 +:10FE10000895EDDF803219F088E0F5DFFFCF84E14F +:10FE2000DFCFCF93C82FE3DFC150E9F7CF91F1CFF8 +:10FE3000FC010A0167BFE895112407B600FCFDCF5D +:10FE4000667029F0452B19F481E187BFE895089584 +:10FE5000F999FECF92BD81BDF89A992780B5089592 +:10FE6000262FF999FECF1FBA92BD81BD20BD0FB6D6 +:0CFE7000F894FA9AF99A0FBE01960895D2 +:10FE7C0056657273696F6E3D382E30004F50544981 +:10FE8C00424F4F545F435553544F4D5645523D309E +:10FE9C00004465766963653D61746D6567613634F0 +:10FEAC00347000465F4350553D3136303030303081 +:10FEBC00304C00424947424F4F543D310042756926 +:10FECC006C743A53657020323020323031383A300D +:10FEDC00313A31383A353000554152543D300042B8 +:10FEEC004155445F524154453D313135323030003B +:10FEFC004C45443D4230004C45445F5354415254B0 +:0CFF0C005F464C41534845533D33000014 +:02FFFE000008F9 :040000030000FC00FD :00000001FF diff --git a/optiboot/bootloaders/optiboot/optiboot_atmega644p.lst b/optiboot/bootloaders/optiboot/optiboot_atmega644p.lst index 2ba4775..0cc5171 100644 --- a/optiboot/bootloaders/optiboot/optiboot_atmega644p.lst +++ b/optiboot/bootloaders/optiboot/optiboot_atmega644p.lst @@ -3,681 +3,745 @@ optiboot_atmega644p.elf: file format elf32-avr Sections: Idx Name Size VMA LMA File off Algn - 0 .data 00000000 00800100 0000fe48 000002dc 2**0 + 0 .data 0000009c 00800100 0000fe7c 00000310 2**0 CONTENTS, ALLOC, LOAD, DATA - 1 .text 00000248 0000fc00 0000fc00 00000094 2**1 + 1 .text 0000027c 0000fc00 0000fc00 00000094 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE - 2 .version 00000002 0000fffe 0000fffe 000002dc 2**0 + 2 .version 00000002 0000fffe 0000fffe 000003ac 2**0 CONTENTS, ALLOC, LOAD, READONLY, DATA - 3 .comment 0000002f 00000000 00000000 000002de 2**0 + 3 .comment 0000002f 00000000 00000000 000003ae 2**0 CONTENTS, READONLY - 4 .debug_aranges 00000028 00000000 00000000 0000030d 2**0 + 4 .debug_aranges 00000030 00000000 00000000 000003dd 2**0 CONTENTS, READONLY, DEBUGGING - 5 .debug_info 00000625 00000000 00000000 00000335 2**0 + 5 .debug_info 000007a8 00000000 00000000 0000040d 2**0 CONTENTS, READONLY, DEBUGGING - 6 .debug_abbrev 00000286 00000000 00000000 0000095a 2**0 + 6 .debug_abbrev 000002c5 00000000 00000000 00000bb5 2**0 CONTENTS, READONLY, DEBUGGING - 7 .debug_line 0000035f 00000000 00000000 00000be0 2**0 + 7 .debug_line 0000039a 00000000 00000000 00000e7a 2**0 CONTENTS, READONLY, DEBUGGING - 8 .debug_frame 0000008c 00000000 00000000 00000f40 2**2 + 8 .debug_frame 0000009c 00000000 00000000 00001214 2**2 CONTENTS, READONLY, DEBUGGING - 9 .debug_str 0000021d 00000000 00000000 00000fcc 2**0 + 9 .debug_str 0000028b 00000000 00000000 000012b0 2**0 CONTENTS, READONLY, DEBUGGING - 10 .debug_loc 00000421 00000000 00000000 000011e9 2**0 + 10 .debug_loc 00000449 00000000 00000000 0000153b 2**0 CONTENTS, READONLY, DEBUGGING - 11 .debug_ranges 00000060 00000000 00000000 0000160a 2**0 + 11 .debug_ranges 00000068 00000000 00000000 00001984 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: -0000fc00
: +0000fc00 <__ctors_end>: + fc00: 11 e0 ldi r17, 0x01 ; 1 + fc02: a0 e0 ldi r26, 0x00 ; 0 + fc04: b1 e0 ldi r27, 0x01 ; 1 + fc06: ec e7 ldi r30, 0x7C ; 124 + fc08: fe ef ldi r31, 0xFE ; 254 + fc0a: 02 c0 rjmp .+4 ; 0xfc10 <__ctors_end+0x10> + fc0c: 05 90 lpm r0, Z+ + fc0e: 0d 92 st X+, r0 + fc10: ac 39 cpi r26, 0x9C ; 156 + fc12: b1 07 cpc r27, r17 + fc14: d9 f7 brne .-10 ; 0xfc0c <__ctors_end+0xc> + +0000fc16 : +/* everything that needs to run VERY early */ +void pre_main(void) { + // Allow convenient way of calling do_spm function - jump table, + // so entry to this function will always be here, indepedent of compilation, + // features etc + asm volatile ( + fc16: 01 c0 rjmp .+2 ; 0xfc1a
+ fc18: 0b c1 rjmp .+534 ; 0xfe30 + +0000fc1a
: // SP points to RAMEND // r1 contains zero // // If not, uncomment the following instructions: // cli(); asm volatile ("clr __zero_reg__"); - fc00: 11 24 eor r1, r1 - * - * Code by MarkG55 - * see discusion in https://github.com/Optiboot/optiboot/issues/97 - */ -#if !defined(__AVR_ATmega16__) - ch = MCUSR; - fc02: 84 b7 in r24, 0x34 ; 52 -#else + fc1a: 11 24 eor r1, r1 +#if defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) || \ + defined(__AVR_ATmega16__) || defined(__AVR_ATmega162__) || \ + defined (__AVR_ATmega128__) ch = MCUCSR; +#else + ch = MCUSR; + fc1c: 84 b7 in r24, 0x34 ; 52 #endif // Skip all logic and run bootloader if MCUSR is cleared (application request) if (ch != 0) { - fc04: 88 23 and r24, r24 - fc06: 49 f0 breq .+18 ; 0xfc1a + fc1e: 88 23 and r24, r24 + fc20: 61 f0 breq .+24 ; 0xfc3a * 2. we clear WDRF if it's set with EXTRF to avoid loops * One problematic scenario: broken application code sets watchdog timer * without clearing MCUSR before and triggers it quickly. But it's * recoverable by power-on with pushed reset button. */ if ((ch & (_BV(WDRF) | _BV(EXTRF))) != _BV(EXTRF)) { - fc08: 98 2f mov r25, r24 - fc0a: 9a 70 andi r25, 0x0A ; 10 - fc0c: 92 30 cpi r25, 0x02 ; 2 - fc0e: 29 f0 breq .+10 ; 0xfc1a + fc22: 98 2f mov r25, r24 + fc24: 9a 70 andi r25, 0x0A ; 10 + fc26: 92 30 cpi r25, 0x02 ; 2 + fc28: 41 f0 breq .+16 ; 0xfc3a if (ch & _BV(EXTRF)) { - fc10: 81 ff sbrs r24, 1 - fc12: 02 c0 rjmp .+4 ; 0xfc18 - * prevent entering bootloader. - * '&' operation is skipped to spare few bytes as bits in MCUSR - * can only be cleared. - */ -#if !defined(__AVR_ATmega16__) - MCUSR = ~(_BV(WDRF)); - fc14: 97 ef ldi r25, 0xF7 ; 247 - fc16: 94 bf out 0x34, r25 ; 52 + fc2a: 81 ff sbrs r24, 1 + fc2c: 02 c0 rjmp .+4 ; 0xfc32 + defined(__AVR_ATmega16__) || defined(__AVR_ATmega162__) || \ + defined(__AVR_ATmega128__) + // Fix missing definitions in avr-libc + MCUCSR = ~(_BV(WDRF)); #else - MCUCSR = ~(_BV(WDRF)); -#endif - } - appStart(ch); - fc18: fb d0 rcall .+502 ; 0xfe10 + MCUSR = ~(_BV(WDRF)); + fc2e: 97 ef ldi r25, 0xF7 ; 247 + fc30: 94 bf out 0x34, r25 ; 52 + /* + * save the reset flags in the designated register + * This can be saved in a main program by putting code in .init0 (which + * executes before normal c init code) to save R2 to a global variable. + */ + __asm__ __volatile__ ("mov r2, %0\n" :: "r" (ch)); + fc32: 28 2e mov r2, r24 + + // switch off watchdog + watchdogConfig(WATCHDOG_OFF); + fc34: 80 e0 ldi r24, 0x00 ; 0 + fc36: e7 d0 rcall .+462 ; 0xfe06 + // Note that appstart_vec is defined so that this works with either + // real or virtual boot partitions. + __asm__ __volatile__ ( + fc38: e3 c1 rjmp .+966 ; 0x10000 <__EEPROM_REGION_LENGTH__> } } #if LED_START_FLASHES > 0 // Set up Timer 1 for timeout counter TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - fc1a: 85 e0 ldi r24, 0x05 ; 5 - fc1c: 80 93 81 00 sts 0x0081, r24 ; 0x800081 <__TEXT_REGION_LENGTH__+0x7e0081> - UCSRA = _BV(U2X); //Double speed mode USART - UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx - UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 - UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); -#else + fc3a: 85 e0 ldi r24, 0x05 ; 5 + fc3c: 80 93 81 00 sts 0x0081, r24 ; 0x800081 <__TEXT_REGION_LENGTH__+0x7e0081> + LINBTR = (1 << LDISR) | (8 << LBT0); + LINCR = _BV(LENA) | _BV(LCMD2) | _BV(LCMD1) | _BV(LCMD0); + LINDAT=0; + #else + #ifndef SINGLESPEED UART_SRA = _BV(U2X0); //Double speed mode USART0 - fc20: 82 e0 ldi r24, 0x02 ; 2 - fc22: 80 93 c0 00 sts 0x00C0, r24 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + fc40: 82 e0 ldi r24, 0x02 ; 2 + fc42: 80 93 c0 00 sts 0x00C0, r24 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + #endif UART_SRB = _BV(RXEN0) | _BV(TXEN0); - fc26: 88 e1 ldi r24, 0x18 ; 24 - fc28: 80 93 c1 00 sts 0x00C1, r24 ; 0x8000c1 <__TEXT_REGION_LENGTH__+0x7e00c1> + fc46: 88 e1 ldi r24, 0x18 ; 24 + fc48: 80 93 c1 00 sts 0x00C1, r24 ; 0x8000c1 <__TEXT_REGION_LENGTH__+0x7e00c1> UART_SRC = _BV(UCSZ00) | _BV(UCSZ01); - fc2c: 86 e0 ldi r24, 0x06 ; 6 - fc2e: 80 93 c2 00 sts 0x00C2, r24 ; 0x8000c2 <__TEXT_REGION_LENGTH__+0x7e00c2> - UART_SRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - fc32: 80 e1 ldi r24, 0x10 ; 16 - fc34: 80 93 c4 00 sts 0x00C4, r24 ; 0x8000c4 <__TEXT_REGION_LENGTH__+0x7e00c4> -#endif -#endif + fc4c: 86 e0 ldi r24, 0x06 ; 6 + fc4e: 80 93 c2 00 sts 0x00C2, r24 ; 0x8000c2 <__TEXT_REGION_LENGTH__+0x7e00c2> + UART_SRL = (uint8_t)BAUD_SETTING; + fc52: 80 e1 ldi r24, 0x10 ; 16 + fc54: 80 93 c4 00 sts 0x00C4, r24 ; 0x8000c4 <__TEXT_REGION_LENGTH__+0x7e00c4> + #endif // LIN_UART + #endif // mega8/etc +#endif // soft_uart // Set up watchdog to trigger after 1s watchdogConfig(WATCHDOG_1S); - fc38: 8e e0 ldi r24, 0x0E ; 14 - fc3a: d5 d0 rcall .+426 ; 0xfde6 + fc58: 8e e0 ldi r24, 0x0E ; 14 + fc5a: d5 d0 rcall .+426 ; 0xfe06 #if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH) || defined(LED_START_ON) /* Set LED pin as output */ LED_DDR |= _BV(LED); - fc3c: 20 9a sbi 0x04, 0 ; 4 - fc3e: 86 e0 ldi r24, 0x06 ; 6 + fc5c: 20 9a sbi 0x04, 0 ; 4 + fc5e: 86 e0 ldi r24, 0x06 ; 6 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - fc40: 20 e3 ldi r18, 0x30 ; 48 - fc42: 3c ef ldi r19, 0xFC ; 252 + fc60: 20 e3 ldi r18, 0x30 ; 48 + fc62: 3c ef ldi r19, 0xFC ; 252 TIFR1 = _BV(TOV1); - fc44: 91 e0 ldi r25, 0x01 ; 1 + fc64: 91 e0 ldi r25, 0x01 ; 1 } #if LED_START_FLASHES > 0 void flash_led(uint8_t count) { do { TCNT1 = -(F_CPU/(1024*16)); - fc46: 30 93 85 00 sts 0x0085, r19 ; 0x800085 <__TEXT_REGION_LENGTH__+0x7e0085> - fc4a: 20 93 84 00 sts 0x0084, r18 ; 0x800084 <__TEXT_REGION_LENGTH__+0x7e0084> + fc66: 30 93 85 00 sts 0x0085, r19 ; 0x800085 <__TEXT_REGION_LENGTH__+0x7e0085> + fc6a: 20 93 84 00 sts 0x0084, r18 ; 0x800084 <__TEXT_REGION_LENGTH__+0x7e0084> TIFR1 = _BV(TOV1); - fc4e: 96 bb out 0x16, r25 ; 22 + fc6e: 96 bb out 0x16, r25 ; 22 while(!(TIFR1 & _BV(TOV1))); - fc50: b0 9b sbis 0x16, 0 ; 22 - fc52: fe cf rjmp .-4 ; 0xfc50 -#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega16__) + fc70: b0 9b sbis 0x16, 0 ; 22 + fc72: fe cf rjmp .-4 ; 0xfc70 + defined(__AVR_ATmega8535__) || defined(__AVR_ATmega16__) || \ + defined(__AVR_ATmega162__) || defined(__AVR_ATmega32__) || \ + defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__) LED_PORT ^= _BV(LED); #else LED_PIN |= _BV(LED); - fc54: 18 9a sbi 0x03, 0 ; 3 + fc74: 18 9a sbi 0x03, 0 ; 3 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - fc56: a8 95 wdr - * While in theory, the STK500 initial commands would be buffered + fc76: a8 95 wdr * by the UART hardware, avrdude sends several attempts in rather * quick succession, some of which will be lost and cause us to * get out of sync. So if we see any data; stop blinking. */ +#ifndef LIN_UART if (UART_SRA & _BV(RXC0)) - fc58: 40 91 c0 00 lds r20, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - fc5c: 47 fd sbrc r20, 7 - fc5e: 02 c0 rjmp .+4 ; 0xfc64 - fc60: 81 50 subi r24, 0x01 ; 1 + fc78: 40 91 c0 00 lds r20, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + fc7c: 47 fd sbrc r20, 7 + fc7e: 02 c0 rjmp .+4 ; 0xfc84 + fc80: 81 50 subi r24, 0x01 ; 1 #else // This doesn't seem to work? // if ((UART_PIN & (1< + fc82: 89 f7 brne .-30 ; 0xfc66 /* * Copy data from the buffer into the flash write buffer. */ do { __boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++)); - fc64: ff 24 eor r15, r15 - fc66: f3 94 inc r15 + fc84: ff 24 eor r15, r15 + fc86: f3 94 inc r15 } while (len -= 2); /* * Actually Write the buffer to flash (and wait for it to finish.) */ __boot_page_write_short(address.word); - fc68: 55 e0 ldi r21, 0x05 ; 5 - fc6a: e5 2e mov r14, r21 + fc88: 55 e0 ldi r21, 0x05 ; 5 + fc8a: e5 2e mov r14, r21 boot_spm_busy_wait(); #if defined(RWWSRE) // Reenable read access to flash __boot_rww_enable_short(); - fc6c: 61 e1 ldi r22, 0x11 ; 17 + fc8c: 61 e1 ldi r22, 0x11 ; 17 #endif /* Forever loop: exits by causing WDT reset */ for (;;) { /* get character from UART */ ch = getch(); - fc6e: d6 2e mov r13, r22 + fc8e: d6 2e mov r13, r22 if(ch == STK_GET_PARAMETER) { - fc70: ae d0 rcall .+348 ; 0xfdce + fc90: ae d0 rcall .+348 ; 0xfdee unsigned char which = getch(); - fc72: 81 34 cpi r24, 0x41 ; 65 - fc74: 61 f4 brne .+24 ; 0xfc8e - fc76: ab d0 rcall .+342 ; 0xfdce + fc92: 81 34 cpi r24, 0x41 ; 65 + fc94: 61 f4 brne .+24 ; 0xfcae + fc96: ab d0 rcall .+342 ; 0xfdee verifySpace(); - fc78: c8 2f mov r28, r24 - fc7a: bb d0 rcall .+374 ; 0xfdf2 + fc98: c8 2f mov r28, r24 + fc9a: bb d0 rcall .+374 ; 0xfe12 /* * Send optiboot version as "SW version" * Note that the references to memory are optimized away. */ if (which == STK_SW_MINOR) { - fc7c: c2 38 cpi r28, 0x82 ; 130 - fc7e: e9 f0 breq .+58 ; 0xfcba + fc9c: c2 38 cpi r28, 0x82 ; 130 + fc9e: e9 f0 breq .+58 ; 0xfcda putch(optiboot_version & 0xFF); } else if (which == STK_SW_MAJOR) { - fc80: c1 38 cpi r28, 0x81 ; 129 + fca0: c1 38 cpi r28, 0x81 ; 129 putch(optiboot_version >> 8); - fc82: 11 f4 brne .+4 ; 0xfc88 - fc84: 87 e0 ldi r24, 0x07 ; 7 + fca2: 11 f4 brne .+4 ; 0xfca8 + fca4: 88 e0 ldi r24, 0x08 ; 8 } else { /* * GET PARAMETER returns a generic 0x03 reply for * other parameters - enough to keep Avrdude happy */ putch(0x03); - fc86: 01 c0 rjmp .+2 ; 0xfc8a - fc88: 83 e0 ldi r24, 0x03 ; 3 - fc8a: 9a d0 rcall .+308 ; 0xfdc0 - fc8c: 96 c0 rjmp .+300 ; 0xfdba + fca6: 01 c0 rjmp .+2 ; 0xfcaa + fca8: 83 e0 ldi r24, 0x03 ; 3 + fcaa: 9a d0 rcall .+308 ; 0xfde0 + fcac: 96 c0 rjmp .+300 ; 0xfdda } } else if(ch == STK_SET_DEVICE) { - fc8e: 82 34 cpi r24, 0x42 ; 66 + fcae: 82 34 cpi r24, 0x42 ; 66 // SET DEVICE is ignored getNch(20); - fc90: 11 f4 brne .+4 ; 0xfc96 - fc92: 84 e1 ldi r24, 0x14 ; 20 + fcb0: 11 f4 brne .+4 ; 0xfcb6 + fcb2: 84 e1 ldi r24, 0x14 ; 20 } else if(ch == STK_SET_DEVICE_EXT) { - fc94: 03 c0 rjmp .+6 ; 0xfc9c + fcb4: 03 c0 rjmp .+6 ; 0xfcbc // SET DEVICE EXT is ignored getNch(5); - fc96: 85 34 cpi r24, 0x45 ; 69 - fc98: 19 f4 brne .+6 ; 0xfca0 - fc9a: 85 e0 ldi r24, 0x05 ; 5 + fcb6: 85 34 cpi r24, 0x45 ; 69 + fcb8: 19 f4 brne .+6 ; 0xfcc0 + fcba: 85 e0 ldi r24, 0x05 ; 5 } else if(ch == STK_LOAD_ADDRESS) { - fc9c: b2 d0 rcall .+356 ; 0xfe02 - fc9e: 8d c0 rjmp .+282 ; 0xfdba + fcbc: b2 d0 rcall .+356 ; 0xfe22 + fcbe: 8d c0 rjmp .+282 ; 0xfdda // LOAD ADDRESS address.bytes[0] = getch(); - fca0: 85 35 cpi r24, 0x55 ; 85 - fca2: 39 f4 brne .+14 ; 0xfcb2 - fca4: 94 d0 rcall .+296 ; 0xfdce + fcc0: 85 35 cpi r24, 0x55 ; 85 + fcc2: 39 f4 brne .+14 ; 0xfcd2 + fcc4: 94 d0 rcall .+296 ; 0xfdee address.bytes[1] = getch(); - fca6: 08 2f mov r16, r24 - fca8: 92 d0 rcall .+292 ; 0xfdce + fcc6: 08 2f mov r16, r24 + fcc8: 92 d0 rcall .+292 ; 0xfdee } else { RAMPZ &= 0xFE; } #endif address.word *= 2; // Convert from word address to byte address - fcaa: 18 2f mov r17, r24 - fcac: 00 0f add r16, r16 - fcae: 11 1f adc r17, r17 + fcca: 18 2f mov r17, r24 + fccc: 00 0f add r16, r16 + fcce: 11 1f adc r17, r17 verifySpace(); } else if(ch == STK_UNIVERSAL) { - fcb0: 83 c0 rjmp .+262 ; 0xfdb8 + fcd0: 83 c0 rjmp .+262 ; 0xfdd8 getNch(3); putch(0x00); } #else // UNIVERSAL command is ignored getNch(4); - fcb2: 86 35 cpi r24, 0x56 ; 86 - fcb4: 21 f4 brne .+8 ; 0xfcbe - fcb6: 84 e0 ldi r24, 0x04 ; 4 + fcd2: 86 35 cpi r24, 0x56 ; 86 + fcd4: 21 f4 brne .+8 ; 0xfcde + fcd6: 84 e0 ldi r24, 0x04 ; 4 putch(0x00); - fcb8: a4 d0 rcall .+328 ; 0xfe02 + fcd8: a4 d0 rcall .+328 ; 0xfe22 #endif } /* Write memory, length is big endian and is in bytes */ else if(ch == STK_PROG_PAGE) { - fcba: 80 e0 ldi r24, 0x00 ; 0 - fcbc: e6 cf rjmp .-52 ; 0xfc8a + fcda: 80 e0 ldi r24, 0x00 ; 0 + fcdc: e6 cf rjmp .-52 ; 0xfcaa // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t desttype; uint8_t *bufPtr; pagelen_t savelength; GETLENGTH(length); - fcbe: 84 36 cpi r24, 0x64 ; 100 - fcc0: 09 f0 breq .+2 ; 0xfcc4 - fcc2: 48 c0 rjmp .+144 ; 0xfd54 - fcc4: 84 d0 rcall .+264 ; 0xfdce - fcc6: c8 2f mov r28, r24 - fcc8: d0 e0 ldi r29, 0x00 ; 0 - fcca: dc 2f mov r29, r28 - fccc: cc 27 eor r28, r28 + fcde: 84 36 cpi r24, 0x64 ; 100 + fce0: 09 f0 breq .+2 ; 0xfce4 + fce2: 48 c0 rjmp .+144 ; 0xfd74 + fce4: 84 d0 rcall .+264 ; 0xfdee + fce6: c8 2f mov r28, r24 + fce8: d0 e0 ldi r29, 0x00 ; 0 + fcea: dc 2f mov r29, r28 + fcec: cc 27 eor r28, r28 savelength = length; desttype = getch(); - fcce: 7f d0 rcall .+254 ; 0xfdce - fcd0: c8 2b or r28, r24 + fcee: 7f d0 rcall .+254 ; 0xfdee + fcf0: c8 2b or r28, r24 // PROGRAM PAGE - we support flash programming only, not EEPROM uint8_t desttype; uint8_t *bufPtr; pagelen_t savelength; GETLENGTH(length); - fcd2: 7d d0 rcall .+250 ; 0xfdce + fcf2: 7d d0 rcall .+250 ; 0xfdee savelength = length; desttype = getch(); - fcd4: c8 2e mov r12, r24 - fcd6: 5e 01 movw r10, r28 - fcd8: 81 2c mov r8, r1 + fcf4: c8 2e mov r12, r24 + fcf6: 5e 01 movw r10, r28 + fcf8: 81 2c mov r8, r1 // read a page worth of contents bufPtr = buff.bptr; do *bufPtr++ = getch(); - fcda: 99 24 eor r9, r9 - fcdc: 93 94 inc r9 - fcde: 77 d0 rcall .+238 ; 0xfdce - fce0: f4 01 movw r30, r8 - fce2: 81 93 st Z+, r24 + fcfa: 99 24 eor r9, r9 + fcfc: 93 94 inc r9 + fcfe: 77 d0 rcall .+238 ; 0xfdee + fd00: f4 01 movw r30, r8 + fd02: 81 93 st Z+, r24 while (--length); - fce4: 4f 01 movw r8, r30 - fce6: f1 e0 ldi r31, 0x01 ; 1 - fce8: af 1a sub r10, r31 - fcea: b1 08 sbc r11, r1 + fd04: 4f 01 movw r8, r30 + fd06: f1 e0 ldi r31, 0x01 ; 1 + fd08: af 1a sub r10, r31 + fd0a: b1 08 sbc r11, r1 // Read command terminator, start reply verifySpace(); - fcec: c1 f7 brne .-16 ; 0xfcde - fcee: 81 d0 rcall .+258 ; 0xfdf2 + fd0c: c1 f7 brne .-16 ; 0xfcfe + fd0e: 81 d0 rcall .+258 ; 0xfe12 * void writebuffer(memtype, buffer, address, length) */ static inline void writebuffer(int8_t memtype, addr16_t mybuff, addr16_t address, pagelen_t len) { switch (memtype) { - fcf0: 85 e4 ldi r24, 0x45 ; 69 - fcf2: c8 12 cpse r12, r24 - fcf4: 12 c0 rjmp .+36 ; 0xfd1a - fcf6: d3 95 inc r29 - fcf8: 48 01 movw r8, r16 - fcfa: a1 2c mov r10, r1 - fcfc: bb 24 eor r11, r11 + fd10: 85 e4 ldi r24, 0x45 ; 69 + fd12: c8 12 cpse r12, r24 + fd14: 12 c0 rjmp .+36 ; 0xfd3a + fd16: d3 95 inc r29 + fd18: 48 01 movw r8, r16 + fd1a: a1 2c mov r10, r1 + fd1c: bb 24 eor r11, r11 case 'E': // EEPROM #if defined(SUPPORT_EEPROM) || defined(BIGBOOT) while(len--) { - fcfe: b3 94 inc r11 - fd00: ac 16 cp r10, r28 - fd02: bd 06 cpc r11, r29 - fd04: 09 f4 brne .+2 ; 0xfd08 + fd1e: b3 94 inc r11 + fd20: ac 16 cp r10, r28 + fd22: bd 06 cpc r11, r29 + fd24: 09 f4 brne .+2 ; 0xfd28 eeprom_write_byte((address.bptr++), *(mybuff.bptr++)); - fd06: 59 c0 rjmp .+178 ; 0xfdba - fd08: f5 01 movw r30, r10 - fd0a: 61 91 ld r22, Z+ - fd0c: 5f 01 movw r10, r30 - fd0e: c4 01 movw r24, r8 - fd10: 8d d0 rcall .+282 ; 0xfe2c - fd12: ff ef ldi r31, 0xFF ; 255 - fd14: 8f 1a sub r8, r31 - fd16: 9f 0a sbc r9, r31 - fd18: f3 cf rjmp .-26 ; 0xfd00 - * Start the page erase and wait for it to finish. There - * used to be code to do this while receiving the data over - * the serial link, but the performance improvement was slight, + fd26: 59 c0 rjmp .+178 ; 0xfdda + fd28: f5 01 movw r30, r10 + fd2a: 61 91 ld r22, Z+ + fd2c: 5f 01 movw r10, r30 + fd2e: c4 01 movw r24, r8 + fd30: 97 d0 rcall .+302 ; 0xfe60 + fd32: ff ef ldi r31, 0xFF ; 255 + fd34: 8f 1a sub r8, r31 + fd36: 9f 0a sbc r9, r31 + fd38: f3 cf rjmp .-26 ; 0xfd20 * and we needed the space back. */ +#ifdef FOURPAGEERASE + if ((address.bytes[0] & ((SPM_PAGESIZE<<2)-1))==0) { +#endif __boot_page_erase_short(address.word); - fd1a: 83 e0 ldi r24, 0x03 ; 3 - fd1c: f8 01 movw r30, r16 - fd1e: 87 bf out 0x37, r24 ; 55 - fd20: e8 95 spm + fd3a: 83 e0 ldi r24, 0x03 ; 3 + fd3c: f8 01 movw r30, r16 + fd3e: 87 bf out 0x37, r24 ; 55 + fd40: e8 95 spm boot_spm_busy_wait(); - fd22: 07 b6 in r0, 0x37 ; 55 - fd24: 00 fc sbrc r0, 0 - fd26: fd cf rjmp .-6 ; 0xfd22 - fd28: a0 e0 ldi r26, 0x00 ; 0 - fd2a: b1 e0 ldi r27, 0x01 ; 1 - fd2c: f8 01 movw r30, r16 + fd42: 07 b6 in r0, 0x37 ; 55 + fd44: 00 fc sbrc r0, 0 + fd46: fd cf rjmp .-6 ; 0xfd42 + fd48: a0 e0 ldi r26, 0x00 ; 0 + fd4a: b1 e0 ldi r27, 0x01 ; 1 + fd4c: f8 01 movw r30, r16 /* * Copy data from the buffer into the flash write buffer. */ do { __boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++)); - fd2e: 8d 91 ld r24, X+ - fd30: 9d 91 ld r25, X+ - fd32: 0c 01 movw r0, r24 - fd34: f7 be out 0x37, r15 ; 55 - fd36: e8 95 spm + fd4e: 8d 91 ld r24, X+ + fd50: 9d 91 ld r25, X+ + fd52: 0c 01 movw r0, r24 + fd54: f7 be out 0x37, r15 ; 55 + fd56: e8 95 spm addrPtr += 2; } while (len -= 2); - fd38: 11 24 eor r1, r1 - fd3a: 22 97 sbiw r28, 0x02 ; 2 - fd3c: 32 96 adiw r30, 0x02 ; 2 - fd3e: 20 97 sbiw r28, 0x00 ; 0 + fd58: 11 24 eor r1, r1 + fd5a: 22 97 sbiw r28, 0x02 ; 2 + fd5c: 32 96 adiw r30, 0x02 ; 2 + fd5e: 20 97 sbiw r28, 0x00 ; 0 /* * Actually Write the buffer to flash (and wait for it to finish.) */ __boot_page_write_short(address.word); - fd40: b1 f7 brne .-20 ; 0xfd2e - fd42: f8 01 movw r30, r16 + fd60: b1 f7 brne .-20 ; 0xfd4e + fd62: f8 01 movw r30, r16 boot_spm_busy_wait(); - fd44: e7 be out 0x37, r14 ; 55 - fd46: e8 95 spm + fd64: e7 be out 0x37, r14 ; 55 + fd66: e8 95 spm #if defined(RWWSRE) // Reenable read access to flash __boot_rww_enable_short(); - fd48: 07 b6 in r0, 0x37 ; 55 - fd4a: 00 fc sbrc r0, 0 - fd4c: fd cf rjmp .-6 ; 0xfd48 + fd68: 07 b6 in r0, 0x37 ; 55 + fd6a: 00 fc sbrc r0, 0 + fd6c: fd cf rjmp .-6 ; 0xfd68 writebuffer(desttype, buff, address, savelength); } /* Read memory block mode, length is big endian. */ else if(ch == STK_READ_PAGE) { - fd4e: d7 be out 0x37, r13 ; 55 - fd50: e8 95 spm + fd6e: d7 be out 0x37, r13 ; 55 + fd70: e8 95 spm uint8_t desttype; GETLENGTH(length); - fd52: 33 c0 rjmp .+102 ; 0xfdba - fd54: 84 37 cpi r24, 0x74 ; 116 - fd56: 19 f5 brne .+70 ; 0xfd9e - fd58: 3a d0 rcall .+116 ; 0xfdce - fd5a: c8 2f mov r28, r24 - fd5c: d0 e0 ldi r29, 0x00 ; 0 - fd5e: dc 2f mov r29, r28 - fd60: cc 27 eor r28, r28 + fd72: 33 c0 rjmp .+102 ; 0xfdda + fd74: 84 37 cpi r24, 0x74 ; 116 + fd76: 19 f5 brne .+70 ; 0xfdbe + fd78: 3a d0 rcall .+116 ; 0xfdee + fd7a: c8 2f mov r28, r24 + fd7c: d0 e0 ldi r29, 0x00 ; 0 + fd7e: dc 2f mov r29, r28 + fd80: cc 27 eor r28, r28 desttype = getch(); - fd62: 35 d0 rcall .+106 ; 0xfdce - fd64: 5e 01 movw r10, r28 - fd66: a8 2a or r10, r24 + fd82: 35 d0 rcall .+106 ; 0xfdee + fd84: 5e 01 movw r10, r28 + fd86: a8 2a or r10, r24 verifySpace(); - fd68: 32 d0 rcall .+100 ; 0xfdce - fd6a: 98 2e mov r9, r24 + fd88: 32 d0 rcall .+100 ; 0xfdee + fd8a: 98 2e mov r9, r24 static inline void read_mem(uint8_t memtype, addr16_t address, pagelen_t length) { uint8_t ch; switch (memtype) { - fd6c: 42 d0 rcall .+132 ; 0xfdf2 - fd6e: e8 01 movw r28, r16 - fd70: f5 e4 ldi r31, 0x45 ; 69 + fd8c: 42 d0 rcall .+132 ; 0xfe12 + fd8e: e8 01 movw r28, r16 + fd90: f5 e4 ldi r31, 0x45 ; 69 #if defined(SUPPORT_EEPROM) || defined(BIGBOOT) case 'E': // EEPROM do { putch(eeprom_read_byte((address.bptr++))); - fd72: 9f 12 cpse r9, r31 - fd74: 0b c0 rjmp .+22 ; 0xfd8c - fd76: ce 01 movw r24, r28 - fd78: 51 d0 rcall .+162 ; 0xfe1c + fd92: 9f 12 cpse r9, r31 + fd94: 0b c0 rjmp .+22 ; 0xfdac + fd96: ce 01 movw r24, r28 + fd98: 5b d0 rcall .+182 ; 0xfe50 } while (--length); - fd7a: 22 d0 rcall .+68 ; 0xfdc0 - fd7c: 81 e0 ldi r24, 0x01 ; 1 - fd7e: a8 1a sub r10, r24 - fd80: b1 08 sbc r11, r1 - fd82: 21 96 adiw r28, 0x01 ; 1 - fd84: a1 14 cp r10, r1 - fd86: b1 04 cpc r11, r1 + fd9a: 22 d0 rcall .+68 ; 0xfde0 + fd9c: 81 e0 ldi r24, 0x01 ; 1 + fd9e: a8 1a sub r10, r24 + fda0: b1 08 sbc r11, r1 + fda2: 21 96 adiw r28, 0x01 ; 1 + fda4: a1 14 cp r10, r1 + fda6: b1 04 cpc r11, r1 // while (--length); // read a Flash and increment the address (may increment RAMPZ) __asm__ ("elpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address)); #else // read a Flash byte and increment the address __asm__ ("lpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address)); - fd88: b1 f7 brne .-20 ; 0xfd76 - fd8a: 17 c0 rjmp .+46 ; 0xfdba + fda8: b1 f7 brne .-20 ; 0xfd96 + fdaa: 17 c0 rjmp .+46 ; 0xfdda #endif putch(ch); - fd8c: fe 01 movw r30, r28 - fd8e: 85 91 lpm r24, Z+ + fdac: fe 01 movw r30, r28 + fdae: 85 91 lpm r24, Z+ } while (--length); - fd90: ef 01 movw r28, r30 - fd92: 16 d0 rcall .+44 ; 0xfdc0 - fd94: e1 e0 ldi r30, 0x01 ; 1 - fd96: ae 1a sub r10, r30 - fd98: b1 08 sbc r11, r1 + fdb0: ef 01 movw r28, r30 + fdb2: 16 d0 rcall .+44 ; 0xfde0 + fdb4: e1 e0 ldi r30, 0x01 ; 1 + fdb6: ae 1a sub r10, r30 + fdb8: b1 08 sbc r11, r1 read_mem(desttype, address, length); } /* Get device signature bytes */ else if(ch == STK_READ_SIGN) { - fd9a: c1 f7 brne .-16 ; 0xfd8c - fd9c: 0e c0 rjmp .+28 ; 0xfdba + fdba: c1 f7 brne .-16 ; 0xfdac + fdbc: 0e c0 rjmp .+28 ; 0xfdda // READ SIGN - return what Avrdude wants to hear verifySpace(); - fd9e: 85 37 cpi r24, 0x75 ; 117 - fda0: 39 f4 brne .+14 ; 0xfdb0 + fdbe: 85 37 cpi r24, 0x75 ; 117 + fdc0: 39 f4 brne .+14 ; 0xfdd0 putch(SIGNATURE_0); - fda2: 27 d0 rcall .+78 ; 0xfdf2 - fda4: 8e e1 ldi r24, 0x1E ; 30 - fda6: 0c d0 rcall .+24 ; 0xfdc0 + fdc2: 27 d0 rcall .+78 ; 0xfe12 + fdc4: 8e e1 ldi r24, 0x1E ; 30 + fdc6: 0c d0 rcall .+24 ; 0xfde0 putch(SIGNATURE_1); - fda8: 86 e9 ldi r24, 0x96 ; 150 - fdaa: 0a d0 rcall .+20 ; 0xfdc0 - fdac: 8a e0 ldi r24, 0x0A ; 10 + fdc8: 86 e9 ldi r24, 0x96 ; 150 + fdca: 0a d0 rcall .+20 ; 0xfde0 + fdcc: 8a e0 ldi r24, 0x0A ; 10 putch(SIGNATURE_2); - fdae: 6d cf rjmp .-294 ; 0xfc8a - fdb0: 81 35 cpi r24, 0x51 ; 81 + fdce: 6d cf rjmp .-294 ; 0xfcaa + fdd0: 81 35 cpi r24, 0x51 ; 81 } else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */ - fdb2: 11 f4 brne .+4 ; 0xfdb8 - fdb4: 88 e0 ldi r24, 0x08 ; 8 + fdd2: 11 f4 brne .+4 ; 0xfdd8 + fdd4: 88 e0 ldi r24, 0x08 ; 8 // Adaboot no-wait mod watchdogConfig(WATCHDOG_16MS); - fdb6: 17 d0 rcall .+46 ; 0xfde6 - fdb8: 1c d0 rcall .+56 ; 0xfdf2 - fdba: 80 e1 ldi r24, 0x10 ; 16 + fdd6: 17 d0 rcall .+46 ; 0xfe06 + fdd8: 1c d0 rcall .+56 ; 0xfe12 + fdda: 80 e1 ldi r24, 0x10 ; 16 verifySpace(); } else { // This covers the response to commands like STK_ENTER_PROGMODE verifySpace(); - fdbc: 01 d0 rcall .+2 ; 0xfdc0 - fdbe: 58 cf rjmp .-336 ; 0xfc70 + fddc: 01 d0 rcall .+2 ; 0xfde0 + fdde: 58 cf rjmp .-336 ; 0xfc90 -0000fdc0 : +0000fde0 : } putch(STK_OK); - fdc0: 90 91 c0 00 lds r25, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - fdc4: 95 ff sbrs r25, 5 + fde0: 90 91 c0 00 lds r25, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + fde4: 95 ff sbrs r25, 5 } - fdc6: fc cf rjmp .-8 ; 0xfdc0 -} + fde6: fc cf rjmp .-8 ; 0xfde0 + while (!(UART_SRA & _BV(UDRE0))) { /* Spin */ } + #else + while (!(LINSIR & _BV(LTXOK))) { /* Spin */ } + #endif -void putch(char ch) { -#ifndef SOFT_UART - while (!(UART_SRA & _BV(UDRE0))); UART_UDR = ch; - fdc8: 80 93 c6 00 sts 0x00C6, r24 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> - fdcc: 08 95 ret + fde8: 80 93 c6 00 sts 0x00C6, r24 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> + fdec: 08 95 ret -0000fdce : - [uartBit] "I" (UART_RX_BIT) +0000fdee : : "r25" ); #else - while(!(UART_SRA & _BV(RXC0))) - fdce: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - fdd2: 87 ff sbrs r24, 7 - fdd4: fc cf rjmp .-8 ; 0xfdce - ; +#ifndef LIN_UART + while(!(UART_SRA & _BV(RXC0))) { /* Spin */ } + fdee: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + fdf2: 87 ff sbrs r24, 7 + fdf4: fc cf rjmp .-8 ; 0xfdee if (!(UART_SRA & _BV(FE0))) { - fdd6: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - fdda: 84 fd sbrc r24, 4 - fddc: 01 c0 rjmp .+2 ; 0xfde0 + fdf6: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> + fdfa: 84 fd sbrc r24, 4 + fdfc: 01 c0 rjmp .+2 ; 0xfe00 } #endif // Watchdog functions. These are only safe with interrupts turned off. void watchdogReset() { __asm__ __volatile__ ( - fdde: a8 95 wdr + fdfe: a8 95 wdr * don't care that an invalid char is returned...) */ watchdogReset(); } ch = UART_UDR; - fde0: 80 91 c6 00 lds r24, 0x00C6 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> + fe00: 80 91 c6 00 lds r24, 0x00C6 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> LED_PIN |= _BV(LED); #endif #endif return ch; } - fde4: 08 95 ret + fe04: 08 95 ret -0000fde6 : - "wdr\n" - ); +0000fe06 : } void watchdogConfig(uint8_t x) { +#ifdef WDCE //does it have a Watchdog Change Enable? + #ifdef WDTCSR WDTCSR = _BV(WDCE) | _BV(WDE); - fde6: e0 e6 ldi r30, 0x60 ; 96 - fde8: f0 e0 ldi r31, 0x00 ; 0 - fdea: 98 e1 ldi r25, 0x18 ; 24 - fdec: 90 83 st Z, r25 - WDTCSR = x; - fdee: 80 83 st Z, r24 - fdf0: 08 95 ret + fe06: e0 e6 ldi r30, 0x60 ; 96 + fe08: f0 e0 ldi r31, 0x00 ; 0 + fe0a: 98 e1 ldi r25, 0x18 ; 24 + fe0c: 90 83 st Z, r25 +#else //then it must be one of those newfangled ones that use CCP + CCP=0xD8; //so write this magic number to CCP +#endif -0000fdf2 : +#ifdef WDTCSR + WDTCSR = x; + fe0e: 80 83 st Z, r24 + fe10: 08 95 ret + +0000fe12 : do getch(); while (--count); verifySpace(); } void verifySpace() { if (getch() != CRC_EOP) { - fdf2: ed df rcall .-38 ; 0xfdce - fdf4: 80 32 cpi r24, 0x20 ; 32 - fdf6: 19 f0 breq .+6 ; 0xfdfe + fe12: ed df rcall .-38 ; 0xfdee + fe14: 80 32 cpi r24, 0x20 ; 32 + fe16: 19 f0 breq .+6 ; 0xfe1e watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - fdf8: 88 e0 ldi r24, 0x08 ; 8 - fdfa: f5 df rcall .-22 ; 0xfde6 - fdfc: ff cf rjmp .-2 ; 0xfdfc + fe18: 88 e0 ldi r24, 0x08 ; 8 + fe1a: f5 df rcall .-22 ; 0xfe06 + fe1c: ff cf rjmp .-2 ; 0xfe1c while (1) // and busy-loop so that WD causes ; // a reset and app start. } putch(STK_INSYNC); - fdfe: 84 e1 ldi r24, 0x14 ; 20 - fe00: df cf rjmp .-66 ; 0xfdc0 + fe1e: 84 e1 ldi r24, 0x14 ; 20 + fe20: df cf rjmp .-66 ; 0xfde0 -0000fe02 : +0000fe22 : ::[count] "M" (UART_B_VALUE) ); } #endif void getNch(uint8_t count) { - fe02: cf 93 push r28 - fe04: c8 2f mov r28, r24 + fe22: cf 93 push r28 + fe24: c8 2f mov r28, r24 do getch(); while (--count); - fe06: e3 df rcall .-58 ; 0xfdce - fe08: c1 50 subi r28, 0x01 ; 1 - fe0a: e9 f7 brne .-6 ; 0xfe06 + fe26: e3 df rcall .-58 ; 0xfdee + fe28: c1 50 subi r28, 0x01 ; 1 + fe2a: e9 f7 brne .-6 ; 0xfe26 verifySpace(); - fe0c: cf 91 pop r28 - fe0e: f1 cf rjmp .-30 ; 0xfdf2 +} + fe2c: cf 91 pop r28 +} +#endif -0000fe10 : +void getNch(uint8_t count) { + do getch(); while (--count); + verifySpace(); + fe2e: f1 cf rjmp .-30 ; 0xfe12 -void appStart(uint8_t rstFlags) { - // save the reset flags in the designated register - // This can be saved in a main program by putting code in .init0 (which - // executes before normal c init code) to save R2 to a global variable. - __asm__ __volatile__ ("mov r2, %0\n" :: "r" (rstFlags)); - fe10: 28 2e mov r2, r24 +0000fe30 : + fe30: fc 01 movw r30, r24 + * data=0 in WRITE + */ +static void do_spm(uint16_t address, uint8_t command, uint16_t data) __attribute__ ((used)); +static void do_spm(uint16_t address, uint8_t command, uint16_t data) { + // Do spm stuff + asm volatile ( + fe32: 0a 01 movw r0, r20 + fe34: 67 bf out 0x37, r22 ; 55 + fe36: e8 95 spm + fe38: 11 24 eor r1, r1 + fe3a: 07 b6 in r0, 0x37 ; 55 + ); - watchdogConfig(WATCHDOG_OFF); - fe12: 80 e0 ldi r24, 0x00 ; 0 - fe14: e8 df rcall .-48 ; 0xfde6 - fe16: e0 e0 ldi r30, 0x00 ; 0 - // Note that appstart_vec is defined so that this works with either - // real or virtual boot partitions. - __asm__ __volatile__ ( - fe18: ff 27 eor r31, r31 - fe1a: 09 94 ijmp + // wait for spm to complete + // it doesn't have much sense for __BOOT_PAGE_FILL, + // but it doesn't hurt and saves some bytes on 'if' + boot_spm_busy_wait(); + fe3c: 00 fc sbrc r0, 0 + fe3e: fd cf rjmp .-6 ; 0xfe3a + fe40: 66 70 andi r22, 0x06 ; 6 +#if defined(RWWSRE) + // this 'if' condition should be: (command == __BOOT_PAGE_WRITE || command == __BOOT_PAGE_ERASE)... + // but it's tweaked a little assuming that in every command we are interested in here, there + // must be also SELFPRGEN set. If we skip checking this bit, we save here 4B + if ((command & (_BV(PGWRT)|_BV(PGERS))) && (data == 0) ) { + fe42: 29 f0 breq .+10 ; 0xfe4e + fe44: 45 2b or r20, r21 + fe46: 19 f4 brne .+6 ; 0xfe4e + fe48: 81 e1 ldi r24, 0x11 ; 17 + // Reenable read access to flash + __boot_rww_enable_short(); + fe4a: 87 bf out 0x37, r24 ; 55 + fe4c: e8 95 spm + fe4e: 08 95 ret -0000fe1c : - fe1c: f9 99 sbic 0x1f, 1 ; 31 - fe1e: fe cf rjmp .-4 ; 0xfe1c - fe20: 92 bd out 0x22, r25 ; 34 - fe22: 81 bd out 0x21, r24 ; 33 - fe24: f8 9a sbi 0x1f, 0 ; 31 - fe26: 99 27 eor r25, r25 - fe28: 80 b5 in r24, 0x20 ; 32 - fe2a: 08 95 ret +0000fe50 : + fe50: f9 99 sbic 0x1f, 1 ; 31 + fe52: fe cf rjmp .-4 ; 0xfe50 + fe54: 92 bd out 0x22, r25 ; 34 + fe56: 81 bd out 0x21, r24 ; 33 + fe58: f8 9a sbi 0x1f, 0 ; 31 + fe5a: 99 27 eor r25, r25 + fe5c: 80 b5 in r24, 0x20 ; 32 + fe5e: 08 95 ret -0000fe2c : - fe2c: 26 2f mov r18, r22 +0000fe60 : + fe60: 26 2f mov r18, r22 -0000fe2e : - fe2e: f9 99 sbic 0x1f, 1 ; 31 - fe30: fe cf rjmp .-4 ; 0xfe2e - fe32: 1f ba out 0x1f, r1 ; 31 - fe34: 92 bd out 0x22, r25 ; 34 - fe36: 81 bd out 0x21, r24 ; 33 - fe38: 20 bd out 0x20, r18 ; 32 - fe3a: 0f b6 in r0, 0x3f ; 63 - fe3c: f8 94 cli - fe3e: fa 9a sbi 0x1f, 2 ; 31 - fe40: f9 9a sbi 0x1f, 1 ; 31 - fe42: 0f be out 0x3f, r0 ; 63 - fe44: 01 96 adiw r24, 0x01 ; 1 - fe46: 08 95 ret +0000fe62 : + fe62: f9 99 sbic 0x1f, 1 ; 31 + fe64: fe cf rjmp .-4 ; 0xfe62 + fe66: 1f ba out 0x1f, r1 ; 31 + fe68: 92 bd out 0x22, r25 ; 34 + fe6a: 81 bd out 0x21, r24 ; 33 + fe6c: 20 bd out 0x20, r18 ; 32 + fe6e: 0f b6 in r0, 0x3f ; 63 + fe70: f8 94 cli + fe72: fa 9a sbi 0x1f, 2 ; 31 + fe74: f9 9a sbi 0x1f, 1 ; 31 + fe76: 0f be out 0x3f, r0 ; 63 + fe78: 01 96 adiw r24, 0x01 ; 1 + fe7a: 08 95 ret diff --git a/optiboot/bootloaders/optiboot/optiboot_diecimila.lst b/optiboot/bootloaders/optiboot/optiboot_diecimila.lst deleted file mode 100644 index 5cb1e03..0000000 --- a/optiboot/bootloaders/optiboot/optiboot_diecimila.lst +++ /dev/null @@ -1,584 +0,0 @@ - -optiboot_atmega168.elf: file format elf32-avr - -Sections: -Idx Name Size VMA LMA File off Algn - 0 .data 00000000 00800100 00003fbe 00000252 2**0 - CONTENTS, ALLOC, LOAD, DATA - 1 .text 000001be 00003e00 00003e00 00000094 2**1 - CONTENTS, ALLOC, LOAD, READONLY, CODE - 2 .version 00000002 00003ffe 00003ffe 00000252 2**0 - CONTENTS, ALLOC, LOAD, READONLY, DATA - 3 .comment 0000002f 00000000 00000000 00000254 2**0 - CONTENTS, READONLY - 4 .debug_aranges 00000028 00000000 00000000 00000283 2**0 - CONTENTS, READONLY, DEBUGGING - 5 .debug_info 000005c8 00000000 00000000 000002ab 2**0 - CONTENTS, READONLY, DEBUGGING - 6 .debug_abbrev 00000282 00000000 00000000 00000873 2**0 - CONTENTS, READONLY, DEBUGGING - 7 .debug_line 000002f9 00000000 00000000 00000af5 2**0 - CONTENTS, READONLY, DEBUGGING - 8 .debug_frame 0000008c 00000000 00000000 00000df0 2**2 - CONTENTS, READONLY, DEBUGGING - 9 .debug_str 000001fa 00000000 00000000 00000e7c 2**0 - CONTENTS, READONLY, DEBUGGING - 10 .debug_loc 00000331 00000000 00000000 00001076 2**0 - CONTENTS, READONLY, DEBUGGING - 11 .debug_ranges 00000060 00000000 00000000 000013a7 2**0 - CONTENTS, READONLY, DEBUGGING - -Disassembly of section .text: - -00003e00
: - // SP points to RAMEND - // r1 contains zero - // - // If not, uncomment the following instructions: - // cli(); - asm volatile ("clr __zero_reg__"); - 3e00: 11 24 eor r1, r1 - * - * Code by MarkG55 - * see discusion in https://github.com/Optiboot/optiboot/issues/97 - */ -#if !defined(__AVR_ATmega16__) - ch = MCUSR; - 3e02: 84 b7 in r24, 0x34 ; 52 -#else - ch = MCUCSR; -#endif - // Skip all logic and run bootloader if MCUSR is cleared (application request) - if (ch != 0) { - 3e04: 88 23 and r24, r24 - 3e06: 49 f0 breq .+18 ; 0x3e1a - * 2. we clear WDRF if it's set with EXTRF to avoid loops - * One problematic scenario: broken application code sets watchdog timer - * without clearing MCUSR before and triggers it quickly. But it's - * recoverable by power-on with pushed reset button. - */ - if ((ch & (_BV(WDRF) | _BV(EXTRF))) != _BV(EXTRF)) { - 3e08: 98 2f mov r25, r24 - 3e0a: 9a 70 andi r25, 0x0A ; 10 - 3e0c: 92 30 cpi r25, 0x02 ; 2 - 3e0e: 29 f0 breq .+10 ; 0x3e1a - if (ch & _BV(EXTRF)) { - 3e10: 81 ff sbrs r24, 1 - 3e12: 02 c0 rjmp .+4 ; 0x3e18 - * prevent entering bootloader. - * '&' operation is skipped to spare few bytes as bits in MCUSR - * can only be cleared. - */ -#if !defined(__AVR_ATmega16__) - MCUSR = ~(_BV(WDRF)); - 3e14: 97 ef ldi r25, 0xF7 ; 247 - 3e16: 94 bf out 0x34, r25 ; 52 -#else - MCUCSR = ~(_BV(WDRF)); -#endif - } - appStart(ch); - 3e18: cc d0 rcall .+408 ; 0x3fb2 - } - } - -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - 3e1a: 85 e0 ldi r24, 0x05 ; 5 - 3e1c: 80 93 81 00 sts 0x0081, r24 ; 0x800081 <__TEXT_REGION_LENGTH__+0x7e0081> - UCSRA = _BV(U2X); //Double speed mode USART - UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx - UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 - UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); -#else - UART_SRA = _BV(U2X0); //Double speed mode USART0 - 3e20: 82 e0 ldi r24, 0x02 ; 2 - 3e22: 80 93 c0 00 sts 0x00C0, r24 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - UART_SRB = _BV(RXEN0) | _BV(TXEN0); - 3e26: 88 e1 ldi r24, 0x18 ; 24 - 3e28: 80 93 c1 00 sts 0x00C1, r24 ; 0x8000c1 <__TEXT_REGION_LENGTH__+0x7e00c1> - UART_SRC = _BV(UCSZ00) | _BV(UCSZ01); - 3e2c: 86 e0 ldi r24, 0x06 ; 6 - 3e2e: 80 93 c2 00 sts 0x00C2, r24 ; 0x8000c2 <__TEXT_REGION_LENGTH__+0x7e00c2> - UART_SRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 3e32: 80 e1 ldi r24, 0x10 ; 16 - 3e34: 80 93 c4 00 sts 0x00C4, r24 ; 0x8000c4 <__TEXT_REGION_LENGTH__+0x7e00c4> -#endif -#endif - - // Set up watchdog to trigger after 1s - watchdogConfig(WATCHDOG_1S); - 3e38: 8e e0 ldi r24, 0x0E ; 14 - 3e3a: a6 d0 rcall .+332 ; 0x3f88 - -#if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH) || defined(LED_START_ON) - /* Set LED pin as output */ - LED_DDR |= _BV(LED); - 3e3c: 25 9a sbi 0x04, 5 ; 4 - 3e3e: 86 e0 ldi r24, 0x06 ; 6 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e40: 20 e3 ldi r18, 0x30 ; 48 - 3e42: 3c ef ldi r19, 0xFC ; 252 - TIFR1 = _BV(TOV1); - 3e44: 91 e0 ldi r25, 0x01 ; 1 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e46: 30 93 85 00 sts 0x0085, r19 ; 0x800085 <__TEXT_REGION_LENGTH__+0x7e0085> - 3e4a: 20 93 84 00 sts 0x0084, r18 ; 0x800084 <__TEXT_REGION_LENGTH__+0x7e0084> - TIFR1 = _BV(TOV1); - 3e4e: 96 bb out 0x16, r25 ; 22 - while(!(TIFR1 & _BV(TOV1))); - 3e50: b0 9b sbis 0x16, 0 ; 22 - 3e52: fe cf rjmp .-4 ; 0x3e50 -#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega16__) - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); - 3e54: 1d 9a sbi 0x03, 5 ; 3 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3e56: a8 95 wdr - * While in theory, the STK500 initial commands would be buffered - * by the UART hardware, avrdude sends several attempts in rather - * quick succession, some of which will be lost and cause us to - * get out of sync. So if we see any data; stop blinking. - */ - if (UART_SRA & _BV(RXC0)) - 3e58: 40 91 c0 00 lds r20, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - 3e5c: 47 fd sbrc r20, 7 - 3e5e: 02 c0 rjmp .+4 ; 0x3e64 - 3e60: 81 50 subi r24, 0x01 ; 1 -#else -// This doesn't seem to work? -// if ((UART_PIN & (1< - - /* - * Copy data from the buffer into the flash write buffer. - */ - do { - __boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++)); - 3e64: ee 24 eor r14, r14 - 3e66: e3 94 inc r14 - } while (len -= 2); - - /* - * Actually Write the buffer to flash (and wait for it to finish.) - */ - __boot_page_write_short(address.word); - 3e68: 95 e0 ldi r25, 0x05 ; 5 - 3e6a: d9 2e mov r13, r25 - boot_spm_busy_wait(); -#if defined(RWWSRE) - // Reenable read access to flash - __boot_rww_enable_short(); - 3e6c: 21 e1 ldi r18, 0x11 ; 17 -#endif - - /* Forever loop: exits by causing WDT reset */ - for (;;) { - /* get character from UART */ - ch = getch(); - 3e6e: c2 2e mov r12, r18 - - if(ch == STK_GET_PARAMETER) { - 3e70: 7f d0 rcall .+254 ; 0x3f70 - unsigned char which = getch(); - 3e72: 81 34 cpi r24, 0x41 ; 65 - 3e74: 61 f4 brne .+24 ; 0x3e8e - 3e76: 7c d0 rcall .+248 ; 0x3f70 - verifySpace(); - 3e78: 18 2f mov r17, r24 - 3e7a: 8c d0 rcall .+280 ; 0x3f94 - /* - * Send optiboot version as "SW version" - * Note that the references to memory are optimized away. - */ - if (which == STK_SW_MINOR) { - 3e7c: 12 38 cpi r17, 0x82 ; 130 - 3e7e: e9 f0 breq .+58 ; 0x3eba - putch(optiboot_version & 0xFF); - } else if (which == STK_SW_MAJOR) { - 3e80: 11 38 cpi r17, 0x81 ; 129 - putch(optiboot_version >> 8); - 3e82: 11 f4 brne .+4 ; 0x3e88 - 3e84: 87 e0 ldi r24, 0x07 ; 7 - } else { - /* - * GET PARAMETER returns a generic 0x03 reply for - * other parameters - enough to keep Avrdude happy - */ - putch(0x03); - 3e86: 01 c0 rjmp .+2 ; 0x3e8a - 3e88: 83 e0 ldi r24, 0x03 ; 3 - 3e8a: 6b d0 rcall .+214 ; 0x3f62 - 3e8c: 67 c0 rjmp .+206 ; 0x3f5c - } - } - else if(ch == STK_SET_DEVICE) { - 3e8e: 82 34 cpi r24, 0x42 ; 66 - // SET DEVICE is ignored - getNch(20); - 3e90: 11 f4 brne .+4 ; 0x3e96 - 3e92: 84 e1 ldi r24, 0x14 ; 20 - } - else if(ch == STK_SET_DEVICE_EXT) { - 3e94: 03 c0 rjmp .+6 ; 0x3e9c - // SET DEVICE EXT is ignored - getNch(5); - 3e96: 85 34 cpi r24, 0x45 ; 69 - 3e98: 19 f4 brne .+6 ; 0x3ea0 - 3e9a: 85 e0 ldi r24, 0x05 ; 5 - } - else if(ch == STK_LOAD_ADDRESS) { - 3e9c: 83 d0 rcall .+262 ; 0x3fa4 - 3e9e: 5e c0 rjmp .+188 ; 0x3f5c - // LOAD ADDRESS - address.bytes[0] = getch(); - 3ea0: 85 35 cpi r24, 0x55 ; 85 - 3ea2: 39 f4 brne .+14 ; 0x3eb2 - 3ea4: 65 d0 rcall .+202 ; 0x3f70 - address.bytes[1] = getch(); - 3ea6: c8 2f mov r28, r24 - 3ea8: 63 d0 rcall .+198 ; 0x3f70 - } - else { - RAMPZ &= 0xFE; - } -#endif - address.word *= 2; // Convert from word address to byte address - 3eaa: d8 2f mov r29, r24 - 3eac: cc 0f add r28, r28 - 3eae: dd 1f adc r29, r29 - verifySpace(); - } - else if(ch == STK_UNIVERSAL) { - 3eb0: 54 c0 rjmp .+168 ; 0x3f5a - getNch(3); - putch(0x00); - } -#else - // UNIVERSAL command is ignored - getNch(4); - 3eb2: 86 35 cpi r24, 0x56 ; 86 - 3eb4: 21 f4 brne .+8 ; 0x3ebe - putch(0x00); - 3eb6: 84 e0 ldi r24, 0x04 ; 4 - 3eb8: 75 d0 rcall .+234 ; 0x3fa4 -#endif - } - /* Write memory, length is big endian and is in bytes */ - else if(ch == STK_PROG_PAGE) { - 3eba: 80 e0 ldi r24, 0x00 ; 0 - 3ebc: e6 cf rjmp .-52 ; 0x3e8a - // PROGRAM PAGE - we support flash programming only, not EEPROM - uint8_t desttype; - uint8_t *bufPtr; - pagelen_t savelength; - - GETLENGTH(length); - 3ebe: 84 36 cpi r24, 0x64 ; 100 - 3ec0: 09 f0 breq .+2 ; 0x3ec4 - 3ec2: 2e c0 rjmp .+92 ; 0x3f20 - 3ec4: 55 d0 rcall .+170 ; 0x3f70 - savelength = length; - desttype = getch(); - 3ec6: 54 d0 rcall .+168 ; 0x3f70 - 3ec8: f8 2e mov r15, r24 - 3eca: 52 d0 rcall .+164 ; 0x3f70 - 3ecc: b8 2e mov r11, r24 - 3ece: 00 e0 ldi r16, 0x00 ; 0 - - // read a page worth of contents - bufPtr = buff.bptr; - do *bufPtr++ = getch(); - 3ed0: 11 e0 ldi r17, 0x01 ; 1 - 3ed2: 4e d0 rcall .+156 ; 0x3f70 - 3ed4: f8 01 movw r30, r16 - 3ed6: 81 93 st Z+, r24 - 3ed8: 8f 01 movw r16, r30 - while (--length); - 3eda: fe 12 cpse r15, r30 - 3edc: fa cf rjmp .-12 ; 0x3ed2 - - // Read command terminator, start reply - verifySpace(); - 3ede: 5a d0 rcall .+180 ; 0x3f94 - 3ee0: f5 e4 ldi r31, 0x45 ; 69 - * void writebuffer(memtype, buffer, address, length) - */ -static inline void writebuffer(int8_t memtype, addr16_t mybuff, - addr16_t address, pagelen_t len) -{ - switch (memtype) { - 3ee2: bf 12 cpse r11, r31 - 3ee4: 01 c0 rjmp .+2 ; 0x3ee8 - 3ee6: ff cf rjmp .-2 ; 0x3ee6 - 3ee8: 83 e0 ldi r24, 0x03 ; 3 - * Start the page erase and wait for it to finish. There - * used to be code to do this while receiving the data over - * the serial link, but the performance improvement was slight, - * and we needed the space back. - */ - __boot_page_erase_short(address.word); - 3eea: fe 01 movw r30, r28 - 3eec: 87 bf out 0x37, r24 ; 55 - 3eee: e8 95 spm - 3ef0: 07 b6 in r0, 0x37 ; 55 - boot_spm_busy_wait(); - 3ef2: 00 fc sbrc r0, 0 - 3ef4: fd cf rjmp .-6 ; 0x3ef0 - 3ef6: a0 e0 ldi r26, 0x00 ; 0 - 3ef8: b1 e0 ldi r27, 0x01 ; 1 - 3efa: fe 01 movw r30, r28 - 3efc: 8d 91 ld r24, X+ - - /* - * Copy data from the buffer into the flash write buffer. - */ - do { - __boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++)); - 3efe: 9d 91 ld r25, X+ - 3f00: 0c 01 movw r0, r24 - 3f02: e7 be out 0x37, r14 ; 55 - 3f04: e8 95 spm - 3f06: 11 24 eor r1, r1 - 3f08: 32 96 adiw r30, 0x02 ; 2 - addrPtr += 2; - } while (len -= 2); - 3f0a: fa 12 cpse r15, r26 - - /* - * Actually Write the buffer to flash (and wait for it to finish.) - */ - __boot_page_write_short(address.word); - 3f0c: f7 cf rjmp .-18 ; 0x3efc - 3f0e: fe 01 movw r30, r28 - boot_spm_busy_wait(); - 3f10: d7 be out 0x37, r13 ; 55 - 3f12: e8 95 spm -#if defined(RWWSRE) - // Reenable read access to flash - __boot_rww_enable_short(); - 3f14: 07 b6 in r0, 0x37 ; 55 - 3f16: 00 fc sbrc r0, 0 - 3f18: fd cf rjmp .-6 ; 0x3f14 - writebuffer(desttype, buff, address, savelength); - - - } - /* Read memory block mode, length is big endian. */ - else if(ch == STK_READ_PAGE) { - 3f1a: c7 be out 0x37, r12 ; 55 - 3f1c: e8 95 spm - uint8_t desttype; - GETLENGTH(length); - 3f1e: 1e c0 rjmp .+60 ; 0x3f5c - 3f20: 84 37 cpi r24, 0x74 ; 116 - 3f22: 71 f4 brne .+28 ; 0x3f40 - - desttype = getch(); - 3f24: 25 d0 rcall .+74 ; 0x3f70 - - verifySpace(); - 3f26: 24 d0 rcall .+72 ; 0x3f70 - 3f28: f8 2e mov r15, r24 - 3f2a: 22 d0 rcall .+68 ; 0x3f70 - // while (--length); - // read a Flash and increment the address (may increment RAMPZ) - __asm__ ("elpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address)); -#else - // read a Flash byte and increment the address - __asm__ ("lpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address)); - 3f2c: 33 d0 rcall .+102 ; 0x3f94 - 3f2e: 8e 01 movw r16, r28 -#endif - putch(ch); - 3f30: f8 01 movw r30, r16 - } while (--length); - 3f32: 85 91 lpm r24, Z+ - 3f34: 8f 01 movw r16, r30 - 3f36: 15 d0 rcall .+42 ; 0x3f62 - 3f38: fa 94 dec r15 - - read_mem(desttype, address, length); - } - - /* Get device signature bytes */ - else if(ch == STK_READ_SIGN) { - 3f3a: f1 10 cpse r15, r1 - 3f3c: f9 cf rjmp .-14 ; 0x3f30 - // READ SIGN - return what Avrdude wants to hear - verifySpace(); - 3f3e: 0e c0 rjmp .+28 ; 0x3f5c - 3f40: 85 37 cpi r24, 0x75 ; 117 - putch(SIGNATURE_0); - 3f42: 39 f4 brne .+14 ; 0x3f52 - 3f44: 27 d0 rcall .+78 ; 0x3f94 - 3f46: 8e e1 ldi r24, 0x1E ; 30 - putch(SIGNATURE_1); - 3f48: 0c d0 rcall .+24 ; 0x3f62 - 3f4a: 84 e9 ldi r24, 0x94 ; 148 - 3f4c: 0a d0 rcall .+20 ; 0x3f62 - putch(SIGNATURE_2); - 3f4e: 86 e0 ldi r24, 0x06 ; 6 - 3f50: 9c cf rjmp .-200 ; 0x3e8a - } - else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */ - 3f52: 81 35 cpi r24, 0x51 ; 81 - 3f54: 11 f4 brne .+4 ; 0x3f5a - // Adaboot no-wait mod - watchdogConfig(WATCHDOG_16MS); - 3f56: 88 e0 ldi r24, 0x08 ; 8 - 3f58: 17 d0 rcall .+46 ; 0x3f88 - 3f5a: 1c d0 rcall .+56 ; 0x3f94 - verifySpace(); - } - else { - // This covers the response to commands like STK_ENTER_PROGMODE - verifySpace(); - 3f5c: 80 e1 ldi r24, 0x10 ; 16 - 3f5e: 01 d0 rcall .+2 ; 0x3f62 - } - putch(STK_OK); - 3f60: 87 cf rjmp .-242 ; 0x3e70 - -00003f62 : - 3f62: 90 91 c0 00 lds r25, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - } - 3f66: 95 ff sbrs r25, 5 -} - -void putch(char ch) { -#ifndef SOFT_UART - while (!(UART_SRA & _BV(UDRE0))); - 3f68: fc cf rjmp .-8 ; 0x3f62 - UART_UDR = ch; - 3f6a: 80 93 c6 00 sts 0x00C6, r24 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> - 3f6e: 08 95 ret - -00003f70 : - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UART_SRA & _BV(RXC0))) - 3f70: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - 3f74: 87 ff sbrs r24, 7 - 3f76: fc cf rjmp .-8 ; 0x3f70 - ; - if (!(UART_SRA & _BV(FE0))) { - 3f78: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - 3f7c: 84 fd sbrc r24, 4 - 3f7e: 01 c0 rjmp .+2 ; 0x3f82 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3f80: a8 95 wdr - * don't care that an invalid char is returned...) - */ - watchdogReset(); - } - - ch = UART_UDR; - 3f82: 80 91 c6 00 lds r24, 0x00C6 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> - LED_PIN |= _BV(LED); -#endif -#endif - - return ch; -} - 3f86: 08 95 ret - -00003f88 : - "wdr\n" - ); -} - -void watchdogConfig(uint8_t x) { - WDTCSR = _BV(WDCE) | _BV(WDE); - 3f88: e0 e6 ldi r30, 0x60 ; 96 - 3f8a: f0 e0 ldi r31, 0x00 ; 0 - 3f8c: 98 e1 ldi r25, 0x18 ; 24 - 3f8e: 90 83 st Z, r25 - WDTCSR = x; - 3f90: 80 83 st Z, r24 - 3f92: 08 95 ret - -00003f94 : - do getch(); while (--count); - verifySpace(); -} - -void verifySpace() { - if (getch() != CRC_EOP) { - 3f94: ed df rcall .-38 ; 0x3f70 - 3f96: 80 32 cpi r24, 0x20 ; 32 - 3f98: 19 f0 breq .+6 ; 0x3fa0 - watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 3f9a: 88 e0 ldi r24, 0x08 ; 8 - 3f9c: f5 df rcall .-22 ; 0x3f88 - 3f9e: ff cf rjmp .-2 ; 0x3f9e - while (1) // and busy-loop so that WD causes - ; // a reset and app start. - } - putch(STK_INSYNC); - 3fa0: 84 e1 ldi r24, 0x14 ; 20 - 3fa2: df cf rjmp .-66 ; 0x3f62 - -00003fa4 : - ::[count] "M" (UART_B_VALUE) - ); -} -#endif - -void getNch(uint8_t count) { - 3fa4: cf 93 push r28 - 3fa6: c8 2f mov r28, r24 - do getch(); while (--count); - 3fa8: e3 df rcall .-58 ; 0x3f70 - 3faa: c1 50 subi r28, 0x01 ; 1 - 3fac: e9 f7 brne .-6 ; 0x3fa8 - verifySpace(); - 3fae: cf 91 pop r28 - 3fb0: f1 cf rjmp .-30 ; 0x3f94 - -00003fb2 : - -void appStart(uint8_t rstFlags) { - // save the reset flags in the designated register - // This can be saved in a main program by putting code in .init0 (which - // executes before normal c init code) to save R2 to a global variable. - __asm__ __volatile__ ("mov r2, %0\n" :: "r" (rstFlags)); - 3fb2: 28 2e mov r2, r24 - - watchdogConfig(WATCHDOG_OFF); - 3fb4: 80 e0 ldi r24, 0x00 ; 0 - 3fb6: e8 df rcall .-48 ; 0x3f88 - 3fb8: e0 e0 ldi r30, 0x00 ; 0 - // Note that appstart_vec is defined so that this works with either - // real or virtual boot partitions. - __asm__ __volatile__ ( - 3fba: ff 27 eor r31, r31 - 3fbc: 09 94 ijmp diff --git a/optiboot/bootloaders/optiboot/optiboot_lilypad.hex b/optiboot/bootloaders/optiboot/optiboot_lilypad.hex deleted file mode 100644 index 8503bb3..0000000 --- a/optiboot/bootloaders/optiboot/optiboot_lilypad.hex +++ /dev/null @@ -1,31 +0,0 @@ -:103E0000112484B7882349F0982F9A70923029F0B2 -:103E100081FF02C097EF94BFCCD085E080938100F2 -:103E200082E08093C00088E18093C10086E08093A7 -:103E3000C20088E08093C4008EE0A6D0259A86E078 -:103E400028E13EEF91E0309385002093840096BBFB -:103E5000B09BFECF1D9AA8954091C00047FD02C0BF -:103E6000815089F7EE24E39495E0D92E21E1C22E0A -:103E70007FD0813461F47CD0182F8CD01238E9F0D7 -:103E8000113811F487E001C083E06BD067C0823441 -:103E900011F484E103C0853419F485E083D05EC059 -:103EA000853539F465D0C82F63D0D82FCC0FDD1FEE -:103EB00054C0863521F484E075D080E0E6CF8436A6 -:103EC00009F02EC055D054D0F82E52D0B82E00E0B4 -:103ED00011E04ED0F80181938F01FE12FACF5AD033 -:103EE000F5E4BF1201C0FFCF83E0FE0187BFE89574 -:103EF00007B600FCFDCFA0E0B1E0FE018D919D91E1 -:103F00000C01E7BEE89511243296FA12F7CFFE01B4 -:103F1000D7BEE89507B600FCFDCFC7BEE8951EC02A -:103F2000843771F425D024D0F82E22D033D08E01DE -:103F3000F80185918F0115D0FA94F110F9CF0EC0D8 -:103F4000853739F427D08EE10CD084E90AD086E099 -:103F50009CCF813511F488E017D01CD080E101D0CE -:103F600087CF9091C00095FFFCCF8093C600089545 -:103F70008091C00087FFFCCF8091C00084FD01C00C -:103F8000A8958091C6000895E0E6F0E098E190835E -:103F900080830895EDDF803219F088E0F5DFFFCFF0 -:103FA00084E1DFCFCF93C82FE3DFC150E9F7CF9192 -:0E3FB000F1CF282E80E0E8DFE0E0FF27099443 -:023FFE000007BA -:0400000300003E00BB -:00000001FF diff --git a/optiboot/bootloaders/optiboot/optiboot_lilypad.lst b/optiboot/bootloaders/optiboot/optiboot_lilypad.lst deleted file mode 100644 index c92490b..0000000 --- a/optiboot/bootloaders/optiboot/optiboot_lilypad.lst +++ /dev/null @@ -1,584 +0,0 @@ - -optiboot_atmega168.elf: file format elf32-avr - -Sections: -Idx Name Size VMA LMA File off Algn - 0 .data 00000000 00800100 00003fbe 00000252 2**0 - CONTENTS, ALLOC, LOAD, DATA - 1 .text 000001be 00003e00 00003e00 00000094 2**1 - CONTENTS, ALLOC, LOAD, READONLY, CODE - 2 .version 00000002 00003ffe 00003ffe 00000252 2**0 - CONTENTS, ALLOC, LOAD, READONLY, DATA - 3 .comment 0000002f 00000000 00000000 00000254 2**0 - CONTENTS, READONLY - 4 .debug_aranges 00000028 00000000 00000000 00000283 2**0 - CONTENTS, READONLY, DEBUGGING - 5 .debug_info 000005c8 00000000 00000000 000002ab 2**0 - CONTENTS, READONLY, DEBUGGING - 6 .debug_abbrev 00000282 00000000 00000000 00000873 2**0 - CONTENTS, READONLY, DEBUGGING - 7 .debug_line 000002f9 00000000 00000000 00000af5 2**0 - CONTENTS, READONLY, DEBUGGING - 8 .debug_frame 0000008c 00000000 00000000 00000df0 2**2 - CONTENTS, READONLY, DEBUGGING - 9 .debug_str 000001fa 00000000 00000000 00000e7c 2**0 - CONTENTS, READONLY, DEBUGGING - 10 .debug_loc 00000331 00000000 00000000 00001076 2**0 - CONTENTS, READONLY, DEBUGGING - 11 .debug_ranges 00000060 00000000 00000000 000013a7 2**0 - CONTENTS, READONLY, DEBUGGING - -Disassembly of section .text: - -00003e00
: - // SP points to RAMEND - // r1 contains zero - // - // If not, uncomment the following instructions: - // cli(); - asm volatile ("clr __zero_reg__"); - 3e00: 11 24 eor r1, r1 - * - * Code by MarkG55 - * see discusion in https://github.com/Optiboot/optiboot/issues/97 - */ -#if !defined(__AVR_ATmega16__) - ch = MCUSR; - 3e02: 84 b7 in r24, 0x34 ; 52 -#else - ch = MCUCSR; -#endif - // Skip all logic and run bootloader if MCUSR is cleared (application request) - if (ch != 0) { - 3e04: 88 23 and r24, r24 - 3e06: 49 f0 breq .+18 ; 0x3e1a - * 2. we clear WDRF if it's set with EXTRF to avoid loops - * One problematic scenario: broken application code sets watchdog timer - * without clearing MCUSR before and triggers it quickly. But it's - * recoverable by power-on with pushed reset button. - */ - if ((ch & (_BV(WDRF) | _BV(EXTRF))) != _BV(EXTRF)) { - 3e08: 98 2f mov r25, r24 - 3e0a: 9a 70 andi r25, 0x0A ; 10 - 3e0c: 92 30 cpi r25, 0x02 ; 2 - 3e0e: 29 f0 breq .+10 ; 0x3e1a - if (ch & _BV(EXTRF)) { - 3e10: 81 ff sbrs r24, 1 - 3e12: 02 c0 rjmp .+4 ; 0x3e18 - * prevent entering bootloader. - * '&' operation is skipped to spare few bytes as bits in MCUSR - * can only be cleared. - */ -#if !defined(__AVR_ATmega16__) - MCUSR = ~(_BV(WDRF)); - 3e14: 97 ef ldi r25, 0xF7 ; 247 - 3e16: 94 bf out 0x34, r25 ; 52 -#else - MCUCSR = ~(_BV(WDRF)); -#endif - } - appStart(ch); - 3e18: cc d0 rcall .+408 ; 0x3fb2 - } - } - -#if LED_START_FLASHES > 0 - // Set up Timer 1 for timeout counter - TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 - 3e1a: 85 e0 ldi r24, 0x05 ; 5 - 3e1c: 80 93 81 00 sts 0x0081, r24 ; 0x800081 <__TEXT_REGION_LENGTH__+0x7e0081> - UCSRA = _BV(U2X); //Double speed mode USART - UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx - UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 - UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); -#else - UART_SRA = _BV(U2X0); //Double speed mode USART0 - 3e20: 82 e0 ldi r24, 0x02 ; 2 - 3e22: 80 93 c0 00 sts 0x00C0, r24 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - UART_SRB = _BV(RXEN0) | _BV(TXEN0); - 3e26: 88 e1 ldi r24, 0x18 ; 24 - 3e28: 80 93 c1 00 sts 0x00C1, r24 ; 0x8000c1 <__TEXT_REGION_LENGTH__+0x7e00c1> - UART_SRC = _BV(UCSZ00) | _BV(UCSZ01); - 3e2c: 86 e0 ldi r24, 0x06 ; 6 - 3e2e: 80 93 c2 00 sts 0x00C2, r24 ; 0x8000c2 <__TEXT_REGION_LENGTH__+0x7e00c2> - UART_SRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); - 3e32: 88 e0 ldi r24, 0x08 ; 8 - 3e34: 80 93 c4 00 sts 0x00C4, r24 ; 0x8000c4 <__TEXT_REGION_LENGTH__+0x7e00c4> -#endif -#endif - - // Set up watchdog to trigger after 1s - watchdogConfig(WATCHDOG_1S); - 3e38: 8e e0 ldi r24, 0x0E ; 14 - 3e3a: a6 d0 rcall .+332 ; 0x3f88 - -#if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH) || defined(LED_START_ON) - /* Set LED pin as output */ - LED_DDR |= _BV(LED); - 3e3c: 25 9a sbi 0x04, 5 ; 4 - 3e3e: 86 e0 ldi r24, 0x06 ; 6 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e40: 28 e1 ldi r18, 0x18 ; 24 - 3e42: 3e ef ldi r19, 0xFE ; 254 - TIFR1 = _BV(TOV1); - 3e44: 91 e0 ldi r25, 0x01 ; 1 -} - -#if LED_START_FLASHES > 0 -void flash_led(uint8_t count) { - do { - TCNT1 = -(F_CPU/(1024*16)); - 3e46: 30 93 85 00 sts 0x0085, r19 ; 0x800085 <__TEXT_REGION_LENGTH__+0x7e0085> - 3e4a: 20 93 84 00 sts 0x0084, r18 ; 0x800084 <__TEXT_REGION_LENGTH__+0x7e0084> - TIFR1 = _BV(TOV1); - 3e4e: 96 bb out 0x16, r25 ; 22 - while(!(TIFR1 & _BV(TOV1))); - 3e50: b0 9b sbis 0x16, 0 ; 22 - 3e52: fe cf rjmp .-4 ; 0x3e50 -#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega16__) - LED_PORT ^= _BV(LED); -#else - LED_PIN |= _BV(LED); - 3e54: 1d 9a sbi 0x03, 5 ; 3 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3e56: a8 95 wdr - * While in theory, the STK500 initial commands would be buffered - * by the UART hardware, avrdude sends several attempts in rather - * quick succession, some of which will be lost and cause us to - * get out of sync. So if we see any data; stop blinking. - */ - if (UART_SRA & _BV(RXC0)) - 3e58: 40 91 c0 00 lds r20, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - 3e5c: 47 fd sbrc r20, 7 - 3e5e: 02 c0 rjmp .+4 ; 0x3e64 - 3e60: 81 50 subi r24, 0x01 ; 1 -#else -// This doesn't seem to work? -// if ((UART_PIN & (1< - - /* - * Copy data from the buffer into the flash write buffer. - */ - do { - __boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++)); - 3e64: ee 24 eor r14, r14 - 3e66: e3 94 inc r14 - } while (len -= 2); - - /* - * Actually Write the buffer to flash (and wait for it to finish.) - */ - __boot_page_write_short(address.word); - 3e68: 95 e0 ldi r25, 0x05 ; 5 - 3e6a: d9 2e mov r13, r25 - boot_spm_busy_wait(); -#if defined(RWWSRE) - // Reenable read access to flash - __boot_rww_enable_short(); - 3e6c: 21 e1 ldi r18, 0x11 ; 17 -#endif - - /* Forever loop: exits by causing WDT reset */ - for (;;) { - /* get character from UART */ - ch = getch(); - 3e6e: c2 2e mov r12, r18 - - if(ch == STK_GET_PARAMETER) { - 3e70: 7f d0 rcall .+254 ; 0x3f70 - unsigned char which = getch(); - 3e72: 81 34 cpi r24, 0x41 ; 65 - 3e74: 61 f4 brne .+24 ; 0x3e8e - 3e76: 7c d0 rcall .+248 ; 0x3f70 - verifySpace(); - 3e78: 18 2f mov r17, r24 - 3e7a: 8c d0 rcall .+280 ; 0x3f94 - /* - * Send optiboot version as "SW version" - * Note that the references to memory are optimized away. - */ - if (which == STK_SW_MINOR) { - 3e7c: 12 38 cpi r17, 0x82 ; 130 - 3e7e: e9 f0 breq .+58 ; 0x3eba - putch(optiboot_version & 0xFF); - } else if (which == STK_SW_MAJOR) { - 3e80: 11 38 cpi r17, 0x81 ; 129 - putch(optiboot_version >> 8); - 3e82: 11 f4 brne .+4 ; 0x3e88 - 3e84: 87 e0 ldi r24, 0x07 ; 7 - } else { - /* - * GET PARAMETER returns a generic 0x03 reply for - * other parameters - enough to keep Avrdude happy - */ - putch(0x03); - 3e86: 01 c0 rjmp .+2 ; 0x3e8a - 3e88: 83 e0 ldi r24, 0x03 ; 3 - 3e8a: 6b d0 rcall .+214 ; 0x3f62 - 3e8c: 67 c0 rjmp .+206 ; 0x3f5c - } - } - else if(ch == STK_SET_DEVICE) { - 3e8e: 82 34 cpi r24, 0x42 ; 66 - // SET DEVICE is ignored - getNch(20); - 3e90: 11 f4 brne .+4 ; 0x3e96 - 3e92: 84 e1 ldi r24, 0x14 ; 20 - } - else if(ch == STK_SET_DEVICE_EXT) { - 3e94: 03 c0 rjmp .+6 ; 0x3e9c - // SET DEVICE EXT is ignored - getNch(5); - 3e96: 85 34 cpi r24, 0x45 ; 69 - 3e98: 19 f4 brne .+6 ; 0x3ea0 - 3e9a: 85 e0 ldi r24, 0x05 ; 5 - } - else if(ch == STK_LOAD_ADDRESS) { - 3e9c: 83 d0 rcall .+262 ; 0x3fa4 - 3e9e: 5e c0 rjmp .+188 ; 0x3f5c - // LOAD ADDRESS - address.bytes[0] = getch(); - 3ea0: 85 35 cpi r24, 0x55 ; 85 - 3ea2: 39 f4 brne .+14 ; 0x3eb2 - 3ea4: 65 d0 rcall .+202 ; 0x3f70 - address.bytes[1] = getch(); - 3ea6: c8 2f mov r28, r24 - 3ea8: 63 d0 rcall .+198 ; 0x3f70 - } - else { - RAMPZ &= 0xFE; - } -#endif - address.word *= 2; // Convert from word address to byte address - 3eaa: d8 2f mov r29, r24 - 3eac: cc 0f add r28, r28 - 3eae: dd 1f adc r29, r29 - verifySpace(); - } - else if(ch == STK_UNIVERSAL) { - 3eb0: 54 c0 rjmp .+168 ; 0x3f5a - getNch(3); - putch(0x00); - } -#else - // UNIVERSAL command is ignored - getNch(4); - 3eb2: 86 35 cpi r24, 0x56 ; 86 - 3eb4: 21 f4 brne .+8 ; 0x3ebe - putch(0x00); - 3eb6: 84 e0 ldi r24, 0x04 ; 4 - 3eb8: 75 d0 rcall .+234 ; 0x3fa4 -#endif - } - /* Write memory, length is big endian and is in bytes */ - else if(ch == STK_PROG_PAGE) { - 3eba: 80 e0 ldi r24, 0x00 ; 0 - 3ebc: e6 cf rjmp .-52 ; 0x3e8a - // PROGRAM PAGE - we support flash programming only, not EEPROM - uint8_t desttype; - uint8_t *bufPtr; - pagelen_t savelength; - - GETLENGTH(length); - 3ebe: 84 36 cpi r24, 0x64 ; 100 - 3ec0: 09 f0 breq .+2 ; 0x3ec4 - 3ec2: 2e c0 rjmp .+92 ; 0x3f20 - 3ec4: 55 d0 rcall .+170 ; 0x3f70 - savelength = length; - desttype = getch(); - 3ec6: 54 d0 rcall .+168 ; 0x3f70 - 3ec8: f8 2e mov r15, r24 - 3eca: 52 d0 rcall .+164 ; 0x3f70 - 3ecc: b8 2e mov r11, r24 - 3ece: 00 e0 ldi r16, 0x00 ; 0 - - // read a page worth of contents - bufPtr = buff.bptr; - do *bufPtr++ = getch(); - 3ed0: 11 e0 ldi r17, 0x01 ; 1 - 3ed2: 4e d0 rcall .+156 ; 0x3f70 - 3ed4: f8 01 movw r30, r16 - 3ed6: 81 93 st Z+, r24 - 3ed8: 8f 01 movw r16, r30 - while (--length); - 3eda: fe 12 cpse r15, r30 - 3edc: fa cf rjmp .-12 ; 0x3ed2 - - // Read command terminator, start reply - verifySpace(); - 3ede: 5a d0 rcall .+180 ; 0x3f94 - 3ee0: f5 e4 ldi r31, 0x45 ; 69 - * void writebuffer(memtype, buffer, address, length) - */ -static inline void writebuffer(int8_t memtype, addr16_t mybuff, - addr16_t address, pagelen_t len) -{ - switch (memtype) { - 3ee2: bf 12 cpse r11, r31 - 3ee4: 01 c0 rjmp .+2 ; 0x3ee8 - 3ee6: ff cf rjmp .-2 ; 0x3ee6 - 3ee8: 83 e0 ldi r24, 0x03 ; 3 - * Start the page erase and wait for it to finish. There - * used to be code to do this while receiving the data over - * the serial link, but the performance improvement was slight, - * and we needed the space back. - */ - __boot_page_erase_short(address.word); - 3eea: fe 01 movw r30, r28 - 3eec: 87 bf out 0x37, r24 ; 55 - 3eee: e8 95 spm - 3ef0: 07 b6 in r0, 0x37 ; 55 - boot_spm_busy_wait(); - 3ef2: 00 fc sbrc r0, 0 - 3ef4: fd cf rjmp .-6 ; 0x3ef0 - 3ef6: a0 e0 ldi r26, 0x00 ; 0 - 3ef8: b1 e0 ldi r27, 0x01 ; 1 - 3efa: fe 01 movw r30, r28 - 3efc: 8d 91 ld r24, X+ - - /* - * Copy data from the buffer into the flash write buffer. - */ - do { - __boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++)); - 3efe: 9d 91 ld r25, X+ - 3f00: 0c 01 movw r0, r24 - 3f02: e7 be out 0x37, r14 ; 55 - 3f04: e8 95 spm - 3f06: 11 24 eor r1, r1 - 3f08: 32 96 adiw r30, 0x02 ; 2 - addrPtr += 2; - } while (len -= 2); - 3f0a: fa 12 cpse r15, r26 - - /* - * Actually Write the buffer to flash (and wait for it to finish.) - */ - __boot_page_write_short(address.word); - 3f0c: f7 cf rjmp .-18 ; 0x3efc - 3f0e: fe 01 movw r30, r28 - boot_spm_busy_wait(); - 3f10: d7 be out 0x37, r13 ; 55 - 3f12: e8 95 spm -#if defined(RWWSRE) - // Reenable read access to flash - __boot_rww_enable_short(); - 3f14: 07 b6 in r0, 0x37 ; 55 - 3f16: 00 fc sbrc r0, 0 - 3f18: fd cf rjmp .-6 ; 0x3f14 - writebuffer(desttype, buff, address, savelength); - - - } - /* Read memory block mode, length is big endian. */ - else if(ch == STK_READ_PAGE) { - 3f1a: c7 be out 0x37, r12 ; 55 - 3f1c: e8 95 spm - uint8_t desttype; - GETLENGTH(length); - 3f1e: 1e c0 rjmp .+60 ; 0x3f5c - 3f20: 84 37 cpi r24, 0x74 ; 116 - 3f22: 71 f4 brne .+28 ; 0x3f40 - - desttype = getch(); - 3f24: 25 d0 rcall .+74 ; 0x3f70 - - verifySpace(); - 3f26: 24 d0 rcall .+72 ; 0x3f70 - 3f28: f8 2e mov r15, r24 - 3f2a: 22 d0 rcall .+68 ; 0x3f70 - // while (--length); - // read a Flash and increment the address (may increment RAMPZ) - __asm__ ("elpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address)); -#else - // read a Flash byte and increment the address - __asm__ ("lpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address)); - 3f2c: 33 d0 rcall .+102 ; 0x3f94 - 3f2e: 8e 01 movw r16, r28 -#endif - putch(ch); - 3f30: f8 01 movw r30, r16 - } while (--length); - 3f32: 85 91 lpm r24, Z+ - 3f34: 8f 01 movw r16, r30 - 3f36: 15 d0 rcall .+42 ; 0x3f62 - 3f38: fa 94 dec r15 - - read_mem(desttype, address, length); - } - - /* Get device signature bytes */ - else if(ch == STK_READ_SIGN) { - 3f3a: f1 10 cpse r15, r1 - 3f3c: f9 cf rjmp .-14 ; 0x3f30 - // READ SIGN - return what Avrdude wants to hear - verifySpace(); - 3f3e: 0e c0 rjmp .+28 ; 0x3f5c - 3f40: 85 37 cpi r24, 0x75 ; 117 - putch(SIGNATURE_0); - 3f42: 39 f4 brne .+14 ; 0x3f52 - 3f44: 27 d0 rcall .+78 ; 0x3f94 - 3f46: 8e e1 ldi r24, 0x1E ; 30 - putch(SIGNATURE_1); - 3f48: 0c d0 rcall .+24 ; 0x3f62 - 3f4a: 84 e9 ldi r24, 0x94 ; 148 - 3f4c: 0a d0 rcall .+20 ; 0x3f62 - putch(SIGNATURE_2); - 3f4e: 86 e0 ldi r24, 0x06 ; 6 - 3f50: 9c cf rjmp .-200 ; 0x3e8a - } - else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */ - 3f52: 81 35 cpi r24, 0x51 ; 81 - 3f54: 11 f4 brne .+4 ; 0x3f5a - // Adaboot no-wait mod - watchdogConfig(WATCHDOG_16MS); - 3f56: 88 e0 ldi r24, 0x08 ; 8 - 3f58: 17 d0 rcall .+46 ; 0x3f88 - 3f5a: 1c d0 rcall .+56 ; 0x3f94 - verifySpace(); - } - else { - // This covers the response to commands like STK_ENTER_PROGMODE - verifySpace(); - 3f5c: 80 e1 ldi r24, 0x10 ; 16 - 3f5e: 01 d0 rcall .+2 ; 0x3f62 - } - putch(STK_OK); - 3f60: 87 cf rjmp .-242 ; 0x3e70 - -00003f62 : - 3f62: 90 91 c0 00 lds r25, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - } - 3f66: 95 ff sbrs r25, 5 -} - -void putch(char ch) { -#ifndef SOFT_UART - while (!(UART_SRA & _BV(UDRE0))); - 3f68: fc cf rjmp .-8 ; 0x3f62 - UART_UDR = ch; - 3f6a: 80 93 c6 00 sts 0x00C6, r24 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> - 3f6e: 08 95 ret - -00003f70 : - [uartBit] "I" (UART_RX_BIT) - : - "r25" -); -#else - while(!(UART_SRA & _BV(RXC0))) - 3f70: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - 3f74: 87 ff sbrs r24, 7 - 3f76: fc cf rjmp .-8 ; 0x3f70 - ; - if (!(UART_SRA & _BV(FE0))) { - 3f78: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> - 3f7c: 84 fd sbrc r24, 4 - 3f7e: 01 c0 rjmp .+2 ; 0x3f82 -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 3f80: a8 95 wdr - * don't care that an invalid char is returned...) - */ - watchdogReset(); - } - - ch = UART_UDR; - 3f82: 80 91 c6 00 lds r24, 0x00C6 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> - LED_PIN |= _BV(LED); -#endif -#endif - - return ch; -} - 3f86: 08 95 ret - -00003f88 : - "wdr\n" - ); -} - -void watchdogConfig(uint8_t x) { - WDTCSR = _BV(WDCE) | _BV(WDE); - 3f88: e0 e6 ldi r30, 0x60 ; 96 - 3f8a: f0 e0 ldi r31, 0x00 ; 0 - 3f8c: 98 e1 ldi r25, 0x18 ; 24 - 3f8e: 90 83 st Z, r25 - WDTCSR = x; - 3f90: 80 83 st Z, r24 - 3f92: 08 95 ret - -00003f94 : - do getch(); while (--count); - verifySpace(); -} - -void verifySpace() { - if (getch() != CRC_EOP) { - 3f94: ed df rcall .-38 ; 0x3f70 - 3f96: 80 32 cpi r24, 0x20 ; 32 - 3f98: 19 f0 breq .+6 ; 0x3fa0 - watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 3f9a: 88 e0 ldi r24, 0x08 ; 8 - 3f9c: f5 df rcall .-22 ; 0x3f88 - 3f9e: ff cf rjmp .-2 ; 0x3f9e - while (1) // and busy-loop so that WD causes - ; // a reset and app start. - } - putch(STK_INSYNC); - 3fa0: 84 e1 ldi r24, 0x14 ; 20 - 3fa2: df cf rjmp .-66 ; 0x3f62 - -00003fa4 : - ::[count] "M" (UART_B_VALUE) - ); -} -#endif - -void getNch(uint8_t count) { - 3fa4: cf 93 push r28 - 3fa6: c8 2f mov r28, r24 - do getch(); while (--count); - 3fa8: e3 df rcall .-58 ; 0x3f70 - 3faa: c1 50 subi r28, 0x01 ; 1 - 3fac: e9 f7 brne .-6 ; 0x3fa8 - verifySpace(); - 3fae: cf 91 pop r28 - 3fb0: f1 cf rjmp .-30 ; 0x3f94 - -00003fb2 : - -void appStart(uint8_t rstFlags) { - // save the reset flags in the designated register - // This can be saved in a main program by putting code in .init0 (which - // executes before normal c init code) to save R2 to a global variable. - __asm__ __volatile__ ("mov r2, %0\n" :: "r" (rstFlags)); - 3fb2: 28 2e mov r2, r24 - - watchdogConfig(WATCHDOG_OFF); - 3fb4: 80 e0 ldi r24, 0x00 ; 0 - 3fb6: e8 df rcall .-48 ; 0x3f88 - 3fb8: e0 e0 ldi r30, 0x00 ; 0 - // Note that appstart_vec is defined so that this works with either - // real or virtual boot partitions. - __asm__ __volatile__ ( - 3fba: ff 27 eor r31, r31 - 3fbc: 09 94 ijmp diff --git a/optiboot/bootloaders/optiboot/optiboot_luminet.hex b/optiboot/bootloaders/optiboot/optiboot_luminet.hex deleted file mode 100644 index 2a22c46..0000000 --- a/optiboot/bootloaders/optiboot/optiboot_luminet.hex +++ /dev/null @@ -1,38 +0,0 @@ -:101D0000112484B7882349F0982F9A70923029F0D3 -:101D100081FF02C097EF94BFFED08EE0E9D0D29A47 -:101D200023E0C22EBB24B39435E0A32ECDD0813462 -:101D300071F4CAD0F82EE0D082E8F816F1F0E1E8AC -:101D4000FE1202C087E001C083E0AFD0ABC0823496 -:101D500011F484E103C0853419F485E0D5D0A2C024 -:101D6000853539F4B1D0C82FAFD0D82FCC0FDD1FB7 -:101D700098C0863521F484E0C7D080E0E6CF843671 -:101D800009F055C0A1D0A0D0F82E9ED0D82EEF2CAF -:101D900080E6882E912C98D0F40181934F01EA942B -:101DA000E110F9CFA9D0209719F590916000909398 -:101DB000E400809161008093E50020916800209309 -:101DC000E600209169002093E700092F182F0450A6 -:101DD000110900936800812F8F70806C80936900D7 -:101DE00000E81EE000936000812F806C809361000A -:101DF000F5E4DF1201C0FFCFFE01C7BEE89507B6CC -:101E000000FCFDCFA0E6B0E0FE018D919D910C019C -:101E1000B7BEE8951124FA94FA943296F110F5CFF2 -:101E2000FE01A7BEE89507B600FCFDCF3BC0843796 -:101E300059F54AD049D0D82E47D05ED07E01E11462 -:101E4000F10419F48091E40017C0F1E0EF16F104F9 -:101E500019F48091E50010C088E0E816F10419F447 -:101E60008091E60009C0E9E0EE16F10419F48091D2 -:101E7000E70002C0F701849118D0DA94FFEFEF1A5F -:101E8000FF0AD110DCCF0EC0853739F435D08EE192 -:101E90000CD083E90AD08CE058CF813511F488E06A -:101EA00027D02AD080E101D041CF2AE030E08095D0 -:101EB000089410F4DA9802C0DA9A000015D014D011 -:101EC00086952A95B1F70895A89529E030E0CB9939 -:101ED000FECF0AD009D008D08894CB9908942A95CF -:101EE00011F08795F7CF08959EE09A95F1F7089540 -:101EF00098E191BD81BD0895E7DF803219F088E057 -:101F0000F7DFFFCF84E1D1CFCF93C82FDDDFC15002 -:101F1000E9F7CF91F1CF282E80E0EADFE4E0FF2758 -:021F2000099422 -:021FFE000007DA -:0400000300001D00DC -:00000001FF diff --git a/optiboot/bootloaders/optiboot/optiboot_luminet.lst b/optiboot/bootloaders/optiboot/optiboot_luminet.lst deleted file mode 100644 index 0eb42d4..0000000 --- a/optiboot/bootloaders/optiboot/optiboot_luminet.lst +++ /dev/null @@ -1,634 +0,0 @@ - -optiboot_attiny84.elf: file format elf32-avr - -Sections: -Idx Name Size VMA LMA File off Algn - 0 .text 00000222 00001d00 00001d00 00000074 2**1 - CONTENTS, ALLOC, LOAD, READONLY, CODE - 1 .version 00000002 00001ffe 00001ffe 00000296 2**0 - CONTENTS, ALLOC, LOAD, READONLY, DATA - 2 .data 00000000 00800060 00800060 00000298 2**0 - CONTENTS, ALLOC, LOAD, DATA - 3 .comment 0000002f 00000000 00000000 00000298 2**0 - CONTENTS, READONLY - 4 .debug_aranges 00000028 00000000 00000000 000002c7 2**0 - CONTENTS, READONLY, DEBUGGING - 5 .debug_info 000005e9 00000000 00000000 000002ef 2**0 - CONTENTS, READONLY, DEBUGGING - 6 .debug_abbrev 0000029f 00000000 00000000 000008d8 2**0 - CONTENTS, READONLY, DEBUGGING - 7 .debug_line 00000307 00000000 00000000 00000b77 2**0 - CONTENTS, READONLY, DEBUGGING - 8 .debug_frame 0000009c 00000000 00000000 00000e80 2**2 - CONTENTS, READONLY, DEBUGGING - 9 .debug_str 00000212 00000000 00000000 00000f1c 2**0 - CONTENTS, READONLY, DEBUGGING - 10 .debug_loc 00000367 00000000 00000000 0000112e 2**0 - CONTENTS, READONLY, DEBUGGING - 11 .debug_ranges 00000060 00000000 00000000 00001495 2**0 - CONTENTS, READONLY, DEBUGGING - -Disassembly of section .text: - -00001d00
: - // SP points to RAMEND - // r1 contains zero - // - // If not, uncomment the following instructions: - // cli(); - asm volatile ("clr __zero_reg__"); - 1d00: 11 24 eor r1, r1 - * - * Code by MarkG55 - * see discusion in https://github.com/Optiboot/optiboot/issues/97 - */ -#if !defined(__AVR_ATmega16__) - ch = MCUSR; - 1d02: 84 b7 in r24, 0x34 ; 52 -#else - ch = MCUCSR; -#endif - // Skip all logic and run bootloader if MCUSR is cleared (application request) - if (ch != 0) { - 1d04: 88 23 and r24, r24 - 1d06: 49 f0 breq .+18 ; 0x1d1a - * 2. we clear WDRF if it's set with EXTRF to avoid loops - * One problematic scenario: broken application code sets watchdog timer - * without clearing MCUSR before and triggers it quickly. But it's - * recoverable by power-on with pushed reset button. - */ - if ((ch & (_BV(WDRF) | _BV(EXTRF))) != _BV(EXTRF)) { - 1d08: 98 2f mov r25, r24 - 1d0a: 9a 70 andi r25, 0x0A ; 10 - 1d0c: 92 30 cpi r25, 0x02 ; 2 - 1d0e: 29 f0 breq .+10 ; 0x1d1a - if (ch & _BV(EXTRF)) { - 1d10: 81 ff sbrs r24, 1 - 1d12: 02 c0 rjmp .+4 ; 0x1d18 - * prevent entering bootloader. - * '&' operation is skipped to spare few bytes as bits in MCUSR - * can only be cleared. - */ -#if !defined(__AVR_ATmega16__) - MCUSR = ~(_BV(WDRF)); - 1d14: 97 ef ldi r25, 0xF7 ; 247 - 1d16: 94 bf out 0x34, r25 ; 52 -#else - MCUCSR = ~(_BV(WDRF)); -#endif - } - appStart(ch); - 1d18: fe d0 rcall .+508 ; 0x1f16 - UART_SRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); -#endif -#endif - - // Set up watchdog to trigger after 1s - watchdogConfig(WATCHDOG_1S); - 1d1a: 8e e0 ldi r24, 0x0E ; 14 - 1d1c: e9 d0 rcall .+466 ; 0x1ef0 - LED_DDR |= _BV(LED); -#endif - -#ifdef SOFT_UART - /* Set TX pin as output */ - UART_DDR |= _BV(UART_TX_BIT); - 1d1e: d2 9a sbi 0x1a, 2 ; 26 - * Start the page erase and wait for it to finish. There - * used to be code to do this while receiving the data over - * the serial link, but the performance improvement was slight, - * and we needed the space back. - */ - __boot_page_erase_short(address.word); - 1d20: 23 e0 ldi r18, 0x03 ; 3 - 1d22: c2 2e mov r12, r18 - - /* - * Copy data from the buffer into the flash write buffer. - */ - do { - __boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++)); - 1d24: bb 24 eor r11, r11 - 1d26: b3 94 inc r11 - } while (len -= 2); - - /* - * Actually Write the buffer to flash (and wait for it to finish.) - */ - __boot_page_write_short(address.word); - 1d28: 35 e0 ldi r19, 0x05 ; 5 - 1d2a: a3 2e mov r10, r19 -#endif - - /* Forever loop: exits by causing WDT reset */ - for (;;) { - /* get character from UART */ - ch = getch(); - 1d2c: cd d0 rcall .+410 ; 0x1ec8 - - if(ch == STK_GET_PARAMETER) { - 1d2e: 81 34 cpi r24, 0x41 ; 65 - 1d30: 71 f4 brne .+28 ; 0x1d4e - unsigned char which = getch(); - 1d32: ca d0 rcall .+404 ; 0x1ec8 - 1d34: f8 2e mov r15, r24 - verifySpace(); - 1d36: e0 d0 rcall .+448 ; 0x1ef8 - /* - * Send optiboot version as "SW version" - * Note that the references to memory are optimized away. - */ - if (which == STK_SW_MINOR) { - 1d38: 82 e8 ldi r24, 0x82 ; 130 - 1d3a: f8 16 cp r15, r24 - 1d3c: f1 f0 breq .+60 ; 0x1d7a - putch(optiboot_version & 0xFF); - } else if (which == STK_SW_MAJOR) { - 1d3e: e1 e8 ldi r30, 0x81 ; 129 - 1d40: fe 12 cpse r15, r30 - 1d42: 02 c0 rjmp .+4 ; 0x1d48 - putch(optiboot_version >> 8); - 1d44: 87 e0 ldi r24, 0x07 ; 7 - 1d46: 01 c0 rjmp .+2 ; 0x1d4a - } else { - /* - * GET PARAMETER returns a generic 0x03 reply for - * other parameters - enough to keep Avrdude happy - */ - putch(0x03); - 1d48: 83 e0 ldi r24, 0x03 ; 3 - 1d4a: af d0 rcall .+350 ; 0x1eaa - 1d4c: ab c0 rjmp .+342 ; 0x1ea4 - } - } - else if(ch == STK_SET_DEVICE) { - 1d4e: 82 34 cpi r24, 0x42 ; 66 - 1d50: 11 f4 brne .+4 ; 0x1d56 - // SET DEVICE is ignored - getNch(20); - 1d52: 84 e1 ldi r24, 0x14 ; 20 - 1d54: 03 c0 rjmp .+6 ; 0x1d5c - } - else if(ch == STK_SET_DEVICE_EXT) { - 1d56: 85 34 cpi r24, 0x45 ; 69 - 1d58: 19 f4 brne .+6 ; 0x1d60 - // SET DEVICE EXT is ignored - getNch(5); - 1d5a: 85 e0 ldi r24, 0x05 ; 5 - 1d5c: d5 d0 rcall .+426 ; 0x1f08 - 1d5e: a2 c0 rjmp .+324 ; 0x1ea4 - } - else if(ch == STK_LOAD_ADDRESS) { - 1d60: 85 35 cpi r24, 0x55 ; 85 - 1d62: 39 f4 brne .+14 ; 0x1d72 - // LOAD ADDRESS - address.bytes[0] = getch(); - 1d64: b1 d0 rcall .+354 ; 0x1ec8 - 1d66: c8 2f mov r28, r24 - address.bytes[1] = getch(); - 1d68: af d0 rcall .+350 ; 0x1ec8 - 1d6a: d8 2f mov r29, r24 - } - else { - RAMPZ &= 0xFE; - } -#endif - address.word *= 2; // Convert from word address to byte address - 1d6c: cc 0f add r28, r28 - 1d6e: dd 1f adc r29, r29 - 1d70: 98 c0 rjmp .+304 ; 0x1ea2 - verifySpace(); - } - else if(ch == STK_UNIVERSAL) { - 1d72: 86 35 cpi r24, 0x56 ; 86 - 1d74: 21 f4 brne .+8 ; 0x1d7e - getNch(3); - putch(0x00); - } -#else - // UNIVERSAL command is ignored - getNch(4); - 1d76: 84 e0 ldi r24, 0x04 ; 4 - 1d78: c7 d0 rcall .+398 ; 0x1f08 - putch(0x00); - 1d7a: 80 e0 ldi r24, 0x00 ; 0 - 1d7c: e6 cf rjmp .-52 ; 0x1d4a -#endif - } - /* Write memory, length is big endian and is in bytes */ - else if(ch == STK_PROG_PAGE) { - 1d7e: 84 36 cpi r24, 0x64 ; 100 - 1d80: 09 f0 breq .+2 ; 0x1d84 - 1d82: 55 c0 rjmp .+170 ; 0x1e2e - // PROGRAM PAGE - we support flash programming only, not EEPROM - uint8_t desttype; - uint8_t *bufPtr; - pagelen_t savelength; - - GETLENGTH(length); - 1d84: a1 d0 rcall .+322 ; 0x1ec8 - 1d86: a0 d0 rcall .+320 ; 0x1ec8 - 1d88: f8 2e mov r15, r24 - savelength = length; - desttype = getch(); - 1d8a: 9e d0 rcall .+316 ; 0x1ec8 - 1d8c: d8 2e mov r13, r24 - // PROGRAM PAGE - we support flash programming only, not EEPROM - uint8_t desttype; - uint8_t *bufPtr; - pagelen_t savelength; - - GETLENGTH(length); - 1d8e: ef 2c mov r14, r15 - savelength = length; - desttype = getch(); - 1d90: 80 e6 ldi r24, 0x60 ; 96 - 1d92: 88 2e mov r8, r24 - 1d94: 91 2c mov r9, r1 - - // read a page worth of contents - bufPtr = buff.bptr; - do *bufPtr++ = getch(); - 1d96: 98 d0 rcall .+304 ; 0x1ec8 - 1d98: f4 01 movw r30, r8 - 1d9a: 81 93 st Z+, r24 - 1d9c: 4f 01 movw r8, r30 - while (--length); - 1d9e: ea 94 dec r14 - 1da0: e1 10 cpse r14, r1 - 1da2: f9 cf rjmp .-14 ; 0x1d96 - - // Read command terminator, start reply - verifySpace(); - 1da4: a9 d0 rcall .+338 ; 0x1ef8 - -#else -/* - * AVR with 2-byte ISR Vectors and rjmp - */ - if (address.word == rstVect0) { - 1da6: 20 97 sbiw r28, 0x00 ; 0 - 1da8: 19 f5 brne .+70 ; 0x1df0 - // This is the reset vector page. We need to live-patch - // the code so the bootloader runs first. - // - // Move RESET vector to 'save' vector - // Save jmp targets (for "Verify") - rstVect0_sav = buff.bptr[rstVect0]; - 1daa: 90 91 60 00 lds r25, 0x0060 ; 0x800060 <_edata> - 1dae: 90 93 e4 00 sts 0x00E4, r25 ; 0x8000e4 <_edata+0x84> - rstVect1_sav = buff.bptr[rstVect1]; - 1db2: 80 91 61 00 lds r24, 0x0061 ; 0x800061 <_edata+0x1> - 1db6: 80 93 e5 00 sts 0x00E5, r24 ; 0x8000e5 <_edata+0x85> - saveVect0_sav = buff.bptr[saveVect0]; - 1dba: 20 91 68 00 lds r18, 0x0068 ; 0x800068 <_edata+0x8> - 1dbe: 20 93 e6 00 sts 0x00E6, r18 ; 0x8000e6 <_edata+0x86> - saveVect1_sav = buff.bptr[saveVect1]; - 1dc2: 20 91 69 00 lds r18, 0x0069 ; 0x800069 <_edata+0x9> - 1dc6: 20 93 e7 00 sts 0x00E7, r18 ; 0x8000e7 <_edata+0x87> - - // Instruction is a relative jump (rjmp), so recalculate. - // an RJMP instruction is 0b1100xxxx xxxxxxxx, so we should be able to - // do math on the offsets without masking it off first. - addr16_t vect; - vect.bytes[0] = rstVect0_sav; - 1dca: 09 2f mov r16, r25 - vect.bytes[1] = rstVect1_sav; - 1dcc: 18 2f mov r17, r24 - vect.word = (vect.word-save_vect_num); //substract 'save' interrupt position - 1dce: 04 50 subi r16, 0x04 ; 4 - 1dd0: 11 09 sbc r17, r1 - // Move RESET jmp target to 'save' vector - buff.bptr[saveVect0] = vect.bytes[0]; - 1dd2: 00 93 68 00 sts 0x0068, r16 ; 0x800068 <_edata+0x8> - buff.bptr[saveVect1] = (vect.bytes[1] & 0x0F)| 0xC0; // make an "rjmp" - 1dd6: 81 2f mov r24, r17 - 1dd8: 8f 70 andi r24, 0x0F ; 15 - 1dda: 80 6c ori r24, 0xC0 ; 192 - 1ddc: 80 93 69 00 sts 0x0069, r24 ; 0x800069 <_edata+0x9> - // Add rjump to bootloader at RESET vector - vect.word = ((uint16_t)main); // (main) is always <= 0x0FFF; no masking needed. - 1de0: 00 e8 ldi r16, 0x80 ; 128 - 1de2: 1e e0 ldi r17, 0x0E ; 14 - buff.bptr[0] = vect.bytes[0]; // rjmp 0x1c00 instruction - 1de4: 00 93 60 00 sts 0x0060, r16 ; 0x800060 <_edata> - buff.bptr[1] = vect.bytes[1] | 0xC0; // make an "rjmp" - 1de8: 81 2f mov r24, r17 - 1dea: 80 6c ori r24, 0xC0 ; 192 - 1dec: 80 93 61 00 sts 0x0061, r24 ; 0x800061 <_edata+0x1> - * void writebuffer(memtype, buffer, address, length) - */ -static inline void writebuffer(int8_t memtype, addr16_t mybuff, - addr16_t address, pagelen_t len) -{ - switch (memtype) { - 1df0: f5 e4 ldi r31, 0x45 ; 69 - 1df2: df 12 cpse r13, r31 - 1df4: 01 c0 rjmp .+2 ; 0x1df8 - 1df6: ff cf rjmp .-2 ; 0x1df6 - * Start the page erase and wait for it to finish. There - * used to be code to do this while receiving the data over - * the serial link, but the performance improvement was slight, - * and we needed the space back. - */ - __boot_page_erase_short(address.word); - 1df8: fe 01 movw r30, r28 - 1dfa: c7 be out 0x37, r12 ; 55 - 1dfc: e8 95 spm - boot_spm_busy_wait(); - 1dfe: 07 b6 in r0, 0x37 ; 55 - 1e00: 00 fc sbrc r0, 0 - 1e02: fd cf rjmp .-6 ; 0x1dfe - 1e04: a0 e6 ldi r26, 0x60 ; 96 - 1e06: b0 e0 ldi r27, 0x00 ; 0 - 1e08: fe 01 movw r30, r28 - - /* - * Copy data from the buffer into the flash write buffer. - */ - do { - __boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++)); - 1e0a: 8d 91 ld r24, X+ - 1e0c: 9d 91 ld r25, X+ - 1e0e: 0c 01 movw r0, r24 - 1e10: b7 be out 0x37, r11 ; 55 - 1e12: e8 95 spm - 1e14: 11 24 eor r1, r1 - addrPtr += 2; - } while (len -= 2); - 1e16: fa 94 dec r15 - 1e18: fa 94 dec r15 - 1e1a: 32 96 adiw r30, 0x02 ; 2 - 1e1c: f1 10 cpse r15, r1 - 1e1e: f5 cf rjmp .-22 ; 0x1e0a - - /* - * Actually Write the buffer to flash (and wait for it to finish.) - */ - __boot_page_write_short(address.word); - 1e20: fe 01 movw r30, r28 - 1e22: a7 be out 0x37, r10 ; 55 - 1e24: e8 95 spm - boot_spm_busy_wait(); - 1e26: 07 b6 in r0, 0x37 ; 55 - 1e28: 00 fc sbrc r0, 0 - 1e2a: fd cf rjmp .-6 ; 0x1e26 - 1e2c: 3b c0 rjmp .+118 ; 0x1ea4 - writebuffer(desttype, buff, address, savelength); - - - } - /* Read memory block mode, length is big endian. */ - else if(ch == STK_READ_PAGE) { - 1e2e: 84 37 cpi r24, 0x74 ; 116 - 1e30: 59 f5 brne .+86 ; 0x1e88 - uint8_t desttype; - GETLENGTH(length); - 1e32: 4a d0 rcall .+148 ; 0x1ec8 - 1e34: 49 d0 rcall .+146 ; 0x1ec8 - 1e36: d8 2e mov r13, r24 - - desttype = getch(); - 1e38: 47 d0 rcall .+142 ; 0x1ec8 - - verifySpace(); - 1e3a: 5e d0 rcall .+188 ; 0x1ef8 - 1e3c: 7e 01 movw r14, r28 -#endif - default: - do { -#ifdef VIRTUAL_BOOT_PARTITION - // Undo vector patch in bottom page so verify passes - if (address.word == rstVect0) ch = rstVect0_sav; - 1e3e: e1 14 cp r14, r1 - 1e40: f1 04 cpc r15, r1 - 1e42: 19 f4 brne .+6 ; 0x1e4a - 1e44: 80 91 e4 00 lds r24, 0x00E4 ; 0x8000e4 <_edata+0x84> - 1e48: 17 c0 rjmp .+46 ; 0x1e78 - else if (address.word == rstVect1) ch = rstVect1_sav; - 1e4a: f1 e0 ldi r31, 0x01 ; 1 - 1e4c: ef 16 cp r14, r31 - 1e4e: f1 04 cpc r15, r1 - 1e50: 19 f4 brne .+6 ; 0x1e58 - 1e52: 80 91 e5 00 lds r24, 0x00E5 ; 0x8000e5 <_edata+0x85> - 1e56: 10 c0 rjmp .+32 ; 0x1e78 - else if (address.word == saveVect0) ch = saveVect0_sav; - 1e58: 88 e0 ldi r24, 0x08 ; 8 - 1e5a: e8 16 cp r14, r24 - 1e5c: f1 04 cpc r15, r1 - 1e5e: 19 f4 brne .+6 ; 0x1e66 - 1e60: 80 91 e6 00 lds r24, 0x00E6 ; 0x8000e6 <_edata+0x86> - 1e64: 09 c0 rjmp .+18 ; 0x1e78 - else if (address.word == saveVect1) ch = saveVect1_sav; - 1e66: e9 e0 ldi r30, 0x09 ; 9 - 1e68: ee 16 cp r14, r30 - 1e6a: f1 04 cpc r15, r1 - 1e6c: 19 f4 brne .+6 ; 0x1e74 - 1e6e: 80 91 e7 00 lds r24, 0x00E7 ; 0x8000e7 <_edata+0x87> - 1e72: 02 c0 rjmp .+4 ; 0x1e78 - else ch = pgm_read_byte_near(address.bptr); - 1e74: f7 01 movw r30, r14 - 1e76: 84 91 lpm r24, Z - __asm__ ("elpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address)); -#else - // read a Flash byte and increment the address - __asm__ ("lpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address)); -#endif - putch(ch); - 1e78: 18 d0 rcall .+48 ; 0x1eaa - } while (--length); - 1e7a: da 94 dec r13 - 1e7c: ff ef ldi r31, 0xFF ; 255 - 1e7e: ef 1a sub r14, r31 - 1e80: ff 0a sbc r15, r31 - 1e82: d1 10 cpse r13, r1 - 1e84: dc cf rjmp .-72 ; 0x1e3e - 1e86: 0e c0 rjmp .+28 ; 0x1ea4 - - read_mem(desttype, address, length); - } - - /* Get device signature bytes */ - else if(ch == STK_READ_SIGN) { - 1e88: 85 37 cpi r24, 0x75 ; 117 - 1e8a: 39 f4 brne .+14 ; 0x1e9a - // READ SIGN - return what Avrdude wants to hear - verifySpace(); - 1e8c: 35 d0 rcall .+106 ; 0x1ef8 - putch(SIGNATURE_0); - 1e8e: 8e e1 ldi r24, 0x1E ; 30 - 1e90: 0c d0 rcall .+24 ; 0x1eaa - putch(SIGNATURE_1); - 1e92: 83 e9 ldi r24, 0x93 ; 147 - 1e94: 0a d0 rcall .+20 ; 0x1eaa - putch(SIGNATURE_2); - 1e96: 8c e0 ldi r24, 0x0C ; 12 - 1e98: 58 cf rjmp .-336 ; 0x1d4a - } - else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */ - 1e9a: 81 35 cpi r24, 0x51 ; 81 - 1e9c: 11 f4 brne .+4 ; 0x1ea2 - // Adaboot no-wait mod - watchdogConfig(WATCHDOG_16MS); - 1e9e: 88 e0 ldi r24, 0x08 ; 8 - 1ea0: 27 d0 rcall .+78 ; 0x1ef0 - verifySpace(); - } - else { - // This covers the response to commands like STK_ENTER_PROGMODE - verifySpace(); - 1ea2: 2a d0 rcall .+84 ; 0x1ef8 - } - putch(STK_OK); - 1ea4: 80 e1 ldi r24, 0x10 ; 16 - 1ea6: 01 d0 rcall .+2 ; 0x1eaa - } - 1ea8: 41 cf rjmp .-382 ; 0x1d2c - -00001eaa : -void putch(char ch) { -#ifndef SOFT_UART - while (!(UART_SRA & _BV(UDRE0))); - UART_UDR = ch; -#else - __asm__ __volatile__ ( - 1eaa: 2a e0 ldi r18, 0x0A ; 10 - 1eac: 30 e0 ldi r19, 0x00 ; 0 - 1eae: 80 95 com r24 - 1eb0: 08 94 sec - 1eb2: 10 f4 brcc .+4 ; 0x1eb8 - 1eb4: da 98 cbi 0x1b, 2 ; 27 - 1eb6: 02 c0 rjmp .+4 ; 0x1ebc - 1eb8: da 9a sbi 0x1b, 2 ; 27 - 1eba: 00 00 nop - 1ebc: 15 d0 rcall .+42 ; 0x1ee8 - 1ebe: 14 d0 rcall .+40 ; 0x1ee8 - 1ec0: 86 95 lsr r24 - 1ec2: 2a 95 dec r18 - 1ec4: b1 f7 brne .-20 ; 0x1eb2 - 1ec6: 08 95 ret - -00001ec8 : -} -#endif - -// Watchdog functions. These are only safe with interrupts turned off. -void watchdogReset() { - __asm__ __volatile__ ( - 1ec8: a8 95 wdr -#endif -#endif - -#ifdef SOFT_UART - watchdogReset(); - __asm__ __volatile__ ( - 1eca: 29 e0 ldi r18, 0x09 ; 9 - 1ecc: 30 e0 ldi r19, 0x00 ; 0 - 1ece: cb 99 sbic 0x19, 3 ; 25 - 1ed0: fe cf rjmp .-4 ; 0x1ece - 1ed2: 0a d0 rcall .+20 ; 0x1ee8 - 1ed4: 09 d0 rcall .+18 ; 0x1ee8 - 1ed6: 08 d0 rcall .+16 ; 0x1ee8 - 1ed8: 88 94 clc - 1eda: cb 99 sbic 0x19, 3 ; 25 - 1edc: 08 94 sec - 1ede: 2a 95 dec r18 - 1ee0: 11 f0 breq .+4 ; 0x1ee6 - 1ee2: 87 95 ror r24 - 1ee4: f7 cf rjmp .-18 ; 0x1ed4 - LED_PIN |= _BV(LED); -#endif -#endif - - return ch; -} - 1ee6: 08 95 ret - -00001ee8 : -#if UART_B_VALUE > 255 -#error Baud rate too slow for soft UART -#endif - -void uartDelay() { - __asm__ __volatile__ ( - 1ee8: 9e e0 ldi r25, 0x0E ; 14 - 1eea: 9a 95 dec r25 - 1eec: f1 f7 brne .-4 ; 0x1eea - 1eee: 08 95 ret - -00001ef0 : - "wdr\n" - ); -} - -void watchdogConfig(uint8_t x) { - WDTCSR = _BV(WDCE) | _BV(WDE); - 1ef0: 98 e1 ldi r25, 0x18 ; 24 - 1ef2: 91 bd out 0x21, r25 ; 33 - WDTCSR = x; - 1ef4: 81 bd out 0x21, r24 ; 33 - 1ef6: 08 95 ret - -00001ef8 : - do getch(); while (--count); - verifySpace(); -} - -void verifySpace() { - if (getch() != CRC_EOP) { - 1ef8: e7 df rcall .-50 ; 0x1ec8 - 1efa: 80 32 cpi r24, 0x20 ; 32 - 1efc: 19 f0 breq .+6 ; 0x1f04 - watchdogConfig(WATCHDOG_16MS); // shorten WD timeout - 1efe: 88 e0 ldi r24, 0x08 ; 8 - 1f00: f7 df rcall .-18 ; 0x1ef0 - 1f02: ff cf rjmp .-2 ; 0x1f02 - while (1) // and busy-loop so that WD causes - ; // a reset and app start. - } - putch(STK_INSYNC); - 1f04: 84 e1 ldi r24, 0x14 ; 20 - 1f06: d1 cf rjmp .-94 ; 0x1eaa - -00001f08 : - ::[count] "M" (UART_B_VALUE) - ); -} -#endif - -void getNch(uint8_t count) { - 1f08: cf 93 push r28 - 1f0a: c8 2f mov r28, r24 - do getch(); while (--count); - 1f0c: dd df rcall .-70 ; 0x1ec8 - 1f0e: c1 50 subi r28, 0x01 ; 1 - 1f10: e9 f7 brne .-6 ; 0x1f0c - verifySpace(); -} - 1f12: cf 91 pop r28 -} -#endif - -void getNch(uint8_t count) { - do getch(); while (--count); - verifySpace(); - 1f14: f1 cf rjmp .-30 ; 0x1ef8 - -00001f16 : - -void appStart(uint8_t rstFlags) { - // save the reset flags in the designated register - // This can be saved in a main program by putting code in .init0 (which - // executes before normal c init code) to save R2 to a global variable. - __asm__ __volatile__ ("mov r2, %0\n" :: "r" (rstFlags)); - 1f16: 28 2e mov r2, r24 - - watchdogConfig(WATCHDOG_OFF); - 1f18: 80 e0 ldi r24, 0x00 ; 0 - 1f1a: ea df rcall .-44 ; 0x1ef0 - // Note that appstart_vec is defined so that this works with either - // real or virtual boot partitions. - __asm__ __volatile__ ( - 1f1c: e4 e0 ldi r30, 0x04 ; 4 - 1f1e: ff 27 eor r31, r31 - 1f20: 09 94 ijmp diff --git a/optiboot/examples/test_dospm/test_dospm.ino b/optiboot/examples/test_dospm/test_dospm.ino new file mode 100644 index 0000000..32d968b --- /dev/null +++ b/optiboot/examples/test_dospm/test_dospm.ino @@ -0,0 +1,238 @@ +/*------------- Optiboot flasher example for the MiniCore ------------------| + | | + | Created May 2016 by MCUdude, https://github.com/MCUdude | + | Based on the work done by Marek Wodzinski, https://github.com/majekw | + | Released to public domain | + | | + | This is example how to use optiboot.h together with Optiboot | + | bootloader to write to FLASH memory by application code. | + | | + | IMPORTANT THINGS: | + | - All flash content gets erased after each upload cycle | + | - Buffer must be page aligned (see declaration of flash_buffer) | + | - Interrupts must be disabled during SPM | + | - Writing to EEPROM destroys temporary buffer | + | - You can write only once into one location of temporary buffer | + | - Only safely and always working sequence is erase-fill-write | + | - If you want to do fill-erase-write, you must put code in NRWW | + | and pass data!=0 for erase. It's not easy, but possible. | + | | + | WRITE SEQUENCE - OPTION 1 (used in this example) | + | 1. Erase page by optiboot_page_erase | + | 2. Write contents of page into temporary buffer by optiboot_page_fill | + | 3. Write temporary buffer to FLASH by optiboot_page_write | + | | + | WRITE SEQUENCE - OPTION 2 (works only for code in NRWW) | + | 1. Write contents of page into temporary buffer by optiboot_page_fill | + | 2. Erase page by optiboot_page_erase (set data to NOT zero) | + | 3. Write temporary buffer to FLASH by optiboot_page_write | + |-------------------------------------------------------------------------*/ + +// optiboot.h contains the functions that lets you read to +// and write from the flash memory +#include "optiboot.h" + + +// Define the number of pages you want to write to here (limited by flash size) +#define NUMBER_OF_PAGES 8 + +// Define your termination and blank character here +const char terminationChar = '@'; + +// This is the character that gets printed if the memory block doesn't contain any data +const char blankChar = '.'; + + +uint8_t charBuffer; +uint8_t menuOption; +uint16_t pageNumber; +char returnToMenu; + +// The temporary data (data that's read or is about to get written) is stored here +uint8_t ramBuffer[SPM_PAGESIZE]; + +// This array allocates the space you'll be able to write to +const uint8_t flashSpace[SPM_PAGESIZE * NUMBER_OF_PAGES] __attribute__ (( aligned(SPM_PAGESIZE) )) PROGMEM = { + "This some default content stored on page one" +}; + + + +void setup() +{ + // Initialize serial + Serial.begin(9600); +} + + +void loop() +{ + // Print main menu + Serial.println(); + Serial.println(F("|------------------------------------------------|")); + Serial.println(F("| Welcome to the Optiboot flash writer example! |")); + Serial.print(F("| Each flash page is ")); + Serial.print(SPM_PAGESIZE); + Serial.println(F(" bytes long. |")); + Serial.print(F("| There are ")); + Serial.print(NUMBER_OF_PAGES); + Serial.println(F(" pages that can be read/written to. |")); + Serial.print(F("| Total assigned flash space: ")); + Serial.print(NUMBER_OF_PAGES * SPM_PAGESIZE); + Serial.println(F(" bytes. |")); + Serial.println(F("| Change the NUMBER_OF_PAGES constant to |")); + Serial.println(F("| increase or decrease this number. |")); + Serial.println(F("| |")); + Serial.println(F("| What do you want to do? |")); + Serial.println(F("| 1. Show current flash content |")); + Serial.println(F("| 2. Write to flash memory |")); + Serial.println(F("|------------------------------------------------|")); + Serial.println(); + + + // Get menu option from the serial monitor + do + { + while(!Serial.available()); + menuOption = Serial.parseInt(); + if(menuOption < 1 || menuOption > 2) + Serial.print(F("\nPlease enter a valid option! ")); + } + while(menuOption < 1 || menuOption > 2); + + Serial.print(F("Option ")); + Serial.print(menuOption); + Serial.println(F(" selected.")); + + + + // Read flash option selected + if(menuOption == 1) + { + Serial.print(F("What page number do you want to read? Page: ")); + + //Get page number from the serial monitor + do + { + while(!Serial.available()); + pageNumber = Serial.parseInt(); + if(pageNumber < 1 || pageNumber > NUMBER_OF_PAGES) + { + Serial.print(F("\nPlease enter a valid page between 1 and ")); + Serial.print(NUMBER_OF_PAGES); + Serial.println(F(". The number of pages can be extended by changing NUMBER_OF_PAGES constant")); + } + } + while(pageNumber > NUMBER_OF_PAGES); + + if(pageNumber > 0) + Serial.println(pageNumber); + + // READ SELECTED PAGE AND STORE THE CONTENT IN THE ramBuffer ARRAY + // flash_buffer is where the data is stored (contains the memory addresses) + // ramBuffer is where the data gets stored after reading from flash + // pageNumber is the page the data is read from + // blankChar is the character that gets printed/stored if there are unused space (default '.') + // use optiboot_readPage(flashSpace, ramBuffer, pageNumber) if you don't want blank chars + + if(pageNumber == 0) // Read all pages + { + Serial.println(F("\nAll flash content:")); + for(uint16_t page = 1; page < NUMBER_OF_PAGES+1; page++) + { + Serial.print(F("Page ")); + Serial.print(page); + Serial.print(F(": ")); + optiboot_readPage(flashSpace, ramBuffer, page, blankChar); + Serial.println((char*)ramBuffer); + } + } + else // Read selected page + { + optiboot_readPage(flashSpace, ramBuffer, pageNumber, blankChar); + + // Print page content + Serial.print(F("\nContent of page ")); + Serial.print(pageNumber); + Serial.println(F(":")); + Serial.println((char*)ramBuffer); + } + + } // End of flash read option + + + + // Write flash option selected + else if(menuOption == 2) + { + // Clear pageNumber + pageNumber = 0; + + //Get page number from the serial monitor + Serial.print(F("\nWhat page do you want to write to? Page: ")); + do + { + while(!Serial.available()); + pageNumber = Serial.parseInt(); + if(pageNumber < 1 || pageNumber > NUMBER_OF_PAGES) + { + Serial.print(F("\nPlease enter a valid page between 1 and ")); + Serial.print(NUMBER_OF_PAGES); + Serial.println(F(". The number of pages can be extended by changing NUMBER_OF_PAGES constant")); + } + } + while(pageNumber < 1 || pageNumber > NUMBER_OF_PAGES); + Serial.println(pageNumber); + + // Print prompt to enter some new characters to write to flash + Serial.print(F("Please type the characters you want to store (max ")); + Serial.print(SPM_PAGESIZE); + Serial.println(F(" characters)")); + Serial.print(F("End the line by sending the '")); + Serial.write(terminationChar); + Serial.println(F("' character:")); + + // Get all characters from the serial monitor and store it to the ramBuffer + memset(ramBuffer, 0, sizeof(ramBuffer)); + uint16_t counter = 0; + while (counter < SPM_PAGESIZE && charBuffer != terminationChar) + { + if(Serial.available() > 0) + { + charBuffer = Serial.read(); // read character from serial + if(charBuffer != terminationChar) + { + Serial.write(charBuffer); // echo character back + ramBuffer[counter] = charBuffer; + counter++; + } + } + } + charBuffer = 0; + Serial.println(F("\n\nAll chars received \nWriting to flash...")); + + // WRITE RECEIVED DATA TO THE CURRENT FLASH PAGE + // flash_buffer is where the data is stored (contains the memory addresses) + // ramBuffer contains the data that's going to be stored in the flash + // pageNumber is the page the data is written to + optiboot_writePage(flashSpace, ramBuffer, pageNumber); + + Serial.println(F("Writing finished. You can now reset or power cycle the board and check for new contents!")); + } // End of flash write option + + + + //Return to the main menu if 'm' is sent + Serial.println(F("\ntype the character 'm' to return to to the main menu")); + do + { + while(!Serial.available()); + returnToMenu = Serial.read(); + if(returnToMenu != 'm') + Serial.print(F("\nPlease type a valid character! ")); + } + while(returnToMenu != 'm'); + returnToMenu = 0; + +} // End of loop + diff --git a/optiboot/release.sh b/optiboot/release.sh index 287fb9d..494bd45 100644 --- a/optiboot/release.sh +++ b/optiboot/release.sh @@ -5,6 +5,8 @@ # Build a "release" .zip file for Optiboot bootloader # Run from the build directory +version=$1 + # Uncomment if you want a clean builds of specific files # make clean # make atmega328 @@ -18,7 +20,7 @@ rm -Rf /tmp/optiboot-release # Note that the structure under "packages" (handed by boards manager) # is different than the structure under "sketchbook/hardware" would be. -TOP=/tmp/optiboot-release/Optiboot$1/ +TOP=/tmp/optiboot-release/Optiboot-$version/ # # Bootloaders directory mkdir -p $TOP/bootloaders/optiboot @@ -38,12 +40,12 @@ cp ../../boards-1.6.txt $TOP/boards.txt # # Create platform.txt, because it contains the "group" name for the boards menu -echo name=Optiboot $1 > $TOP/platform.txt -echo version=$1 >> $TOP/platform.txt +echo name=Optiboot $version > $TOP/platform.txt +echo version=$version >> $TOP/platform.txt # # Create a README file. -echo This is an Optiboot version $1 \"Binary\" Release. > $TOP/README.TXT +echo This is an Optiboot version $version \"Binary\" Release. > $TOP/README.TXT echo >> $TOP/README.TXT echo For Source code see http://github.com/Optiboot/optiboot>> $TOP/README.TXT @@ -63,11 +65,11 @@ cp *.hex $TOP/bootloaders/optiboot # # zip everything up. pushd /tmp/optiboot-release -zip -r Optiboot$1.zip Optiboot$1 -HASH=`openssl dgst -sha256 Optiboot$1.zip | sed -e 's/.* //'` -SIZE=`stat -f %z Optiboot$1.zip` +zip -r Optiboot-$version.zip Optiboot-$version +HASH=`openssl dgst -sha256 Optiboot-$version.zip | sed -e 's/.* //'` +SIZE=`stat -f %z Optiboot-$version.zip` popd -sed -e "s/#.*//" -e "s/%HASH%/$HASH/g" -e "s/%VERSION%/$1/g" -e "s/%SIZE%/$SIZE/g" ../../package_optiboot_optiboot-additional_index.json.TEMPLATE > /tmp/optiboot-release/package_optiboot_optiboot-additional_index.json +sed -e "s/#.*//" -e "s/%HASH%/$HASH/g" -e "s/%VERSION%/$version/g" -e "s/%SIZE%/$SIZE/g" ../../package_optiboot_optiboot-additional_index.json.TEMPLATE > /tmp/optiboot-release/package_optiboot_optiboot-additional_index.json # # This leaves the .zip and the .json file in /tmp/optiboot-release