Arduino UNO R4 Minima 用のブートローダーのソースコードを読む ( クロック設定編 )
変更履歴
- rev.0 2025/02/26 新規作成
1. はじめに
Arduino UNO R4 Minima 用のブートローダーのソースコードを調べて記事にまとめています。今回は、SystemInit 関数の記事で省略した、bsp_clock_init
関数 とR_BSP_Init_RTC
関数の内容について記述します。
今回も#ifdef
によるコードの適用・除外がありますが、SystemInit
関数の場合と比べて粒度が細かく、数も多くなっています。そのため、適用されるコードに着目し、対象外のコードについては基本的に割愛したいと思います。
- 過去の関連記事
- Arduino UNO R4 Minima用のブートローダーをビルドする
- Arduino UNO R4 Minima用のブートローダのソースコードを読む (アプリケーション起動編)
- Arduino UNO R4 Minima用のブートローダのソースコードを読む (SystemInit編)
クロック設定の概要と関連資料
今回確認する機能はクロック設定に関する部分となります。そのため、下記の文書と設定ヘッダファイルを確認するとコードが読みやすくなるかと思います。
-
クロック発生回路のブロック図[1]
-
回路図
- BSP 設定ヘッダ (bsp_cfg.h)
- BSP クロック設定ヘッダ (bsp_clock_cfg.h)
ポイント
- XTAL, EXTAL, XCIN, XCOUT 端子に接続する水晶振動子は非搭載(メインクロック発振器、サブクロック発振器、および PLL を使用しない)
- 高速オンチップオシレーター (HOCO) のクロックは 48 MHz を指定
- システムクロック (ICLK) のクロックソース は HOCO (分周比は1) を指定
- USB クロック (UCLK) のクロックソースは HOCO を指定
2. bsp_clock_init 関数
まず、SystemInit
関数内で呼び出されていたbsp_clock_init
関数を、上から順番に確認したいと思います。
レジスタへの書き込みプロテクトを無効化
R_SYSTEM->PRCR
はプロテクトレジスタ[2]です。BSP_PRV_PRCR_UNLOCK は 次のように定義されています。
PRCR レジスタへの書き込みは、下位 8bitに目的の値を設定し、上位 8bit にキーコード (0xA5) をセットした 16 bit 単位で行います。
今回、目的の値は0x3Uとなるため、クロック発生回路関連レジスタと低消費電力モード、およびバッテリバックアップ機能関連レジスタへの書き込みをこの操作によって許可しています。
FLASH Cache の無効化
RA4M1 には消費電力低減機能として、電力制御モードがあります[3]。このモードは、動作電力コントロールレジスタ (OPCCR) で設定できます。
リセット時の値は Low-voltage モードとなります[4]。今回の場合は、電力制御モードを最終的に High-speed モードに設定します。そのため、定数 BSP_CFG_USE_LOW_VOLTAGE_MODE は以下のように 0 で定義されています:
この設定では、RA4M1 の 1204行目でR_BSP_FlashCacheDisable
関数が実行されます。関数のコメントには、「MEMWAIT・SOPCCR・OPCCR レジスタを変更する前にフラッシュキャッシュを無効にする」と記載されています。
ハードウェアマニュアルを確認すると、電力制御モードを Low-voltage モードから High-speed モードに切り替える手順の中で、OPCCR レジスタ操作前にフラッシュキャッシュを禁止する操作が書かれていました[5]。
この後に続くプリフェッチバッファの無効化処理は、RA4M1 では対象外となります。このレジスタは RA2L1 等のマイコンに搭載されています[6]。RA4M1 にもプリフェッチバッファは搭載されていますが、こちらの場合は、R_BSP_FlashCacheDisable()
内で操作している FCACHEEN でフラッシュキャッシュ1, フラッシュキャッシュ2 と合わせて有効、無効を設定するようです[7]。
bsp_clock_freq_vars_init 関数
各クロック情報を格納する変数を初期化しています。
まず、低速、中速、高速オンチップオシレータ (LOCO, MOCO, HOCO) の周波数をg_clock_freq
配列に格納しています。
BSP_HOCO_HZ は bsp_mcu_family_cfg.h で定義されています。
BSP_CFG_HOCO_FREQUENCY は bsp_clock_cfg.h で定義されています。
BSP_CFG_HOCO_FREQUECNY は 4 となっているため、HOCO の周波数は 48MHz となります。また、BSP_MOCO_FREQ_HZ、BSP_LOCO_FREQ_HZ については bsp_clocks.h 内で定義されています。
Arduino UNO R4 Minima にはメインクロック発振器用の水晶振動子、およびサブクロック発振器用の 32.768kHz 水晶振動子は搭載されていません。そのため 0 を代入しています。
また、ここからSystemCoreClockUpdate
関数まで (1132-1186行目) のコードは対象外となります。これらのブロックは、ノンセキュアビルド時の処理と、PLL 関連の処理となります。前者については RA4M1 には TrustZone は非搭載であるため除外されます。また、後者についてですが、クロック発生回路のブロック図[8]によると、PLL の入力はメインクロック発振器のみとなっています。今回の場合はメインクロック発振器は使用しないため、BSP_CLOCK_CFG_MAIN_OSC_POPULATED は 0 となっています。また、ra4m1/bsp_feature.h を見ると BSP_FEATURE_CGC_PLLCCR_TYPE は (2U) として定義されています。そのため、BSP_PRV_PLL_SUPPORTED の値は、下記の 75 行目の (0) となり、コードから除外されます。
SystemCoreClockUpdate 関数 (一回目)
init_clock_vars
関数の最後にSystemCoreClockUpdate
関数が実行されています。
SystemCoreClockUpdate
関数の内容は下記のとおりです。
R_SYSTEM->SCKSCR
はシステムクロックソースコントロールレジスタです[9]。この CKSEL[2:0] ビットによってクロックソースを選択することができます。この値のリセット時の値は 1 (MOCO) です。
定数 BSP_FEATURE_CGC_HAS_CPUCLK は RA4M1 の場合 0 で定義されているため、780行目の処理が実行されます。
今回の場合、clock_index
は 1 となります。この値は bsp_clocks.h の 40 行目に定義されている BSP_CLOCKS_SOURCE_CLOCK_MOCO に対応します。
そのため、g_clock_freq[clock_index] はbsp_clock_freq_vars_init
関数の冒頭で設定した
g_clock_freq[BSP_CLOCKS_SOURCE_CLOCK_MOCO] = BSP_MOCO_FREQ_HZ;
に対応します。BSP_MOCO_FREQ_HZ は 8MHz です。
R_SYSTEM->SCKDIVCR_b
はシステムクロック分周コントロールレジスタで、ICK ビットによってシステムクロック (ICLK) の周波数を選択することができます[10]。
この値のリセット時の値は 0b100 (16分周) です。そのため、SystemCoreClock
はこの時点では 8MHz/16 = 500kHz となります。
サブクロック発振器の停止
SystemCoreClockUpdate
関数実行後、bsp_clock_freq_vars_init
関数からbsp_clock_init
関数に戻ります。まず、後続の1221-1247行目ですが、これはメインクロック発振器に関する処理のため、コードから除外されます。次に1248-1276行目ですが、これはサブクロック発振器に関する処理になります。こちらについても水晶振動子は非搭載 (BSP_CLOCK_CFG_SUBCLOCK_POPULATED が 0) となるため、1273行目のコードが実行されます。
R_SYSTEM->SOSCCR
はサブクロック発振器コントロールレジスタ (SOSCCR) です[11]。この SOSTP ビットでサブクロック発振器の動作・停止を選択できます。ここでは、1 を設定してサブクロック発振器を停止しています。
1277-1300行目は、高速オンチップオシレータウェイトコントロールレジスタ(HOCOWTCR)の設定を行っています。このレジスタの HOCO 待機時間設定 (HSTS) には、0b101 (リセット時の値) または 0b110 のいずれかを設定できます。ただし、0b110 は HOCO の動作周波数が 64MHz の場合に使用し、それ以外では 0b101 を設定します[12]。
今回の設定では HOCO の動作周波数が 48MHz なので、このブロックは対象外となります。
電力制御モードの設定
このブロックでは電力制御モードの設定を行います。電力制御モードのリセット時の値は Low-voltage モードですが、これを High-speed モードに変更します。
BSP_CFG_STARTUP_CLOCK_REG_NOT_RESET は リセット時にクロック設定を再初期化しない場合に 0 以外の値を設定する定数かと思いますが、今回の場合はブートローダーであるため、0 として定義されています。そのため 1302-1305 行目は対象外となり、1306 行目の評価に移ります。
定数 BSP_FEATURE_CGC_LOW_VOLTAGE_MAX_FREQ_HZ はマイコンが Low-voltage モードをサポートする場合は 0 より大きな値が設定されます。RA4M1 の場合は、以下のように 4MHz となります。
この場合は、電力制御モードの設定を bsp_prv_operating_mode_set 関数によって行っています。なお、bsp_prv_operating_mode_set 関数後のブロックは HOCO を使用しない場合の処理のため、コードから除外されます。
bsp_prv_operating_mode_opccr_set 関数
電力制御モードを High-speed モードに設定します。RA4M1 では、動作電力コントロールレジスタ (OPCCR) によって電力制御モードを切り替える場合、発振安定フラグレジスタ (OSCSF)の HOCOSF ビットが 1 である必要があります[13],[14]。そのため、#if BSP_FEATURE_CGC_HOCOSF_BEFORE_OPCCR
内のブロック (662-676行目) がコードに組み込まれます。この処理は、要求した電力モードと OPCCR の値が異なる場合にのみ実行されます。
R_SYSTEM->HOCOCR
は高速オンチップオシレータコントロールレジスタで、HCSTP ビットの値によって HOCO クロックの動作/停止を制御します[15]。HCSTP が 0 の場合は HOCO クロック動作となるため、この場合に R_SYSTEM->OSCSF_b.HOCOSF
を見て HOCO クロックが安定するまで待機しています。HOCOCR.HCSTP のリセット時の値は、オプション機能選択レジスタ 1 (OFS1) の HOCOEN ビットの値によって決まります[16]。
電力制御モードの遷移状態は、OPCCR の OPCMTSF ビットによって確認できます。1 の場合は遷移中、0 になると遷移完了となります。そのため、まず、電力制御モードが遷移中ではないことを確認した後に、電力制御モードを指定した値 (ここでは High-speed モード) に切り替え、状態遷移が完了するまで待機しています。
bsp_prv_operating_mode_set 関数を抜けた後のブロック (1324-1331 行目)は、HOCO に FLL (周波数ロックループ) 機能がある場合の処理で、RA4M1 の場合は対象外となります。
HOCOクロック動作
今回の場合はHOCOを使用するため、このブロックはコードに組み込まれます。まず、HOCOCR の HCSTP ビットを 0 にしてHOCO クロックを動作させた後、HOCOSF ビットを確認して、1345行目の処理で HOCO クロックが安定化するまで待機しています。
1336-1340行目のコードは FLL 機能に関する処理であるため対象外となります。また、1348-1434行目の処理も、MOCO, LOCO, MOSC を使用しない、PLLを使用しない、PLL2が実装されてない、といった理由から対象外となります。
クロックソースをHOCOに変更
BSP_CFG_STARTUP_CLOCK_REG_NOT_RESET は bsp_cfg.h 内で 0 として定義されています。そのため、このブロックでは 1450 行目にある bsp_prv_clock_set_hard_reset 関数が実行されます。
bsp_prv_clock_set_hard_reset 関数
メモリウェイトサイクル設定
まず、989-1012行目ですが、RA4M1 には FLWT レジスタが非搭載となるためコードから除外されます。一方、1013-1019 行目のコードは組み込まれます。
今回は、電力制御モードはHigh-Speedモードで、ICLK は 48MHz ( > 32 MHz ) となります。そのため、MEMWAIT レジスタの MEMWAIT ビットは 1 (ウェイトあり)にする必要があります[17]。
1020-1028行目の処理は、RA4M1 に FLDWAITR レジスタが搭載されていないためコードから除外されます。
システムクロック分周設定
1034行目の定数 BSP_STARTUP_SOURCE_CLOCK_HZ ですが、これは bsp_clocks.h に定義があります。
今回の設定では、BSP_STARTUP_SOURCE_CLOCK_HZ は BSP_HOCO_HZ になります。そのため、1035行目の条件が評価されますが、RA4M1 の場合、BSP_FEATURE_CGC_HAS_CPUCLK は 0 であるため、この条件には該当しません。結果として、1050行目の処理が実行されます。
R_SYSTEM->SCKDIVCR
はシステムクロック分周コントロールレジスタです[18]。定数 BSP_PRV_STARTUP_SCKDIVCR は 下記に定義があります。
BSP_CFG_ICLK_DIV は bsp_clock_cfg.h に 分周比 1 として定義されています。
クロックソース選択
R_SYSTEM->SCKSCR
はシステムクロックソースコントロールレジスタ(SCKSCR)です[19]。この CKSEL[2:0] ビットによってクロックソースの選択が行えます。BSP_CFG_CLOCK_SOURCE は bsp_clock_cfg.h の通り、BSP_CLOCKS_SOURCE_CLOCK_HOCO となります。そのため、ここでシステムクロックが HOCO に切り替わります。
後続の 1056-1077 行目のブロックは、システム起動時のクロック周波数が MOCO よりも低い場合に実行される処理です。今回は、システム起動時のクロック周波数が MOCO よりも高いため、このブロックは実行されず、コードから除外されます。
SystemCoreClockUpdate 関数 (二回目)
二回目のSystemCoreClockUpdate
関数の実行です。処理内容は一回目と同様ですが、SystemCoreClock 変数の値が、HOCO 周波数 (=48MHz) / 分周比 (=1) に更新されます。
SystemCoreClockUpdate
関数を抜けた後のブロック (1082-1105行目) は、RA4M1 には SRAMWTSC レジスタがないため対象外となります。その結果、bsp_prv_clock_set_hard_reset
関数から抜けた後、すぐにbsp_clock_init
関数に戻ります。
USB クロック選択
まず、1453-1516 行目のコードは対象外となります。次の 1517-1559 行目のブロックはコードに組み込まれます。その中の1549-1553 行目が実際に適用されるコード です。
R_SYSTEM->USBCKCR_ALT
はUSB クロックコントロールレジスタ(USBCKCR)です[20]。このUSBCLKSELビットを 1 にするとクロックソースを HOCO に設定することができます。リセット時の値は 0 (PLL) です。
この後の 1561-1565 行目は、RA4M1 の場合、BSP_FEATURE_BSP_HAS_USB_CLOCK_REQ が 0 であるため、コードから除外されます。また、1569-1643 行目までのコードも RA4M1 に非搭載の機能であるため対象外となります。
レジスタへの書き込みプロテクトを有効化
bsp_clock_init 関数の冒頭で行ったレジスタへの書き込み解除をもとに戻します。
FLASH Cache の有効化
無効化していたフラッシュキャッシュを有効化します。また、1651-1652行目は無効化の時と同様に対象外となります。これでbsp_clock_init
関数は終了です。
3. R_BSP_Init_RTC 関数
最後にR_BSP_Init_RTC
関数について確認します。
カウントソース選択
R_RTC->RCR4
はRTC コントロールレジスタ 4(RCR4)です[21]。このレジスタの RCKSEL ビットによって、カウントソースをサブクロック発振器か LOCO を選択できます。
今回の場合は 2002 行目のコードが実行されます。ここでは 0 (サブクロック発振器) を指定しています。
[対象外] RTC の無効化
定数 BSP_CFG_USE_RTC は未定義のため、2006 行目の評価に進みます。しかし、今回は LOCO を使用せず、サブクロック発振器も搭載されていないため、このブロックは対象外となります。
2008-2019 行目までのコードは、リアルタイムクロックを使用しない場合の初期化手順としてハードウェアマニュアルに記載されたフローチャートの処理かと思います[22]。
この処理に続けて、時間キャプチャコントロールレジスタ y(RTCCRy)(y = 0 ~ 2)の時間キャプチャイベント入力端子有効 (TCEN) を 無効 (0) にしています[23]。
また VBATT 入力コントロールレジスタ (VBTICTLR) の VCHnINEN ビット(VBATT ウェイクアップ入出力 n 入力許可)(n = 0 ~ 2)を禁止にしています[24]。
4. おわりに
Arduino UNO R4 Minima のブートローダーがアプリケーションを起動するまでの確認は以上で終了です。ここまでお読みいただきありがとうございました!
また、前回の記事で、Arduino UNO R4 と同じマイコンを搭載した「XIAO RA4M1」を使って電子オルゴールを作成する方法について紹介しました。
この電子オルゴールのスケッチ (プログラム) は Arduino UNO R4 でも動作しますので、よろしければこちらもご覧ください。
Seeed Studio XIAO RA4M1 でつくる電子オルゴール[25]
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.144, "図 8.1 クロック発生回路のブロック図" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.262, "12.2.1 プロテクトレジスタ(PRCR)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.194, "表 10.1 低消費電力モード機能の仕様" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.204, "10.2.6 動作電力コントロールレジスタ(OPCCR)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.215, "(2) 消費電力が小さいモードから大きいモードへ切り替える場合 例2:" ↩︎
-
Renesas Electronics Corporation, "Renesas RA2L1グループ ユーザーズマニュアル ハードウェア編 Rev.1.50", Oct 2024, p.984, "37.3.2 PFBER : プリフェッチバッファイネーブルレジスタ" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.1484, "44.4.1 フラッシュキャッシュイネーブルレジスタ(FCACHEE)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.144, "図 8.1 クロック発生回路のブロック図" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.148, "8.2.2 システムクロックソースコントロールレジスタ(SCKSCR)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.146, "8.2.1 システムクロック分周コントロールレジスタ(SCKDIVCR)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.155, "8.2.7 サブクロック発振器コントロールレジスタ(SOSCCR)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.165, "8.2.16 高速オンチップオシレータウェイトコントロールレジスタ(HOCOWTCR)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.204, "10.2.6 動作電力コントロールレジスタ(OPCCR)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.160, "8.2.12 発振安定フラグレジスタ(OSCSF)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.157, "8.2.9 高速オンチップオシレータコントロールレジスタ(HOCOCR)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.115, "6.2.2 オプション機能選択レジスタ 1(OFS1)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.151, "8.2.5 メモリウェイトサイクルコントロールレジスタ(MEMWAIT)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.146, "8.2.1 システムクロック分周コントロールレジスタ(SCKDIVCR)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.148, "8.2.2 システムクロックソースコントロールレジスタ(SCKSCR)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.172, "8.2.25 USB クロックコントロールレジスタ(USBCKCR)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.654, "24.2.19 RTC コントロールレジスタ 4(RCR4)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.680, "24.6.7 リアルタイムクロックを使用しない場合の初期化手順" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.657, "24.2.22 時間キャプチャコントロールレジスタ y(RTCCRy)(y = 0 ~ 2)" ↩︎
-
Renesas Electronics Corporation, "Renesas RA4M1グループ ユーザーズマニュアル ハードウェア編 Rev.1.10", 2023.09, p.247, "11.2.11 VBATT 入力コントロールレジスタ(VBTICTLR)" ↩︎
Discussion