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

-- 情報 ----------------------------------------------------------------
ファイル名：		sample_dma_mem.c
作成日：			2015/03/03
更新日：			2015/03/23	"v14.0 以前のツールでコンパイルエラーとなる問題を修正 (alt_dma_custom.c)"
更新日：			2015/06/25	"SoC EDS 15.0 用の HWLib に対応。文字コードを UTF-8 に変更 (Linux の日本語表示)。
						 		割込みログの実装を改善 (割込み利用の場合のみ)"
更新日：			2016/01/08	"SoC EDS 15.1 用の HWLib に対応。HWLib の変更に伴いコンパイルが通らない状態になっていた"
更新日：			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 バージョン：	14.1 (SoC EDS Version: 14.1, Build: 186)
確認 HWLib バージョン：	15.0 (SoC EDS Version: 15.0.1, Build: 60)
確認 HWLib バージョン：	15.1 (SoC EDS Version: 15.1, Build: 185)
確認 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 v15.0 以前のツールを利用する場合には、本サンプルに含まれるソースコードの差し替えが必要となります。
　 alt_dma_custom__old_hwlib_base.c を alt_dma_custom.c へリネームして差し替えを行ってください。

※ 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. *
**************************************************************************************

※ 本サンプルでは、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

※ 本サンプルでは、sample_app.c 内で DMA の初期化を行わせるために、
　 config.mk ファイル内の USED_DMA 定義を 1 に設定してビルドしてください。
　################################
　# USE DMA sample (0:No / 1:Yes)#
　################################
　USED_DMA := 1

※ 本サンプルでは、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 等で書き込みしてください）


-- 概要 ----------------------------------------------------------------
HPS 内臓 DMA (DMA-330) を使って、メモリ to メモリの DMA 転送を行うサンプルです。
本サンプルでは MMU および L1, L2 キャッシュ、ならびに ACP ポートを有効化した環境下で
転送を行う実装としています。

ターゲット・ボード上の PUSHSW、DIPSW の操作により下記のオプションを選択可能としています。
 - DMA Channel の選択（0～7）
 - 転送経路（通常ポート(ACP 未使用) / ACP ポート経由）
 - キャッシュメンテナンス操作を行う/行わない 

　※ Arria 10 SoC は、AXI トランザクションのキャッシュ属性を見て ACP ポートの利用を
　　 自動的に判断するため、ACP 使用/未使用のオプションは意味を持ちません。

上記のオプションを選択した上で DMA テストを実行すると、
1 回の実行当たり、MMU 設定の異なる以下 8 パターンのバッファ間転送を試行し、
DMA 転送の実行にかかった処理時間および転送結果 (OK/NG) を表示します。

＜ DMA 転送元/先バッファ組み合わせ（8 パターン）＞
 - TEST.01 : NonCache Buffer --> NonCache Buffer
 - TEST.02 : Cacheable[Write-Through(WT)] Buffer --> NonCache Buffer
 - TEST.03 : Cacheable[Write-Back(WB)] Buffer --> NonCache Buffer
 - TEST.04 : Cacheable[Write-Back with Allocate(WBA)] Buffer --> NonCache Buffer
 - TEST.05 : NonCache Buffer --> Cacheable[WBA] Buffer
 - TEST.06 : Cacheable[WT] Buffer --> Cacheable[WBA] Buffer
 - TEST.07 : Cacheable[WB] Buffer --> Cacheable[WBA] Buffer
 - TEST.08 : Cacheable[WBA] Buffer --> Cacheable[WBA] Buffer

DMA 転送を行う際の処理手順は以下のように実装しています。
実行時に表示される処理時間(※)も以下の手順別に表示されます。

＜ DMA 転送テストの処理手順 ＞
 1. テストデータ格納（転送元へデータ書き込み／転送先を 0 クリア）
 2. キャッシュメンテナンス（on-cache で格納されたデータを物理メモリへ反映）
 3. DMA-330 用マイクロコード生成
 4. DMA 実行（転送開始 ～ DMA 完了割り込み発生）
 5. DMA 転送結果をベリファイ .. 結果を OK/NG 表示

※注意：ACP ポート経由の DMA 転送を利用した場合、L1, L2 キャッシュにも作用するため、
　　　　CPU からのアクセスに対するキャッシュ効率が下がることが考えられます。
　　　　ACP の利用については、CPU 側の処理性能も十分に検証した上でご検討されるようご注意ください。
　　　　（本サンプルで表示される処理時間は、あくまで参考までとして下さい）


プログラム実行開始後、初期設定や各種 API の実行テストが完了すると、下記の表示とともにループ処理を開始します。
"==== Start While(1) loop process!!! (Exit PUSHSW0(SW8) becomes ON.) ===="

ループ中に HPS 用 PUSHSW の操作を検出した場合、それぞれ以下の処理を実行します。
	- HPS 用 PUSHSW0 ... ループを抜けてプログラム終了。
	- HPS 用 PUSHSW1 ... DMA レジスタ表示（Management Thread, Ch Thead のステータスを表示）
	- HPS 用 PUSHSW2 ... DMA 転送テスト実行（オプション選択：通常ポート(ACP 未使用)）
	- HPS 用 PUSHSW3 ... DMA 転送テスト実行（オプション選択：ACP ポート経由）
	- HPS 用 DIPSW0 .... オプション選択：キャッシュメンテナス ON/OFF 
	- HPS 用 DIPSW[3:1]. オプション選択：DMA Channel 0～7 

● 基本的に、Running(F8) した状態で、PUSHSW／DIPSW を操作して DMA テストを実行します。
　 転送データの内容を確認する場合には、Break(F9) してメモリビューを参照してください。


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

　　①．アーカイブを 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_DMA の定義を "1" に設定してプロジェクトをビルドすると、
	　　ターゲットボードの DIP スイッチを 「Command モード」 に設定してコンソールから "dmamem" コマンドを入力することにより、
	　　util/cmd.c 内から sample_dma_mem.c の sample_dma_mem_test_cmd() 関数が呼び出されます。

　ENABLE_EXAMPLE_DMA     : sample_dmac.c,sample_dma_mem.c (USED_DMA must be 1) 
　ENABLE_EXAMPLE_DMA     := 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_dma_mem_test_cmd() 以降） ------------------------------

◎ sample_dma_mem_test_cmd() 関数内の構成概要を以下に記載します。

1. HPS (CPU) およびターゲット・ボート用の初期設定を行います（MMU, ACP の設定処理はこの関数内を参照）。
　　// CPU and board settings.
　　cpu0_init();

2. DMA-330 用の設定を行います（割り込みコールバックの登録など、DMA-330 利用に必要な設定等はこの関数内を参照）。
　　// Initializing the dmac functions of hwlib. 
　　sample_dma_mem_test_init();

3. 無限ループに入り以下のテストを実行します。
　　printf("==== Start While(1) loop process!!! (Exit PUSHSW0(SW8) becomes ON.) ====\n");
　　while(1)
　　{
　　　　...
　　
　　3-1. DMAC ステータスを表示します（DMA Manager スレッドおよび DIPSW で選択中の DMA CH ステータスを表示）。
　　　　// PUSHSW HPS 1
　　　　　　sample_dma_mem_print_manager_status();
　　　　　　sample_dma_mem_print_ch_status(channel, true);
　　
　　　　...
　　
　　3-2. DMA 転送テストを実行します（下記の関数内で 8 パターンの転送を行います。転送処理の詳細は以下の関数内を参照）。
　　　　// PUSHSW HPS 2
　　　　// PUSHSW HPS 3
　　　　　　sample_dma_mem_test_main(channel, acp_en, cacheope_en);
　　　　...
　　}


◎ 補足１．ACP を利用するためには ｢SMP モード ON｣、および ｢SCU 有効｣ の設定が前提条件となります。
　　　　　 本サンプルにおける該当の処理は以下の部分となります。

ファイル名：sample_app_setting.c
00394|int cpu0_init(void)
00395|{
...
00401|    // ACTLR.SMP=1 / NSACR.NS_SMP=1
00402|    enable_actlr_smp();
00403|    enable_nsacr_nssmp();
00404|    
00405|    // Initialize SCU (SCU is a shared resource in the MPCore. So, performed only by Core0.)
00406|    SOCFPGA5XS1_BSP_SCU_CTLR    = 0x0;                          /* Disable SCU */
00407|    SOCFPGA5XS1_BSP_SCU_INV_WAY = 0xFFFF;                       /* Invalidate SCU Tag RAM */
00408|    SOCFPGA5XS1_BSP_SCU_CTLR    = 0x1;                          /* Enable SCU */


◎ 補足２．DMA-330 利用に必要な設定は、HWLib の API:alt_dma_init を呼び出して対応しています。
　　　　　 alt_dma_init の引数 (構造体：ALT_DMA_CFG_t) にパラメータを渡す事で設定が行われます。
　　　　　 該当の処理は以下の部分となります (System Manager のセキュリティ設定)。

ファイル名：sample_app.c
00417|static void sample_dmac_test_init(void)
...
00425|    /* Execute initialize dmac function of hwlib  */
00426|    /* Usage:   ALT_STATUS_CODE  alt_dma_init (const ALT_DMA_CFG_t *dma_cfg);   */
00427|    // Set the parameters for alt_dma_init().
00428|    for(i=0; i<4; i++){
00429|        dma_config.periph_mux[i] = ALT_DMA_PERIPH_MUX_DEFAULT;  // Handle FPGA / CAN muxing (default is FPGA)
00430|    }
00431|    dma_config.manager_sec = ALT_DMA_SECURITY_DEFAULT;          // Handle Manager Secure / NonSecure (default is Secure)
00432|    for(i=0; i<ALT_SYSMGR_DMA_CTL_IRQNONSECURE_WIDTH; i++){
00433|        dma_config.irq_sec[i] = ALT_DMA_SECURITY_DEFAULT;       // Handle IRQ Secure / NonSecure (default is Secure)
00434|    }
00435|    for(i=0; i<32; i++){
00436|        dma_config.periph_sec[i] = ALT_DMA_SECURITY_DEFAULT;    // peripheral Secure / NonSecure (default is Secure)
00437|    }
00438|    result_code = alt_dma_init(&dma_config);
00439|    if(result_code != ALT_E_SUCCESS){
00440|        printf("ERROR!!: alt_dma_init() .... result=%d\n", (int)result_code);
00441|    }


◎ 補足３．DMA 転送テスト実行時に表示される処理時間は、Global Timer を利用して計測しています。
　　　　　 Atlas ボード (デバイス：5CSEMA4U23C6N) を以下の Main PLL 設定で動作させた場合を前提に
　　　　　 正しい時間が表示されるように実装しているので、他の環境に移植した場合には調整が必要となります。
　　
　　ALT_CLK_MPU(19):            Frequency= 925000000 (Hz) [Divider=2]
　　ALT_CLK_MPU_L2_RAM(20):     Frequency= 462500000 (Hz) [Divider=2]
　　ALT_CLK_MPU_PERIPH(21):     Frequency= 231250000 (Hz) [Divider=4]
　　ALT_CLK_L4_MAIN(25):        Frequency= 462500000 (Hz) [Divider=4]
　　ALT_CLK_L4_MP(26):          Frequency= 100000000 (Hz) [Divider=2]
　　ALT_CLK_L4_SP(27):          Frequency= 100000000 (Hz) [Divider=2]


◎ 補足４．DMA 用 HWLib のカスタマイズ (alt_dma_custom.c)
　　　　　 本サンプルの DMA 転送用APIは、HWLib の alt_dma.c をベースにカスタマイズした
　　　　　 ファイル alt_dma_custom.c を利用しています。

○４－１．＜変更点１＞
　　　　　DMA 転送時間を計測する都合で、HWLib の メモリ to メモリ転送実行用の API：alt_dma_memory_to_memory の
　　　　　DMA-330 用マイクロコード生成部分のみを別関数化しています。
　　　　　また、ACP ポート経由で DMA 転送を行うためには、AXI 信号 (AWCACHE/ARCACHE) の C ビットを 1 に設定する
　　　　　必要があるため、引数指定にて DMA 転送実行時の AXI 信号を指定可能としています。

ファイル名：alt_dma_custom.c
05983|ALT_STATUS_CODE alt_dma_channel_program_memory_to_memory(ALT_DMA_CHANNEL_t channel,
05984|                                            ALT_DMA_PROGRAM_t * program,
05985|                                            void * dst,       int dst_cache_ctrl,
05986|                                            const void * src, int src_cache_ctrl,
05987|                                            size_t size)
05988|{
...
06198|}

　　　　　ACP ポート利用時の AWCACHE/ARCACHE 設定については、ARM ドキュメント
　　　　　『Cortex(TM)-A9 MPCore テクニカルリファレンスマニュアル』
　　　　　「2.4.1 ACP 要求」を参照ください。


○４－２．＜変更点２＞
　　　　　DMA-330 用マイクロコード格納バッファのサイズに最大値を指定しています。
　　　　　Makefile 上で ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE=65536 を指定する事で
　　　　　大きなサイズの DMA 転送が行えるように変更しています。
　　　　　(最大値 65535 を指定すると大量のメモリを占有するため、本来はマイクロコードの最大サイズに
　　　　　応じて最適なサイズを指定します)。
　　　　　
　　　　　標準の設定では、弊社で試した限りでは、転送サイズ 2 ～ 3 MByte 程度 (利用する API により異なる)で
　　　　　バッファが足りなくなるようです (バッファが足りない場合、API がエラー ALT_E_BUF_OVF を返します)。
　　　　　この件は、HWLib の alt_dma_program.h に下記のように記載されています。

/*!
 * This preprocessor definition determines the size of the program buffer
 * within the ALT_DMA_PROGRAM_t structure. This size should provide adequate
 * size for most DMA microcode programs. If calls within this API are
 * reporting out of memory response codes, consider increasing the provisioned
 * program buffersize.
 *
 * To specify another DMA microcode program buffer size, redefine the macro
 * below by defining ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE to another size in
 * your Makefile. It is recommended that the size be a multiple of the
 * microcode engine cache line size. See ALT_DMA_PROGRAM_CACHE_LINE_SIZE for
 * more information. The largest supported buffer size is 65536 bytes.
 */
#ifndef ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE
#define ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE   (ALT_DMA_PROGRAM_CACHE_LINE_SIZE * ALT_DMA_PROGRAM_CACHE_LINE_COUNT)
#endif


◎ 補足５．DMA 転送テストは、転送サイズ 128MByte で実装されています。
　　　　　 サイズを変えて試したい場合には、下記の変数 (dma_trans_size) を変更することで再コンパイルせずに
　　　　　 サイズ変更することも可能です (一旦 Break(F9) して、変数値を書き換えます)。

ファイル名：sample_app.c
00118|size_t  dma_trans_size = DMA_TEST_SIZE;         // DMA転送サイズ

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