﻿<<<< HWLib Example Program >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

-- 情報 ----------------------------------------------------------------
ファイル名：		sample_clock_manager.c
作成日：			2013/11/11
更新日：			2014/01/30	"体裁修正" 
更新日：			2014/04/21	"u-boot-spl.axf を v13.1 で生成したファイルに変更"
更新日：			2014/07/29	"SoC EDS 14.0 用に Makefile を修正"
更新日：			2014/08/18	"誤植訂正、操作説明の表示を追加"
更新日：			2015/06/25	"SoC EDS 15.0 用の HWLib に対応。文字コードを UTF-8 に変更 (Linux の日本語表示)。
						 		割込みログの実装を改善（割込み利用の場合のみ）"
更新日：			2016/03/14	"デバッグコンフィギュレーション設定変更（レジスタ定義読み込み）"
更新日：			2016/03/29	"デバッグコンフィギュレーション設定変更（レジスタ定義読み込み） ファイルの修正"
更新日：			2016/07/08	"マルチボード対応（Helio/Atlas/Sodia/C5SoCDevKit）"
更新日：			2017/05/22	"Arria 10 Soc DevKit 対応, DS-5 レジスタビュー表示にも対応"
更新日：			2018/07/02	"All in One ベアメタル・アプリケーション v17.1 への対応を実施"
更新日：			2019/02/25	"All in One ベアメタル・アプリケーション v18.1 への対応を実施"
更新日：			2021/04/23	"SoC EDS v20.1 / Arm DS 2020.1 への対応を実施、Helio は更新対象外(v18.1 用を使用)"
更新日：			2025/07/29	"SoC EDS v20.1 / Arm DS 2024.1 への対応を実施"

確認 HWLib バージョン：	13.0 Beta (SoC EDS 13.0sp1)
確認 HWLib バージョン：	13.1 (SoC EDS 13.1)
確認 HWLib バージョン：	14.0 (SoC EDS 14.0 patch0.02)
確認 HWLib バージョン：	15.0 (SoC EDS Version: 15.0.1, Build: 60)
確認 HWLib バージョン：	15.1 (SoC EDS Version: 15.1.1, Build: 60)
確認 HWLib バージョン：	16.0 (SoC EDS Version: 16.0, Build: 211)
確認 HWLib バージョン：	16.1 (SoC EDS Version: 16.1.0, Build: 196)
確認 HWLib バージョン：	17.0 (SoC EDS Version: 17.0, Build: 595)
確認 HWLib バージョン：	17.1 (SoC EDS Version: 17.1, Build: 585)
確認 HWLib バージョン：	18.1 (SoC EDS Version: 18.1, Build: 625)
確認 HWLib バージョン：	github.com/altera-opensource - tag: rel_socfpga_v2020.10_21.03.01_pr
　　　　　　　　　　　　　Download: [ https://github.com/altera-fpga/u-boot-socfpga/releases/tag/rel_socfpga_v2020.10_21.03.01_pr ]
確認 HWLib バージョン：	github.com/altera-opensource - tag: rel_socfpga_v2024.01_24.11.03_pr
　　　　　　　　　　　　　Download: [ https://github.com/altera-fpga/u-boot-socfpga/releases/tag/rel_socfpga_v2024.01_24.11.03_pr ]

※ 本 HWLib Example を利用する場合には、プロジェクト 「ALT-HWLib-All-In-One_vXX.X_r○」 をインポートし、
　 TOP ディレクトリーに本 HWLib Example ファイルをコピーしてコンパイル対象とすることで、
　 Makefile を修正すること無く各種評価ができるようになっています（FPGA のコンフィギュレーションデータ等を共有するため）。

※ SoC EDS v13.1 以前のツールを利用する場合には、本サンプルに含まれる Makefile に下記変更を加えて下さい。
　【変更前】 CROSS_COMPILE := arm-altera-eabi-　　... SoC EDS v14.0 以降を利用の場合
　【変更後】 CROSS_COMPILE := arm-none-eabi-　　..... SoC EDS v13.1 以前を利用の場合
　 リンカスクリプト（cycloneV-dk-ram-hosted.ld）内に記述されるラベル（2 カ所）にも変更が必要な場合があります。
　【変更前】 __cs3_reset_cycloneV_dk_ram
　【変更後】 __cs3_reset_generic
　 他、HWLib のバージョン違いにより一部の API でコンパイルエラーが発生する場合があります。
　 その場合は、適宜サンプルコードを変更してご利用下さい。

**************************************************************************************
* Copyright (C) 2013-2025 MACNICA,Inc. All Rights Reserved.                          *
*   This software is licensed "AS IS".                                               *
*   Please perform use of this software by a user's own responsibility and expense.  *
*   It cannot guarantee in the maker side about the damage which occurred by the ab- *
*   ility not to use or use this software, and all damage that occurred secondarily. *
**************************************************************************************

※ HPS 用 DIPSW[3:0] の切り替え契機で Main PLL の M(1-4096) を変更するサンプルです
（HPS の Main クロック周波数切り替えを試します）。

 HPS 用 DIPSW[3:0] の値に応じて、Main クロックを下記の通りに変更します。
---------------------------------
DISPSW    Main PLL の M   mpu_clk
[3210]    (1 - 4096)     (MHz)
---------------------------------
 0000      4              50
 0001      8             100
 0010     12             150
 0011     16             200
 0100     20             250
 0101     24             300
 0110     28             350
 0111     32             400
 1000     36             450
 1001     40             500
 1010     44             550
 1011     48             600
 1100     52             650
 1101     56             700
 1110     60             750
 1111     64             800
---------------------------------

　※注意事項： MainPLL を変更する際には、1 回の変化を 20% 以内とする必要があります。
　-- quote from "Cyclone V Device Handbook Volume3" --- 
　Once a PLL is locked, changes to any PLL VCO frequency that are 20 percent or less
　do not cause the PLL to lose lock. Iteratively changing the VCO frequency in
　increments of 20 percent or less allow a slow ramp of the VCO base frequency without
　loss of lock.For example, to change a VCO frequency by 40% without losing lock,
　change the frequency by 20%, then change it again by 16.7%.

※ 本サンプルでは、DS Intel SoC FPGA Edition (Altera Edition) のレジスタ・ビューには
　 標準では表示されない下記ペリフェラルのレジスタ表示に対応しています。
　  * DMA Controller（DMA-330）
　  * L2Cache Controller（L2C-310）
　  * Cortex-A9 MPCore 内蔵 SCU（Snoop Control Unit）
　  * Cortex-A9 MPCore 内蔵 Interrupt Controller（GIC: PL-390）
　  * Cortex-A9 MPCore 内蔵 Timer（Global Timer, Private Timer, Watchdog Timer）
　
　レジスタ・ビューのカスタマイズ方法は、マクニカサイトの技術情報をご参照ください。
　『Arm DS 活用テクニック ～レジスタ・ビュー［2/3］レジスタ定義の自作』
　 https://www.macnica.co.jp/business/semiconductor/articles/intel/115085 

※ config.mk ファイル内のシンボル定義を変更することで、ターゲットボードの選択が可能です。
　 下記から 1 行だけを選択します（その他の行は # でコメントアウトします）。
　#######################
　# Select Target Board #
　#######################
　TARGET_BOARD := atlas		← Atlas-SoC / DE0-Nano-SoC
　#TARGET_BOARD := sodia		← Mpression Sodia Evaluation Board 
　#TARGET_BOARD := c5socdk		← Cyclone V SoC Development Kit 
　#TARGET_BOARD := a10socdk		← Arria 10 SoC Development Kit 
　#TARGET_BOARD := de10nano		← DE10-Nano

※ 本サンプルでは、HPS 側の PUSH スイッチ 4 つと DIPSW (SLIDE) 4 つを
　 操作することでソフトウェアの動作を切り替える仕組みを実装しております。
　
　但し、ターゲットボードに Atlas-SoC / DE0-Nano-SoC / DE10-Nano を選択した場合、
　HPS 側には前述のスイッチが不足する状態となるため、以下の対応でご利用頂く実装としています。
　 * PUSHSW0 ... FPGA 側の PUSH BUTTON (KEY0, KEY1) を同時押し 
　 * PUSHSW1 ... FPGA 側の PUSH BUTTON (KEY0) を単押し
　 * PUSHSW2 ... FPGA 側の PUSH BUTTON (KEY1) を単押し
　 * PUSHSW3 ... HPS 側の USER PUSH BUTTON (KEY2) を単押し
　 * DIPSW[3:0] ... FPGA 側の SLIDE スイッチ (SW3, SW2, SW1, SW0) 
　
　Arria 10 SoC Development Kit を選択した場合は、全てのスイッチ（PUSH × 4、
　DIPSW (SLIDE) × 4）を HPS 側ではなく FPGA 側をご利用頂く実装としています。
　
　FPGA 側のスイッチを利用するため当該スイッチ用の PIO を実装した .sof にて
　事前に FPGA のコンフィギュレーションを行って頂く必要があります。

※ FPGA のコンフィギュレーション用の .sof ファイルは、DS ワークスペース以下
　 ALT-HWLib-All-In-One_vXX.X_r○\target_board の中に格納してあります。
　（必要に応じて Quartus Programmer 等で書き込みしてください）


-- 概要 ----------------------------------------------------------------
HWLib にて、下記のカテゴリに分類されている API を一通り動作させます。
	The Clock Manager API
	 ＋　Clock Manager Status
	 ＋　Safe Mode Options
	 ＋　PLL Bypass Control
	 ＋　Clock Gating Control
	 ＋　Clock Source Selection
	 ＋　Clock Frequency Control
	 ＋　Clock Manager Interrupt Management
	 ＋　Clock Group Configuration

上記カテゴリの全ての API を試行するとともに、3 種の PLL（Main PLL、Peripheral PLL、SDRAM PLL）の
コンフィグレーション情報を表示して目視可能としています。
また、Clock Manager から発生する割り込み（3 種の PLL の Lock/Unlock）について
も発生契機でコンソール表示を行うように対応しています。
その他、HPS 用 DIPSW / PUSHSW 契機で、特定の API を試行できるよう実装しています。


-- 使い方 --------------------------------------------------------------

　　①．アーカイブを SoC EDS (DS) へインポートします。
　　~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	１．SoC EDS（DS）のメニューから「ファイル(F) -> インポート(I)...」を実行します。
	　　※ 注意：SoC EDS (DS) は Embedded_Command_Shell から起動してください。
		↓
	２．インポートダイアログ上のインポート・ソースの選択(S)： として
	　　「一般 -> 既存プロジェクトをワークスペースへ」を選択して［次へ(N)>］を実行します。
		↓
	３．アーカイブ・ファイルの選択(A) のチェックを有効にして、
	　　［参照(R)...］ボタンから起動されるファイル選択ダイアログにて
	　　「ALT-HWLib-All-In-One_vXX.X_r○.tar.gz」を選択します。
		↓
	４．「終了(F)」を実行してインポートを完了します。
		↓
	５．ALT-HWLib-All-In-One_vXX.X_r○ の中に格納してある
	　　config.mk ファイル内の ENABLE_EXAMPLE_CLK の定義を "1" に設定してプロジェクトをビルドすると、
	　　ターゲットボードの DIP スイッチを 「Command モード」 に設定してコンソールから "clk" コマンドを入力することにより、
	　　util/cmd.c 内から sample_clock_manager.c の sample_clkmgr_test_cmd() 関数がが呼び出されます。

　#ENABLE_EXAMPLE_CLK     : sample_clock_manager.c
　ENABLE_EXAMPLE_CLK       := 1


　　②．ALT-HWLib-All-In-One_vXX.X_r○ プロジェクトをビルドします。
　　~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	１．ALT-HWLib-All-In-One_vXX.X_r○ プロジェクトの config.mk を必要に応じて修正します。
		↓
	２．プロジェクト・エクスプローラ上で ALT-HWLib-All-In-One_vXX.X_r○
	　　の右クリックメニューから「プロジェクトのビルド(B)」を実行します。

　　③．デバッグを実行します。
　　~~~~~~~~~~~~~~~~~~~~~~~~
	１．SoC EDS（DS）のメニューから「実行(R) -> デバッグの構成(B)...」を実行します。
		↓
	２．デバッグの構成ダイアログ上で、左側のツリー上で
	　　「DSデバッガ -> ALT-HWLib-All-In-One_vXX.X_r○」が選択された状態にします。
		↓
	３．接続タブの［参照...］ボタンからデバッグハードウェアの選択ダイアログを起動して、
	　　適切な Connection を選択します。
	　　（例えば、Atlas ボードと USB-Blaster II 接続なら「DE-SoC on localhost[USB-1]:DE-SoC USB-1」）
		↓
	４．［デバッグ(D)］を実行すると、プログラムがロードされた後に sample_app.c 内の main() でブレイクします。
	　　以降、デバッガで動作をご確認下さい。　


-- 詳細（sample_clkmgr_test_cmd() 以降） --------------------------------

◎ sample_clkmgr_test_cmd() 関数内の下記の記述にて、サンプルコードを呼び出しています。
　　//// Sample Function Call!!! |---->
　　printf(">>>> Execute sample_clkmgr_init(); !!! <<<<\r\n");
　　sample_clkmgr_init();
　　
　　printf(">>>> Execute sample_clkmgr_test_print_pllconfig(); !!! <<<<\r\n");
　　sample_clkmgr_test_print_pllconfig();
　　
　　printf(">>>> Execute sample_clkmgr_test_customize_config(); !!! <<<<\r\n");
　　sample_clkmgr_test_customize_config();
　　
　　printf(">>>> Re-Execute sample_clkmgr_test_print_pllconfig(); !!! <<<<\r\n");
　　sample_clkmgr_test_print_pllconfig();
　　
　　printf(">>>> sample_clkmgr_test(); !!! <<<<\r\n");
　　sample_clkmgr_test_main();
　　//// Sample Function Call!!! <----|


◎ 各サンプル関数の概要を示します。

sample_clkmgr_init();
	→ ターゲット・ボードの HPS 用 DIPSW, PUSHSW のための GPIO 設定を行います（テストプログラム操作用）。
	→ Global Timer の設定を行います（CPU Core の動作クロックで Timer イネーブル）（テストプログラム操作用）。
	→ 動作確認用に割り込みコントローラ（GIC）の設定変更を行います。
	　 本関数で設定を行った後、PLL の Lock/Unlock 契機で割り込み処理が動作し、下記のコンソールメッセージを出力します。
	　"[IRQ#205] CLKMGR_IRQ (0x000000CD,0x000001C7) count=1"

sample_clkmgr_test_print_pllconfig();
	→ Clock Manager の情報取得系 API を実行し、下記の情報を表示します（情報取得系 API の試行 兼 設定内容の確認）。
	
	＜表示サンプル＞
	==== Input Clock Frequency Value =====
	ALT_CLK_IN_PIN_OSC1(0): Frequency=  25000000 (Hz)
	ALT_CLK_IN_PIN_OSC2(1): Frequency=  25000000 (Hz)
	ALT_CLK_F2H_PERIPH_REF(2):  Frequency=         0 (Hz)
	ALT_CLK_F2H_SDRAM_REF(3):   Frequency=         0 (Hz)

	==== Output Clock Frequency and Divider Value =====
	ALT_CLK_MPU(19):            Frequency= 800000000 (Hz) [Divider=2]
	ALT_CLK_MPU_L2_RAM(20):     Frequency= 400000000 (Hz) [Divider=2]
	ALT_CLK_MPU_PERIPH(21):     Frequency= 200000000 (Hz) [Divider=4]
	ALT_CLK_L4_MAIN(25):        Frequency= 400000000 (Hz) [Divider=4]
	ALT_CLK_L4_MP(26):          Frequency= 100000000 (Hz) [Divider=2]
	ALT_CLK_L4_SP(27):          Frequency= 100000000 (Hz) [Divider=2]

	==== setting information of Main PLL: (pll=9) ====
	-- HWLib test : alt_clk_source_get() --
	 * PLL Reference Clock Source: 0
	-- HWLib test : alt_clk_pll_vco_cfg_get() --
	 * VCO - Multiplier (M) value: 64
	 * VCO - Divider (N) value   : 1
	-- HWLib test : alt_clk_pll_cfg_get() --
	 * PLL Reference Clock Source: 0
	 * VCO - Multiplier (M) value: 63 (=>64)
	 * VCO - Divider (N) value   : 0 (=>1)
	 * C0 - {PhaseShift, Divider}: {0, 0 (=>1 x K)}
	 * C1 - {PhaseShift, Divider}: {0, 0 (=>1 x K)}
	 * C2 - {PhaseShift, Divider}: {0, 0 (=>1 x K)}
	 * C3 - {PhaseShift, Divider}: {0, 3 (=>4 x K)}
	 * C4 - {PhaseShift, Divider}: {0, 3 (=>4 x K)}
	 * C5 - {PhaseShift, Divider}: {0, 15 (=>16 x K)}
	 # in the main PLL, K=2 for C0, and K=4 for C1,C2. Others are all K=1.
	-- HWLib test : alt_clk_pll_guard_band_get() --
	-- HWLib test : alt_clk_pll_vco_freq_get() --
	 * Gurad Band Value            :  20 (%)
	 * VCO Frequency (Fvco)        : 1600000000 (Hz)
	-- HWLib test : alt_clk_pll_is_bypassed(),alt_clk_is_enabled() --
	 * Is bypassed(1) or not(0)  : 0
	 * Is enabled(1) or not(0)   : 1
	-- HWLib test : alt_clk_freq_get() --
	 * Clock Frequency - Fin=  25000000 (Hz)
	             +-- C0:Fout= 800000000 (Hz)
	             +-- C1:Fout= 400000000 (Hz)
	             +-- C2:Fout= 400000000 (Hz)
	             +-- C3:Fout= 400000000 (Hz)
	             +-- C4:Fout= 400000000 (Hz)
	             +-- C5:Fout= 100000000 (Hz)

	==== setting information of Peripheral PLL: (pll=10) ====
	-- HWLib test : alt_clk_source_get() --
	 * PLL Reference Clock Source: 0
	-- HWLib test : alt_clk_pll_vco_cfg_get() --
	 * VCO - Multiplier (M) value: 80
	 * VCO - Divider (N) value   : 2
	-- HWLib test : alt_clk_pll_cfg_get() --
	 * PLL Reference Clock Source: 0
	 * VCO - Multiplier (M) value: 79 (=>80)
	 * VCO - Divider (N) value   : 1 (=>2)
	 * C0 - {PhaseShift, Divider}: {0, 3 (=>4 x K)}
	 * C1 - {PhaseShift, Divider}: {0, 3 (=>4 x K)}
	 * C2 - {PhaseShift, Divider}: {0, 1 (=>2 x K)}
	 * C3 - {PhaseShift, Divider}: {0, 19 (=>20 x K)}
	 * C4 - {PhaseShift, Divider}: {0, 4 (=>5 x K)}
	 * C5 - {PhaseShift, Divider}: {0, 9 (=>10 x K)}
	 # in the main PLL, K=2 for C0, and K=4 for C1,C2. Others are all K=1.
	-- HWLib test : alt_clk_pll_guard_band_get() --
	-- HWLib test : alt_clk_pll_vco_freq_get() --
	 * Gurad Band Value            :  20 (%)
	 * VCO Frequency (Fvco)        : 1000000000 (Hz)
	-- HWLib test : alt_clk_pll_is_bypassed(),alt_clk_is_enabled() --
	 * Is bypassed(1) or not(0)  : 0
	 * Is enabled(1) or not(0)   : 1
	-- HWLib test : alt_clk_freq_get() --
	 * Clock Frequency - Fin=  25000000 (Hz)
	             +-- C0:Fout= 250000000 (Hz)
	             +-- C1:Fout= 250000000 (Hz)
	             +-- C2:Fout= 500000000 (Hz)
	             +-- C3:Fout=  50000000 (Hz)
	             +-- C4:Fout= 200000000 (Hz)
	             +-- C5:Fout= 100000000 (Hz)

	==== setting information of SDRAM PLL: (pll=11) ====
	-- HWLib test : alt_clk_source_get() --
	 * PLL Reference Clock Source: 0
	-- HWLib test : alt_clk_pll_vco_cfg_get() --
	 * VCO - Multiplier (M) value: 32
	 * VCO - Divider (N) value   : 1
	-- HWLib test : alt_clk_pll_cfg_get() --
	 * PLL Reference Clock Source: 0
	 * VCO - Multiplier (M) value: 31 (=>32)
	 * VCO - Divider (N) value   : 0 (=>1)
	 * C0 - {PhaseShift, Divider}: {0, 1 (=>2 x K)}
	 * C1 - {PhaseShift, Divider}: {0, 0 (=>1 x K)}
	 * C2 - {PhaseShift, Divider}: {0, 1 (=>2 x K)}
	 * C3 - {PhaseShift, Divider}: {0, 0 (=>1 x K)}
	 * C4 - {PhaseShift, Divider}: {0, 0 (=>1 x K)}
	 * C5 - {PhaseShift, Divider}: {0, 5 (=>6 x K)}
	 # in the main PLL, K=2 for C0, and K=4 for C1,C2. Others are all K=1.
	-- HWLib test : alt_clk_pll_guard_band_get() --
	-- HWLib test : alt_clk_pll_vco_freq_get() --
	 * Gurad Band Value            :  20 (%)
	 * VCO Frequency (Fvco)        :  800000000 (Hz)
	-- HWLib test : alt_clk_pll_is_bypassed(),alt_clk_is_enabled() --
	 * Is bypassed(1) or not(0)  : 0
	 * Is enabled(1) or not(0)   : 1
	-- HWLib test : alt_clk_freq_get() --
	 * Clock Frequency - Fin=  25000000 (Hz)
	             +-- C0:Fout= 400000000 (Hz)
	             +-- C1:Fout= 800000000 (Hz)
	             +-- C2:Fout= 400000000 (Hz)
	             +-- C3:Fout=  50000000 (Hz)
	             +-- C4:Fout= 200000000 (Hz)
	             +-- C5:Fout= 133333333 (Hz)

sample_clkmgr_test_customize_config();
	→ Clock Manager の設定変更系 API を一通り実行します（設定変更系 API の試行）。

sample_clkmgr_test_main();
	→ テストプログラムを実行します。
	　 無限ループ内で以下の処理を行います。

	　 - Global Timer カウンタ値の下から 28bit 目以上（下位 32bit の bit#31:28）が変化する毎にカウンタ値をコンソール出力します。
	　　 HPS 用 PUSHSW3 が押されている間は無条件にコンソール出力します（Timer カウンタの進み具合の確認用）。
	
	　 - HPS 用 PUSHSW2 の押下契機で カテゴリ：Clock Manager Status の API を試行します。
	　　 PLL Lock/Unlock Status のクリアおよび表示を行います（Clock Manager Status API の試行）。

	　 - HPS 用 PUSHSW1 の押下契機で カテゴリ：Safe Mode Options の API を試行します。
	　　 Safe Mode ステータスの表示およびクリアを行います（Safe Mode Options API の試行）。
	
	　 - HPS 用 DIPSW[3:0] の変更契機で、PLL の Multiplier 設定値の変更および変更後のクロック周波数の表示を試みます。
	　　 Main PLL の M(1-4096) を対象に、DIPSW1 を MSB、DIPSW4 を LSB として（4bit値 × 4）を Multiplier の設定値に適用します。
	　　 ※ 尚、PLL の変更中は secure モードで動作させるように PLL 変更前後で下記の API を実行します。

	　 - HPS 用 PUSHSW0 の押下契機で無限ループを終了します（テストプログラムの終了）。

◎ プログラム起動（sample_app.c 内の main() 関数の先頭で break）の後、続行(F8) を行うと、
　 コンソール上にてクロックマネージャの動作情報（HPS の動作クロック他）が確認できます。
　 また、無限ループ開始後に HPS 用 PUSHSW、 DIPSW を操作することで特定の API の動作が確認可能になっています。

------------------------------------------------------------------------
>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 以上 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
