2017-01-25 62 views
0

嵌入式系統的開發強加了另一種編碼方式。 爲了最大限度地減少名爲RF24Wave的庫的大小,我將調整我的主類的結構。 這個想法是在我的程序庫包含在主程序中的時候聲明某些函數只有在某些#define的存在。優化庫Arduino:未定義的參考

流行的庫,如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 

我PlaformIO核心1.7.1編譯/ ATOM 1.13.0

最後,這個問題的原因是#define的範圍。

此問題的解決方案是將編譯標誌添加到gcc編譯器!

如果使用組合PlatformIO/ATOM,您可以加入這一行到這個 配置文件platformio.ini

  • build_flags = -D$NAME_DEFINE

在我們的例子:

  • build_flags = -DWAVE_MASTER

添加這條線後,建築看起來很好!

另外,通過這個選擇性#define,我的程序庫減少了超過10%的佔用空間!

非常感謝您的幫助。

+0

其中WAVE_MASTER是爲「master.cpp」定義的嗎?這是行不通的,因爲你無法控制你的代碼文件的定義。 (除非你使用編譯器選項,如果有的話) –

+0

Arduino明確地不是C,也不完全是C++。 – Olaf

+1

可能重複[什麼是未定義的引用/無法解析的外部符號錯誤,以及如何解決它?](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external- symbol-error-and-how-do-i-fix) – Olaf

回答

1

如果您將庫添加到arduino IDE中,因爲它描述爲here它只是將另一個項目鏈接到庫函數。它不是一個靜態庫(參見static and dynamic libraries)。然後我認爲沒有必要擔心它的大小,因爲只有在你使用它們的時候,編譯器纔會嵌入你的庫函數。

嘗試打開任何示例(AnalogReadSerial),編譯它。然後Sketch->添加一個庫 - > SPI。再次編譯它,大小不會改變。嘗試在設置功能中調用SPI.begin(),尺寸增加。加入電話SPI.setBitOrder(MSBFIRST);,尺寸再次增加。將另一個調用添加到SPI.setBitOrder(MSBFIRST);,大小再次增加,但不是相同的數量,因爲它只包含一個setBitOrder定義和兩個對setBitOrder函數的調用。

對於所有庫而言,這並不完全正確,因爲即使未使用該變量,某些構造可能會強制編譯器嵌入一些代碼或分配內存(請參閱volatile variables)。

所以,關於你的大小問題,你可能只需要使用一個#define MASTER,寫在由#ifdef MASTER包圍設置和循環功能的主代碼和#else...#endif包圍了從編碼。編譯器將包含主設備或從設備使用的功能定義。

0

所以,你的答案,我找到了解決方案! 問題是#define的範圍。在編譯期間,編譯的第一個源代碼是主要草圖!因此,它包含master.cppRF24Wave.h中的正確#define WAVE_MASTER。但是,編譯器不會將此定義考慮在其他源文件中。因此,在編譯RF24Wave.cpp時,#define WAVE_MASTER未針對此源文件定義。

該解決方案包括添加一個額外的gcc標誌來爲所有源文件和頭文件定義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%的內存使用量,因爲像這是一個大類對象,編譯器會構建所有功能。通過選擇性定義,編譯器將只構建有用的函數。