“Section type conflict” due to macro definition in

2019-07-21 09:43发布

问题:

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.

回答1:

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.


标签: c arduino