「RX」カテゴリーアーカイブ

RX26Tの動作確認

RX26T が発表されている

RX26Tが発表されて、購入が可能な事が判り、いつもの chip1stop で購入した。
品番は、R5F526TFDGFPで、フラッシュ512K、RAM64K、データフラッシュ16K、100ピンのバージョンだ。

構成としては、かなり目新しい部分もあるが、基本的にはRX200シリーズなので、RX24Tの後継品だろうか・・

基本、家電製品や自動車などに使う事がメインと思うので、値段もまぁまぁ安い部類。


特徴

  • RXv3 コア(最大120MHz動作)
  • TFU2 内蔵(バージョンアップ版 TFU)
  • RSCI モジュール(新しいシリアル通信モジュール)
  • I3C バスインターフェース
  • RSPIA(シリアルペリフェラルインターフェース)
  • CANFD(FD 仕様の CAN モジュール)

こんな感じだろうか・・
他にも細かい部分で色々な機能がある。
残念なのは、USB インターフェースが無い点。
※CANFD のクロック分周器が新設されたが、これは以前は、USB クロックの分周器として利用していたものなので、そのせいで、USB を切ったのかもしれない。

TFU2 は、レジスタ退避機能があり、割り込み内で利用可能になったようだ。

RSCI、I3C、RSPIA,CANFD は、新たにドライバーを作り直す必要がある。
これらモジュールは、ARM 系モジュールでも使われて、今後、RX マイコンでも主流になるものと思う。
※ソフト資産を共有可能なのだろう~

内蔵メモリの容量違いで、機能が削られたりする仕様があり、デバイス選択に複雑な要因が入り込む。
このようなセールスはやめて欲しいと思う、何かメリットがあるのだろうか?
内蔵RAMが64K版と48K版がある・・、この仕様も、何かメリットがあるのだろうか?


難産・・・

早速、ユニバーサル基板に組み、初期実験を行った。
フレームワークは、RX24T、RX66T、などと共通点が多く、必要な部分を実装しておいた。
どちらかと言うと RX66T に近い構成。

しかし、ちゃんと動作しない・・・
簡単なLED点滅ですら、動かない・・・

調査調査調査・・・

少し調査した限りでは、クロックのブーストは動作しているようだが、その先でつまずくようだ・・・
こんな症状は初めてで、基板の配線、電源、色々と検査した。
VSS が1本接続忘れがあったり、細かい部分でミスを発見したが、直しても、駄目・・・

簡単なプログラムでも、リセットを繰り返すと、頻度は少ないが動作しない場合がある。
これは、クロックのブーストが失敗するのかも・・

基板の配線、主に電源ラインを確認したり、何か間違いが無いか確認したりと色々と行ったが成果無し。

色々な事をトライして、判ったのは、内部 PLL の最大周波数を 240MHz にすると、動作が不安定になる。
120MHz だと、安定して動作するようだ。
ハードウェアーマニュアルでは、120MHz~240MHz となっている。

VCL に接続したコンデンサは、 0.47uF が無かったので 1uF を付けた、それが原因なのかもしれない。
しかし、内部電源の平滑用なので、容量は PLL の動作に関係無いと思うのだが・・

昔に、チップワンストップで、チップコンデンサがファイルされた「コンデンサセレクション」を買った(高かった)、それを探したら、0.47uF があったので付け替えた。
※ここぞと言う場合に使うので、あまり使いたく無いのと、サイズが1608なのが・・
しかし、やはり 240MHz の動作は不安定でほぼ動作しない。

とりあえず、内部 PLL は 120MHz で動作させる事とした。


ソフト・ディレイループ定数

RX24T より、優秀で、単純なループでも、40%くらい速い感じがある、同じ RXv3 コアの RX66T、RX72T とほぼ同等の性能のようだ。

        static constexpr uint32_t   DELAY_MS    = ICLK / 3'065'133;   ///< ソフトウェアー遅延における定数(1マイクロ秒)

オーバークロック耐性

        static constexpr uint32_t   PLL_BASE    =  180'000'000;       ///< PLL ベースクロック(最大 120 to 240MHz)

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

オーバークロックによるSCIサンプルの動作:

Start SCI (UART) sample for 'RX26T DIY' 180[MHz]
SCI PCLK: 45000000 [Hz]
SCI Baud rate (set): 115200 [BPS]
  Baud rate (real): 115355 (0.13 [%])
  SEMR_BRME: true
  SEMR_BGDM: true
CMT Timer (set):  100 [Hz]
  Timer (real): 100 [Hz] (0.00 [%])
#

とりあえず、180MHz(1.5倍)の動作は確認した、PLL が 240MHz で不安定なので、240MHz(2倍)は動作しないだろうと思う。
それでも、十分な耐性だと思える。


サンプルアプリの動作

当然なのだが、C++ フレームワークの柔軟性により、FIRST_sample が動作したら、SCI 関係も、何の苦労無く普通に動作する。

  • FIRST_sample
  • SCI_sample
  • RAYTRACER_sample

RAYTRACER_sample:

マイコン core FPU fsqrt 命令 周波数 [MHz] 描画方式 時間 [ms]
RX62N RXv1 O X 96 8 bits, port-bus 1860
RX631 RXv1 O X 96 8 bits, port-bus 1868
RX24T RXv2 O O 80 8 bits, port-bus 1224
RX26T RXv3 O O 120 8 bits, port-bus 692
RX65N RXv2 O O 120 Frame Memory 784
RX64M RXv2 O O 120 16 bits, port-bus 751
RX66T RXv3 O O 160 8 bits, port-bus 602
RX72T RXv3 O O 192 8 bits, port-bus 464
RX71M RXv2 O O 240 16 bits, port-bus 439
RX72N RXv3 O O 240 Frame Memory 361
  • CALC_sample
Start CALC sample for 'RX26T DIY' 120[MHz]
# Rad
# tan(355/226)
 -7497258.185325587112905071831891248663417267943785263161571
# Deg
# sin(45)
 0.7071067811865475244008443621048490392848359376884740365883
# cos(60)
 0.5
# cos(45)
 0.7071067811865475244008443621048490392848359376884740365883
# sin(60)
 0.8660254037844386467637231707529361834714026269051903140279
#

まとめ

久しぶりにブログを書いた。
RXマイコン関係もかなり久しぶり。

RX26T は、CP が高めなのと、新しいペリフェラルの投入もあり、中々面白いCPUとなっている。
RX26T に新設されたペリフェラルの実装もまだなので、今後それらを中心にサポート、実験をしていきたい。

RXマイコン CAN_sample

記事を Qiita に投稿

CAN_sample は、RXマイコン C++ フレームワークを使った、対話形式の CAN 通信サンプルです。

その解説を Qiita に投稿しました。

RXマイコン C++ フレームワークによる CAN 通信


今回のキモはやはり C++

boost::unordered_map、boost::unordered_set を利用しています。

std ライブラリにも同等のクラスはあるけど、boost の方がサイズが若干小さくなるので、CAN_sample では、boost 版で説明しています。

CAN 通信を行う場合、C++ を利用するとメリットが多いです。


GR-CITRUS を使ってみた

GR-CITRUS は、プロダクトとしては及第点に達していないけれでも、入手性と、コストで選びました。

  • GR-CITRUS は秋月電子で、処分価格(1500円)で販売されています。
  • GR-CITRUS に載っているRXマイコンは、Flash:2M、RAM:256K と豊富なので、大きなプログラムも動かせます。
  • GR-CITRUS で数少ないピンでも CAN0 を利用可能。

RXマイコンの品不足はいつまで続くのだろうか・・・


通信実験の相方は RX72T

以前、RX72M を購入する際、同時に購入して実験した RX72T/144 ピンボードを利用しました。


今後

RX72N Envision Kit の PMOD 端子に出ているポートにも、CAN バスをアサイン可能なので、RX72N でも試してみたい・・
それと、LCD もあるので、OBD2 を使って、車の ECU 情報を表示をしてみたい・・

CAN は意外と簡単に扱え、ノイズに強い高品質な通信が出来るので、複数のマイコンを使った装置など作る際に、相互の通信インターフェースとして重宝すると思われます。

RX631/RX63N 割り込みレベル設定の不具合など・・

CAN の実験で気がついた

GR-CITRUS はピンの制限が非道なのだが、CAN0 で利用するピン CRX0(P33), CTX0(P32) はとりあえず使える。
そこで、CAN_sample を動かしてみようと思い、プロジェクトに RX631 を追加してコンパイル。
とりあえず、ターミナル表示を確認した。

Start CAN sample for 'RX631 GR-CITRUS' 96[MHz]
CAN command version: 0.89
CAN0: SPEED: 1000000 [bps], BRP: 2, TSEG1: 15, TSEG2: 8, SJW: 4
    RX Interrupt level: 1, TX Interrupt level: 0
#

何故か、TX の割り込みレベルが0と表示されている・・
can_io クラスは、ポーリングでの動作は出来ない、必ず、1以上の割り込みレベルが必須となっていて、何も指定しないと、レベル1割り込みを設定する。
おかしいな・・、色々調べて、icu.hpp の CAN 関係の割り込みベクターに間違いがあった・・・
それを直して、もう一度。

Start CAN sample for 'RX631 GR-CITRUS' 96[MHz]
CAN command version: 0.89
CAN0: SPEED: 1000000 [bps], BRP: 2, TSEG1: 15, TSEG2: 8, SJW: 4
    RX Interrupt level: 0, TX Interrupt level: 0
#

今度は、両方「0」に・・・
調べると、RX631/RX63N の割り込みレベル設定(IPR レジスタ)は、かなりの部分が共有されており、この部分のケアが抜けていた。
RX621、RX62N や、RX63T、RX24T などでも同じだが、そちらはケアされていた。
RX621/RX62N に比べると、規則性があるが、全般に渡ってかなりの分量だったが、何とか修正した。

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        /*!
            @brief  IPR レジスタ・クラス @n
                    全て、下位4ビットが有効
            @param[in]  base    ベースアドレス
        */
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        template <uint32_t base>
        struct ipr_t {

            //-------------------------------------------------------------//
            /*!
                @brief  []オペレータ
                @param[in]  vec     標準割り込みベクター型
                @return IPR レジスターの参照
            */
            //-------------------------------------------------------------//
            volatile uint8_t& operator [] (VECTOR vec) {
                uint32_t idx = 0;
                switch(vec) {
                case VECTOR::BUSERR: idx = 0; break;
                case VECTOR::FIFERR: idx = 1; break;
                case VECTOR::FRDYI:  idx = 2; break;
                case VECTOR::SWINT:  idx = 3; break;
                case VECTOR::CMI0:   idx = 4; break;
                case VECTOR::CMI1:   idx = 5; break;
                case VECTOR::CMI2:   idx = 6; break;
                case VECTOR::CMI3:   idx = 7; break;
                case VECTOR::SPRI0:
                case VECTOR::SPTI0:
                case VECTOR::SPII0:
                    idx = static_cast<uint32_t>(VECTOR::SPRI0);
                    break;
                case VECTOR::SPRI1:
                case VECTOR::SPTI1:
                case VECTOR::SPII1:
                    idx = static_cast<uint32_t>(VECTOR::SPRI1);
                    break;
                case VECTOR::SPRI2:
                case VECTOR::SPTI2:
                case VECTOR::SPII2:
                    idx = static_cast<uint32_t>(VECTOR::SPRI2);
                    break;
                case VECTOR::RXF0:
                case VECTOR::TXF0:
                case VECTOR::RXM0:
                case VECTOR::TXM0:
                    idx = static_cast<uint32_t>(VECTOR::RXF0);
                    break;
                case VECTOR::RXF1:
                case VECTOR::TXF1:
                case VECTOR::RXM1:
                case VECTOR::TXM1:
                    idx = static_cast<uint32_t>(VECTOR::RXF1);
                    break;

...

                default: idx = static_cast<uint32_t>(vec); break;
                }
                return *reinterpret_cast<volatile uint8_t*>(base + idx);
            }
        };
        typedef ipr_t<0x0008'7300> IPR_;
        static IPR_ IPR;

※最近の RX マイコンは、ほぼ、割り込み要因毎に割り込みレベルが設定出来る仕様になっているのでスルーしていた。
※古い、RxV1 コアなどのマイコンは注意しなければならない・・


未定義ビットの扱い

システムクロックコントロールレジスタ(SCKCR)の予約ビットの扱いを見直した。

このレジスタ、B0~B7 には書き込む場合に特定のビットを立てなくてはならない。
素のままだと、特定のビットだけを変更する場合に問題が発生する。

    device::system::SCKCR.ICK = 10;

このような実装では、最終的に SCKCR レジスタ、B0~B7 には、読み出した値(全て0)が上書きされる。

そこで、以下のように、書き込み時に、特定のビットフィールドを追加するように改修した。

        //-----------------------------------------------------------------//
        /*!
            @brief  システムクロックコントロールレジスタ(SCKCR)
            @param[in]  base    ベースアドレス
        */
        //-----------------------------------------------------------------//
        template <uint32_t base>
        struct sckcr_t : public rw32_t<base, 0b0001'0001> {
            typedef rw32_t<base, 0b0001'0001> io_;
            using io_::operator =;
            using io_::operator ();
            using io_::operator |=;
            using io_::operator &=;

            bits_rw_t<io_, bitpos::B8,  4> PCKB;
            bits_rw_t<io_, bitpos::B12, 4> PCKA;
            bits_rw_t<io_, bitpos::B16, 4> BCK;

            bit_rw_t <io_, bitpos::B22>    PSTOP0;
            bit_rw_t <io_, bitpos::B23>    PSTOP1;
            bits_rw_t<io_, bitpos::B24, 4> ICK;
            bits_rw_t<io_, bitpos::B28, 4> FCK;
        };
        typedef sckcr_t<0x0008'0020> SCKCR_;
        static SCKCR_ SCKCR;

rw32_t クラスは、以下のように変更。

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    /*!
        @brief  Read/Write 32 bits アクセス・テンプレート
        @param[in]  adr アドレス
        @param[in]  wov 書き込み OR 値(通常0)
    */
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    template <address_type adr, uint32_t wov = 0>
    struct rw32_t {

        typedef uint32_t value_type;

        static constexpr auto address = adr;    ///< アドレス定義
        static constexpr auto write_or_value = wov; ///< 書き込み OR 値
        static constexpr uint8_t BUS = 32;      ///< バス幅
        static constexpr bool RD = true;        ///< 読出し
        static constexpr bool WR = true;        ///< 書き込み

        //-----------------------------------------------------------------//
        /*!
            @brief  書き込み
            @param[in]  data    書き込み値
        */
        //-----------------------------------------------------------------//
        static void write(value_type data) noexcept { wr32_(adr, data | wov); }

...

    };

テンプレートパラメーター、wov は、何も指定しない場合、「0」なので、影響を与えない。
書き込み時に「0」を OR するのが余計だと思うかもしれないが、最適化されると、その操作は削除されてて無くなるので通常動作で余分なマシンサイクルを消費しない。
最適化しない場合、余分なコードが大量に生成されてしまうので、専用関数とするべきかもしれない・・


まとめ

実装時、かなり注意しているが、間違いを避ける事は難しい、集中している時は、それも少ないとは言え、何かの別作業が間に入ったりすると、凡ミスも多くなる。
少し前から、ペリフェラルの定義を検証する為の仕組みを入れ始めている。
重要な部分はユニットテストなどを行うしかないが、テストコードを生成する、良い方法を考えないと現実的では無いとも思う。
これは、すこし考えたい・・
ハードウェアーマニュアルから必要な部分を抽出して、テストコードを自動生成するような事が必要かもしれない・・

RXマイコン、RX631/RX63N をサポート開始

最終的にはRXマイコン全サポートしたい!

かなり昔、RX63N が出た時期、176ピン版を購入した。(今は販売していない)

その時、変換基板も同時に購入して、実験基板を作ろうとしていたが、ピンの配置間隔がハーフピッチずれたバグ基板を掴まされ、作る気力が萎えてしまった・・
※ハーフピッチずれている為、ユニバーサル基板に乗せる事が出来ない。

そうこうしているうちに RX64M が出て、それを購入、品質の高い変換基板も購入、実験基板を制作して動かすまでになった。
そんなこんなで、RX631/RX63N はサポートをしていなかった。

デバイスは持っているので、実験しないと肥やしになるだけだし、ペリフェラル定義も、共通部分が多い事から RX220 サポートの勢いで進めていた。
必要最低限のピンを接続して、とりあえず動作する状態にしたい。

RXマイコンも、未だ購入が出来ない状態が続いているので、シリーズを増やすにしても、何とも歯がゆい状態が続いている。


GR-CITRUS を買う

基板を作る準備をしていたが、面倒になり、停滞していた。

そんな時、秋月のRXマイコン関係で、GR-CITRUS が1500円(通常2200円)の処分価格で売られている事を発見し、他の部品と共に注文した。
※使っていないピンを出していないとか、かなり不満の残るボードだが、1500円ならまーいいかと思って購入。

GR-CITRUS は、標準では USB 接続でフラッシュを書き換えるようになっている。
※MD端子は出ているが、2.54mm ピッチでは無い、狭いフットプリントになっているのが駄目・・(何で?)

RX631/RX63N は、フラッシュプログラム「rxprog」もサポートしたいので、外部にSCI1、MD 端子などを出してシリアルブート出来るように改造した。

RX631/RX63N は RX63T に近いプログラミングフォーマットとなっており、簡単に実装出来た。
マイクロマウスでRX631を使っている人が、rxprog を改造して使っているようだが、最新バージョンではコンパイルするだけで利用出来ると思う。

プログラムの書き込みは何の問題もなく出来た。

GR-CITRUS でシリアル書き込みを行う場合、P30(RXD1)、P26(TXD1) を配線する必要がある。
又、PC7 を抵抗でプルダウンする必要がある。
P26 は J5 によって、P05/DA1 ピンと共有するのだが、そうすると P05 を使えなくなる。
なので、J5 の P26 側にだけ配線を行い、外部に出す。
折角 100 ピンの RX631 を実装しているのに、多くのピンが未接続だし、ピンを共有していたり(何かの互換の為?)、ハッキリ言って糞ボードだと思う。
以上の点を許容できる人のみ購入を検討してみるのが賢明と思う。


クロックのブーストでハマる

RX631/RX63N は RX63T に近いクロック機能なので、RX63T のコードをコピーして少し手直しした。

とりあえず、LED 点滅「FIRST_sample」を書き込んだが、点滅しない・・・

調べると、クロック速度が遅い状態で、先に進まないようだ。
RX63T では動いていたから、何か違いがあるのか、色々調べたり、クロック関係のレジスタに直で値を入れたり、色々やったが全く駄目・・・
高速内部発振器「HOCO」では、ちゃんと動作しているようで、何で???と、数時間悩んだ・・・

そして、ようやく謎が解けたー

システムクロックコントロールレジスタ(SCKCR)の予約ビットに「0b0001」を書き込む必要があり、それが「0b0000」だと、ICLK が正しい周波数にならない・・

読み出すと「0b0000」なので、何も対策しないとハマる・・・

            device::SYSTEM::SCKCR = device::SYSTEM::SCKCR.FCK.b(clock_div_(clock_profile::FCLK))
                                  | device::SYSTEM::SCKCR.ICK.b(clock_div_(clock_profile::ICLK))
                                  | device::SYSTEM::SCKCR.BCK.b(clock_div_(clock_profile::BCLK))
                                  | device::SYSTEM::SCKCR.PCKA.b(clock_div_(clock_profile::PCLKA))
                                  | device::SYSTEM::SCKCR.PCKB.b(clock_div_(clock_profile::PCLKB))
                                  | 0b0001'0001;

この修正を加えたら、システムクロックがブーストするようになった。

RX631 のソフトディレイを調整した。


現在のフレームワーク状態

現在、ペリフェラルの実装、動作確認、は以下のようになっている。

シリーズ コア FPU DFPU 動作確認 ペリフェラルクラス rx_prog サポート リンカーファイル
RX220 RXv1 No - R5F52206
RX631/RX63N RXv1 Yes - R5F5631F/NE
RX63T RXv1 Yes - R5F563T6
RX621/RX62N RXv1 Yes - R5F562N7/8
RX24T RXv2 Yes - R5F524T8/A
RX64M RXv2 Yes - R5F564MF/G/J/L
RX71M RXv2 Yes - R5F571MF/G/J/L
RX651/RX65N RXv2 Yes - R5F565NE
RX66T RXv3 Yes - R5F566TA/E/F/K
RX72T RXv3 Yes - R5F572TF/K
RX72N RXv3 Yes Yes R5F572ND/N
RX72M RXv3 Yes Yes R5F572MD/N

RX631/RX63N は、RX63T にフラッシュプログラムは近いので、rx_prog もサポートした。


まとめ

とりあえず、FIRST_sample、SCI_sample、RAYTRACER_sample などで動作確認を行った。

SCI_sample:

Start SCI (UART) sample for 'RX631 GR-CITRUS' 96[MHz]
SCI PCLK: 48000000 [Hz]
SCI Baud rate (set): 115200 [BPS]
  Baud rate (real): 115384 (0.16 [%])
  SEMR_BRME: false
  SEMR_BGDM: false
CMT Timer (set):  100 [Hz]
  Timer (real): 100 [Hz] (0.00 [%])
#

RAYTRACER_sample:

RX631 GR-CITRUS Start for Ray Trace: 320, 240
# Render time: 1886ms (1)

CALC_sample:(関数電卓サンプル)

# Rad
# tan(355/226)
 -7497258.185325587112905071831891248663417267943785263161571

CAN_sample:

  • コンパイルのみ、動作確認はしていない。

I2C_sample:

  • コンパイルのみ、動作確認はしていない。

PSG_sample:

  • DA1 出力をアンプに接続して、動作確認。

「rxprog」は、RX631/RX63N を追加して、プログレス表示で、%の表示を追加した。

GR-CITRUS は、メモリもそれなりに多く、今後、他プロジェクトでも、RX631 を追加して、動作確認をおこなっていく。
惜しいのは、使っていないピンをランドに出していない点、そして、一部のポート同士を接続してある点、これが無ければ、色々応用が出来るのだが・・

現状のコードは、Github にコミットしてあり、マスターブランチにマージ済。

RXマイコンC++フレームワーク、RX220をサポート開始

RX220 マイコンをサポートする

半導体不足は未だ解消の気配は無く、RXマイコンを買うにしても、以前のような価格では流通していないし、バックオーダーで、買う事も出来ない。

RX220は、機能と価格で、CPはそんなに良くないが、秋月さんで売っているので、入手はしやすいだろうと思う。

  • DIPスイッチを逆に取り付けてしまったバージョンの基板なら比較的安価に購入できる。(1250円)
  • 以前RX72T(200MHz、RXv3コア)が10個で@600円くらいだった事を考えると、最大32MHzでRXv1コアはあまり触手が伸びない。
  • RX220はFPUも内蔵していない・・
  • 既に購入済で、積みボードになっている人もいるかもしれない。

とりあえず、RXマイコン全制覇を目論んでいるし、200番台をサポートするのは、それなりに価値がある。


秋月RX220ボードの改造

秋月さんのRX220ボードは、そのままでは多少使いづらい・・
このボードでは、内蔵フラッシュを書き換えるには、シリアル書き込みがほぼ標準的となる。
その場合、SCI1を使う事になるが、そのままだと、RSー232Cのレベル変換ICに接続されている。
今や、PCとの通信でRSー232Cを使う事は「稀」で、FT232やCP2102NなどのUSB/シリアル変換モジュールを使って、ロジックレベルで行うのが標準的となっている。
そうすると、RXマイコンのTxDは出力なので問題無いとしても、Rxdは入力となっていて、レベル変換ICの出力が接続されているので、モジュールのロジック端子を繋ぐ事ができない。
そこで、ボードのパターンをカットして、接続できるように改造した。
※何かの記事で読んだが、この「カットをする意味が判らない」と綴っている人がいた・・、これは、本当にビックリした、その程度の知識でマイコンをやってる人がいる現実に驚くばかり。
まぁ、でもマイコン掲示板で、自分で何も調べないで、いきなり質問する人や、初歩的と思えるような質問をする人、様々な人がいる現実を考えると、まぁそんなものかもしれない。


ソフトディレイの調整

RX220は最大32MHz(内蔵発振器動作)で動作する。

  • クロックジェネレーターにはPLL回路が無い為、外部にクリスタルを接続して利用する場合は、最大20MHzとなる。
  • クリスタルの発信器は、20MHzを超えると、ちょっと特殊な回路にしないと発振が安定しない(発振しない)ので、そうなっていると思う。
  • ただ、外部クロック入力でも最大20MHzなので、その他の物理的な要因が関係しているのかもしれない。
  • 内部発信器だと、正確性やジッタの問題があるとも思うが、意外と安定していると思う。
  • 内部発信器は最大50MHzで発振する事も出来るので、50MHzオーバークロックで動かしてみたが、普通に動作はするようだ。

最初、1マイクロ秒のソフト遅延を行う為、NOP命令のループ回数を調整していたが、思うように調整出来ない・・・
ある値を境に、遅くなったり、速くなったり、不思議な現象が発生した。

                for(uint32_t n = 0; n < device::clock_profile::DELAY_MS; ++n) {
                    asm("nop");
                }

・・・

少し考えたら、理由は判った、今まで、最低速度は、RX24Tの80MHzだったので、ループ回数はそれなりの値で問題無かった。
しかし、32MHzだと、ループ回数は少なく、ある値を境に、「asm("nop");」が、インライン展開されてしまう。

そこで、RX220の場合は、専用のAPIにした。

        static void delay_us() noexcept
        {
            // 定数(DELAY_MS)で指定すると、ループ数が少なくインライン展開され、予想した時間にならない為、直で’NOP’数で調整する。
            if(ICLK == 32'000'000) {  // 32MHz 用
                asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
                asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
                asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
                asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
            } else if(ICLK == 20'000'000) { // 20MHz 用
                asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
                asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop"); asm("nop");
                asm("nop"); asm("nop"); asm("nop");
            } else {
                for(volatile uint8_t i = 0; i < (ICLK / 1'000'000) - 10; ++i) {
                    asm("nop");
                }
            }
        }

rx_prog でも、RX220をサポート

最初、とりあえずルネサスフラッシュプログラマーで書き込みを行ったが、非常に不安定で、書き込みに失敗、そもそも接続も出来ないなどのトラブルが多発した。
この原因は追究していないが、USBシリアルデバイスがCP2102Nなのが問題なのかと思った。

  • CP2102Nは、FTDIより高速で、同じボーレートでも、転送にかかる遅延が非常に少ない為と思った。
  • RX200系は、RXマイコン初期の物なので、あまり枯れていないのかもと思った。
  • ルネサスフラッシュプログラマーの無料版は、ノークレームなので、改修を要求する事さえ出来ない。

そこで、まず、rx_prog にRX220のプロトコルを追加する事にした。
ブートモードの説明を斜め読みした感じでは、RX63Tとほぼ同じ感じで、そのまま行けると感じた。

「rx_prog.conf」に、RX220 デバイスのプロファイルを追加して、「rx220_protocol.hpp」を追加、説明と照らし合わせた。

R5F52206 {
    group = "RX220"
    clock = 3200
    divide_sys = 1
    divide_ext = 1
    rom = 256K
    ram = 16K
    data = 8K
    comment = "; RX220 Flash:256K DataFlash:8K RAM:16K"
    rom-area  = FFFC0000,FFFFFFFF
    data-area = 00100000,00101FFF
    ram-area  = 00000000,00003FFF
}

「rx63t_protocol.hpp」ほぼ同じでOKだったが、ファイルは別けておいた。

まず、コネクションを試してみた。

 % rx_prog -d RX220 --verbose
# Platform: 'Cygwin(MSYS2)'
# Configuration file path: '/usr/local/bin/rx_prog.conf'
# Group: 'RX220'
# Serial port path: 'COM7'
# Serial port speed: 230400
# Erase Page Wait: 2000 [uS]
# Write Page Wait: 5000 [uS]
# Serial port alias: COM7 ---> /dev/ttyS6
# Serial port path: '/dev/ttyS6'
# Device: R5F52206 (first find)
#   Master clock: 32.00 MHz
#   ICLK multiplier: 1 (32.00 MHz)
#   PCLK multiplier: 1 (32.00 MHz)
Connection OK. (RX62x)
#01/01: Device: RX200 Series (LittleEndian)
#01/01: Device ID: 0x33306A37
#01/01: Clock Mode: 0x00
#01/02: Multiplier: 1
#02/02: Multiplier: 1
#01/02: Frequency Min: 32 MHz, Max: 32 MHz
#02/02: Frequency Min: 32 MHz, Max: 32 MHz
#01/01: Change baud rate: 115200
#01/01: Boot Area: FF7FC000, FF7FFFFF
#01/01: Area: FFFC0000, FFFFFFFF
#01/26: Area: FFFFF000, FFFFFFFF
#02/26: Area: FFFFE000, FFFFEFFF
#03/26: Area: FFFFD000, FFFFDFFF
#04/26: Area: FFFFC000, FFFFCFFF
#05/26: Area: FFFFB000, FFFFBFFF
#06/26: Area: FFFFA000, FFFFAFFF
#07/26: Area: FFFF9000, FFFF9FFF
#08/26: Area: FFFF8000, FFFF8FFF
#09/26: Area: FFFF4000, FFFF7FFF
#10/26: Area: FFFF0000, FFFF3FFF
#11/26: Area: FFFEC000, FFFEFFFF
#12/26: Area: FFFE8000, FFFEBFFF
#13/26: Area: FFFE4000, FFFE7FFF
#14/26: Area: FFFE0000, FFFE3FFF
#15/26: Area: FFFDC000, FFFDFFFF
#16/26: Area: FFFD8000, FFFDBFFF
#17/26: Area: FFFD4000, FFFD7FFF
#18/26: Area: FFFD0000, FFFD3FFF
#19/26: Area: FFFCC000, FFFCFFFF
#20/26: Area: FFFC8000, FFFCBFFF
#21/26: Area: FFFC4000, FFFC7FFF
#22/26: Area: FFFC0000, FFFC3FFF
#23/26: Area: 00101800, 00101FFF
#24/26: Area: 00101000, 001017FF
#25/26: Area: 00100800, 00100FFF
#26/26: Area: 00100000, 001007FF
#01/01: Program size: 256 Bytes
#01/01: ID Protect: false

問題無い。

次に、書き込み、ベリファイも試して、問題無かった。
rx_prog は、多少書き込み速度が遅いものの、安定して書き込めるし、OS-X、Linux でも同じように動作する実績がある。
※RX220 は、OS-X、Linux では試していないけど・・

rx_prog -d RX220 --progress  --write --verify sci_sample.mot
Write:  #################################################
Verify: #################################################

これで、RX220を正式サポートした事になると思う。

Makefile は、以下の部分のみ異なるだけで良く、RX220 に移る事は簡単だ。

DEVICE      =   R5F52206

RX_DEF      =   SIG_RX220

まとめ

現状、サンプルプログラムは、「FIRST_sample」、「SCI_sample」のみだが、今後拡充してゆく予定。
※基本、各プロジェクトで、Makefileを用意すればOKだが、まだ、RSPIや、RIIC(I2C)ペリフェラルの追加などをしていない。

RX220 は浮動小数点を扱うとエミュレーションになってしまうが、「utils::format」の表示関係は、内部はほぼ整数を使っているし、速度以外はそれなりに使えると思う。
もう少し安価に入手できれば・・・
それでも、32ビットなので、RL78などの8ビット系に比べて大きなアドバンテージがあるのは言うまでも無い。

Start SCI (UART) sample for 'AE-RX220' 32[MHz]
SCI PCLK: 32000000 [Hz]
SCI Baud rate (set): 115200 [BPS]
  Baud rate (real): 117647 (2.08 [%])
  SEMR_BRME: false
  SEMR_BGDM: false
CMT Timer (set):  100 [Hz]
  Timer (real): 100 [Hz] (0.00 [%])
#

現在、RX631/RX63N もサポート中で、秋月ユーザーでも、C++ フレームワークを使ってみる機会がそれなりに増えると思う。

C++ に対する嫌悪感

主にC言語しか使わない人は、C++ に対する嫌悪感が半端ない事が多い。
また、C++ は判らないし、難しそうだから近寄らない人も多い。

しかしながら、マイコン初心者(プログラムの経験が全く無い人)に教える場合、C++ から始めても、そんなに敬遠したりしない事が判っている。
※もちろん、最初はあまり多くを示さないで、簡単な事、理解しやすい事、シンプルな事から始める。
むしろ、半端にプログラム出来る人より、飲み込みが速く、応用が利く人が多いように思う、これは、教え方次第のように思う。
年齢は関係無い、若い人は頭が柔らかく、吸収する力が大きいように感じる。

C++だと、コンパイラが教えてくれる事が多く、小さなミスは、ほぼ起きなくなるし、柔軟で応用範囲が広いライブラリなど、利便性が高い。

今回 RX220 をサポートしたが、アプリケーションレベルでは変更が全くなく、同じように動作する。

今後、勉強会や、講習会、YouTubeビデオなど、学べる機会や媒体を増やしていく予定でいる。

RXマイコン、C++、sci_io クラスの機能追加(RS-485)

RS-485

RS-485 は、非同期シリアルに RS-485 用ドライバを付け、若干のソフトを追加するだけで、利用出来る。
ドライバーは、差動信号を使い、ノイズに強く、長い通信路でも、信号の品質を維持する事が出来る。
ネットワークのトポロジーとして、CAN のような構成にできて、複数の機器を相互に接続出来る。
詳しくは、RS-485 の解説を参照してもらいたい。

但し、半二重通信なので、送信を行うには、送信ゲートを適切にコントロールする必要がある。
また、プロトコルを実装して、クライアントと通信するので、全体の構成を考える必要がある。
受信だけなら、流れてくるパケットをデコードするだけなので簡単だが、送信するには、受信データを監視して、タイミングを守る必要がある。
プロトコルは規定されていないが、PLC、インバーターなどで良く使われるものがあるようだ。

今回は、三相モーターのインバーターと通信するのがとりあえずのゴール。


sci_io クラスに機能を追加

sci_io クラスは、SCI を使った非同期シリアル通信を扱うクラスとなっている。

今回、RS-485 の送信ゲート制御を追加した。

一つのクラスに、あまり多くの機能を盛り込むのは、設計上別の問題もあるが、色々検討した結果、少しの機能追加で行える事が判ったので、機能追加とした。

RS-485 のゲート制御は、テンプレートパラメータで決定する為、通常の SCI 通信では、余分なコードが残らないように配慮してある。


機能を切り替える仕組み

定義は以下のようなもので、通常の SCI 定義を拡張したものとなっている。
ハードフロー制御(RTS)と共用となっているので、enum class の FLOW_CTRL 型に、RS485 を含めてあり、テンプレートパラメータで指示する。

    typedef utils::fixed_fifo<char, 1024> RS485_RXB;  // RS-485/RX (受信) バッファの定義
    typedef utils::fixed_fifo<char, 512>  RS485_TXB;  // RS-485/TX (送信) バッファの定義

    typedef device::PORT<device::PORT3, device::bitpos::B3> RS485_DE;   // for MAX3485 DE
    typedef device::sci_io<RS485_CH, RS485_RXB, RS485_TXB, device::port_map::ORDER::SECOND, device::sci_io_base::FLOW_CTRL::RS485, RS485_DE> RS485;
    RS485   rs485_;
  • RS-485 ドライバーの DE(送信ゲート)を制御する為、ポート定義を同時に行う。
  • RS-485 ドライバーの受信ゲートは、常に有効にしてある。
  • RS-485 ドライバは、ループバックしているので、送信した文字列をそのまま受信する。
  • 送信した文字列と受信した文字列が等しければ、衝突は発生せず、正しく送信出来た事を保障する事が出来る。
  • RS-485 ドライバーは、MAX3485 を使っている。(3.3V 動作品)

DE ポートの制御

  • RS-485 の送信ゲート制御は、送信データ列が出ている間だけ、送信ゲートを有効にする必要がある。
  • RX マイコンの SCI では、シリアル送信中のデータ列が出ている期間を知る手法はいくつかあるのだが、送信データがバッファリングされている為、単純な方法では、うまくいかない。
  • 送信割り込みは、送信が可能になったタイミングで発生する。
  • ストップビットを含めたシリアルデータが全て送られたタイミングで「送信終了割り込み」が発生する。
  • 色々検討して実験した結果、送信開始前に、ゲートを有効にして、送信 FIFO が「空」になったら、送信終了割り込みを発生させ、そのタイミングでゲートを閉じるようにした。


9600bps


送信終了割り込み(TEI)のハンドリング

送信終了割り込み(TEI)は多少厄介で、一工夫が必要となっている。
それは、マイコンによって、通常割り込みの場合と、グループ割り込みの場合がある為で、それを正しく管理する必要がある。

  • RX621/RX62N/RX63T/RX24T では通常割り込み。
  • RX64M/RX71M/RX65N/RX72N/RX66T/RX72T ではグループ割り込み。
        static inline void tei_task_()
        {
            if(send_.length() == 0) {
                RTS::P = 0;
            }
            SCI::SCR.TEIE = 0;
        }

        static INTERRUPT_FUNC void tei_itask_()
        {
            tei_task_();
        }

        void set_intr_(uint8_t level) noexcept
        {
            if(level > 0) {
                icu_mgr::set_interrupt(SCI::RXI, rxi_task_, level);
                icu_mgr::set_interrupt(SCI::TXI, txi_task_, level);
                if(FLCT == FLOW_CTRL::RS485) {
                    auto gv = icu_mgr::get_group_vector(SCI::TEI);
                    if(gv == ICU::VECTOR::NONE) {
                        icu_mgr::set_interrupt(SCI::TEI, tei_itask_, level);
                    } else {
                        icu_mgr::set_interrupt(SCI::TEI, tei_task_, level);
                    }
                }
            } else {
                icu_mgr::set_interrupt(SCI::RXI, nullptr, level);
                icu_mgr::set_interrupt(SCI::TXI, nullptr, level);
                if(FLCT == FLOW_CTRL::RS485) {
                    icu_mgr::set_interrupt(SCI::TEI, nullptr, level);
                }
            }
        }

現在、RX マイコン C++ フレームワークでは、グループ割り込みは、標準のディスパッチルーチンから呼ばれるので、割り込みタスクの属性を適切に設定する必要がある。

SCI::TEI(送信終了割り込み)がグループベクターの場合は、通常のタスクを登録し、グループベクターでは無い場合には、「INTERRUPT_FUNC」属性を付与した関数を登録する。
「INTERRUPT_FUNC」属性では、「RTE」オペコードで終了する。(通常関数は「RTS」オペコード)

RX24T の場合、「TEI」は通常ベクターで、グループでは無いので、「VECTOR::NONE」が返る。

        static ICU::VECTOR get_group_vector(ICU::VECTOR vec) noexcept {
            return ICU::VECTOR::NONE;
        }

RX72T の場合、「TEI」は「VECTOR_AL0」なので、「VECTOR::GROUPAL0」が返る。

        static ICU::VECTOR get_group_vector(ICU::VECTOR_AL0 vec) noexcept {
            return ICU::VECTOR::GROUPAL0;
        }

「icu_mgr::get_group_vector(SCI::TEI);」で、「SCI::TEI」がグループベクターなのか、そうでないのか判定出来る。
C++ では「型」の違いで、コンパイラが自動で関数を呼び分ける事ができ、処理を切り替える事が可能なので、柔軟性が大きい。
この判定は、定数が返るだけなので、最適化がされると、分岐や判定が綺麗に消えて、無駄なコードが残らない為、余分なメモリとマシンサイクルを節約する。
このような精妙な仕組みがスマートに実装出来るのは C++ の特徴となっている。
このような仕組みはC言語では難しい。


グループベクターのハンドリング

自分のフレームワークでは、割り込みなどは登録制にしてあり、グループベクターも登録制となっている。

        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        /*!
            @brief  GROUPAL0・ベクター型
        */
        //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
        enum class VECTOR_AL0 : uint8_t {
            TEI11 = 12,     ///< SCI11 / TEI11
            ERI11,          ///< SCI11 / ERI11

            SPII0 = 16,     ///< RSPI0 / SPII0
            SPEI0,          ///< RSPI0 / SPEI0
            NUM_ = 4
        };

SCI11 の送信終了割り込み「TEI11」は「グループベクター AL0」のグループで、上記番号は、レジスターのビット位置となっている。
グループ割り込みが発生した場合に該当する処理を呼び分けるディスパッチルーチンはなるべく高速に実行したいので、割り込みタスク登録時に必要なデータを登録してある。

        typedef icu_utils::dispatch<ICU::VECTOR_AL0> GROUPAL0_dispatch_t;
        static GROUPAL0_dispatch_t GROUPAL0_dispatch_;

        template<typename GRPV>
        class dispatch {
...
            void set_task(GRPV grpv, GTASK task) noexcept
            {
                uint32_t bits = 1 << static_cast<uint32_t>(grpv);
                for(uint32_t i = 0; i < NUM; ++i) {
                    if(bits_[i] == bits) {
                        bits_[i] = 0;
                        task_[i] = nullptr;
                        break;
                    }
                }
                for(uint32_t i = 0; i < NUM; ++i) {
                    if(bits_[i] == 0) {
                        bits_[i] = bits;
                        task_[i] = task;
                        break;
                    }
                }
            }

            void run(uint32_t togo) const noexcept
            {
                for(uint32_t i = 0; i < NUM; ++i) {
                    if(bits_[i] == 0) break;
                    if((bits_[i] & togo) != 0 && task_[i] != nullptr) {
                        (*task_[i])();
                    }
                }
            }
        };

        static INTERRUPT_FUNC void group_al0_handler_() noexcept
        {
            GROUPAL0_dispatch_.run(ICU::GRPAL0());
        }

        static void install_group_task(ICU::VECTOR_AL0 grpv, icu_utils::GTASK task) noexcept
        {
            ICU::GENAL0.set(grpv, false);
            set_task(get_group_vector(grpv), group_al0_handler_);
            GROUPAL0_dispatch_.set_task(grpv, task);
            if(task != nullptr) {
                ICU::GENAL0.set(grpv);
            }
        }
  • dispatch::run(togo) は割り込み要因 GRPAL0 レジスタを引数に呼ばれる。
  • 登録されたデータに従い、タスクを呼び出す。
  • この辺り、部分的な実装を抜き出しているので雰囲気だけなので、実際は、github のコードを観て下さい。

RX72T 関係
icu_utils 関係


まとめ

  • 現在サポートしているRXマイコンは10種程度に及ぶので、良く考えて実装しないと、修正が大掛かりになる場合もある。
  • 同じような機能を提供するクラスや関数をなるべく共有できるようにしないと、全ての品種で恩恵が薄くなる。

C++ だと、テンプレートや、C++11、C++14、C++17 で備わった機能など色々使って、かなりシンプルに実装が出来る、速度も速い!
テンプレートの場合、コンパイルがエラー無く通ると、大体ちゃんと動く場合が多い。
そして、ほとんどが、ヘッダーのみに全て実装出来る、なんて便利なんだろうといつも思う、利用する人が増えれば良いのにと思う。

RX62Nのフラッシュ書き換えツール実装でまた発見!

基板の提供ありがとう~

基板の提供を受けました、「Lathe」さん大変ありがとうございます。


RX62N の フラッシュ書き換えツール対応

RX62N の C++ フレームワーク対応も、ほぼ出来上がり、これで、本格的に使えるようになった感じ。

一番厄介だった、MTU 関係も、何とかなり、ブログに記事をまとめていたのだが、


とりあえず、フラッシュの書き換えは、「Renesas Flash Programmer V3.06.01(無償版)」を使って USB 接続で書き換えしていた。

しかし、書き換えの度に、USB 接続をしたり切ったりするのが何だかなぁーと思って、遅くてもシリアルで書き換え出来るようにしておこうと思い、SCI1 にコネクタを接続しておいた。

そして、フラッシュ書き換えツールも対応しておこうと思い、ブートモードの解説を観ていたら、どうやら、これは RX63T にかなり近い仕様だと判った。
RX63T のリソースを使い、それを改造すれば割と簡単に対応可能だと判り実装を始めた。


奇妙な事を発見

まず、最初は、

  • ブートモードで起動
  • 接続
  • シリアルの通信速度をキック
  • デバイス情報の取得
  • 書き換え

ざっと、こんな感じなのだが、その過程で、「デバイス情報取得」で奇妙な事が起こっていた。

 % rx_prog -d RX62N --verbose
# Platform: 'Cygwin'
# Configuration file path: 'rx_prog.conf'
# Device: 'RX62N'
# Serial port path: 'COM7'
# Serial port speed: 230400
# Erase Page Wait: 2000 [uS]
# Write Page Wait: 5000 [uS]
# Serial port alias: COM7 ---> /dev/ttyS6
# Serial port path: '/dev/ttyS6'
Connection OK. (RX62x)
#01/01: Device: RX600 Series
#01/01: Device ID: 0x35307936
#01/01: Clock Mode: 0x00
#01/02: Multiplier: 1, 2, 4, 8
#02/02: Multiplier: 1, 2, 4, 8
#01/02: Frequency Min: 8 MHz, Max: 100 MHz
#02/02: Frequency Min: 8 MHz, Max: 50 MHz
#01/01: Change baud rate: 115200
#01/01: Boot Area: FF7FC000, FF7FFFFF
#01/01: Area: FFF80000, FFFFFFFF
#01/54: Area: FFFFF000, FFFFFFFF
#02/54: Area: FFFFE000, FFFFEFFF
#03/54: Area: FFFFD000, FFFFDFFF
#04/54: Area: FFFFC000, FFFFCFFF
#05/54: Area: FFFFB000, FFFFBFFF
#06/54: Area: FFFFA000, FFFFAFFF
#07/54: Area: FFFF9000, FFFF9FFF
#08/54: Area: FFFF8000, FFFF8FFF

...

#50/54: Area: 00102000, 001027FF
#51/54: Area: 00101800, 00101FFF
#52/54: Area: 00101000, 001017FF
#53/54: Area: 00100800, 00100FFF
#54/54: Area: 00100000, 001007FF
#01/01: Program size: 256 Bytes
#01/01: ID Protect: false

このデバイスは、「R5F562N7」なので、「フラッシュ:384K、RAM:64K」品のハズなので、
「Area:」は、FFFA0000 から始まるハズなのだが・・・

ん??

これは、もしや・・・

物理的なデバイスは、全て「R5F562N8」と同じ物で、デバイスIDで識別しているだけなのでは?

そこで、Makefile のデバイス名を切り替えて、プログラムを書き換えると、普通に書き換え出来たーーー

# BlueBoard-RX62N_100pin
#DEVICE     =   R5F562N8
# FRK-RX62N (CQ出版)
#DEVICE     =   R5F562N7
DEVICE      =   R5F562N8
USER_DEFS   =   CQ_FRK
Memory Configuration

Name             Origin             Length             Attributes
RAM              0x00000000         0x00017a00         w
USTACK           0x00017e00         0x00000004         w
ISTACK           0x00018000         0x00000004         w
ROM              0xfff80000         0x0007ffd0         w

そして普通に動く!!!

やっぱりね・・

まぁ、そういう事なのだろう。

驚いた事に、ルネサス、フラッシュプログラマーでも、普通に書き換えが出来、動くようだ・・

とゆー事は、「刻印」が違うだけなのか・・・


まぁ、ROM が 384K から 512K に増えても、そんなに大きなプログラムを作らない限り変わらないかもしれないが、RAM が 64K から 96K だと、やはり使いかってが違うと思う。


まとめ

これは、今回のボードに載っているデバイス特有の事なのかもしれない・・

このボード、かなりの数を出荷したと思うが、当時、「7」の384K品が不足していた為、512K品を刻印だけ変えて出荷したとも考えられる。

他に試せるデバイスを持っていないので、判らないが・・・

まぁ、どちらにしても、うれしい誤算である事は言うまでもない。

このボードを持っている人は試してみる事を勧める~

R8C、RX開発環境のアップデート

R8C の開発環境が作れないとのツイートをもらう・・

先日、Twitter で 過誤出来ないツイートをもらった。

ツイートは短く、詳細は不明なので、実際にどんな事が起きているのか判らなかった。

何度かやりとりをする中で、どうやら、これは Linux 環境で発生している事が判った。

その要因は、最新の gcc 環境(Version 11)などで、gcc-4.9.4 の C++ ビルドで失敗する事が判った。

そういえば、Windows の MSYS2 環境もしばらくアップデートしていない、そこで、まずは、MSYS2 をアップデートする事から始めた。
※Linux 環境は、ノートPC にあり、古いので、新しい環境に入れ直す必要があり、確認するのも時間がかかる。

pacman -Sy pacman
pacman -Syu

この段階で、データベースの更新に失敗して、先に進まない・・

MSYS2 は、かなり更新しているようで、根本的にシステムが大幅に変わったようだ、そこで、インストールからやり直す事にした。

念の為、MSYS2 のコア部分、「C:\msys64」をリネームして、残しておいた。

最新版をインストールして、必要なツールをインストール。
※複数パッケージのインストールが、マルチスレッドで同時進行するようになっているw

MSYS2 はアイコンが少し新しくなり、大きな変更があったようだ。

また、新たな環境が二つ追加された:

  • MSYS
  • mingw32
  • mingw64
  • ucrt64(追加)
  • clang64(追加)

※追加された環境が、どのような特徴があるのか調べていない。(clang64 は何となく判る)

MSYS のカレント gcc は11系になっている。

gcc (GCC) 11.3.0
Copyright (C) 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

次に、R8C 用 gcc のビルドにとりかかる。
gcc のビルドは、MSYS で行う。(この環境がもっとも Linux などに近い)

手順を進めていって、やはり、gcc C++ の構築でエラーが発生して止まる・・・

うーーん、これは、どうしたものか・・・

そもそも、gcc-4.9.4 は古すぎると以前から思っていた。
しかし、開発環境を変更する事で、発生する別の問題を恐れて「まぁ動いているから枯れた方がいいかな」とも思っていた。

この機会に、手始めに R8C の開発環境をアップデートして、gcc-11 でエラー無くコンパイル出来るようにした方が建設的ではと思った。
この段階で、エラーを報告してくれた人は、ネットの情報を精査して、configure で生成された Makefile に、C++11 のオプションを付ける事で回避したようだ。
※なるほど、その回避もあるよなぁーと思ったが、やはり、gcc のビルドで特別な事を行うのは少し抵抗がある。


RX マイコンの開発環境では、最近は GNU-RX(魔改造されている)を使っている為、素の gcc を使う事が無くなっている。

RX のツールチェインは、以下の組み合わせとなっている。

binutils-2.34
gcc-7.5.0
newlib-2.4.0

組み合わせは重要で、リリースが同じくらいのパッケージを組み合わせないと、ビルドが通っても、コンパイル中にインターナルエラーで止まったり、
出来たコンパイラで作ったバイナリーをマイコンに焼いても動作しないなど、色々なトラブルが起こったりする。

そこで、R8C(m32c-elf)のビルドを上記組み合わせで作ってみた。

ビルド途中で、エラーで、失敗する・・・

うーーーん・・・

この組み合わせは、m32c-elf では相性が悪い・・・

そこで、少し古いバージョンの組み合わせで、色々試してみた。
m32c-elf は多分、メンテナンスされていないので、欲張らずにそこそこ新しい物で我慢する方が安全と考えた。
SSD(1TB) と、大きな主記憶(32GB)で武装された、最新の PC(Rizen7) でも、gcc のビルドは、そこそこの時間を要する。

色々、試して:

  • binutils-2.28.1.tar.gz
  • gcc-6.4.0.tar.gz
  • newlib-2.4.0.tar.gz

この組み合わせで、ビルドが通った。


boost 問題・・・

r8cprog など、一部のコードは、boost を使っている。

本来なら、MSYS 環境に boost を入れるのが良いと思うが、mingw64 などには対応しているが、MSYS 環境には無い。
そこで、mingw64 環境に入れた boost を間借りする形で使っていた。
しかし、新しい MSYS2 ではそのやり方では問題が発生する事が判った。

そこで、boost_1_74_0 のアーカイブを取ってきて、C ドライブのルートに展開し、そのパスを食わせる事で解決した。

この変則的なやり方は、あまりスマートとは言えないが、手順は難しく無いので、まぁ及第点だろうか・・


R8C のプロジェクトを全ビルド

新しく出来たツールチェインを使って、R8C のプロジェクトを全てビルドしてみた。

エラー無くビルドが通った。

とりあえず、「UART_sample」を動かしてみて、ちゃんと動作するバイナリーが出来る事も確認した。


RX 関係も確認

RX 関係も、一応確認した。

RX の gcc ビルドは問題無く通ったので、「良し」としたが、boost のパスは、R8C と同じく変更した。


RL78 環境

RL78 も、R8C と同じ環境にして、gcc をビルドしてみた。
これも、順調に通り、構築出来た。

しかし、プロジェクトをビルドすると、gcc がインターナルエラーで停止する・・・

rl78-elf-g++ -c  -std=c++17 -Wall -Werror -Wno-unused-variable -Wno-exceptions -Wno-unused-function -Os -mmul=g13 -DSIG_G13 -DF_CLK=32000000  -I. -I../ -I../G13  -o release/main.o main.cpp
In file included from main.cpp:15:0:
../common/format.hpp: In member function 'void utils::basic_format<CHAOUT>::out_fixed_point_(VAL, uint8_t, bool) [with VAL = long long unsigned int; CHAOUT = utils::stdout_chaout]':
../common/format.hpp:589:3: internal compiler error: in push_reload, at reload.c:1348
   }
   ^
unrecognized DWARF version in .debug_info at 6
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
make: *** [Makefile:112: release/main.o] Error 1

うーーーん、これは痛い・・・

そーいえば、ルネサスさん、RL78 用に LLVM ベースのコンパイラをリリースしているんだよなぁー、アレ試してみたいんだよなぁー

今ここ。


まとめ

とりあえず、R8C、RX 関係は、何とかなったので、RL78 も何とかしたいけど、時間切れ。
Linux 環境も試しておく必要があるし、まだ、時間がかかる。

R8C の教材も中途だし、中々先に進まない。

しかし、Windows の最新環境にマッチするように改修したのは、大きな進歩と思える。

RXマイコン、RX621/RX62N のサポート

※昔に購入した RX62N が載った格安ボード、確か2000円くらいで買った覚えがあるが、現在は5000円くらいする。


古い、RX621/RX62N のサポート

RX621/RX62N は、そこそこ古いRXマイコンのグループで、C++ フレームワークの出発点となった記念すべきCPUでもある。

しかし、新しいグループがリリースされ、使わなくなり、機能的に見劣りするのと、新規に購入するのもコスト的に見合わないので、ある時期から「レガシー」として、サポートをやめてしまった。

ところが、現在、政治的な動きに係る半導体不足から、最近リリースされた新しいデバイスの購入が殆ど出来なくなっており、いつ解消するかも不透明となっている。
RX621/RX62N は、かなり昔のデバイスで、そこそこ流通しており、かなり昔に、本の付録として流通した事もあるし、秋月では、未だに販売もされている。
なので、持っている人で肥やしになってる人も少なからずいるのではないか?

最終的には、RXマイコン全制覇を目論んでいるので、そろそろ、仕組みを考えておくのも必要だと考えていたので今回のサポートは丁度良いタイミングとなっている。

速度的には、100MHz 動作で、浮動小数点演算器も持っているデバイスなので、パフォーマンス的には、現在でもそんなに悪くなく、機能もそこそこあるので、何か作る場合でも、そんなに困らないのではと思う。

それでも、新規に購入しようとするとそこそこの価格だが、秋月で購入も可能なので、入手性など考えると、サポートしない理由はない。


構成を部分的に考え直して修正

この頃のRXマイコンは、現在の豊富な機能と比べると、かなり見劣りする。

C++ フレームワークでは、機能的に異なる部分を隠蔽するような仕組みを多数使っているので、「#if」などコンパイルの制御文を駆使しなくても、かなり綺麗に実装が可能となっている。
それでいて、最適化後のコードには、余分な部分が殆ど残らないので、速度低下もなく、上位の層(アプリケーション部分)は、ほぼそのまま再利用が可能となっている。

「#if」を多用して、細かい動作を切り替えているソースを読んだ事がある人は、判ると思うが、非常に読みにくく、デバッグも困難になる。
C++ では、そんな実装方法をとらなくても、最小限の分岐だけで、かなり複雑で柔軟な構成にできる。


FIRST_sample

まずは、LED 点滅から・・・

RX62x は、クロック生成部分が、非常にシンプルで、構成が大きく異なるので、専用のクラスとし、新規に書き直した。

ポートの構成も、大きく異なるので、専用のクラスとした。

各ファイルのインクルード制御は、common/device.hpp、common/renesas.hpp で行っている。

  • なので、アプリケーション側は、「common/renesas.hpp」をインクルードするだけで良い。

また、オシロスコープを使って波形を計測、ソフト遅延のパラメーターを適正な値に調整した。

この部分、「#if」で別けているので、定数を clock_profile に定義して参照するようにしないと駄目だな・・・
※今後改修する予定。


SCI_sample

  • SCI を動かすには、割り込みが必要なので、まずは、割り込み関係をサポート
  • 構成は、RX24T に近く、部分的に流用した
  • ついでに、他マイコンで、割り込み関係に係る部分を修正した

SCI 関係のペリフェラルは、現行のRXマイコンと、初期のRXマイコンでは、かなり異なる。

大きく異なるのは、ボーレートクロック生成の仕組みとなっている:

  • 倍速モードの追加
  • ボーレート変調レジスタの追加(比較的高いボーレートの場合に、クロックを間引いて、なるべく正確なレートになるように調整)
        //-----------------------------------------------------------------//
        /*!
            @brief  シリアル拡張レジスタ (SEMR)
            @param[in]  ofs     レジスタ・オフセット
        */
        //-----------------------------------------------------------------//
        template <uint32_t ofs>
        struct semr_t : public rw8_t<ofs> {
            typedef rw8_t<ofs> io_;
            using io_::operator =;
            using io_::operator ();
            using io_::operator |=;
            using io_::operator &=;

            bit_rw_t<io_, bitpos::B0> ACS0;
            bit_rw_t<io_, bitpos::B2> BRME;       // sci[g]

            bit_rw_t<io_, bitpos::B4> ABCS;
            bit_rw_t<io_, bitpos::B5> NFEN;       // sci[g]
            bit_rw_t<io_, bitpos::B6> BGDM;       // sci[g]
            bit_rw_t<io_, bitpos::B7> RXDESEL;    // sci[g]
        };

上記は、SEMR レジスタの定義だが、「sci[g]」は、新しいRXマイコンにはあるが、RX62x には存在しない。
現行の SCI 制御クラス(sci_io.hpp)では、全てを使ってボーレートを生成しているので、そのままでは、機能の無いマイコンには使えない。

RX62x に無いフラグやレジスタを定義から外す事も可能だが、それを行うと、sci_io.hpp のコンパイルが出来なくなってしまう。

  • なので、利用しているフラグビットは、常に存在するようにしないとならない(使う、使わないだけで別ける)
  • より厳密に行うには、そのビットにアクセスしても、無意味になるように出来るけど、それはやり過ぎと思ったので・・

そこで、SCI の定義クラスに、どのビットが有効なのかを宣言しておく。

  • sci_io クラスは、それを参照して利用するか、しないかを決定する。
  • 無効なビットに書き込む場合は、「0」を必ず書くようにする。
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    /*!
        @brief  SCIa 定義クラス
        @param[in]  base    ベース・アドレス
        @param[in]  per     ペリフェラル型
        @param[in]  txv     送信ベクター
        @param[in]  rxv     受信ベクター
        @param[in]  tev     送信終了ベクター
        @param[in]  pclk    PCLK 周波数
    */
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    template <uint32_t base, peripheral per, ICU::VECTOR txv, ICU::VECTOR rxv,
        typename INT, INT tev, uint32_t pclk>
    struct scia_t : public sci_core_t<base> {

        static constexpr auto PERIPHERAL = per; ///< ペリフェラル型
        static constexpr auto TX_VEC = txv;     ///< 受信割り込みベクター
        static constexpr auto RX_VEC = rxv;     ///< 送信割り込みベクター
        static constexpr auto TE_VEC = tev;     ///< 送信終了割り込みベクター
        static constexpr auto PCLK = pclk;  ///< PCLK 周波数

        static constexpr bool SEMR_BRME = false;    ///< BRME(ボーレート微調整)
        static constexpr bool SEMR_BGDM = false;    ///< BGDM(ボーレート倍速)

最近のRXマイコンでは:

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    /*!
        @brief  SCIg クラス
        @param[in]  base    ベース・アドレス
        @param[in]  per     ペリフェラル型
        @param[in]  txv     送信ベクター
        @param[in]  rxv     受信ベクター
        @param[in]  tev     送信終了ベクター
        @param[in]  pclk    PCLK 周波数
    */
    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
    template <uint32_t base, peripheral per, ICU::VECTOR txv, ICU::VECTOR rxv,
        typename INT, INT tev, uint32_t pclk>
    struct scig_t : public sci_core_t<base>, sci_core2_t<base> {

        static constexpr auto PERIPHERAL = per; ///< ペリフェラル型
        static constexpr auto TX_VEC = txv;     ///< 受信割り込みベクター
        static constexpr auto RX_VEC = rxv;     ///< 送信割り込みベクター
        static constexpr auto TE_VEC = tev;     ///< 送信終了割り込みベクター
        static constexpr uint32_t PCLK = pclk;  ///< PCLK 周波数

        static constexpr bool SEMR_BRME = true; ///< BRME(ボーレート微調整)
        static constexpr bool SEMR_BGDM = true; ///< BGDM(ボーレート倍速)
    };

RXマイコングループの違いは、以下のようになっている(#if が必要な部分)

  • SCI の基準クロックは、clock_profile に定義してあり、それを参照している。
  • RX62x の場合は「clock_profile::PCLK」、RX24T の場合は「colock_profile::PCLKB」となる。
  • SCI ハードウェアーの開始アドレスも大きく異なる。
  • RX72N などでは、割り込みの「型」も異なる。
#if defined(SIG_RX621) || defined(SIG_RX62N)
    typedef scia_t<0x00088240, peripheral::SCI0, ICU::VECTOR::TXI0, ICU::VECTOR::RXI0,
        ICU::VECTOR, ICU::VECTOR::TEI0, clock_profile::PCLK> SCI0;
    typedef scia_t<0x00088248, peripheral::SCI1, ICU::VECTOR::TXI1, ICU::VECTOR::RXI1,
        ICU::VECTOR, ICU::VECTOR::TEI1, clock_profile::PCLK> SCI1;
    typedef scia_t<0x00088250, peripheral::SCI2, ICU::VECTOR::TXI2, ICU::VECTOR::RXI2,
        ICU::VECTOR, ICU::VECTOR::TEI2, clock_profile::PCLK> SCI2;
    typedef scia_t<0x00088258, peripheral::SCI3, ICU::VECTOR::TXI3, ICU::VECTOR::RXI3,
        ICU::VECTOR, ICU::VECTOR::TEI3, clock_profile::PCLK> SCI3;
    typedef scia_t<0x00088268, peripheral::SCI5, ICU::VECTOR::TXI5, ICU::VECTOR::RXI5,
        ICU::VECTOR, ICU::VECTOR::TEI5, clock_profile::PCLK> SCI5;
    typedef scia_t<0x00088270, peripheral::SCI6, ICU::VECTOR::TXI6, ICU::VECTOR::RXI6,
        ICU::VECTOR, ICU::VECTOR::TEI6, clock_profile::PCLK> SCI6;
#elif defined(SIG_RX24T)
    typedef scig_t<0x0008A020, peripheral::SCI1, ICU::VECTOR::TXI1, ICU::VECTOR::RXI1,
        ICU::VECTOR, ICU::VECTOR::TEI1, clock_profile::PCLKB> SCI1;
    typedef scig_t<0x0008A020, peripheral::SCI1C, ICU::VECTOR::TXI1, ICU::VECTOR::RXI1,
        ICU::VECTOR, ICU::VECTOR::TEI1, clock_profile::PCLKB> SCI1C;
    typedef scig_t<0x0008A0A0, peripheral::SCI5, ICU::VECTOR::TXI5, ICU::VECTOR::RXI5,
        ICU::VECTOR, ICU::VECTOR::TEI5, clock_profile::PCLKB> SCI5;
    typedef scig_t<0x0008A0A0, peripheral::SCI5C, ICU::VECTOR::TXI5, ICU::VECTOR::RXI5,
        ICU::VECTOR, ICU::VECTOR::TEI5, clock_profile::PCLKB> SCI5C;
    typedef scig_t<0x0008A0C0, peripheral::SCI6, ICU::VECTOR::TXI6, ICU::VECTOR::RXI6,
        ICU::VECTOR, ICU::VECTOR::TEI6, clock_profile::PCLKB> SCI6;
    typedef scig_t<0x0008A0C0, peripheral::SCI6C, ICU::VECTOR::TXI6, ICU::VECTOR::RXI6,
        ICU::VECTOR, ICU::VECTOR::TEI6, clock_profile::PCLKB> SCI6C;

sci_io クラスでは、SCI に定義してある、値を参照して処理を切り替えている。

            // BGDM が使える場合、1/8 スタート
            uint32_t mtx = 8;
            uint32_t limit = 1024;
            if(!SCI::SEMR_BGDM) {  // BGDM が使えない場合 1/16 スタート
                mtx = 16;
                limit = 512;
            }
            uint32_t brr = SCI::PCLK / mtx / baud;
            uint8_t cks = 0;
            while(brr > limit) {
                brr >>= 2;
                ++cks;
                if(cks >= 4) {  // 範囲外の速度
                    port_map::turn(SCI::PERIPHERAL, false, PSEL);
                    power_mgr::turn(SCI::PERIPHERAL, false);
                    return false;
                }
            }

            // BGDM フラグの設定
            bool bgdm = true;
            if(SCI::SEMR_BGDM) {
                if(brr > 512) { brr >>= 1; bgdm = false; mtx <<= 1; }
            } else {
                bgdm = false;
            }
            bool abcs = true;
            if(brr > 256) { brr >>= 1; abcs = false; mtx <<= 1; }

C++ を知らない人は、最適化されても、余分なコードが含まれると思うかもしれないが、C++ の最適化では、参照先の状態に応じて、必要無い部分は、全て消してくれる。
テンプレートクラスでは、それが、究極的に行われる。
そして、必要な部分だけが、残る、コンパイル時に計算出来る部分は、計算され、定数が直接使われる。
※なので、constexpr などが重要な要素となる。


GNU-RX 8.3.0 の対応

今まで、RXv2 コアは、コンパイルオプション、「-misa=v2」を使っていたのだが、RXv2 コアは、昔と今では、多少異なるようだ・・・

RX62x で、「-misa=v2」でコンパイルすると、浮動小数点の計算で例外が出るようだ。
RX62x は、RXv1 コア。
※RX24T、RX65x などでは問題無い。
結局、RX62x では、「-mcpu=RX600」とする事で、適合するコードが生成される事が判った。

以下、makefile の共通部分:

ifeq ($(RX_DEF),SIG_RX62N)
  RX_CPU = RX62N
  RX_CHOOSE = -mcpu=RX600
  LDSCRIPT  =   ../../RX62x/$(DEVICE).ld
endif

ifeq ($(RX_DEF),SIG_RX24T)
  RX_CPU = RX24T
  RX_CHOOSE = -misa=v2
  LDSCRIPT  =   ../../RX24T/$(DEVICE).ld
  PROG_VERIFY =
endif

RAYTRACER_sample

少し大きいアプリを試しておく必要があるので、浮動小数点演算などが多く含まれたプログラムを走らせてみた。

RX62x は、RXv2 コアだが、fsqrt などの命令をサポートしないようだ・・
RX62x は、RXv1 コア
これが利いて、96MHz ではあるが、一番遅い・・

マイコン core fsqrt 命令 周波数 [MHz] 描画方式 時間 [ms]
RX62N RX600 X 96 8 bits, port-bus 1860
RX24T RXv2 O 80 8 bits, port-bus 1224
RX65N RXv2 O 120 Frame Memory 784
RX64M RXv2 O 120 16 bits, port-bus 751
RX66T RXv3 O 160 8 bits, port-bus 602
RX72T RXv3 O 192 8 bits, port-bus 464
RX71M RXv2 O 240 16 bits, port-bus 439
RX72N RXv3 O 240 Frame Memory 361
  • 単に動かしただけで、生成した画像を観ていないが、ストールせずに走るので、ちゃんと計算しているものと思う。
  • 余裕が出来たら LCD を接続して確認したい。

まとめ

RX62x のサポートがスムーズに出来たので、頃合いをみて、次は手持ちの RX63T をサポートしようと思う。
その前に、各サンプルで、RX62x のプロジェクトを追加する必要があるけど・・

それと、rx_prog で RX62x のフラッシュを書けるようにしたいが、これは、かなり昔のプロトコルなので時間がかかりそうだ・・・


雑誌付録の RX62N 基板を持っていて、譲っても良い人は連絡をくれると助かります。

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 のトラックを引くところまで済ます予定だったが、レンジ切り替えの問題で、先延ばしになった。

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