1

我在将 c++ 代码编译到 stm32f4 微芯片上时遇到问题。

目标

我想在这里实现一些目标:

  1. 将 C++ 代码编译到 stm32f4-discovery (已在裸机程序上成功完成[带有构造函数和其他 c++ 特定功能的实现])
  2. 使用 ST 提供的外设库编写代码(在本例中,我使用的是 USART 功能)
  3. 使用 GNU 工具在不使用商业 IDE 的情况下编译代码(这是一项学习任务)

问题

我有两个项目设置,一个是 ac 项目,可以正确编译。我还用这个项目的输出刷新了 stm32f4,它运行正常。第二个项目使用相同的代码,对 C++ 编译器的 make 文件和文件名进行了细微更改(代码没有区别)。C 项目成功编译,C++ 项目抛出错误。

这两个项目及其在终端上的输出都可以在这里找到: https ://dl.dropboxusercontent.com/u/32204435/USART.tar.gz

设置

我正在使用 Ubuntu 12.04.3 LTS 64 位。我已按照本网站上的说明安装了 arm-none-eabi 工具链:vedder.se/2012/07/get-started-with-stm32f4-on-ubuntu-linux/

信息与分析

据我所知,arm-none-eabi-g++ 编译器中对 newlib 的支持存在错误。我不明白为什么会出现错误,因为两个项目之间没有代码差异。newlib 中的函数(如 printf)在使用时也会产生类似的错误。在 USART 示例中,我限制了项目使用 newlib 的任何可能性(只有数据类型例外)。该错误似乎不是由 newlib 引起的,而是由缺少的硬件标头(或称为 newlib 存根)引起的(syscalls.h)。我尝试应用 syscalls.h 均未成功。

任何人都可以通过 C++ 支持帮助构建这个项目,甚至可以提供在 newlib 中正确使用代码的解决方案(比如 printf [或者,我知道一个大问题,来自 iostream 的 cout])?

我还在学习,我今年 17 岁,没有老师(自我驱动),所以似乎缺乏经验,我就是这样 :) 期待知识空白。

圣诞节快乐!

4

2 回答 2

2

将 -fno-rtti 和 -fno-exceptions 添加到 Makefile 上的 CFLAGS。

或者,您可以将此 hack 添加到编译文件

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)
                ;
}

}

这禁用了异常检查上的信号捕获。

好哈克!

于 2013-12-24T18:01:31.233 回答
0

对于 rtti 和异常的使用,您需要定义一些系统调用实现:

在我的编译器(gcc arm 嵌入式 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 添加到链接器标志。

生成的可执行文件比非异常版本略胖。(大约 8K)但是如果您需要异常并且 rtti 机制在具有 1M 闪存的 Cortex-M4 上的开销很小

于 2013-12-25T15:08:22.043 回答