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

Fix/small rewrite of Virtual boot partition

* Changed interrupt vector to save original jump. Now uses SPM_Ready
  instead of watchdog's.
* Rewrite/fix 'rjmp' part to use and calculate correctly on all 12 bits
  of address.
* Added 'virboot8' test target to Makefile with Virtboot on Atmega8.
This commit is contained in:
majekw
2015-05-29 01:03:14 +02:00
parent 49e184b0f0
commit 6e7851a093
2 changed files with 54 additions and 26 deletions

View File

@ -236,6 +236,15 @@ endif
# Test platforms # Test platforms
# Virtual boot block test # Virtual boot block test
virboot8: TARGET = atmega8
virboot8: MCU_TARGET = atmega8
virboot8: CFLAGS += $(COMMON_OPTIONS) '-DVIRTUAL_BOOT_PARTITION'
virboot8: AVR_FREQ ?= 16000000L
virboot8: LDSECTIONS = -Wl,--section-start=.text=0x1c00 -Wl,--section-start=.version=0x1ffe
virboot8: $(PROGRAM)_virboot8.hex
virboot8: $(PROGRAM)_virboot8.lst
virboot328: TARGET = atmega328 virboot328: TARGET = atmega328
virboot328: MCU_TARGET = atmega328p virboot328: MCU_TARGET = atmega328p
virboot328: CFLAGS += $(COMMON_OPTIONS) '-DVIRTUAL_BOOT_PARTITION' virboot328: CFLAGS += $(COMMON_OPTIONS) '-DVIRTUAL_BOOT_PARTITION'

View File

@ -388,25 +388,41 @@ void appStart(uint8_t rstFlags) __attribute__ ((naked));
/* These definitions are NOT zero initialised, but that doesn't matter */ /* These definitions are NOT zero initialised, but that doesn't matter */
/* This allows us to drop the zero init code, saving us memory */ /* This allows us to drop the zero init code, saving us memory */
#define buff ((uint8_t*)(RAMSTART)) #define buff ((uint8_t*)(RAMSTART))
/* Virtual boot partition support */
#ifdef VIRTUAL_BOOT_PARTITION #ifdef VIRTUAL_BOOT_PARTITION
#define rstVect0_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+4)) #define rstVect0_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+4))
#define rstVect1_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+5)) #define rstVect1_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+5))
#define wdtVect0_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #define saveVect0_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+6))
#define wdtVect1_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+7)) #define saveVect1_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+7))
// Vector to save original reset jump - SPM Ready is least probably used
#if defined (SPM_RDY_vect_num)
#define save_vect_num (SPM_RDY_vect_num)
#elif defined (SPM_READY_vect_num)
#define save_vect_num (SPM_READY_vect_num)
#else
#error Cant find SPM interrupt vector for this CPU
#endif
// check if it's on the same page (code assumes that)
#if (SPM_PAGESIZE <= save_vect_num)
#error Save vector not in the same page as reset!
#endif
#if FLASHEND > 8192 #if FLASHEND > 8192
// AVRs with more than 8k of flash have 4-byte vectors, and use jmp. // AVRs with more than 8k of flash have 4-byte vectors, and use jmp.
// We save only 16 bits of address, so devices with more than 128KB
// may behave wrong for upper part of address space.
#define rstVect0 2 #define rstVect0 2
#define rstVect1 3 #define rstVect1 3
#define wdtVect0 (WDT_vect_num*4+2) #define saveVect0 (save_vect_num*4+2)
#define wdtVect1 (WDT_vect_num*4+3) #define saveVect1 (save_vect_num*4+3)
#define appstart_vec (WDT_vect_num*2) #define appstart_vec (save_vect_num*2)
#else #else
// AVRs with up to 8k of flash have 2-byte vectors, and use rjmp. // AVRs with up to 8k of flash have 2-byte vectors, and use rjmp.
#define rstVect0 0 #define rstVect0 0
#define rstVect1 1 #define rstVect1 1
#define wdtVect0 (WDT_vect_num*2) #define saveVect0 (save_vect_num*2)
#define wdtVect1 (WDT_vect_num*2+1) #define saveVect1 (save_vect_num*2+1)
#define appstart_vec (WDT_vect_num) #define appstart_vec (save_vect_num)
#endif #endif
#else #else
#define appstart_vec (0) #define appstart_vec (0)
@ -561,6 +577,7 @@ int main(void) {
#if FLASHEND > 8192 #if FLASHEND > 8192
/* /*
* AVR with 4-byte ISR Vectors and "jmp" * AVR with 4-byte ISR Vectors and "jmp"
* WARNING: this works only up to 128KB flash!
*/ */
if (address == 0) { if (address == 0) {
// This is the reset vector page. We need to live-patch the // This is the reset vector page. We need to live-patch the
@ -569,14 +586,15 @@ int main(void) {
// Save jmp targets (for "Verify") // Save jmp targets (for "Verify")
rstVect0_sav = buff[rstVect0]; rstVect0_sav = buff[rstVect0];
rstVect1_sav = buff[rstVect1]; rstVect1_sav = buff[rstVect1];
wdtVect0_sav = buff[wdtVect0]; saveVect0_sav = buff[saveVect0];
wdtVect1_sav = buff[wdtVect1]; saveVect1_sav = buff[saveVect1];
// Move RESET jmp target to WDT vector // Move RESET jmp target to 'save' vector
buff[wdtVect0] = rstVect0_sav; buff[saveVect0] = rstVect0_sav;
buff[wdtVect1] = rstVect1_sav; buff[saveVect1] = rstVect1_sav;
// Add jump to bootloader at RESET vector // Add jump to bootloader at RESET vector
// WARNING: this works as long as 'main' is in first section
buff[rstVect0] = ((uint16_t)main) & 0xFF; buff[rstVect0] = ((uint16_t)main) & 0xFF;
buff[rstVect1] = ((uint16_t)main) >> 8; buff[rstVect1] = ((uint16_t)main) >> 8;
} }
@ -589,22 +607,23 @@ int main(void) {
// This is the reset vector page. We need to live-patch // This is the reset vector page. We need to live-patch
// the code so the bootloader runs first. // the code so the bootloader runs first.
// //
// Move RESET vector to WDT vector // Move RESET vector to 'save' vector
// Save jmp targets (for "Verify") // Save jmp targets (for "Verify")
rstVect0_sav = buff[rstVect0]; rstVect0_sav = buff[rstVect0];
rstVect1_sav = buff[rstVect1]; rstVect1_sav = buff[rstVect1];
wdtVect0_sav = buff[wdtVect0]; saveVect0_sav = buff[saveVect0];
wdtVect1_sav = buff[wdtVect1]; saveVect1_sav = buff[saveVect1];
// Instruction is a relative jump (rjmp), so recalculate. // Instruction is a relative jump (rjmp), so recalculate.
uint16_t vect=rstVect0_sav+(rstVect1_sav<<8); uint16_t vect=(rstVect0_sav & 0xff) | ((rstVect1_sav & 0x0f)<<8); //calculate 12b displacement
vect -= WDT_vect_num; vect = (vect-save_vect_num) & 0x0fff; //substract 'save' interrupt position and wrap around 4096
// Move RESET jmp target to WDT vector // Move RESET jmp target to 'save' vector
buff[wdtVect0] = vect & 0xff; buff[saveVect0] = vect & 0xff;
buff[wdtVect1] = vect >> 8; buff[saveVect1] = (vect >> 8) | 0xc0; //
// Add rjump to bootloader at RESET vector // Add rjump to bootloader at RESET vector
buff[0] = (((uint16_t)main) & 0xFFF) & 0xFF; // rjmp 0x1d00 instruction vect = ((uint16_t)main) &0x0fff; //WARNIG: this works as long as 'main' is in first section
buff[1] = ((((uint16_t)main) & 0xFFF) >> 8) | 0xC0; buff[0] = vect & 0xFF; // rjmp 0x1c00 instruction
buff[1] = (vect >> 8) | 0xC0;
} }
#endif // FLASHEND #endif // FLASHEND
#endif // VBP #endif // VBP
@ -812,7 +831,7 @@ void appStart(uint8_t rstFlags) {
// Note that appstart_vec is defined so that this works with either // Note that appstart_vec is defined so that this works with either
// real or virtual boot partitions. // real or virtual boot partitions.
__asm__ __volatile__ ( __asm__ __volatile__ (
// Jump to WDT or RST vector // Jump to 'save' or RST vector
"ldi r30,%[rstvec]\n" "ldi r30,%[rstvec]\n"
"clr r31\n" "clr r31\n"
"ijmp\n"::[rstvec] "M"(appstart_vec) "ijmp\n"::[rstvec] "M"(appstart_vec)
@ -905,8 +924,8 @@ static inline void read_mem(uint8_t memtype, uint16_t address, pagelen_t length)
// Undo vector patch in bottom page so verify passes // Undo vector patch in bottom page so verify passes
if (address == rstVect0) ch = rstVect0_sav; if (address == rstVect0) ch = rstVect0_sav;
else if (address == rstVect1) ch = rstVect1_sav; else if (address == rstVect1) ch = rstVect1_sav;
else if (address == wdtVect0) ch = wdtVect0_sav; else if (address == saveVect0) ch = saveVect0_sav;
else if (address == wdtVect1) ch = wdtVect1_sav; else if (address == saveVect1) ch = saveVect1_sav;
else ch = pgm_read_byte_near(address); else ch = pgm_read_byte_near(address);
address++; address++;
#elif defined(RAMPZ) #elif defined(RAMPZ)