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: 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





reply via email to

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