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

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

[avr-libc-dev] Error when using lagre memory addresses


From: Per Arnold Blåsmo
Subject: [avr-libc-dev] Error when using lagre memory addresses
Date: Tue, 15 Feb 2005 10:25:32 +0100
User-agent: Mozilla Thunderbird 1.0 (X11/20041206)

Hi,
During my work with adapting avg-gcc to a new processor (AT90SC3232CS) I
have discovered a problem regarding addressing that I think is not
working in the generated code.

I would like some comments on this from some of you more expert than me
on this :-)

Consider the following code:
----
#include <avr/io.h>
#include <avr/pgmspace.h>

#define FROMADDR 0x100000L
#define TOADDR1 (uint8_t *)0x200
#define TOADDR2    (uint8_t *)0x100

int main(void)
{
   uint8_t *p_to_addr1= TOADDR1;
   uint8_t *p_to_addr2= TOADDR2;
   uint32_t from_addr = FROMADDR;
   uint8_t size = 255;

   while(size--){
       *p_to_addr1++ = pgm_read_byte_far(from_addr++);
   }
   size=255;
   *p_to_addr1 = TOADDR1;
   while(size--){
       *p_to_addr2++ = *p_to_addr1++;
   }

}
----

Compile for an ATmega128 it gives the following assembly:
(and yes I know it would not work in real life, but I try to show a
point her :-)

----
int main(void)
{
 62:    cf ef           ldi    r28, 0xFF    ; 255
 64:    dc e0           ldi    r29, 0x0C    ; 12
 66:    de bf           out    0x3e, r29    ; 62
 68:    cd bf           out    0x3d, r28    ; 61
   uint8_t *p_to_addr1= TOADDR1;
 6a:    00 e0           ldi    r16, 0x00    ; 0
 6c:    12 e0           ldi    r17, 0x02    ; 2
   uint8_t *p_to_addr2= TOADDR2;
 6e:    ee 24           eor    r14, r14
 70:    ff 24           eor    r15, r15
 72:    68 94           set
 74:    f0 f8           bld    r15, 0
   uint32_t from_addr = FROMADDR;
 76:    40 e0           ldi    r20, 0x00    ; 0
 78:    50 e0           ldi    r21, 0x00    ; 0
 7a:    60 e1           ldi    r22, 0x10    ; 16
 7c:    70 e0           ldi    r23, 0x00    ; 0
   uint8_t size = 255;

   while(size--){
       *p_to_addr1++ = pgm_read_byte_far(from_addr++);
 7e:    ce ef           ldi    r28, 0xFE    ; 254
 80:    db 01           movw    r26, r22
 82:    ca 01           movw    r24, r20
 84:    4f 5f           subi    r20, 0xFF    ; 255
 86:    5f 4f           sbci    r21, 0xFF    ; 255
 88:    6f 4f           sbci    r22, 0xFF    ; 255
 8a:    7f 4f           sbci    r23, 0xFF    ; 255
 8c:    98 01           movw    r18, r16
 8e:    0f 5f           subi    r16, 0xFF    ; 255
 90:    1f 4f           sbci    r17, 0xFF    ; 255
 92:    ab bf           out    0x3b, r26    ; 59   <= 0x3b = RAMPZ set
to 0x10
 94:    fc 01           movw    r30, r24
 96:    87 91           elpm    r24, Z+
 98:    f9 01           movw    r30, r18
 9a:    80 83           st    Z, r24               <= this one should
store to 0x0200 but stores to 0x100200 instead
 9c:    c1 50           subi    r28, 0x01    ; 1
 9e:    80 f7           brcc    .-32         ; 0x80
   }
   size=255;
   *p_to_addr1 = TOADDR1;
 a0:    f8 01           movw    r30, r16
 a2:    10 82           st    Z, r1
   while(size--){
       *p_to_addr2++ = *p_to_addr1++;
 a4:    ce ef           ldi    r28, 0xFE    ; 254
 a6:    f8 01           movw    r30, r16
 a8:    81 91           ld    r24, Z+            <= this one should
load from 0x0200 but loads from 0x100200
 aa:    8f 01           movw    r16, r30
 ac:    f7 01           movw    r30, r14
 ae:    81 93           st    Z+, r24            <= this one should
store in 0x0100 but stores in 0x100100
 b0:    7f 01           movw    r14, r30
 b2:    c1 50           subi    r28, 0x01    ; 1
 b4:    c0 f7           brcc    .-16         ; 0xa6
   }

}

-----------

This code will not work as intended.

As you can see I use a 'from address' that is 24 bit put into a long (32
bit).
To read from this address I use 'pgm_read_byte_far'. 'pgm_read_byte_far'
correctly uses
RAMPZ (0x3b) to address the memory location ((RAMPZ:Z) = 0x100000).

The problem is that RAMPZ does not get reset after used. That clutters
the use of Z later in the code.

My solution to this so far has been to include a line likethis:

   __asm__ volatile ("out     %0, 0x0" : : "I" (_SFR_IO_ADDR(RAMPZ)));
   // Hack to reset RAMPZ after it is used

Anyone like to comment on this or/and suggest another work-around?

Per A.




reply via email to

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