1

として定義された 32 ビット レジスタと、メモリ (DDRAM) 内のTIMERその 32 ビット アドレスがあるとします。TIMER_ADDR

uint32_t TIMER_ADDR; // 32 bits address declared as uint32_t

TIMER のレイアウトは次のように定義されます。

struct timer {
    uint32_t start:1;
    uint32_t mode: 3;
    uint32_t init: 4;
    uint32_t value:24
}

後で、ローカル変数 loc_timer を次のように定義しました。

struct timer loc_timer;

コンテンツを変更できるように、このレジスタをプログラムのローカル レジスタに読み込むにはどうすればよいですか

loc_timer.mode = 4;
loc_timer.init = 10;

それを書き戻して登録しTIMERますか?

何かのようなもの

(*(uint32_t *))&loc_timer = (*((uint32_t *)(TIMER_ADDR))); // read
(*((uint32_t *)(TIMER_ADDR))) = (*(uint32_t *))&loc_timer; // write

しかし、それは機能しません:-(

4

3 に答える 3

1

問題 1: レジスターが volatile として宣言されていないため、レジスターからの読み取りまたはレジスターへの書き込みが機能しません。コンパイラは、読み取りを予想とは異なる値に最適化するか、後で電話をかけるか、完全にスキップするかを決定する場合があります。

問題 2: レジスタは「TIMER_ADDR」と呼ばれる 32 ビット変数です。アドレスが含まれている場合、なぜポインタとして宣言されなかったのですか? 読者に伝えることは不可能です。

問題 3: さまざまな理由から、ハードウェア レジスタのビット マッピングにビット フィールドを使用できない。これを参照してください

問題 4: ハードウェア レジスタのマッピングに構造体もビット フィールドも使用できず、パディングが有効になっていないことが保証されません。これを防ぐには、コンパイラ固有のプラグマまたはコンパイル時の静的チェックが必要です。


上記を無視し、TIMER_ADDR が実際に変数であり、変数へのアドレスではないことを推測すると、解決策は次のようになります。

struct timer loc_timer = *(struct timer*) &TIMER_ADDR;
// and the other way around:
TIMER_ADDR = *(uint32_t*) &loc_timer;

正式には、そのようなキャストは未定義の動作であり、コンパイルはそれらについて警告する場合があります。実際には、アラインメントやパディングの問題がないことが確実である限り、機能します。

于 2013-12-20T10:51:11.937 に答える