RXマイコン、デジタルストレージオシロスコープ(その4)

かなり間が空いたが、再び、デジタルストレージの作業を行った。

ソフトの作業も平行して行っており、かなり充実してきている。


プローブを買い直す。

60MHz のプローブを買い直した、まぁ現代は、それなりに安く購入できるので助かる。

以前に買った 60MHz のプローブはトリマを回すのに特殊なドライバーが必要で(ドライバー無くした)、もっと安いプローブがあったので、別件で部品を買うついでに買ってみた。

60MHz プローブ(TEXAS60)


昔会社勤めの時、プローブの扱いに注意するよう散々言われた、テクトロニクスの 350MHz オシロ用プローブは1本5万くらいしていた。
※実験で色々作業している過程で、プローブを壊す(先のピンを折ってしまう)事が多かったようだ。
※テクトロのプローブは、沢山の知恵が詰っている優れもので、感動した事を覚えている。

プリアンプを考える

実験的に、初段のプリアンプとして、OPA2134Aを使っていたが、これは、オーディオ用なので、帯域が足りない。
※高い周波数でゲインが低下する。
※それに、そんなに安いオペアンプではない。

そこで、色々なオペアンプを探すものの、高性能な物は値段が高く、オーバースペックでもある。
サンプリングが 2MHz だと、高い周波数は測れないのは当然なのだが、
低い周波数でも矩形波を観測した場合などに、立ち上がりや立下りが実際と異なり鈍ると測定器として成立しない。
※正弦波でも、周波数によってゲインが下がって、正確な電圧を計測出来ない。
入力インピーダンスは通常1Mオームと高いので、高速でも、バイアス電流がある程度必要なオペアンプは使えない。

意外と丁度良い物が無い・・

基本的な特性として、以下の点が挙げられる。(これは、今回のプロジェクトに合致する)
※他にも、色々な項目があり、以下の条件をクリアしていても使えない場合もある。

  • スルーレートが高く、GB積が大きい
  • 入力バイアス電流が低い
  • 雑音が少ない
  • +-5V で使える
  • コストがそれなり
  • 二個入り

探す目安でしかないが、非常に沢山の品種から探すのは、何かトピックが無いと絞るのが難しいので、これらの項目で絞って選択する事になる。
※「A/D 変換の入力プリアンプ用」も選択の目安となると思う。
※1個単位で買えて、それなりに安い事も重要。

入力バイアス電流、雑音、速度は、一般的にトレードオフの関係があり、昔は、そのようなオペアンプは無かったと思うが、現在は、技術革新があり、そのような品種がリリースされている。

それで見つけたのが「アナログデバイセズの AD8066」、チップワンストップで10個程購入した(1個400円くらいだった)
※現在は、廃盤になったのか、在庫分くらいしか無いようで、倍の値段になっている・・・

主な特徴は:

  • 入力バイアス電流:1pA
  • 低価格
  • 145MHzで-3dBの帯域幅(G = +1)
  • 180V/µsのスルーレート(G = +2)
  • 低雑音
  • 5~24V
  • 単一電源およびレール・ツー・レール出力
  • 低いオフセット電圧:最大1.5mV

部品が来て、実験すると、まさに思った通りの性能で、感動した!
素晴らしいとしか言いようが無い!

アナログデバイセズ AD8065/AD8066

DC カップリング

RX72N Envision Kit の外部ポートには、200オームの保護抵抗があり、直でドライブするのは不安な為、FETスイッチを入れてある。

DC を除去する「AC」モードと、DC を観測する機能の切り替えとして、回路を簡単にする為、簡易な回路に変更した。
単純に、カップリングのコンデンサを、フォトモスリレーでショートするだけにした、実験では問題無いようだ。
※ACからDCに切り替える時、コンデンサに溜まった電荷をショートするが、ON 抵抗があるので問題無いだろうと思う。

※ただ、この時使った「PS7200K」は、現在では入手が難しいようなので、他の部品を探す必要がある。

一応入力保護

入力に過大な電圧が入った場合に回路を保護するサージ対策について調べた。
完全に保護する事は出来ないが、ある程度のバリアにはなると思う。
すると、非常に高性能でありながら、回路に与える影響が非常に少ない部品(ガス放電管アレスタ)がある事に気がついた。
値段もそんなに高く無い。
今回は、海外の部品で「Littelfuse SG90」を使う事にした(SMD 部品)。
※日本製は数がまとまらないと入手が難しい。(日本製を使いたいのに、このような制約で使う事が出来ない・・)
※最低発注数1000個とか無理!

Littlefuse GDT-SG90

レンジ切り替え

基本、RXマイコンのA/D入力(0~3.3V)なので、レンジ切り替えが必要で、以下の回路を考えてみたが、実験すると、これでは駄目な事が判った・・・

74HC4051 の入力部分には、寄生容量があり、波形が鈍る・・・
※最初は、2MHz のサンプリングなので十分と思っていたが、オシロスコープの入力インピーダンスは1Mオームと高いので、微小な容量でも効いてくる。

アナログSWを通した場合:

本来の波形:

結局、メカリレーにするしか無いかもしれない・・・
※一応、そんな事もあろうかと、部品は買ってあるが、回路を作るのが面倒だし、リレーをドライブする回路を追加する必要がある。

その前に、フォトMOSリレーをスイッチ替わりにして実験してみようと思う。

まとめ

オペアンプは、価格が高いので、他を探す必要がある。(一応候補は見つけたが、実験しておく必要がある。)
ガス放電管アレスタは、Digikey から購入する事になると思うので、キリが良いところで、まとめて発注する。

本当は、PCB のトラックを引くところまで済ます予定だったが、レンジ切り替えの問題で、先延ばしになった。

今回はここまで、別件もあり、中々集中する事が出来ない・・

RXマイコンで、TinyUSB を使ってみる

TinyUSB について

最近、USB のスタックで評判の TinyUSB を実験してみた。

現状の実装では、主に以下のような感じとなっている。

  • オープンソースである。
  • 非常に多くのマイコンに対応している。
  • RX マイコンも、デバイス(クライアント)、ホストのドライバーが用意されている。
  • 主にデバイスの機能が充実している。(PC に繋ぐ、USB 機器を作る場合)
  • USB ホストは実装が始まったばかりで、あまり枯れていないよう。
  • 全体の構成が判りやすく、サンプルやドキュメントが充実している。
  • 機能実装、バグ修正などが GitHub で行われており、将来性が有望。
  • 「Tiny」となっているが、プロジェクトはかなり大きい。
  • API の仕様が明確で適切なので、マイコンの種別に関係無く、ソースコードの再利用が出来る。(ここが大きい!)

など、かなり魅力的なプロジェクトとなっている。

RX マイコン用のドライバーもあるので、自分の環境で実験してみた。
※当初、ホストのドライバーが無かったが、現在は、コミットされている。

RX マイコン用ドライバーは、Koji KITAYAMA さんが実装しているようで、御礼申し上げます。


自分のシステムに取り込む場合

自分の C++ フレームワークに取り込むには、多少の改造が必要なので、その過程を記す。

  • TinyUSB には、サンプルプログラムが沢山あるが、RX マイコンで使う場合、主に CC-RX 環境に依存しているので、gcc で使うには問題がある。
  • そこで、最小限の改造で、使うようにする為、自分のシステムに必要な部分だけ取り込んで実験した。
  • とりあえず、ホスト機能を使い、ゲームパッドやキーボードを利用する事が目的となっている。
  • 非常に機能が豊富なので、他も試していきたい。

RX マイコンのオフィシャルな対応としては、RX63N、RX65N、RX72N となっているが、基本、USB ペリフェラルは、ほぼ同じ構成なので、RX64M、RX71M、RX66T、RX72T など多くのデバイスにも使えると思われる。
※基本 USB2.0 系で、LowSpeed(1.5Mbps)、FullSpeed(12Mbps)に対応していれば良いようである。
※ RX631/RX63N はマイコン側が LowSpeed に対応しない。
※ RX64M/RX71M の HighSpeed(480Mbps)には対応していない。

USB0 のクロック設定

USB0 ペリフェラルのクロック源には 48MHz が必要なので、クロックジェネレーターの設定を調整する。
RX72N では、内部 PLL を 240MHz にすれば、48MHz は 1/5 にすれば良い。

自分のフレームワークでは、clock_profile.hpp で、以下の設定をして、boost_master_clock() を呼べば、あとは自動で設定してくれる。

    class clock_profile {
    public:
        static constexpr bool       TURN_USB    = true;             ///< USB を使う場合「true」
        static constexpr uint32_t   BASE        =  16'000'000;        ///< 外部接続クリスタル
        static constexpr uint32_t   PLL_BASE    = 240'000'000;        ///< PLL ベースクロック(最大240MHz)

        static constexpr uint32_t   ICLK        = 240'000'000;        ///< ICLK 周波数(最大240MHz)
        static constexpr uint32_t   PCLKA       = 120'000'000;        ///< PCLKA 周波数(最大120MHz)
        static constexpr uint32_t   PCLKB       =  60'000'000;        ///< PCLKB 周波数(最大60MHz)
        static constexpr uint32_t   PCLKC       =  60'000'000;        ///< PCLKC 周波数(最大60MHz)
        static constexpr uint32_t   PCLKD       =  60'000'000;        ///< PCLKD 周波数(最大60MHz)
        static constexpr uint32_t   FCLK        =  60'000'000;        ///< FCLK 周波数(最大60MHz)
        static constexpr uint32_t   BCLK        = 120'000'000;        ///< BCLK 周波数(最大120MHz)
    };

※48MHz が作れない設定を行うと、コンパイルを失敗する。

        static constexpr bool       TURN_USB    = true;             ///< USB を使う場合「true」
        static constexpr uint32_t   BASE        =  16'000'000;        ///< 外部接続クリスタル
        static constexpr uint32_t   PLL_BASE    = 200'000'000;        ///< PLL ベースクロック(最大240MHz)

        static constexpr uint32_t   ICLK        = 200'000'000;        ///< ICLK 周波数(最大240MHz)
        static constexpr uint32_t   PCLKA       = 100'000'000;        ///< PCLKA 周波数(最大120MHz)
        static constexpr uint32_t   PCLKB       =  50'000'000;        ///< PCLKB 周波数(最大60MHz)
        static constexpr uint32_t   PCLKC       =  50'000'000;        ///< PCLKC 周波数(最大60MHz)
        static constexpr uint32_t   PCLKD       =  50'000'000;        ///< PCLKD 周波数(最大60MHz)
        static constexpr uint32_t   FCLK        =  50'000'000;        ///< FCLK 周波数(最大60MHz)
        static constexpr uint32_t   BCLK        = 100'000'000;        ///< BCLK 周波数(最大120MHz)

---

../RX600/system_io.hpp:228:34: error: static assertion failed: USB Clock can't divided.
    static_assert(usb_div_() >= 2 && usb_div_() <= 5, "USB Clock can't divided.");
                  ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~
../RX600/system_io.hpp:230:44: error: conversion from 'long unsigned int' to 'device::rw16_t<524324>::value_type' {aka 'short unsigned int'} changes value from '4294967295' to '65535' [-Werror=overflow]
    device::SYSTEM::SCKCR2.UCK = usb_div_() - 1;
                                 ~~~~~~~~~~~^~~
cc1plus.exe: all warnings being treated as errors
make: *** [Makefile:193: release/main.o] エラー 1

USB0 のポート設定

RX72N Envision Kit では、USB の関係ポートとして、以下の2ポートを利用している。

  • USB0_VBUSEN(P16) USB 機器の電源制御ポート
  • USB0_OVRCURB(P14) 外部接続機器の電流制限がオーバーした場合を通知するポート

現在の実装では「オーバーカレント」は観ていないようなので、USB0_VBUSEN のみ設定を行う。

ポート設定は、現在は、ポートマップのオーダーを「SECOND」にする事で、RX72N Envision Kit に対応したもになるようにしてある。

とりあえず、tinyusb_mng クラスを用意して、対応している。

        //-----------------------------------------------------------------//
        /*!
            @brief  開始
            @param[in]  ilvl    割り込みレベル
            @return 成功なら「true」
        */
        //-----------------------------------------------------------------//
        bool start(uint8_t ilvl) noexcept
        {
            if(ilvl == 0) {  // 割り込み無しはエラー
                return false;
            }

            power_mgr::turn(USB_CH::PERIPHERAL);

            // VBUSEN, OVERCURA ピンの設定
            if(!port_map::turn(USB_CH::PERIPHERAL, true, PSEL)) {
                return false;
            }

            ivec_ = icu_mgr::set_interrupt(USB_CH::I_VEC, i_task_, ilvl);

//          utils::format("USB clock divider: 0b%04b\n") % static_cast<uint16_t>(device::SYSTEM::SCKCR2.UCK());
//          utils::format("USB0 interrupt vector: %u\n") % static_cast<uint16_t>(ivec_);

            tuh_init(BOARD_TUH_RHPORT);

            return true;
        }
---

    // RX72N Envision Kit
    typedef device::tinyusb_mng<device::USB0, device::port_map::ORDER::SECOND> TINYUSB;
    TINYUSB tinyusb_;

USB0 の省電力設定

USB0 の省電力設定解除は、ドライバーでされているが、自分のシステムで行いたいので、コメントアウトした。

tinyusb/src/portable/renesas/usba/hcd_usba.c

bool hcd_init(uint8_t rhport)
{
  (void)rhport;
  /* Enable USB0 */

//  uint32_t pswi = disable_interrupt();
//  SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY | SYSTEM_PRCR_PRC1;
//  MSTP(USB0) = 0;
//  SYSTEM.PRCR.WORD = SYSTEM_PRCR_PRKEY;
//  enable_interrupt(pswi);

USB0 の割り込み設定

RX72N では、USB0/USBI は選択型割り込みとなっているので、割り込みベクターを独自に設定して、TinyUSB のハンドラを呼ぶようにしている。

        static INTERRUPT_FUNC void i_task_()
        {
#if CFG_TUH_ENABLED
            tuh_int_handler(0);
#endif
#if CFG_TUD_ENABLED
            tud_int_handler(0);
#endif
        }

...

            ivec_ = icu_mgr::set_interrupt(USB_CH::I_VEC, i_task_, ilvl);

TinyUSB の RX マイコンドライバーでは、マイコンとして、RX72N を選ぶと、選択型割り込みBは、185番がハードコートされている。

自分のシステムでは、選択型割り込みBの割り込みベクターは、内部で管理されていて、設定順により優先度が決定される。
USB0 の初期化は最初に呼ぶので、128番が設定される。

そこで、ドライバーのソースを修正して、128番を使うように修正を行った。

tinyusb/src/portable/renesas/usba/hcd_usba.c

// hcd_init 内
  IR(PERIB, INTB128) = 0;  // IR(PERIB, INTB185) = 0;

void hcd_int_enable(uint8_t rhport)
{
  (void)rhport;
#if ( CFG_TUSB_MCU == OPT_MCU_RX72N )
  IEN(PERIB, INTB128) = 1;  // IEN(PERIB, INTB185) = 1;
#else
  IEN(USB0, USBI0) = 1;
#endif
}

void hcd_int_disable(uint8_t rhport)
{
  (void)rhport;
#if ( CFG_TUSB_MCU == OPT_MCU_RX72N )
  IEN(PERIB, INTB128) = 0;  // IEN(PERIB, INTB185) = 0;
#else
  IEN(USB0, USBI0) = 0;
#endif
}

これで、TinyUSB を自分のシステムで利用する準備が整った。


TinyUSB のコア部分

TinyUSB のコアでは、「tuh_task()」をサービスすれば良いようで、通常無限ループにする。
しかし、それだと、他に何も出来ないので、とりあえず、CMT で 1000Hz(1ms) のタイミングを作り、呼び出すようにした。

    uint16_t cnt = 0;
    uint16_t cnt_max = 50;  // by 100Hz
    while(1) {
        cnt_max = 500;
        cmt_.sync();

        tuh_task();
#if CFG_TUH_CDC
        cdc_task();
#endif

#if CFG_TUH_HID
        hid_app_task();
#endif

        ++cnt;
        if(cnt >= cnt_max) {
            cnt = 0;
        }
        if(cnt < (cnt_max / 2)) {
            LED::P = 0;
        } else {
            LED::P = 1;
        }
    }

TinyUSB のソースをコンパイルする。

iodefine.h は、e2studio/gcc で生成した物をアプリケーションのルートに置いて利用した。

TinyUSB は、tusb_config.h をアプリケーションに合わせて設定する事で、必要なソースをコンパイルするようになっている。
※アプリケーションのルートに置いてある。

ホスト機能を提供する場合、基本的な設定は以下のようになっている。

#define CFG_TUH_HUB                 0
#define CFG_TUH_CDC                 0
#define CFG_TUH_HID                 4 // typical keyboard + mouse device can have 3-4 HID interfaces
#define CFG_TUH_MSC                 0 // Mass Storage Device
#define CFG_TUH_VENDOR              0

とりあえず、HUB は「0」にしてある。

必要なソースを Makefile に追加して、パス、外部変数などを設定する。

CSOURCES    =   common/init.c \
                common/vect.c \
                common/syscalls.c \
                tinyusb/src/tusb.c \
                tinyusb/src/common/tusb_fifo.c \
                tinyusb/src/device/usbd.c \
                tinyusb/src/device/usbd_control.c \
                tinyusb/src/class/audio/audio_device.c \
                tinyusb/src/class/cdc/cdc_device.c \
                tinyusb/src/class/dfu/dfu_device.c \
                tinyusb/src/class/dfu/dfu_rt_device.c \
                tinyusb/src/class/hid/hid_device.c \
                tinyusb/src/class/midi/midi_device.c \
                tinyusb/src/class/msc/msc_device.c \
                tinyusb/src/class/net/ecm_rndis_device.c \
                tinyusb/src/class/net/ncm_device.c \
                tinyusb/src/class/usbtmc/usbtmc_device.c \
                tinyusb/src/class/video/video_device.c \
                tinyusb/src/class/vendor/vendor_device.c \
                tinyusb/src/class/cdc/cdc_host.c \
                tinyusb/src/class/hid/hid_host.c \
                tinyusb/src/class/msc/msc_host.c \
                tinyusb/src/host/hub.c \
                tinyusb/src/host/usbh.c \
                tinyusb/src/portable/ohci/ohci.c \
                tinyusb/src/portable/renesas/usba/hcd_usba.c

...

USER_DEFS   =   SIG_RX72N CFG_TUSB_MCU=OPT_MCU_RX72N

...

# インクルードパス
INC_APP     =   . ../ \
                ../RX600/drw2d/inc/tes \
                ../tinyusb/src

# C コンパイル時の警告設定
CP_OPT      =   -Wall -Werror \
                -Wno-unused-variable \
                -Wno-unused-function \
                -Wno-stringop-truncation \
                -fno-exceptions

これで、TinyUSB 関係ソースをコンパイル出来た。


HID 関係のサービスを実装する

HID 関係の実装は、サンプルがあるので、それを参考にした。

基本、接続時、解放時、データ転送などでコールバックが呼ばれるので、それに対応するコードを実装する。

extern "C" {

    void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
    {
        device::tinyusb_base::hid_mount_cb(dev_addr, instance, desc_report, desc_len);
    }

    void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
    {
        device::tinyusb_base::hid_umount_cb(dev_addr, instance);
    }

    void hid_app_task(void)
    {
        device::tinyusb_base::hid_app_task();
    }

    void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
    {
        device::tinyusb_base::hid_report_received_cb(dev_addr, instance, report, len);
    }
#if 0
    void tuh_cdc_xfer_isr(uint8_t dev_addr, xfer_result_t event, cdc_pipeid_t pipe_id, uint32_t xferred_bytes)
    {
    }
#endif
    void cdc_task(void)
    {
    }

}

とりあえず、C++ で実装して、TinyUSB に繋いだ・・

    struct tinyusb_base {

        static uint8_t dev_addr_;
        static uint8_t instance_;
        static bool send_;
        static uint8_t leds_;

        static void hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
        {
            uint16_t vid, pid;
            tuh_vid_pid_get(dev_addr, &vid, &pid);

            utils::format("HID device address = %d, instance = %d is mounted\r\n")
                % static_cast<uint16_t>(dev_addr) % static_cast<uint16_t>(instance);
            utils::format("VID = %04x, PID = %04x\r\n") % vid % pid;

            auto detect = false;
            auto itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
            switch (itf_protocol) {
            case HID_ITF_PROTOCOL_KEYBOARD:
//              process_kbd_report( (hid_keyboard_report_t const*) report );
                utils::format("Detected KEYBOARD\n");
                detect = true;
                break;

            case HID_ITF_PROTOCOL_MOUSE:
//              process_mouse_report( (hid_mouse_report_t const*) report );
                utils::format("Detected MOUSE\n");
                detect = true;
                break;

            default:
                // Generic report requires matching ReportID and contents with previous parsed report info
//              process_generic_report(dev_addr, instance, report, len);
                utils::format("Detected GENERIC\n");
                detect = true;
                break;
            }

            if (detect) {
                if ( !tuh_hid_receive_report(dev_addr, instance) ) {
                    utils::format("Error: cannot request to receive report\r\n");
                }
            }
        }

        static void hid_umount_cb(uint8_t dev_addr, uint8_t instance)
        {
            utils::format("HID device address = %d, instance = %d is unmounted\r\n")
                % static_cast<uint16_t>(dev_addr) % static_cast<uint16_t>(instance);
        }

        static void hid_app_task()
        {
            if(send_) {
                if(!tuh_hid_set_report(dev_addr_, instance_, 0, HID_REPORT_TYPE_OUTPUT, &leds_, sizeof(leds_))) {
                    utils::format("set report fail...\n");
                }
                send_ = false;
            }
        }

        static void hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
        {
            static uint8_t cnt = 0;

            auto itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
            switch (itf_protocol) {
            case HID_ITF_PROTOCOL_KEYBOARD:
                {
                    uint8_t tmp[8];
                    memcpy(tmp, report, len);
                    utils::format("%d, %d, %d, %d\n") % static_cast<uint16_t>(tmp[0]) % static_cast<uint16_t>(tmp[1]) % static_cast<uint16_t>(tmp[2]) % static_cast<uint16_t>(tmp[3]);
                    if(tmp[2] == 83 || tmp[2] == 57) {
                        ++cnt;
                        if(cnt & 1) {
                            leds_ |= KEYBOARD_LED_NUMLOCK | KEYBOARD_LED_CAPSLOCK;
                        } else {
                            leds_ = 0;
                        }
                        dev_addr_ = dev_addr;
                        instance_ = instance;
                        send_ = true;
                    }
                }
                break;

            case HID_ITF_PROTOCOL_MOUSE:

                break;

            default:

                break;
            }

            // continue to request to receive report
            if ( !tuh_hid_receive_report(dev_addr, instance) ) {
                utils::format("Error: cannot request to receive report\r\n");
            }
        }
    };

実験してみるが・・・

とりあえず、コンパイルが通ったので、RX72N Envision Kit にキーボードを繋いで実験してみた。

Start 'USB0' test for 'RX72N' 240[MHz]
SCI Baud rate (set):  115200
SCI Baud rate (real): 115384 (0.16 [%])
CMT rate (set):  1000 [Hz]
CMT rate (real): 1000 [Hz] (0.00 [%])
Start USB: OK!
HID device address = 1, instance = 0 is mounted
VID = 1c4f, PID = 0027
Detected KEYBOARD
0, 0, 25, 0
0, 0, 0, 0
0, 0, 10, 0
0, 0, 0, 0
0, 0, 9, 0
0, 0, 0, 0
0, 0, 23, 0
0, 0, 0, 0

USB キーボードを繋いで、キーを押してみた。
反応が返る!

問題点

ネットで、TinyUSB/Host でキーボード接続時、LED を点灯する仕組みを探したら、「tuh_hid_set_report」API を使い、LED ビットに対応するバイトデータを送れば良い事が判り、実装するものの、上記 API は「false」を返して失敗するようだ・・・

色々調べたが、キーボード接続時に、IDLE 設定の転送を行い、それが終了しない為、失敗しているようだが、根本的な原因が判らない・・

他にも、GENRIC デバイス(キーボードを外して、ゲームパッドを接続するとハングアップする)の動作が微妙とか。
最初にゲームパッドを接続して、次にキーボードを接続すると認識しないとか(電源を切るまで認識しなくなる)

色々問題があるようだ・・・
ただ、それが、TinyUSB の問題なのか、RX マイコンのドライバーなのか、切り分けが出来ていない。


まとめ

まだまだ、これからのようだが、将来性を考えると、TinyUSB は良い選択となるものと思える。

今後、色々と環境を整えていきたい。