ポート・マップ候補機能
- C++フレームワークでは、各ペリフェラルを扱う場合、どのポートを選択するかを、簡潔に扱う為に、「ポート・マップ候補機能」を導入しています
- 今まで、「候補」がどのポートを選択するかを知る為、各ソースコードを参照するようにとアナウンスしていました
- それを、少しだけ便利にする為、単純に、候補とポートの関係を表にして、各MPUのルートにある、README.md ファイルに集約するようにしました
- これは、ソースコードの修正とは、異なり、単なるドキュメントの更新なんだけど、分量がかなり多く、又、ピン番号も同時に記入してあるので、それなりに大掛かりな作業でした
- ピン番号は、良く使うであろう、パッケージだけに絞り、(例えば、64 ピン、100 ピン、144 ピンなど)全てを網羅している訳では無いのだけど・・・
- パッケージとピン番号の正確性は、ミスもあるかと思うので、実際に配線する前に確認が必要です
各CPUの特徴とリンクなど
現在サポートされ、動作確認済みデバイス:
| シリーズ | MinV | MaxV | MHz | コア | FPU | TFU | DFPU | 動作確認 | rx_prog | リンカーファイル | 
|---|---|---|---|---|---|---|---|---|---|---|
| RX110 | 1.8 | 3.6 | 32 | RXv1 | - | - | - | R5F51103/4/5 | ||
| RX111 | 1.8 | 3.6 | 32 | RXv1 | - | - | - | R5F51115/6/7 | ||
| RX113 | 1.8 | 3.6 | 32 | RXv1 | - | - | - | R5F51136/8 | ||
| RX130 | 1.8 | 5.5 | 32 | RXv1 | - | - | - | R5F51305/6 | ||
| RX140 | 1.8 | 5.5 | 48 | RXv2 | Yes | - | - | 〇 | 〇 | R5F51403/5/6 | 
| RX13T | 2.7 | 5.5 | 32 | RXv1 | Yes | - | - | R5F513T3/5 | ||
| RX210 | 1.62 | 5.5 | 32 | RXv1 | - | - | - | R5F52108/B | ||
| RX220 | 1.62 | 5.5 | 32 | RXv1 | - | - | - | 〇 | 〇 | R5F52206 | 
| RX231 | 1.8 | 5.5 | 54 | RXv2 | Yes | - | - | 〇 | 〇 | R5F52316/7/8 | 
| RX23T | 2.7 | 5.5 | 40 | RXv2 | Yes | - | - | R5F523T5 | ||
| RX24T | 2.7 | 5.5 | 80 | RXv2 | Yes | - | - | 〇 | 〇 | R5F524T8/A | 
| RX24U | 2.7 | 5.5 | 80 | RXv2 | Yes | - | - | R5F524UB/E | ||
| RX261 | 1.6 | 5.5 | 64 | RXv3 | Yes | ー | ー | R5F52618 | ||
| RX26T | 2.7 | 5.5 | 120 | RXv3 | Yes | V2 | ー | 〇 | 〇 | R5F526TF | 
| RX621 | 2.7 | 3.6 | 100 | RXv1 | Yes | - | - | 〇 | 〇 | R5F56218 | 
| RX62N | 2.7 | 3.6 | 100 | RXv1 | Yes | - | - | 〇 | 〇 | R5F562N7/8 | 
| RX631 | 2.7 | 3.6 | 100 | RXv1 | Yes | - | - | 〇 | 〇 | R5F5631F | 
| RX63N | 2.7 | 3.6 | 100 | RXv1 | Yes | - | - | 〇 | 〇 | R5F563NE | 
| RX63T | 3.3 | 5 | 100 | RXv1 | Yes | - | - | 〇 | 〇 | R5F563T6 | 
| RX64M | 2.7 | 3.6 | 120 | RXv2 | Yes | - | - | 〇 | 〇 | R5F564MF/G/J/L | 
| RX71M | 2.7 | 3.6 | 240 | RXv2 | Yes | - | - | 〇 | 〇 | R5F571MF/G/J/L | 
| RX651 | 2.7 | 3.6 | 120 | RXv2 | Yes | - | - | 〇 | 〇 | R5F5651E | 
| RX65N | 2.7 | 3.6 | 120 | RXv2 | Yes | - | - | 〇 | 〇 | R5F565NE | 
| RX66N | 2.7 | 3.6 | 120 | RXv3 | Yes | V1 | Yes | R5F566ND/N | ||
| RX660 | 2.7 | 5.5 | 120 | RXv3 | Yes | - | - | R5F56609 | ||
| RX671 | 2.7 | 5.5 | 120 | RXv3 | Yes | - | - | R5F5671C/E | ||
| RX72N | 2.7 | 3.6 | 240 | RXv3 | Yes | V1 | Yes | 〇 | △ | R5F572ND/N | 
| RX72M | 2.7 | 3.6 | 240 | RXv3 | Yes | V1 | Yes | △ | △ | R5F572MD/N | 
| RX66T | 2.7 | 5.5 | 160 | RXv3 | Yes | - | - | 〇 | 〇 | R5F566TA/E/F/K | 
| RX72T | 2.7 | 5.5 | 200 | RXv3 | Yes | V1 | - | 〇 | 〇 | R5F572TF/K | 
基本的な候補の使い方など
「候補」は以下のようになっています:
    enum class ORDER : uint8_t {
        BYPASS,         ///< ポートマップの設定をバイパスする場合
        FIRST,          ///< 第1候補
        SECOND,         ///< 第2候補
        THIRD,          ///< 第3候補
        FOURTH,         ///< 第4候補
        FIFTH,          ///< 第5候補
        SIXTH,          ///< 第6候補
        SEVENTH,        ///< 第7候補
        EIGHTH,         ///< 第8候補
        NINTH,          ///< 第9候補
        TENTH,          ///< 第10候補
        ELEVENTH,       ///< 第11候補
        TWELVETH,       ///< 第12候補
        USER,           ///< ユーザー設定
        LOCAL0,         ///< 独自の特殊な設定0
        LOCAL1,         ///< 独自の特殊な設定1
    };- 現在、ポート候補は、グループ設定の場合と、単独ポートの場合が混在しています
- たとえば、SCI、CAN、RSPI、IICA などはグループ指定、MTU、TPU、GPT、GPTW、QSPI などは単独で指定可能になっています
- なので、SCI などで、グループを超えて設定(TXD を FIRST、RXD を SECOND みたいな)事は出来ないです
- グループ指定は、複数あるポートを一括して行うものです
- 一般的に、グループ候補の場合、近接するポートを選んでいるので、通常それで困る場合は無いと思います
- 急遽、ペリフェラルの機能が必要になり、余っているポートをかき集めたり、改造を最小限にする為に、異なる候補を選択するしか無い場合はあるかと思います
- そのような場合は、「USER」設定を使って、独自に設定する必要があります
SCI ポート候補の選択例
- 例として RX231、LFQFP64 パッケージの場合
- SCI5 を使いたい場合
Port map order / ポートマップ候補
LFQFP64
| Peripheral | FIRST | SECOND | THIRD | FOURTH | 
|---|---|---|---|---|
| SCI5 / RXD | PA2 (--) | PA3 (43) | PC2 (32) | PC2 (32) | 
| SCI5 / TXD | PA4 (42) | PA4 (42) | PC3 (31) | PC3 (31) | 
候補の選択と管理
- 「Port map order / ポートマップ候補、LFQFP64」の表から、「SCI5 / RXD, SCI5 / TXD」の欄を見ます
- 実際のハードを吟味して、SECOND の RXD/PA3 (43)、TXD/PA4 (42) が使えそうと判断します
- SCI の入出力では、「sci_io.hpp」のテンプレートクラスを使います
- 以下のコードのように、「SECOND」を指定して、sci_io のテンプレートを typedef して型を定義します
- それの実態を定義して、初期化するだけで、使えるようになります
- new しても構いませんが、固定されたハードウェアーで、動的にクラスを生成する必要性が無いので、static に宣言します
- 出来るだけ、new を使わない方法を選択する事が寛容です
- static に宣言すれば、必要なメモリは、C++ コンパイラが適切に領域を設定して配置してくれます
- C++ では、static と宣言しても良いのですが、main 関数があるソースに、無名の名前空間で囲んで定義するのが一般的です
- sci_io クラスでは、定義に、受信、送信バッファの型を伴って定義します
- バッファは、固定長のリングバッファを使います、「fixed_fifo」テンプレートクラス
- 以下の例では、それぞれ、512 バイト、256 バイトの大きさで定義しています
#include "common/renesas.hpp"
#include "common/fixed_fifo.hpp"
#include "common/sci_io.hpp"
namespace {
    typedef utils::fixed_fifo<char, 512> RXB;  // RX (受信) バッファの定義
    typedef utils::fixed_fifo<char, 256> TXB;  // TX (送信) バッファの定義
    typedef device::sci_io<device::SCI5, RXB, TXB, device::port_map_order::SECOND> SCI5_IO;
    SCI5_IO sci5_io_;
}- もし、あーやっぱり、「RXD/PA3 (43)、TXD/PA4 (42)」じゃなく、「RXD/PC2 (32)、TXD/PC3 (31)」の方が、都合が良いとなれば
- 候補を、「SECOND」から「THIRD」にするだけです
- 他は変更する必要がありません
    typedef device::sci_io<device::SCI5, RXB, TXB, device::port_map_order::THIRD> SCI5_IO;
標準入出力の設定
- 一般的な gcc を使った、組み込みアプリケーションでは、標準入出力とのインターフェースを設定する必要があります
- この C++ フレームワークでは、syscall.c をリンクする事で、インターフェースを有効にする事が出来ます
- SCI5 のインスタンスをこの標準入出力と繋げる場合、以下のように定義します
extern "C" {
    // syscalls.c から呼ばれる、標準出力(stdout, stderr)
    void sci_putch(char ch)
    {
        sci5_io_.putch(ch);
    }
    void sci_puts(const char* str)
    {
        sci5_io_.puts(str);
    }
    // syscalls.c から呼ばれる、標準入力(stdin)
    char sci_getch(void)
    {
        return sci5_io_.getch();
    }
    uint16_t sci_length()
    {
        return sci5_io_.recv_length();
    }
}- この定義で、SCI5 での入出力は、標準入出力とリンクされます
- printf や scanf などで入出力を行えます
- C++ では、C 言語の関数は使わないので、format クラス、input クラスの用意があります
初期化
- SCI の初期化は簡単で、ボーレート、割り込みレベル、プロトコルを選択するだけです
// 起動時、1度行って、マスタークロックをブーストして下さい
    SYSTEM_IO::boost_master_clock();
    {  // SCI の開始
        constexpr uint32_t baud = 115200;  // ボーレート(任意の整数値を指定可能)
        static_assert(SCI5_IO::probe_baud(baud), "Failed baud rate accuracy test");  // 許容誤差(3%)を超える場合、コンパイルエラー
        auto intr = device::ICU::LEVEL::_2;     // 割り込みレベル(NONE を指定すると、ポーリング動作になる)
        if(!sci5_io_.start(baud, intr)) {  // 標準では、8ビット、1ストップビットを自動選択
            halt_();
        }
// 通信プロトコルを設定する場合は、通信プロトコルのタイプを指定する事が出来る。
// sci_io.hpp PROTOCOL enum class のタイプを参照
//      sci_.start(baud, intr, SCI::PROTOCOL::B8_E_1S);
    }- これで、入出力が行える準備が整います
- 後は、標準入出力を使って、データ通信を行います
    {  // SCI の設定レポート表示
        utils::format("SCI5 PCLK: %u [Hz]\n") % SCI5_IO::sci_type::PCLK;
        utils::format("SCI5 Baud rate (set): %u [BPS]\n") % sci5_io_.get_baud_rate();
        float rate = 1.0f - static_cast<float>(sci5_io_.get_baud_rate()) / sci5_io_.get_baud_rate(true);
        rate *= 100.0f;
        utils::format("  Baud rate (real): %u (%3.2f [%%])\n") % sci5_io_.get_baud_rate(true) % rate;
        utils::format("  SEMR_BRME: %s\n") % utils::str::get_bool_text(SCI5_IO::sci_type::SEMR_BRME);
        utils::format("  SEMR_BGDM: %s\n") % utils::str::get_bool_text(SCI5_IO::sci_type::SEMR_BGDM);
    }独自ポート設定(ORDER::USER)
- 以下の例は、候補として「USER」を行う場合の方法です
- SCI5: TXD/PA3, RXD/PC3 を利用する例です
- この設定は、初期化 (sci5io.start) を行う前に設定する必要があります(初期化時に、設定された関数が呼ばれます)
- 又、C++ のランタイムをリンクする必要があります(Makefile に supc++ ライブラリを追加してください)
- 独自設定の場合、特別なレジスター郡へのアクセスがあるので、独自関数が呼ばれる前に、書き込み保護が解除された状態になっています
    typedef device::sci_io<device::SCI5, RXB, TXB, device::port_map_order::USER> SCI5_IO;        device::port_map::set_user_func( [=](device::peripheral per, bool ena) {
            // SCI5: TXD/PA3, RXD/PC3 の場合
            using namespace device;
            // セレクターのビット列は、MPC の解説を参照して下さい
            uint8_t sel = ena ? 0b0'1010 : 0;
            MPC::PA3PFS.PSEL = sel;
            PORTA::PMR.B3 = ena;
            MPC::PC3PFS.PSEL = sel;
            PORTC::PMR.B3 = ena;
            return true;
        }
        );Makefile への C++ ランタイムライブラリの追加:
USER_LIBS   =   supc++- この例ではラムダ式を使って簡潔に行っています
- 詳しくは、「std::function ラムダ式」などで検索して、使い方を参照して下さい
- これらのサンプルは、「SCI_sample/main.cpp」に具体的なコードが示されていますので参考にしてください
- ポートの機能設定は、ハードウェアーマニュアルの MPC の解説を参照して下さい
- MPC に、機能を設定するビット列には特別な意味があります、間違えると、正しく動作しません
- ポートの独自設定は、設定を合格とする為「true」で戻る必要があります
まとめ
- 今回の更新は、ドキュメントの追加程度ですが、github に色々な情報を集約するのに都合が良いものでした
- マークダウンの表は、そこそこ見やすいものなので、多少利便性が向上したものと思います
- 又、ポートマップの仕組み、具体的な独自設定の方法などをさらに詳しく示しました






















