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:
@ -236,9 +236,17 @@ SS_CMD = -DSINGLESPEED=1
|
||||
endif
|
||||
endif
|
||||
|
||||
HELPTEXT += "Option NO_APP_SPM=1 - disallow application call of do_spm\n"
|
||||
ifdef NO_APP_SPM
|
||||
ifneq ($(NO_APP_SPM),0)
|
||||
APPSPM_CMD = -DAPP_NOSPM=1
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
COMMON_OPTIONS = $(BAUD_RATE_CMD) $(LED_START_FLASHES_CMD) $(BIGBOOT_CMD)
|
||||
COMMON_OPTIONS += $(SOFT_UART_CMD) $(LED_DATA_FLASH_CMD) $(LED_CMD) $(SS_CMD)
|
||||
COMMON_OPTIONS += $(SUPPORT_EEPROM_CMD) $(LED_START_ON_CMD)
|
||||
COMMON_OPTIONS += $(SUPPORT_EEPROM_CMD) $(LED_START_ON_CMD) $(APPSPM_CMD)
|
||||
COMMON_OPTIONS += $(VERSION_CMD)
|
||||
|
||||
#UART is handled separately and only passed for devices with more than one.
|
||||
@ -380,7 +388,7 @@ atmega168_isp: HFUSE ?= DD
|
||||
atmega168_isp: LFUSE ?= F7
|
||||
ifndef BIGBOOT
|
||||
# 512 byte boot
|
||||
atmega168_isp: EFUSE ?= 04
|
||||
atmega168_isp: EFUSE ?= FC
|
||||
else
|
||||
# 1024byte boot
|
||||
atmega168_isp: EFUSE ?= FA
|
||||
|
@ -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
|
32
optiboot/bootloaders/optiboot/makeall.arduino.sh
Executable file
32
optiboot/bootloaders/optiboot/makeall.arduino.sh
Executable 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 $*
|
@ -193,7 +193,7 @@ do
|
||||
# Print out current build info
|
||||
echo -e " ${mcu_and_params[$i]} AVR_FREQ=${clock_and_baud[$j]} BAUD_RATE=${clock_and_baud[$j+1]} ${mcu_and_params[$i+1]} \x1B[0m"
|
||||
# Build
|
||||
make ${mcu_and_params[$i]} AVR_FREQ=${clock_and_baud[$j]} BAUD_RATE=${clock_and_baud[$j+1]} ${mcu_and_params[$i+1]}
|
||||
make ${mcu_and_params[$i]} AVR_FREQ=${clock_and_baud[$j]} BAUD_RATE=${clock_and_baud[$j+1]} ${mcu_and_params[$i+1]} $*
|
||||
done
|
||||
done
|
||||
|
||||
|
44
optiboot/bootloaders/optiboot/makeall.tiny.sh
Executable file
44
optiboot/bootloaders/optiboot/makeall.tiny.sh
Executable 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 $*
|
@ -152,6 +152,7 @@
|
||||
/* handling, did MORE Makefile mods. EEPROM support now */
|
||||
/* fits in 512 bytes, if you turn off LED Blinking. */
|
||||
/* Various bigboot and virboot targets were fixed. */
|
||||
/* Version 8.0 adds the do_spm code callable from Apps. */
|
||||
/* */
|
||||
/* It would be good if versions implemented outside the */
|
||||
/* official repository used an out-of-seqeunce version */
|
||||
@ -164,6 +165,10 @@
|
||||
/**********************************************************/
|
||||
/* Edit History: */
|
||||
/* */
|
||||
/* Sep 2018 */
|
||||
/* 8.0 WestfW (and MCUDude) */
|
||||
/* Include do_spm routine callable from the app */
|
||||
/* at BOOTSTART+2, controllable with compile option */
|
||||
/* July 2018 */
|
||||
/* 7.0 WestfW (with much input from Others) */
|
||||
/* Fix MCUSR treatement as per much discussion, */
|
||||
@ -246,7 +251,7 @@
|
||||
/* 4.1 WestfW: put version number in binary. */
|
||||
/**********************************************************/
|
||||
|
||||
#define OPTIBOOT_MAJVER 7
|
||||
#define OPTIBOOT_MAJVER 8
|
||||
#define OPTIBOOT_MINVER 0
|
||||
|
||||
/*
|
||||
@ -396,6 +401,7 @@ typedef uint8_t pagelen_t;
|
||||
* supress some compile-time options we want.)
|
||||
*/
|
||||
|
||||
void pre_main(void) __attribute__ ((naked)) __attribute__ ((section (".init8")));
|
||||
int main(void) __attribute__ ((OS_main)) __attribute__ ((section (".init9"))) __attribute__((used));
|
||||
|
||||
void __attribute__((noinline)) __attribute__((leaf)) putch(char);
|
||||
@ -487,6 +493,23 @@ static addr16_t buff = {(uint8_t *)(RAMSTART)};
|
||||
#endif // VIRTUAL_BOOT_PARTITION
|
||||
|
||||
|
||||
/* everything that needs to run VERY early */
|
||||
void pre_main(void) {
|
||||
// Allow convenient way of calling do_spm function - jump table,
|
||||
// so entry to this function will always be here, indepedent of compilation,
|
||||
// features etc
|
||||
asm volatile (
|
||||
" rjmp 1f\n"
|
||||
#ifndef APP_NOSPM
|
||||
" rjmp do_spm\n"
|
||||
#else
|
||||
" ret\n" // if do_spm isn't include, return without doing anything
|
||||
#endif
|
||||
"1:\n"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/* main program starts here */
|
||||
int main(void) {
|
||||
uint8_t ch;
|
||||
@ -1158,6 +1181,59 @@ static inline void read_mem(uint8_t memtype, addr16_t address, pagelen_t length)
|
||||
}
|
||||
|
||||
|
||||
#ifndef APP_NOSPM
|
||||
|
||||
/*
|
||||
* Separate function for doing spm stuff
|
||||
* It's needed for application to do SPM, as SPM instruction works only
|
||||
* from bootloader.
|
||||
*
|
||||
* How it works:
|
||||
* - do SPM
|
||||
* - wait for SPM to complete
|
||||
* - if chip have RWW/NRWW sections it does additionaly:
|
||||
* - if command is WRITE or ERASE, AND data=0 then reenable RWW section
|
||||
*
|
||||
* In short:
|
||||
* If you play erase-fill-write, just set data to 0 in ERASE and WRITE
|
||||
* If you are brave, you have your code just below bootloader in NRWW section
|
||||
* you could do fill-erase-write sequence with data!=0 in ERASE and
|
||||
* data=0 in WRITE
|
||||
*/
|
||||
static void do_spm(uint16_t address, uint8_t command, uint16_t data) __attribute__ ((used));
|
||||
static void do_spm(uint16_t address, uint8_t command, uint16_t data) {
|
||||
// Do spm stuff
|
||||
asm volatile (
|
||||
" movw r0, %3\n"
|
||||
" __wr_spmcsr %0, %1\n"
|
||||
" spm\n"
|
||||
" clr r1\n"
|
||||
:
|
||||
: "i" (_SFR_MEM_ADDR(__SPM_REG)),
|
||||
"r" ((uint8_t)command),
|
||||
"z" ((uint16_t)address),
|
||||
"r" ((uint16_t)data)
|
||||
: "r0"
|
||||
);
|
||||
|
||||
// wait for spm to complete
|
||||
// it doesn't have much sense for __BOOT_PAGE_FILL,
|
||||
// but it doesn't hurt and saves some bytes on 'if'
|
||||
boot_spm_busy_wait();
|
||||
#if defined(RWWSRE)
|
||||
// this 'if' condition should be: (command == __BOOT_PAGE_WRITE || command == __BOOT_PAGE_ERASE)...
|
||||
// but it's tweaked a little assuming that in every command we are interested in here, there
|
||||
// must be also SELFPRGEN set. If we skip checking this bit, we save here 4B
|
||||
if ((command & (_BV(PGWRT)|_BV(PGERS))) && (data == 0) ) {
|
||||
// Reenable read access to flash
|
||||
__boot_rww_enable_short();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef BIGBOOT
|
||||
/*
|
||||
* Optiboot is designed to fit in 512 bytes, with a minimum feature set.
|
||||
|
@ -1,44 +1,57 @@
|
||||
:020000021000EC
|
||||
:10FC0000112484B7882349F0982F9A70923029F0F4
|
||||
:10FC100081FF02C097EF94BF10D185E080938100EF
|
||||
:10FC200082E08093C00088E18093C10086E08093E9
|
||||
:10FC3000C20080E18093C4008EE0EAD0279A86E07B
|
||||
:10FC400020E33CEF91E0309385002093840096BB45
|
||||
:10FC5000B09BFECF1F9AA8954091C00047FD02C0FF
|
||||
:10FC6000815089F7FF24F39455E0E52E61E1D62E0B
|
||||
:10FC7000C3D08134C1F4C0D0C82FD0D0C23809F469
|
||||
:10FC80003AC0C13869F487E00CC0843709F482C0F7
|
||||
:10FC9000853709F0A2C0C2D08EE1A7D087E9A5D0F0
|
||||
:10FCA00083E0A3D09FC0823411F484E103C0853483
|
||||
:10FCB00019F485E0BBD096C0853579F49DD0082F26
|
||||
:10FCC0009BD0182F87FF03C08BB7816002C08BB712
|
||||
:10FCD0008E7F8BBF000F111F84C0863581F48CD0BE
|
||||
:10FCE0008D3459F489D0CBB787D0C170880FC82B19
|
||||
:10FCF000CBBF81E09BD080E0D4CF83E0FBCF8436C4
|
||||
:10FD000009F0C3CF79D0C82FD0E0DC2FCC2774D036
|
||||
:10FD1000C82B72D0C82E5E01812C32E0932E6CD09D
|
||||
:10FD2000F40181934F01F1E0AF1AB108C1F776D029
|
||||
:10FD300085E4C81212C0DE5F4801A12C92E0B92E02
|
||||
:10FD4000AC16BD0609F44EC0F50161915F01C40116
|
||||
:10FD500082D0FFEF8F1A9F0AF3CF83E0F80187BFAD
|
||||
:10FD6000E89507B600FCFDCFA0E0B2E0F8018D9168
|
||||
:10FD70009D910C01F7BEE8951124229732962097A9
|
||||
:10FD8000B1F7F801E7BEE89507B600FCFDCFD7BE96
|
||||
:10FD9000E89528C031D0C82FD0E0DC2FCC272CD05C
|
||||
:10FDA0005E01A82A29D0982E39D0E801F5E49F12E7
|
||||
:10FDB0000BC0CE0148D019D081E0A81AB108219615
|
||||
:10FDC000A114B104B1F70EC0FE018791EF010DD06F
|
||||
:10FDD000E1E0AE1AB108C1F705C0813511F488E041
|
||||
:10FDE00017D01CD080E101D043CF9091C00095FF87
|
||||
:10FDF000FCCF8093C60008958091C00087FFFCCFA0
|
||||
:10FE00008091C00084FD01C0A8958091C60008952E
|
||||
:10FE1000E0E6F0E098E1908380830895EDDF8032A2
|
||||
:10FE200019F088E0F5DFFFCF84E1DFCFCF93C82F53
|
||||
:10FE3000E3DFC150E9F7CF91F1CF282E80E0E8DF72
|
||||
:10FE4000E0E0FF270994F999FECF92BD81BDF89AB1
|
||||
:10FE5000992780B50895262FF999FECF1FBA92BD34
|
||||
:10FE600081BD20BD0FB6F894FA9AF99A0FBE01969B
|
||||
:02FE70000895F3
|
||||
:02FFFE000007FA
|
||||
:10FC000012E0A0E0B2E0ECEAFEEF01E00BBF02C0C0
|
||||
:10FC100007900D92AC39B107D9F701C021C1112469
|
||||
:10FC200084B7882369F0982F9A70923049F081FF49
|
||||
:10FC300002C097EF94BF282E80E0FDD00C94000006
|
||||
:10FC400085E08093810082E08093C00088E180930A
|
||||
:10FC5000C10086E08093C20080E18093C4008EE002
|
||||
:10FC6000EAD0279A86E020E33CEF91E030938500CC
|
||||
:10FC70002093840096BBB09BFECF1F9AA89540911D
|
||||
:10FC8000C00047FD02C0815089F7FF24F39455E07E
|
||||
:10FC9000E52E61E1D62EC3D08134C1F4C0D0C82F87
|
||||
:10FCA000D0D0C23809F43AC0C13869F488E00CC039
|
||||
:10FCB000843709F482C0853709F0A2C0C2D08EE132
|
||||
:10FCC000A7D087E9A5D083E0A3D09FC0823411F4E8
|
||||
:10FCD00084E103C0853419F485E0BBD096C0853536
|
||||
:10FCE00079F49DD0082F9BD0182F87FF03C08BB7C6
|
||||
:10FCF000816002C08BB78E7F8BBF000F111F84C045
|
||||
:10FD0000863581F48CD08D3459F489D0CBB787D027
|
||||
:10FD1000C170880FC82BCBBF81E09BD080E0D4CFCF
|
||||
:10FD200083E0FBCF843609F0C3CF79D0C82FD0E071
|
||||
:10FD3000DC2FCC2774D0C82B72D0C82E5E01812C4A
|
||||
:10FD400032E0932E6CD0F40181934F01F1E0AF1AB1
|
||||
:10FD5000B108C1F776D085E4C81212C0DE5F480151
|
||||
:10FD6000A12C92E0B92EAC16BD0609F44EC0F501E7
|
||||
:10FD700061915F01C4018CD0FFEF8F1A9F0AF3CF0E
|
||||
:10FD800083E0F80187BFE89507B600FCFDCFA0E04F
|
||||
:10FD9000B2E0F8018D919D910C01F7BEE895112418
|
||||
:10FDA000229732962097B1F7F801E7BEE89507B69B
|
||||
:10FDB00000FCFDCFD7BEE89528C031D0C82FD0E0D9
|
||||
:10FDC000DC2FCC272CD05E01A82A29D0982E39D040
|
||||
:10FDD000E801F5E49F120BC0CE0152D019D081E0AA
|
||||
:10FDE000A81AB1082196A114B104B1F70EC0FE0102
|
||||
:10FDF0008791EF010DD0E1E0AE1AB108C1F705C05F
|
||||
:10FE0000813511F488E017D01CD080E101D043CFB8
|
||||
:10FE10009091C00095FFFCCF8093C600089580911B
|
||||
:10FE2000C00087FFFCCF8091C00084FD01C0A89571
|
||||
:10FE30008091C6000895E0E6F0E098E19083808329
|
||||
:10FE40000895EDDF803219F088E0F5DFFFCF84E11F
|
||||
:10FE5000DFCFCF93C82FE3DFC150E9F7CF91F1CFC8
|
||||
:10FE6000FC010A0167BFE895112407B600FCFDCF2D
|
||||
:10FE7000667029F0452B19F481E187BFE895089554
|
||||
:10FE8000F999FECF92BD81BDF89A992780B5089562
|
||||
:10FE9000262FF999FECF1FBA92BD81BD20BD0FB6A6
|
||||
:0CFEA000F894FA9AF99A0FBE01960895A2
|
||||
:10FEAC0056657273696F6E3D382E30004F50544951
|
||||
:10FEBC00424F4F545F435553544F4D5645523D306E
|
||||
:10FECC00004465766963653D61746D6567613132C7
|
||||
:10FEDC00383000465F4350553D313630303030308D
|
||||
:10FEEC00304C00424947424F4F543D3100427569F6
|
||||
:10FEFC006C743A53657020323020323031383A30DD
|
||||
:10FF0C00313A31383A343300554152543D30004285
|
||||
:10FF1C004155445F524154453D313135323030000A
|
||||
:10FF2C004C45443D4237004C45445F535441525478
|
||||
:0CFF3C005F464C41534845533D330000E4
|
||||
:02FFFE000008F9
|
||||
:040000031000FC00ED
|
||||
:00000001FF
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,31 +1,33 @@
|
||||
:107E0000112484B7882349F0982F9A70923029F072
|
||||
:107E100081FF02C097EF94BFCCD085E080938100B2
|
||||
:107E200082E08093C00088E18093C10086E0809367
|
||||
:107E3000C20080E18093C4008EE0A6D0259A86E03F
|
||||
:107E400020E33CEF91E0309385002093840096BBC3
|
||||
:107E5000B09BFECF1D9AA8954091C00047FD02C07F
|
||||
:107E6000815089F7EE24E39495E0D92E21E1C22ECA
|
||||
:107E70007FD0813461F47CD0182F8CD01238E9F097
|
||||
:107E8000113811F487E001C083E06BD067C0823401
|
||||
:107E900011F484E103C0853419F485E083D05EC019
|
||||
:107EA000853539F465D0C82F63D0D82FCC0FDD1FAE
|
||||
:107EB00054C0863521F484E075D080E0E6CF843666
|
||||
:107EC00009F02EC055D054D0F82E52D0B82E00E074
|
||||
:107ED00011E04ED0F80181938F01FE12FACF5AD0F3
|
||||
:107EE000F5E4BF1201C0FFCF83E0FE0187BFE89534
|
||||
:107EF00007B600FCFDCFA0E0B1E0FE018D919D91A1
|
||||
:107F00000C01E7BEE89511243296FA12F7CFFE0174
|
||||
:107F1000D7BEE89507B600FCFDCFC7BEE8951EC0EA
|
||||
:107F2000843771F425D024D0F82E22D033D08E019E
|
||||
:107F3000F80185918F0115D0FA94F110F9CF0EC098
|
||||
:107F4000853739F427D08EE10CD085E90AD08FE04F
|
||||
:107F50009CCF813511F488E017D01CD080E101D08E
|
||||
:107F600087CF9091C00095FFFCCF8093C600089505
|
||||
:107F70008091C00087FFFCCF8091C00084FD01C0CC
|
||||
:107F8000A8958091C6000895E0E6F0E098E190831E
|
||||
:107F900080830895EDDF803219F088E0F5DFFFCFB0
|
||||
:107FA00084E1DFCFCF93C82FE3DFC150E9F7CF9152
|
||||
:0E7FB000F1CF282E80E0E8DFE0E0FF27099403
|
||||
:027FFE0000077A
|
||||
:107E000001C0DCC0112484B7882361F0982F9A70D8
|
||||
:107E1000923041F081FF02C097EF94BF282E80E09E
|
||||
:107E2000B8D0EEC085E08093810082E08093C000EE
|
||||
:107E300088E18093C10086E08093C20080E1809356
|
||||
:107E4000C4008EE0A6D0259A86E020E33CEF91E0C6
|
||||
:107E5000309385002093840096BBB09BFECF1D9A83
|
||||
:107E6000A8954091C00047FD02C0815089F7EE24DB
|
||||
:107E7000E39495E0D92E21E1C22E7FD0813461F4C4
|
||||
:107E80007CD0182F8CD01238E9F0113811F488E02A
|
||||
:107E900001C083E06BD067C0823411F484E103C079
|
||||
:107EA000853419F485E083D05EC0853539F465D01A
|
||||
:107EB000C82F63D0D82FCC0FDD1F54C0863521F4D6
|
||||
:107EC00084E075D080E0E6CF843609F02EC055D02E
|
||||
:107ED00054D0F82E52D0B82E00E011E04ED0F80168
|
||||
:107EE00081938F01FE12FACF5AD0F5E4BF1201C080
|
||||
:107EF000FFCF83E0FE0187BFE89507B600FCFDCF0A
|
||||
:107F0000A0E0B1E0FE018D919D910C01E7BEE895E6
|
||||
:107F100011243296FA12F7CFFE01D7BEE89507B6C4
|
||||
:107F200000FCFDCFC7BEE8951EC0843771F425D094
|
||||
:107F300024D0F82E22D033D08E01F80185918F0104
|
||||
:107F400015D0FA94F110F9CF0EC0853739F427D047
|
||||
:107F50008EE10CD085E90AD08FE09CCF813511F4F9
|
||||
:107F600088E017D01CD080E101D087CF9091C0006D
|
||||
:107F700095FFFCCF8093C60008958091C00087FFD5
|
||||
:107F8000FCCF8091C00084FD01C0A8958091C600FF
|
||||
:107F90000895E0E6F0E098E1908380830895EDDFB6
|
||||
:107FA000803219F088E0F5DFFFCF84E1DFCFCF9397
|
||||
:107FB000C82FE3DFC150E9F7CF91F1CFFC010A01EF
|
||||
:107FC00067BFE895112407B600FCFDCF667029F065
|
||||
:0C7FD000452B19F481E187BFE895089566
|
||||
:027FFE00000879
|
||||
:0400000300007E007B
|
||||
:00000001FF
|
||||
|
@ -3,582 +3,638 @@ optiboot_atmega328.elf: file format elf32-avr
|
||||
|
||||
Sections:
|
||||
Idx Name Size VMA LMA File off Algn
|
||||
0 .data 00000000 00800100 00007fbe 00000252 2**0
|
||||
0 .data 00000000 00800100 00007fdc 00000270 2**0
|
||||
CONTENTS, ALLOC, LOAD, DATA
|
||||
1 .text 000001be 00007e00 00007e00 00000094 2**1
|
||||
1 .text 000001dc 00007e00 00007e00 00000094 2**1
|
||||
CONTENTS, ALLOC, LOAD, READONLY, CODE
|
||||
2 .version 00000002 00007ffe 00007ffe 00000252 2**0
|
||||
2 .version 00000002 00007ffe 00007ffe 00000270 2**0
|
||||
CONTENTS, ALLOC, LOAD, READONLY, DATA
|
||||
3 .comment 0000002f 00000000 00000000 00000254 2**0
|
||||
3 .comment 0000002f 00000000 00000000 00000272 2**0
|
||||
CONTENTS, READONLY
|
||||
4 .debug_aranges 00000028 00000000 00000000 00000283 2**0
|
||||
4 .debug_aranges 00000030 00000000 00000000 000002a1 2**0
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
5 .debug_info 000005c8 00000000 00000000 000002ab 2**0
|
||||
5 .debug_info 000005fd 00000000 00000000 000002d1 2**0
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
6 .debug_abbrev 00000282 00000000 00000000 00000873 2**0
|
||||
6 .debug_abbrev 000002c1 00000000 00000000 000008ce 2**0
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
7 .debug_line 000002f9 00000000 00000000 00000af5 2**0
|
||||
7 .debug_line 00000334 00000000 00000000 00000b8f 2**0
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
8 .debug_frame 0000008c 00000000 00000000 00000df0 2**2
|
||||
8 .debug_frame 0000009c 00000000 00000000 00000ec4 2**2
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
9 .debug_str 000001fa 00000000 00000000 00000e7c 2**0
|
||||
9 .debug_str 00000200 00000000 00000000 00000f60 2**0
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
10 .debug_loc 00000331 00000000 00000000 00001076 2**0
|
||||
10 .debug_loc 00000359 00000000 00000000 00001160 2**0
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
11 .debug_ranges 00000060 00000000 00000000 000013a7 2**0
|
||||
11 .debug_ranges 00000068 00000000 00000000 000014b9 2**0
|
||||
CONTENTS, READONLY, DEBUGGING
|
||||
|
||||
Disassembly of section .text:
|
||||
|
||||
00007e00 <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
|
||||
// r1 contains zero
|
||||
//
|
||||
// If not, uncomment the following instructions:
|
||||
// cli();
|
||||
asm volatile ("clr __zero_reg__");
|
||||
7e00: 11 24 eor r1, r1
|
||||
*
|
||||
* Code by MarkG55
|
||||
* see discusion in https://github.com/Optiboot/optiboot/issues/97
|
||||
*/
|
||||
#if !defined(__AVR_ATmega16__)
|
||||
ch = MCUSR;
|
||||
7e02: 84 b7 in r24, 0x34 ; 52
|
||||
#else
|
||||
7e04: 11 24 eor r1, r1
|
||||
#if defined(__AVR_ATmega8515__) || defined(__AVR_ATmega8535__) || \
|
||||
defined(__AVR_ATmega16__) || defined(__AVR_ATmega162__) || \
|
||||
defined (__AVR_ATmega128__)
|
||||
ch = MCUCSR;
|
||||
#else
|
||||
ch = MCUSR;
|
||||
7e06: 84 b7 in r24, 0x34 ; 52
|
||||
#endif
|
||||
// Skip all logic and run bootloader if MCUSR is cleared (application request)
|
||||
if (ch != 0) {
|
||||
7e04: 88 23 and r24, r24
|
||||
7e06: 49 f0 breq .+18 ; 0x7e1a <main+0x1a>
|
||||
7e08: 88 23 and r24, r24
|
||||
7e0a: 61 f0 breq .+24 ; 0x7e24 <main+0x20>
|
||||
* 2. we clear WDRF if it's set with EXTRF to avoid loops
|
||||
* One problematic scenario: broken application code sets watchdog timer
|
||||
* without clearing MCUSR before and triggers it quickly. But it's
|
||||
* recoverable by power-on with pushed reset button.
|
||||
*/
|
||||
if ((ch & (_BV(WDRF) | _BV(EXTRF))) != _BV(EXTRF)) {
|
||||
7e08: 98 2f mov r25, r24
|
||||
7e0a: 9a 70 andi r25, 0x0A ; 10
|
||||
7e0c: 92 30 cpi r25, 0x02 ; 2
|
||||
7e0e: 29 f0 breq .+10 ; 0x7e1a <main+0x1a>
|
||||
7e0c: 98 2f mov r25, r24
|
||||
7e0e: 9a 70 andi r25, 0x0A ; 10
|
||||
7e10: 92 30 cpi r25, 0x02 ; 2
|
||||
7e12: 41 f0 breq .+16 ; 0x7e24 <main+0x20>
|
||||
if (ch & _BV(EXTRF)) {
|
||||
7e10: 81 ff sbrs r24, 1
|
||||
7e12: 02 c0 rjmp .+4 ; 0x7e18 <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));
|
||||
7e14: 97 ef ldi r25, 0xF7 ; 247
|
||||
7e16: 94 bf out 0x34, r25 ; 52
|
||||
#else
|
||||
7e14: 81 ff sbrs r24, 1
|
||||
7e16: 02 c0 rjmp .+4 ; 0x7e1c <main+0x18>
|
||||
defined(__AVR_ATmega16__) || defined(__AVR_ATmega162__) || \
|
||||
defined(__AVR_ATmega128__)
|
||||
// Fix missing definitions in avr-libc
|
||||
MCUCSR = ~(_BV(WDRF));
|
||||
#endif
|
||||
}
|
||||
appStart(ch);
|
||||
7e18: cc d0 rcall .+408 ; 0x7fb2 <appStart>
|
||||
#else
|
||||
MCUSR = ~(_BV(WDRF));
|
||||
7e18: 97 ef ldi r25, 0xF7 ; 247
|
||||
7e1a: 94 bf out 0x34, r25 ; 52
|
||||
/*
|
||||
* save the reset flags in the designated register
|
||||
* This can be saved in a main program by putting code in .init0 (which
|
||||
* executes before normal c init code) to save R2 to a global variable.
|
||||
*/
|
||||
__asm__ __volatile__ ("mov r2, %0\n" :: "r" (ch));
|
||||
7e1c: 28 2e mov r2, r24
|
||||
|
||||
// switch off watchdog
|
||||
watchdogConfig(WATCHDOG_OFF);
|
||||
7e1e: 80 e0 ldi r24, 0x00 ; 0
|
||||
7e20: b8 d0 rcall .+368 ; 0x7f92 <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
|
||||
// Set up Timer 1 for timeout counter
|
||||
TCCR1B = _BV(CS12) | _BV(CS10); // div 1024
|
||||
7e1a: 85 e0 ldi r24, 0x05 ; 5
|
||||
7e1c: 80 93 81 00 sts 0x0081, r24 ; 0x800081 <__TEXT_REGION_LENGTH__+0x7e0081>
|
||||
UCSRA = _BV(U2X); //Double speed mode USART
|
||||
UCSRB = _BV(RXEN) | _BV(TXEN); // enable Rx & Tx
|
||||
UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0); // config USART; 8N1
|
||||
UBRRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
|
||||
#else
|
||||
7e24: 85 e0 ldi r24, 0x05 ; 5
|
||||
7e26: 80 93 81 00 sts 0x0081, r24 ; 0x800081 <__TEXT_REGION_LENGTH__+0x7e0081>
|
||||
LINBTR = (1 << LDISR) | (8 << LBT0);
|
||||
LINCR = _BV(LENA) | _BV(LCMD2) | _BV(LCMD1) | _BV(LCMD0);
|
||||
LINDAT=0;
|
||||
#else
|
||||
#ifndef SINGLESPEED
|
||||
UART_SRA = _BV(U2X0); //Double speed mode USART0
|
||||
7e20: 82 e0 ldi r24, 0x02 ; 2
|
||||
7e22: 80 93 c0 00 sts 0x00C0, r24 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0>
|
||||
7e2a: 82 e0 ldi r24, 0x02 ; 2
|
||||
7e2c: 80 93 c0 00 sts 0x00C0, r24 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0>
|
||||
#endif
|
||||
UART_SRB = _BV(RXEN0) | _BV(TXEN0);
|
||||
7e26: 88 e1 ldi r24, 0x18 ; 24
|
||||
7e28: 80 93 c1 00 sts 0x00C1, r24 ; 0x8000c1 <__TEXT_REGION_LENGTH__+0x7e00c1>
|
||||
7e30: 88 e1 ldi r24, 0x18 ; 24
|
||||
7e32: 80 93 c1 00 sts 0x00C1, r24 ; 0x8000c1 <__TEXT_REGION_LENGTH__+0x7e00c1>
|
||||
UART_SRC = _BV(UCSZ00) | _BV(UCSZ01);
|
||||
7e2c: 86 e0 ldi r24, 0x06 ; 6
|
||||
7e2e: 80 93 c2 00 sts 0x00C2, r24 ; 0x8000c2 <__TEXT_REGION_LENGTH__+0x7e00c2>
|
||||
UART_SRL = (uint8_t)( (F_CPU + BAUD_RATE * 4L) / (BAUD_RATE * 8L) - 1 );
|
||||
7e32: 80 e1 ldi r24, 0x10 ; 16
|
||||
7e34: 80 93 c4 00 sts 0x00C4, r24 ; 0x8000c4 <__TEXT_REGION_LENGTH__+0x7e00c4>
|
||||
#endif
|
||||
#endif
|
||||
7e36: 86 e0 ldi r24, 0x06 ; 6
|
||||
7e38: 80 93 c2 00 sts 0x00C2, r24 ; 0x8000c2 <__TEXT_REGION_LENGTH__+0x7e00c2>
|
||||
UART_SRL = (uint8_t)BAUD_SETTING;
|
||||
7e3c: 80 e1 ldi r24, 0x10 ; 16
|
||||
7e3e: 80 93 c4 00 sts 0x00C4, r24 ; 0x8000c4 <__TEXT_REGION_LENGTH__+0x7e00c4>
|
||||
#endif // LIN_UART
|
||||
#endif // mega8/etc
|
||||
#endif // soft_uart
|
||||
|
||||
// Set up watchdog to trigger after 1s
|
||||
watchdogConfig(WATCHDOG_1S);
|
||||
7e38: 8e e0 ldi r24, 0x0E ; 14
|
||||
7e3a: a6 d0 rcall .+332 ; 0x7f88 <watchdogConfig>
|
||||
7e42: 8e e0 ldi r24, 0x0E ; 14
|
||||
7e44: a6 d0 rcall .+332 ; 0x7f92 <watchdogConfig>
|
||||
|
||||
#if (LED_START_FLASHES > 0) || defined(LED_DATA_FLASH) || defined(LED_START_ON)
|
||||
/* Set LED pin as output */
|
||||
LED_DDR |= _BV(LED);
|
||||
7e3c: 25 9a sbi 0x04, 5 ; 4
|
||||
7e3e: 86 e0 ldi r24, 0x06 ; 6
|
||||
7e46: 25 9a sbi 0x04, 5 ; 4
|
||||
7e48: 86 e0 ldi r24, 0x06 ; 6
|
||||
}
|
||||
|
||||
#if LED_START_FLASHES > 0
|
||||
void flash_led(uint8_t count) {
|
||||
do {
|
||||
TCNT1 = -(F_CPU/(1024*16));
|
||||
7e40: 20 e3 ldi r18, 0x30 ; 48
|
||||
7e42: 3c ef ldi r19, 0xFC ; 252
|
||||
7e4a: 20 e3 ldi r18, 0x30 ; 48
|
||||
7e4c: 3c ef ldi r19, 0xFC ; 252
|
||||
TIFR1 = _BV(TOV1);
|
||||
7e44: 91 e0 ldi r25, 0x01 ; 1
|
||||
7e4e: 91 e0 ldi r25, 0x01 ; 1
|
||||
}
|
||||
|
||||
#if LED_START_FLASHES > 0
|
||||
void flash_led(uint8_t count) {
|
||||
do {
|
||||
TCNT1 = -(F_CPU/(1024*16));
|
||||
7e46: 30 93 85 00 sts 0x0085, r19 ; 0x800085 <__TEXT_REGION_LENGTH__+0x7e0085>
|
||||
7e4a: 20 93 84 00 sts 0x0084, r18 ; 0x800084 <__TEXT_REGION_LENGTH__+0x7e0084>
|
||||
7e50: 30 93 85 00 sts 0x0085, r19 ; 0x800085 <__TEXT_REGION_LENGTH__+0x7e0085>
|
||||
7e54: 20 93 84 00 sts 0x0084, r18 ; 0x800084 <__TEXT_REGION_LENGTH__+0x7e0084>
|
||||
TIFR1 = _BV(TOV1);
|
||||
7e4e: 96 bb out 0x16, r25 ; 22
|
||||
7e58: 96 bb out 0x16, r25 ; 22
|
||||
while(!(TIFR1 & _BV(TOV1)));
|
||||
7e50: b0 9b sbis 0x16, 0 ; 22
|
||||
7e52: fe cf rjmp .-4 ; 0x7e50 <main+0x50>
|
||||
#if defined(__AVR_ATmega8__) || defined (__AVR_ATmega32__) || defined (__AVR_ATmega16__)
|
||||
7e5a: b0 9b sbis 0x16, 0 ; 22
|
||||
7e5c: fe cf rjmp .-4 ; 0x7e5a <main+0x56>
|
||||
defined(__AVR_ATmega8535__) || defined(__AVR_ATmega16__) || \
|
||||
defined(__AVR_ATmega162__) || defined(__AVR_ATmega32__) || \
|
||||
defined(__AVR_ATmega64__) || defined(__AVR_ATmega128__)
|
||||
LED_PORT ^= _BV(LED);
|
||||
#else
|
||||
LED_PIN |= _BV(LED);
|
||||
7e54: 1d 9a sbi 0x03, 5 ; 3
|
||||
7e5e: 1d 9a sbi 0x03, 5 ; 3
|
||||
}
|
||||
#endif
|
||||
|
||||
// Watchdog functions. These are only safe with interrupts turned off.
|
||||
void watchdogReset() {
|
||||
__asm__ __volatile__ (
|
||||
7e56: a8 95 wdr
|
||||
* While in theory, the STK500 initial commands would be buffered
|
||||
7e60: a8 95 wdr
|
||||
* by the UART hardware, avrdude sends several attempts in rather
|
||||
* quick succession, some of which will be lost and cause us to
|
||||
* get out of sync. So if we see any data; stop blinking.
|
||||
*/
|
||||
#ifndef LIN_UART
|
||||
if (UART_SRA & _BV(RXC0))
|
||||
7e58: 40 91 c0 00 lds r20, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0>
|
||||
7e5c: 47 fd sbrc r20, 7
|
||||
7e5e: 02 c0 rjmp .+4 ; 0x7e64 <main+0x64>
|
||||
7e60: 81 50 subi r24, 0x01 ; 1
|
||||
7e62: 40 91 c0 00 lds r20, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0>
|
||||
7e66: 47 fd sbrc r20, 7
|
||||
7e68: 02 c0 rjmp .+4 ; 0x7e6e <main+0x6a>
|
||||
7e6a: 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);
|
||||
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.
|
||||
*/
|
||||
do {
|
||||
__boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++));
|
||||
7e64: ee 24 eor r14, r14
|
||||
7e66: e3 94 inc r14
|
||||
7e6e: ee 24 eor r14, r14
|
||||
7e70: e3 94 inc r14
|
||||
} while (len -= 2);
|
||||
|
||||
/*
|
||||
* Actually Write the buffer to flash (and wait for it to finish.)
|
||||
*/
|
||||
__boot_page_write_short(address.word);
|
||||
7e68: 95 e0 ldi r25, 0x05 ; 5
|
||||
7e6a: d9 2e mov r13, r25
|
||||
7e72: 95 e0 ldi r25, 0x05 ; 5
|
||||
7e74: d9 2e mov r13, r25
|
||||
boot_spm_busy_wait();
|
||||
#if defined(RWWSRE)
|
||||
// Reenable read access to flash
|
||||
__boot_rww_enable_short();
|
||||
7e6c: 21 e1 ldi r18, 0x11 ; 17
|
||||
7e76: 21 e1 ldi r18, 0x11 ; 17
|
||||
#endif
|
||||
|
||||
/* Forever loop: exits by causing WDT reset */
|
||||
for (;;) {
|
||||
/* get character from UART */
|
||||
ch = getch();
|
||||
7e6e: c2 2e mov r12, r18
|
||||
7e78: c2 2e mov r12, r18
|
||||
|
||||
if(ch == STK_GET_PARAMETER) {
|
||||
7e70: 7f d0 rcall .+254 ; 0x7f70 <getch>
|
||||
7e7a: 7f d0 rcall .+254 ; 0x7f7a <getch>
|
||||
unsigned char which = getch();
|
||||
7e72: 81 34 cpi r24, 0x41 ; 65
|
||||
7e74: 61 f4 brne .+24 ; 0x7e8e <main+0x8e>
|
||||
7e76: 7c d0 rcall .+248 ; 0x7f70 <getch>
|
||||
7e7c: 81 34 cpi r24, 0x41 ; 65
|
||||
7e7e: 61 f4 brne .+24 ; 0x7e98 <main+0x94>
|
||||
7e80: 7c d0 rcall .+248 ; 0x7f7a <getch>
|
||||
verifySpace();
|
||||
7e78: 18 2f mov r17, r24
|
||||
7e7a: 8c d0 rcall .+280 ; 0x7f94 <verifySpace>
|
||||
7e82: 18 2f mov r17, r24
|
||||
7e84: 8c d0 rcall .+280 ; 0x7f9e <verifySpace>
|
||||
/*
|
||||
* Send optiboot version as "SW version"
|
||||
* Note that the references to memory are optimized away.
|
||||
*/
|
||||
if (which == STK_SW_MINOR) {
|
||||
7e7c: 12 38 cpi r17, 0x82 ; 130
|
||||
7e7e: e9 f0 breq .+58 ; 0x7eba <main+0xba>
|
||||
7e86: 12 38 cpi r17, 0x82 ; 130
|
||||
7e88: e9 f0 breq .+58 ; 0x7ec4 <main+0xc0>
|
||||
putch(optiboot_version & 0xFF);
|
||||
} else if (which == STK_SW_MAJOR) {
|
||||
7e80: 11 38 cpi r17, 0x81 ; 129
|
||||
7e8a: 11 38 cpi r17, 0x81 ; 129
|
||||
putch(optiboot_version >> 8);
|
||||
7e82: 11 f4 brne .+4 ; 0x7e88 <main+0x88>
|
||||
7e84: 87 e0 ldi r24, 0x07 ; 7
|
||||
7e8c: 11 f4 brne .+4 ; 0x7e92 <main+0x8e>
|
||||
7e8e: 88 e0 ldi r24, 0x08 ; 8
|
||||
} else {
|
||||
/*
|
||||
* GET PARAMETER returns a generic 0x03 reply for
|
||||
* other parameters - enough to keep Avrdude happy
|
||||
*/
|
||||
putch(0x03);
|
||||
7e86: 01 c0 rjmp .+2 ; 0x7e8a <main+0x8a>
|
||||
7e88: 83 e0 ldi r24, 0x03 ; 3
|
||||
7e8a: 6b d0 rcall .+214 ; 0x7f62 <putch>
|
||||
7e8c: 67 c0 rjmp .+206 ; 0x7f5c <main+0x15c>
|
||||
7e90: 01 c0 rjmp .+2 ; 0x7e94 <main+0x90>
|
||||
7e92: 83 e0 ldi r24, 0x03 ; 3
|
||||
7e94: 6b d0 rcall .+214 ; 0x7f6c <putch>
|
||||
7e96: 67 c0 rjmp .+206 ; 0x7f66 <main+0x162>
|
||||
}
|
||||
}
|
||||
else if(ch == STK_SET_DEVICE) {
|
||||
7e8e: 82 34 cpi r24, 0x42 ; 66
|
||||
7e98: 82 34 cpi r24, 0x42 ; 66
|
||||
// SET DEVICE is ignored
|
||||
getNch(20);
|
||||
7e90: 11 f4 brne .+4 ; 0x7e96 <main+0x96>
|
||||
7e92: 84 e1 ldi r24, 0x14 ; 20
|
||||
7e9a: 11 f4 brne .+4 ; 0x7ea0 <main+0x9c>
|
||||
7e9c: 84 e1 ldi r24, 0x14 ; 20
|
||||
}
|
||||
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
|
||||
getNch(5);
|
||||
7e96: 85 34 cpi r24, 0x45 ; 69
|
||||
7e98: 19 f4 brne .+6 ; 0x7ea0 <main+0xa0>
|
||||
7e9a: 85 e0 ldi r24, 0x05 ; 5
|
||||
7ea0: 85 34 cpi r24, 0x45 ; 69
|
||||
7ea2: 19 f4 brne .+6 ; 0x7eaa <main+0xa6>
|
||||
7ea4: 85 e0 ldi r24, 0x05 ; 5
|
||||
}
|
||||
else if(ch == STK_LOAD_ADDRESS) {
|
||||
7e9c: 83 d0 rcall .+262 ; 0x7fa4 <getNch>
|
||||
7e9e: 5e c0 rjmp .+188 ; 0x7f5c <main+0x15c>
|
||||
7ea6: 83 d0 rcall .+262 ; 0x7fae <getNch>
|
||||
7ea8: 5e c0 rjmp .+188 ; 0x7f66 <main+0x162>
|
||||
// LOAD ADDRESS
|
||||
address.bytes[0] = getch();
|
||||
7ea0: 85 35 cpi r24, 0x55 ; 85
|
||||
7ea2: 39 f4 brne .+14 ; 0x7eb2 <main+0xb2>
|
||||
7ea4: 65 d0 rcall .+202 ; 0x7f70 <getch>
|
||||
7eaa: 85 35 cpi r24, 0x55 ; 85
|
||||
7eac: 39 f4 brne .+14 ; 0x7ebc <main+0xb8>
|
||||
7eae: 65 d0 rcall .+202 ; 0x7f7a <getch>
|
||||
address.bytes[1] = getch();
|
||||
7ea6: c8 2f mov r28, r24
|
||||
7ea8: 63 d0 rcall .+198 ; 0x7f70 <getch>
|
||||
7eb0: c8 2f mov r28, r24
|
||||
7eb2: 63 d0 rcall .+198 ; 0x7f7a <getch>
|
||||
}
|
||||
else {
|
||||
RAMPZ &= 0xFE;
|
||||
}
|
||||
#endif
|
||||
address.word *= 2; // Convert from word address to byte address
|
||||
7eaa: d8 2f mov r29, r24
|
||||
7eac: cc 0f add r28, r28
|
||||
7eae: dd 1f adc r29, r29
|
||||
7eb4: d8 2f mov r29, r24
|
||||
7eb6: cc 0f add r28, r28
|
||||
7eb8: dd 1f adc r29, r29
|
||||
verifySpace();
|
||||
}
|
||||
else if(ch == STK_UNIVERSAL) {
|
||||
7eb0: 54 c0 rjmp .+168 ; 0x7f5a <main+0x15a>
|
||||
7eba: 54 c0 rjmp .+168 ; 0x7f64 <main+0x160>
|
||||
getNch(3);
|
||||
putch(0x00);
|
||||
}
|
||||
#else
|
||||
// UNIVERSAL command is ignored
|
||||
getNch(4);
|
||||
7eb2: 86 35 cpi r24, 0x56 ; 86
|
||||
7eb4: 21 f4 brne .+8 ; 0x7ebe <main+0xbe>
|
||||
7ebc: 86 35 cpi r24, 0x56 ; 86
|
||||
7ebe: 21 f4 brne .+8 ; 0x7ec8 <main+0xc4>
|
||||
putch(0x00);
|
||||
7eb6: 84 e0 ldi r24, 0x04 ; 4
|
||||
7eb8: 75 d0 rcall .+234 ; 0x7fa4 <getNch>
|
||||
7ec0: 84 e0 ldi r24, 0x04 ; 4
|
||||
7ec2: 75 d0 rcall .+234 ; 0x7fae <getNch>
|
||||
#endif
|
||||
}
|
||||
/* Write memory, length is big endian and is in bytes */
|
||||
else if(ch == STK_PROG_PAGE) {
|
||||
7eba: 80 e0 ldi r24, 0x00 ; 0
|
||||
7ebc: e6 cf rjmp .-52 ; 0x7e8a <main+0x8a>
|
||||
7ec4: 80 e0 ldi r24, 0x00 ; 0
|
||||
7ec6: e6 cf rjmp .-52 ; 0x7e94 <main+0x90>
|
||||
// PROGRAM PAGE - we support flash programming only, not EEPROM
|
||||
uint8_t desttype;
|
||||
uint8_t *bufPtr;
|
||||
pagelen_t savelength;
|
||||
|
||||
GETLENGTH(length);
|
||||
7ebe: 84 36 cpi r24, 0x64 ; 100
|
||||
7ec0: 09 f0 breq .+2 ; 0x7ec4 <main+0xc4>
|
||||
7ec2: 2e c0 rjmp .+92 ; 0x7f20 <main+0x120>
|
||||
7ec4: 55 d0 rcall .+170 ; 0x7f70 <getch>
|
||||
7ec8: 84 36 cpi r24, 0x64 ; 100
|
||||
7eca: 09 f0 breq .+2 ; 0x7ece <main+0xca>
|
||||
7ecc: 2e c0 rjmp .+92 ; 0x7f2a <main+0x126>
|
||||
7ece: 55 d0 rcall .+170 ; 0x7f7a <getch>
|
||||
savelength = length;
|
||||
desttype = getch();
|
||||
7ec6: 54 d0 rcall .+168 ; 0x7f70 <getch>
|
||||
7ec8: f8 2e mov r15, r24
|
||||
7eca: 52 d0 rcall .+164 ; 0x7f70 <getch>
|
||||
7ecc: b8 2e mov r11, r24
|
||||
7ece: 00 e0 ldi r16, 0x00 ; 0
|
||||
7ed0: 54 d0 rcall .+168 ; 0x7f7a <getch>
|
||||
7ed2: f8 2e mov r15, r24
|
||||
7ed4: 52 d0 rcall .+164 ; 0x7f7a <getch>
|
||||
7ed6: b8 2e mov r11, r24
|
||||
7ed8: 00 e0 ldi r16, 0x00 ; 0
|
||||
|
||||
// read a page worth of contents
|
||||
bufPtr = buff.bptr;
|
||||
do *bufPtr++ = getch();
|
||||
7ed0: 11 e0 ldi r17, 0x01 ; 1
|
||||
7ed2: 4e d0 rcall .+156 ; 0x7f70 <getch>
|
||||
7ed4: f8 01 movw r30, r16
|
||||
7ed6: 81 93 st Z+, r24
|
||||
7ed8: 8f 01 movw r16, r30
|
||||
7eda: 11 e0 ldi r17, 0x01 ; 1
|
||||
7edc: 4e d0 rcall .+156 ; 0x7f7a <getch>
|
||||
7ede: f8 01 movw r30, r16
|
||||
7ee0: 81 93 st Z+, r24
|
||||
7ee2: 8f 01 movw r16, r30
|
||||
while (--length);
|
||||
7eda: fe 12 cpse r15, r30
|
||||
7edc: fa cf rjmp .-12 ; 0x7ed2 <main+0xd2>
|
||||
7ee4: fe 12 cpse r15, r30
|
||||
7ee6: fa cf rjmp .-12 ; 0x7edc <main+0xd8>
|
||||
|
||||
// Read command terminator, start reply
|
||||
verifySpace();
|
||||
7ede: 5a d0 rcall .+180 ; 0x7f94 <verifySpace>
|
||||
7ee0: f5 e4 ldi r31, 0x45 ; 69
|
||||
7ee8: 5a d0 rcall .+180 ; 0x7f9e <verifySpace>
|
||||
7eea: f5 e4 ldi r31, 0x45 ; 69
|
||||
* void writebuffer(memtype, buffer, address, length)
|
||||
*/
|
||||
static inline void writebuffer(int8_t memtype, addr16_t mybuff,
|
||||
addr16_t address, pagelen_t len)
|
||||
{
|
||||
switch (memtype) {
|
||||
7ee2: bf 12 cpse r11, r31
|
||||
7ee4: 01 c0 rjmp .+2 ; 0x7ee8 <main+0xe8>
|
||||
7ee6: ff cf rjmp .-2 ; 0x7ee6 <main+0xe6>
|
||||
7ee8: 83 e0 ldi r24, 0x03 ; 3
|
||||
* Start the page erase and wait for it to finish. There
|
||||
* used to be code to do this while receiving the data over
|
||||
* the serial link, but the performance improvement was slight,
|
||||
7eec: bf 12 cpse r11, r31
|
||||
7eee: 01 c0 rjmp .+2 ; 0x7ef2 <main+0xee>
|
||||
7ef0: ff cf rjmp .-2 ; 0x7ef0 <main+0xec>
|
||||
7ef2: 83 e0 ldi r24, 0x03 ; 3
|
||||
* and we needed the space back.
|
||||
*/
|
||||
#ifdef FOURPAGEERASE
|
||||
if ((address.bytes[0] & ((SPM_PAGESIZE<<2)-1))==0) {
|
||||
#endif
|
||||
__boot_page_erase_short(address.word);
|
||||
7eea: fe 01 movw r30, r28
|
||||
7eec: 87 bf out 0x37, r24 ; 55
|
||||
7eee: e8 95 spm
|
||||
7ef0: 07 b6 in r0, 0x37 ; 55
|
||||
7ef4: fe 01 movw r30, r28
|
||||
7ef6: 87 bf out 0x37, r24 ; 55
|
||||
7ef8: e8 95 spm
|
||||
7efa: 07 b6 in r0, 0x37 ; 55
|
||||
boot_spm_busy_wait();
|
||||
7ef2: 00 fc sbrc r0, 0
|
||||
7ef4: fd cf rjmp .-6 ; 0x7ef0 <main+0xf0>
|
||||
7ef6: a0 e0 ldi r26, 0x00 ; 0
|
||||
7ef8: b1 e0 ldi r27, 0x01 ; 1
|
||||
7efa: fe 01 movw r30, r28
|
||||
7efc: 8d 91 ld r24, X+
|
||||
7efc: 00 fc sbrc r0, 0
|
||||
7efe: fd cf rjmp .-6 ; 0x7efa <main+0xf6>
|
||||
7f00: a0 e0 ldi r26, 0x00 ; 0
|
||||
7f02: b1 e0 ldi r27, 0x01 ; 1
|
||||
7f04: fe 01 movw r30, r28
|
||||
7f06: 8d 91 ld r24, X+
|
||||
|
||||
/*
|
||||
* Copy data from the buffer into the flash write buffer.
|
||||
*/
|
||||
do {
|
||||
__boot_page_fill_short((uint16_t)(void*)addrPtr, *(mybuff.wptr++));
|
||||
7efe: 9d 91 ld r25, X+
|
||||
7f00: 0c 01 movw r0, r24
|
||||
7f02: e7 be out 0x37, r14 ; 55
|
||||
7f04: e8 95 spm
|
||||
7f06: 11 24 eor r1, r1
|
||||
7f08: 32 96 adiw r30, 0x02 ; 2
|
||||
7f08: 9d 91 ld r25, X+
|
||||
7f0a: 0c 01 movw r0, r24
|
||||
7f0c: e7 be out 0x37, r14 ; 55
|
||||
7f0e: e8 95 spm
|
||||
7f10: 11 24 eor r1, r1
|
||||
7f12: 32 96 adiw r30, 0x02 ; 2
|
||||
addrPtr += 2;
|
||||
} while (len -= 2);
|
||||
7f0a: fa 12 cpse r15, r26
|
||||
7f14: fa 12 cpse r15, r26
|
||||
|
||||
/*
|
||||
* Actually Write the buffer to flash (and wait for it to finish.)
|
||||
*/
|
||||
__boot_page_write_short(address.word);
|
||||
7f0c: f7 cf rjmp .-18 ; 0x7efc <main+0xfc>
|
||||
7f0e: fe 01 movw r30, r28
|
||||
7f16: f7 cf rjmp .-18 ; 0x7f06 <main+0x102>
|
||||
7f18: fe 01 movw r30, r28
|
||||
boot_spm_busy_wait();
|
||||
7f10: d7 be out 0x37, r13 ; 55
|
||||
7f12: e8 95 spm
|
||||
7f1a: d7 be out 0x37, r13 ; 55
|
||||
7f1c: e8 95 spm
|
||||
#if defined(RWWSRE)
|
||||
// Reenable read access to flash
|
||||
__boot_rww_enable_short();
|
||||
7f14: 07 b6 in r0, 0x37 ; 55
|
||||
7f16: 00 fc sbrc r0, 0
|
||||
7f18: fd cf rjmp .-6 ; 0x7f14 <main+0x114>
|
||||
7f1e: 07 b6 in r0, 0x37 ; 55
|
||||
7f20: 00 fc sbrc r0, 0
|
||||
7f22: fd cf rjmp .-6 ; 0x7f1e <main+0x11a>
|
||||
writebuffer(desttype, buff, address, savelength);
|
||||
|
||||
|
||||
}
|
||||
/* Read memory block mode, length is big endian. */
|
||||
else if(ch == STK_READ_PAGE) {
|
||||
7f1a: c7 be out 0x37, r12 ; 55
|
||||
7f1c: e8 95 spm
|
||||
7f24: c7 be out 0x37, r12 ; 55
|
||||
7f26: e8 95 spm
|
||||
uint8_t desttype;
|
||||
GETLENGTH(length);
|
||||
7f1e: 1e c0 rjmp .+60 ; 0x7f5c <main+0x15c>
|
||||
7f20: 84 37 cpi r24, 0x74 ; 116
|
||||
7f22: 71 f4 brne .+28 ; 0x7f40 <main+0x140>
|
||||
7f28: 1e c0 rjmp .+60 ; 0x7f66 <main+0x162>
|
||||
7f2a: 84 37 cpi r24, 0x74 ; 116
|
||||
7f2c: 71 f4 brne .+28 ; 0x7f4a <main+0x146>
|
||||
|
||||
desttype = getch();
|
||||
7f24: 25 d0 rcall .+74 ; 0x7f70 <getch>
|
||||
7f2e: 25 d0 rcall .+74 ; 0x7f7a <getch>
|
||||
|
||||
verifySpace();
|
||||
7f26: 24 d0 rcall .+72 ; 0x7f70 <getch>
|
||||
7f28: f8 2e mov r15, r24
|
||||
7f2a: 22 d0 rcall .+68 ; 0x7f70 <getch>
|
||||
7f30: 24 d0 rcall .+72 ; 0x7f7a <getch>
|
||||
7f32: f8 2e mov r15, r24
|
||||
7f34: 22 d0 rcall .+68 ; 0x7f7a <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));
|
||||
7f2c: 33 d0 rcall .+102 ; 0x7f94 <verifySpace>
|
||||
7f2e: 8e 01 movw r16, r28
|
||||
7f36: 33 d0 rcall .+102 ; 0x7f9e <verifySpace>
|
||||
7f38: 8e 01 movw r16, r28
|
||||
#endif
|
||||
putch(ch);
|
||||
7f30: f8 01 movw r30, r16
|
||||
7f3a: f8 01 movw r30, r16
|
||||
} while (--length);
|
||||
7f32: 85 91 lpm r24, Z+
|
||||
7f34: 8f 01 movw r16, r30
|
||||
7f36: 15 d0 rcall .+42 ; 0x7f62 <putch>
|
||||
7f38: fa 94 dec r15
|
||||
7f3c: 85 91 lpm r24, Z+
|
||||
7f3e: 8f 01 movw r16, r30
|
||||
7f40: 15 d0 rcall .+42 ; 0x7f6c <putch>
|
||||
7f42: fa 94 dec r15
|
||||
|
||||
read_mem(desttype, address, length);
|
||||
}
|
||||
|
||||
/* Get device signature bytes */
|
||||
else if(ch == STK_READ_SIGN) {
|
||||
7f3a: f1 10 cpse r15, r1
|
||||
7f3c: f9 cf rjmp .-14 ; 0x7f30 <main+0x130>
|
||||
7f44: f1 10 cpse r15, r1
|
||||
7f46: f9 cf rjmp .-14 ; 0x7f3a <main+0x136>
|
||||
// READ SIGN - return what Avrdude wants to hear
|
||||
verifySpace();
|
||||
7f3e: 0e c0 rjmp .+28 ; 0x7f5c <main+0x15c>
|
||||
7f40: 85 37 cpi r24, 0x75 ; 117
|
||||
7f48: 0e c0 rjmp .+28 ; 0x7f66 <main+0x162>
|
||||
7f4a: 85 37 cpi r24, 0x75 ; 117
|
||||
putch(SIGNATURE_0);
|
||||
7f42: 39 f4 brne .+14 ; 0x7f52 <main+0x152>
|
||||
7f44: 27 d0 rcall .+78 ; 0x7f94 <verifySpace>
|
||||
7f46: 8e e1 ldi r24, 0x1E ; 30
|
||||
7f4c: 39 f4 brne .+14 ; 0x7f5c <main+0x158>
|
||||
7f4e: 27 d0 rcall .+78 ; 0x7f9e <verifySpace>
|
||||
7f50: 8e e1 ldi r24, 0x1E ; 30
|
||||
putch(SIGNATURE_1);
|
||||
7f48: 0c d0 rcall .+24 ; 0x7f62 <putch>
|
||||
7f4a: 85 e9 ldi r24, 0x95 ; 149
|
||||
7f4c: 0a d0 rcall .+20 ; 0x7f62 <putch>
|
||||
7f52: 0c d0 rcall .+24 ; 0x7f6c <putch>
|
||||
7f54: 85 e9 ldi r24, 0x95 ; 149
|
||||
7f56: 0a d0 rcall .+20 ; 0x7f6c <putch>
|
||||
putch(SIGNATURE_2);
|
||||
7f4e: 8f e0 ldi r24, 0x0F ; 15
|
||||
7f50: 9c cf rjmp .-200 ; 0x7e8a <main+0x8a>
|
||||
7f58: 8f e0 ldi r24, 0x0F ; 15
|
||||
7f5a: 9c cf rjmp .-200 ; 0x7e94 <main+0x90>
|
||||
}
|
||||
else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
|
||||
7f52: 81 35 cpi r24, 0x51 ; 81
|
||||
7f54: 11 f4 brne .+4 ; 0x7f5a <main+0x15a>
|
||||
7f5c: 81 35 cpi r24, 0x51 ; 81
|
||||
7f5e: 11 f4 brne .+4 ; 0x7f64 <main+0x160>
|
||||
// Adaboot no-wait mod
|
||||
watchdogConfig(WATCHDOG_16MS);
|
||||
7f56: 88 e0 ldi r24, 0x08 ; 8
|
||||
7f58: 17 d0 rcall .+46 ; 0x7f88 <watchdogConfig>
|
||||
7f5a: 1c d0 rcall .+56 ; 0x7f94 <verifySpace>
|
||||
7f60: 88 e0 ldi r24, 0x08 ; 8
|
||||
7f62: 17 d0 rcall .+46 ; 0x7f92 <watchdogConfig>
|
||||
7f64: 1c d0 rcall .+56 ; 0x7f9e <verifySpace>
|
||||
verifySpace();
|
||||
}
|
||||
else {
|
||||
// This covers the response to commands like STK_ENTER_PROGMODE
|
||||
verifySpace();
|
||||
7f5c: 80 e1 ldi r24, 0x10 ; 16
|
||||
7f5e: 01 d0 rcall .+2 ; 0x7f62 <putch>
|
||||
7f66: 80 e1 ldi r24, 0x10 ; 16
|
||||
7f68: 01 d0 rcall .+2 ; 0x7f6c <putch>
|
||||
}
|
||||
putch(STK_OK);
|
||||
7f60: 87 cf rjmp .-242 ; 0x7e70 <main+0x70>
|
||||
7f6a: 87 cf rjmp .-242 ; 0x7e7a <main+0x76>
|
||||
|
||||
00007f62 <putch>:
|
||||
7f62: 90 91 c0 00 lds r25, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0>
|
||||
00007f6c <putch>:
|
||||
7f6c: 90 91 c0 00 lds r25, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0>
|
||||
}
|
||||
7f66: 95 ff sbrs r25, 5
|
||||
7f70: 95 ff sbrs r25, 5
|
||||
}
|
||||
|
||||
void putch(char ch) {
|
||||
#ifndef SOFT_UART
|
||||
while (!(UART_SRA & _BV(UDRE0)));
|
||||
7f68: fc cf rjmp .-8 ; 0x7f62 <putch>
|
||||
UART_UDR = ch;
|
||||
7f6a: 80 93 c6 00 sts 0x00C6, r24 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6>
|
||||
7f6e: 08 95 ret
|
||||
#ifndef LIN_UART
|
||||
while (!(UART_SRA & _BV(UDRE0))) { /* Spin */ }
|
||||
7f72: fc cf rjmp .-8 ; 0x7f6c <putch>
|
||||
#else
|
||||
while (!(LINSIR & _BV(LTXOK))) { /* Spin */ }
|
||||
#endif
|
||||
|
||||
00007f70 <getch>:
|
||||
[uartBit] "I" (UART_RX_BIT)
|
||||
UART_UDR = ch;
|
||||
7f74: 80 93 c6 00 sts 0x00C6, r24 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6>
|
||||
7f78: 08 95 ret
|
||||
|
||||
00007f7a <getch>:
|
||||
:
|
||||
"r25"
|
||||
);
|
||||
#else
|
||||
while(!(UART_SRA & _BV(RXC0)))
|
||||
7f70: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0>
|
||||
7f74: 87 ff sbrs r24, 7
|
||||
7f76: fc cf rjmp .-8 ; 0x7f70 <getch>
|
||||
;
|
||||
#ifndef LIN_UART
|
||||
while(!(UART_SRA & _BV(RXC0))) { /* Spin */ }
|
||||
7f7a: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0>
|
||||
7f7e: 87 ff sbrs r24, 7
|
||||
7f80: fc cf rjmp .-8 ; 0x7f7a <getch>
|
||||
if (!(UART_SRA & _BV(FE0))) {
|
||||
7f78: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0>
|
||||
7f7c: 84 fd sbrc r24, 4
|
||||
7f7e: 01 c0 rjmp .+2 ; 0x7f82 <getch+0x12>
|
||||
7f82: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__TEXT_REGION_LENGTH__+0x7e00c0>
|
||||
7f86: 84 fd sbrc r24, 4
|
||||
7f88: 01 c0 rjmp .+2 ; 0x7f8c <getch+0x12>
|
||||
}
|
||||
#endif
|
||||
|
||||
// Watchdog functions. These are only safe with interrupts turned off.
|
||||
void watchdogReset() {
|
||||
__asm__ __volatile__ (
|
||||
7f80: a8 95 wdr
|
||||
7f8a: a8 95 wdr
|
||||
* don't care that an invalid char is returned...)
|
||||
*/
|
||||
watchdogReset();
|
||||
}
|
||||
|
||||
ch = UART_UDR;
|
||||
7f82: 80 91 c6 00 lds r24, 0x00C6 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6>
|
||||
7f8c: 80 91 c6 00 lds r24, 0x00C6 ; 0x8000c6 <__TEXT_REGION_LENGTH__+0x7e00c6>
|
||||
LED_PIN |= _BV(LED);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return ch;
|
||||
}
|
||||
7f86: 08 95 ret
|
||||
7f90: 08 95 ret
|
||||
|
||||
00007f88 <watchdogConfig>:
|
||||
"wdr\n"
|
||||
);
|
||||
00007f92 <watchdogConfig>:
|
||||
}
|
||||
|
||||
void watchdogConfig(uint8_t x) {
|
||||
#ifdef WDCE //does it have a Watchdog Change Enable?
|
||||
#ifdef WDTCSR
|
||||
WDTCSR = _BV(WDCE) | _BV(WDE);
|
||||
7f88: e0 e6 ldi r30, 0x60 ; 96
|
||||
7f8a: f0 e0 ldi r31, 0x00 ; 0
|
||||
7f8c: 98 e1 ldi r25, 0x18 ; 24
|
||||
7f8e: 90 83 st Z, r25
|
||||
WDTCSR = x;
|
||||
7f90: 80 83 st Z, r24
|
||||
7f92: 08 95 ret
|
||||
7f92: e0 e6 ldi r30, 0x60 ; 96
|
||||
7f94: f0 e0 ldi r31, 0x00 ; 0
|
||||
7f96: 98 e1 ldi r25, 0x18 ; 24
|
||||
7f98: 90 83 st Z, r25
|
||||
#else //then it must be one of those newfangled ones that use CCP
|
||||
CCP=0xD8; //so write this magic number to CCP
|
||||
#endif
|
||||
|
||||
00007f94 <verifySpace>:
|
||||
#ifdef WDTCSR
|
||||
WDTCSR = x;
|
||||
7f9a: 80 83 st Z, r24
|
||||
7f9c: 08 95 ret
|
||||
|
||||
00007f9e <verifySpace>:
|
||||
do getch(); while (--count);
|
||||
verifySpace();
|
||||
}
|
||||
|
||||
void verifySpace() {
|
||||
if (getch() != CRC_EOP) {
|
||||
7f94: ed df rcall .-38 ; 0x7f70 <getch>
|
||||
7f96: 80 32 cpi r24, 0x20 ; 32
|
||||
7f98: 19 f0 breq .+6 ; 0x7fa0 <verifySpace+0xc>
|
||||
7f9e: ed df rcall .-38 ; 0x7f7a <getch>
|
||||
7fa0: 80 32 cpi r24, 0x20 ; 32
|
||||
7fa2: 19 f0 breq .+6 ; 0x7faa <verifySpace+0xc>
|
||||
watchdogConfig(WATCHDOG_16MS); // shorten WD timeout
|
||||
7f9a: 88 e0 ldi r24, 0x08 ; 8
|
||||
7f9c: f5 df rcall .-22 ; 0x7f88 <watchdogConfig>
|
||||
7f9e: ff cf rjmp .-2 ; 0x7f9e <verifySpace+0xa>
|
||||
7fa4: 88 e0 ldi r24, 0x08 ; 8
|
||||
7fa6: f5 df rcall .-22 ; 0x7f92 <watchdogConfig>
|
||||
7fa8: ff cf rjmp .-2 ; 0x7fa8 <verifySpace+0xa>
|
||||
while (1) // and busy-loop so that WD causes
|
||||
; // a reset and app start.
|
||||
}
|
||||
putch(STK_INSYNC);
|
||||
7fa0: 84 e1 ldi r24, 0x14 ; 20
|
||||
7fa2: df cf rjmp .-66 ; 0x7f62 <putch>
|
||||
7faa: 84 e1 ldi r24, 0x14 ; 20
|
||||
7fac: df cf rjmp .-66 ; 0x7f6c <putch>
|
||||
|
||||
00007fa4 <getNch>:
|
||||
00007fae <getNch>:
|
||||
::[count] "M" (UART_B_VALUE)
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
void getNch(uint8_t count) {
|
||||
7fa4: cf 93 push r28
|
||||
7fa6: c8 2f mov r28, r24
|
||||
7fae: cf 93 push r28
|
||||
7fb0: c8 2f mov r28, r24
|
||||
do getch(); while (--count);
|
||||
7fa8: e3 df rcall .-58 ; 0x7f70 <getch>
|
||||
7faa: c1 50 subi r28, 0x01 ; 1
|
||||
7fac: e9 f7 brne .-6 ; 0x7fa8 <getNch+0x4>
|
||||
7fb2: e3 df rcall .-58 ; 0x7f7a <getch>
|
||||
7fb4: c1 50 subi r28, 0x01 ; 1
|
||||
7fb6: e9 f7 brne .-6 ; 0x7fb2 <getNch+0x4>
|
||||
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) {
|
||||
// save the reset flags in the designated register
|
||||
// This can be saved in a main program by putting code in .init0 (which
|
||||
// executes before normal c init code) to save R2 to a global variable.
|
||||
__asm__ __volatile__ ("mov r2, %0\n" :: "r" (rstFlags));
|
||||
7fb2: 28 2e mov r2, r24
|
||||
00007fbc <do_spm>:
|
||||
7fbc: fc 01 movw r30, r24
|
||||
* data=0 in WRITE
|
||||
*/
|
||||
static void do_spm(uint16_t address, uint8_t command, uint16_t data) __attribute__ ((used));
|
||||
static void do_spm(uint16_t address, uint8_t command, uint16_t data) {
|
||||
// Do spm stuff
|
||||
asm volatile (
|
||||
7fbe: 0a 01 movw r0, r20
|
||||
7fc0: 67 bf out 0x37, r22 ; 55
|
||||
7fc2: e8 95 spm
|
||||
7fc4: 11 24 eor r1, r1
|
||||
7fc6: 07 b6 in r0, 0x37 ; 55
|
||||
);
|
||||
|
||||
watchdogConfig(WATCHDOG_OFF);
|
||||
7fb4: 80 e0 ldi r24, 0x00 ; 0
|
||||
7fb6: e8 df rcall .-48 ; 0x7f88 <watchdogConfig>
|
||||
7fb8: e0 e0 ldi r30, 0x00 ; 0
|
||||
// Note that appstart_vec is defined so that this works with either
|
||||
// real or virtual boot partitions.
|
||||
__asm__ __volatile__ (
|
||||
7fba: ff 27 eor r31, r31
|
||||
7fbc: 09 94 ijmp
|
||||
// wait for spm to complete
|
||||
// it doesn't have much sense for __BOOT_PAGE_FILL,
|
||||
// but it doesn't hurt and saves some bytes on 'if'
|
||||
boot_spm_busy_wait();
|
||||
7fc8: 00 fc sbrc r0, 0
|
||||
7fca: fd cf rjmp .-6 ; 0x7fc6 <do_spm+0xa>
|
||||
7fcc: 66 70 andi r22, 0x06 ; 6
|
||||
#if defined(RWWSRE)
|
||||
// this 'if' condition should be: (command == __BOOT_PAGE_WRITE || command == __BOOT_PAGE_ERASE)...
|
||||
// but it's tweaked a little assuming that in every command we are interested in here, there
|
||||
// must be also SELFPRGEN set. If we skip checking this bit, we save here 4B
|
||||
if ((command & (_BV(PGWRT)|_BV(PGERS))) && (data == 0) ) {
|
||||
7fce: 29 f0 breq .+10 ; 0x7fda <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
|
||||
|
@ -1,40 +1,53 @@
|
||||
:10FC0000112484B7882349F0982F9A70923029F0F4
|
||||
:10FC100081FF02C097EF94BFFBD085E08093810005
|
||||
:10FC200082E08093C00088E18093C10086E08093E9
|
||||
:10FC3000C20080E18093C4008EE0D5D0209A86E097
|
||||
:10FC400020E33CEF91E0309385002093840096BB45
|
||||
:10FC5000B09BFECF189AA8954091C00047FD02C006
|
||||
:10FC6000815089F7FF24F39455E0E52E61E1D62E0B
|
||||
:10FC7000AED0813461F4ABD0C82FBBD0C238E9F02C
|
||||
:10FC8000C13811F487E001C083E09AD096C0823475
|
||||
:10FC900011F484E103C0853419F485E0B2D08DC03D
|
||||
:10FCA000853539F494D0082F92D0182F000F111FEA
|
||||
:10FCB00083C0863521F484E0A4D080E0E6CF84368A
|
||||
:10FCC00009F048C084D0C82FD0E0DC2FCC277FD0EB
|
||||
:10FCD000C82B7DD0C82E5E01812C9924939477D0B7
|
||||
:10FCE000F40181934F01F1E0AF1AB108C1F781D05F
|
||||
:10FCF00085E4C81212C0D3954801A12CBB24B3944B
|
||||
:10FD0000AC16BD0609F459C0F50161915F01C4014B
|
||||
:10FD10008DD0FFEF8F1A9F0AF3CF83E0F80187BFE2
|
||||
:10FD2000E89507B600FCFDCFA0E0B1E0F8018D91A9
|
||||
:10FD30009D910C01F7BEE8951124229732962097E9
|
||||
:10FD4000B1F7F801E7BEE89507B600FCFDCFD7BED6
|
||||
:10FD5000E89533C0843719F53AD0C82FD0E0DC2FAE
|
||||
:10FD6000CC2735D05E01A82A32D0982E42D0E801A7
|
||||
:10FD7000F5E49F120BC0CE0151D022D081E0A81A29
|
||||
:10FD8000B1082196A114B104B1F717C0FE01859105
|
||||
:10FD9000EF0116D0E1E0AE1AB108C1F70EC0853709
|
||||
:10FDA00039F427D08EE10CD086E90AD08AE06DCFF5
|
||||
:10FDB000813511F488E017D01CD080E101D058CFF4
|
||||
:10FDC0009091C00095FFFCCF8093C600089580916C
|
||||
:10FDD000C00087FFFCCF8091C00084FD01C0A895C2
|
||||
:10FDE0008091C6000895E0E6F0E098E1908380837A
|
||||
:10FDF0000895EDDF803219F088E0F5DFFFCF84E170
|
||||
:10FE0000DFCFCF93C82FE3DFC150E9F7CF91F1CF18
|
||||
:10FE1000282E80E0E8DFE0E0FF270994F999FECF83
|
||||
:10FE200092BD81BDF89A992780B50895262FF9993A
|
||||
:10FE3000FECF1FBA92BD81BD20BD0FB6F894FA9ACD
|
||||
:08FE4000F99A0FBE0196089526
|
||||
:02FFFE000007FA
|
||||
:10FC000011E0A0E0B1E0ECE7FEEF02C005900D923C
|
||||
:10FC1000AC39B107D9F701C00BC1112484B78823CF
|
||||
:10FC200061F0982F9A70923041F081FF02C097EFF7
|
||||
:10FC300094BF282E80E0E7D0E3C185E08093810067
|
||||
:10FC400082E08093C00088E18093C10086E08093C9
|
||||
:10FC5000C20080E18093C4008EE0D5D0209A86E077
|
||||
:10FC600020E33CEF91E0309385002093840096BB25
|
||||
:10FC7000B09BFECF189AA8954091C00047FD02C0E6
|
||||
:10FC8000815089F7FF24F39455E0E52E61E1D62EEB
|
||||
:10FC9000AED0813461F4ABD0C82FBBD0C238E9F00C
|
||||
:10FCA000C13811F488E001C083E09AD096C0823454
|
||||
:10FCB00011F484E103C0853419F485E0B2D08DC01D
|
||||
:10FCC000853539F494D0082F92D0182F000F111FCA
|
||||
:10FCD00083C0863521F484E0A4D080E0E6CF84366A
|
||||
:10FCE00009F048C084D0C82FD0E0DC2FCC277FD0CB
|
||||
:10FCF000C82B7DD0C82E5E01812C9924939477D097
|
||||
:10FD0000F40181934F01F1E0AF1AB108C1F781D03E
|
||||
:10FD100085E4C81212C0D3954801A12CBB24B3942A
|
||||
:10FD2000AC16BD0609F459C0F50161915F01C4012B
|
||||
:10FD300097D0FFEF8F1A9F0AF3CF83E0F80187BFB8
|
||||
:10FD4000E89507B600FCFDCFA0E0B1E0F8018D9189
|
||||
:10FD50009D910C01F7BEE8951124229732962097C9
|
||||
:10FD6000B1F7F801E7BEE89507B600FCFDCFD7BEB6
|
||||
:10FD7000E89533C0843719F53AD0C82FD0E0DC2F8E
|
||||
:10FD8000CC2735D05E01A82A32D0982E42D0E80187
|
||||
:10FD9000F5E49F120BC0CE015BD022D081E0A81AFF
|
||||
:10FDA000B1082196A114B104B1F717C0FE018591E5
|
||||
:10FDB000EF0116D0E1E0AE1AB108C1F70EC08537E9
|
||||
:10FDC00039F427D08EE10CD086E90AD08AE06DCFD5
|
||||
:10FDD000813511F488E017D01CD080E101D058CFD4
|
||||
:10FDE0009091C00095FFFCCF8093C600089580914C
|
||||
:10FDF000C00087FFFCCF8091C00084FD01C0A895A2
|
||||
:10FE00008091C6000895E0E6F0E098E19083808359
|
||||
:10FE10000895EDDF803219F088E0F5DFFFCF84E14F
|
||||
:10FE2000DFCFCF93C82FE3DFC150E9F7CF91F1CFF8
|
||||
:10FE3000FC010A0167BFE895112407B600FCFDCF5D
|
||||
:10FE4000667029F0452B19F481E187BFE895089584
|
||||
:10FE5000F999FECF92BD81BDF89A992780B5089592
|
||||
:10FE6000262FF999FECF1FBA92BD81BD20BD0FB6D6
|
||||
:0CFE7000F894FA9AF99A0FBE01960895D2
|
||||
:10FE7C0056657273696F6E3D382E30004F50544981
|
||||
:10FE8C00424F4F545F435553544F4D5645523D309E
|
||||
:10FE9C00004465766963653D61746D6567613634F0
|
||||
:10FEAC00347000465F4350553D3136303030303081
|
||||
:10FEBC00304C00424947424F4F543D310042756926
|
||||
:10FECC006C743A53657020323020323031383A300D
|
||||
:10FEDC00313A31383A353000554152543D300042B8
|
||||
:10FEEC004155445F524154453D313135323030003B
|
||||
:10FEFC004C45443D4230004C45445F5354415254B0
|
||||
:0CFF0C005F464C41534845533D33000014
|
||||
:02FFFE000008F9
|
||||
:040000030000FC00FD
|
||||
:00000001FF
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
238
optiboot/examples/test_dospm/test_dospm.ino
Normal file
238
optiboot/examples/test_dospm/test_dospm.ino
Normal 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
|
||||
|
@ -5,6 +5,8 @@
|
||||
# Build a "release" .zip file for Optiboot bootloader
|
||||
# Run from the build directory
|
||||
|
||||
version=$1
|
||||
|
||||
# Uncomment if you want a clean builds of specific files
|
||||
# make clean
|
||||
# make atmega328
|
||||
@ -18,7 +20,7 @@ rm -Rf /tmp/optiboot-release
|
||||
# Note that the structure under "packages" (handed by boards manager)
|
||||
# is different than the structure under "sketchbook/hardware" would be.
|
||||
|
||||
TOP=/tmp/optiboot-release/Optiboot$1/
|
||||
TOP=/tmp/optiboot-release/Optiboot-$version/
|
||||
#
|
||||
# Bootloaders directory
|
||||
mkdir -p $TOP/bootloaders/optiboot
|
||||
@ -38,12 +40,12 @@ cp ../../boards-1.6.txt $TOP/boards.txt
|
||||
|
||||
#
|
||||
# Create platform.txt, because it contains the "group" name for the boards menu
|
||||
echo name=Optiboot $1 > $TOP/platform.txt
|
||||
echo version=$1 >> $TOP/platform.txt
|
||||
echo name=Optiboot $version > $TOP/platform.txt
|
||||
echo version=$version >> $TOP/platform.txt
|
||||
|
||||
#
|
||||
# Create a README file.
|
||||
echo This is an Optiboot version $1 \"Binary\" Release. > $TOP/README.TXT
|
||||
echo This is an Optiboot version $version \"Binary\" Release. > $TOP/README.TXT
|
||||
echo >> $TOP/README.TXT
|
||||
echo For Source code see http://github.com/Optiboot/optiboot>> $TOP/README.TXT
|
||||
|
||||
@ -63,11 +65,11 @@ cp *.hex $TOP/bootloaders/optiboot
|
||||
#
|
||||
# zip everything up.
|
||||
pushd /tmp/optiboot-release
|
||||
zip -r Optiboot$1.zip Optiboot$1
|
||||
HASH=`openssl dgst -sha256 Optiboot$1.zip | sed -e 's/.* //'`
|
||||
SIZE=`stat -f %z Optiboot$1.zip`
|
||||
zip -r Optiboot-$version.zip Optiboot-$version
|
||||
HASH=`openssl dgst -sha256 Optiboot-$version.zip | sed -e 's/.* //'`
|
||||
SIZE=`stat -f %z Optiboot-$version.zip`
|
||||
popd
|
||||
sed -e "s/#.*//" -e "s/%HASH%/$HASH/g" -e "s/%VERSION%/$1/g" -e "s/%SIZE%/$SIZE/g" ../../package_optiboot_optiboot-additional_index.json.TEMPLATE > /tmp/optiboot-release/package_optiboot_optiboot-additional_index.json
|
||||
sed -e "s/#.*//" -e "s/%HASH%/$HASH/g" -e "s/%VERSION%/$version/g" -e "s/%SIZE%/$SIZE/g" ../../package_optiboot_optiboot-additional_index.json.TEMPLATE > /tmp/optiboot-release/package_optiboot_optiboot-additional_index.json
|
||||
|
||||
#
|
||||
# This leaves the .zip and the .json file in /tmp/optiboot-release
|
||||
|
Reference in New Issue
Block a user