1
0
mirror of https://github.com/Optiboot/optiboot.git synced 2025-07-04 16:42:25 +03:00

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.
This commit is contained in:
WestfW
2018-09-20 01:19:15 -07:00
parent b10ce15298
commit e9af37fef0
19 changed files with 1734 additions and 3018 deletions

View File

@ -236,9 +236,17 @@ SS_CMD = -DSINGLESPEED=1
endif endif
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 = $(BAUD_RATE_CMD) $(LED_START_FLASHES_CMD) $(BIGBOOT_CMD)
COMMON_OPTIONS += $(SOFT_UART_CMD) $(LED_DATA_FLASH_CMD) $(LED_CMD) $(SS_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) COMMON_OPTIONS += $(VERSION_CMD)
#UART is handled separately and only passed for devices with more than one. #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 atmega168_isp: LFUSE ?= F7
ifndef BIGBOOT ifndef BIGBOOT
# 512 byte boot # 512 byte boot
atmega168_isp: EFUSE ?= 04 atmega168_isp: EFUSE ?= FC
else else
# 1024byte boot # 1024byte boot
atmega168_isp: EFUSE ?= FA atmega168_isp: EFUSE ?= FA

View File

@ -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

View File

@ -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 $*

View File

@ -193,7 +193,7 @@ do
# Print out current build info # 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" 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 # 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
done done

View File

@ -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 $*

View File

@ -152,6 +152,7 @@
/* handling, did MORE Makefile mods. EEPROM support now */ /* handling, did MORE Makefile mods. EEPROM support now */
/* fits in 512 bytes, if you turn off LED Blinking. */ /* fits in 512 bytes, if you turn off LED Blinking. */
/* Various bigboot and virboot targets were fixed. */ /* 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 */ /* It would be good if versions implemented outside the */
/* official repository used an out-of-seqeunce version */ /* official repository used an out-of-seqeunce version */
@ -164,6 +165,10 @@
/**********************************************************/ /**********************************************************/
/* Edit History: */ /* 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 */ /* July 2018 */
/* 7.0 WestfW (with much input from Others) */ /* 7.0 WestfW (with much input from Others) */
/* Fix MCUSR treatement as per much discussion, */ /* Fix MCUSR treatement as per much discussion, */
@ -246,7 +251,7 @@
/* 4.1 WestfW: put version number in binary. */ /* 4.1 WestfW: put version number in binary. */
/**********************************************************/ /**********************************************************/
#define OPTIBOOT_MAJVER 7 #define OPTIBOOT_MAJVER 8
#define OPTIBOOT_MINVER 0 #define OPTIBOOT_MINVER 0
/* /*
@ -396,6 +401,7 @@ typedef uint8_t pagelen_t;
* supress some compile-time options we want.) * 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)); int main(void) __attribute__ ((OS_main)) __attribute__ ((section (".init9"))) __attribute__((used));
void __attribute__((noinline)) __attribute__((leaf)) putch(char); void __attribute__((noinline)) __attribute__((leaf)) putch(char);
@ -487,6 +493,23 @@ static addr16_t buff = {(uint8_t *)(RAMSTART)};
#endif // VIRTUAL_BOOT_PARTITION #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 */ /* main program starts here */
int main(void) { int main(void) {
uint8_t ch; 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 #ifdef BIGBOOT
/* /*
* Optiboot is designed to fit in 512 bytes, with a minimum feature set. * Optiboot is designed to fit in 512 bytes, with a minimum feature set.

View File

@ -1,44 +1,57 @@
:020000021000EC :020000021000EC
:10FC0000112484B7882349F0982F9A70923029F0F4 :10FC000012E0A0E0B2E0ECEAFEEF01E00BBF02C0C0
:10FC100081FF02C097EF94BF10D185E080938100EF :10FC100007900D92AC39B107D9F701C021C1112469
:10FC200082E08093C00088E18093C10086E08093E9 :10FC200084B7882369F0982F9A70923049F081FF49
:10FC3000C20080E18093C4008EE0EAD0279A86E07B :10FC300002C097EF94BF282E80E0FDD00C94000006
:10FC400020E33CEF91E0309385002093840096BB45 :10FC400085E08093810082E08093C00088E180930A
:10FC5000B09BFECF1F9AA8954091C00047FD02C0FF :10FC5000C10086E08093C20080E18093C4008EE002
:10FC6000815089F7FF24F39455E0E52E61E1D62E0B :10FC6000EAD0279A86E020E33CEF91E030938500CC
:10FC7000C3D08134C1F4C0D0C82FD0D0C23809F469 :10FC70002093840096BBB09BFECF1F9AA89540911D
:10FC80003AC0C13869F487E00CC0843709F482C0F7 :10FC8000C00047FD02C0815089F7FF24F39455E07E
:10FC9000853709F0A2C0C2D08EE1A7D087E9A5D0F0 :10FC9000E52E61E1D62EC3D08134C1F4C0D0C82F87
:10FCA00083E0A3D09FC0823411F484E103C0853483 :10FCA000D0D0C23809F43AC0C13869F488E00CC039
:10FCB00019F485E0BBD096C0853579F49DD0082F26 :10FCB000843709F482C0853709F0A2C0C2D08EE132
:10FCC0009BD0182F87FF03C08BB7816002C08BB712 :10FCC000A7D087E9A5D083E0A3D09FC0823411F4E8
:10FCD0008E7F8BBF000F111F84C0863581F48CD0BE :10FCD00084E103C0853419F485E0BBD096C0853536
:10FCE0008D3459F489D0CBB787D0C170880FC82B19 :10FCE00079F49DD0082F9BD0182F87FF03C08BB7C6
:10FCF000CBBF81E09BD080E0D4CF83E0FBCF8436C4 :10FCF000816002C08BB78E7F8BBF000F111F84C045
:10FD000009F0C3CF79D0C82FD0E0DC2FCC2774D036 :10FD0000863581F48CD08D3459F489D0CBB787D027
:10FD1000C82B72D0C82E5E01812C32E0932E6CD09D :10FD1000C170880FC82BCBBF81E09BD080E0D4CFCF
:10FD2000F40181934F01F1E0AF1AB108C1F776D029 :10FD200083E0FBCF843609F0C3CF79D0C82FD0E071
:10FD300085E4C81212C0DE5F4801A12C92E0B92E02 :10FD3000DC2FCC2774D0C82B72D0C82E5E01812C4A
:10FD4000AC16BD0609F44EC0F50161915F01C40116 :10FD400032E0932E6CD0F40181934F01F1E0AF1AB1
:10FD500082D0FFEF8F1A9F0AF3CF83E0F80187BFAD :10FD5000B108C1F776D085E4C81212C0DE5F480151
:10FD6000E89507B600FCFDCFA0E0B2E0F8018D9168 :10FD6000A12C92E0B92EAC16BD0609F44EC0F501E7
:10FD70009D910C01F7BEE8951124229732962097A9 :10FD700061915F01C4018CD0FFEF8F1A9F0AF3CF0E
:10FD8000B1F7F801E7BEE89507B600FCFDCFD7BE96 :10FD800083E0F80187BFE89507B600FCFDCFA0E04F
:10FD9000E89528C031D0C82FD0E0DC2FCC272CD05C :10FD9000B2E0F8018D919D910C01F7BEE895112418
:10FDA0005E01A82A29D0982E39D0E801F5E49F12E7 :10FDA000229732962097B1F7F801E7BEE89507B69B
:10FDB0000BC0CE0148D019D081E0A81AB108219615 :10FDB00000FCFDCFD7BEE89528C031D0C82FD0E0D9
:10FDC000A114B104B1F70EC0FE018791EF010DD06F :10FDC000DC2FCC272CD05E01A82A29D0982E39D040
:10FDD000E1E0AE1AB108C1F705C0813511F488E041 :10FDD000E801F5E49F120BC0CE0152D019D081E0AA
:10FDE00017D01CD080E101D043CF9091C00095FF87 :10FDE000A81AB1082196A114B104B1F70EC0FE0102
:10FDF000FCCF8093C60008958091C00087FFFCCFA0 :10FDF0008791EF010DD0E1E0AE1AB108C1F705C05F
:10FE00008091C00084FD01C0A8958091C60008952E :10FE0000813511F488E017D01CD080E101D043CFB8
:10FE1000E0E6F0E098E1908380830895EDDF8032A2 :10FE10009091C00095FFFCCF8093C600089580911B
:10FE200019F088E0F5DFFFCF84E1DFCFCF93C82F53 :10FE2000C00087FFFCCF8091C00084FD01C0A89571
:10FE3000E3DFC150E9F7CF91F1CF282E80E0E8DF72 :10FE30008091C6000895E0E6F0E098E19083808329
:10FE4000E0E0FF270994F999FECF92BD81BDF89AB1 :10FE40000895EDDF803219F088E0F5DFFFCF84E11F
:10FE5000992780B50895262FF999FECF1FBA92BD34 :10FE5000DFCFCF93C82FE3DFC150E9F7CF91F1CFC8
:10FE600081BD20BD0FB6F894FA9AF99A0FBE01969B :10FE6000FC010A0167BFE895112407B600FCFDCF2D
:02FE70000895F3 :10FE7000667029F0452B19F481E187BFE895089554
:02FFFE000007FA :10FE8000F999FECF92BD81BDF89A992780B5089562
:10FE9000262FF999FECF1FBA92BD81BD20BD0FB6A6
:0CFEA000F894FA9AF99A0FBE01960895A2
:10FEAC0056657273696F6E3D382E30004F50544951
:10FEBC00424F4F545F435553544F4D5645523D306E
:10FECC00004465766963653D61746D6567613132C7
:10FEDC00383000465F4350553D313630303030308D
:10FEEC00304C00424947424F4F543D3100427569F6
:10FEFC006C743A53657020323020323031383A30DD
:10FF0C00313A31383A343300554152543D30004285
:10FF1C004155445F524154453D313135323030000A
:10FF2C004C45443D4237004C45445F535441525478
:0CFF3C005F464C41534845533D330000E4
:02FFFE000008F9
:040000031000FC00ED :040000031000FC00ED
:00000001FF :00000001FF

File diff suppressed because it is too large Load Diff

View File

@ -1,31 +1,33 @@
:107E0000112484B7882349F0982F9A70923029F072 :107E000001C0DCC0112484B7882361F0982F9A70D8
:107E100081FF02C097EF94BFCCD085E080938100B2 :107E1000923041F081FF02C097EF94BF282E80E09E
:107E200082E08093C00088E18093C10086E0809367 :107E2000B8D0EEC085E08093810082E08093C000EE
:107E3000C20080E18093C4008EE0A6D0259A86E03F :107E300088E18093C10086E08093C20080E1809356
:107E400020E33CEF91E0309385002093840096BBC3 :107E4000C4008EE0A6D0259A86E020E33CEF91E0C6
:107E5000B09BFECF1D9AA8954091C00047FD02C07F :107E5000309385002093840096BBB09BFECF1D9A83
:107E6000815089F7EE24E39495E0D92E21E1C22ECA :107E6000A8954091C00047FD02C0815089F7EE24DB
:107E70007FD0813461F47CD0182F8CD01238E9F097 :107E7000E39495E0D92E21E1C22E7FD0813461F4C4
:107E8000113811F487E001C083E06BD067C0823401 :107E80007CD0182F8CD01238E9F0113811F488E02A
:107E900011F484E103C0853419F485E083D05EC019 :107E900001C083E06BD067C0823411F484E103C079
:107EA000853539F465D0C82F63D0D82FCC0FDD1FAE :107EA000853419F485E083D05EC0853539F465D01A
:107EB00054C0863521F484E075D080E0E6CF843666 :107EB000C82F63D0D82FCC0FDD1F54C0863521F4D6
:107EC00009F02EC055D054D0F82E52D0B82E00E074 :107EC00084E075D080E0E6CF843609F02EC055D02E
:107ED00011E04ED0F80181938F01FE12FACF5AD0F3 :107ED00054D0F82E52D0B82E00E011E04ED0F80168
:107EE000F5E4BF1201C0FFCF83E0FE0187BFE89534 :107EE00081938F01FE12FACF5AD0F5E4BF1201C080
:107EF00007B600FCFDCFA0E0B1E0FE018D919D91A1 :107EF000FFCF83E0FE0187BFE89507B600FCFDCF0A
:107F00000C01E7BEE89511243296FA12F7CFFE0174 :107F0000A0E0B1E0FE018D919D910C01E7BEE895E6
:107F1000D7BEE89507B600FCFDCFC7BEE8951EC0EA :107F100011243296FA12F7CFFE01D7BEE89507B6C4
:107F2000843771F425D024D0F82E22D033D08E019E :107F200000FCFDCFC7BEE8951EC0843771F425D094
:107F3000F80185918F0115D0FA94F110F9CF0EC098 :107F300024D0F82E22D033D08E01F80185918F0104
:107F4000853739F427D08EE10CD085E90AD08FE04F :107F400015D0FA94F110F9CF0EC0853739F427D047
:107F50009CCF813511F488E017D01CD080E101D08E :107F50008EE10CD085E90AD08FE09CCF813511F4F9
:107F600087CF9091C00095FFFCCF8093C600089505 :107F600088E017D01CD080E101D087CF9091C0006D
:107F70008091C00087FFFCCF8091C00084FD01C0CC :107F700095FFFCCF8093C60008958091C00087FFD5
:107F8000A8958091C6000895E0E6F0E098E190831E :107F8000FCCF8091C00084FD01C0A8958091C600FF
:107F900080830895EDDF803219F088E0F5DFFFCFB0 :107F90000895E0E6F0E098E1908380830895EDDFB6
:107FA00084E1DFCFCF93C82FE3DFC150E9F7CF9152 :107FA000803219F088E0F5DFFFCF84E1DFCFCF9397
:0E7FB000F1CF282E80E0E8DFE0E0FF27099403 :107FB000C82FE3DFC150E9F7CF91F1CFFC010A01EF
:027FFE0000077A :107FC00067BFE895112407B600FCFDCF667029F065
:0C7FD000452B19F481E187BFE895089566
:027FFE00000879
:0400000300007E007B :0400000300007E007B
:00000001FF :00000001FF

View File

@ -3,582 +3,638 @@ optiboot_atmega328.elf: file format elf32-avr
Sections: Sections:
Idx Name Size VMA LMA File off Algn 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 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 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 CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .comment 0000002f 00000000 00000000 00000254 2**0 3 .comment 0000002f 00000000 00000000 00000272 2**0
CONTENTS, READONLY CONTENTS, READONLY
4 .debug_aranges 00000028 00000000 00000000 00000283 2**0 4 .debug_aranges 00000030 00000000 00000000 000002a1 2**0
CONTENTS, READONLY, DEBUGGING CONTENTS, READONLY, DEBUGGING
5 .debug_info 000005c8 00000000 00000000 000002ab 2**0 5 .debug_info 000005fd 00000000 00000000 000002d1 2**0
CONTENTS, READONLY, DEBUGGING CONTENTS, READONLY, DEBUGGING
6 .debug_abbrev 00000282 00000000 00000000 00000873 2**0 6 .debug_abbrev 000002c1 00000000 00000000 000008ce 2**0
CONTENTS, READONLY, DEBUGGING CONTENTS, READONLY, DEBUGGING
7 .debug_line 000002f9 00000000 00000000 00000af5 2**0 7 .debug_line 00000334 00000000 00000000 00000b8f 2**0
CONTENTS, READONLY, DEBUGGING CONTENTS, READONLY, DEBUGGING
8 .debug_frame 0000008c 00000000 00000000 00000df0 2**2 8 .debug_frame 0000009c 00000000 00000000 00000ec4 2**2
CONTENTS, READONLY, DEBUGGING CONTENTS, READONLY, DEBUGGING
9 .debug_str 000001fa 00000000 00000000 00000e7c 2**0 9 .debug_str 00000200 00000000 00000000 00000f60 2**0
CONTENTS, READONLY, DEBUGGING CONTENTS, READONLY, DEBUGGING
10 .debug_loc 00000331 00000000 00000000 00001076 2**0 10 .debug_loc 00000359 00000000 00000000 00001160 2**0
CONTENTS, READONLY, DEBUGGING CONTENTS, READONLY, DEBUGGING
11 .debug_ranges 00000060 00000000 00000000 000013a7 2**0 11 .debug_ranges 00000068 00000000 00000000 000014b9 2**0
CONTENTS, READONLY, DEBUGGING CONTENTS, READONLY, DEBUGGING
Disassembly of section .text: Disassembly of section .text:
00007e00 <main>: 00007e00 <pre_main>:
/* 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 <main>
7e02: dc c0 rjmp .+440 ; 0x7fbc <do_spm>
00007e04 <main>:
// SP points to RAMEND // SP points to RAMEND
// r1 contains zero // r1 contains zero
// //
// If not, uncomment the following instructions: // If not, uncomment the following instructions:
// cli(); // cli();
asm volatile ("clr __zero_reg__"); asm volatile ("clr __zero_reg__");
7e00: 11 24 eor r1, r1 7e04: 11 24 eor r1, r1
* #if defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) || \
* Code by MarkG55 defined(__AVR_ATmega16__) || defined(__AVR_ATmega162__) || \
* see discusion in https://github.com/Optiboot/optiboot/issues/97 defined (__AVR_ATmega128__)
*/
#if !defined(__AVR_ATmega16__)
ch = MCUSR;
7e02: 84 b7 in r24, 0x34 ; 52
#else
ch = MCUCSR; ch = MCUCSR;
#else
ch = MCUSR;
7e06: 84 b7 in r24, 0x34 ; 52
#endif #endif
// Skip all logic and run bootloader if MCUSR is cleared (application request) // Skip all logic and run bootloader if MCUSR is cleared (application request)
if (ch != 0) { if (ch != 0) {
7e04: 88 23 and r24, r24 7e08: 88 23 and r24, r24
7e06: 49 f0 breq .+18 ; 0x7e1a <main+0x1a> 7e0a: 61 f0 breq .+24 ; 0x7e24 <main+0x20>
* 2. we clear WDRF if it's set with EXTRF to avoid loops * 2. we clear WDRF if it's set with EXTRF to avoid loops
* One problematic scenario: broken application code sets watchdog timer * One problematic scenario: broken application code sets watchdog timer
* without clearing MCUSR before and triggers it quickly. But it's * without clearing MCUSR before and triggers it quickly. But it's
* recoverable by power-on with pushed reset button. * recoverable by power-on with pushed reset button.
*/ */
if ((ch & (_BV(WDRF) | _BV(EXTRF))) != _BV(EXTRF)) { if ((ch & (_BV(WDRF) | _BV(EXTRF))) != _BV(EXTRF)) {
7e08: 98 2f mov r25, r24 7e0c: 98 2f mov r25, r24
7e0a: 9a 70 andi r25, 0x0A ; 10 7e0e: 9a 70 andi r25, 0x0A ; 10
7e0c: 92 30 cpi r25, 0x02 ; 2 7e10: 92 30 cpi r25, 0x02 ; 2
7e0e: 29 f0 breq .+10 ; 0x7e1a <main+0x1a> 7e12: 41 f0 breq .+16 ; 0x7e24 <main+0x20>
if (ch & _BV(EXTRF)) { if (ch & _BV(EXTRF)) {
7e10: 81 ff sbrs r24, 1 7e14: 81 ff sbrs r24, 1
7e12: 02 c0 rjmp .+4 ; 0x7e18 <main+0x18> 7e16: 02 c0 rjmp .+4 ; 0x7e1c <main+0x18>
* prevent entering bootloader. defined(__AVR_ATmega16__) || defined(__AVR_ATmega162__) || \
* '&' operation is skipped to spare few bytes as bits in MCUSR defined(__AVR_ATmega128__)
* can only be cleared. // Fix missing definitions in avr-libc
*/ MCUCSR = ~(_BV(WDRF));
#if !defined(__AVR_ATmega16__)
MCUSR = ~(_BV(WDRF));
7e14: 97 ef ldi r25, 0xF7 ; 247
7e16: 94 bf out 0x34, r25 ; 52
#else #else
MCUCSR = ~(_BV(WDRF)); MCUSR = ~(_BV(WDRF));
#endif 7e18: 97 ef ldi r25, 0xF7 ; 247
} 7e1a: 94 bf out 0x34, r25 ; 52
appStart(ch); /*
7e18: cc d0 rcall .+408 ; 0x7fb2 <appStart> * 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 <watchdogConfig>
// 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 <optiboot_version+0x2>
} }
} }
#if LED_START_FLASHES > 0 #if LED_START_FLASHES > 0
// Set up Timer 1 for timeout counter // Set up Timer 1 for timeout counter
TCCR1B = _BV(CS12) | _BV(CS10); // div 1024 TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
7e1a: 85 e0 ldi r24, 0x05 ; 5 7e24: 85 e0 ldi r24, 0x05 ; 5
7e1c: 80 93 81 00 sts 0x0081, r24 ; 0x800081 <__TEXT_REGION_LENGTH__+0x7e0081> 7e26: 80 93 81 00 sts 0x0081, r24 ; 0x800081 <__TEXT_REGION_LENGTH__+0x7e0081>
UCSRA = _BV(U2X); //Double speed mode USART LINBTR = (1 << LDISR) | (8 << LBT0);
UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx LINCR = _BV(LENA) | _BV(LCMD2) | _BV(LCMD1) | _BV(LCMD0);
UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1 LINDAT=0;
UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 ); #else
#else #ifndef SINGLESPEED
UART_SRA = _BV(U2X0); //Double speed mode USART0 UART_SRA = _BV(U2X0); //Double speed mode USART0
7e20: 82 e0 ldi r24, 0x02 ; 2 7e2a: 82 e0 ldi r24, 0x02 ; 2
7e22: 80 93 c0 00 sts 0x00C0, r24 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> 7e2c: 80 93 c0 00 sts 0x00C0, r24 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0>
#endif
UART_SRB = _BV(RXEN0) | _BV(TXEN0); UART_SRB = _BV(RXEN0) | _BV(TXEN0);
7e26: 88 e1 ldi r24, 0x18 ; 24 7e30: 88 e1 ldi r24, 0x18 ; 24
7e28: 80 93 c1 00 sts 0x00C1, r24 ; 0x8000c1 <__TEXT_REGION_LENGTH__+0x7e00c1> 7e32: 80 93 c1 00 sts 0x00C1, r24 ; 0x8000c1 <__TEXT_REGION_LENGTH__+0x7e00c1>
UART_SRC = _BV(UCSZ00) | _BV(UCSZ01); UART_SRC = _BV(UCSZ00) | _BV(UCSZ01);
7e2c: 86 e0 ldi r24, 0x06 ; 6 7e36: 86 e0 ldi r24, 0x06 ; 6
7e2e: 80 93 c2 00 sts 0x00C2, r24 ; 0x8000c2 <__TEXT_REGION_LENGTH__+0x7e00c2> 7e38: 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 ); UART_SRL = (uint8_t)BAUD_SETTING;
7e32: 80 e1 ldi r24, 0x10 ; 16 7e3c: 80 e1 ldi r24, 0x10 ; 16
7e34: 80 93 c4 00 sts 0x00C4, r24 ; 0x8000c4 <__TEXT_REGION_LENGTH__+0x7e00c4> 7e3e: 80 93 c4 00 sts 0x00C4, r24 ; 0x8000c4 <__TEXT_REGION_LENGTH__+0x7e00c4>
#endif #endif // LIN_UART
#endif #endif // mega8/etc
#endif // soft_uart
// Set up watchdog to trigger after 1s // Set up watchdog to trigger after 1s
watchdogConfig(WATCHDOG_1S); watchdogConfig(WATCHDOG_1S);
7e38: 8e e0 ldi r24, 0x0E ; 14 7e42: 8e e0 ldi r24, 0x0E ; 14
7e3a: a6 d0 rcall .+332 ; 0x7f88 <watchdogConfig> 7e44: a6 d0 rcall .+332 ; 0x7f92 <watchdogConfig>
#if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH) || defined(LED_START_ON) #if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH) || defined(LED_START_ON)
/* Set LED pin as output */ /* Set LED pin as output */
LED_DDR |= _BV(LED); LED_DDR |= _BV(LED);
7e3c: 25 9a sbi 0x04, 5 ; 4 7e46: 25 9a sbi 0x04, 5 ; 4
7e3e: 86 e0 ldi r24, 0x06 ; 6 7e48: 86 e0 ldi r24, 0x06 ; 6
} }
#if LED_START_FLASHES > 0 #if LED_START_FLASHES > 0
void flash_led(uint8_t count) { void flash_led(uint8_t count) {
do { do {
TCNT1 = -(F_CPU/(1024*16)); TCNT1 = -(F_CPU/(1024*16));
7e40: 20 e3 ldi r18, 0x30 ; 48 7e4a: 20 e3 ldi r18, 0x30 ; 48
7e42: 3c ef ldi r19, 0xFC ; 252 7e4c: 3c ef ldi r19, 0xFC ; 252
TIFR1 = _BV(TOV1); TIFR1 = _BV(TOV1);
7e44: 91 e0 ldi r25, 0x01 ; 1 7e4e: 91 e0 ldi r25, 0x01 ; 1
} }
#if LED_START_FLASHES > 0 #if LED_START_FLASHES > 0
void flash_led(uint8_t count) { void flash_led(uint8_t count) {
do { do {
TCNT1 = -(F_CPU/(1024*16)); TCNT1 = -(F_CPU/(1024*16));
7e46: 30 93 85 00 sts 0x0085, r19 ; 0x800085 <__TEXT_REGION_LENGTH__+0x7e0085> 7e50: 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> 7e54: 20 93 84 00 sts 0x0084, r18 ; 0x800084 <__TEXT_REGION_LENGTH__+0x7e0084>
TIFR1 = _BV(TOV1); TIFR1 = _BV(TOV1);
7e4e: 96 bb out 0x16, r25 ; 22 7e58: 96 bb out 0x16, r25 ; 22
while(!(TIFR1 & _BV(TOV1))); while(!(TIFR1 & _BV(TOV1)));
7e50: b0 9b sbis 0x16, 0 ; 22 7e5a: b0 9b sbis 0x16, 0 ; 22
7e52: fe cf rjmp .-4 ; 0x7e50 <main+0x50> 7e5c: fe cf rjmp .-4 ; 0x7e5a <main+0x56>
#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega16__) defined(__AVR_ATmega8535__) || defined(__AVR_ATmega16__) || \
defined(__AVR_ATmega162__) || defined(__AVR_ATmega32__) || \
defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
LED_PORT ^= _BV(LED); LED_PORT ^= _BV(LED);
#else #else
LED_PIN |= _BV(LED); LED_PIN |= _BV(LED);
7e54: 1d 9a sbi 0x03, 5 ; 3 7e5e: 1d 9a sbi 0x03, 5 ; 3
} }
#endif #endif
// Watchdog functions. These are only safe with interrupts turned off. // Watchdog functions. These are only safe with interrupts turned off.
void watchdogReset() { void watchdogReset() {
__asm__ __volatile__ ( __asm__ __volatile__ (
7e56: a8 95 wdr 7e60: a8 95 wdr
* While in theory, the STK500 initial commands would be buffered
* by the UART hardware, avrdude sends several attempts in rather * by the UART hardware, avrdude sends several attempts in rather
* quick succession, some of which will be lost and cause us to * quick succession, some of which will be lost and cause us to
* get out of sync. So if we see any data; stop blinking. * get out of sync. So if we see any data; stop blinking.
*/ */
#ifndef LIN_UART
if (UART_SRA & _BV(RXC0)) if (UART_SRA & _BV(RXC0))
7e58: 40 91 c0 00 lds r20, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> 7e62: 40 91 c0 00 lds r20, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0>
7e5c: 47 fd sbrc r20, 7 7e66: 47 fd sbrc r20, 7
7e5e: 02 c0 rjmp .+4 ; 0x7e64 <main+0x64> 7e68: 02 c0 rjmp .+4 ; 0x7e6e <main+0x6a>
7e60: 81 50 subi r24, 0x01 ; 1 7e6a: 81 50 subi r24, 0x01 ; 1
#else #else
// This doesn't seem to work? // This doesn't seem to work?
// if ((UART_PIN & (1<<UART_RX_BIT)) == 0) // if ((UART_PIN & (1<<UART_RX_BIT)) == 0)
// break; // detect start bit on soft uart too. // break; // detect start bit on soft uart too.
#endif #endif
} while (--count); } while (--count);
7e62: 89 f7 brne .-30 ; 0x7e46 <main+0x46> 7e6c: 89 f7 brne .-30 ; 0x7e50 <main+0x4c>
/* /*
* Copy data from the buffer into the flash write buffer. * Copy data from the buffer into the flash write buffer.
*/ */
do { do {
__boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++)); __boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++));
7e64: ee 24 eor r14, r14 7e6e: ee 24 eor r14, r14
7e66: e3 94 inc r14 7e70: e3 94 inc r14
} while (len -= 2); } while (len -= 2);
/* /*
* Actually Write the buffer to flash (and wait for it to finish.) * Actually Write the buffer to flash (and wait for it to finish.)
*/ */
__boot_page_write_short(address.word); __boot_page_write_short(address.word);
7e68: 95 e0 ldi r25, 0x05 ; 5 7e72: 95 e0 ldi r25, 0x05 ; 5
7e6a: d9 2e mov r13, r25 7e74: d9 2e mov r13, r25
boot_spm_busy_wait(); boot_spm_busy_wait();
#if defined(RWWSRE) #if defined(RWWSRE)
// Reenable read access to flash // Reenable read access to flash
__boot_rww_enable_short(); __boot_rww_enable_short();
7e6c: 21 e1 ldi r18, 0x11 ; 17 7e76: 21 e1 ldi r18, 0x11 ; 17
#endif #endif
/* Forever loop: exits by causing WDT reset */ /* Forever loop: exits by causing WDT reset */
for (;;) { for (;;) {
/* get character from UART */ /* get character from UART */
ch = getch(); ch = getch();
7e6e: c2 2e mov r12, r18 7e78: c2 2e mov r12, r18
if(ch == STK_GET_PARAMETER) { if(ch == STK_GET_PARAMETER) {
7e70: 7f d0 rcall .+254 ; 0x7f70 <getch> 7e7a: 7f d0 rcall .+254 ; 0x7f7a <getch>
unsigned char which = getch(); unsigned char which = getch();
7e72: 81 34 cpi r24, 0x41 ; 65 7e7c: 81 34 cpi r24, 0x41 ; 65
7e74: 61 f4 brne .+24 ; 0x7e8e <main+0x8e> 7e7e: 61 f4 brne .+24 ; 0x7e98 <main+0x94>
7e76: 7c d0 rcall .+248 ; 0x7f70 <getch> 7e80: 7c d0 rcall .+248 ; 0x7f7a <getch>
verifySpace(); verifySpace();
7e78: 18 2f mov r17, r24 7e82: 18 2f mov r17, r24
7e7a: 8c d0 rcall .+280 ; 0x7f94 <verifySpace> 7e84: 8c d0 rcall .+280 ; 0x7f9e <verifySpace>
/* /*
* Send optiboot version as "SW version" * Send optiboot version as "SW version"
* Note that the references to memory are optimized away. * Note that the references to memory are optimized away.
*/ */
if (which == STK_SW_MINOR) { if (which == STK_SW_MINOR) {
7e7c: 12 38 cpi r17, 0x82 ; 130 7e86: 12 38 cpi r17, 0x82 ; 130
7e7e: e9 f0 breq .+58 ; 0x7eba <main+0xba> 7e88: e9 f0 breq .+58 ; 0x7ec4 <main+0xc0>
putch(optiboot_version & 0xFF); putch(optiboot_version & 0xFF);
} else if (which == STK_SW_MAJOR) { } else if (which == STK_SW_MAJOR) {
7e80: 11 38 cpi r17, 0x81 ; 129 7e8a: 11 38 cpi r17, 0x81 ; 129
putch(optiboot_version >> 8); putch(optiboot_version >> 8);
7e82: 11 f4 brne .+4 ; 0x7e88 <main+0x88> 7e8c: 11 f4 brne .+4 ; 0x7e92 <main+0x8e>
7e84: 87 e0 ldi r24, 0x07 ; 7 7e8e: 88 e0 ldi r24, 0x08 ; 8
} else { } else {
/* /*
* GET PARAMETER returns a generic 0x03 reply for * GET PARAMETER returns a generic 0x03 reply for
* other parameters - enough to keep Avrdude happy * other parameters - enough to keep Avrdude happy
*/ */
putch(0x03); putch(0x03);
7e86: 01 c0 rjmp .+2 ; 0x7e8a <main+0x8a> 7e90: 01 c0 rjmp .+2 ; 0x7e94 <main+0x90>
7e88: 83 e0 ldi r24, 0x03 ; 3 7e92: 83 e0 ldi r24, 0x03 ; 3
7e8a: 6b d0 rcall .+214 ; 0x7f62 <putch> 7e94: 6b d0 rcall .+214 ; 0x7f6c <putch>
7e8c: 67 c0 rjmp .+206 ; 0x7f5c <main+0x15c> 7e96: 67 c0 rjmp .+206 ; 0x7f66 <main+0x162>
} }
} }
else if(ch == STK_SET_DEVICE) { else if(ch == STK_SET_DEVICE) {
7e8e: 82 34 cpi r24, 0x42 ; 66 7e98: 82 34 cpi r24, 0x42 ; 66
// SET DEVICE is ignored // SET DEVICE is ignored
getNch(20); getNch(20);
7e90: 11 f4 brne .+4 ; 0x7e96 <main+0x96> 7e9a: 11 f4 brne .+4 ; 0x7ea0 <main+0x9c>
7e92: 84 e1 ldi r24, 0x14 ; 20 7e9c: 84 e1 ldi r24, 0x14 ; 20
} }
else if(ch == STK_SET_DEVICE_EXT) { else if(ch == STK_SET_DEVICE_EXT) {
7e94: 03 c0 rjmp .+6 ; 0x7e9c <main+0x9c> 7e9e: 03 c0 rjmp .+6 ; 0x7ea6 <main+0xa2>
// SET DEVICE EXT is ignored // SET DEVICE EXT is ignored
getNch(5); getNch(5);
7e96: 85 34 cpi r24, 0x45 ; 69 7ea0: 85 34 cpi r24, 0x45 ; 69
7e98: 19 f4 brne .+6 ; 0x7ea0 <main+0xa0> 7ea2: 19 f4 brne .+6 ; 0x7eaa <main+0xa6>
7e9a: 85 e0 ldi r24, 0x05 ; 5 7ea4: 85 e0 ldi r24, 0x05 ; 5
} }
else if(ch == STK_LOAD_ADDRESS) { else if(ch == STK_LOAD_ADDRESS) {
7e9c: 83 d0 rcall .+262 ; 0x7fa4 <getNch> 7ea6: 83 d0 rcall .+262 ; 0x7fae <getNch>
7e9e: 5e c0 rjmp .+188 ; 0x7f5c <main+0x15c> 7ea8: 5e c0 rjmp .+188 ; 0x7f66 <main+0x162>
// LOAD ADDRESS // LOAD ADDRESS
address.bytes[0] = getch(); address.bytes[0] = getch();
7ea0: 85 35 cpi r24, 0x55 ; 85 7eaa: 85 35 cpi r24, 0x55 ; 85
7ea2: 39 f4 brne .+14 ; 0x7eb2 <main+0xb2> 7eac: 39 f4 brne .+14 ; 0x7ebc <main+0xb8>
7ea4: 65 d0 rcall .+202 ; 0x7f70 <getch> 7eae: 65 d0 rcall .+202 ; 0x7f7a <getch>
address.bytes[1] = getch(); address.bytes[1] = getch();
7ea6: c8 2f mov r28, r24 7eb0: c8 2f mov r28, r24
7ea8: 63 d0 rcall .+198 ; 0x7f70 <getch> 7eb2: 63 d0 rcall .+198 ; 0x7f7a <getch>
} }
else { else {
RAMPZ &= 0xFE; RAMPZ &= 0xFE;
} }
#endif #endif
address.word *= 2; // Convert from word address to byte address address.word *= 2; // Convert from word address to byte address
7eaa: d8 2f mov r29, r24 7eb4: d8 2f mov r29, r24
7eac: cc 0f add r28, r28 7eb6: cc 0f add r28, r28
7eae: dd 1f adc r29, r29 7eb8: dd 1f adc r29, r29
verifySpace(); verifySpace();
} }
else if(ch == STK_UNIVERSAL) { else if(ch == STK_UNIVERSAL) {
7eb0: 54 c0 rjmp .+168 ; 0x7f5a <main+0x15a> 7eba: 54 c0 rjmp .+168 ; 0x7f64 <main+0x160>
getNch(3); getNch(3);
putch(0x00); putch(0x00);
} }
#else #else
// UNIVERSAL command is ignored // UNIVERSAL command is ignored
getNch(4); getNch(4);
7eb2: 86 35 cpi r24, 0x56 ; 86 7ebc: 86 35 cpi r24, 0x56 ; 86
7eb4: 21 f4 brne .+8 ; 0x7ebe <main+0xbe> 7ebe: 21 f4 brne .+8 ; 0x7ec8 <main+0xc4>
putch(0x00); putch(0x00);
7eb6: 84 e0 ldi r24, 0x04 ; 4 7ec0: 84 e0 ldi r24, 0x04 ; 4
7eb8: 75 d0 rcall .+234 ; 0x7fa4 <getNch> 7ec2: 75 d0 rcall .+234 ; 0x7fae <getNch>
#endif #endif
} }
/* Write memory, length is big endian and is in bytes */ /* Write memory, length is big endian and is in bytes */
else if(ch == STK_PROG_PAGE) { else if(ch == STK_PROG_PAGE) {
7eba: 80 e0 ldi r24, 0x00 ; 0 7ec4: 80 e0 ldi r24, 0x00 ; 0
7ebc: e6 cf rjmp .-52 ; 0x7e8a <main+0x8a> 7ec6: e6 cf rjmp .-52 ; 0x7e94 <main+0x90>
// PROGRAM PAGE - we support flash programming only, not EEPROM // PROGRAM PAGE - we support flash programming only, not EEPROM
uint8_t desttype; uint8_t desttype;
uint8_t *bufPtr; uint8_t *bufPtr;
pagelen_t savelength; pagelen_t savelength;
GETLENGTH(length); GETLENGTH(length);
7ebe: 84 36 cpi r24, 0x64 ; 100 7ec8: 84 36 cpi r24, 0x64 ; 100
7ec0: 09 f0 breq .+2 ; 0x7ec4 <main+0xc4> 7eca: 09 f0 breq .+2 ; 0x7ece <main+0xca>
7ec2: 2e c0 rjmp .+92 ; 0x7f20 <main+0x120> 7ecc: 2e c0 rjmp .+92 ; 0x7f2a <main+0x126>
7ec4: 55 d0 rcall .+170 ; 0x7f70 <getch> 7ece: 55 d0 rcall .+170 ; 0x7f7a <getch>
savelength = length; savelength = length;
desttype = getch(); desttype = getch();
7ec6: 54 d0 rcall .+168 ; 0x7f70 <getch> 7ed0: 54 d0 rcall .+168 ; 0x7f7a <getch>
7ec8: f8 2e mov r15, r24 7ed2: f8 2e mov r15, r24
7eca: 52 d0 rcall .+164 ; 0x7f70 <getch> 7ed4: 52 d0 rcall .+164 ; 0x7f7a <getch>
7ecc: b8 2e mov r11, r24 7ed6: b8 2e mov r11, r24
7ece: 00 e0 ldi r16, 0x00 ; 0 7ed8: 00 e0 ldi r16, 0x00 ; 0
// read a page worth of contents // read a page worth of contents
bufPtr = buff.bptr; bufPtr = buff.bptr;
do *bufPtr++ = getch(); do *bufPtr++ = getch();
7ed0: 11 e0 ldi r17, 0x01 ; 1 7eda: 11 e0 ldi r17, 0x01 ; 1
7ed2: 4e d0 rcall .+156 ; 0x7f70 <getch> 7edc: 4e d0 rcall .+156 ; 0x7f7a <getch>
7ed4: f8 01 movw r30, r16 7ede: f8 01 movw r30, r16
7ed6: 81 93 st Z+, r24 7ee0: 81 93 st Z+, r24
7ed8: 8f 01 movw r16, r30 7ee2: 8f 01 movw r16, r30
while (--length); while (--length);
7eda: fe 12 cpse r15, r30 7ee4: fe 12 cpse r15, r30
7edc: fa cf rjmp .-12 ; 0x7ed2 <main+0xd2> 7ee6: fa cf rjmp .-12 ; 0x7edc <main+0xd8>
// Read command terminator, start reply // Read command terminator, start reply
verifySpace(); verifySpace();
7ede: 5a d0 rcall .+180 ; 0x7f94 <verifySpace> 7ee8: 5a d0 rcall .+180 ; 0x7f9e <verifySpace>
7ee0: f5 e4 ldi r31, 0x45 ; 69 7eea: f5 e4 ldi r31, 0x45 ; 69
* void writebuffer(memtype, buffer, address, length) * void writebuffer(memtype, buffer, address, length)
*/ */
static inline void writebuffer(int8_t memtype, addr16_t mybuff, static inline void writebuffer(int8_t memtype, addr16_t mybuff,
addr16_t address, pagelen_t len) addr16_t address, pagelen_t len)
{ {
switch (memtype) { switch (memtype) {
7ee2: bf 12 cpse r11, r31 7eec: bf 12 cpse r11, r31
7ee4: 01 c0 rjmp .+2 ; 0x7ee8 <main+0xe8> 7eee: 01 c0 rjmp .+2 ; 0x7ef2 <main+0xee>
7ee6: ff cf rjmp .-2 ; 0x7ee6 <main+0xe6> 7ef0: ff cf rjmp .-2 ; 0x7ef0 <main+0xec>
7ee8: 83 e0 ldi r24, 0x03 ; 3 7ef2: 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. * and we needed the space back.
*/ */
#ifdef FOURPAGEERASE
if ((address.bytes[0] & ((SPM_PAGESIZE<<2)-1))==0) {
#endif
__boot_page_erase_short(address.word); __boot_page_erase_short(address.word);
7eea: fe 01 movw r30, r28 7ef4: fe 01 movw r30, r28
7eec: 87 bf out 0x37, r24 ; 55 7ef6: 87 bf out 0x37, r24 ; 55
7eee: e8 95 spm 7ef8: e8 95 spm
7ef0: 07 b6 in r0, 0x37 ; 55 7efa: 07 b6 in r0, 0x37 ; 55
boot_spm_busy_wait(); boot_spm_busy_wait();
7ef2: 00 fc sbrc r0, 0 7efc: 00 fc sbrc r0, 0
7ef4: fd cf rjmp .-6 ; 0x7ef0 <main+0xf0> 7efe: fd cf rjmp .-6 ; 0x7efa <main+0xf6>
7ef6: a0 e0 ldi r26, 0x00 ; 0 7f00: a0 e0 ldi r26, 0x00 ; 0
7ef8: b1 e0 ldi r27, 0x01 ; 1 7f02: b1 e0 ldi r27, 0x01 ; 1
7efa: fe 01 movw r30, r28 7f04: fe 01 movw r30, r28
7efc: 8d 91 ld r24, X+ 7f06: 8d 91 ld r24, X+
/* /*
* Copy data from the buffer into the flash write buffer. * Copy data from the buffer into the flash write buffer.
*/ */
do { do {
__boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++)); __boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++));
7efe: 9d 91 ld r25, X+ 7f08: 9d 91 ld r25, X+
7f00: 0c 01 movw r0, r24 7f0a: 0c 01 movw r0, r24
7f02: e7 be out 0x37, r14 ; 55 7f0c: e7 be out 0x37, r14 ; 55
7f04: e8 95 spm 7f0e: e8 95 spm
7f06: 11 24 eor r1, r1 7f10: 11 24 eor r1, r1
7f08: 32 96 adiw r30, 0x02 ; 2 7f12: 32 96 adiw r30, 0x02 ; 2
addrPtr += 2; addrPtr += 2;
} while (len -= 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.) * Actually Write the buffer to flash (and wait for it to finish.)
*/ */
__boot_page_write_short(address.word); __boot_page_write_short(address.word);
7f0c: f7 cf rjmp .-18 ; 0x7efc <main+0xfc> 7f16: f7 cf rjmp .-18 ; 0x7f06 <main+0x102>
7f0e: fe 01 movw r30, r28 7f18: fe 01 movw r30, r28
boot_spm_busy_wait(); boot_spm_busy_wait();
7f10: d7 be out 0x37, r13 ; 55 7f1a: d7 be out 0x37, r13 ; 55
7f12: e8 95 spm 7f1c: e8 95 spm
#if defined(RWWSRE) #if defined(RWWSRE)
// Reenable read access to flash // Reenable read access to flash
__boot_rww_enable_short(); __boot_rww_enable_short();
7f14: 07 b6 in r0, 0x37 ; 55 7f1e: 07 b6 in r0, 0x37 ; 55
7f16: 00 fc sbrc r0, 0 7f20: 00 fc sbrc r0, 0
7f18: fd cf rjmp .-6 ; 0x7f14 <main+0x114> 7f22: fd cf rjmp .-6 ; 0x7f1e <main+0x11a>
writebuffer(desttype, buff, address, savelength); writebuffer(desttype, buff, address, savelength);
} }
/* Read memory block mode, length is big endian. */ /* Read memory block mode, length is big endian. */
else if(ch == STK_READ_PAGE) { else if(ch == STK_READ_PAGE) {
7f1a: c7 be out 0x37, r12 ; 55 7f24: c7 be out 0x37, r12 ; 55
7f1c: e8 95 spm 7f26: e8 95 spm
uint8_t desttype; uint8_t desttype;
GETLENGTH(length); GETLENGTH(length);
7f1e: 1e c0 rjmp .+60 ; 0x7f5c <main+0x15c> 7f28: 1e c0 rjmp .+60 ; 0x7f66 <main+0x162>
7f20: 84 37 cpi r24, 0x74 ; 116 7f2a: 84 37 cpi r24, 0x74 ; 116
7f22: 71 f4 brne .+28 ; 0x7f40 <main+0x140> 7f2c: 71 f4 brne .+28 ; 0x7f4a <main+0x146>
desttype = getch(); desttype = getch();
7f24: 25 d0 rcall .+74 ; 0x7f70 <getch> 7f2e: 25 d0 rcall .+74 ; 0x7f7a <getch>
verifySpace(); verifySpace();
7f26: 24 d0 rcall .+72 ; 0x7f70 <getch> 7f30: 24 d0 rcall .+72 ; 0x7f7a <getch>
7f28: f8 2e mov r15, r24 7f32: f8 2e mov r15, r24
7f2a: 22 d0 rcall .+68 ; 0x7f70 <getch> 7f34: 22 d0 rcall .+68 ; 0x7f7a <getch>
// while (--length); // while (--length);
// read a Flash and increment the address (may increment RAMPZ) // read a Flash and increment the address (may increment RAMPZ)
__asm__ ("elpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address)); __asm__ ("elpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address));
#else #else
// read a Flash byte and increment the address // read a Flash byte and increment the address
__asm__ ("lpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address)); __asm__ ("lpm %0,Z+\n" : "=r" (ch), "=z" (address.bptr): "1" (address));
7f2c: 33 d0 rcall .+102 ; 0x7f94 <verifySpace> 7f36: 33 d0 rcall .+102 ; 0x7f9e <verifySpace>
7f2e: 8e 01 movw r16, r28 7f38: 8e 01 movw r16, r28
#endif #endif
putch(ch); putch(ch);
7f30: f8 01 movw r30, r16 7f3a: f8 01 movw r30, r16
} while (--length); } while (--length);
7f32: 85 91 lpm r24, Z+ 7f3c: 85 91 lpm r24, Z+
7f34: 8f 01 movw r16, r30 7f3e: 8f 01 movw r16, r30
7f36: 15 d0 rcall .+42 ; 0x7f62 <putch> 7f40: 15 d0 rcall .+42 ; 0x7f6c <putch>
7f38: fa 94 dec r15 7f42: fa 94 dec r15
read_mem(desttype, address, length); read_mem(desttype, address, length);
} }
/* Get device signature bytes */ /* Get device signature bytes */
else if(ch == STK_READ_SIGN) { else if(ch == STK_READ_SIGN) {
7f3a: f1 10 cpse r15, r1 7f44: f1 10 cpse r15, r1
7f3c: f9 cf rjmp .-14 ; 0x7f30 <main+0x130> 7f46: f9 cf rjmp .-14 ; 0x7f3a <main+0x136>
// READ SIGN - return what Avrdude wants to hear // READ SIGN - return what Avrdude wants to hear
verifySpace(); verifySpace();
7f3e: 0e c0 rjmp .+28 ; 0x7f5c <main+0x15c> 7f48: 0e c0 rjmp .+28 ; 0x7f66 <main+0x162>
7f40: 85 37 cpi r24, 0x75 ; 117 7f4a: 85 37 cpi r24, 0x75 ; 117
putch(SIGNATURE_0); putch(SIGNATURE_0);
7f42: 39 f4 brne .+14 ; 0x7f52 <main+0x152> 7f4c: 39 f4 brne .+14 ; 0x7f5c <main+0x158>
7f44: 27 d0 rcall .+78 ; 0x7f94 <verifySpace> 7f4e: 27 d0 rcall .+78 ; 0x7f9e <verifySpace>
7f46: 8e e1 ldi r24, 0x1E ; 30 7f50: 8e e1 ldi r24, 0x1E ; 30
putch(SIGNATURE_1); putch(SIGNATURE_1);
7f48: 0c d0 rcall .+24 ; 0x7f62 <putch> 7f52: 0c d0 rcall .+24 ; 0x7f6c <putch>
7f4a: 85 e9 ldi r24, 0x95 ; 149 7f54: 85 e9 ldi r24, 0x95 ; 149
7f4c: 0a d0 rcall .+20 ; 0x7f62 <putch> 7f56: 0a d0 rcall .+20 ; 0x7f6c <putch>
putch(SIGNATURE_2); putch(SIGNATURE_2);
7f4e: 8f e0 ldi r24, 0x0F ; 15 7f58: 8f e0 ldi r24, 0x0F ; 15
7f50: 9c cf rjmp .-200 ; 0x7e8a <main+0x8a> 7f5a: 9c cf rjmp .-200 ; 0x7e94 <main+0x90>
} }
else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */ else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
7f52: 81 35 cpi r24, 0x51 ; 81 7f5c: 81 35 cpi r24, 0x51 ; 81
7f54: 11 f4 brne .+4 ; 0x7f5a <main+0x15a> 7f5e: 11 f4 brne .+4 ; 0x7f64 <main+0x160>
// Adaboot no-wait mod // Adaboot no-wait mod
watchdogConfig(WATCHDOG_16MS); watchdogConfig(WATCHDOG_16MS);
7f56: 88 e0 ldi r24, 0x08 ; 8 7f60: 88 e0 ldi r24, 0x08 ; 8
7f58: 17 d0 rcall .+46 ; 0x7f88 <watchdogConfig> 7f62: 17 d0 rcall .+46 ; 0x7f92 <watchdogConfig>
7f5a: 1c d0 rcall .+56 ; 0x7f94 <verifySpace> 7f64: 1c d0 rcall .+56 ; 0x7f9e <verifySpace>
verifySpace(); verifySpace();
} }
else { else {
// This covers the response to commands like STK_ENTER_PROGMODE // This covers the response to commands like STK_ENTER_PROGMODE
verifySpace(); verifySpace();
7f5c: 80 e1 ldi r24, 0x10 ; 16 7f66: 80 e1 ldi r24, 0x10 ; 16
7f5e: 01 d0 rcall .+2 ; 0x7f62 <putch> 7f68: 01 d0 rcall .+2 ; 0x7f6c <putch>
} }
putch(STK_OK); putch(STK_OK);
7f60: 87 cf rjmp .-242 ; 0x7e70 <main+0x70> 7f6a: 87 cf rjmp .-242 ; 0x7e7a <main+0x76>
00007f62 <putch>: 00007f6c <putch>:
7f62: 90 91 c0 00 lds r25, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> 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) { void putch(char ch) {
#ifndef SOFT_UART #ifndef SOFT_UART
while (!(UART_SRA & _BV(UDRE0))); #ifndef LIN_UART
7f68: fc cf rjmp .-8 ; 0x7f62 <putch> while (!(UART_SRA & _BV(UDRE0))) { /* Spin */ }
UART_UDR = ch; 7f72: fc cf rjmp .-8 ; 0x7f6c <putch>
7f6a: 80 93 c6 00 sts 0x00C6, r24 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6> #else
7f6e: 08 95 ret while (!(LINSIR & _BV(LTXOK))) { /* Spin */ }
#endif
00007f70 <getch>: UART_UDR = ch;
[uartBit] "I" (UART_RX_BIT) 7f74: 80 93 c6 00 sts 0x00C6, r24 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6>
7f78: 08 95 ret
00007f7a <getch>:
: :
"r25" "r25"
); );
#else #else
while(!(UART_SRA & _BV(RXC0))) #ifndef LIN_UART
7f70: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> while(!(UART_SRA & _BV(RXC0))) { /* Spin */ }
7f74: 87 ff sbrs r24, 7 7f7a: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0>
7f76: fc cf rjmp .-8 ; 0x7f70 <getch> 7f7e: 87 ff sbrs r24, 7
; 7f80: fc cf rjmp .-8 ; 0x7f7a <getch>
if (!(UART_SRA & _BV(FE0))) { if (!(UART_SRA & _BV(FE0))) {
7f78: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0> 7f82: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0>
7f7c: 84 fd sbrc r24, 4 7f86: 84 fd sbrc r24, 4
7f7e: 01 c0 rjmp .+2 ; 0x7f82 <getch+0x12> 7f88: 01 c0 rjmp .+2 ; 0x7f8c <getch+0x12>
} }
#endif #endif
// Watchdog functions. These are only safe with interrupts turned off. // Watchdog functions. These are only safe with interrupts turned off.
void watchdogReset() { void watchdogReset() {
__asm__ __volatile__ ( __asm__ __volatile__ (
7f80: a8 95 wdr 7f8a: a8 95 wdr
* don't care that an invalid char is returned...) * don't care that an invalid char is returned...)
*/ */
watchdogReset(); watchdogReset();
} }
ch = UART_UDR; 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); LED_PIN |= _BV(LED);
#endif #endif
#endif #endif
return ch; return ch;
} }
7f86: 08 95 ret 7f90: 08 95 ret
00007f88 <watchdogConfig>: 00007f92 <watchdogConfig>:
"wdr\n"
);
} }
void watchdogConfig(uint8_t x) { void watchdogConfig(uint8_t x) {
#ifdef WDCE //does it have a Watchdog Change Enable?
#ifdef WDTCSR
WDTCSR = _BV(WDCE) | _BV(WDE); WDTCSR = _BV(WDCE) | _BV(WDE);
7f88: e0 e6 ldi r30, 0x60 ; 96 7f92: e0 e6 ldi r30, 0x60 ; 96
7f8a: f0 e0 ldi r31, 0x00 ; 0 7f94: f0 e0 ldi r31, 0x00 ; 0
7f8c: 98 e1 ldi r25, 0x18 ; 24 7f96: 98 e1 ldi r25, 0x18 ; 24
7f8e: 90 83 st Z, r25 7f98: 90 83 st Z, r25
WDTCSR = x; #else //then it must be one of those newfangled ones that use CCP
7f90: 80 83 st Z, r24 CCP=0xD8; //so write this magic number to CCP
7f92: 08 95 ret #endif
00007f94 <verifySpace>: #ifdef WDTCSR
WDTCSR = x;
7f9a: 80 83 st Z, r24
7f9c: 08 95 ret
00007f9e <verifySpace>:
do getch(); while (--count); do getch(); while (--count);
verifySpace(); verifySpace();
} }
void verifySpace() { void verifySpace() {
if (getch() != CRC_EOP) { if (getch() != CRC_EOP) {
7f94: ed df rcall .-38 ; 0x7f70 <getch> 7f9e: ed df rcall .-38 ; 0x7f7a <getch>
7f96: 80 32 cpi r24, 0x20 ; 32 7fa0: 80 32 cpi r24, 0x20 ; 32
7f98: 19 f0 breq .+6 ; 0x7fa0 <verifySpace+0xc> 7fa2: 19 f0 breq .+6 ; 0x7faa <verifySpace+0xc>
watchdogConfig(WATCHDOG_16MS); // shorten WD timeout watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
7f9a: 88 e0 ldi r24, 0x08 ; 8 7fa4: 88 e0 ldi r24, 0x08 ; 8
7f9c: f5 df rcall .-22 ; 0x7f88 <watchdogConfig> 7fa6: f5 df rcall .-22 ; 0x7f92 <watchdogConfig>
7f9e: ff cf rjmp .-2 ; 0x7f9e <verifySpace+0xa> 7fa8: ff cf rjmp .-2 ; 0x7fa8 <verifySpace+0xa>
while (1) // and busy-loop so that WD causes while (1) // and busy-loop so that WD causes
; // a reset and app start. ; // a reset and app start.
} }
putch(STK_INSYNC); putch(STK_INSYNC);
7fa0: 84 e1 ldi r24, 0x14 ; 20 7faa: 84 e1 ldi r24, 0x14 ; 20
7fa2: df cf rjmp .-66 ; 0x7f62 <putch> 7fac: df cf rjmp .-66 ; 0x7f6c <putch>
00007fa4 <getNch>: 00007fae <getNch>:
::[count] "M" (UART_B_VALUE) ::[count] "M" (UART_B_VALUE)
); );
} }
#endif #endif
void getNch(uint8_t count) { void getNch(uint8_t count) {
7fa4: cf 93 push r28 7fae: cf 93 push r28
7fa6: c8 2f mov r28, r24 7fb0: c8 2f mov r28, r24
do getch(); while (--count); do getch(); while (--count);
7fa8: e3 df rcall .-58 ; 0x7f70 <getch> 7fb2: e3 df rcall .-58 ; 0x7f7a <getch>
7faa: c1 50 subi r28, 0x01 ; 1 7fb4: c1 50 subi r28, 0x01 ; 1
7fac: e9 f7 brne .-6 ; 0x7fa8 <getNch+0x4> 7fb6: e9 f7 brne .-6 ; 0x7fb2 <getNch+0x4>
verifySpace(); verifySpace();
7fae: cf 91 pop r28 }
7fb0: f1 cf rjmp .-30 ; 0x7f94 <verifySpace> 7fb8: cf 91 pop r28
}
#endif
00007fb2 <appStart>: void getNch(uint8_t count) {
do getch(); while (--count);
verifySpace();
7fba: f1 cf rjmp .-30 ; 0x7f9e <verifySpace>
void appStart(uint8_t rstFlags) { 00007fbc <do_spm>:
// save the reset flags in the designated register 7fbc: fc 01 movw r30, r24
// This can be saved in a main program by putting code in .init0 (which * data=0 in WRITE
// executes before normal c init code) to save R2 to a global variable. */
__asm__ __volatile__ ("mov r2, %0\n" :: "r" (rstFlags)); static void do_spm(uint16_t address, uint8_t command, uint16_t data) __attribute__ ((used));
7fb2: 28 2e mov r2, r24 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); // wait for spm to complete
7fb4: 80 e0 ldi r24, 0x00 ; 0 // it doesn't have much sense for __BOOT_PAGE_FILL,
7fb6: e8 df rcall .-48 ; 0x7f88 <watchdogConfig> // but it doesn't hurt and saves some bytes on 'if'
7fb8: e0 e0 ldi r30, 0x00 ; 0 boot_spm_busy_wait();
// Note that appstart_vec is defined so that this works with either 7fc8: 00 fc sbrc r0, 0
// real or virtual boot partitions. 7fca: fd cf rjmp .-6 ; 0x7fc6 <do_spm+0xa>
__asm__ __volatile__ ( 7fcc: 66 70 andi r22, 0x06 ; 6
7fba: ff 27 eor r31, r31 #if defined(RWWSRE)
7fbc: 09 94 ijmp // 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 <do_spm+0x1e>
7fd0: 45 2b or r20, r21
7fd2: 19 f4 brne .+6 ; 0x7fda <do_spm+0x1e>
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

View File

@ -1,40 +1,53 @@
:10FC0000112484B7882349F0982F9A70923029F0F4 :10FC000011E0A0E0B1E0ECE7FEEF02C005900D923C
:10FC100081FF02C097EF94BFFBD085E08093810005 :10FC1000AC39B107D9F701C00BC1112484B78823CF
:10FC200082E08093C00088E18093C10086E08093E9 :10FC200061F0982F9A70923041F081FF02C097EFF7
:10FC3000C20080E18093C4008EE0D5D0209A86E097 :10FC300094BF282E80E0E7D0E3C185E08093810067
:10FC400020E33CEF91E0309385002093840096BB45 :10FC400082E08093C00088E18093C10086E08093C9
:10FC5000B09BFECF189AA8954091C00047FD02C006 :10FC5000C20080E18093C4008EE0D5D0209A86E077
:10FC6000815089F7FF24F39455E0E52E61E1D62E0B :10FC600020E33CEF91E0309385002093840096BB25
:10FC7000AED0813461F4ABD0C82FBBD0C238E9F02C :10FC7000B09BFECF189AA8954091C00047FD02C0E6
:10FC8000C13811F487E001C083E09AD096C0823475 :10FC8000815089F7FF24F39455E0E52E61E1D62EEB
:10FC900011F484E103C0853419F485E0B2D08DC03D :10FC9000AED0813461F4ABD0C82FBBD0C238E9F00C
:10FCA000853539F494D0082F92D0182F000F111FEA :10FCA000C13811F488E001C083E09AD096C0823454
:10FCB00083C0863521F484E0A4D080E0E6CF84368A :10FCB00011F484E103C0853419F485E0B2D08DC01D
:10FCC00009F048C084D0C82FD0E0DC2FCC277FD0EB :10FCC000853539F494D0082F92D0182F000F111FCA
:10FCD000C82B7DD0C82E5E01812C9924939477D0B7 :10FCD00083C0863521F484E0A4D080E0E6CF84366A
:10FCE000F40181934F01F1E0AF1AB108C1F781D05F :10FCE00009F048C084D0C82FD0E0DC2FCC277FD0CB
:10FCF00085E4C81212C0D3954801A12CBB24B3944B :10FCF000C82B7DD0C82E5E01812C9924939477D097
:10FD0000AC16BD0609F459C0F50161915F01C4014B :10FD0000F40181934F01F1E0AF1AB108C1F781D03E
:10FD10008DD0FFEF8F1A9F0AF3CF83E0F80187BFE2 :10FD100085E4C81212C0D3954801A12CBB24B3942A
:10FD2000E89507B600FCFDCFA0E0B1E0F8018D91A9 :10FD2000AC16BD0609F459C0F50161915F01C4012B
:10FD30009D910C01F7BEE8951124229732962097E9 :10FD300097D0FFEF8F1A9F0AF3CF83E0F80187BFB8
:10FD4000B1F7F801E7BEE89507B600FCFDCFD7BED6 :10FD4000E89507B600FCFDCFA0E0B1E0F8018D9189
:10FD5000E89533C0843719F53AD0C82FD0E0DC2FAE :10FD50009D910C01F7BEE8951124229732962097C9
:10FD6000CC2735D05E01A82A32D0982E42D0E801A7 :10FD6000B1F7F801E7BEE89507B600FCFDCFD7BEB6
:10FD7000F5E49F120BC0CE0151D022D081E0A81A29 :10FD7000E89533C0843719F53AD0C82FD0E0DC2F8E
:10FD8000B1082196A114B104B1F717C0FE01859105 :10FD8000CC2735D05E01A82A32D0982E42D0E80187
:10FD9000EF0116D0E1E0AE1AB108C1F70EC0853709 :10FD9000F5E49F120BC0CE015BD022D081E0A81AFF
:10FDA00039F427D08EE10CD086E90AD08AE06DCFF5 :10FDA000B1082196A114B104B1F717C0FE018591E5
:10FDB000813511F488E017D01CD080E101D058CFF4 :10FDB000EF0116D0E1E0AE1AB108C1F70EC08537E9
:10FDC0009091C00095FFFCCF8093C600089580916C :10FDC00039F427D08EE10CD086E90AD08AE06DCFD5
:10FDD000C00087FFFCCF8091C00084FD01C0A895C2 :10FDD000813511F488E017D01CD080E101D058CFD4
:10FDE0008091C6000895E0E6F0E098E1908380837A :10FDE0009091C00095FFFCCF8093C600089580914C
:10FDF0000895EDDF803219F088E0F5DFFFCF84E170 :10FDF000C00087FFFCCF8091C00084FD01C0A895A2
:10FE0000DFCFCF93C82FE3DFC150E9F7CF91F1CF18 :10FE00008091C6000895E0E6F0E098E19083808359
:10FE1000282E80E0E8DFE0E0FF270994F999FECF83 :10FE10000895EDDF803219F088E0F5DFFFCF84E14F
:10FE200092BD81BDF89A992780B50895262FF9993A :10FE2000DFCFCF93C82FE3DFC150E9F7CF91F1CFF8
:10FE3000FECF1FBA92BD81BD20BD0FB6F894FA9ACD :10FE3000FC010A0167BFE895112407B600FCFDCF5D
:08FE4000F99A0FBE0196089526 :10FE4000667029F0452B19F481E187BFE895089584
:02FFFE000007FA :10FE5000F999FECF92BD81BDF89A992780B5089592
:10FE6000262FF999FECF1FBA92BD81BD20BD0FB6D6
:0CFE7000F894FA9AF99A0FBE01960895D2
:10FE7C0056657273696F6E3D382E30004F50544981
:10FE8C00424F4F545F435553544F4D5645523D309E
:10FE9C00004465766963653D61746D6567613634F0
:10FEAC00347000465F4350553D3136303030303081
:10FEBC00304C00424947424F4F543D310042756926
:10FECC006C743A53657020323020323031383A300D
:10FEDC00313A31383A353000554152543D300042B8
:10FEEC004155445F524154453D313135323030003B
:10FEFC004C45443D4230004C45445F5354415254B0
:0CFF0C005F464C41534845533D33000014
:02FFFE000008F9
:040000030000FC00FD :040000030000FC00FD
:00000001FF :00000001FF

File diff suppressed because it is too large Load Diff

View File

@ -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 <main>:
// 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 <main+0x1a>
* 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 <main+0x1a>
if (ch & _BV(EXTRF)) {
3e10: 81 ff sbrs r24, 1
3e12: 02 c0 rjmp .+4 ; 0x3e18 <main+0x18>
* 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 <appStart>
}
}
#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 <watchdogConfig>
#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 <main+0x50>
#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 <main+0x64>
3e60: 81 50 subi r24, 0x01 ; 1
#else
// This doesn't seem to work?
// if ((UART_PIN & (1<<UART_RX_BIT)) == 0)
// break; // detect start bit on soft uart too.
#endif
} while (--count);
3e62: 89 f7 brne .-30 ; 0x3e46 <main+0x46>
/*
* 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 <getch>
unsigned char which = getch();
3e72: 81 34 cpi r24, 0x41 ; 65
3e74: 61 f4 brne .+24 ; 0x3e8e <main+0x8e>
3e76: 7c d0 rcall .+248 ; 0x3f70 <getch>
verifySpace();
3e78: 18 2f mov r17, r24
3e7a: 8c d0 rcall .+280 ; 0x3f94 <verifySpace>
/*
* 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 <main+0xba>
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 <main+0x88>
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 <main+0x8a>
3e88: 83 e0 ldi r24, 0x03 ; 3
3e8a: 6b d0 rcall .+214 ; 0x3f62 <putch>
3e8c: 67 c0 rjmp .+206 ; 0x3f5c <main+0x15c>
}
}
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 <main+0x96>
3e92: 84 e1 ldi r24, 0x14 ; 20
}
else if(ch == STK_SET_DEVICE_EXT) {
3e94: 03 c0 rjmp .+6 ; 0x3e9c <main+0x9c>
// SET DEVICE EXT is ignored
getNch(5);
3e96: 85 34 cpi r24, 0x45 ; 69
3e98: 19 f4 brne .+6 ; 0x3ea0 <main+0xa0>
3e9a: 85 e0 ldi r24, 0x05 ; 5
}
else if(ch == STK_LOAD_ADDRESS) {
3e9c: 83 d0 rcall .+262 ; 0x3fa4 <getNch>
3e9e: 5e c0 rjmp .+188 ; 0x3f5c <main+0x15c>
// LOAD ADDRESS
address.bytes[0] = getch();
3ea0: 85 35 cpi r24, 0x55 ; 85
3ea2: 39 f4 brne .+14 ; 0x3eb2 <main+0xb2>
3ea4: 65 d0 rcall .+202 ; 0x3f70 <getch>
address.bytes[1] = getch();
3ea6: c8 2f mov r28, r24
3ea8: 63 d0 rcall .+198 ; 0x3f70 <getch>
}
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 <main+0x15a>
getNch(3);
putch(0x00);
}
#else
// UNIVERSAL command is ignored
getNch(4);
3eb2: 86 35 cpi r24, 0x56 ; 86
3eb4: 21 f4 brne .+8 ; 0x3ebe <main+0xbe>
putch(0x00);
3eb6: 84 e0 ldi r24, 0x04 ; 4
3eb8: 75 d0 rcall .+234 ; 0x3fa4 <getNch>
#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 <main+0x8a>
// 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 <main+0xc4>
3ec2: 2e c0 rjmp .+92 ; 0x3f20 <main+0x120>
3ec4: 55 d0 rcall .+170 ; 0x3f70 <getch>
savelength = length;
desttype = getch();
3ec6: 54 d0 rcall .+168 ; 0x3f70 <getch>
3ec8: f8 2e mov r15, r24
3eca: 52 d0 rcall .+164 ; 0x3f70 <getch>
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 <getch>
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 <main+0xd2>
// Read command terminator, start reply
verifySpace();
3ede: 5a d0 rcall .+180 ; 0x3f94 <verifySpace>
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 <main+0xe8>
3ee6: ff cf rjmp .-2 ; 0x3ee6 <main+0xe6>
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 <main+0xf0>
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 <main+0xfc>
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 <main+0x114>
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 <main+0x15c>
3f20: 84 37 cpi r24, 0x74 ; 116
3f22: 71 f4 brne .+28 ; 0x3f40 <main+0x140>
desttype = getch();
3f24: 25 d0 rcall .+74 ; 0x3f70 <getch>
verifySpace();
3f26: 24 d0 rcall .+72 ; 0x3f70 <getch>
3f28: f8 2e mov r15, r24
3f2a: 22 d0 rcall .+68 ; 0x3f70 <getch>
// 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 <verifySpace>
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 <putch>
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 <main+0x130>
// READ SIGN - return what Avrdude wants to hear
verifySpace();
3f3e: 0e c0 rjmp .+28 ; 0x3f5c <main+0x15c>
3f40: 85 37 cpi r24, 0x75 ; 117
putch(SIGNATURE_0);
3f42: 39 f4 brne .+14 ; 0x3f52 <main+0x152>
3f44: 27 d0 rcall .+78 ; 0x3f94 <verifySpace>
3f46: 8e e1 ldi r24, 0x1E ; 30
putch(SIGNATURE_1);
3f48: 0c d0 rcall .+24 ; 0x3f62 <putch>
3f4a: 84 e9 ldi r24, 0x94 ; 148
3f4c: 0a d0 rcall .+20 ; 0x3f62 <putch>
putch(SIGNATURE_2);
3f4e: 86 e0 ldi r24, 0x06 ; 6
3f50: 9c cf rjmp .-200 ; 0x3e8a <main+0x8a>
}
else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
3f52: 81 35 cpi r24, 0x51 ; 81
3f54: 11 f4 brne .+4 ; 0x3f5a <main+0x15a>
// Adaboot no-wait mod
watchdogConfig(WATCHDOG_16MS);
3f56: 88 e0 ldi r24, 0x08 ; 8
3f58: 17 d0 rcall .+46 ; 0x3f88 <watchdogConfig>
3f5a: 1c d0 rcall .+56 ; 0x3f94 <verifySpace>
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>
}
putch(STK_OK);
3f60: 87 cf rjmp .-242 ; 0x3e70 <main+0x70>
00003f62 <putch>:
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 <putch>
UART_UDR = ch;
3f6a: 80 93 c6 00 sts 0x00C6, r24 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6>
3f6e: 08 95 ret
00003f70 <getch>:
[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 <getch>
;
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 <getch+0x12>
}
#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 <watchdogConfig>:
"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 <verifySpace>:
do getch(); while (--count);
verifySpace();
}
void verifySpace() {
if (getch() != CRC_EOP) {
3f94: ed df rcall .-38 ; 0x3f70 <getch>
3f96: 80 32 cpi r24, 0x20 ; 32
3f98: 19 f0 breq .+6 ; 0x3fa0 <verifySpace+0xc>
watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
3f9a: 88 e0 ldi r24, 0x08 ; 8
3f9c: f5 df rcall .-22 ; 0x3f88 <watchdogConfig>
3f9e: ff cf rjmp .-2 ; 0x3f9e <verifySpace+0xa>
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 <putch>
00003fa4 <getNch>:
::[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 <getch>
3faa: c1 50 subi r28, 0x01 ; 1
3fac: e9 f7 brne .-6 ; 0x3fa8 <getNch+0x4>
verifySpace();
3fae: cf 91 pop r28
3fb0: f1 cf rjmp .-30 ; 0x3f94 <verifySpace>
00003fb2 <appStart>:
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 <watchdogConfig>
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

View File

@ -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

View File

@ -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 <main>:
// 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 <main+0x1a>
* 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 <main+0x1a>
if (ch & _BV(EXTRF)) {
3e10: 81 ff sbrs r24, 1
3e12: 02 c0 rjmp .+4 ; 0x3e18 <main+0x18>
* 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 <appStart>
}
}
#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 <watchdogConfig>
#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 <main+0x50>
#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 <main+0x64>
3e60: 81 50 subi r24, 0x01 ; 1
#else
// This doesn't seem to work?
// if ((UART_PIN & (1<<UART_RX_BIT)) == 0)
// break; // detect start bit on soft uart too.
#endif
} while (--count);
3e62: 89 f7 brne .-30 ; 0x3e46 <main+0x46>
/*
* 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 <getch>
unsigned char which = getch();
3e72: 81 34 cpi r24, 0x41 ; 65
3e74: 61 f4 brne .+24 ; 0x3e8e <main+0x8e>
3e76: 7c d0 rcall .+248 ; 0x3f70 <getch>
verifySpace();
3e78: 18 2f mov r17, r24
3e7a: 8c d0 rcall .+280 ; 0x3f94 <verifySpace>
/*
* 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 <main+0xba>
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 <main+0x88>
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 <main+0x8a>
3e88: 83 e0 ldi r24, 0x03 ; 3
3e8a: 6b d0 rcall .+214 ; 0x3f62 <putch>
3e8c: 67 c0 rjmp .+206 ; 0x3f5c <main+0x15c>
}
}
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 <main+0x96>
3e92: 84 e1 ldi r24, 0x14 ; 20
}
else if(ch == STK_SET_DEVICE_EXT) {
3e94: 03 c0 rjmp .+6 ; 0x3e9c <main+0x9c>
// SET DEVICE EXT is ignored
getNch(5);
3e96: 85 34 cpi r24, 0x45 ; 69
3e98: 19 f4 brne .+6 ; 0x3ea0 <main+0xa0>
3e9a: 85 e0 ldi r24, 0x05 ; 5
}
else if(ch == STK_LOAD_ADDRESS) {
3e9c: 83 d0 rcall .+262 ; 0x3fa4 <getNch>
3e9e: 5e c0 rjmp .+188 ; 0x3f5c <main+0x15c>
// LOAD ADDRESS
address.bytes[0] = getch();
3ea0: 85 35 cpi r24, 0x55 ; 85
3ea2: 39 f4 brne .+14 ; 0x3eb2 <main+0xb2>
3ea4: 65 d0 rcall .+202 ; 0x3f70 <getch>
address.bytes[1] = getch();
3ea6: c8 2f mov r28, r24
3ea8: 63 d0 rcall .+198 ; 0x3f70 <getch>
}
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 <main+0x15a>
getNch(3);
putch(0x00);
}
#else
// UNIVERSAL command is ignored
getNch(4);
3eb2: 86 35 cpi r24, 0x56 ; 86
3eb4: 21 f4 brne .+8 ; 0x3ebe <main+0xbe>
putch(0x00);
3eb6: 84 e0 ldi r24, 0x04 ; 4
3eb8: 75 d0 rcall .+234 ; 0x3fa4 <getNch>
#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 <main+0x8a>
// 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 <main+0xc4>
3ec2: 2e c0 rjmp .+92 ; 0x3f20 <main+0x120>
3ec4: 55 d0 rcall .+170 ; 0x3f70 <getch>
savelength = length;
desttype = getch();
3ec6: 54 d0 rcall .+168 ; 0x3f70 <getch>
3ec8: f8 2e mov r15, r24
3eca: 52 d0 rcall .+164 ; 0x3f70 <getch>
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 <getch>
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 <main+0xd2>
// Read command terminator, start reply
verifySpace();
3ede: 5a d0 rcall .+180 ; 0x3f94 <verifySpace>
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 <main+0xe8>
3ee6: ff cf rjmp .-2 ; 0x3ee6 <main+0xe6>
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 <main+0xf0>
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 <main+0xfc>
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 <main+0x114>
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 <main+0x15c>
3f20: 84 37 cpi r24, 0x74 ; 116
3f22: 71 f4 brne .+28 ; 0x3f40 <main+0x140>
desttype = getch();
3f24: 25 d0 rcall .+74 ; 0x3f70 <getch>
verifySpace();
3f26: 24 d0 rcall .+72 ; 0x3f70 <getch>
3f28: f8 2e mov r15, r24
3f2a: 22 d0 rcall .+68 ; 0x3f70 <getch>
// 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 <verifySpace>
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 <putch>
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 <main+0x130>
// READ SIGN - return what Avrdude wants to hear
verifySpace();
3f3e: 0e c0 rjmp .+28 ; 0x3f5c <main+0x15c>
3f40: 85 37 cpi r24, 0x75 ; 117
putch(SIGNATURE_0);
3f42: 39 f4 brne .+14 ; 0x3f52 <main+0x152>
3f44: 27 d0 rcall .+78 ; 0x3f94 <verifySpace>
3f46: 8e e1 ldi r24, 0x1E ; 30
putch(SIGNATURE_1);
3f48: 0c d0 rcall .+24 ; 0x3f62 <putch>
3f4a: 84 e9 ldi r24, 0x94 ; 148
3f4c: 0a d0 rcall .+20 ; 0x3f62 <putch>
putch(SIGNATURE_2);
3f4e: 86 e0 ldi r24, 0x06 ; 6
3f50: 9c cf rjmp .-200 ; 0x3e8a <main+0x8a>
}
else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
3f52: 81 35 cpi r24, 0x51 ; 81
3f54: 11 f4 brne .+4 ; 0x3f5a <main+0x15a>
// Adaboot no-wait mod
watchdogConfig(WATCHDOG_16MS);
3f56: 88 e0 ldi r24, 0x08 ; 8
3f58: 17 d0 rcall .+46 ; 0x3f88 <watchdogConfig>
3f5a: 1c d0 rcall .+56 ; 0x3f94 <verifySpace>
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>
}
putch(STK_OK);
3f60: 87 cf rjmp .-242 ; 0x3e70 <main+0x70>
00003f62 <putch>:
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 <putch>
UART_UDR = ch;
3f6a: 80 93 c6 00 sts 0x00C6, r24 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6>
3f6e: 08 95 ret
00003f70 <getch>:
[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 <getch>
;
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 <getch+0x12>
}
#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 <watchdogConfig>:
"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 <verifySpace>:
do getch(); while (--count);
verifySpace();
}
void verifySpace() {
if (getch() != CRC_EOP) {
3f94: ed df rcall .-38 ; 0x3f70 <getch>
3f96: 80 32 cpi r24, 0x20 ; 32
3f98: 19 f0 breq .+6 ; 0x3fa0 <verifySpace+0xc>
watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
3f9a: 88 e0 ldi r24, 0x08 ; 8
3f9c: f5 df rcall .-22 ; 0x3f88 <watchdogConfig>
3f9e: ff cf rjmp .-2 ; 0x3f9e <verifySpace+0xa>
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 <putch>
00003fa4 <getNch>:
::[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 <getch>
3faa: c1 50 subi r28, 0x01 ; 1
3fac: e9 f7 brne .-6 ; 0x3fa8 <getNch+0x4>
verifySpace();
3fae: cf 91 pop r28
3fb0: f1 cf rjmp .-30 ; 0x3f94 <verifySpace>
00003fb2 <appStart>:
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 <watchdogConfig>
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

View File

@ -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

View File

@ -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 <main>:
// 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 <main+0x1a>
* 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 <main+0x1a>
if (ch & _BV(EXTRF)) {
1d10: 81 ff sbrs r24, 1
1d12: 02 c0 rjmp .+4 ; 0x1d18 <main+0x18>
* 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 <appStart>
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 <watchdogConfig>
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 <getch>
if(ch == STK_GET_PARAMETER) {
1d2e: 81 34 cpi r24, 0x41 ; 65
1d30: 71 f4 brne .+28 ; 0x1d4e <main+0x4e>
unsigned char which = getch();
1d32: ca d0 rcall .+404 ; 0x1ec8 <getch>
1d34: f8 2e mov r15, r24
verifySpace();
1d36: e0 d0 rcall .+448 ; 0x1ef8 <verifySpace>
/*
* 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 <main+0x7a>
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 <main+0x48>
putch(optiboot_version >> 8);
1d44: 87 e0 ldi r24, 0x07 ; 7
1d46: 01 c0 rjmp .+2 ; 0x1d4a <main+0x4a>
} 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 <putch>
1d4c: ab c0 rjmp .+342 ; 0x1ea4 <main+0x1a4>
}
}
else if(ch == STK_SET_DEVICE) {
1d4e: 82 34 cpi r24, 0x42 ; 66
1d50: 11 f4 brne .+4 ; 0x1d56 <main+0x56>
// SET DEVICE is ignored
getNch(20);
1d52: 84 e1 ldi r24, 0x14 ; 20
1d54: 03 c0 rjmp .+6 ; 0x1d5c <main+0x5c>
}
else if(ch == STK_SET_DEVICE_EXT) {
1d56: 85 34 cpi r24, 0x45 ; 69
1d58: 19 f4 brne .+6 ; 0x1d60 <main+0x60>
// SET DEVICE EXT is ignored
getNch(5);
1d5a: 85 e0 ldi r24, 0x05 ; 5
1d5c: d5 d0 rcall .+426 ; 0x1f08 <getNch>
1d5e: a2 c0 rjmp .+324 ; 0x1ea4 <main+0x1a4>
}
else if(ch == STK_LOAD_ADDRESS) {
1d60: 85 35 cpi r24, 0x55 ; 85
1d62: 39 f4 brne .+14 ; 0x1d72 <main+0x72>
// LOAD ADDRESS
address.bytes[0] = getch();
1d64: b1 d0 rcall .+354 ; 0x1ec8 <getch>
1d66: c8 2f mov r28, r24
address.bytes[1] = getch();
1d68: af d0 rcall .+350 ; 0x1ec8 <getch>
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 <main+0x1a2>
verifySpace();
}
else if(ch == STK_UNIVERSAL) {
1d72: 86 35 cpi r24, 0x56 ; 86
1d74: 21 f4 brne .+8 ; 0x1d7e <main+0x7e>
getNch(3);
putch(0x00);
}
#else
// UNIVERSAL command is ignored
getNch(4);
1d76: 84 e0 ldi r24, 0x04 ; 4
1d78: c7 d0 rcall .+398 ; 0x1f08 <getNch>
putch(0x00);
1d7a: 80 e0 ldi r24, 0x00 ; 0
1d7c: e6 cf rjmp .-52 ; 0x1d4a <main+0x4a>
#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 <main+0x84>
1d82: 55 c0 rjmp .+170 ; 0x1e2e <main+0x12e>
// 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 <getch>
1d86: a0 d0 rcall .+320 ; 0x1ec8 <getch>
1d88: f8 2e mov r15, r24
savelength = length;
desttype = getch();
1d8a: 9e d0 rcall .+316 ; 0x1ec8 <getch>
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 <getch>
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 <main+0x96>
// Read command terminator, start reply
verifySpace();
1da4: a9 d0 rcall .+338 ; 0x1ef8 <verifySpace>
#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 <main+0xf0>
// 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 <main+0xf8>
1df6: ff cf rjmp .-2 ; 0x1df6 <main+0xf6>
* 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 <main+0xfe>
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 <main+0x10a>
/*
* 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 <main+0x126>
1e2c: 3b c0 rjmp .+118 ; 0x1ea4 <main+0x1a4>
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 <main+0x188>
uint8_t desttype;
GETLENGTH(length);
1e32: 4a d0 rcall .+148 ; 0x1ec8 <getch>
1e34: 49 d0 rcall .+146 ; 0x1ec8 <getch>
1e36: d8 2e mov r13, r24
desttype = getch();
1e38: 47 d0 rcall .+142 ; 0x1ec8 <getch>
verifySpace();
1e3a: 5e d0 rcall .+188 ; 0x1ef8 <verifySpace>
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 <main+0x14a>
1e44: 80 91 e4 00 lds r24, 0x00E4 ; 0x8000e4 <_edata+0x84>
1e48: 17 c0 rjmp .+46 ; 0x1e78 <main+0x178>
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 <main+0x158>
1e52: 80 91 e5 00 lds r24, 0x00E5 ; 0x8000e5 <_edata+0x85>
1e56: 10 c0 rjmp .+32 ; 0x1e78 <main+0x178>
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 <main+0x166>
1e60: 80 91 e6 00 lds r24, 0x00E6 ; 0x8000e6 <_edata+0x86>
1e64: 09 c0 rjmp .+18 ; 0x1e78 <main+0x178>
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 <main+0x174>
1e6e: 80 91 e7 00 lds r24, 0x00E7 ; 0x8000e7 <_edata+0x87>
1e72: 02 c0 rjmp .+4 ; 0x1e78 <main+0x178>
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 <putch>
} 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 <main+0x13e>
1e86: 0e c0 rjmp .+28 ; 0x1ea4 <main+0x1a4>
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 <main+0x19a>
// READ SIGN - return what Avrdude wants to hear
verifySpace();
1e8c: 35 d0 rcall .+106 ; 0x1ef8 <verifySpace>
putch(SIGNATURE_0);
1e8e: 8e e1 ldi r24, 0x1E ; 30
1e90: 0c d0 rcall .+24 ; 0x1eaa <putch>
putch(SIGNATURE_1);
1e92: 83 e9 ldi r24, 0x93 ; 147
1e94: 0a d0 rcall .+20 ; 0x1eaa <putch>
putch(SIGNATURE_2);
1e96: 8c e0 ldi r24, 0x0C ; 12
1e98: 58 cf rjmp .-336 ; 0x1d4a <main+0x4a>
}
else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
1e9a: 81 35 cpi r24, 0x51 ; 81
1e9c: 11 f4 brne .+4 ; 0x1ea2 <main+0x1a2>
// Adaboot no-wait mod
watchdogConfig(WATCHDOG_16MS);
1e9e: 88 e0 ldi r24, 0x08 ; 8
1ea0: 27 d0 rcall .+78 ; 0x1ef0 <watchdogConfig>
verifySpace();
}
else {
// This covers the response to commands like STK_ENTER_PROGMODE
verifySpace();
1ea2: 2a d0 rcall .+84 ; 0x1ef8 <verifySpace>
}
putch(STK_OK);
1ea4: 80 e1 ldi r24, 0x10 ; 16
1ea6: 01 d0 rcall .+2 ; 0x1eaa <putch>
}
1ea8: 41 cf rjmp .-382 ; 0x1d2c <main+0x2c>
00001eaa <putch>:
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 <putch+0xe>
1eb4: da 98 cbi 0x1b, 2 ; 27
1eb6: 02 c0 rjmp .+4 ; 0x1ebc <putch+0x12>
1eb8: da 9a sbi 0x1b, 2 ; 27
1eba: 00 00 nop
1ebc: 15 d0 rcall .+42 ; 0x1ee8 <uartDelay>
1ebe: 14 d0 rcall .+40 ; 0x1ee8 <uartDelay>
1ec0: 86 95 lsr r24
1ec2: 2a 95 dec r18
1ec4: b1 f7 brne .-20 ; 0x1eb2 <putch+0x8>
1ec6: 08 95 ret
00001ec8 <getch>:
}
#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 <getch+0x6>
1ed2: 0a d0 rcall .+20 ; 0x1ee8 <uartDelay>
1ed4: 09 d0 rcall .+18 ; 0x1ee8 <uartDelay>
1ed6: 08 d0 rcall .+16 ; 0x1ee8 <uartDelay>
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 <getch+0x1e>
1ee2: 87 95 ror r24
1ee4: f7 cf rjmp .-18 ; 0x1ed4 <getch+0xc>
LED_PIN |= _BV(LED);
#endif
#endif
return ch;
}
1ee6: 08 95 ret
00001ee8 <uartDelay>:
#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 <uartDelay+0x2>
1eee: 08 95 ret
00001ef0 <watchdogConfig>:
"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 <verifySpace>:
do getch(); while (--count);
verifySpace();
}
void verifySpace() {
if (getch() != CRC_EOP) {
1ef8: e7 df rcall .-50 ; 0x1ec8 <getch>
1efa: 80 32 cpi r24, 0x20 ; 32
1efc: 19 f0 breq .+6 ; 0x1f04 <verifySpace+0xc>
watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
1efe: 88 e0 ldi r24, 0x08 ; 8
1f00: f7 df rcall .-18 ; 0x1ef0 <watchdogConfig>
1f02: ff cf rjmp .-2 ; 0x1f02 <verifySpace+0xa>
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 <putch>
00001f08 <getNch>:
::[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 <getch>
1f0e: c1 50 subi r28, 0x01 ; 1
1f10: e9 f7 brne .-6 ; 0x1f0c <getNch+0x4>
verifySpace();
}
1f12: cf 91 pop r28
}
#endif
void getNch(uint8_t count) {
do getch(); while (--count);
verifySpace();
1f14: f1 cf rjmp .-30 ; 0x1ef8 <verifySpace>
00001f16 <appStart>:
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 <watchdogConfig>
// 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

View File

@ -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

View File

@ -5,6 +5,8 @@
# Build a "release" .zip file for Optiboot bootloader # Build a "release" .zip file for Optiboot bootloader
# Run from the build directory # Run from the build directory
version=$1
# Uncomment if you want a clean builds of specific files # Uncomment if you want a clean builds of specific files
# make clean # make clean
# make atmega328 # make atmega328
@ -18,7 +20,7 @@ rm -Rf /tmp/optiboot-release
# Note that the structure under "packages" (handed by boards manager) # Note that the structure under "packages" (handed by boards manager)
# is different than the structure under "sketchbook/hardware" would be. # is different than the structure under "sketchbook/hardware" would be.
TOP=/tmp/optiboot-release/Optiboot$1/ TOP=/tmp/optiboot-release/Optiboot-$version/
# #
# Bootloaders directory # Bootloaders directory
mkdir -p $TOP/bootloaders/optiboot 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 # Create platform.txt, because it contains the "group" name for the boards menu
echo name=Optiboot $1 > $TOP/platform.txt echo name=Optiboot $version > $TOP/platform.txt
echo version=$1 >> $TOP/platform.txt echo version=$version >> $TOP/platform.txt
# #
# Create a README file. # 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 >> $TOP/README.TXT
echo For Source code see http://github.com/Optiboot/optiboot>> $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. # zip everything up.
pushd /tmp/optiboot-release pushd /tmp/optiboot-release
zip -r Optiboot$1.zip Optiboot$1 zip -r Optiboot-$version.zip Optiboot-$version
HASH=`openssl dgst -sha256 Optiboot$1.zip | sed -e 's/.* //'` HASH=`openssl dgst -sha256 Optiboot-$version.zip | sed -e 's/.* //'`
SIZE=`stat -f %z Optiboot$1.zip` SIZE=`stat -f %z Optiboot-$version.zip`
popd 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 # This leaves the .zip and the .json file in /tmp/optiboot-release