Cannot understand pgm_read_dword_far(address_long) issue

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ref: AXMEGA128A3U

 

Hi -

I've asked this question sometime back and never really understood why the following code will not properly read back the last dword stored in Application memory:

I patch this location with an external tool and know the crc is properly located at the location, but  the pgm_read_dword_far function doesn't work the way I would have thought.

Would someone please explain why this does not work?

 

Thanks

Jim

/** \ingroup avr_pgmspace
    \def pgm_read_dword_far(address_long)
    Read a double word from the program space with a 32-bit (far) address.

    \note The address is a byte address.
    The address is in the program space. */

#define pgm_read_dword_far(address_long) __ELPM_dword((uint32_t)(address_long))


//****************************************************************
uint32_t GetStoredCRC(void)
//****************************************************************
{
    return pgm_read_dword_far(APP_SECTION_END-sizeof(uint32_t));
}

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What is APP_SECTION_END defined as?

 

Also why are you defining "pgm_read_dword_far"? The pgmspace.h header already has:

/** \ingroup avr_pgmspace
    \def pgm_read_dword_far(address_long)
    Read a double word from the program space with a 32-bit (far) address. 

    \note The address is a byte address.
    The address is in the program space. */

#define pgm_read_dword_far(address_long) __ELPM_dword((uint32_t)(address_long))

in which the __ELPM_dword is referring to:

#if defined (__AVR_HAVE_RAMPD__)

#define __ELPM(addr)        __ELPM_xmega__(addr)
#define __ELPM_word(addr)   __ELPM_word_xmega__(addr)
#define __ELPM_dword(addr)  __ELPM_dword_xmega__(addr)
#define __ELPM_float(addr)  __ELPM_float_xmega__(addr)

which in turn is referring to:

#define __ELPM_dword_xmega__(addr)        \
(__extension__({                          \
    uint32_t __addr32 = (uint32_t)(addr); \
    uint32_t __result;                    \
    __asm__ __volatile__                  \
    (                                     \
        "in __tmp_reg__, %2" "\n\t"       \
        "out %2, %C1"   "\n\t"            \
        "movw r30, %1"  "\n\t"            \
        "elpm %A0, Z+"  "\n\t"            \
        "elpm %B0, Z+"  "\n\t"            \
        "elpm %C0, Z+"  "\n\t"            \
        "elpm %D0, Z"   "\n\t"            \
        "out %2, __tmp_reg__"             \
        : "=r" (__result)                 \
        : "r" (__addr32),                 \
          "I" (_SFR_IO_ADDR(RAMPZ))       \
        : "r30", "r31"                    \
    );                                    \
    __result;                             \
}))

so you need ALL of that for this to work. You get that when your own code simply does:

#include <avr/pgmspace.h>

//****************************************************************
uint32_t GetStoredCRC(void)
//****************************************************************
{
    return pgm_read_dword_far(APP_SECTION_END-sizeof(uint32_t));
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

No... I didn't redefine "pgm_read_dword_far".  I just copied the definition from the GCC manual for everyone's review.  I should have clarified that point.

 

I found my error.

return pgm_read_dword_far(APP_SECTION_END-sizeof(uint32_t));

should be:

return pgm_read_dword_far(APP_SECTION_END - 3);

I misinterpreted APP_SECTION_END.  These are predefined in the header iox128a3u.h

#define APP_SECTION_START     (0x0000) 
#define APP_SECTION_SIZE      (131072)
#define APP_SECTION_PAGE_SIZE (512)
#define APP_SECTION_END       (APP_SECTION_START + APP_SECTION_SIZE - 1)

The problem is now resolved.  Thanks for commenting.

Jim