RX65N/RX72N emWin+AppWizardでJapanese Language Displayが出来るか調べてみることにしました(Is it available?)

こんにちは。NoMaYです。

最近、以下のスレッドに関わったのですが、日本語が表示出来ないなんて?と、気になったので調べてみることにしました。もっとも、何から手を付けて良いのかさっぱり分からない状態からのスタートですので、ぼちぼちと、、、

AppWizardでの日本語テキスト表示について
japan.renesasrulz.com/cafe_rene/f/002-2095199602/8313/appwizard

まず、ソッコーで思い浮かんでアクセスしてみる情報から。

SEGGER emWinグラフィックスライブラリ (RX MCUs)
www.renesas.com/jp/ja/products/microcontrollers-microprocessors/rx-32-bit-performance-efficiency-mcus/rx-partners/segger-emwin-graphics-library-rx-mcus

RX Ecosystem Partner Solution
emWin - PROFESSIONAL EMBEDDED GRAPHICS LIBRARY
SEGGER( 日本国内販売代理店:株式会社エンビテック)
www.renesas.com/jp/ja/document/prb/segger-emwin-graphics-library-solution-brief-rx-mcus

emWin
Graphic Library with Graphical User Interface
User Guide & Reference Manual
Document: UM03001
Software version: V5.50 ⇒ ドキュメントのバージョンが古過ぎますね(下記のFITモジュールのとおり既にV6.22ですね)
Document revision: 0
Date: June 11, 2019
www.renesas.com/jp/ja/document/mat/emwin-graphic-library-gui-user-guide-reference-manual

RXファミリ emWin v6.22モジュール Firmware Integration Technology
www.renesas.com/jp/ja/document/apn/rx-family-emwin-v622-module-using-firmware-integration-technology
 

  • こんにちは。NoMaYです。

    AppWizardで日本語フォントのクリエイト(ホストOSのフォントからの変換)を行おうとしても、なかなか思惑通りのものがクリエイト出来ない(変換出来ない)です。思い浮かんだ原因として、AppWizardでデフォルト設定されているクリエイト対象(変換対象)の文字コード範囲定義が(当然ながら)英語を前提とした定義だからではないだろうか、という気がしました。その定義を日本語向けに定義し直せば改善されるのではないだろうか、という考えから日本語のUNICODE範囲について調べてみたところ、下記のウェブページに辿り着きました。(情報収集機械翻訳サイト?)

    www.web-dev-qa-db-ja.com/ja/unicode/日本語のユニコード範囲/1043031498/

    UNICODEというのは昨今は最大4バイト長らしいのですが、AppWizardでは旧来からの2バイト長であることが想定されている印象がありましたので、その場合には、日本語というのは以下の文字コード範囲となるようです。(上記より引用。)

    ひらがな                    0x3041-0x3096
    カタカナ(全角)            0x30A0-0x30FF
    漢字                        0x3400-0x4DB5, 0x4E00-0x9FCB, 0xF900-0xFA6A
    漢字ラジカル                0x2E80-0x2FD5
    カタカナと句読点(半角)    0xFF5F-0xFF9F
    日本語記号と句読点          0x3000-0x303F
    その他の日本語の記号と文字  0x31F0-0x31FF, 0x3220-0x3243, 0x3280-0x337F
    英数字と句読点(全角)      0xFF01-0xFF5E

     
    これを几帳面に設定するのは面倒なので、取り合えず、試しに、以下を設定してみることにしました。

    0x2E80-0x9FCB       29004文字相当分
    0x2E80-0x9FFF       29056文字相当分 ← UNICODEの文字分類の切れ目としてはコチラらしい
    0xF900-0xFF9F        1696文字相当分

     
    以下、AppWizardの画面コピーです。



     

  • こんにちは。NoMaYです。

    すみません、先日投稿したソース/プロジェクトですが、AppWizardでボタンを追加したり背景の塗り潰しを追加したり、とかしてもそのままでは描画されません、、、(片っ端からチェックする根気は無いので、気付いた分だけですが、文字描画以外まったく出来ないのかも、、、) (GNURX版のことです。CC-RX版はもともとCC-RXの無償評価版のサイズ制限を超えてしまっていますので、当方ではCC-RX版の動作確認は出来ていません。)

    今のところ気付いた回避策は以下の通りです。

    (1) 2D描画アクセラレータ(DRW2DやD/AVE 2Dなどと表記されている機能)を使わない設定にする
    (2) あるいは、GNURXのコンパイラ設定で最適化オプションを -Os → -O0 と変更する

    予感としては、FITモジュールでソース提供されている2D描画アクセラレータサポートソースにコンパイラ移植問題が潜んでいるのではないだろうか、という気がします。おいおい調べて行きます。

  • こんにちは。NoMaYです。

    2D描画アクセラレータが動いてくれないというのはIAR EWRXでもあったようです。emWinでは無くて他のグラフィックソフトですけれども。なお、スレッド内では解決に至っていませんでした。

    The DRW2D on RX651 platform does not fill the framebuffer memory with the display list instructions
    asked Feb 23, 2021 in System Integration by nsk515
    ask.embedded-wizard.de/5371/drw2d-rx651-platform-framebuffer-memory-display-instructions

    [メモ]

    他には関連の深そうなのはありませんでしたけれどもメモとして残しておきます。(関連の少なそうなのも残しておきます。)

    Search results for Renesas - Ask Embedded Wizard
    ask.embedded-wizard.de/search?q=Renesas

    The View::Frame is displayed with incorrect color on target device
    asked Feb 12, 2021 in GUI Development by Vikas Rokade
    ask.embedded-wizard.de/5333/the-view-frame-displayed-with-incorrect-color-target-device
     

  • こんにちは。NoMaYです。

    FITモジュールでソース提供されている2D描画アクセラレータサポートソースには、大別して、以下の2つのフォルダがあるのですけれども、フォルダに対する個別コンパイルオプション設定で(1)の方に-Osを設定すると誤動作するようになりますね。(言い換えると(2)の方を-Osにしても誤動作しませんでした。)

    (1) src/smc_gen/r_drw2d_rx/src/rx/
    (2) src/smc_gen/r_drw2d_rx/src/tes/

    以下、e2 studioの画面コピーです。


     

  • こんにちは。NoMaYです。

    更にソースを絞り込もうとして、下の画面コピーのように以下のソースに対して個別コンパイルオプション設定で-Osを設定したところ誤動作するようになりました。

    ● src/smc_gen/r_drw2d_rx/src/rx/dave_base_rx.c

    ソースやコンパイルリストファイルと睨めっこして気付いたのは、以下の3つの関数でvolatileが抜けているのでは?という点でした。試しに赤文字箇所にてvolatileを補ってやると動作するようになりました、、、

    /***********************************************************************
     * Function Name: d1_mstp_set
     * Description  : Write the MSTP register.
     * Arguments    : enable
     *                    Enable or disable the register bit.
     *                mstp_char
     *                    MSTP register offset position.
     *                mstp_num
     *                    The register bit position.
     * Return Value : none
     **********************************************************************/
    static void d1_mstp_set(bool enable, int mstp_char, int mstp_num)
    {
        volatile unsigned long *p_mstp_addr;

        /* The address offset from the address of the base register is cast to match the size of the register. */
        p_mstp_addr = ((volatile unsigned long *)MSTP_0_BASE) + mstp_char;

        if (true == enable)
        {
            *p_mstp_addr = ((*p_mstp_addr) & (~(1 << mstp_num)));
        }
        else
        {
            *p_mstp_addr = ((*p_mstp_addr) | (1 << mstp_num));
        }
    } /* End of function d1_mstp_set() */

    /***********************************************************************
     * Function Name: d1_registerprotectenable
     * Description  : Enable protect bit 1 of PRCR register.
     * Arguments    : none
     * Return Value : none
     **********************************************************************/
    static void d1_registerprotectenable()
    {
        volatile unsigned short *p_prcr_addr;

        /* The address of the base register is cast to match the size of the register. */
        p_prcr_addr = (volatile unsigned short *)PRCR_0_BASE;
        *p_prcr_addr = (((*p_prcr_addr) | PRCR_KEY) & (~PRCR_PRC1));
    } /* End of function d1_registerprotectenable() */

    /***********************************************************************
     * Function Name: d1_registerprotectdisable
     * Description  : Disable protect bit 1 of PRCR register.
     * Arguments    : none
     * Return Value : none
     **********************************************************************/
    static void d1_registerprotectdisable()
    {
        volatile unsigned short *p_prcr_addr;

        /* The address of the base register is cast to match the size of the register. */
        p_prcr_addr = (volatile unsigned short *)PRCR_0_BASE;
        *p_prcr_addr = (((*p_prcr_addr) | PRCR_KEY) | PRCR_PRC1);
    } /* End of function d1_registerprotectdisable() */

     
    以下、e2 studioの画面コピーです。


     

  • こんにちは。NoMaYです。

    > ソースやコンパイルリストファイルと睨めっこして気付いたのは、以下の3つの関数でvolatileが抜けているのでは?という点でした。試しに赤文字箇所にてvolatileを補ってやると動作するようになりました、、、

    くだんのvolatileを補う前と後でコンパイルリストファイルを比べてみました。なお、GNURXでは(そもそもはGCCに由来して?)最適化において関数の自動インライン展開がCC-RXより積極的に行われるような印象があるのですが、今回もvolatileを補った関数は呼び出し元の関数(及びもうひとつ別の関数)に自動インライン展開されています。

    それで何が起こっていたかというと、自動インライン展開された結果、コンパイラから見ると以下の3行が順番に行われているように見えていたと思われますが、volatileが無い場合は1行目の書き込み処理は実行する必要が無い(3行目でも同じ場所に書き込んでいるから1行目の書き込みは無意味)と判断されているようです。

       *p_prcr_addr = (((*p_prcr_addr) | PRCR_KEY) | PRCR_PRC1);
       *p_mstp_addr = ((*p_mstp_addr) & (~(1 << mstp_num)));
       *p_prcr_addr = (((*p_prcr_addr) | PRCR_KEY) & (~PRCR_PRC1));

     
    以下、呼び出し元の関数とコンパイルリストファイル(赤文字箇所(特に赤太文字箇所)の有無に注目)です。

    src/smc_gen/r_drw2d_rx/src/rx/dave_base_rx.c

    d1_device * d1_opendevice(long flags)
    {
        略

        /* apply power to peripheral */
        d1_registerprotectdisable();
        d1_mstp_set (true, MSTP_C, DAVE2D_MSTP_NUM);
        d1_registerprotectenable();

        略    /* reset irq handlers */
    }

     
    volatileなしの場合 (見易くする為に生のコンパイルリストファイルをかなり加工しています)

     215:../src/smc_gen/r_drw2d_rx/src/rx/dave_base_rx.c ****     *p_prcr_addr = (((*p_prcr_addr) | PRCR_KEY) | PRCR_PRC1);
      40 0010 FB 3E FE 03 08                mov.L   #0x803fe, r3
      41 0015 DC 35                         mov.W   [r3], r5

     180:../src/smc_gen/r_drw2d_rx/src/rx/dave_base_rx.c ****         *p_mstp_addr = ((*p_mstp_addr) & (~(1 << mstp_num)));
      55 0017 FB 2E 18 00 08                mov.L   #0x80018, r2
      57 001c EC 24                         mov.L   [r2], r4
      58 001e 7B C4                         bclr    #28, r4
      60 0020 E3 24                         mov.L   r4, [r2]

     199:../src/smc_gen/r_drw2d_rx/src/rx/dave_base_rx.c ****     *p_prcr_addr = (((*p_prcr_addr) | PRCR_KEY) & (~PRCR_PRC1));
      74 0022 76 25 FD 5A                   and #0x5afd, r5
      75 0026 76 35 00 A5                   or  #-23296, r5
      77 002a D3 35                         mov.W   r5, [r3]

     
    volatileありの場合 (見易くする為に生のコンパイルリストファイルをかなり加工しています)

     215:../src/smc_gen/r_drw2d_rx/src/rx/dave_base_rx.c ****     *p_prcr_addr = (((*p_prcr_addr) | PRCR_KEY) | PRCR_PRC1);
      40 0010 FB 4E FE 03 08                mov.L   #0x803fe, r4
      41 0015 DC 45                         mov.W   [r4], r5
      43 0017 76 35 02 A5                   or  #-23294, r5
      44 001b D3 45                         mov.W   r5, [r4]

     180:../src/smc_gen/r_drw2d_rx/src/rx/dave_base_rx.c ****         *p_mstp_addr = ((*p_mstp_addr) & (~(1 << mstp_num)));
      58 001d FB 3E 18 00 08                mov.L   #0x80018, r3
      59 0022 EC 35                         mov.L   [r3], r5
      61 0024 7B C5                         bclr    #28, r5
      63 0026 E3 35                         mov.L   r5, [r3]

     199:../src/smc_gen/r_drw2d_rx/src/rx/dave_base_rx.c ****     *p_prcr_addr = (((*p_prcr_addr) | PRCR_KEY) & (~PRCR_PRC1));
      77 0028 DC 45                         mov.W   [r4], r5
      79 002a 7A 15                         bclr    #1, r5
      80 002c 76 35 00 A5                   or  #-23296, r5
      82 0030 D3 45                         mov.W   r5, [r4]

     

  • こんにちは。NoMaYです。

    volatileが抜けている、ということからすれば、CC-RXでも何かしらの最適化設定において誤動作するのではないだろうか、と気になりましたので、CC-RXであれこれやってみました。当方の手元ではCC-RXの無償評価版のサイズ制限を超えてしまっている事情で動作/非動作の確認まで出来ていませんが、コンパイルリストファイルからの推測では -optimize=max -speed で問題が発生してもおかしくない気がします。なお、CC-RXではvolatile抜けというより__evenaccess抜けと考えるのが良さそうです。

    何が起きるかというと、以下のように32ビット長のmstpレジスタの1つに8ビット長でリードモデファイライトしてしまいます。

    自動インライン展開された結果として、コンパイラに見えているであろう処理

        *p_prcr_addr = (((*p_prcr_addr) | PRCR_KEY) | PRCR_PRC1);
        *p_mstp_addr = ((*p_mstp_addr) & (~(1 << mstp_num)));
        *p_prcr_addr = (((*p_prcr_addr) | PRCR_KEY) & (~PRCR_PRC1));

     
    最適化オプション -optimize=max -speed でのコンパイルリストファイルから抽出したコード(ソースと対応するよう色分け)

    00000014 FB5EFE0308  MOV.L #000803FEH, R5
    00000019 DC5F        MOV.W [R5], R15
    0000001B FBEE1B0008  MOV.L #0008001BH, R14
    00000020 773F02A500  OR #0A502H, R15
    00000025 D35F        MOV.W R15, [R5]
    00000027 F0EC        BCLR #04H, [R14].B ← 32ビット長のmstpレジスタの1つに8ビット長でリードモデファイライトする
    00000029 DC5E        MOV.W [R5], R14
    0000002B 773E00A500  OR #0A500H, R14
    00000030 772EFDFF00  AND #0FFFDH, R14
    00000035 D35E        MOV.W R14, [R5]

     
    [追記]

    上記の最適化オプションでソースに__evenaccessを補った場合: 緑字のソース行は無意味と判断されコード生成されていない

    00000014 FB4E180008  MOV.L #00080018H, R4
    00000019 EC45        MOV.L [R4], R5
    0000001B FBFEFE0308  MOV.L #000803FEH, R15
    00000020 DCFE        MOV.W [R15], R14
    00000022 7BC5        BCLR #1CH, R5
    00000024 773E00A500  OR #0A500H, R14
    00000029 772EFDFF00  AND #0FFFDH, R14
    0000002E E345        MOV.L R5, [R4]
    00000030 D3FE        MOV.W R14, [R15]

     
    上記の最適化オプションでソースに__evenaccess volatileを補った場合: 問題無いと思われる

    00000014 FB5EFE0308  MOV.L #000803FEH, R5
    00000019 DC5E        MOV.W [R5], R14
    0000001B FBFE180008  MOV.L #00080018H, R15
    00000020 773E02A500  OR #0A502H, R14
    00000025 D35E        MOV.W R14, [R5]
    00000027 ECFE        MOV.L [R15], R14
    00000029 7BCE        BCLR #1CH, R14
    0000002B E3FE        MOV.L R14, [R15]
    0000002D DC5E        MOV.W [R5], R14
    0000002F 773E00A500  OR #0A500H, R14
    00000034 772EFDFF00  AND #0FFFDH, R14
    00000039 D35E        MOV.W R14, [R5]

     
    ソース(なお__evenaccessとvolatileの記述場所はiodefine.hに合わせました)

    static void d1_mstp_set(bool enable, int mstp_char, int mstp_num)
    {
        volatile unsigned long __evenaccess *p_mstp_addr;

        /* The address offset from the address of the base register is cast to match the size of the register. */
        p_mstp_addr = ((volatile unsigned long __evenaccess *)MSTP_0_BASE) + mstp_char;

        if (true == enable)
        {
            *p_mstp_addr = ((*p_mstp_addr) & (~(1 << mstp_num)));
        }
        else
        {
            *p_mstp_addr = ((*p_mstp_addr) | (1 << mstp_num));
        }
    } /* End of function d1_mstp_set() */

    static void d1_registerprotectenable()
    {
        volatile unsigned short __evenaccess *p_prcr_addr;

        /* The address of the base register is cast to match the size of the register. */
        p_prcr_addr = (volatile unsigned short __evenaccess *)PRCR_0_BASE;
        *p_prcr_addr = (((*p_prcr_addr) | PRCR_KEY) & (~PRCR_PRC1));
    } /* End of function d1_registerprotectenable() */

    static void d1_registerprotectdisable()
    {
        volatile unsigned short __evenaccess *p_prcr_addr;

        /* The address of the base register is cast to match the size of the register. */
        p_prcr_addr = (volatile unsigned short __evenaccess *)PRCR_0_BASE;
        *p_prcr_addr = (((*p_prcr_addr) | PRCR_KEY) | PRCR_PRC1);
    } /* End of function d1_registerprotectdisable() */

     
    [追記2]

    上記の最適化オプションでソースにvolatileのみ補った場合: 問題ありと思われる

    00000014 FB5EFE0308  MOV.L #000803FEH, R5
    00000019 DC5E        MOV.W [R5], R14
    0000001B FBFE1B0008  MOV.L #0008001BH, R15
    00000020 773E02A500  OR #0A502H, R14
    00000025 D35E        MOV.W R14, [R5]
    00000027 58FE        MOVU.B [R15], R14 ← 32ビット長のmstpレジスタの1つに8ビット長でリードする
    00000029 762EEF00    AND #0EFH, R14
    0000002D C3FE        MOV.B R14, [R15] ← 32ビット長のmstpレジスタの1つに8ビット長でライトする
    0000002F DC5E        MOV.W [R5], R14
    00000031 773E00A500  OR #0A500H, R14
    00000036 772EFDFF00  AND #0FFFDH, R14
    0000003B D35E        MOV.W R14, [R5]


    上記の最適化オプションでソースにvolatileのみ補い且つコンパイルオプションに-type_size_access_to_volatileを追加した場合: 問題無いと思われる

    00000014 FB5EFE0308  MOV.L #000803FEH, R5
    00000019 DC5E        MOV.W [R5], R14
    0000001B FBFE180008  MOV.L #00080018H, R15
    00000020 773E02A500  OR #0A502H, R14
    00000025 D35E        MOV.W R14, [R5]
    00000027 ECFE        MOV.L [R15], R14
    00000029 7BCE        BCLR #1CH, R14
    0000002B E3FE        MOV.L R14, [R15]
    0000002D DC5E        MOV.W [R5], R14
    0000002F 773E00A500  OR #0A500H, R14
    00000034 772EFDFF00  AND #0FFFDH, R14
    00000039 D35E        MOV.W R14, [R5]

     
    [関連リンク]

    CC-RXでvolatile指定有り__evenaccess指定無しのobjectへのaccess sizeが保証されないのは言語規格上妥当なのかな?
    japan.renesasrulz.com/cafe_rene/f/forum5/5094/cc-rx-volatile-__evenaccess-object-access-size
     

  • こんにちは。NoMaYです。

    完全に脱線しますけれども、CC-RXには -volatile 及び -type_size_access_to_volatile という以下のヘルプの画面コピーのコンパイルオプションがあります。まったくの好奇心からですが、くだんのソースに volatile も __evenaccess も付けずに、果たして、この2つのコンパイルオプションを付けたらどうなるか試してみました。もっとも、以下のような理由で思惑通りにならないだろうなぁ、とは思いつつですけれども。結果は、やはり問題ありでした。

    (1) ソース上で `外部変数` として宣言してあるわけでは無いので(単に絶対アドレスを代入したポインタの先なので)、そもそも -volatile は作用しない
    (2) ソース上に `volatile` が記述されているわけでは無いので(且つ上記(1)もあり)、それでは  -type_size_access_to_volatile が作用しようがない

    以下、最適化オプション -optimize=max -speed でのコンパイルリストファイルから抽出したコードです。(先日のソースと対応するよう色分けしています。)
    なお、ソースには volatile も __evenaccess も付けない、ようにしてあります。
    他方、コンパイルオプションに -volatile 及び -type_size_access_to_volatile を付ける、ようにしてあります。

    00000014 FB5EFE0308  MOV.L #000803FEH, R5
    00000019 DC5F        MOV.W [R5], R15
    0000001B FBEE1B0008  MOV.L #0008001BH, R14
    00000020 773F02A500  OR #0A502H, R15
    00000025 D35F        MOV.W R15, [R5]
    00000027 F0EC        BCLR #04H, [R14].B ← 32ビット長のmstpレジスタの1つに8ビット長でリードモデファイライトする
    00000029 DC5E        MOV.W [R5], R14
    0000002B 773E00A500  OR #0A500H, R14
    00000030 772EFDFF00  AND #0FFFDH, R14
    00000035 D35E        MOV.W R14, [R5]

     
    以下、CC-RXのヘルプの画面コピーです。



     

  • こんにちは。NoMaYです。

    コンパイルオプションに関して別の話になりますが、以下のアプリケーションノートでは、CC-RXの場合として(というか実はCC-RXの場合しか対象にしていないのですけれども) -nostuff=C を設定するように指示しています。実は今のところ、GNURXの場合に相応する設定をどうすれば良いのか考えが思い浮かんでいません。

    今のFITモジュールは基本的にCC-RX/GNURX/ICCRXの3つのコンパイラに対応した共通ソースかつ同一処理になっていますので、CC-RXでそのような特殊な設定が必要となるコーディングが行われているなら、他の2つのコンパイラにおいて悪影響を与える可能性が高い筈なのです。

    ということで、以下の流れで、その設定が指示されている原因を調べてみようかと思います。

    (1) 描画に関係する各FITモジュールのドキュメントを確認して、どのFITモジュールに由来するのか把握する
    (2) そのFITモジュールのソースコードを調べて、該当箇所を特定する
    (3) GNURX(やICCRX)の場合にはどうすれば良いのか考える

    RXファミリ QE for Display [RX] アプリケーションノート
    R20AN0582JJ0121 Rev.1.21 Pages 141 May.26.21
    www.renesas.com/jp/ja/document/apn/rx-family-qe-display-rx-application-note#page=62
    画面コピー

     

  • こんにちは。NoMaYです。

    最新のRX Driver Package V1.35(今月リリース済み)に含まれるFITモジュールでQE for Displayのプロジェクトを構成すると描画に関係するFITモジュールは以下のとおりになるのですが、それらのドキュメントにはCC-RXの場合に -nostuff=C を設定するよう指示しているものはありませんね、、、

    ・ GLCDCモジュール V1.50
    ・ DRW2Dモジュール V1.11
    ・ emWinモジュール V6.22.1.00

    [追記]

    すみません、emWinモジュールに記載がありました、、、

    [ここまで追記]

    以下、ドキュメントの画面コピーです。







    [追記]