RA4M1コアボードの16MHz水晶をPLLでメインクロックに
2025年5月2日:Arduino UNO R4互換品:RA4M1コアボード
この続き。
16MHz水晶を発振させ、PLLで48MHzのメインクロックを
作ってみました。
問題は、チップのスペックを外れているということ。
発振子の周波数は大丈夫なのですが、PLL部の最大入力周波数
と、分周値に対する最大出力周波数を超えてしまっているの
です。
「ユーザーズマニュアル・ハードウェア編」にはこんな表が
出ています。
入力周波数の最大が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に切り替わります。
切り替えはこんなタイミング。
拡大すると
millisパルスを拡大すると、loopパルスが途切れて
いるのが見えます。
millis処理のための割り込みが裏で走ってるのが
これでわかるかと。
とりあえず、手元のRA4M1コアボード(5V電源版)では
PLL駆動ができました。
Arduino UNO R4でも発振子をくっつければ試せるの
ではと思います。
・RA4M1コアボードの発振部回路
16MHzの発振子が小さい
・Arduino UNO R4の発振部回路
16MHz水晶がくっつくように回路図が描かれています。
しかし16MHzではスペックオーバー。
12MHzのがあれば8逓倍・2分周で48MHzが作れます。
形状の小さい水晶がぁぁぁ。
しかし、しかし。
まだややこしことはしていません。
GPTを使って1MHzパルスを出しただけ。
ほんとに大丈夫かはこれからです。
※1MHzのビート音でクロックの純度を音にしてみました。
・RA4M1コアボードでPLLメインクロックを試す
| 固定リンク
「Arduino UNO R4」カテゴリの記事
- Arduino UNO R4 minimaに12MHz水晶を(2025.06.09)
- Arduino UNO R4で2つの1Hz信号の位相変化を見る(2025.06.06)
- UNO R4はanalogWrite(n,128)でデュティー50%の方形波が出るぞ(2025.06.03)
- Arduino UNO R4 minima 電源供給方法でクロックが変わる#6(2025.06.02)
- Arduino UNO R4 minima 電源供給方法でクロックが変わる#5(2025.06.01)
コメント
色々と参考にさせていただいています。
私は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分