ошибка stm32f4 g++, связанная с newlib _kill_r,_kill, _getpid_r, _getpid,

У меня возникла проблема с компиляцией кода С++ на микрочип stm32f4.

Цель

Я пытаюсь добиться нескольких вещей здесь:

  1. скомпилировать код C++ для обнаружения stm32f4 (что было успешно выполнено в базовой программе [с реализацией конструкторов и других специфических функций C++])
  2. написать код, используя библиотеку периферийных устройств, предоставленную ST (в данном случае я использую функциональность USART)
  3. Скомпилируйте код без использования коммерческой IDE (это задача по обучению) с помощью инструментов GNU.

Проблема

У меня есть два проекта, один из которых является проектом c и будет правильно компилироваться. Я также прошивал stm32f4 с выводом этого проекта, и он работал правильно. Второй проект использует тот же код с небольшими изменениями в файле make и именах файлов для компилятора C++ (никаких различий в коде). Проект C успешно компилируется, а проект C++ выдает ошибки.

Оба проекта и их вывод на терминал можно найти здесь: https://dl.dropboxusercontent.com/u/32204435/USART.tar.gz

Настраивать

Я использую Ubuntu 12.04.3 LTS 64bit. Я установил набор инструментов arm-none-eabi по инструкции на этом сайте: vedder.se/2012/07/get-started-with-stm32f4-on-ubuntu-linux/

Информация и анализ

Из того, что я могу сделать, это ошибка с поддержкой newlib в компиляторе arm-none-eabi-g++. Я не понимаю, почему возникает ошибка, поскольку между двумя проектами нет различий в коде. Функции из newlib, такие как printf, также приводят к подобным ошибкам, если они используются. В примерах USART я ограничил любую возможность использования проекта newlib (исключение только для типов данных). Похоже, что ошибка вызвана не новой библиотекой, а отсутствующим аппаратным заголовком (или известным как заглушки новой библиотеки) (syscalls.h). Я безуспешно пытался применить syscalls.h.

Может ли кто-нибудь помочь с созданием этого проекта с поддержкой C++ и, возможно, даже предложить решение для использования кода в newlib без ошибок (например, printf [или, я знаю, большой вопрос, cout из iostream])?

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

С Рождеством!


person NicholasB    schedule 24.12.2013    source источник


Ответы (2)


Добавьте -fno-rtti и -fno-exceptions в CFLAGS в Makefile.

Кроме того, вы можете добавить этот хак в файлы компиляции.

extern "C" int __aeabi_atexit(void *obj, void (*dtr)(void *), void *dso_h) {
    (void) obj;
    (void) dtr;
    (void) dso_h;
    return 0;
}

void *__dso_handle = 0;

/**
 * This is an error handler that is invoked by the C++ runtime when a pure virtual function is called.
 * If anywhere in the runtime of your program an object is created with a virtual function pointer not
 * filled in, and when the corresponding function is called, you will be calling a 'pure virtual function'.
 * The handler you describe should be defined in the default libraries that come with your development environment.
 */
extern "C" void __cxa_pure_virtual() {
        while (1)
                ;
}

namespace __gnu_cxx {

void __verbose_terminate_handler() {
        while(1)
                ;
}

}

Это отключает перехват сигналов вместо проверки исключений.

Хороший хак!

person martinribelotta    schedule 24.12.2013
comment
Флаги работают! хотя взломать дозу нет. Как бы вы это реализовали? Я реализовал это в main.cpp. Знаете ли вы какой-либо способ заставить функцию printf() работать из ‹stdio.h›? Я могу перенаправить printf на интерфейс USART, но когда я компилирую это с помощью g++, я получаю такие ошибки: In function _sbrk_r: sbrkr.c:(.text._sbrk_r+0xc): undefined reference to _sbrk и другие, связанные с _write _close _fstat _isatty _lseek и _read - person NicholasB; 25.12.2013
comment
Извиняюсь! вам нужна реализация _sbrk. Система роста стека. Ответ ниже - person martinribelotta; 25.12.2013
comment
Учебное пособие по запуску в работу процедур ввода-вывода printf и консоли: sites.google.com/site/stm32discovery/ - person martinribelotta; 25.12.2013

Для использования rtti и исключений вам необходимо определить некоторые реализации системных вызовов:

В моем компиляторе (gcc arm embedded 4.8 + newlib nano) этот обходной путь работает нормально (добавьте в новый файл с именем src/hack.cpp):

extern "C" int __aeabi_atexit(void *obj, void (*dtr)(void *), void *dso_h) {
    return 0;
}

/* Enable if your stub don't provide dso handle symbol */
#if 0
void *__dso_handle = 0;
#endif

extern "C" void __cxa_pure_virtual() {
    while (1)
        ;
}

namespace __gnu_cxx {
  void __verbose_terminate_handler() { while(1) ; }
}

extern "C" int _getpid(void) {
  return 1;
}

extern "C" void _kill(int pid) { while(1) ; }

extern "C" int _end;

static char *end_of_data = (char *) &_end;

/*
 * WARNING: No stack/heap colition check.
 * For check colition and stack growing overflow use SP register value
 * or RAM end limit depeding of processor architecture
 */
extern "C" char *_sbrk (int delta) {
        char *ptr = end_of_data;
        end_of_data += delta;
        return ptr;
}

Если у вас по-прежнему возникают проблемы с неопределенными символами, такими как _write или _isatty, добавьте -lnosys к флагам компоновщика.

Полученный исполняемый файл немного толще, чем версия без исключений. (около 8 КБ). Но если вам нужны исключения, а механизм rtti требует минимальных затрат на Cortex-M4 с 1 МБ флэш-памяти.

person martinribelotta    schedule 25.12.2013
comment
Я сделал hack.cpp и не возражаю против накладных расходов. Я не знаю, как использовать компоновщик, мой make-файл (ссылка) в настоящее время не не используйте лд. Какие изменения я должен внести, чтобы все файлы правильно связывались? - person NicholasB; 26.12.2013
comment
Я также сделал еще один файл для заглушек newlib. Я отредактировал файл по предоставленной вами ссылке с поддержки stm32f0 на stm32f4. Хотя любая попытка компиляции этих исходников все равно приведет к ошибкам с неопределенными символами. - person NicholasB; 26.12.2013
comment
Мне удалось заставить работать функцию printf(). Я еще недостаточно опытен, чтобы использовать компоновщик (ld), но у меня есть c-версия startup_stm32f4xx из coocox IDE. Под этим я вставил код newlib_stubs, и все работает хорошо. Это кажется грязной настройкой, но это работает. - person NicholasB; 26.12.2013