"Конфликт типа раздела" из-за определения макроса в GCC 4.8.2

Я получаю "конфликт типов разделов", если вызываю макрос во встроенной функции. Нет ничего, что можно найти об этой ошибке в WWW.

Цель макроса - предложить макрос для работы со строками, сохраненными во флэш-памяти для Arduino (просто дополнительная информация). Если функция не встроена, все в порядке. В чем может быть причина?

#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

Код:

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
}

Ошибки для: "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'

РЕДАКТИРОВАТЬ:

Вызов PSTR() в двух производных классах вызывает ту же проблему. Я думаю, что это ошибка компилятора, которая приводит к неопределенному поведению.

1 ответ

Пытаться: PROGMEM static const prog_char __c[], Странно, что я обнаружил, что атрибут должен предшествовать объявлению. Не уверен, что на самом деле делает ваша версия. Это вполне может быть проблемой.

Альтернативно: тип раздела - это атрибут к разделу локальной памяти, значения которого хранятся. Я предполагаю, что об этом сообщил компоновщик. раздел PROGMEM по умолчанию является NOLOAD (что имеет смысл для этого раздела). Однако из-за инициализации компилятор требует, чтобы раздел был противоположным, что приводит к ошибке. Даже если это не так, я бы искал проблему в этой области.

Некоторые дополнительные замечания:

  • используйте типы stdint, не полагайтесь на встроенные типы для их размера.
  • Будьте осторожны с "char". Используйте только для реальных персонажей и не полагайтесь на их подпись. Если вам нужно позаботиться о другом типе (uint8_t или int8_t), будет более подходящим.
  • Макросы `#undef'не перед их использованием, а после при необходимости. В противном случае непреднамеренное переопределение может пройти без предупреждения. Эти ошибки могут быть очень сложными для отладки! Вместо этого используйте охранников в заголовках.
  • В микроконтроллерах правильность const жизненно важна, поэтому используйте ее с умом. Не избегайте const даже если это требует больше усилий (пока вы не получите больше опыта). Это не только обнаружит общий недостаток во время компиляции, но также сохранит ОЗУ и (возможно, даже) Flash, поскольку неконстантные переменные хранятся в ОЗУ со значениями инициализации во Flash.
  • Не использовать __ -приставки в коде Custon. Они должны быть зарезервированы для компилятора и системных библиотек инструментария). Вы можете использовать это как суффикс, хотя (но почему в примере??)
  • Избегайте Typecasts. Большинство приведений в коде новичка на самом деле не нужны или являются признаком плохого дизайна интерфейса. В основном: если вам не нужно указывать тип аргумента для функции, приведение типа не требуется. (Да, есть исключения - вот почему я называю это основным правилом, а не законом).
  • В общем: используйте всю помощь от компилятора, которую вы можете получить. Встроенная отладка не очень весело.
Другие вопросы по тегам