RL78マイコン|volatile変数アクセスの衝突防止(結局はDI/EIですが) (1)
前のエントリでvolatile変数アクセスの衝突防止は律儀にやっておいた方が得策だと思い、その為のアセンブラ
コードを書いてみました。衝突防止といっても結局は一時的に(ごっそりと)割り込み禁止にして割り込み処理へ
飛んでいかない(飛んでいくのをちょっと待たせる)ようにしてvolatile変数アクセスが衝突しないようにしている
だけなのですが、コンパイラの組み込み関数のDI()/EI()だけでやろうとすると割り込み処理と通常処理(非割り
込み処理)のどちらからでも呼び出される関数内の場合にちょっと煩わしい(もともとがDI状態の時はEI()しては
いけない)ですので、そのことに対処するようにアセンブラコード化してみました。(追記 : アセンブラコードは、
お蔵入りとなりました。)
; This code is in the public domain. You may use, modify or distribute it freely.
PUBLIC _begin_noInterrupts
_begin_noInterrupts: ;char begin_noInterrupts(void), return value : old PSW.IE
MOV A, PSW ; PSW.7 is PSW.IE
SHR A, 7
MOV C, A ; C = return value (old PSW.IE)
CLR1 IE ; DI
RET
PUBLIC _end_noInterrupts
_end_noInterrupts: ;void end_noInterrupts(char psw_i), psw_i : new PSW.IE
SHRW AX, 1 ; X = psw_i (new PSW.IE), A = ignored
MOV1 IE, CY ; EI (when psw_i = 1) or DI (when psw_i = 0)
RET
END
つまり、volatile変数アクセスの衝突を防ぎたい部分をbegin_noInterrupts()関数とend_noInterrupts()関数で
以下のようにサンドイッチするだけで済むようにしてみました。(なお、処理内容次第では変数アクセス前後の
処理も含めてサンドイッチする必要がある場合もあります。)
psw_i = begin_noInterrupts();
tick = V_timer_tick;
end_noInterrupts( psw_i );

何となくソースコード上の見た目の印象がちょっと薄いような気がしましたので以下のマクロも作ってみました。
(ポインタをアセンブラコードに渡そうとするとnear/farが絡んでちょっと面倒そうなのでマクロにしました。)
#define BEGIN_NOINTERRUPTS(a) *(a) = begin_noInterrupts()
#define END_NOINTERRUPTS(a) end_noInterrupts(a)
こうするとちょっとは目立ってくれるような気がします。
BEGIN_NOINTERRUPTS( &psw_i );
tick = V_timer_tick;
END_NOINTERRUPTS( psw_i );

以下は作成したアセンブラコードをステップ実行してみた時の要所の画面コピーです。




コードを書いてみました。衝突防止といっても結局は一時的に(ごっそりと)割り込み禁止にして割り込み処理へ
飛んでいかない(飛んでいくのをちょっと待たせる)ようにしてvolatile変数アクセスが衝突しないようにしている
だけなのですが、コンパイラの組み込み関数のDI()/EI()だけでやろうとすると割り込み処理と通常処理(非割り
込み処理)のどちらからでも呼び出される関数内の場合にちょっと煩わしい(もともとがDI状態の時はEI()しては
いけない)ですので、そのことに対処するようにアセンブラコード化してみました。(追記 : アセンブラコードは、
お蔵入りとなりました。)
; This code is in the public domain. You may use, modify or distribute it freely.
PUBLIC _begin_noInterrupts
_begin_noInterrupts: ;char begin_noInterrupts(void), return value : old PSW.IE
MOV A, PSW ; PSW.7 is PSW.IE
SHR A, 7
MOV C, A ; C = return value (old PSW.IE)
CLR1 IE ; DI
RET
PUBLIC _end_noInterrupts
_end_noInterrupts: ;void end_noInterrupts(char psw_i), psw_i : new PSW.IE
SHRW AX, 1 ; X = psw_i (new PSW.IE), A = ignored
MOV1 IE, CY ; EI (when psw_i = 1) or DI (when psw_i = 0)
RET
END
つまり、volatile変数アクセスの衝突を防ぎたい部分をbegin_noInterrupts()関数とend_noInterrupts()関数で
以下のようにサンドイッチするだけで済むようにしてみました。(なお、処理内容次第では変数アクセス前後の
処理も含めてサンドイッチする必要がある場合もあります。)
psw_i = begin_noInterrupts();
tick = V_timer_tick;
end_noInterrupts( psw_i );

何となくソースコード上の見た目の印象がちょっと薄いような気がしましたので以下のマクロも作ってみました。
(ポインタをアセンブラコードに渡そうとするとnear/farが絡んでちょっと面倒そうなのでマクロにしました。)
#define BEGIN_NOINTERRUPTS(a) *(a) = begin_noInterrupts()
#define END_NOINTERRUPTS(a) end_noInterrupts(a)
こうするとちょっとは目立ってくれるような気がします。
BEGIN_NOINTERRUPTS( &psw_i );
tick = V_timer_tick;
END_NOINTERRUPTS( psw_i );

以下は作成したアセンブラコードをステップ実行してみた時の要所の画面コピーです。




- 関連記事
-
- RL78マイコン|プログラムが変なところでブレークした時にどこまでデバッグ出来るか? (3)
- RL78マイコン|プログラムが変なところでブレークした時にどこまでデバッグ出来るか? (2)
- RL78マイコン|プログラムが変なところでブレークした時にどこまでデバッグ出来るか? (1)
- RL78マイコン|プログラムが変なところでブレークする様子をシミュレータで見てみた
- RL78マイコン|volatile変数アクセスの衝突防止(結局はDI/EIですが) (2)
- RL78マイコン|KURUMIスケッチ環境でのvolatile変数アクセスの衝突防止の実装 → 無かった
- RL78マイコン|本家Arduinoライブラリでのvolatile変数アクセスの衝突防止の実装
- RL78マイコン|volatile変数アクセスの衝突防止(結局はDI/EIですが) (1)
- RL78マイコン|32bit変数へのアクセスはアトミックじゃない
- RL78マイコン(G12,G13,G14)|CS+(CubeSuite+)でインターバルタイマシミュレーションを試す
- RL78マイコン基板(RL78/G10)|CS+(CubeSuite+)で内蔵周辺機能シミュレーションを試す (3)
- RL78マイコン基板(RL78/G10)|CS+(CubeSuite+)で内蔵周辺機能シミュレーションを試す (2)
- RL78マイコン基板(RL78/G10)|CS+(CubeSuite+)で内蔵周辺機能シミュレーションを試す (1)
- RL78マイコン基板(RL78/G10)|e2studio同梱のPython 2.7.2+pySerial 2.7でシリアルポート操作
- RL78マイコン基板(RL78/G10)|CS+(CubeSuite+)のPythonコンソール上でシリアルポート操作 (3)
2015/01/28 blog-entry-559 category: RL78 /* 16bit,8bit CISC */
| h o m e |