I develope a new bus system (uartbus) which includes a host application that can handle new program uploads throught the bus.
How it's work in short: The host application flashed to the AVR. This located between 0-2000 addresses and the flashing function at the end in the NRWW section. Application is written between 2000 and before NRWW section when it's received from the bus.
It's worked for a while with small AVR codes, but now as i try to integrate with the arduino system i've faced a weird problem: sometimes a page between 100 and 180 (one 128 byte page) been erased and some code filled almost at the beginning.
I thought the flashing function has been called with some wild parameter that results this fault, so i added some guard condition to check before write the flash:
__attribute__((section(".bootloader"))) void bootloader_main()
{
asm ("jmp 0x0");
}
//modified version of:
//https://www.nongnu.org/avr-libc/user-manual/group__avr__boot.html#gaeb0dba1dd9d338516a94c0bd8a8db78a
__attribute__((section(".bootloader"))) void ubh_impl_write_program_page(const uint32_t page,const uint8_t *buf,const uint8_t size)
{
if(page < 0x2000 || (page > 0x7900+SPM_PAGESIZE) || size > SPM_PAGESIZE)
{
return;
}
uint16_t i;
uint8_t sreg;
// Disable interrupts.
sreg = SREG;
cli();
eeprom_busy_wait ();
boot_page_erase (page);
boot_spm_busy_wait (); // Wait until the memory is erased.
for (i=0; i<size; i+=2)
{
// Set up little-endian word.
uint16_t w = *buf++;
w += (*buf++) << 8;
boot_page_fill (page + i, w);
}
boot_page_write (page); // Store buffer in flash page.
boot_spm_busy_wait(); // Wait until the memory is written.
// Reenable RWW-section again. We need this if we want to jump back
// to the application after bootloading.
boot_rww_enable ();
// Re-enable interrupts (if they were ever enabled).
SREG = sreg;
}
But the problem remained. Because the host code has been partially overwritten, the AVR can't receive new code from the bus. After dumped the AVR's flash and disassembled to invesigate what's happened.
avrdude -p atmega328p -b 19200 -P /dev/ttyUSB0 -c avrisp -U flash:r:flash.hex:i
avr-objdump -j .sec1 -d -m avr5 flash.hex > flash.asm
... good code ...
fc: fb 01 movw r30, r22
fe: 31 83 std Z+1, r19 ; 0x01
100: ff ff .word 0xffff ; ????
102: ff ff .word 0xffff ; ????
104: ff ff .word 0xffff ; ????
106: ff ff .word 0xffff ; ????
108: ff ff .word 0xffff ; ????
10a: ff ff .word 0xffff ; ????
10c: ff ff .word 0xffff ; ????
//looks like this code is from the application space between 2b8e and 2b96
10e: ff 1f adc r31, r31
110: 05 90 lpm r0, Z+
112: f4 91 lpm r31, Z
114: e0 2d mov r30, r0
116: 09 94 ijmp
118: ff ff .word 0xffff ; ????
11a: ff ff .word 0xffff ; ????
11c: ff ff .word 0xffff ; ????
11e: ff ff .word 0xffff ; ????
....
17c: ff ff .word 0xffff ; ????
17e: ff ff .word 0xffff ; ????
180: 9f 93 push r25
182: 8f 93 push r24
184: 0e 94 9e 0a call 0x153c ; 0x153c
...good code ...
How is this possible to happen even after adding some guard condition before writing the flash?
(Another guard is also installed: when AVR accidentally starts in bootloader mode it's jumps immedialty to 0x00). I also checked, there's no SPM instruction in the code i uploaded and as far as i know they can be run outside of the NRWW section.
if
can't apply. so what is the problem?