avr-libc-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [avr-libc-dev] Problem writing to flash - atmega644


From: Patrick Mahoney
Subject: RE: [avr-libc-dev] Problem writing to flash - atmega644
Date: Wed, 22 Aug 2007 17:22:28 -0400

Brian,

You were right. I had avr's word-addressing confused with gcc's
byte-addressing. I upgraded the AVR Studio to the latest version (same
as yours: 4.13 build 528) and 100% correctly simulated & emulated my
flash programming routine. 

The problem is that the actual execution doesn't yield the same results.
In fact, the problem isnt flash-programming-related at all...

I am having unexpected resets when executing code located outside of the
.text section. When it's a plain 'while(1);', which gets translated into
a 'rjmp .-2', its fine. But as soon as theres some kind of logic (write
access to global variables, call to libc routine, etc...), the processor
resets very shortly after the execution of the 'call' instruction. And
this happens whether I put the .bootloader section at byte-address
0xfc00 or 0xa000 or anywhere else i tried. So it happens whether or not
the code is located in the BLS or the Application memory region. Again,
theres no call to SPM or LPM.

It might not be an actual reset because all bits in the MCUSR register
are cleared. So it could be a jmp to address 0, but it doesn't make more
sense... Again, the sims run perfectly...

Anyone experienced similar behaviour on the mega644?

Thanks.


Pat Mahoney


-----Original Message-----
From: Brian Sidebotham [mailto:address@hidden 
Sent: August 21, 2007 11:40 AM
To: Patrick Mahoney
Cc: address@hidden
Subject: Re: [avr-libc-dev] Problem writing to flash - atmega644

Patrick Mahoney wrote:
> Good morning Brian,
> 
> Thanks for getting back to me.
> 
> It is true that my code snippet was iterating over a page number
whereas
> the required parameter is the full address.
> 
> But still... Erasing the page containing address 0 should blank the
> first 256 bytes in memory, which contain the reset vector and the
> interrupt vector table. The processor should NOT be functional after
> such an operation.
> 
> Also, I tried using your code snippet as is and didn't work either. I
> even tried:
>       for (i=0; i<FLASH_PROGRAM_SIZE; i++)
>           boot_program_page(i);
> ... without anymore success.

Why try something you know to be wrong? (stepping over page number
instead of 
page address)

Anyway, I successfully simulated the code pasted below in AVR Studio
4.13 build 
528 on a mega644 and the the first page is erased and programmed with
zero's 
correctly.

However, AVR Studio simulates this no matter where the bootloader
section starts 
(i.e. irrelevant of where boot() or boot_program_page() is placed)

Which leads me on to your avr-nm output:
        (...)
        00007e00 T boot_program_page
        00007e76 T CopyMemory

These addresses are in bytes, but the avr uses word addresses. That is
to say 
that the byte address 0x7e00 is in fact address 0x3F00 in the avr. See
my nm 
output, vs the offset shown in the avr studio disassembler:

00007e00 T boot_program_page
00007f0c T boot

and

@00003F00: boot_program_page

So, looks like your linker options are wrong. To get the code in the
correct 
place, you will need -Wl,--section-start,.bootloader=0xFC00

Which gives nm of:

0000fc00 T boot_program_page
0000fd0c T boot

and in avr studio:

@00007E00: boot_program_page

So, nothing to do with avr-libc! ;)

Best Regards,

Brian Sidebotham.

// test.c
#include <inttypes.h>
#include <avr/io.h>
#include <avr/boot.h>
#include <avr/interrupt.h>

void boot_program_page (uint32_t page, uint8_t *buf) BOOTLOADER_SECTION;
void boot_program_page (uint32_t page, uint8_t *buf)
{
     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<SPM_PAGESIZE; 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;
}

void boot(void) BOOTLOADER_SECTION;
void boot(void)
{
     unsigned int i;
     unsigned char boot_page[256];

     for (i=0; i<256; i++)
         boot_page[i] = 0;

     for (i=0; i<32768; i+=SPM_PAGESIZE)
         boot_program_page(i, boot_page);

     while(1) ;
}


void main(void)
{
     boot();

     while(1) ;
}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]