[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-libc-dev] Error when using large memory addresses
From: |
Paul Schlie |
Subject: |
Re: [avr-libc-dev] Error when using large memory addresses |
Date: |
Tue, 15 Feb 2005 13:27:57 -0500 |
User-agent: |
Microsoft-Entourage/11.1.0.040913 |
However if pgm_read_byte_far(...) were called from within an interrupt
routine, and there were a danger of another pgm_read_byte_far(...) call
being interrupted (although wouldn't be a great way to structure things),
then the interrupt routine would need to save the previous RAMPZ value
somewhere, and then restore it prior to returning.
> From: Paul Schlie <address@hidden>
>
> Unless I misunderstand (and may), there seems to be nothing to work around; as
> RAMPZ does not affect RAM load/stores on any devices (I'm aware of), and is
> correctly set as required when program memory is accessed; so why would you
> want to add code which does nothing useful?
>
>
>> From: gouy yann <address@hidden>
>> Date: Tue, 15 Feb 2005 15:44:34 +0100 (CET)
>> To: Per Arnold Blåsmo <address@hidden>, <address@hidden>
>> Subject: Re: [avr-libc-dev] Error when using lagre memory addresses
>>
>> hello,
>>
>> I suspect you will ask to write a bug report for the problem not to be
>> forgiven!
>>
>> regards.
>>
>> Yann
>>
>> --- Per Arnold Blåsmo <address@hidden> a écrit :
>>> 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 mailing list
>>> address@hidden
>>> http://lists.nongnu.org/mailman/listinfo/avr-libc-dev
>>>
>>
>>
>>
>>
>>
>>
>> Découvrez le nouveau Yahoo! Mail : 250 Mo d'espace de stockage pour vos mails
>> !
>> Créez votre Yahoo! Mail sur http://fr.mail.yahoo.com/
>>
>>
>> _______________________________________________
>> AVR-libc-dev mailing list
>> address@hidden
>> http://lists.nongnu.org/mailman/listinfo/avr-libc-dev