1
0
mirror of https://github.com/Optiboot/optiboot.git synced 2025-08-19 09:02:05 +03:00

restructure the Virtual Boot code so that it is easier to read.

These are preprocesing and commenting changes, and do not cause any changes in the binaries (tested for all of the bootloaders generated by the makeall.* scripts.)
This commit is contained in:
WestfW
2019-08-27 19:17:59 -07:00
parent b8b760546b
commit ba257540f8

View File

@@ -449,10 +449,14 @@ static addr16_t buff = {(uint8_t *)(RAMSTART)};
/* Virtual boot partition support */ /* Virtual boot partition support */
#ifdef VIRTUAL_BOOT_PARTITION #ifdef VIRTUAL_BOOT_PARTITION
// RAM locations to save vector info (temporarilly)
#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 saveVect0_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+6)) #define saveVect0_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+6))
#define saveVect1_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+7)) #define saveVect1_sav (*(uint8_t*)(RAMSTART+SPM_PAGESIZE*2+7))
#define RSTVEC_ADDRESS 0 // flash address where vectors start.
// Vector to save original reset jump: // Vector to save original reset jump:
// SPM Ready is least probably used, so it's default // SPM Ready is least probably used, so it's default
// if not, use old way WDT_vect_num, // if not, use old way WDT_vect_num,
@@ -473,6 +477,7 @@ static addr16_t buff = {(uint8_t *)(RAMSTART)};
#error Cant find SPM or WDT interrupt vector for this CPU #error Cant find SPM or WDT interrupt vector for this CPU
#endif #endif
#endif //save_vect_num #endif //save_vect_num
// check if it's on the same page (code assumes that) // check if it's on the same page (code assumes that)
#if FLASHEND > 8192 #if FLASHEND > 8192
@@ -484,17 +489,27 @@ static addr16_t buff = {(uint8_t *)(RAMSTART)};
#define saveVect0 (save_vect_num*4+2) #define saveVect0 (save_vect_num*4+2)
#define saveVect1 (save_vect_num*4+3) #define saveVect1 (save_vect_num*4+3)
#define appstart_vec (save_vect_num*2) #define appstart_vec (save_vect_num*2)
#else
// AVRs with up to 8k of flash have 2-byte vectors, and use rjmp.
// address of page that will have the saved vector
#define SAVVEC_ADDRESS (SPM_PAGESIZE*(save_vect_num/(SPM_PAGESIZE/4)))
#else
// 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 saveVect0 (save_vect_num*2) #define saveVect0 (save_vect_num*2)
#define saveVect1 (save_vect_num*2+1) #define saveVect1 (save_vect_num*2+1)
#define appstart_vec (save_vect_num) #define appstart_vec (save_vect_num)
// address of page that will have the saved vector
#define SAVVEC_ADDRESS (SPM_PAGESIZE*(save_vect_num/(SPM_PAGESIZE/2)))
#endif #endif
#else #else
#define appstart_vec (0) #define appstart_vec (0)
#endif // VIRTUAL_BOOT_PARTITION #endif // VIRTUAL_BOOT_PARTITION
@@ -780,6 +795,32 @@ int main(void) {
verifySpace(); verifySpace();
#ifdef VIRTUAL_BOOT_PARTITION #ifdef VIRTUAL_BOOT_PARTITION
/*
* How the Virtual Boot Partition works:
* At the beginning of a normal AVR program are a set of vectors that
* implement the interrupt mechanism. Each vector is usually a single
* instruction that dispatches to the appropriate ISR.
* The instruction is normally an rjmp (on AVRs with 8k or less of flash)
* or jmp instruction, and the 0th vector is executed on reset and jumps
* to the start of the user program:
* vectors: jmp startup
* jmp ISR1
* jmp ISR2
* : ;; etc
* jmp lastvector
* To implement the "Virtual Boot Partition", Optiboot detects when the
* flash page containing the vectors is being programmed, and replaces the
* startup vector with a jump to te beginning of Optiboot. Then it saves
* the applications's startup vector in another (must be unused by the
* application), and finally programs the page with the changed vectors.
* Thereafter, on reset, the vector will dispatch to the beginning of
* Optiboot. When Optiboot decides that it will run the user application,
* it fetches the saved start address from the unused vector, and jumps
* there.
* The logic is dependent on size of flash, and whether the reset vector is
* on the same flash page as the saved start address.
*/
#if FLASHEND > 8192 #if FLASHEND > 8192
/* /*
* AVR with 4-byte ISR Vectors and "jmp" * AVR with 4-byte ISR Vectors and "jmp"
@@ -788,7 +829,7 @@ int main(void) {
#if FLASHEND > (128*1024) #if FLASHEND > (128*1024)
#error "Can't use VIRTUAL_BOOT_PARTITION with more than 128k of Flash" #error "Can't use VIRTUAL_BOOT_PARTITION with more than 128k of Flash"
#endif #endif
if (address.word == 0) { if (address.word == RSTVECT_ADDRESS) {
// This is the reset vector page. We need to live-patch the // This is the reset vector page. We need to live-patch the
// code so the bootloader runs first. // code so the bootloader runs first.
// //
@@ -796,19 +837,20 @@ int main(void) {
rstVect0_sav = buff.bptr[rstVect0]; rstVect0_sav = buff.bptr[rstVect0];
rstVect1_sav = buff.bptr[rstVect1]; rstVect1_sav = buff.bptr[rstVect1];
// Add "jump to Optiboot" at RESET vector
// Add jump to bootloader at RESET vector
// WARNING: this works as long as 'main' is in first section // WARNING: this works as long as 'main' is in first section
buff.bptr[rstVect0] = ((uint16_t)main) & 0xFF; buff.bptr[rstVect0] = ((uint16_t)main) & 0xFF;
buff.bptr[rstVect1] = ((uint16_t)main) >> 8; buff.bptr[rstVect1] = ((uint16_t)main) >> 8;
#if (save_vect_num>SPM_PAGESIZE/4)
} else if (address.word == (SPM_PAGESIZE*(save_vect_num/(SPM_PAGESIZE/4)))) { //allow for any vector #if (SAVVEC_ADDRESS != RSTVEC_ADDRESS)
saveVect0_sav = buff.bptr[saveVect0-(SPM_PAGESIZE*(save_vect_num/(SPM_PAGESIZE/4)))]; // the save_vector is not necessarilly on the same flash page as the reset
saveVect1_sav = buff.bptr[saveVect1-(SPM_PAGESIZE*(save_vect_num/(SPM_PAGESIZE/4)))]; // vector. If it isn't, we've waiting to actually write it.
} else if (address.word == SAVVEC_ADDRESS) {
saveVect0_sav = saveVect1_sav = buff.bptr[saveVect-SAVVEC_ADDRESS];
// Move RESET jmp target to 'save' vector // Move RESET jmp target to 'save' vector
buff.bptr[saveVect0-(SPM_PAGESIZE*(save_vect_num/(SPM_PAGESIZE/4)))] = rstVect0_sav; buff.bptr[saveVect0 - SAVVEC_ADDRESS] = rstVect0_sav;
buff.bptr[saveVect1-(SPM_PAGESIZE*(save_vect_num/(SPM_PAGESIZE/4)))] = rstVect1_sav; buff.bptr[saveVect1 - SAVVEC_ADDRESS] = rstVect1_sav;
} }
#else #else
saveVect0_sav = buff.bptr[saveVect0]; saveVect0_sav = buff.bptr[saveVect0];
@@ -834,24 +876,25 @@ int main(void) {
rstVect1_sav = buff.bptr[rstVect1]; rstVect1_sav = buff.bptr[rstVect1];
addr16_t vect; addr16_t vect;
vect.word = ((uint16_t)main); vect.word = ((uint16_t)main);
buff.bptr[0] = vect.bytes[0]; // rjmp to start of bootloader
buff.bptr[1] = vect.bytes[1] | 0xC0; // make an "rjmp"
#if (save_vect_num > SPM_PAGESIZE/2)
} else if (address.word == (SPM_PAGESIZE*(save_vect_num/(SPM_PAGESIZE/2)))) { //allow for any vector
// Instruction is a relative jump (rjmp), so recalculate. // Instruction is a relative jump (rjmp), so recalculate.
// an RJMP instruction is 0b1100xxxx xxxxxxxx, so we should be able to // an RJMP instruction is 0b1100xxxx xxxxxxxx, so we should be able to
// do math on the offsets without masking it off first. // do math on the offsets without masking it off first.
// Note that rjmp is relative to the already incremented PC, so the
// offset is one less than you might expect.
buff.bptr[0] = vect.bytes[0]; // rjmp to start of bootloader
buff.bptr[1] = vect.bytes[1] | 0xC0; // make an "rjmp"
#if (SAVVEC_ADDRESS != RSTVEC_ADDRESS)
} else if (address.word == SAVVEC_ADDRESS) {
addr16_t vect; addr16_t vect;
vect.bytes[0] = rstVect0_sav; vect.bytes[0] = rstVect0_sav;
vect.bytes[1] = rstVect1_sav; vect.bytes[1] = rstVect1_sav;
saveVect0_sav = buff.bptr[saveVect0-(SPM_PAGESIZE*(save_vect_num/(SPM_PAGESIZE/2)))]; saveVect0_sav = buff.bptr[saveVect0 - SAVVEC_ADDRESS];
saveVect1_sav = buff.bptr[saveVect1-(SPM_PAGESIZE*(save_vect_num/(SPM_PAGESIZE/2)))]; saveVect1_sav = buff.bptr[saveVect1 - SAVVEC_ADDRESS];
vect.word = (vect.word-save_vect_num); //substract 'save' interrupt position vect.word = (vect.word-save_vect_num); //substract 'save' interrupt position
// Move RESET jmp target to 'save' vector // Move RESET jmp target to 'save' vector
buff.bptr[saveVect0-(SPM_PAGESIZE*(save_vect_num/(SPM_PAGESIZE/2)))] = vect.bytes[0]; buff.bptr[saveVect0 - SAVVEC_ADDRESS] = vect.bytes[0];
buff.bptr[saveVect1-(SPM_PAGESIZE*(save_vect_num/(SPM_PAGESIZE/2)))] = (vect.bytes[1] & 0x0F)| 0xC0; // make an "rjmp" buff.bptr[saveVect1 - SAVVEC_ADDRESS] = (vect.bytes[1] & 0x0F)| 0xC0; // make an "rjmp"
} }
#else #else
saveVect0_sav = buff.bptr[saveVect0]; saveVect0_sav = buff.bptr[saveVect0];
@@ -869,7 +912,6 @@ int main(void) {
#endif #endif
#endif // FLASHEND #endif // FLASHEND
#endif // VBP #endif // VBP