> 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.) _______________________________________________ AVR-libc-dev mailing list AVR-libc-dev@nongnu.org https://lists.nongnu.org/mailman/listinfo/avr-libc-dev