mirror of
https://github.com/Optiboot/optiboot.git
synced 2025-07-03 05:42:30 +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:
@ -236,6 +236,15 @@ endif
|
||||
|
||||
# Test platforms
|
||||
# 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: MCU_TARGET = atmega328p
|
||||
virboot328: CFLAGS += $(COMMON_OPTIONS) '-DVIRTUAL_BOOT_PARTITION'
|
||||
|
@ -388,25 +388,41 @@ void appStart(uint8_t rstFlags) __attribute__ ((naked));
|
||||
/* These definitions are NOT zero initialised, but that doesn't matter */
|
||||
/* This allows us to drop the zero init code, saving us memory */
|
||||
#define buff ((uint8_t*)(RAMSTART))
|
||||
|
||||
/* Virtual boot partition support */
|
||||
#ifdef VIRTUAL_BOOT_PARTITION
|
||||
#define rstVect0_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+4))
|
||||
#define rstVect1_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+5))
|
||||
#define wdtVect0_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+6))
|
||||
#define wdtVect1_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+7))
|
||||
#define saveVect0_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+6))
|
||||
#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
|
||||
// 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 rstVect1 3
|
||||
#define wdtVect0 (WDT_vect_num*4+2)
|
||||
#define wdtVect1 (WDT_vect_num*4+3)
|
||||
#define appstart_vec (WDT_vect_num*2)
|
||||
#define saveVect0 (save_vect_num*4+2)
|
||||
#define saveVect1 (save_vect_num*4+3)
|
||||
#define appstart_vec (save_vect_num*2)
|
||||
#else
|
||||
// AVRs with up to 8k of flash have 2-byte vectors, and use rjmp.
|
||||
#define rstVect0 0
|
||||
#define rstVect1 1
|
||||
#define wdtVect0 (WDT_vect_num*2)
|
||||
#define wdtVect1 (WDT_vect_num*2+1)
|
||||
#define appstart_vec (WDT_vect_num)
|
||||
#define saveVect0 (save_vect_num*2)
|
||||
#define saveVect1 (save_vect_num*2+1)
|
||||
#define appstart_vec (save_vect_num)
|
||||
#endif
|
||||
#else
|
||||
#define appstart_vec (0)
|
||||
@ -561,6 +577,7 @@ int main(void) {
|
||||
#if FLASHEND > 8192
|
||||
/*
|
||||
* AVR with 4-byte ISR Vectors and "jmp"
|
||||
* WARNING: this works only up to 128KB flash!
|
||||
*/
|
||||
if (address == 0) {
|
||||
// This is the reset vector page. We need to live-patch the
|
||||
@ -569,14 +586,15 @@ int main(void) {
|
||||
// Save jmp targets (for "Verify")
|
||||
rstVect0_sav = buff[rstVect0];
|
||||
rstVect1_sav = buff[rstVect1];
|
||||
wdtVect0_sav = buff[wdtVect0];
|
||||
wdtVect1_sav = buff[wdtVect1];
|
||||
saveVect0_sav = buff[saveVect0];
|
||||
saveVect1_sav = buff[saveVect1];
|
||||
|
||||
// Move RESET jmp target to WDT vector
|
||||
buff[wdtVect0] = rstVect0_sav;
|
||||
buff[wdtVect1] = rstVect1_sav;
|
||||
// Move RESET jmp target to 'save' vector
|
||||
buff[saveVect0] = rstVect0_sav;
|
||||
buff[saveVect1] = rstVect1_sav;
|
||||
|
||||
// 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[rstVect1] = ((uint16_t)main) >> 8;
|
||||
}
|
||||
@ -589,22 +607,23 @@ int main(void) {
|
||||
// This is the reset vector page. We need to live-patch
|
||||
// the code so the bootloader runs first.
|
||||
//
|
||||
// Move RESET vector to WDT vector
|
||||
// Move RESET vector to 'save' vector
|
||||
// Save jmp targets (for "Verify")
|
||||
rstVect0_sav = buff[rstVect0];
|
||||
rstVect1_sav = buff[rstVect1];
|
||||
wdtVect0_sav = buff[wdtVect0];
|
||||
wdtVect1_sav = buff[wdtVect1];
|
||||
saveVect0_sav = buff[saveVect0];
|
||||
saveVect1_sav = buff[saveVect1];
|
||||
|
||||
// Instruction is a relative jump (rjmp), so recalculate.
|
||||
uint16_t vect=rstVect0_sav+(rstVect1_sav<<8);
|
||||
vect -= WDT_vect_num;
|
||||
// Move RESET jmp target to WDT vector
|
||||
buff[wdtVect0] = vect & 0xff;
|
||||
buff[wdtVect1] = vect >> 8;
|
||||
uint16_t vect=(rstVect0_sav & 0xff) | ((rstVect1_sav & 0x0f)<<8); //calculate 12b displacement
|
||||
vect = (vect-save_vect_num) & 0x0fff; //substract 'save' interrupt position and wrap around 4096
|
||||
// Move RESET jmp target to 'save' vector
|
||||
buff[saveVect0] = vect & 0xff;
|
||||
buff[saveVect1] = (vect >> 8) | 0xc0; //
|
||||
// Add rjump to bootloader at RESET vector
|
||||
buff[0] = (((uint16_t)main) & 0xFFF) & 0xFF; // rjmp 0x1d00 instruction
|
||||
buff[1] = ((((uint16_t)main) & 0xFFF) >> 8) | 0xC0;
|
||||
vect = ((uint16_t)main) &0x0fff; //WARNIG: this works as long as 'main' is in first section
|
||||
buff[0] = vect & 0xFF; // rjmp 0x1c00 instruction
|
||||
buff[1] = (vect >> 8) | 0xC0;
|
||||
}
|
||||
#endif // FLASHEND
|
||||
#endif // VBP
|
||||
@ -812,7 +831,7 @@ void appStart(uint8_t rstFlags) {
|
||||
// Note that appstart_vec is defined so that this works with either
|
||||
// real or virtual boot partitions.
|
||||
__asm__ __volatile__ (
|
||||
// Jump to WDT or RST vector
|
||||
// Jump to 'save' or RST vector
|
||||
"ldi r30,%[rstvec]\n"
|
||||
"clr r31\n"
|
||||
"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
|
||||
if (address == rstVect0) ch = rstVect0_sav;
|
||||
else if (address == rstVect1) ch = rstVect1_sav;
|
||||
else if (address == wdtVect0) ch = wdtVect0_sav;
|
||||
else if (address == wdtVect1) ch = wdtVect1_sav;
|
||||
else if (address == saveVect0) ch = saveVect0_sav;
|
||||
else if (address == saveVect1) ch = saveVect1_sav;
|
||||
else ch = pgm_read_byte_near(address);
|
||||
address++;
|
||||
#elif defined(RAMPZ)
|
||||
|
Reference in New Issue
Block a user