[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [avr-libc-dev] Suggested improvement to <avr/pgmspace.h>
From: |
Georg-Johann Lay |
Subject: |
Re: [avr-libc-dev] Suggested improvement to <avr/pgmspace.h> |
Date: |
Mon, 2 Jan 2017 17:27:19 +0100 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.6.0 |
On 02.01.2017 11:58, Marko Mäkelä wrote:
Hi all,
I am trying to revive my AVR hobby again, this time using the avr-libc,
mainly to introduce my kids to low-level programming. I am using a
couple of Arduino boards with the ATmega328P.
I started with a simple "hello world" program that outputs a
NUL-terminated string to the UART:
static void msg(const char* PROGMEM msg)
{
char c;
while ((c = pgm_read_byte_postinc (&msg))) {
UDR0 = c;
loop_until_bit_is_set(UCSR0A, UDRE0);
}
}
You can use the __flash address space instead of PROGMEM + pgm_read, cf.
https://gcc.gnu.org/onlinedocs/gcc/Named-Address-Spaces.html
In your case, the function would read:
static void msg (const __flash char *msg)
{
char c;
while ((c = *msg++))
{
UDR0 = c;
loop_until_bit_is_set (UCSR0A, UDRE0);
}
}
The __flash address space is implemented by the compiler as a GNU
extension to the C language, and hence -std=gnu99 (or higher) is
needed. There is no guarantee for an optimal code being generated
for that example (as applies to any other C code).
Also notice that PROGMEM is just a variable attribute; its only
effect is to locate data to .progmem.data for variable definitions
which are attributed progmem. Specifying it with prototypes or
declarations is void.
The advantage is that less typing is needed and the feature is more
trqansparent w.r.t. code that only addresses generic address space,
e.g. to deflate to .rodata (which is located in RAM for avr) you
only need to
#define __flash /* empty */
Johann
For optimal AVR implementation, this would require some inline assembly:
static char pgm_read_byte_postinc (const char** PROGMEM s)
{
#ifdef __AVR_HAVE_LPMX__
char c;
asm volatile ("lpm %0, %a1+" "\n\t" : "=r" (c), "+z" (*s));
return c;
#else
return pgm_read_byte((*s)++);
#endif
}
I would like to have pre/post-increment/decrement variants of all
pgm_read_* functions in <avr/pgmspace.h> that are natively supported on
some AVR platform. I wonder what would be the practical way to achieve
this. Contribute a patch myself? I hereby contribute the above idea to
the public domain.
Best regards,
Marko
_______________________________________________
AVR-libc-dev mailing list
address@hidden
https://lists.nongnu.org/mailman/listinfo/avr-libc-dev