Skip to content

Commit

Permalink
bootloader: Go to sleep during SPM write operation
Browse files Browse the repository at this point in the history
Atmel confirms there is a hardware bug that can, under some unknown set
of circumstances, overwrite the program counter when writing to the
second half of the flash on the ATMEGA64/128/256 RFR2 and 4RFR2 family.

As a workaround, it helps to sleep during the SPM operation (waiting for
the SPM complete interrupt to wake us up), since the bug requires
reads from flash to trigger.

It should only affect flash writes, but this applies the sleep trick to
page erases as well, just for good measure.

This fix was originally created by Geoff and improved by Matthijs.
  • Loading branch information
gvdw authored and matthijskooijman committed Apr 17, 2015
1 parent b8cc5c0 commit d1a92f6
Showing 1 changed file with 26 additions and 2 deletions.
28 changes: 26 additions & 2 deletions firmware/bootloader/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -525,6 +525,30 @@ uint32_t count = 0;
return UART_DATA_REG;
}

ISR(SPM_READY_vect) {} // empty vector, just wake us up

static void spm_wait(void)
{
// Point interrupt vectors to bootloader section
MCUCR = (1 << IVCE);
MCUCR = (1 << IVSEL);

// Enable SPM interupt
SPMCSR |= (1 << SPMIE);
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_enable();
sei();
sleep_cpu();
cli();
sleep_disable();
// Disable SPM interupt again
SPMCSR &= ~(1 << SPMIE);

// Point interrupt vectors back to main section
MCUCR = (1 << IVCE);
MCUCR = (0 << IVSEL);
}

//* for watch dog timer startup
void (*app_start)(void) = 0x0000;

Expand Down Expand Up @@ -1058,7 +1082,7 @@ int main(void)
{

boot_page_erase(address); // Perform page erase
boot_spm_busy_wait(); // Wait until the memory is erased.
spm_wait();

/* Write FLASH */
tempAddress = address;
Expand All @@ -1075,7 +1099,7 @@ int main(void)
} while (size); // Loop until all bytes written

boot_page_write(address);
boot_spm_busy_wait();
spm_wait();
boot_rww_enable(); // Re-enable the RWW section

msgLength = 2;
Expand Down

0 comments on commit d1a92f6

Please sign in to comment.