我的应用程序有许多模块,每个模块都需要将一些变量存储在片外非易失性存储器中。为了使这些读取和写入更容易,我试图将它们一起收集到一个连续的RAM区域,以便NVM驱动程序在与NVM设备通信时可以寻址单个内存块。
为实现这一目标,我创建了一个包含以下部分定义的自定义链接描述文件。
.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);
使用Microchip为目标器件提供的标准定义,在MEMORY部分中定义data
区域。
data (a!xr) : ORIGIN = 0x1000, LENGTH = 0xD000
尝试将其变量放在此部分中的C源文件的一个示例是NVM驱动程序本身。驱动程序在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)堆栈。这样可以在NVM中保存模块ID和比特率。
// 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'
如上所述_slaveConfig
声明所示,如果NVM驱动程序无法从NVM设备加载变量,那么变量可以通过crt启动时的值初始化,这一点非常重要(&#39) ;空白,或软件版本已更改,等)。这是导致属性不匹配的原因吗?
这里和Microchip论坛上有几个问题,涉及访问C中链接描述文件中定义的符号。大多数这些问题涉及程序闪存中的值以及如何从C访问它们;我知道怎么做。有a similar question,但这似乎没有解决属性问题,并且由于特定于不同目标处理器的链接器而有点混乱。
我已经在线阅读了Microchip链接器手册和各种GCC链接器文档,但无法找到相关章节,因为我并不真正理解错误的含义以及它与我的代码的关系。什么是输入和输出部分属性',它们在我的代码中指定了哪些内容,以及如何让它们相互匹配?
答案 0 :(得分:0)
问题是由于_nvmHeader
变量没有在C源中为其分配初始值,但_slaveConfig
变量确实存在。
这会导致链接器从.nvm_fram
输入节属性推断出.nvm_header
输出节是未初始化的(nbss)。因此,当它从.nvm_canopen
变量的_slaveConfig
输入部分中包含初始化数据时,输入部分属性中存在不匹配:.nvm_fram
用于未初始化的数据,但是{{1}包含初始化数据。
解决方案是确保将放置在.nvm_canopen
输出部分中的所有变量赋予C源中的初始值。
.nvm_fram
因此,答案是输出部分属性可以部分地由该部分所在的存储区域以及分配给它的第一输入部分的属性确定。初始化和未初始化的C变量具有不同的输入节属性,因此不能位于同一输出节中。