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

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

RE: [avr-libc-dev] New pgm_read_ptr() macro?


From: Weddington, Eric
Subject: RE: [avr-libc-dev] New pgm_read_ptr() macro?
Date: Thu, 3 Jun 2010 01:47:48 -0600

I think it's not so much a philosophical change that concerns me. I'm 
interested in how resulting code size would be affected, as suggested by 
someone else on this list (sorry, I've forgotten who it was).

Have you done some testing about resulting code size using this macro compared 
to the more specific macros?

Code size is probably the *most* important factor that I hear users focus on.

Eric Weddington 

> -----Original Message-----
> From: 
> address@hidden 
> [mailto:address@hidden
> org] On Behalf Of David Brown
> Sent: Thursday, June 03, 2010 9:03 AM
> To: address@hidden
> Subject: Re: [avr-libc-dev] New pgm_read_ptr() macro?
> 
> Hi,
> 
> Are there any opinions about whether a macro such as the one I gave 
> below should be part of avrlibc?  It's not as clear-cut as Dean's 
> pgm_read_ptr() macro, which follows the existing patterns in the 
> headers.  Macros like mine are more like template programming 
> than the 
> fixed-size macros, and thus are a slight change in philosophy.
> 
> If the idea of a generic pgm_read(&x) macro does appeal, then 
> the same 
> tricks can be used for other accesses such as wrapping an access in 
> "volatile", reading and writing eeprom, and atomically accessing data.
> 
> mvh.,
> 
> David
> 
> 
> >
> > How about a more general solution based on typeof and sizeof?
> >
> > #define pgm_read(v) ((typeof(*v)) \
> > (__builtin_choose_expr(sizeof(*v) == 1, pgm_read_byte(v), \
> > __builtin_choose_expr(sizeof(*v) == 2, pgm_read_word(v), \
> > __builtin_choose_expr(sizeof(*v) == 4, pgm_read_dword(v), \
> > ({ char error[((sizeof(*v) == 1) || (sizeof(*v) == 2) || \
> > (sizeof(*v) == 4)) ? 1 : -1]; error[0]; }) \
> > )))))
> >
> >
> > The macro above looks a bit ugly, but it's not too hard to follow.
> > Basically, we are using sizeof(*v) to figure out the size 
> of the data
> > you are wanting, and using it to pick the correct 
> pgm_read_xxx function
> > for the data size. We use __builtin_choose_expr instead of 
> ?: to avoid
> > any unwanted expression evaluations or side effects, as 
> well as to allow
> > different sized return values. The "char error[...]" part 
> is a way to
> > force a compile-time error if the macro is used with something whose
> > size is not 1, 2 or 4 bytes.
> >
> > The result is that you can write:
> >
> > char x;
> > char* PROGMEM FlashPointer = &x;
> > char* FlashPtr = pgm_read(&FlashPointer);
> >
> > You can equally write:
> >
> > static const PROGMEM uint8_t x8 = 8;
> > static const PROGMEM uint16_t x16 = 16;
> > static const PROGMEM uint32_t x32 = 32;
> >
> > void test(void) {
> > volatile uint8_t y8 = pgm_read(&x8);
> > volatile uint16_t y16 = pgm_read(&x16);
> > volatile uint32_t y32 = pgm_read(&x32);
> > }
> >
> >
> > Now your pgm_read's are independent of the type, assuming 
> they have a
> > compatible size.
> >
> >
> > Personally, my preference would be to change the semantics 
> to remove the
> > "&", so that you would write:
> >
> > char* FlashPtr = pgm_read(FlashPointer);
> >
> > This is just a small change to the macro, but I think it's 
> neater - you
> > are reading an object from flash, rather than reading data from an
> > address in flash. But such a change would require a name 
> change to avoid
> > accidents.
> >
> > mvh.,
> >
> > David
> >
> >
> >
> >
> >
> > _______________________________________________
> > AVR-libc-dev mailing list
> > address@hidden
> > http://lists.nongnu.org/mailman/listinfo/avr-libc-dev
> >
> 
> 
> _______________________________________________
> AVR-libc-dev mailing list
> address@hidden
> http://lists.nongnu.org/mailman/listinfo/avr-libc-dev
> 



reply via email to

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