优化库 Arduino:未定义参考

Optimize library Arduino : undefined reference

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

流行的库,如 MySensor 使用这种方式来最小化内存占用。

所以,我的图书馆有两个文件:

#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;
}
#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:

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

The goal is to include only master functions when #define WAVE_MASTER is defined in the main sketch.

然而,在编译我的主要草图时,我有一个链接错误

In function `main':
undefined reference to `RF24Wave::printNetwork()'
collect2: error: ld returned 1 exit status
*** [.pioenvs/uno/firmware.elf] Error 1

I compiled with PlaformIO Core 1.7.1 /Atom 1.13.0

最后,这个问题的原因是范围#define

The solution of this problem is added build flags to gcc-compiler !

If you use combo PlatformIO/Atom, you can add this line into this config file platformio.ini :

  • build_flags = -D$NAME_DEFINE

In our case :

  • build_flags = -DWAVE_MASTER

After adding this line, the building seems work fine !

此外,通过这种选择性 #define,我的图书馆减少了超过 10% 的内存占用!

非常感谢您的帮助。

如果你在 arduino IDE 中添加你的库,正如它所描述的那样 here it just consists in linking another project to your library functions. It's not a static library (see static and dynamic libraries)。然后我认为没有必要担心它的大小,因为只有当你使用它们时,编译器才会嵌入你的库函数。

尝试打开任何示例(AnalogReadSerial),编译它。然后Sketch->Add a library->SPI。再次编译,大小没有变化。尝试在设置函数中调用 SPI.begin(),大小增加。添加对 SPI.setBitOrder(MSBFIRST); 的调用,大小再次增加。添加对 SPI.setBitOrder(MSBFIRST); 的另一个调用,大小再次增加,但增加的量不同,因为它只包含一个 setBitOrder 定义和对 setBitOrder 函数的两次调用。

并非所有库都如此,因为某些结构可能会强制编译器嵌入某些代码或分配内存,即使变量未被使用(参见 volatile variables 示例)。

所以关于你的尺寸问题,你可能只需要使用一个 #define MASTER,在设置和循环函数中写主代码,用 #ifdef MASTER 包围,从代码用 #else...#endif。编译器将包括主从使用的函数定义。

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

解决方案包括添加一个额外的 gcc-flag 来为所有源文件和头文件定义 WAVE_MASTER

使用 PlatformIO/Atom,可以在配置文件中添加这一行 platformio.ini

  • build_flags = -DWAVE_MASTER

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

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

使用此解决方案,不再需要在头文件中添加 #define WAVE_MASTER,因为这是编译器为您添加的。

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