Browse Source

Merge pull request #135 from majekw/virtualboot

Fix/small rewrite of Virtual boot partition
Bill Westfield 9 years ago
parent
commit
52a7902d74
2 changed files with 62 additions and 26 deletions
  1. 9 0
      optiboot/bootloaders/optiboot/Makefile
  2. 53 26
      optiboot/bootloaders/optiboot/optiboot.c

+ 9 - 0
optiboot/bootloaders/optiboot/Makefile

@@ -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' '-Dsave_vect_num=EE_RDY_vect_num'
+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'

+ 53 - 26
optiboot/bootloaders/optiboot/optiboot.c

@@ -388,25 +388,49 @@ 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 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, so it's default
+//   if not, use old way WDT_vect_num,
+//   or simply set custom save_vect_num in Makefile using vector name
+//   or even raw number.
+#if !defined (save_vect_num)
+#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)
+#elif defined (WDT_vect_num)
+#define save_vect_num (WDT_vect_num)
+#else
+#error Cant find SPM or WDT interrupt vector for this CPU
+#endif
+#endif //save_vect_num
+// 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 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
 #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 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
 #endif
 #else
 #else
 #define appstart_vec (0)
 #define appstart_vec (0)
@@ -561,6 +585,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 +594,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];
-	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
         // 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 +615,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];
-	wdtVect1_sav = buff[wdtVect1];
+	saveVect0_sav = buff[saveVect0];
+	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);
-        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
         // 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 // FLASHEND
 #endif // VBP
 #endif // VBP
@@ -812,7 +839,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 +932,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 == 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);
 	    else ch = pgm_read_byte_near(address);
 	    address++;
 	    address++;
 #elif defined(RAMPZ)
 #elif defined(RAMPZ)