RX231 の動作確認
RX231 は、RX26T と同じ時期に購入してあったけど、中々作業が出来ないでいた。
RX26T も、落ち着き、余裕が出来たので実験基板を配線した。
今回、Flash:256K、RAM:32K のデバイスで、64 ピンパッケージを購入した、RX200 系は比較的安価な製品が多い。
いつものように、変換基板を直にユニバーサル基板へハンダ付けしている。
64 ピンだと、実験基板を作成するのは楽(電源ピンが少ない)なのだが、色々な機能をアサインする場合にピンが足りなくなる・・
RX231 は動作周波数が低く、それ程興味が無かったのもあって、なるべく安いデバイスを購入。
でも、100ピン版を購入しておくべきだったかもしれない・・・
Flash も 256K は少し物足りない・・・
RX231 の特徴
- RXv2 コア(最大 54MHz 動作)
- USB インターフェース
- SDHI インターフェース(SD カードアクセス)
- SSI インターフェース(シリアルサウンドインタフェース)
- 静電容量式タッチセンサ
- CAN インターフェース(RSCAN なので、専用ドライバーを実装する必要があり、現在開発中)
など、意外と機能が豊富で、応用範囲が広い。
※USB のクロック用に専用 PLL 回路があり、USB を使う場合でも、CPU のクロック周波数に影響しない。
※USB を使う場合、専用 PLL の制限により、外部発振周波数は、6MHz、12MHz のいずれか。(48MHz を作る必要がある為)
gcc 関数の最適化を制御
一般に、gcc の最適化 -O3 では、インライン展開や、直接埋め込みなど、色々な手法を駆使して、最大限高速に動作するようなバイナリーを生成する。
ただ、それだと、意図と異なった動作になる場合がある。
この C++ フレームワークでは、ソフトウェアーによる時間待ちが、その影響を受ける。
以下のコードは、ソフトウェアーによる時間待ち関数になる。
//-----------------------------------------------------------------//
/*!
@brief マイクロ秒単位の待ち @n
あまり正確では無く、速度に関連する設定に依存します。 @n
※キャッシュ有効、最高速度での物理計測によるパラメータ
@param[in] us 待ち時間(マイクロ秒)
*/
//-----------------------------------------------------------------//
static __attribute__((optimize(1))) void micro_second(uint32_t us) noexcept
{
while(us > 0) {
for(uint32_t n = 0; n < device::clock_profile::DELAY_MS; ++n) {
asm("nop");
}
--us;
}
if(device::clock_profile::DELAY_T1) { asm("nop"); }
}
この時間待ちは、大体1マイクロ秒になるように、ループ数を調整している。
CPU の速度が 80MHz とかだと問題無いが、54MHz だと、ループの回数が少なく、for ループが展開されて、NOP 命令のみとなり高速に動作してしまう。
for ループを最適化で展開させないようにする為「attribute((optimize(1)))」を宣言してある。
※この方法を見つける為に、色々試行錯誤した。
「((optimize(1)))」が無い場合のアセンブルリスト(for ループが展開されている):
fffc0278: fb 5a e8 03 mov.l #0x3e8, r5
fffc027c: 03 nop
fffc027d: 03 nop
fffc027e: 03 nop
fffc027f: 03 nop
fffc0280: 03 nop
fffc0281: 03 nop
fffc0282: 03 nop
fffc0283: 03 nop
fffc0284: 03 nop
fffc0285: 03 nop
fffc0286: 03 nop
fffc0287: 03 nop
fffc0288: 60 15 sub #1, r5
fffc028a: 21 f2 bne.b fffc027c <__romdatastart+0xffffffc4>
fffc028c: 03 nop
fffc028d: 60 14 sub #1, r4
fffc028f: 21 e9 bne.b fffc0278 <__romdatastart+0xffffffc0>
「((optimize(1)))」がある場合:
fffc01a0: 61 01 cmp #0, r1
fffc01a2: 20 0d beq.b fffc01af <__romdatastart+0xffffff07>
fffc01a4: 66 c5 mov.l #12, r5
fffc01a6: 03 nop
fffc01a7: 60 15 sub #1, r5
fffc01a9: 21 fd bne.b fffc01a6 <__romdatastart+0xfffffefe>
fffc01ab: 60 11 sub #1, r1
fffc01ad: 21 f7 bne.b fffc01a4 <__romdatastart+0xfffffefc>
fffc01af: 03 nop
※「noinline」の場合、関数呼び出しを消して、インライン展開するのを除外する、関数内のループには通常の最適化が行われるので、適当ではない。
RX231 のオーバークロック耐性
とりあえず、72MHz は動作するようだ・・(この位が安全圏か!?)
2024-01-28 01:18:18 Sunday
RX231 には、「動作電力コントロールレジスタ(OPCCR)」があって、初期状態では「中速モード」になっている。
これを「高速モード」に切り替える事で、高いクロックでも安定して動作するようだ。
90MHz で駆動したが、ちゃんと動作するようだ。
PLL | USB専用PLL | HOCO | LOCO | IWDTCLK | メインクロック発振器 | サブクロック発振器 | |
---|---|---|---|---|---|---|---|
高速動作モード | ○(注 1) | ○(注 1) | ○ | ○ | ○ | ○ | ○ |
中速動作モード | ○(注 1) | ○(注 1) | ○ | ○ | ○ | ○ | ○ |
低速動作モード | × | × | × | × | ○ | × | ○ |
RX231/clock_profile.hpp の定義:
#if 0
static constexpr uint32_t PLL_BASE = 54'000'000; ///< PLL ベースクロック(最大 54MHz)
static constexpr uint32_t ICLK = 54'000'000; ///< ICLK 周波数(最大 54MHz)
static constexpr uint32_t PCLKA = 54'000'000; ///< PCLKB 周波数(最大 54MHz)
static constexpr uint32_t PCLKB = 27'000'000; ///< PCLKB 周波数(最大 32MHz)
static constexpr uint32_t PCLKD = 54'000'000; ///< PCLKD 周波数(最大 54MHz)
static constexpr uint32_t FCLK = 27'000'000; ///< FCLK 周波数(最大 1 ~ 32MHz)
static constexpr uint32_t BCLK = 27'000'000; ///< BCLK 周波数(最大 32MHz)
#else
// static constexpr uint32_t PLL_BASE = 72'000'000; ///< PLL ベースクロック(最大 54MHz)
// static constexpr uint32_t ICLK = 72'000'000; ///< ICLK 周波数(最大 54MHz)
// static constexpr uint32_t PCLKA = 72'000'000; ///< PCLKB 周波数(最大 54MHz)
// static constexpr uint32_t PCLKB = 36'000'000; ///< PCLKB 周波数(最大 32MHz)
// static constexpr uint32_t PCLKD = 72'000'000; ///< PCLKD 周波数(最大 54MHz)
// static constexpr uint32_t FCLK = 36'000'000; ///< FCLK 周波数(最大 1 ~ 32MHz)
// static constexpr uint32_t BCLK = 36'000'000; ///< BCLK 周波数(最大 32MHz)
static constexpr uint32_t PLL_BASE = 90'000'000; ///< PLL ベースクロック(最大 54MHz)
static constexpr uint32_t ICLK = 90'000'000; ///< ICLK 周波数(最大 54MHz)
static constexpr uint32_t PCLKA = 90'000'000; ///< PCLKB 周波数(最大 54MHz)
static constexpr uint32_t PCLKB = 45'000'000; ///< PCLKB 周波数(最大 32MHz)
static constexpr uint32_t PCLKD = 90'000'000; ///< PCLKD 周波数(最大 54MHz)
static constexpr uint32_t FCLK = 45'000'000; ///< FCLK 周波数(最大 1 ~ 32MHz)
static constexpr uint32_t BCLK = 45'000'000; ///< BCLK 周波数(最大 32MHz)
#endif
まとめ
現状、RX231 向けに、以下のプロジェクトを動作確認して、コミットしてある。
- FIRST_sample
- SCI_sample
- FLASH_sample
- FreeRTOS
- RAYTRACER_sample
- PSG_sample
※RAYTRACER_sample では、RXv2 コアの優位性で、54MHz 動作の RX231 の方が、96MHz 動作の RX62N より高速だった。
マイコン | core | FPU | fsqrt 命令 | 周波数 [MHz] | 描画方式 | 時間 [ms] |
---|---|---|---|---|---|---|
RX231 | RXv2 | O | O | 54 | 8 bits, port-bus | 1736 |
RX62N | RXv1 | O | X | 96 | 8 bits, port-bus | 1860 |