1

我在 PIC24f16ka102 和 xc16 编译器中遇到了一个简单而快速的 C 问题。

我想将变量引用传递给我的函数。变量在 eeprom 空间中:

   int __attribute__ ((space(eedata))) eeData; // Variable located in EEPROM,declared as a global variable.

通过这个序列,我可以在 eeprom 内存中保存一些数据:

unsigned int offset;
// Set up NVMCON to erase one word of data EEPROM
NVMCON = 0x4004;
// Set up a pointer to the EEPROM location to be erased
TBLPAG = __builtin_tblpage(&eeData2); // Initialize EE Data page pointer
testDebug = TBLPAG;

offset = __builtin_tbloffset(&eeData); // Initizlize lower word of address
__builtin_tblwtl(offset, 0x9876); // Write EEPROM data to write latch
asm volatile ("disi #5"); // Disable Interrupts For 5 Instructions
__builtin_write_NVM(); // Issue Unlock Sequence & Start Write Cycle
while(NVMCONbits.WR == 1);

这样我将值 0x9876 写入 eeprom 的前 16 位。但我需要把它作为 &eeData

我想编写自己的函数:

void eeprom_writeWord(unsigned int __attribute__ ((space(eedata)))  addresOfMyEEpromVariable, unsigned int value)
{
    unsigned int offset;
// Set up NVMCON to erase one word of data EEPROM
NVMCON = 0x4004;
// Set up a pointer to the EEPROM location to be erased
TBLPAG = __builtin_tblpage(&addresOfMyEEpromVariable); // Initialize EE Data page pointer
offset = __builtin_tbloffset(&addresOfMyEEpromVariable); // Initizlize lower word of address
__builtin_tblwtl(offset, value); // Write EEPROM data to write latch
asm volatile ("disi #5"); // Disable Interrupts For 5 Instructions
__builtin_write_NVM(); // Issue Unlock Sequence & Start Write Cycle
while(NVMCONbits.WR == 1);
}

但是如何将我的地址作为函数参数传递,以便我的函数可以看到它仍然是 eeprom 空间中的地址?它不能只是地址,因为如果这样我就会出错。__builtin 函数需要具有某些属性的地址,它是 eeprom 内存。

如何将带有属性的 eeprom 地址传递给我的函数?请帮忙

编辑:

谢谢你的建议,但我仍然得到同样的错误:

    error: Argument to __builtin_tbloffset() is not the address
of an object in a code, psv, or eedata section;

函数 __builtin_tbloffset 需要 eeprom 内存的地址,而不仅仅是某物的地址。如果我使用整个序列而不是函数(我的意思是我的第一篇文章中的序列),它会很好地工作。

现在我按照你所说的那样尝试:

void eeprom_writeWord(unsigned int *addresOfMyEEpromVariable, unsigned int value)
{
        //write word
// Set up NVMCON to write one word of data EEPROM
NVMCON = 0x4004;
// Set up a pointer to the EEPROM location to be written
TBLPAG = __builtin_tblpage(*addresOfMyEEpromVariable);
unsigned int offset = __builtin_tbloffset(*addresOfMyEEpromVariable);
// Write Data Value To Holding Latch
__builtin_tblwtl(offset, 0x9999);
// Disable Interrupts For 5 Instructions
asm volatile ("disi #5");
// Issue Unlock Sequence & Start Write Cycle
__builtin_write_NVM();
while(NVMCONbits.WR == 1);
}

甚至没有'*'符号:

void eeprom_writeWord(unsigned int *addresOfMyEEpromVariable, unsigned int value)
{
        //write word
// Set up NVMCON to write one word of data EEPROM
NVMCON = 0x4004;
// Set up a pointer to the EEPROM location to be written
TBLPAG = __builtin_tblpage(addresOfMyEEpromVariable);
unsigned int offset = __builtin_tbloffset(addresOfMyEEpromVariable);
// Write Data Value To Holding Latch
__builtin_tblwtl(offset, 0x9999);
// Disable Interrupts For 5 Instructions
asm volatile ("disi #5");
// Issue Unlock Sequence & Start Write Cycle
__builtin_write_NVM();
while(NVMCONbits.WR == 1);
}

结果还是一样。__builtin_tblpage 和其他 __builtin_(...) 函数是内置于 xc16 编译器的函数。

4

2 回答 2

1

可能是内置例程可以处理硬编码地址(如在您的第一个示例中 - 编译器/链接器知道 eeData 的位置),但不能处理变量地址。

您可以尝试两件事:

(1) 使 eeprom_writeWord 成为内联函数(这样编译器就可以再次对地址进行硬编码)。请注意,如果这有效,它仍然可能会在“复杂”情况下失败,例如存储在索引数组中的地址。

(2) 查看为您的工作示例中的内置例程生成的汇编程序代码,并根据您的需要重写它们(使用 C 或内联汇编程序)。这些例程只有几条指令长。例如 __builtin_tblpage 只是剥离了地址的上半部分——这在 C 中很容易通过屏蔽和/或右移来完成。

于 2015-07-30T05:47:47.057 回答
0

考虑这个原型:

void eeprom_writeWord(unsigned int addresOfMyEEpromVariable, unsigned int value)

该属性可能在这里没有做任何事情,为了可读性而忽略了。您所做的不是获取地址(类型为unsigned int *),而是获取值本身(一个普通unsigned int的 ,这不是一个神奇的指针,只是通过调用它addressOfSomething;)),所以它只是被复制到您的函数中。

将其更改为以下

void eeprom_writeWord(unsigned int *addresOfMyEEpromVariable, unsigned int value)

并像这样使用

eeprom_writeWord(&eeData, 0x9876);

而且,当然,不要再&在函数中使用 addressOf 运算符了……因为现在你已经有了一个指针。然后,这将达到您的预期。

编辑:关于您的答案,您应该删除它(因为它不是答案),而是编辑您的原始问题并将其放在那里。

没有星号的版本是正确的。不了解您的编译器,在您的函数原型中包含该属性也可能会有所帮助:

void eeprom_writeWord(
    unsigned int __attribute__ ((space(eedata))) *addresOfMyEEpromVariable,
    unsigned int value)

只是说那里没有星号(将参数标记为指针),它绝对行不通。

于 2015-07-29T11:42:49.590 回答