[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.
- [avr-libc-dev] Error when using lagre memory addresses,
Per Arnold Blåsmo <=