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

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

Re: [avr-libc-dev] Suggested improvement to <avr/pgmspace.h>


From: George Spelvin
Subject: Re: [avr-libc-dev] Suggested improvement to <avr/pgmspace.h>
Date: 2 Jan 2017 13:26:45 -0500

> 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);
>   }
> }
> 
> For optimal AVR implementation, this would require some inline assembly:

You could also try using a compiler feature and skipping the pgm_read
function entirely.

static void msg(const char __flash *msg)
{
  char c;
  while ((c = *msg++)) {
    UDR0 = c;
    loop_until_bit_is_set(UCSR0A, UDRE0);
  }
}

Of course, GCC is generating terrible code for me on this (not only
is it not using Z+, it's copying the pointer to a different register to
increment it and using a subi/sbci sequence to do it), but it's definitely
more legible source code.

I also wonder if we could do something like:

static inline char pgm_read_byte(char const * PROGMEM p)
{
        char c;
        asm("lpm %0,%1" : "=r" (c) : "m<>" (*p));
        return c;
}

which would tell GCC how to make "pgm_read_byte(msg++)" use
a postincrement addressing mode, without having to add another
function.


(We should also update inttypes.h and pgmspace.h to use
__int24/__uint24 for far addresses.)



reply via email to

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