なんとかなるさね

マイコンをネタにブログを始めてみました


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 );




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






関連記事

2015/01/28   blog-entry-559   category: RL78 /* 16bit,8bit CISC */

go page top