2015-04-24 22 views
2

我的應用程序的數,每個需要一些變量被存儲在芯片外的非易失性存儲器模塊。爲了使這些讀取和寫入更容易,我試圖將它們一起收集到RAM的連續區域,以便NVM驅動程序可以在與NVM設備通信時尋址單塊內存。在數據存儲器輸出部分放置C變量需要哪些輸入部分屬性?

要做到這一點,我已經創建了一個包含以下部分定義自定義鏈接腳本。

.nvm_fram : 
{ 
    /* Include the "nvm_header" input section first. */  
    *(.nvm_header) 
    /* Include all other input sections prefixed with "nvm_" from all modules. */  
    *(.nvm_*) 

    /* Allocate a 16 bit variable at the end of the section to hold the CRC. */ 
    . = ALIGN(2); 
    _gld_NvmFramCrc = .; 
    LONG(0); 
} > data 
_GLD_NVM_FRAM_SIZE = SIZEOF(.nvm_fram); 

data區域在使用由Microchip目標設備提供的標準定義存儲部限定。

data (a!xr) : ORIGIN = 0x1000, LENGTH = 0xD000 

嘗試在本節中放置其變量的C源文件的一個示例是NVM驅動程序本身。驅動程序在NVM部分的開頭保存一個短頭結構,以便在將其加載到RAM之前驗證NVM設備的內容。沒有鏈接器錯誤報告這個變量。

// Locate the NVM configuration in the non-volatile RAM section. 
nvm_header_t _nvmHeader __attribute__((section(".nvm_header"))); 

在.nvm_fram部分存儲變量的另一個模塊是通信(CANopen)堆棧。這將模塊ID和比特率保存在NVM中。

// Locate LSS Slave configuration in the non-volatile RAM section. 
LSS_slave_config_t _slaveConfig __attribute__((section(".nvm_canopen"))) = 
    { .BitRate = DEFAULT_BITRATE, .ModuleId = DEFAULT_MODULEID }; 

一切編譯很好,但鏈接器運行時,下面的錯誤停止建設。

elf-ld.exe: Link Error: attributes for input section '.nvm_canopen' conflict with 
output section '.nvm_fram' 

這是很重要的變量可以與CRT啓動值被初始化,如上圖所示由_slaveConfig聲明,如果NVM驅動器不能從NVM設備加載它們(它是空白,或軟件版本已經改變等)。這是什麼導致屬性不匹配?

有幾個問題在這裏和Microchip的論壇上,這涉及到訪問的鏈接腳本中定義的從C.這些擔憂值大部分在閃存程序存儲器,以及如何從C訪問這些符號;我知道如何做到這一點。有a similar question,但是這似乎並沒有解決的屬性問題,是由於特定於爲不同的目標處理器連接有點混亂。

我讀過Microchip的連接手冊以及各種GCC連接在線文檔,但無法找到相關的部分,因爲我真的不明白是什麼錯誤意味着以及它如何與我的代碼。什麼是「輸入和輸出部分屬性」,它們在我的代碼中指定的地方,以及如何讓它們與海誓山盟匹配?

回答

0

問題是由於_nvmHeader變量在C源代碼中沒有分配給它的初始值,而是_slaveConfig變量。

這導致鏈接器推斷出.nvm_fram輸出節從.nvm_header輸入節屬性未初始化(nbss)。所以,當它enconters從_slaveConfig變量.nvm_canopen輸入部分初始化數據,所以在輸入部分不匹配屬性:.nvm_fram是未初始化的數據,但.nvm_canopen包含初始化的數據。

解決方法是確保所有變量將被放置在.nvm_fram輸出節中的C源中給出初始值。

// Type used to hold metadata for the content of the NVM. 
typedef struct 
{ 
    void*  NvmBase; // The original RAM address. 
    uint16_t NvmSize; // The original NVM section size. 
} nvm_header_t; 

// The linker supplies the gld_NVM_FRAM_SIZE symbol as a 'number'. 
// This is represented as the address of an array of unspecified 
// length, so that it cannot be implicitly dereferenced, and cast 
// to the correct type when used. 
extern char GLD_NVM_FRAM_SIZE[]; 

// The following defines are used to convert linker symbols into values that 
// can be used to initialise the _nvmHeader structure below. 
#define NVM_FRAM_BASE ((void*)&_nvmHeader) 
#define NVM_FRAM_SIZE ((uint16_t)GLD_NVM_FRAM_SIZE) 

// Locate the NVM configuration in the non-volatile RAM section. 
nvm_header_t _nvmHeader __attribute__((section(".nvm_header"))) = 
{ 
    .NvmBase = NVM_FRAM_BASE, .NvmSize = NVM_FRAM_SIZE 
}; 

因此答案是輸出段屬性可以通過在其中部將被定位和存儲區域部分地確定也由分配給它的第一輸入部的屬性。初始化和未初始化的C變量具有不同的輸入節屬性,因此不能位於同一輸出節中。

相關問題