A.1.4 通常時と割り込み時に使用する変数を定義する
通常時の処理と割り込みの処理の両方で使用する変数は,volatile指定してください。
volatile修飾子をつけて変数宣言すると,その変数は最適化の対象になりません。volatile指定された変数に対する操作を行うときは,必ずメモリから値を読み込み,volatile指定された変数に値を代入するときは必ずメモリへ値を書き込みます。また,volatile指定された変数のアクセス順序やアクセス幅も変更されません。volatile指定されていない変数は,最適化によってレジスタに割り付けられ,その変数をメモリからロードするコードが削除されることがあります。また,volatile指定されていない変数に同じ値を代入する場合,冗長な処理と解釈されて最適化によりコードが削除されることもあります。
例 1. | volatile 指定しなかった場合のソースと出力コードイメージの例 |
“変数a” ,“変数b”をvolatile 指定しなかった場合,これらの変数がレジスタに割り付けられ,最適化される場合があります。たとえば,この間に割り込みが入り,割り込み内で変数値を変更しても,値が反映されないことになります。
int a;
int b;
void func(void){
if(a <= 0){
b++;
} else {
b+=2;
}
b++;
}
|
_func:
movhi highw1(#_a), r0, r6
ld.w loww(#_a)[r6], r6
cmp 0x00000000, r6
movhi highw1(#_b), r0, r6
ld.w loww(#_b)[r6], r6
bgt .bb1_2 ; bb3
.bb1_1: ; bb1
add 0x00000001, r6
br .bb1_3 ; bb9
.bb1_2: ; bb3
add 0x00000002, r6
.bb1_3: ; bb9
add 0x00000001, r6
movhi highw1(#_b), r0, r7
st.w r6, loww(#_b)[r7]
jmp [r31]
|
例 2. | volatile指定した場合のソースと出力コードの例 |
“変数a”,“変数b”,および“変数c”をvolatile指定した場合,これらの変数値を必ずメモリから読み込み,値を代入するときはメモリへ書き込むコードが出力されます。たとえば,この間に割り込みが入り,割り込み内で変数値が変更されても,その変更が反映された結果を取得することができます。
volatile指定をすると,メモリの読み込み/書き込み処理が入るため,volatile指定しなかった場合よりもコード・サイズは大きくなります。
volatile int a;
volatile int b;
void func(void){
if(a <= 0){
b++;
} else {
b+=2;
}
b++;
}
|
_func:
movhi highw1(#_a), r0, r6
ld.w loww(#_a)[r6], r6
cmp 0x00000000, r6
bgt .bb1_2 ; bb3
.bb1_1: ; bb1
movhi highw1(#_b), r0, r6
ld.w loww(#_b)[r6], r6
add 0x00000001, r6
br .bb1_3 ; bb9
.bb1_2: ; bb3
movhi highw1(#_b), r0, r6
ld.w loww(#_b)[r6], r6
add 0x00000002, r6
.bb1_3: ; bb9
movhi highw1(#_b), r0, r7
st.w r6, loww(#_b)[r7]
ld.w loww(#_b)[r7], r6
add 0x00000001, r6
st.w r6, loww(#_b)[r7]
jmp [r31]
|