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さん

    シェルティです、こんにちは。

    すみません、読み間違えました。フレームバッファをマルチ化する方法ではなく、シングル化をする方法をご質問いただいていますね。上記説明でマルチ化をしない設定にする(2022/08/30時点のQE for Displayだとバッファアドレスを2個指定してもシングルになります)とシングル化できます。

    カギは上記URLで示したAPPWConf.cの179行目の変数が入力となる231行目のAPPW_MULTIBUF_Enable(_MultibufEnable);ですね。

    以上です

  • シェルティさん、こんにちは。NoMaYです。

    リプライありがとうございました。ナント、私が先日投稿したzipファイルのソースでは、既に以下のコードになっていてフレームバッファを1面しか使わない設定になっていました。(GCC版もCC-RX版も同一。) たまたま残っていたバックアップソースを過去に遡ると、先日の私の場合は、まずGCC向けにプロジェクトを作成してQE for Displayで設定していきましたので、QE for DisplayのGCC向けモードのバグか何かを踏んでしまったのかもしれません。(そしてそれを丸っとCC-RX向けプロジェクトにコピペしてCC-RX向けのプロジェクトを調整していったので両方とも変になっていたのかも知れません。) 後日、CC-RX向けのプロジェクトから作成してみる手順を試してみようかと思います。

    /*********************************************************************
    *
    *       Multibuffering
    */
    static U8 _MultibufEnable = 0;

     
    [追記]

    あっ、ひょっとして、「2022/08/30時点のQE for Displayだとバッファアドレスを2個指定してもシングルになります」というのは、AppWizard側で結局上記ソースとなって1面しか使われないです、という意味でしたでしょうか、、、

  • NoMaYさん

    シェルティです、こんにちは。

    ご推察の通りと思います。[追記]のご質問の回答もYesです。現状のQE for Displayだとシェルティの手元でも手動で_MultibufEnable の値を1にしないとマルチバッファになりませんでした。

    NoMaYさんの作られたファイルの中身までは確認しておらずお手間おかけしました。シェルティもNoMaYさんと同じロジックで「マルチバッファの扱いがなんか変だ」とたどり着き、QE for Displayの開発チーム、emWinの移植チーム、GLCDC/DRW2Dのドライバ開発チームに聞いてみたところ、マルチバッファの扱いは次版QE for Displayで修正すると聞きました。もう一度開発チームにこのスレッドを読んでもらってシェルティが何か変なことを言ってないか確認してもらおうと思います。

    以上です

  • NoMaYさん

    シェルティです、こんにちは。

    聞いてみたところ、Segger本社にお願いしてAppWizard側でマルチバッファの有効・無効のチェックボックスを追加してもらうとのことでした。QE for Displayも次版でこれに対応します。

    と書いていて思いだしましたが、数日前に上記を聞いたあとに、AppWizard最新版(V130_626d)をダウンロードしてみて、以下のようにマルチバッファののチェックボックスが増えているのを自分で確認したのでした。

    以上です

  • シェルティさん、こんにちは。NoMaYです。

    リプライありがとうございました。そういうことだったのですね。その他に、私の気の付いたこととして以下があります。次版(次々版以降?)の改善項目案のリストに加えて頂ければと思います。

    ● GCCの場合にリンカスクリプトでLCDフレームバッファの領域を避けるようにリンカスクリプトを変更する処置が無かったです

    CC-RXの場合には、rlinkのオプション設定でLCDフレームバッファの領域を避けるように.cprojectが変更されました。それに対し、GCCの場合には、リンカスクリプトが変更されていませんでした。(別スレッドにてリューキィさんから受け取ったリンカスクリプトで変更されてなかったので私の記憶違いでは無いと思うのです。)

    GCCの場合にそうであるならば、IARコンパイラの場合にも、そうかも知れません。もっとも、EWRX向けのQEというものはそもそも存在していない気がしますので、あくまでe2 studio上にてICCRX+QE for Displayを使う場合の話ですけれども。(余力が無かったのでICCRXは試さなかったです。)

  • NoMaYさん

    シェルティです、こんにちは。

    ありがとうございます。いただいた点を改善項目案のリストに追加しておきます。

    個人的にもGCC環境をもっとしっかり整備したいと感じております。私自身学生時分に純正コンパイラが購入できず、GCC環境で自作のモニタプログラムを作ってH8マイコンでなにか作って遊んでました。その後H8マイコンの会社(ルネサス)に入り込み、少しGCC環境を公式に広げる(IDEからGCCを選べるようにしたりとか)ことができたようにも思いますが、もっと裾野を広げるために引き続きGCC環境を推してまいります。一方でお客様の量産製品開発では純正コンパイラやIARコンパイラを使うユーザも多くいますので、分け隔てなく整備していければ、と思っています。

    以上です

  • こんにちは。NoMaYです。

    エンビテック社のドキュメントがアップデートされていました。

    スタートアップガイド:RX65N/RX72N Envision キット用 emWin デモサンプル
    更新日:2022年9月
    www.embitek.co.jp/technote/emwin/StartupGuide_emWin_EnvisionKit.pdf


    [関連リンク]

    emWin GUI  - エンビテック
    www.embitek.co.jp/product/emwin.html

    emWin for RX - エンビテック
    www.embitek.co.jp/renesas/emwin-rx.html

    [追記]

    Renesasマイコンデバイスの評価ボード用のRTOS及びミドルウェアソフトウェア製品の評価版は無償で提供しています。
    www.embitek.co.jp/download/evalsamples/renesas/

    RZ/A1H RSK
    www.embitek.co.jp/download/evalsamples/renesas/rza1h-rsk/
    SeggerEval_R7S72100_Renesas_RSK_RZA1H_ARM_SES_COMPRESS_FS_GUI_IOT_IP_MB_OS_SECURE_SSH_SSL_USB_USBH_190411.zip

    RZA1LU Stream it!
    www.embitek.co.jp/download/evalsamples/renesas/rz-stream-it/
    RZA1_Stream_it_sample.zip

  • こんにちは。NoMaYです。

    フォントデータとかでもCPUが直接データにアクセス可能になるものなのかなぁ、、、

    マイコンのコード領域を簡単に拡張可能!QSPI XIP モードを使用したシリアル ROM 上のプログラム実行例の紹介
    www.renesas.com/jp/ja/blogs/easy-expansion-mcu-code-area-introducing-example-program-execution-serial-rom-using-qspi-xip-mode

    このモードをサポートしているマイコンとシリアルフラッシュを使用すれば、MCUのアドレス空間にマッピングしてアクセス可能となり、CPUが直接コードにアクセス可能になります。


  • こんにちは。NoMaYです。

    少し前の話になってしまいますが、FIT emWin v6.26モジュールがリリースされていますね。他方、まだ新しいRX Driver Packageは出ていないようです。ですので、今のところ、単体のFIT emWin v6.26モジュールをダウンロードして組み込む必要があります。以下のルネサスさんのURLからでもダウンロード出来ますが、RXスマートコンフィグレータ上でもダウンロード出来ます。(まだ私は試していないです。)

    それとは関連が無いのですけれども、emWin内でheapの確保に失敗した時に失敗したことがどのようにユーザに通知されるのか、ちょっと調べてみようと思います。あと、FreeRTOS使用時にheapの確保/開放を安全に行う仕組みがどうなっているのか(emWinが安全に行う為にユーザがemWinに対して何をする必要があるのか)、これもちょっと調べてみようと思います。

    RXファミリ emWin v6.26 モジュール Firmware Integration Technology Rev.1.00

    PDF
    https://www.renesas.com/jp/ja/document/apn/rx-family-emwin-v626-module-using-firmware-integration-technology

    ZIP
    www.renesas.com/jp/ja/document/scd/rx-family-emwin-v626-module-using-firmware-integration-technology-sample-code
     

  • こんにちは。NoMaYです。

    最近またソースコードを見ていたのですけれども、以下のようなコードは、タスク切り替えや(多重割り込み含めて)割り込みに対して危険ですね。(以下のコード自体は、起動時の初期化で呼ばれるだけだろうと思いますので、危険度は高くは無いだろうと思いますけれども。) 以下は、FIT emWin v6.22モジュールのソースです。

    人類の知性には、プログラムを最初からちゃんと考えて書く、という課題は早過ぎるのではないでしょうかね。宇宙銀河連邦(そういうものがあるとして)に人類が加盟出来るようになるのと、どっちが先になるでしょうかね。

    src/smc_gen/r_drw2d_rx/src/rx/dave_irq_rx.c

    /***********************************************************************
     * Function Name: d1_ien_set
     * Description  : Write the IER register.
     * Arguments    : enable
     *                    Enable or disable the register bit.
     *                vector
     *                    Interrupt vector number.
     * Return Value : none
     **********************************************************************/
    static void d1_ien_set(bool enable, int vector)
    {
        unsigned char *p_ien_addr;
        unsigned char tmp_ier;
        unsigned char tmp_ien;

        tmp_ier = vector / 8;
        tmp_ien = vector % 8;

        /* The address offset from the address of the base register is cast
    to match the size of the register. */
        p_ien_addr = ((unsigned char *)IEN_0_BASE) + tmp_ier;

        if (true == enable)
        {
            *p_ien_addr = ((*p_ien_addr) | (1 << tmp_ien));
        }
        else
        {
            *p_ien_addr = ((*p_ien_addr) & (~(1 << tmp_ien)));
        }
    } /* End of function d1_ien_set() */

     

    /***********************************************************************
     * Function Name: d1_genal1_set
     * Description  : Write the GENAL1 register.
     * Arguments    : enable
     *                    Enable or disable the register bit.
     *                grp_num
     *                    The register bit position.
     * Return Value : none
     **********************************************************************/
    static void d1_genal1_set(bool enable, int grp_num)
    {
        unsigned long *p_genal1_addr;

        /* The address of the base register is cast to match the size of the register. */
        p_genal1_addr = ((unsigned long *)GENAL1_0_BASE);

        if (true == enable)
        {
            *p_genal1_addr = ((*p_genal1_addr) | (1 << grp_num));
        }
        else
        {
            *p_genal1_addr = ((*p_genal1_addr) & (~(1 << grp_num)));
        }
    } /* End of function d1_genal1_set() */

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

    /***********************************************************************
     * 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 R_BSP_EVENACCESS_SFR *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 R_BSP_EVENACCESS_SFR *)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 R_BSP_EVENACCESS_SFR *p_prcr_addr;

        /* The address of the base register is cast to match the size of the register. */
        p_prcr_addr = (volatile unsigned short R_BSP_EVENACCESS_SFR *)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 R_BSP_EVENACCESS_SFR *p_prcr_addr;

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

     
    [追記]

    修正案は、以下ではないかなぁ、と思います。

    (1) ビット操作はビット操作命令を使うコードに書き換える。(ビット操作命令を使う組み込みライブラリ関数でも可。)
    (2) レジスタライトプロテクトの解除操作/再開操作はgetpsw(),clrpsw_i(),setpsw_i()で大域的に割り込み不可にする。
    (2') それだけでは不十分かも?、、、一連の動作全体を何かで保護しないといけない?、、、
    (2'-1) タスク切り替えが起きないようにする。
    (2'-2) 割り込み処理中で2重に解除操作/再開操作をしてしまわないようにするカラクリも用意する。(BSPのAPIとする。)
    (2'-3) 一連の動作全体を大域的に割り込み不可にしてしまうという手も無くは無いけれども。

    [追記]

    RXマイコンではIRレジスタに1を書き込むことは出来ないです。(レベル割り込みでは0を書き込むことも出来ないです。)

    src/smc_gen/r_drw2d_rx/src/rx/dave_irq_rx.c

    /***********************************************************************
     * Function Name: d1_ir_set
     * Description  : Write the IR register.
     * Arguments    : enable
     *                    Enable or disable the register bit.
     *                vector
     *                    Interrupt vector number.
     * Return Value : none
     **********************************************************************/
    static void d1_ir_set(bool enable, int vector)
    {
        unsigned char *p_ir_addr;

        /* The address offset from the address of the base register is cast
    to match the size of the register. */
        p_ir_addr = ((unsigned char *)IR_0_BASE) + vector;

        if (true == enable)
        {
            *p_ir_addr = 1;
        }
        else
        {
            *p_ir_addr = 0;
        }
    } /* End of function d1_ir_set() */