volatileについて

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
青い犬

volatileについて

#1

投稿記事 by 青い犬 » 17年前

初めまして。volatileの効果について教えてください。
これまで、ポートやレジスタにアクセスするために以下のようにしてきました。
typedef struct tRegs {
  volatile unsigned int sourceReg;
  volatile unsigned int destinationReg;
  volatile unsigned int lengthReg;
} Regs;

Regs *dma1Reg = (Regs *)DMA1_BASE_ADDR;

void func()
{
  dmaReg->sourceReg = SOURCE_ADDR;
}
●質問1
これは、
typedef struct tRegs {
  unsigned int sourceReg;
  unsigned int destinationReg;
  unsigned int lengthReg;
} Regs;

volatile Regs *dma1Reg = (volatile Regs *)DMA1_BASE_ADDR;
‥‥
としても同じでしょうか?

というのは、レジスタアクセス以外に
通常の変数としてもこのRegs構造体を使用したいのです。
Reg saveReg;

void func2()
{
  saveReg.sourceReg = SOURCE_ADDR2;
}
しかし、このときにvolatileによって毎回メモリアクセスすることになり
処理に遅延が発生するのではないかと懸念しています。


●質問2
質問1の結果次第ではありますが、構造体を入れ子関係にした場合、
例えば、
typedef struct tRegs {
  unsigned int sourceReg;
  unsigned int destinationReg;
  unsigned int lengthReg;
} Regs;

typedef struct tDMARegs {
  Regs DMA0;
  Regs DMA1;
} DMARegs;

volatile DMARegs *dmaRegs = (volatile Regs *)DMA_BASE_ADDR;
‥‥
とした場合にRegsの要素にvolatileが有効になりますか?


よりよいコーディングをしたいものの知識が乏しく困っています。
よろしくお願いいたします。

たかぎ

Re:volatileについて

#2

投稿記事 by たかぎ » 17年前

●質問1

> volatile Regs *dma1Reg = (volatile Regs *)DMA1_BASE_ADDR;
> ‥‥
> としても同じでしょうか?

完全に同じではありませんが、同じ効果は期待できます。
どちらかといえば、volatile Regs *の方が望ましいでしょう。


●質問2

> Regsの要素にvolatileが有効になりますか?

有効です。

青い犬

Re:volatileについて

#3

投稿記事 by 青い犬 » 17年前

ご回答ありがとうございます。
もう少しだけ質問させてください。

●質問1
> 完全に同じではありませんが、同じ効果は期待できます。
の真意について教えていただけないでしょうか?

ひとつ気になっているのは、
Regsの要素に異なるサイズの型が混在した場合に
Regsの各要素にvolatileをつけないと
要素の並びを最適化してしまうのではないかという点です。
実際に私が実装としている今回の例では全てunsigned intなので
関係だとは思います。

的外れかもしれませんがこのことが完全に同じではないという
回答の意味でしょうか?

よろしくお願いします。

たかぎ

Re:volatileについて

#4

投稿記事 by たかぎ » 17年前

> > 完全に同じではありませんが、同じ効果は期待できます。
> の真意について教えていただけないでしょうか?

例えば、

> Regs *dma1Reg = (Regs *)DMA1_BASE_ADDR;

の場合だと、dma1Reg の参照先そのものがvolatile修飾されているわけではありません。
そのため、

void *ptr = dma1Reg;

のような使い方をしても、警告が出ることはまずないでしょう。
一方、

> volatile Regs *dma1Reg = (volatile Regs *)DMA1_BASE_ADDR;


としておけば、先のような使い方をすれば、(処理系やコンパイルオプションにもよりますが)警告が出ることをある程度期待できます。

> Regsの要素に異なるサイズの型が混在した場合に
> Regsの各要素にvolatileをつけないと
> 要素の並びを最適化してしまうのではないかという点です。

少なくとも規格合致処理系ではそのようなことは起こりません。
構造体のメンバは、アドレスの下位から記述した順に配置されることが保証されています。
ただし、非標準処理系や非標準拡張を用いた場合はこの限りではありせん。

なお、構造体のメンバの配置を入れ替える処理系が複数実在することを知っていますが、いずれもvolatile修飾子を付けたとしてもそれを抑止することはできません。
いずれの処理系も、メンバの再配置を行うか否かは、コンパイルオプションで設定するか、#pragma指令で明示的に設定するようになっていました。

青い犬

Re:volatileについて

#5

投稿記事 by 青い犬 » 17年前

疑問が解決しました。
たかぎさん、ありがとうございました。

> なお、構造体のメンバの配置を入れ替える処理系が複数実在することを知っていますが、
> いずれもvolatile修飾子を付けたとしてもそれを抑止することはできません。
ずっと勘違いした認識を持っていました。
勉強になります。

それにしても、ここはよい掲示板ですね。

閉鎖

“C言語何でも質問掲示板” へ戻る