优化库Arduino:未定义的引用

时间:2017-01-25 13:50:39

标签: arduino undefined-reference

嵌入式系统的开发强加了另一种代码方式。 在最小化名为#define的库的大小的目标中,我将调整我的主类的结构。 我的想法是在将我的库包含在主程序中时,仅在存在某些MySensor的情况下声明某些函数。

RF24Wave.h这样的流行库使用这种方式来减少内存占用。

所以,我的库有两个文件:

  • #ifndef __RF24WAVE_H #define __RF24WAVE_H #include <arduino.h> ... class RF24Wave { public: /****** Common functions ******/ void begin(); #if !defined(WAVE_MASTER) /****** Node functions ********/ void connect(); #else /****** Master functions ******/ void printNetwork(); #endif private: bool synchronized = false; } :包含函数声明的头文件
RF24Wave.cpp
  • #include "RF24Wave.h" void begin() { //Body of my function } #if !defined(WAVE_MASTER) void connect() { //Body of my function } #else void printNetwork() { //Body of my function } #endif :包含函数定义的源文件
master.cpp

其次,我将此库包含在名为#define WAVE_MASTER的主草图中,其中包含master.cpp

  • #include <RF24.h> #include <RF24Network.h> #include <RF24Mesh.h> #include <SPI.h> #define WAVE_MASTER #include <RF24Wave.h> #include "master.h" // Configure the chosen CE, CSN pins RF24 radio(CE_PIN, CSN_PIN); RF24Network network(radio); RF24Mesh mesh(radio,network); RF24Wave wave(network, mesh); uint32_t displayTimer = 0; void setup() { Serial.begin(115200); wave.begin(); } void loop() { wave.listen(); wave.printNetwork(); } :主草图
master functions
  

目标是在主草图中定义#define WAVE_MASTER时仅包括In function `main': undefined reference to `RF24Wave::printNetwork()' collect2: error: ld returned 1 exit status *** [.pioenvs/uno/firmware.elf] Error 1

但是,在编译主草图时,我有一个链接错误

#define
  

我使用PlaformIO Core 1.7.1 / Atom 1.13.0编译

最后,出现此问题的原因是platformio.ini

的范围
  

此问题的解决方案是向gcc-compiler添加构建标志!

     

如果您使用combo PlatformIO / Atom,则可以在此添加此行   配置文件build_flags = -D$NAME_DEFINE

     
      
  • build_flags = -DWAVE_MASTER
  •   
     

在我们的案例中:

     
      
  • #define
  •   
     

添加此行后,该建筑似乎工作正常!

此外,有了这个选择性{{1}},我的图书馆的足迹记忆减少了10%以上!

非常感谢你的帮助。

2 个答案:

答案 0 :(得分:1)

如果您在arduino IDE中添加库,如here所述,它只是将另一个项目链接到您的库函数。它不是静态库(请参阅static and dynamic libraries)。然后我认为没有必要担心它的大小,因为编译器只有在你使用它们时才会嵌入你的库函数。

尝试打开任何示例(AnalogReadSerial),编译它。然后Sketch-&gt;添加库 - &gt; SPI。再次编译,大小不会改变。尝试在设置功能中调用SPI.begin(),大小会增加。添加对SPI.setBitOrder(MSBFIRST);的调用,大小再次增加。添加另一个调用SPI.setBitOrder(MSBFIRST);,大小再次增加,但不是相同的数量,因为它只包含一个setBitOrder定义和两个调用setBitOrder函数。

对于所有库来说并不完全正确,因为一些构造可能会强制编译器嵌入一些代码或分配内存,即使未使用该变量(例如参见volatile variables)。

因此,关于您的大小问题,您可能只需要使用一个#define MASTER,在#ifdef MASTER包围的设置和循环函数中编写主代码,并且{{{}}包围的从代码1}}。编译器将包括主服务器或从服务器使用的功能定义。

答案 1 :(得分:0)

所以,有了你的答案,我找到了解决方案! 问题是#define的范围。在构建过程中,编译的第一个源代码是主草图!因此,它包含#define WAVE_MASTER RF24Wave.hmaster.cpp的正确RF24Wave.cpp。但是,编译器不会将此定义考虑到其他源文件。因此,在编译#define WAVE_MASTER期间,没有为此源文件定义WAVE_MASTER

解决方案包括添加额外的gcc-flag以定义所有源文件和头文件的platformio.ini

使用PlatformIO / Atom,可以在配置文件中添加此行build_flags = -DWAVE_MASTER

  • [env:uno] platform = atmelavr board = uno framework = arduino build_flags = -DWAVE_MASTER

最后,您的配置文件应如下所示:

#define WAVE_MASTER

使用此解决方案,不再需要在头文件中添加use Zend\Mvc\MvcEvent; ... $eventManager = $event->getApplication()->getEventManager(); $eventManager->attach(MvcEvent::EVENT_ROUTE, array($this, 'onRoute'), -100); ,因为这是为您添加它的编译器。

此外,这种优化已经减少了超过10%的内存使用量,因为像这是一个大类对象,编译器构建了所有函数。使用选择性定义,编译器将只构建有用的函数。