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

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

Re: [avr-libc-dev] Why include <ina90.h> from <avr/pgmspace.h>?


From: Marek Michalkiewicz
Subject: Re: [avr-libc-dev] Why include <ina90.h> from <avr/pgmspace.h>?
Date: Tue, 8 Oct 2002 21:29:14 +0200 (CEST)

> My question was whether when accessing an __attribute__((progmem))
> string, would gcc automatically set the appropriate value in RAMPZ, or
> is it in the domain of the programmer to do so.  If gcc doesn't handle
> this automatically, i don't see why one should always use ELPM on >
> 64KB devices.

GCC doesn't do anything with RAMPZ and doesn't use ELPM.  All data
is assumed to be in the lower 64K of program memory, and the upper
64K can only be used for executable code.  Linker scripts put any
sections with ".progmem*" names below .text, and you can have
almost 64K (minus interrupt vectors) of this data.

> Btw., unfortunately, there's no different architecture name for > 64K
> devices (only a distinction for <= 8KB and > 8KB since the latter
> require JMP/CALL instead of RJMP/RCALL to cover the entire address
> space), thus the existence of RAMPZ & ELPM cannot be automatically
> determined inside library code anyway (since there's only one library
> version per architecture).  This, for example, will restrict the
> impending printf_p() implementation from accessing format strings
> beyond 64 KB.  Perhaps we should invent avr6 for avr5 devices with
> more than 64 KB of RAM?

I think it is more efficient to keep things as is, keep all format
strings in the lower 64K, and not have to deal with 17-bit pointers.
One exception: there is a separate crt*.o for each device, so the
ones for >64K devices use RAMPZ and ELPM in the loop that copies
initialized data from Flash to RAM.  This data is placed above the
executable code, so it doesn't use any of the precious lower 64K.
But nothing else except C startup accesses that data.

BTW, a note for printf/printf_P implementors: if we want to stay
compatible with ICC-AVR, one person using that compiler told me
they use %S in the format string to access a string constant in
the program memory.  Unfortunately, this conflicts with glibc
use of %S - "This is an alias for `%ls' which is supported for
compatibility with the Unix standard." but I don't think we are
going to support multibyte characters anytime soon :).

There may be special applications with a lot (>64K) of constants
in Flash, and small code.  It makes sense to organize the data in
smaller pieces (each <64K), addressed with 16-bit offsets from the
(17-bit) base address of the object.  There was some discussion
about this a few months ago, here is an example (not tested, and
only for the enhanced core - mega128 replaces mega103 anyway):

static inline unsigned char
get_audio1_byte(unsigned int addr)
{
        unsigned char byte;
        unsigned int dummy;
        asm (
                "clr %1" "\n\t"
                "subi r30,lo8(-(audio1))" "\n\t"
                "sbci r31,hi8(-(audio1))" "\n\t"
                "sbci %1,hh8(-(audio1))" "\n\t"
                "out %2,%1" "\n\t"
                "elpm %1,Z"
                : "=&z" (dummy), "=&d" (byte)
                : "I" (_SFR_IO_ADDR(RAMPZ)), "0" (addr)
        );
        return byte;
}

Here audio1[] is an array of constant bytes anywhere in program
memory - could be put in the .text section (instead of .progmem).

This could be made a macro where the array name is passed as an
argument (not hardcoded as "audio1" inside the "asm"), by using
some C preprocessor magic.  Similar macros could be written for
accessing larger objects, where RAMPZ has to be loaded only once
(ELPM Rd,Z+ nicely increments RAMPZ if Z wraps around to 0).

Hope this helps,
Marek





reply via email to

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