moerjielovecookie

Sawen_Blog

一个普通工科牲的博客网站
x
github
follow
email

AXI DMA+AXI-S FIFOループ学習

DMA の紹介#

DMA は現代のコンピュータの特徴の一つであり、ハードウェアがメモリとメモリ、メモリと I/O デバイス間で直接高速データ転送を行うメモリ技術です。これにより、異なる速度のデバイスが CPU の割り込み負荷に依存せずに通信できます。
DMA を使用しない場合、CPU はデータソースから各データセグメントをレジスタにコピーする必要があり、このプロセスは CPU のリソースを常に占有します。DMA を使用すると、CPU は DMA にストレージ転送リクエストを送信し、DMA コントローラがリクエストを受け取ると、データをソースアドレスから目的アドレスに移動します。この移動中は CPU のリソースを消費せず、転送が完了すると DMA コントローラが CPU に割り込みで通知します。
転送トランザクションを開始するには、DMA コントローラには以下が必要です:

  1. ソースアドレス
  2. 目的アドレス
  3. 転送長
    DMA ストレージ転送のプロセスは次の通りです:
  4. プロセッサが DMA コントローラに DMA コマンドを送信します
  5. DMA コントローラがデータを外部デバイスからメモリに転送するか、メモリからメモリに移動し、CPU が他の操作を行えるようにします
  6. データ転送が完了すると、DMA コントローラが CPU に割り込みを発行し、DMA 転送が完了したことを通知します

ZYNQ は二種類の DMA を提供します。一つは PS に統合されたハードコア DMA、もう一つは PL にあるソフトコア AXI DMA IP です。
さまざまなインターフェース方式の比較は以下の通りです:
|500
PL の DMA と AXI_HP インターフェースの転送は、大量データの高性能転送に適しており、帯域幅が高く、転送方式のトポロジー図は以下の通りです:
|500

AXI DMA IP#

AXI ダイレクトメモリアクセス(AXI DMA)IP コアは、AXI 4 メモリマップと AXI 4-Stream IP インターフェース間で高帯域幅の直接ストレージアクセスを提供します。

|500
AXI DMA は三種類のバスを使用します。AXI 4-Lite はレジスタの設定に使用され、AXI 4 メモリマップバスは DDR 内のデータの読み書きに使用され、AXI 4 ストリームバスは AXI DMA が外部デバイスデータの読み書きに使用します。その中で AXI 4 ストリームマスター(MM 2 S、メモリマップからストリーム)インターフェースは PL にデータを書き込み、AXI 4-Stream スレーブ(S 2 MM、ストリームからメモリマップ)インターフェースは PL からデータを読み取ります。
AXI DMA は、ダイレクトレジスタモード、スキャッター / ギャザー モード、サイクリック DMA(循環 DMA)モードの 3 つのモードを提供し、一般的に使用されるのはダイレクトレジスタモードです。
ダイレクトレジスタ DMA モードは、シンプル DMA モードです。ダイレクトレジスタモードは、MM 2 S と S 2 MM チャンネル上でシンプルな DMA 転送を実行するための設定を提供します。シンプル DMA は、アプリケーションが DMA とデバイス間で単一のトランザクションを定義できるようにします。これには二つのチャンネルがあります:一つは DMA からデバイスへ、もう一つはデバイスから DMA へです。ここで注意が必要なのは、シンプル DMA コードを書く際に、対応するチャンネルの転送を開始するためにバッファアドレスと長さフィールドを設定する必要があることです。(PL はデバイスに対応します)

Vivado における IP 設定#

image

スキャッターギャザエンジンを有効にする
このオプションを選択すると、スキャッターギャザー モード操作が有効になり、AXI DMA にスキャッターギャザエンジンが含まれます。このオプションを選択解除すると、ダイレクトレジスタモード操作が有効になり、AXI DMA にスキャッターギャザエンジンは含まれません。スキャッターギャザエンジンを無効にすると、スキャッター / ギャザーエンジンのすべての出力ポートがゼロにバインドされ、すべての入力ポートはオープンのままになります。ここでは、スキャッターギャザエンジンを有効にするチェックを外します。
マイクロ DMA を有効にする
有効にすると、高度に最適化された DMA が生成され、リソース消費が少なく、極少量のデータ転送に使用されます。
バッファ長レジスタの幅
このオプションは、AXI DMA が一度に最大何バイトを転送できるかを設定します。バイト数 $=2^{Width}$
アドレス幅 (32 - 64)
アドレス空間の幅を指定します。32 から 64 の間の任意の値を指定できます。
読み取りチャネルを有効にする
AXI DMA の読み取りチャネル MM 2 S を有効にし、関連する設定は以下の通りです:

  • チャンネル数:指定されたチャンネル数。デフォルト値 1 を保持します。
  • メモリマップデータ幅:AXI MM 2 S ストレージマップが読み取るデータバスのデータビット幅。有効な値は 32、64、128、256、512、1024 です。ここではデフォルト値 32 を保持します。
  • ストリームデータ幅:AXI MM 2 S AXI 4-Stream データバスのデータビット幅。この値はメモリマップデータ幅以下でなければなりません。有効な値は 8、16、32、64、128、512、1024 です。ここではデフォルト値 32 を保持します。
  • 最大バーストサイズ:バースト分割粒度の設定。この設定は、MM 2 S の AXI 4 メモリマップ側のバーストサイクルの最大値を指定します。有効な値は 2、4、8、16、32、64、128、256 です。
  • アライメントされていない転送を許可:MM 2 S データ再配置エンジン(Data Realignment Engine、DRE)を有効または無効にします。選択すると、DRE が有効になり、MM 2 S ストレージマップデータパス上のデータが 8 ビットのバイトレベルに再配置されることを許可します。MM 2 S チャンネルの場合、メモリからデータを読み取ります。DRE が有効な場合、データの読み取りは任意のバッファアドレスのバイトオフセットから開始でき、読み取られたデータは整列され、最初のバイトの読み取りは AXI 4-Stream 上の最初の有効バイト出力となります。
    書き込みチャネルを有効にする
    AXI DMA の書き込みチャネル S 2 MM を有効にし、関連する設定は上記と同様です。

Vitis プロジェクト解析#

ヘッダーファイルのインクルードとマクロ定義#

/***************************** Include Files *********************************/

#include "xaxidma.h"
#include "xparameters.h"
#include "xil_exception.h"
#include "xdebug.h"
#include "xil_util.h"

#ifdef XPAR_UARTNS550_0_BASEADDR
#include "xuartns550_l.h" /* to use uartns550 */
#endif

#ifdef XPAR_INTC_0_DEVICE_ID
#include "xintc.h"
#else
#include "xscugic.h"
#endif

/************************** Constant Definitions *****************************/

/*
 * Device hardware build related constants.
 */

#define DMA_DEV_ID XPAR_AXIDMA_0_DEVICE_ID

#ifdef XPAR_AXI_7SDDR_0_S_AXI_BASEADDR
#define DDR_BASE_ADDR XPAR_AXI_7SDDR_0_S_AXI_BASEADDR
#elif defined(XPAR_MIG7SERIES_0_BASEADDR)
#define DDR_BASE_ADDR XPAR_MIG7SERIES_0_BASEADDR
#elif defined(XPAR_MIG_0_C0_DDR4_MEMORY_MAP_BASEADDR)
#define DDR_BASE_ADDR XPAR_MIG_0_C0_DDR4_MEMORY_MAP_BASEADDR
#elif defined(XPAR_PSU_DDR_0_S_AXI_BASEADDR)
#define DDR_BASE_ADDR XPAR_PSU_DDR_0_S_AXI_BASEADDR
#endif

#define DDR_BASE_ADDR XPAR_PS7_DDR_0_S_AXI_BASEADDR // 0x00100000

#ifndef DDR_BASE_ADDR
#warning CHECK FOR THE VALID DDR ADDRESS IN XPARAMETERS.H, \
		DEFAULT SET TO 0x01000000
#define MEM_BASE_ADDR 0x01000000
#else
#define MEM_BASE_ADDR (DDR_BASE_ADDR + 0x01000000) // 0x01100000
#endif

#ifdef XPAR_INTC_0_DEVICE_ID
#define RX_INTR_ID XPAR_INTC_0_AXIDMA_0_S2MM_INTROUT_VEC_ID
#define TX_INTR_ID XPAR_INTC_0_AXIDMA_0_MM2S_INTROUT_VEC_ID
#else
#define RX_INTR_ID XPAR_FABRIC_AXIDMA_0_S2MM_INTROUT_VEC_ID
#define TX_INTR_ID XPAR_FABRIC_AXIDMA_0_MM2S_INTROUT_VEC_ID
#endif

#define TX_BUFFER_BASE (MEM_BASE_ADDR + 0x00100000) // 0x01200000
#define RX_BUFFER_BASE (MEM_BASE_ADDR + 0x00300000) // 0x01400000
#define RX_BUFFER_HIGH (MEM_BASE_ADDR + 0x004FFFFF) // 0x015FFFFF

#ifdef XPAR_INTC_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_INTC_0_DEVICE_ID
#else
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#endif

#ifdef XPAR_INTC_0_DEVICE_ID
#define INTC XIntc
#define INTC_HANDLER XIntc_InterruptHandler
#else
#define INTC XScuGic
#define INTC_HANDLER XScuGic_InterruptHandler
#endif

/* Timeout loop counter for reset
 */
#define RESET_TIMEOUT_COUNTER 10000

#define TEST_START_VALUE 0x1
/*
 * Buffer and Buffer Descriptor related constant definition
 */
#define MAX_PKT_LEN 0x200

#define NUMBER_OF_TRANSFERS 10
#define POLL_TIMEOUT_COUNTER 1000000U
#define NUMBER_OF_EVENTS 1

#define DDR_BASE_ADDR XPAR_AXI_7SDDR_0_S_AXI_BASEADDR は DDR 3 の基準アドレスを再定義します。データの読み書きの基準アドレスは #define MEM_BASE_ADDR (DDR_BASE_ADDR + 0x01000000) // 0x01100000 で、AXI DMA がデータを読み取る開始アドレスは #define TX_BUFFER_BASE (MEM_BASE_ADDR + 0x00100000) // 0x01200000 で、書き込みアドレスは 0x01400000 です。

関数の定義と関連するインスタンスおよびフラグ変数の宣言#

/**************************** Type Definitions *******************************/

/***************** Macros (Inline Functions) Definitions *********************/

/************************** Function Prototypes ******************************/
#ifndef DEBUG
extern void xil_printf(const char *format, ...);
#endif

#ifdef XPAR_UARTNS550_0_BASEADDR
static void Uart550_Setup(void);
#endif

static int CheckData(int Length, u8 StartValue);
static void TxIntrHandler(void *Callback);
static void RxIntrHandler(void *Callback);

static int SetupIntrSystem(INTC *IntcInstancePtr,
						   XAxiDma *AxiDmaPtr, u16 TxIntrId, u16 RxIntrId);
static void DisableIntrSystem(INTC *IntcInstancePtr,
							  u16 TxIntrId, u16 RxIntrId);

/************************** Variable Definitions *****************************/
/*
 * Device instance definitions
 */

static XAxiDma AxiDma; /* XAxiDma のインスタンス */

static INTC Intc; /* 割り込みコントローラのインスタンス */

/*
 * フラグ割り込みハンドラがアプリケーションコンテキストにイベントを通知するために使用します。
 */
volatile u32 TxDone;
volatile u32 RxDone;
volatile u32 Error;

Main 関数#

/*****************************************************************************/
/**
 *
 * Main function
 *
 * This function is the main entry of the interrupt test. It does the following:
 *	Set up the output terminal if UART16550 is in the hardware build
 *	Initialize the DMA engine
 *	Set up Tx and Rx channels
 *	Set up the interrupt system for the Tx and Rx interrupts
 *	Submit a transfer
 *	Wait for the transfer to finish
 *	Check transfer status
 *	Disable Tx and Rx interrupts
 *	Print test status and exit
 *
 * @param	None
 *
 * @return
 *		- XST_SUCCESS if example finishes successfully
 *		- XST_FAILURE if example fails.
 *
 * @note		None.
 *
 ******************************************************************************/
int main(void)
{
	int Status;
	XAxiDma_Config *Config;
	int Tries = NUMBER_OF_TRANSFERS;
	int Index;
	u8 *TxBufferPtr;
	u8 *RxBufferPtr;
	u8 Value;

	TxBufferPtr = (u8 *)TX_BUFFER_BASE;
	RxBufferPtr = (u8 *)RX_BUFFER_BASE;
	/* Uart16550 の初期設定 */
#ifdef XPAR_UARTNS550_0_BASEADDR

	Uart550_Setup();

#endif

	xil_printf("\r\n--- main() に入ります --- \r\n");

	Config = XAxiDma_LookupConfig(DMA_DEV_ID);
	if (!Config)
	{
		xil_printf("%d の設定が見つかりません\r\n", DMA_DEV_ID);

		return XST_FAILURE;
	}
	else
	{
		xil_printf("%d の設定が見つかりました\r\n", DMA_DEV_ID);
	}

	/* DMA エンジンの初期化 */
	Status = XAxiDma_CfgInitialize(&AxiDma, Config);

	if (Status != XST_SUCCESS)
	{
		xil_printf("初期化に失敗しました %d\r\n", Status);
		return XST_FAILURE;
	}
	else
	{
		xil_printf("DMA 初期化成功 %d\r\n", Status);
	}

	if (XAxiDma_HasSg(&AxiDma))
	{
		xil_printf("デバイスは SG モードに設定されています\r\n");
		return XST_FAILURE;
	}
	else
	{
		xil_printf("デバイスはシンプルモードに設定されています\r\n");
	}

	/* 割り込みシステムの設定  */
	Status = SetupIntrSystem(&Intc, &AxiDma, TX_INTR_ID, RX_INTR_ID);
	if (Status != XST_SUCCESS)
	{

		xil_printf("割り込み設定に失敗しました\r\n");
		return XST_FAILURE;
	}

	/* 設定前にすべての割り込みを無効にします */

	XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
						XAXIDMA_DMA_TO_DEVICE);

	XAxiDma_IntrDisable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
						XAXIDMA_DEVICE_TO_DMA);

	/* すべての割り込みを有効にします */
	XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
					   XAXIDMA_DMA_TO_DEVICE);

	XAxiDma_IntrEnable(&AxiDma, XAXIDMA_IRQ_ALL_MASK,
					   XAXIDMA_DEVICE_TO_DMA);

	/* 転送テスト開始前にフラグを初期化します  */
	TxDone = 0;
	RxDone = 0;
	Error = 0;

	Value = TEST_START_VALUE;

	for (Index = 0; Index < MAX_PKT_LEN; Index++)
	{
		TxBufferPtr[Index] = Value;

		Value = (Value + 1) & 0xFF;
	}

	/* DMA 転送前にバッファをフラッシュします。データキャッシュが有効な場合に備えて
	 */
	Xil_DCacheFlushRange((UINTPTR)TxBufferPtr, MAX_PKT_LEN);
	Xil_DCacheFlushRange((UINTPTR)RxBufferPtr, MAX_PKT_LEN);
	/* パケットを送信します */
	for (int i = 0; i < Tries; i++)
	{

		Status = XAxiDma_SimpleTransfer(&AxiDma, (UINTPTR)RxBufferPtr,
										MAX_PKT_LEN, XAXIDMA_DEVICE_TO_DMA);

		if (Status != XST_SUCCESS)
		{
			return XST_FAILURE;
		}

		Status = XAxiDma_SimpleTransfer(&AxiDma, (UINTPTR)TxBufferPtr,
										MAX_PKT_LEN, XAXIDMA_DMA_TO_DEVICE);

		if (Status != XST_SUCCESS)
		{
			return XST_FAILURE;
		}

		Status = Xil_WaitForEventSet(POLL_TIMEOUT_COUNTER, NUMBER_OF_EVENTS, &Error);
		if (Status == XST_SUCCESS)
		{
			if (!TxDone)
			{
				xil_printf("送信エラー %d\r\n", Status);
				goto Done;
			}
			else if (Status == XST_SUCCESS && !RxDone)
			{
				xil_printf("受信エラー %d\r\n", Status);
				goto Done;
			}
		}

		/*
		 * TX 完了またはタイムアウトを待ちます
		 */
		Status = Xil_WaitForEventSet(POLL_TIMEOUT_COUNTER, NUMBER_OF_EVENTS, &TxDone);
		if (Status != XST_SUCCESS)
		{
			xil_printf("送信に失敗しました %d\r\n", Status);
			goto Done;
		}

		/*
		 * RX 完了またはタイムアウトを待ちます
		 */
		Status = Xil_WaitForEventSet(POLL_TIMEOUT_COUNTER, NUMBER_OF_EVENTS, &RxDone);
		if (Status != XST_SUCCESS)
		{
			xil_printf("受信に失敗しました %d\r\n", Status);
			goto Done;
		}

		/*
		 * テストが完了しました。データを確認します
		 */
		Status = CheckData(MAX_PKT_LEN, 0x1);
		if (Status != XST_SUCCESS)
		{
			xil_printf("データチェックに失敗しました\r\n");
			goto Done;
		}
		xil_printf("転送 %d 完了\r\n", i + 1);
	}
	xil_printf("AXI DMA 割り込み例が正常に実行されました\r\n");

	/* TX および RX リング割り込みを無効にし、成功を返します */

	DisableIntrSystem(&Intc, TX_INTR_ID, RX_INTR_ID);

Done:
	xil_printf("--- main() を終了します --- \r\n");

	if (Status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}

	return XST_SUCCESS;
}

Tries はテストループの回数です。

関数の実装#

/*****************************************************************************/
/*
 *
 * この関数は DMA 転送が完了した後にデータバッファをチェックします。
 *
 * 静的な tx/rx バッファを使用します。
 *
 * @param	Length はチェックする長さです
 * @param	StartValue は最初のバイトの開始値です
 *
 * @return
 *		- 検証が成功した場合は XST_SUCCESS
 *		- 検証が失敗した場合は XST_FAILURE。
 *
 * @note		なし。
 *
 ******************************************************************************/
static int CheckData(int Length, u8 StartValue)
{
	u8 *RxPacket;
	int Index = 0;
	u8 Value;

	RxPacket = (u8 *)RX_BUFFER_BASE;
	Value = StartValue;

	/* データを受信する前に DestBuffer を無効にします。データキャッシュが有効な場合に備えて
	 */
	Xil_DCacheInvalidateRange((UINTPTR)RxPacket, Length);

	for (Index = 0; Index < Length; Index++)
	{
		if (RxPacket[Index] != Value)
		{
			xil_printf("データエラー %d: %x/%x\r\n",
					   Index, RxPacket[Index], Value);

			return XST_FAILURE;
		}
		Value = (Value + 1) & 0xFF;
	}

	return XST_SUCCESS;
}

/*****************************************************************************/
/*
 *
 * これは DMA TX 割り込みハンドラ関数です。
 *
 * ハードウェアから割り込みステータスを取得し、確認し、エラーが発生した場合はハードウェアをリセットします。そうでなければ、完了割り込みが存在する場合は TxDone フラグを設定します。
 *
 * @param	Callback は DMA エンジンの TX チャンネルへのポインタです。
 *
 * @return	なし。
 *
 * @note		なし。
 *
 ******************************************************************************/
static void TxIntrHandler(void *Callback)
{

	u32 IrqStatus;
	int TimeOut;
	XAxiDma *AxiDmaInst = (XAxiDma *)Callback;

	/* 保留中の割り込みを読み取ります */
	IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DMA_TO_DEVICE);

	/* 保留中の割り込みを確認します */

	XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DMA_TO_DEVICE);

	/*
	 * 割り込みが発生していない場合は、何もしません
	 */
	if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK))
	{

		return;
	}

	/*
	 * エラー割り込みが発生した場合は、エラーフラグを上げ、ハードウェアをリセットしてエラーから回復し、さらなる処理を行わずに戻ります。
	 */
	if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK))
	{

		Error = 1;

		/*
		 * 送信チャネルのリセットは失敗してはなりません
		 */
		XAxiDma_Reset(AxiDmaInst);

		TimeOut = RESET_TIMEOUT_COUNTER;

		while (TimeOut)
		{
			if (XAxiDma_ResetIsDone(AxiDmaInst))
			{
				break;
			}

			TimeOut -= 1;
		}

		return;
	}

	/*
	 * 完了割り込みが発生した場合は、TxDone フラグを設定します
	 */
	if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK))
	{

		TxDone = 1;
	}
}

/*****************************************************************************/
/*
 *
 * これは DMA RX 割り込みハンドラ関数です。
 *
 * ハードウェアから割り込みステータスを取得し、確認し、エラーが発生した場合はハードウェアをリセットします。そうでなければ、完了割り込みが存在する場合は RxDone フラグを設定します。
 *
 * @param	Callback は DMA エンジンの RX チャンネルへのポインタです。
 *
 * @return	なし。
 *
 * @note		なし。
 *
 ******************************************************************************/
static void RxIntrHandler(void *Callback)
{
	u32 IrqStatus;
	int TimeOut;
	XAxiDma *AxiDmaInst = (XAxiDma *)Callback;

	/* 保留中の割り込みを読み取ります */
	IrqStatus = XAxiDma_IntrGetIrq(AxiDmaInst, XAXIDMA_DEVICE_TO_DMA);

	/* 保留中の割り込みを確認します */
	XAxiDma_IntrAckIrq(AxiDmaInst, IrqStatus, XAXIDMA_DEVICE_TO_DMA);

	/*
	 * 割り込みが発生していない場合は、何もしません
	 */
	if (!(IrqStatus & XAXIDMA_IRQ_ALL_MASK))
	{
		return;
	}

	/*
	 * エラー割り込みが発生した場合は、エラーフラグを上げ、ハードウェアをリセットしてエラーから回復し、さらなる処理を行わずに戻ります。
	 */
	if ((IrqStatus & XAXIDMA_IRQ_ERROR_MASK))
	{

		Error = 1;

		/* リセットは失敗する可能性があり、ハングする可能性があります
		 * これを処理する方法が必要です、または呼び出さないでください??
		 */
		XAxiDma_Reset(AxiDmaInst);

		TimeOut = RESET_TIMEOUT_COUNTER;

		while (TimeOut)
		{
			if (XAxiDma_ResetIsDone(AxiDmaInst))
			{
				break;
			}

			TimeOut -= 1;
		}

		return;
	}

	/*
	 * 完了割り込みが発生した場合は、RxDone フラグを設定します
	 */
	if ((IrqStatus & XAXIDMA_IRQ_IOC_MASK))
	{

		RxDone = 1;
	}
}

/*****************************************************************************/
/*
 *
 * この関数は、DMA の割り込みシステムを設定して割り込みが発生できるようにします。ハードウェアシステムに INTC コンポーネントが存在することを前提としています。
 *
 * @param	IntcInstancePtr は INTC のインスタンスへのポインタです。
 * @param	AxiDmaPtr は DMA エンジンのインスタンスへのポインタです
 * @param	TxIntrId は TX チャンネルの割り込み ID です。
 * @param	RxIntrId は RX チャンネルの割り込み ID です。
 *
 * @return
 *		- 成功した場合は XST_SUCCESS、
 *		- 成功しなかった場合は XST_FAILURE
 *
 * @note		なし。
 *
 ******************************************************************************/
static int SetupIntrSystem(INTC *IntcInstancePtr,
						   XAxiDma *AxiDmaPtr, u16 TxIntrId, u16 RxIntrId)
{
	int Status;

#ifdef XPAR_INTC_0_DEVICE_ID

	/* 割り込みコントローラを初期化し、ISR を接続します */
	Status = XIntc_Initialize(IntcInstancePtr, INTC_DEVICE_ID);
	if (Status != XST_SUCCESS)
	{

		xil_printf("INTC の初期化に失敗しました\r\n");
		return XST_FAILURE;
	}

	Status = XIntc_Connect(IntcInstancePtr, TxIntrId,
						   (XInterruptHandler)TxIntrHandler, AxiDmaPtr);
	if (Status != XST_SUCCESS)
	{

		xil_printf("TX を INTC に接続するのに失敗しました\r\n");
		return XST_FAILURE;
	}

	Status = XIntc_Connect(IntcInstancePtr, RxIntrId,
						   (XInterruptHandler)RxIntrHandler, AxiDmaPtr);
	if (Status != XST_SUCCESS)
	{

		xil_printf("RX を INTC に接続するのに失敗しました\r\n");
		return XST_FAILURE;
	}

	/* 割り込みコントローラを起動します */
	Status = XIntc_Start(IntcInstancePtr, XIN_REAL_MODE);
	if (Status != XST_SUCCESS)
	{

		xil_printf("INTC を起動するのに失敗しました\r\n");
		return XST_FAILURE;
	}

	XIntc_Enable(IntcInstancePtr, TxIntrId);
	XIntc_Enable(IntcInstancePtr, RxIntrId);

#else

	XScuGic_Config *IntcConfig;

	/*
	 * 割り込みコントローラドライバを初期化して、使用できるようにします。
	 */
	IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
	if (NULL == IntcConfig)
	{
		return XST_FAILURE;
	}

	Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
								   IntcConfig->CpuBaseAddress);
	if (Status != XST_SUCCESS)
	{
		return XST_FAILURE;
	}
	// 割り込み優先度とトリガタイプを設定します
	XScuGic_SetPriorityTriggerType(IntcInstancePtr, TxIntrId, 0xA0, 0x3);

	XScuGic_SetPriorityTriggerType(IntcInstancePtr, RxIntrId, 0xA0, 0x3);
	/*
	 * デバイスに対する割り込みが発生したときに呼び出されるデバイスドライバハンドラを接続します。上記で定義されたハンドラは、デバイスの特定の割り込み処理を実行します。
	 */
	 // 割り込み処理関数を設定します
	Status = XScuGic_Connect(IntcInstancePtr, TxIntrId,
							 (Xil_InterruptHandler)TxIntrHandler,
							 AxiDmaPtr);
	if (Status != XST_SUCCESS)
	{
		return Status;
	}

	Status = XScuGic_Connect(IntcInstancePtr, RxIntrId,
							 (Xil_InterruptHandler)RxIntrHandler,
							 AxiDmaPtr);
	if (Status != XST_SUCCESS)
	{
		return Status;
	}
	
	XScuGic_Enable(IntcInstancePtr, TxIntrId);
	XScuGic_Enable(IntcInstancePtr, RxIntrId);

#endif

	/* ハードウェアからの割り込みを有効にします */

	Xil_ExceptionInit();
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
								 (Xil_ExceptionHandler)INTC_HANDLER,
								 (void *)IntcInstancePtr);

	Xil_ExceptionEnable();

	return XST_SUCCESS;
}

/*****************************************************************************/
/**
 *
 * この関数は DMA エンジンの割り込みを無効にします。
 *
 * @param	IntcInstancePtr は INTC コンポーネントインスタンスへのポインタです
 * @param	TxIntrId は DMA TX チャンネルに関連付けられた割り込み ID です
 * @param	RxIntrId は DMA RX チャンネルに関連付けられた割り込み ID です
 *
 * @return	なし。
 *
 * @note		なし。
 *
 ******************************************************************************/
static void DisableIntrSystem(INTC *IntcInstancePtr,
							  u16 TxIntrId, u16 RxIntrId)
{
#ifdef XPAR_INTC_0_DEVICE_ID
	/* DMA TX および RX チャンネルの割り込みを切断します */
	XIntc_Disconnect(IntcInstancePtr, TxIntrId);
	XIntc_Disconnect(IntcInstancePtr, RxIntrId);
#else
	XScuGic_Disconnect(IntcInstancePtr, TxIntrId);
	XScuGic_Disconnect(IntcInstancePtr, RxIntrId);
#endif
}

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。