中断初期化設定プロセス#
- 中断コントローラの設定情報を探し、中断コントローラドライバを初期化する(XScuGic_LookupConfig、XScuGic_CfgInitialize)
- 中断タイプを設定する(XScuGic_SetPriorityTriggerType)
- 中断処理関数を中断に設定する(XScuGic_Connect)
- 中断を有効にする (XScuGic_Enable)
- 中断例外を設定し、有効にする(Xil_ExceptionInit、Xil_ExceptionRegisterHandler、Xil_ExceptionEnable)
- GPIO 中断を有効にする(XGpioPs_IntrEnablePin)
コード例#
このコードは AXI GPIO 初期化の一部を含み、残りは PS 側 GPIO の初期化と中断初期化設定です。
/******************************************************************************
* Copyright (C) 2002 - 2021 Xilinx, Inc. All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/
/*****************************************************************************/
/**
* @file xgpio_example.c
*
* このファイルはAXI GPIOドライバ(XGpio)と
* ハードウェアデバイスを使用した設計例を含みます。 これは
* GPIOデバイスのチャネル1のみを使用し、
* GPIOのビット0がHWボードのLEDに接続されていると仮定します。
*
*
* <pre>
* 修正履歴:
*
* Ver 誰 日付 変更
* ----- ---- -------- -----------------------------------------------
* 1.00a rmm 03/13/02 初回リリース
* 1.00a rpm 08/04/03 2番目の例と無効なマクロ呼び出しを削除
* 2.00a jhl 12/15/03 デュアルチャネルのサポートを追加
* 2.00a sv 04/20/05 Doxygenとコーディングガイドラインに準拠するための小さな変更
* 3.00a ktn 11/20/09 コーディングガイドラインに従った小さな変更。
* 4.1 lks 11/18/15 標準のxparametersを使用するように更新し、
* コメントとコードをCR 900381のためにクリーンアップ
* 4.3 sk 09/29/16 LED_bitsが出力として設定されているときに動作するように例を修正。 CR# 958644
* ms 01/23/17 メイン関数にxil_printfステートメントを追加し、
* "Successfully ran"および"Failed"文字列が
* すべての例で利用可能であることを確認します。 これは
* CR-965028の修正です。
* 4.5 sne 06/12/19 IARコンパイラの警告を修正。
*
* </pre>
******************************************************************************/
/***************************** Include Files *********************************/
#include "xparameters.h"
#include "xgpio.h"
#include "xil_printf.h"
#include "sleep.h"
#include "xscugic.h"
#include "xil_exception.h"
#include <xgpiops.h>
/************************** Constant Definitions *****************************/
#define MODE_SINGLE_TONE 0x00
#define MODE_PRINTER 0x01
/*
* 以下の定数は、xparameters.hファイルで作成されたXPARパラメータにマッピングされます。
* これらは、ユーザーが必要なすべてのパラメータを1か所で簡単に変更できるようにここに定義されています。
*/
//PS側GPIOデバイスID
#define GPIO_EXAMPLE_DEVICE_ID XPAR_GPIO_0_DEVICE_ID
/*
* 以下の定数は、LEDが点灯した後に待機するために使用され、
* 人間の目に見えることを確認します。 この定数は、
* より速いまたは遅いプロセッサ速度に合わせて調整する必要があります。
*/
#define LED_DELAY 10000000
/*
* 以下の定数は、2つのチャネルがサポートされている場合に
* LEDに使用されるGPIOのチャネルを決定するために使用されます。
*/
#define MODE_CHANGE_CHANNEL 1
/*GPIO定義 */
//PS側GPIOデバイスID
#define MIO_ID XPAR_PS7_GPIO_0_DEVICE_ID
//汎用中断コントローラID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
//PS側GPIO中断ID
#define KEY_INTR_ID XPAR_XGPIOPS_0_INTR
#define PS_KEY_MIO 50 //キーはMIO50に接続されています
#define PS_LED_MIO_1 0
#define PS_LED_MIO_2 13
#define GPIO_INPUT 1
#define GPIO_OUTPUT 0
/**************************** Type Definitions *******************************/
/***************** Macros (Inline Functions) Definitions *********************/
/************************** Function Prototypes ******************************/
int IntrInitFunction(XScuGic *InstancePtr, u16 DeviceId, XGpioPs *GpioInstancePtr);
void GpioHandler(void *CallBackRef);
/************************** Variable Definitions *****************************/
/*
* 以下はグローバルに宣言されているため、ゼロに初期化され、
* デバッガから簡単にアクセスできます。
*/
XGpio Gpio; /* PL側AXI GPIOデバイスドライバインスタンス */
XGpioPs GpioPs; /* PS側GPIOデバイスドライバインスタンス */
XScuGic INTCInst; /* 汎用中断コントローラドライバインスタンス */
int key_flag; // psキー0フラグ
/*****************************************************************************/
/**
*
* この関数の目的は、GPIOドライバを使用してLEDをオンおよびオフにする方法を示すことです。
*
*
* @return XST_FAILUREは、GPIO初期化が
* 失敗したことを示します。
*
* @note この関数は、テストが実行されている場合は戻りません。
*
******************************************************************************/
int main(void)
{
XGpioPs_Config *GpioConfig; /*PS側GPIO設定情報*/
int Status;
int mode_flag = 0;
key_flag = 0;
/* GPIOpsドライバを初期化する*/
/*デバイスIDに基づいて設定情報を探す*/
GpioConfig = XGpioPs_LookupConfig(MIO_ID);
/*GPIOドライバを初期化する*/
Status = XGpioPs_CfgInitialize(&GpioPs, GpioConfig, GpioConfig->BaseAddr);
if (Status != XST_SUCCESS)
{
xil_printf("GpioPs初期化失敗\r\n");
return XST_FAILURE;
}
else
{
xil_printf("GpioPs初期化成功\r\n");
}
/* GPIOドライバを初期化する */
/*PL側AXI GPIOドライバを初期化する*/
Status = XGpio_Initialize(&Gpio, GPIO_EXAMPLE_DEVICE_ID);
if (Status != XST_SUCCESS)
{
xil_printf("Gpio初期化失敗\r\n");
return XST_FAILURE;
}
else
{
xil_printf("Gpio初期化成功\r\n");
}
/*GPIO_PS Intr初期化*/
/*KEY接続のMIOピンの方向を入力に設定する*/
XGpioPs_SetDirectionPin(&GpioPs, PS_KEY_MIO, GPIO_INPUT);
/*ボタン中断を有効にする*/
XGpioPs_SetIntrTypePin(&GpioPs, PS_KEY_MIO, XGPIOPS_IRQ_TYPE_EDGE_RISING);
XGpioPs_IntrEnablePin(&GpioPs, PS_KEY_MIO);
Status = IntrInitFunction(&INTCInst, MIO_ID, &GpioPs);
if (Status != XST_SUCCESS)
{
xil_printf("IntrInitFunction失敗\r\n");
return XST_FAILURE;
}
else
{
xil_printf("IntrInitFunction成功\r\n");
}
/* GPIO OUTの方向を設定する */
XGpio_SetDataDirection(&Gpio, MODE_CHANGE_CHANNEL, GPIO_OUTPUT);
/*PS GPIO 1の出力用の方向を設定し、0の入力用*/
XGpioPs_SetDirectionPin(&GpioPs, PS_LED_MIO_1, 1);
XGpioPs_SetDirectionPin(&GpioPs, PS_LED_MIO_2, 1);
XGpioPs_SetOutputEnablePin(&GpioPs, PS_LED_MIO_1, 1);
XGpioPs_SetOutputEnablePin(&GpioPs, PS_LED_MIO_2, 1);
/* LEDを点滅させるために無限ループ */
while (1)
{
if (key_flag)
{
if (mode_flag == 0)
{
XGpio_DiscreteWrite(&Gpio, MODE_CHANGE_CHANNEL, MODE_SINGLE_TONE);
xil_printf("MODE_SINGLE_TONE, mode flag:%d\r\n", mode_flag);
XGpioPs_WritePin(&GpioPs, PS_LED_MIO_1, 0); // LED1 ON
XGpioPs_WritePin(&GpioPs, PS_LED_MIO_2, 1); // LED2 OFF
mode_flag++;
}
else if (mode_flag == 1)
{
XGpio_DiscreteWrite(&Gpio, MODE_CHANGE_CHANNEL, MODE_PRINTER);
xil_printf("Painter, mode flag:%d\r\n", mode_flag);
XGpioPs_WritePin(&GpioPs, PS_LED_MIO_1, 1); // LED1 OFF
XGpioPs_WritePin(&GpioPs, PS_LED_MIO_2, 0); // LED2 ON
mode_flag = 0;
}
key_flag = 0;
}
}
return 0;
}
int IntrInitFunction(XScuGic *InstancePtr, u16 DeviceId, XGpioPs *GpioInstancePtr)
{
XScuGic_Config *IntcConfig; /*中断コントローラ設定情報*/
int Status;
/*
* 中断コントローラドライバを初期化し、使用できるようにします。
*/
/*中断コントローラの設定情報を探し、中断コントローラドライバを初期化する*/
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
Status = XScuGic_CfgInitialize(InstancePtr, IntcConfig, IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS)
return XST_FAILURE;
/*
* 優先度とトリガタイプを設定します。
* 中断タイプを上昇エッジ中断に設定します。
*/
XScuGic_SetPriorityTriggerType(InstancePtr, KEY_INTR_ID,
0xA0, 0x3);
/*
* デバイスの中断が発生したときに呼び出されるデバイスドライバハンドラを接続します。
* 上記のハンドラは、デバイスの特定の中断処理を実行します。
*/
/*中断処理関数を中断に設定する*/
Status = XScuGic_Connect(InstancePtr, KEY_INTR_ID,
(Xil_ExceptionHandler)GpioHandler,
(void *)GpioInstancePtr);
if (Status != XST_SUCCESS)
return XST_FAILURE;
/*
* デバイスの中断を有効にします。
* GPIOからの中断を有効にします。
*/
XScuGic_Enable(InstancePtr, KEY_INTR_ID);
/*中断例外を設定し、有効にする*/
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
InstancePtr);
Xil_ExceptionEnable();
return XST_SUCCESS;
}
void GpioHandler(void *CallBackRef)
{
XGpioPs *GpioInstancePtr = (XGpioPs *)CallBackRef;
int intr_val;
intr_val = XGpioPs_IntrGetStatusPin(GpioInstancePtr, PS_KEY_MIO);
/* 中断をクリアする */
XGpioPs_IntrClearPin(GpioInstancePtr, PS_KEY_MIO);
if (intr_val)
{
xil_printf("ボタンが押されました\r\n");
key_flag = 1;
}
}