avr-gcc-list
[Top][All Lists]
Advanced

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

[avr-gcc-list] Accessing function and strings in flash in the ATMega 644


From: Robert von Knobloch
Subject: [avr-gcc-list] Accessing function and strings in flash in the ATMega 644
Date: Mon, 02 Feb 2009 16:48:45 +0100
User-agent: Thunderbird 1.5.0.14 (X11/20060911)

Firstly, sorry that this post is a bit long, but I need to explain what
is happening.

I am trying to access the flash memory in an ATMega 644 chip that I am
using as the basis for a piece of test equipment.
This tester will be used to program and test small devices with a
ATTiny13 and so contains an array of 10 flash images for the target
devices (Each one 0x900 bytes) and an array of 10 test routines
(functions) also 0x900 bytes each. These elements are located in the
ATMega644's flash by means of SECTION directives. The purpose here is
that flash images and/or test routines can be written and tested here
and sent to the production location as an intel-hex file which the
tester can download using minicom or teraterm via an inbuilt ihex
downloader. This won't happen very often so flash life is not an issue.
Reading of the flash images is achieved by defining:

FLASHIMAGE_SECTION uint8_t flashimage[] = {};    // Base of flash images

- and indexing flashimage[i]. GCC will not let me dimension this, but,
fortunately does not check bounds, so I abuse the system and let i point
to whatever.

All works fine, EXCEPT that my attempts to access the test routines
generate unexpected code:

//******************************************************************************
 if (pgm_read_byte((PGM_P)(TESTIMAGE + (IMAGE_SIZE * projnum) +
SIGNATURE) != 0))
 49c:    80 91 38 03     lds    r24, 0x0338
 4a0:    90 e0           ldi    r25, 0x00    ; 0
 4a2:    8c 9f           mul    r24, r28
 4a4:    90 01           movw    r18, r0
 4a6:    8d 9f           mul    r24, r29
 4a8:    30 0d           add    r19, r0
 4aa:    9c 9f           mul    r25, r28
 4ac:    30 0d           add    r19, r0
 4ae:    11 24           eor    r1, r1
 4b0:    e0 e0           ldi    r30, 0x00    ; 0
 4b2:    f0 e0           ldi    r31, 0x00    ; 0
 4b4:    81 ed           ldi    r24, 0xD1    ; 209
 4b6:    2c 37           cpi    r18, 0x7C    ; 124
 4b8:    38 07           cpc    r19, r24
 4ba:    11 f0           breq    .+4          ; 0x4c0 <main+0x14a>
 4bc:    e1 e0           ldi    r30, 0x01    ; 1
 4be:    f0 e0           ldi    r31, 0x00    ; 0
 4c0:    84 91           lpm    r24, Z
 4c2:    88 23           and    r24, r24
 4c4:    29 f0           breq    .+10         ; 0x4d0 <main+0x15a>
//******************************************************************************

Which, as far as I can see loads the Z-Pointer with either 0x0000 or
0x0001 before the lpm.

I rather expected Z to point to (assuming projnum = 0):
    TESTIMAGE + NAME = (0x2300 + 0x88c = 0x2b8c) // The string
describing the test routine.

Can anyone tell me a: why this does not work and/or what I am assuming
that is wrong?


Best regards,

     Robert von Knobloch



Here are snippets of my code:

//******************************************************************************
// Image definitions in Flash Memory

#define NUM_IMAGES    10
#define IMAGE_SIZE    0x900

// Offsets in the image
// Warning 'FUSES' defined in ../avr/fuses.h, use another name

#define FLASHIMAGE    0
#define FLASHIMAGE_SIZE    0x800                // Size of flash in host
#define EEPROMIMAGE    FLASHIMAGE + FLASHIMAGE_SIZE
#define    EEPROM_SIZE    0x80                // Size of EE in host
#define    TARGETF_LENGTH    EEPROMIMAGE + EEPROM_SIZE   // Flash used
in target
#define TARGFLEN_SIZE    2                // 16-Bit quantity
#define TARGETEE_LENGTH    TARGETF_LENGTH + TARGFLEN_SIZE
#define TARGEE_SIZE    2                // 16-Bit quantity
#define SIGNATURE    TARGETEE_LENGTH + TARGEE_SIZE
#define SIG_SIZE    3
#define    UUTFUSES    SIGNATURE + SIG_SIZE
#define UUTFUSE_SIZE    2
#define NUM_PAGES    UUTFUSES + UUTFUSE_SIZE
#define NUMPAGE_SIZE    1                // 8-Bit quantity
#define    PAGE_WORDS    NUM_PAGES + NUMPAGE_SIZE
#define PAGEWORDS_SIZE    1                // 8-Bit quantity
#define TESTER_SLOT    PAGE_WORDS + PAGEWORDS_SIZE
#define TESTSLOT_SIZE    1                // 8-Bit quantity
#define TEST_ROUTINE    TESTER_SLOT + TESTSLOT_SIZE
#define TESTROUT_SIZE    1                // 8-Bit quantity
#define NAME        TEST_ROUTINE + TESTROUT_SIZE
#define NAME_SIZE    LCDLINELENGTH


#define TESTIMAGE 0x2600            // Base address of test images

#define TEST0_SECTION __attribute__((section (".test0")))
#define TEST1_SECTION __attribute__((section (".test1")))
#define TESTPARMS0_SECTION __attribute__((section (".testparms0")))
#define TESTPARMS1_SECTION __attribute__((section (".testparms1")))

// Global variables
uint16_t (*test[])(void) = {test0,test1};

/*
******************************************************************************
*   Tester routine 0
******************************************************************************
*/

TEST0_SECTION uint16_t test0(void)
{
    int x;
    DDRA = 0xff;
    for (x = 0; x < 1000; ++x)
    {
    PORTA = x;
    milliSecDelay(10);
    }
    return NO_ERROR;
}

TESTPARMS0_SECTION uint16_t flash0  = 1024;            // Bytes
TESTPARMS0_SECTION uint16_t eep0    = 64;            // Bytes
TESTPARMS0_SECTION uint8_t sig0[]   = {0x00, 0x00, 0x00};   // Test file
TESTPARMS0_SECTION uint8_t fuse0[]  = {0xfb, 0x33};        // Big-Endian
TESTPARMS0_SECTION uint8_t np0        = 32;            // Flash
TESTPARMS0_SECTION uint8_t ps0        = 16;            // In 16-bit words
TESTPARMS0_SECTION uint8_t ts0        = 0;            // Slot in NKP
tester[0-9]
TESTPARMS0_SECTION uint8_t tr0        = 0;            // Routine in
tester[0-9]
TESTPARMS0_SECTION char    pn0[]        = "ES07 Test 0     ";   // Pad
to exactly 16 chars

/*
 ******************************************************************************
 *    Send program-merory resident string LCD.
 ******************************************************************************
 */

BOOTLOADER_SECTION void prog_lcd_string1(PGM_P string)
{
    char temp;

    while ((temp = pgm_read_byte(string++)) != 0)
    {
    lcd_putchar(temp);
    }
}

//
******************************************************************************

in main:

// projnum is a uint8_t with values from 0-9

if (pgm_read_byte((PGM_P)(TESTIMAGE + (IMAGE_SIZE * projnum) +
SIGNATURE) != 0)) //Read 1 byte from Flash
{
    lcd_string2("No test loaded!");
    goto  error;
}
prog_lcd_string1((PGM_P)(TESTIMAGE + (projnum * IMAGE_SIZE) + NAME)); //
Display string from Flash

if ((errorcode = test[projnum]()) != NO_ERROR)        // Run test
routine from flash
{
    lcd_errorout2(errorcode);
    goto  error;
}



error:    // Do something else

//
******************************************************************************
In the Makefile:
LDFLAGS       = -Wl,-Map,$(PRG).map \
        -Wl,--section-start=.test0=0x2600 \
        -Wl,--section-start=.testparms0=0x2e80 \
        -Wl,--section-start=.test1=0x2f00 \
        -Wl,--section-start=.testparms1=0x3780 \
        -Wl,--section-start=.flashimage=0x8000 \
        -Wl,--section-start=.bootloader=0xe000





reply via email to

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