GUNRX用プロジェクトのスマートコンフィグレータのBSPを見ていて気付いた変な移植コード

こんにちは。NoMaYです。

CC-RX用プロジェクトのFITのBSPモジュールとGUNRX用プロジェクトのスマートコンフィグレータのBSPモジュールを比較していて気付いたのですが、この書き換えは元のコードの意図を全く理解していないですよね、、、

CC-RX用プロジェクトのFITのBSPモジュールのr_bsp\mcu\rx65n\locking.c

bool R_BSP_SoftwareLock (BSP_CFG_USER_LOCKING_TYPE * const plock)
{
#if BSP_CFG_USER_LOCKING_ENABLED == 0
    bool ret = false;

    /* Variable used in trying to acquire lock. Using the xchg instruction makes this atomic */
    int32_t is_locked = true;
    
    /* This example uses the RX MCU's atomic xchg() instruction. plock->lock is the lock we are trying to reserve.
       The way this works is that 'is_locked' gets the value of the plock->lock and plock->lock gets the value of
       'is_locked' which we just set to 'true'. Basically this is an atomic 'swap' command. If the lock had not yet been
       reserved then its value would be 'false' and after the xchg() instruction finished 'is_locked' would have
       'false'. If it had already been reserved then 'is_locked' would have 'true' after the xchg() instruction. Since
       plock->lock was already 'true' and we just set it back to 'true' everything is ok. To see if we reserved the lock
       we just need to check the value of 'is_locked' after this instruction finishes. */

    /* Try to acquire semaphore to obtain lock */
    xchg(&is_locked, &plock->lock);
    
    /* Check to see if semaphore was successfully taken */
    if (is_locked == false)
    {        
        /* Lock obtained, return success. */
        ret = true;
    }
    else
    {
        /* Lock was not obtained, another task already has it. */
    }

    return ret;   
#else
    /* User is going to handle the locking themselves. */
    return BSP_CFG_USER_LOCKING_SW_LOCK_FUNCTION(plock);
#endif
} /* End of function R_BSP_SoftwareLock() */

生成されたコード(最適化無しでの例)

bool R_BSP_SoftwareLock (BSP_CFG_USER_LOCKING_TYPE * const plock)
        ADD #0FFFFFFF0H, R0
        MOV.L R1, 0CH[R0]

    bool ret = false;
        MOV.B #00H, 03H[R0]

    int32_t is_locked = true;
        MOV.L #00000001H, 04H[R0]

    xchg(&is_locked, &plock->lock); ← 第2引数がxchg命令のメモリオペランド側となる仕様の組み込み関数
        MOV.L 0CH[R0], R1
        MOV.L 04H[R0], R2
        XCHG [R1].L, R2
        MOV.L R2, 04H[R0]

    以後省略


GUNRX用プロジェクトのスマートコンフィグレータのBSPのBSPモジュールのr_bsp\mcu\rx65n\locking.c

bool R_BSP_SoftwareLock (BSP_CFG_USER_LOCKING_TYPE * const plock)
{
#if BSP_CFG_USER_LOCKING_ENABLED == 0
    bool ret = false;

    /* Variable used in trying to acquire lock. Using the xchg instruction makes this atomic */
    int32_t is_locked = true;
    
    /* This example uses the RX MCU's atomic xchg() instruction. plock->lock is the lock we are trying to reserve.
       The way this works is that 'is_locked' gets the value of the plock->lock and plock->lock gets the value of
       'is_locked' which we just set to 'true'. Basically this is an atomic 'swap' command. If the lock had not yet been
       reserved then its value would be 'false' and after the xchg() instruction finished 'is_locked' would have
       'false'. If it had already been reserved then 'is_locked' would have 'true' after the xchg() instruction. Since
       plock->lock was already 'true' and we just set it back to 'true' everything is ok. To see if we reserved the lock
       we just need to check the value of 'is_locked' after this instruction finishes. */

    /* Try to acquire semaphore to obtain lock */
    int32_t tmp;
    tmp = is_locked;
    is_locked = plock->lock;
    plock->lock = tmp;
    
    /* Check to see if semaphore was successfully taken */
    if (is_locked == false)
    {        
        /* Lock obtained, return success. */
        ret = true;
    }
    else
    {
        /* Lock was not obtained, another task already has it. */
    }

    return ret;   
#else
    /* User is going to handle the locking themselves. */
    return BSP_CFG_USER_LOCKING_SW_LOCK_FUNCTION(plock);
#endif
} /* End of function R_BSP_SoftwareLock() */

生成されたコード(最適化無しでの例)

bool R_BSP_SoftwareLock (BSP_CFG_USER_LOCKING_TYPE * const plock)
        push.l  r6
        add #-16, r0, r6
        mov.L   r6, r0
        mov.L   r1, 12[r6]

    bool ret = false;
        mov.B   #0, [r6]

    int32_t is_locked = true;
        mov.L   #1, 4[r6]

    int32_t tmp;
    tmp = is_locked;
        mov.L   4[r6], r5
        mov.L   r5, 8[r6]

    is_locked = plock->lock;
        mov.L   12[r6], r5
        mov.L   [r5], r5
        mov.L   r5, 4[r6]

    plock->lock = tmp;
        mov.L   12[r6], r5
        mov.L   8[r6], r4
        mov.L   r4, [r5]

    以後省略


[関連リンク]

RXファミリ RXv2命令セットアーキテクチャ ユーザーズマニュアル ソフトウェア編
www.renesas.com/ja-jp/search/keyword-search.html#q=R01US0071

CC-RXコンパイラ ユーザーズマニュアル
www.renesas.com/ja-jp/search/keyword-search.html#q=R20UT3248
 

Parents
  • ルネサスエレクトロニクスの鈴木と申します。NoMaY様、報告ありがとうございます。担当部署に報告しました。2018/7リリース予定のスマート・コンフィグレータで修正される予定です。修正の際は、他の移植コードを含めて再度確認いたします。以上、よろしくお願い致します。
  • NoMaY様、すみません確認させください。開発部隊に確認したところ、現状のコードで動作しますがコードが冗長なので問題ということでしょうか?
    私も勘違いしていましたが、現状のコードでもデータ交換は行っているとのことです。
    以上、よろしくお願いします。
  • 鈴木さん、こんにちは。NoMaYです。

    元のコードに非常に長いコメント(下記)が存在することから察して欲しいと思うのですが、この箇所は、ただ単にデータ交換を行うコードでは無い、ということなのです。

    This example uses the RX MCU's atomic xchg() instruction. plock->lock is the lock we are trying to reserve. 
    The way this works is that 'is_locked' gets the value of the plock->lock and plock->lock gets the value of
    'is_locked' which we just set to 'true'. Basically this is an atomic 'swap' command. If the lock had not yet been
    reserved then its value would be 'false' and after the xchg() instruction finished 'is_locked' would have
    'false'. If it had already been reserved then 'is_locked' would have 'true' after the xchg() instruction. Since
    plock->lock was already 'true' and we just set it back to 'true' everything is ok. To see if we reserved the lock
    we just need to check the value of 'is_locked' after this instruction finishes.

    元のコードに書かれている以下のコメントから分かる通り、セマフォのロックを行うコード、なのです。

    Variable used in trying to acquire lock. Using the xchg instruction makes this atomic
    Try to acquire semaphore to obtain lock
    Check to see if semaphore was successfully taken

    この件に関しては、Wikipediaの以下のページが理解の一助になると思います。(ちなみに、元のコードの処理と1対1で対応する説明が書かれている訳では無いですので、それなりに、頭を使う必要があります。)

    en.wikipedia.org/wiki/Semaphore_(programming)
    ja.wikipedia.org/wiki/セマフォ
    en.wikipedia.org/wiki/Test-and-set
    ja.wikipedia.org/wiki/テスト・アンド・セット

    以下、そこからの画面コピーです。














  • NoMaY様、解説ありがとうございます。OSと一緒に使う場合に注意が必要ですね。R_BSP_SoftwareLock関数の背景を含めて検討するように致します。
    以上、よろしくお願いします。
Reply
  • NoMaY様、解説ありがとうございます。OSと一緒に使う場合に注意が必要ですね。R_BSP_SoftwareLock関数の背景を含めて検討するように致します。
    以上、よろしくお願いします。
Children
No Data