« Arduino UNO R4互換品:RA4M1コアボード | トップページ | RA4M1コアボードでPLLメインクロックを試す »

2025年5月 3日 (土)

RA4M1コアボードの16MHz水晶をPLLでメインクロックに

2025年5月2日:Arduino UNO R4互換品:RA4M1コアボード
この続き。
16MHz水晶を発振させ、PLLで48MHzのメインクロックを
作ってみました。

問題は、チップのスペックを外れているということ。
発振子の周波数は大丈夫なのですが、PLL部の最大入力周波数
と、分周値に対する最大出力周波数を超えてしまっているの
です。
「ユーザーズマニュアル・ハードウェア編」にはこんな表が
出ています。
Rr23

入力周波数の最大が12.5MHz
  これが16MHzで大丈夫か?
そして4分周時の最大周波数が32MHz
  これが48MHzになってしまうがどうだ?
これで安定に動くかどうか、ということになります。

私が買ったRA4M1コアボードは「電圧5V版」。
3.3V版より条件は良さそうです。

これが作ったスケッチ。

//  RA4M1コアボードの16MHz水晶でのPLLを試す
// 16MHz * 12逓倍で192MHz, 192MHz ÷ 4分周で 48MHz
// D5ピン P102 GT2B 1MHzでトグル出力
// D4ピン P103 GT2A 2相パルスでトグル出力
// D8ピン P304 loopでH/L
// D9ピン P303 millis変化でトグル(500Hz)
// D10ピン P112 1秒後にH PLL切り替えを示す
// ポートH/L制御出力
#define D8_H (R_PORT3->PODR_b.PODR4 = 1) // D8:P304 H/L
#define D8_L (R_PORT3->PODR_b.PODR4 = 0)
#define D9_H (R_PORT3->PODR_b.PODR3 = 1) // D9:P303 H/L
#define D9_L (R_PORT3->PODR_b.PODR3 = 0)
#define D10_H (R_PORT1->PODR_b.PODR12 = 1) // D10:P112 H/L
#define D10_L (R_PORT1->PODR_b.PODR12 = 0)
// PLL切り替え処理データ
int f_pllon; // PLL切り替え完了フラグ
// 起動後1秒経過で切り替え
/***** メインクロックをPLLに切り替え *****/
void PLLon(void)
{
byte b;
R_SYSTEM->PRCR = 0xA501; // クロック関連レジスタのプロテクト解除
// メインクロック水晶発振
R_SYSTEM->MOSCWTCR = 0b1001; // 発振安定32.768ms待ち (初期値2.08ms)
R_SYSTEM->MOSCCR_b.MOSTP = 0; // XTAL発振開始
b = R_SYSTEM->MOSCCR_b.MOSTP; // MOSTPの状態, 0の確認はいるのか?
while(1){ // 発振安定待ち
if(R_SYSTEM->OSCSF_b.MOSCSF == 1) break; // MOSCSFが1で安定
}
// PLL切り替え
R_SYSTEM->PLLCCR2_b.PLLMUL = 12 - 1; // 12逓倍 16MHz*12 = 192MHz
R_SYSTEM->PLLCCR2_b.PLODIV = 0b10; // 4分周 192MHz/4 = 48MHz
R_SYSTEM->PLLCR_b.PLLSTP = 0; // PLL開始
while(1){ // PLL安定待ち
if(R_SYSTEM->OSCSF_b.PLLSF == 1) break; // PLLSFが1で安定
}
R_SYSTEM->SCKSCR_b.CKSEL = 0b101; // クロックソースをPLLに
R_SYSTEM->PRCR = 0xA500; // プロテクト戻す
}

/***** SETUP *****/
void setup()
{
pinMode(8, OUTPUT); // D8:P304
pinMode(9, OUTPUT); // D9:P303
pinMode(10, OUTPUT); // D10:P112
// PFSプロテクト解除
R_PMISC->PWPR_b.B0WI = 0; // PFS書き込みプロテクト解除
R_PMISC->PWPR_b.PFSWE = 1; // (プロテクト戻してないよ)
// D5:P102 (参:19.2.5)
R_PFS->PORT[1].PIN[2].PmnPFS_b.PDR = 1; // ポート出力
R_PFS->PORT[1].PIN[2].PmnPFS_b.PSEL = 0b00011; // GTIOC2B出力に
R_PFS->PORT[1].PIN[2].PmnPFS_b.PMR = 1; // 周辺機能有効
// D4:P103
R_PFS->PORT[1].PIN[3].PmnPFS_b.PDR = 1; // ポート出力
R_PFS->PORT[1].PIN[3].PmnPFS_b.PSEL = 0b00011; // GTIOC2A出力に
R_PFS->PORT[1].PIN[3].PmnPFS_b.PMR = 1; // 周辺機能有効
// GPT2 B出力を1MHzでトグル A出力と合わせて2相パルスに (参:図22.15)
R_MSTP->MSTPCRD_b.MSTPD6 = 0; // PWMモジュールストップ解除
R_GPT2->GTCR_b.MD = 0b000; // ノコギリ波モード
R_GPT2->GTUDDTYC = 0b11; // 強制的にupカウント
R_GPT2->GTUDDTYC = 0b01; // up継続
R_GPT2->GTCR_b.TPCS = 0b000; // PCLKD/1 48MHz
R_GPT2->GTPR = 24 - 1; // 48MHz/24=2MHz トグルで1/2して1MHz
R_GPT2->GTCNT = 0; // 初回カウント値
R_GPT2->GTIOR_b.GTIOB = 0b01100; // GTIOC2B 周期の終わりでトグル出力
R_GPT2->GTIOR_b.GTIOA = 0b10011; // GTIOC2A コンペアマッチでトグル出力
R_GPT2->GTIOR_b.OBE = 1; // B出力許可
R_GPT2->GTIOR_b.OAE = 1; // A出力許可
R_GPT2->GTCCR[0] = 12; // GTCCRA:Aのトグル位置
R_GPT2->GTCR_b.CST = 1; // カウント開始
}
// コンペアキャプチャレジスタのGTCCRAのアクセスは
// 「R_GPT2->GTCCR[0] = n;」と
// GTCCRAなら[0]と番号で指定 しなければエラーになる。
//  「R_GPT2->GTCCRA」や
//  「R_GPT2->GTCCR_b.GTCCRA」とはできない。

/***** LOOP *****/
// 3秒後にPLLに切り替え
void loop()
{
uint32_t ms , a; // 1msチェックデータ
int f_x9 = 0; // D9ポート反転フラグ
int tm_1ms; // 1msダウンカウントタイマー
ms = millis(); // 現1ms値
tm_1ms = 3000; // 3秒セット
// loop
while(1){
D8_H; // D8:P304 H/L
D8_L;
a = millis(); // 新1ms値
if(ms != a){ // 1ms変化?
f_x9 ^= 1; // 0/1
if(f_x9) D9_H; // D9:P303 H/L
else D9_L;
if(tm_1ms) tm_1ms--; // 1msダウンカウント
ms = a; // 次の1msを待つ
}
// PLL変更タイミング
if((tm_1ms == 0) && // 3秒経過
(f_pllon == 0)){ // まだPLLにしていない
D10_H; // D10をHにして知らせる
PLLon(); // PLLに
f_pllon = 1; // 1回だけ実行
}
}
}
// <2025-05-03 JH3DBO>

リセットして3秒経ったらPLLクロックに切り替えると
いう仕様にしました。

オシロをD5ポートあるいはD4ポートにつないでいれば
1MHzの方形波が見えるはずです。
   D5、D4は90度位相差の2相パルス。
   ハード的に出しているのでジッタは無し。

D8ポートはwhile loopで出すパルス。

D9ポートはmillis()値の変化でトグルさせている
ので500Hzのパルスが出てきます。
  ソフトの処理が絡むのでジッタ有り。

D10がHになったタイミングでPLLに切り替えています。
  発振安定時間を32msみてますんで、Hになった
  あとちょっとしてからPLLに切り替わります。

切り替えはこんなタイミング。
Image000_20250503164501
拡大すると
Image001_20250503164901

millisパルスを拡大すると、loopパルスが途切れて
いるのが見えます。
Image002_20250503165701

millis処理のための割り込みが裏で走ってるのが
これでわかるかと。

とりあえず、手元のRA4M1コアボード(5V電源版)では
PLL駆動ができました。

Arduino UNO R4でも発振子をくっつければ試せるの
ではと思います。

RA4M1コアボードの発振部回路
Rr21_20250503170101

16MHzの発振子が小さい
R25

Arduino UNO R4の発振部回路
Rr22

16MHz水晶がくっつくように回路図が描かれています。
しかし16MHzではスペックオーバー。
12MHzのがあれば8逓倍・2分周で48MHzが作れます。
  形状の小さい水晶がぁぁぁ。


しかし、しかし。
まだややこしことはしていません。
GPTを使って1MHzパルスを出しただけ。
ほんとに大丈夫かはこれからです。


※1MHzのビート音でクロックの純度を音にしてみました。
RA4M1コアボードでPLLメインクロックを試す

|

« Arduino UNO R4互換品:RA4M1コアボード | トップページ | RA4M1コアボードでPLLメインクロックを試す »

Arduino UNO R4」カテゴリの記事

コメント

色々と参考にさせていただいています。
私は16MHzを6倍してから1/2にして動いていると思っていましたが、6倍は仕様範囲外なんですね。いま一度確かめてみます。

投稿: siliconvalley4066 | 2025年5月 6日 (火) 00時16分

「表8・1」にあるよう、
 逓倍比が8~31(1ステップずつ)
 出力分周比が2分周か4分周
この数値範囲の縛りで16MHzから48MHzを得ようとすると「12逓倍して1/4」となります。
「6逓倍」を許してもらえるのならエエんですが・・・
スペックオーバーしている周波数を我慢するか、スペック外の6逓倍を許すか、むつかしいところかと。

投稿: 居酒屋ガレージ店主(JH3DBO) | 2025年5月 6日 (火) 08時57分

外付けの水晶発振子を12MHzに交換できれば(未実装品なら新規実装)できれば良いんですが、RA4M1コアボードだと同じサイズの12MHz発振子が見つかりません。

投稿: 居酒屋ガレージ店主(JH3DBO) | 2025年5月 6日 (火) 13時22分

コメントを書く



(ウェブ上には掲載しません)




« Arduino UNO R4互換品:RA4M1コアボード | トップページ | RA4M1コアボードでPLLメインクロックを試す »