Github/RX にプルリクが来たので、それの対応など

最適化をしないコンパイル

現在(少し前)のフレームワークでは、最適化をしない「-O0」場合、大量にリンクで失敗する。

これは、「static」なオブジェクトの実態が無い為で、以前は最適化が標準となっているので、あまり問題にならなかった。
※static なオブジェクトと言っても、リソースを必要とするような実装は無く、最適化すると、実態を持たないものだった。

それでも、最適化しない場合、実態は必ず必要なので、リンクできずに実行バイナリーを作れず停止する。

たとえば、このような感じ・・・

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    /*!
        @brief  CMT 定義基底クラス
        @param[in]  base    ベース・アドレス
        @param[in]  per     ペリフェラル
        @param[in]  VEC     ベクター型
        @param[in]  ivec    割り込みベクター
    */
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    template <uint32_t base, peripheral per, typename VEC, VEC ivec>
    struct cmt_t {

...

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        /*!
            @brief  CMCR レジスタ
            @param[in]  ofs     レジスタ・オフセット
        */
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
       template <uint32_t ofs>
        struct cmcr_t : public rw16_t<ofs> {
            typedef rw16_t<ofs> io_;
            using io_::operator =;
            using io_::operator ();
            using io_::operator |=;
            using io_::operator &=;

            bits_rw_t<io_, bitpos::B0, 2> CKS;
            bit_rw_t <io_, bitpos::B6>    CMIE;
        };
        static cmcr_t<base + 0x00> CMCR;

...

    };

    typedef cmt_t<0x00088002, peripheral::CMT0, ICU::VECTOR, ICU::VECTOR::CMI0> CMT0;

「CMCR」は、「cmcr_t」テンプレートクラスの「static」オブジェクトとなっている。

このオブジェクトは、「cmt_t」テンプレートクラスのメンバーで、実際には、「実態」となる物を定義する必要がある。

これが、テンプレートクラスでは無い場合、別にソースコードを作成して、その中で、staticなオブジェクトとして宣言しておく。

テンプレートクラスの場合、それはできないので、ヘッダーに特殊な書き方で定義する。

        typedef cmcr_t<base + 0x00> CMCR_;
        static CMCR_ CMCR;
    };

    template <uint32_t base, peripheral per, typename VEC, VEC ivec>
        typename cmt_t<base, per, VEC, ivec>::CMCR_ cmt_t<base, per, VEC, ivec>::CMCR;

上記のように、定義には、「CMCR」オブジェクトの型「cmtt<base, per, VEC, ivec>::CMCR」が必要なので、ペリフェラルの定義全部を大幅に書き換える必要がある。

何度か、修正しようと思った事もあったが、修正範囲が広く、自分には、それほど必要な機能でも無かったので、割愛してきた。

しかし、「-O0」にしないと、デバッガーで止めたりできないとの事で、この莫大な修正を行い、プルリクを送ってくれた方がいたので、このリクエストを受けて、マージする事にした。
※非常にありがたい修正で、修正したソースの分量もすさまじく、この修正を入れる事で、より良い物になるのは明白だ。

ただ、最近、RX72Nの為に色々と、改変している最中で、そのままマージしても、コンフリクトする事は明白なので、内容を精査しながら少しづつマージする事にした。

このプルリクを送ってくれた「Sinsjr2」さんには大変感謝しており、この場を借りて御礼申し上げます。

※自分以外でこのフレームワークを使っている人は、何人くらいいるのだろうか?
少なくとも一人はいる事が判ったw


普通のクラスをテンプレートクラスにするメリット

先ほどの説明で、static なオブジェクトの実態について、通常のクラスの場合は、別にソースを作成して記述する事を説明した。

しかしながら、そうすると、ヘッダーの他にソースコードが増えて、Makefile でソースを列挙する必要が出てくる。

これを回避する方法がある。

普通のクラスを無理やりテンプレートにする方法で、boost などでも使われている。

たとえば、以下のクラスをテンプレート化すると・・・

class flash_io
{

    flash_io() { }

};

template <class _> class flash_io_
{

    flash_io_() { }

};
typedef flash_io_<void> flash_io;

知ってはいたが、以前に実験した時、サイズが少しだけ大きくなるので、敬遠していた。
しかし、最近の RX マイコンは、サイズをあまり気にする程、ROM が小さくないので、存分に使うべきかもしれない・・


Makefile の機能追加

「make」は、「-e」オプションを使うと、外部から、内部で使っている環境変数をオーバーライド出来る。

  -e, --environment-overrides
                              環境変数が makefile 中の記述に優先する

たとえば、最適化は、

    OPTIMIZE = -O3

となっており、

W10./d/Git/RX/FIRST_sample/RX72N % make clean
W10./d/Git/RX/FIRST_sample/RX72N % export OPTIMIZE=-O0
W10./d/Git/RX/FIRST_sample/RX72N % make -e

とすれば、最適化無しで、コンパイルする事が出来る。

しかし、少し工夫して、「debug」と「release」と二つの状態を設ける事にした。
※「release」は元々固定となっている。

BUILD       =   release
#BUILD      =   debug

どちらかを有効にする事で、release(リリース版)と、debug(デバッグ版)を作成可能とした。
※事前に「clean」を行ってオブジェクトを全部廃棄する必要がある。
また、これは、変数をオーバーライド出来るので、「通常」を「release」としておく。

さらに、

ifeq ($(BUILD),debug)
    CC_OPT += -g -DDEBUG
    CP_OPT += -g -DDEBUG
    OPTIMIZE = -O0
endif

ifeq ($(BUILD),release)
    CC_OPT += -DNDEBUG
    CP_OPT += -DNDEBUG
    OPTIMIZE = -O3
endif

BUILD 変数により、オプションをいくつか追加している。

これで、かなり自由にオブジェクトの生成を制御できるようになった。


全体ビルドシェルコマンドの強化

プロジェクトは、最近はかなり大きくなっており、サンプルの数も増えて、メンテナンスに苦労が多い。

そこで、ディレクトリーを巡回して、「Makefile」を見つけたら、「make」を起動するスクリプトを shell で作成してある。

W10./d/Git/RX % sh all_project_build.sh help
Usage: all_project_build.sh options [clean]
    -debug      debug build, 'OPTIMIZE=-O0'

このスクリプトに「-debug」オプションを追加してある。


RX600 ディレクトリの「最適化無し」対応状況

2020-04-24 07:14:47 Friday

ファイル 対応 ファイル 対応 ファイル 対応 ファイル 対応
bus.hpp O cmt.hpp O dmac.hpp O icu.hpp O
cac.hpp O can.hpp O cmpc.hpp O cmtw.hpp O
crc.hpp O crca.hpp O doc.hpp O drw2d.hpp O
dsmif.hpp O dtc.hpp O edmac.hpp O elc.hpp O
eptpc.hpp O etherc.hpp O exdmac.hpp O flash.hpp O
glcdc.hpp O gpt.hpp O iwdt.hpp O lvda.hpp O
mmcif.hpp O mpc.hpp O mpu.hpp O mtu3.hpp O
pdc.hpp O pmgi.hpp O poe3.hpp O port.hpp O
ppg.hpp O qspi.hpp O r12da.hpp O riic.hpp O
rspi.hpp O rtc.hpp O s12adc.hpp O sci.hpp O
scif.hpp O sdhi.hpp O sdram.hpp - sdsi.hpp #
src.hpp O ssi.hpp O ssie.hpp O system.hpp O
tmr.hpp O tpu.hpp O usb.hpp O usba.hpp O
wdta.hpp O

※ Ox:中途(現状、必要な部分だけ)
※ X 今後アップデート予定
※ # 実装中

最適化無しでコンパイル、リンク出来るプロジェクト

FIRST_sample
SCI_sample
SDCARD_sample
AUDIO_sample
FLASH_sample
RAYTRACER_sample
SIDE_sample
NESEMU_sample
FreeRTOS

主要なプロジェクトは大体大丈夫と思う。


自動変換スクリプト

複雑な構造の場合は、一筋ではいかないものの、簡単なスクリプトで変換は「できる」・・

s/static \(.*\) \([0-9A-Z]*\);/typedef \1 \2_;static \2_ \2;/
s/;static/;\
                static /

これは、sed による変換スクリプトで、static 宣言された行で、オブジェクト名を分けて、typedef、static を部分コピーする。
次に、行を分けて、二行にする。
※ただ、全てに対して上手くいく訳ではないのだが・・・

次にテンプレートクラスの実態を生成する。

/static.*;/!d
s/static/template <uint32_t base, peripheral per> typename glcdc_t<base, per>::/
s/_ /_ glcdc_t<base, per>::/

※これは、glcdc.hpp クラス用だ、テンプレートの型が違う場合に、微妙に作り替えないとならない・・・

それにしても sed は便利で強力なツールだ・・