2011-10-29 7 views
0

アドバイスをお願いします。私は小さな組み込みuPで作業しています。特定のメモリへの関数ポインタ

myfunctions構造体に私の様々な関数を割り当てたいと思います。それを正しく行うには? 次に、このmyfunctions(関数ポインタの構造体)を特定のメモリアドレス(0x1000など)に配置します。これを達成する最良の方法は何ですか?

typedef void (*fptr)(void); 

typedef struct FCN_IMAGE 
{ 
    fptr fcn1; 
    fptr fcn2; 
    fptr fcn3; 
} FUNC_T; 

FUNC_T myfunctions; 

実際にはジャンプテーブルのようなものです。


第2に、指定されたアドレスの場所(例:0x1000)から直接、この関数ポインタを他のプログラム内から読みたいと思います。

最初のコードは、特定のメモリ位置に関数ポインタの構造体を割り当てる必要があり、他の独立したコードは特定のメモリからこのテーブルを読み込む必要があります。これらの2つのプログラム間の相互接続は

#define FCN_BASE_ADDRESS (0x1000) 

でなければなりません。それを達成する最も良い方法は何ですか?

P.S.これはPCではなく組み込みプロセッサで実行されます。

+2

私はあなたのリンカーの機能だろうと思う。 –

+0

部分的には正しいですが、リンカが関与していないように、特定のメモリ位置に関数ポインタを置くことは達成可能でなければなりません。 – Pepe

+0

例:正しいかどうかわかりません: – Pepe

答えて

3

特定の場所にオブジェクトを配置することは、通常、コンパイラ固有の拡張機能を使用することで最も簡単に実行できます。言語によって定義された標準的な方法はありません。リンカスクリプトを変更することで特定の場所にグローバルオブジェクトを配置することも可能ですが、特定のツールチェーンに固有のものがあります

どのコンパイラ/ツールチェーンを使用していますか?そのドキュメントを参照してください。

+0

私はFreescale CodeWarriorツールを使用していますが、リンカそのものの方法しかないようです。それではまだそれを勉強しています... – Pepe

+1

@ペペ:「Codewarior」はフリースケールが開発ツール(IDE)で使用しているアーキテクチャの名前です。使用しているコンパイラについては何も教えてくれません。私はあなたが正しいと確信していませんが、ドキュメンテーションの "[Global Variable Address Modifier(@address)](http://www.freescale.com/infocenter/Codewarrior/index.jsp?topic=/com)を見てください。 freescale.doc.mcu.hcs08_compiler/080_ANSI-C_Frontend.Global_Variable_Address_Modifier_%28address%29.html)」と入力します。 – Clifford

+0

@ペペ、クリフォードがあなたの質問に答えました。私はFreescale Codewarriorを使用し、 'typename varname @ address'フォーマットはあなたが望むことをする方法です。 –

0

たぶん、以下がお手伝いします:

// assign my various functions to myfunctions struct 
myfunctions.fcn1 = &YourFunction1; 
myfunctions.fcn2 = &YourFunction2; 
myfunctions.fcn3 = &YourFunction3; 

// assign the struct of function pointers to specific memory location 
memcpy((void*)FCN_BASE_ADDRESS, &myfunctions, sizeof(myfunctions)); 

// read this table from specific memory 
memcpy(&myfunctions, (void*)FCN_BASE_ADDRESS, sizeof(myfunctions)); 

これは、あなたが実際に何をしたいかに私の推測に基づいています。

+0

私はちょうど試してみてください。コードは推奨通りにコンパイルされますが、機能しませんし、結果もありません。特定のアドレスには機能がありません。多分memcpyはこれで機能しません(関数ポインタのために推測するだけです)。 – Pepe

+0

@Pepe:memcpyはmemcpyです。これがあなたのためにうまくいかなかったら、あなたはそのソリューションを誤解しているか誤って適用しました。これは、 'FCN_BASE_ADDRESS'が* not * ROMである限り動作します。しかし、より単純な方法があります。 'FCN_BASE_ADDRESS'がタイプ 'FUNC_T *'であれば、関数は' FCN_BASE_ADDRESS-> fcn1() 'を介して直接アクセスすることができます。例えば、2番目のmemcpy()はありません。 – Clifford

0

これはポータブルな方法でそれを解決するための最良の方法である:

typedef void (*fptr)(void); 

#define FCN_BASE_ADDRESS ((volatile fptr*)0x1000) 

/* Make myfunctions an array, not a struct. 
    Structs can have padding and aren't portable. 
    It doesn't look like you need a struct in this case. 
*/ 
fptr myfunctions [N] = 
{  
    fptr fcn1; 
    fptr fcn2; 
    fptr fcn3; 
}; 

memcpy(&FCN_BASE_ADDRESS, myfunctions, sizeof(myfunctions)); 

あなたがCodeWarriorのを使用している場合、あなたはおそらく、あなたがそれらをしたい場所にそれらを割り当てるための#pragmaを使用することができますが。ここでは、読み書きRAMと32ビットアドレスバスに格納されていると仮定しています。

// .prm file 
SECTIONS 
    MEM_FCN_BASE_ADDRESS = READ_WRITE 0x2000 TO 0x200C; 
END 

PLACEMENT 
    FCN_BASE_ADDRESS INTO MEM_FCN_BASE_ADDRESS; 
END 

// .c file 
#pragma DATA_SEG FCN_BASE_ADDRESS 
fptr myfunctions[N] = ...; 
#pragma DATA_SEG DEFAULT 

彼らはそれがREAD_ONLYのセクションは、#pragma CONST_SEGとconst fptrと異なって行われなければならない、ベクタテーブル例えば、ROM /フラッシュに格納する必要がある場合。 (Cのconstキーワードは、typedef:edポインタと組み合わされると非合理的な振る舞いをすることに注意してください。この場合、定数ではない関数への定数ポインタが与えられ、NVMで必要になるはずです)

関連する問題