2

I get a "section type conflict" if I call a macro in an inlined function. There is nothing which can be found about this error in the WWW.

The intention of the macro is to offer a macro to deal with strings saved in the flash for Arduino (just a side info). If the function is not inlined everything is fine. What may be the reason?

#undef PROGMEM
#define PROGMEM __attribute__(( section(".progmem.data") ))

#undef PSTR
/* need to define prog_char in avr-gcc 4.7 */
#if __AVR__ && __GNUC__ == 4 && __GNUC_MINOR__ > 6
typedef char prog_char;
#endif
/* Need const type for progmem - new for avr-gcc 4.6 */
#if __AVR__ && __GNUC__ == 4 && __GNUC_MINOR__ > 5
#define PSTR(s) (__extension__({static const prog_char __c[] PROGMEM = (s); \
                                  (const prog_char_t *)&__c[0]; }))
#else
#define PSTR(s) (__extension__({static prog_char __c[] PROGMEM = (s); \
                                  (prog_char_t *)&__c[0]; }))
#endif

Code:

inline void test() {
    hal.console->println("AP_Common tests\n");
    hal.console->println_P(PSTR("AP_Common tests\n") );
    hal.console->printf_P(PSTR("AP_Common tests\n") );
}

void setup(void)
{
  test();
}

void loop(void)
{
    // do nothing
}

Errors for: "println_P(PSTR("Bad var table\n") );"

AP_HAL/utility/BetterStream.h:53:57: note: in definition of macro 'printf_P'
 #define printf_P(fmt, ...) _printf_P((const prog_char *)fmt, ## __VA_ARGS__)
                                                         ^
output_debug.h:13:26: note: in expansion of macro 'PSTR'
   hal.console->printf_P( PSTR("{\"t\":\"s_cmp\",\"h\":%.1f}\n"),
                          ^
AP_Progmem/AP_Progmem_AVR.h:25:56: note: '__c' was declared here
 #define PSTR(s) (__extension__({static const prog_char __c[] PROGMEM = (s); \
                                                        ^
AP_HAL/utility/BetterStream.h:53:57: note: in definition of macro 'printf_P'
 #define printf_P(fmt, ...) _printf_P((const prog_char *)fmt, ## __VA_ARGS__)
                                                         ^
AP_test.ino:60:27: note: in expansion of macro 'PSTR'

EDIT:

Calling PSTR() in two times derived classes causes the same problem. I think it is a compiler bug, which leads to undefined behavior.

dgrat
  • 2,214
  • 4
  • 24
  • 46
  • Try to remove `PROGMEM` just to see whether that makes a difference. Also check that you have only a single call for PSTR() in your code. – Aaron Digulla May 04 '15 at 14:23
  • Note that per the standard, "All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use." Your macro's use of `__c` as an identifier therefore produces undefined behavior. In practice, you can often get away with using reserved identifiers, but if GCC defines `__c` as a macro in the relevant scope -- which it is at liberty to do on account of it being reserved -- then all manner of havoc could ensue. – John Bollinger May 04 '15 at 14:39
  • It might be illuminating to examine the result of preprocessing the affected header: `gcc -E AP_Progmem_AVR.h`. – John Bollinger May 04 '15 at 14:40
  • @John: __c naming is not the problem. Renaming doesn't solve it. – dgrat May 04 '15 at 16:04
  • @dgrat: `__c` seems still to result in an follow-up error according to the messages posted (there must be another message for this problem). – too honest for this site May 04 '15 at 18:29
  • Also see [Compile error "X causes a section type conflict with Y" should provide more information](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82209) in the GCC Issue Tracker. – jww Sep 14 '17 at 07:34

1 Answers1

2

try: PROGMEM static const prog_char __c[]. Strange is, that I found out the attribute must preceed the declaration Not sure what your version actually does. This might very well be the problem.

Alternatively: The section type is an attribute to the locical memory section the values are stored. I suppose this was reported by the linker. the PROGMEM section is NOLOAD by default (which is makes sense for this section). However, due to the initialization, the compiler requires the section to be the opposite, thus resulting in the error. Even if that is not true, I would search the problem in this area.

Some additional remarks:

  • use stdint types, do not rely on the built-in types for their size.
  • Be careful with 'char'. Use only for actual characters and do not rely on their signed-ness. If you have to care about a different type (uint8_t or int8_t) would be more appropriate.
  • `#undef' macros not before their usage, but after if necessary. Otherwise, an unintended redefinition might pass without a warning. These errors can be very hard to debug! Use guards in headers instead.
  • In microcontrollers, const-correctness is vital, so use it wisely. Do not avoid const even if this takes more effort (until you get more experience). This will not only detect common flaw at compile-time, but also saves RAM and (possibly even) Flash as non-const variables are stored in RAM with initialization values in Flash.
  • Do not use __-prefixes in custon code. These should be reserved for the compiler and system libs of the toolchain). You might use this as suffix, though (but why in the example??)
  • Avoid typecasts. Most casts in beginner's code are actually unnecessary or a symptom of bad interface design. Basically: if you do not have to specify the type of an argument to a function, a typecast should not be required. (Yes, there are exeptions - that's why I call it a basic rule, not a law).
  • In general: use all help from the compiler you can get. Embedded debugging is not really fun.
too honest for this site
  • 12,050
  • 4
  • 30
  • 52
  • I created a minimal demo. The error is only occuring if I make the function call PSTR in a inlined function. Is this a compiler error? – dgrat May 04 '15 at 15:37
  • Not sure, I use the original 4.7.2 on ARM and have not worked with the AVR actually. But I would not think so. I still do not understand why there would be a difference between 4.6 and it predecessors. `const` is actually standard. Btw, if it is just for Flash vs. RAM: normally, gcc does puts constant variables (sic: that's what `const` actually says in `C`) into the `.const` section which would be linked by default into Flash. But maybe this is different for the AVR's external harward architecture (the ARMs and MSP430 I used have external von Neumann architecture as most modern CPUs). – too honest for this site May 04 '15 at 17:55
  • 1
    Good answer, but I disagree with the remark about stdint types. It's absolutely fine to declare your own types to provide a hint about the meaning. After all, that's why we have types like `size_t` and all the other types in `` and friends. But even if you'd like to use standard types, the correct one here would be `char` instead of `uint8_t` as a string really contains _characters_. – DarkDust May 05 '15 at 07:16
  • @DarkDust: I agree and my Answer might have been a bit incomplete. I actually also use size_t, and - of course - typedef (quite a lot actually). I clarified that in an edit. Btw.: were are talking about bare-metal embedded programming, so I would not expect `sys/types.h` to exist, neither do most other headers (freestanding/non hosted environment). – too honest for this site May 05 '15 at 11:44
  • Putting PROGMEM in front of the declaration doesn't help here. – dgrat May 05 '15 at 16:30
  • Could you please update the question and post the complete error messages? Also, please clarify if this is ardouino (programming) or native gcc code and for which CPU (AVR I suppose?). Is that macro and framework homemade or something external? If the latter: did you ask the vendor? If native gcc: did you check out the AVR extensions of gcc; there are some predefined qualifiers for the various memory types which might be helpful. – too honest for this site May 05 '15 at 21:00