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空間のアドレスであることを確認するにはどうすればよいですか? エラーが発生するため、アドレスだけではいけません。__組み込み関数は、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 の場所を認識しています)、変数アドレスを処理できません。

あなたが試すことができる2つのこと:

(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 に答える