DE0-Nano-SoC用ベアメタルアプリのインタラプト

FPGA

Cyclone Vのベアメタルアプリで、FPGAからHPSへのインタラプトを認識するインタラプト・ハンドラの作成例です。

ハードウェアについて

FPGAから出力したインタラプトを、QsysのPIOを介してHPSに接続しています。回路とQuartus II/Qsysの具体的な設定は、こちらです。

インタラプト・ハンドラの参考コード

ベアメタルのインタラプト・ハンドラは、以下のページの”GPIO Example-CV”が参考になります。
https://www.altera.com/support/support-resources/design-examples/soc.html

具体例

今回のインタラプトは、72番に反応するようにインタラプト・ハンドラを記述します。具体的なコードは次のとおりです。

ソースコード

このプログラムでは、FPGA内に実装したLCD表示回路から、Vブランクのタイミングでインタラプト72番が発生します。インタラプトが発生すると、vint_isr_callbackが呼ばれます。

#include <stdio.h>

#include "alt_interrupt.h"
#include "hwlib.h"
#include "socal/socal.h"
#include "socal/hps.h"
#include "hps_0.h"
#include "pl_address_table.h"

volatile uint32_t vint_stat = 0;

// ISR callback for the FPGA
void vint_isr_callback(uint32_t icciar, void * context);

ALT_STATUS_CODE socfpga_int_setup(ALT_INT_INTERRUPT_t int_id, ALT_INT_TRIGGER_t trigger)
{
    ALT_STATUS_CODE status = ALT_E_SUCCESS;

    printf("INFO: Setting up V-sync interrupt.\n");

    // Initialize global interrupts
    status = alt_int_global_init();
    // Initialize CPU interrupts
    status = alt_int_cpu_init();
    // Set interrupt distributor target
    int target = 0x3;
    status = alt_int_dist_target_set(int_id, target);
    // Set interrupt trigger type
    status = alt_int_dist_trigger_set(int_id, trigger);
    // Enable interrupt at the distributor level
    status = alt_int_dist_enable(int_id);
    // Enable CPU interrupts
    status = alt_int_cpu_enable();
    // Enable global interrupts
    status = alt_int_global_enable();

    return status;
}

ALT_STATUS_CODE system_init(void)
{
    ALT_STATUS_CODE status = ALT_E_SUCCESS;

    printf("INFO: System Initialization.\n");
    
    // Setup Interrupt
    socfpga_int_setup(ALT_INT_INTERRUPT_F2S_FPGA_IRQ0, ALT_INT_TRIGGER_LEVEL);
    printf("INFO: Set up ISR.\n");
    // Register slave ISR
    status = alt_int_isr_register(ALT_INT_INTERRUPT_F2S_FPGA_IRQ0, vint_isr_callback, NULL);

   // Enable VINT FPGA interrupt
   printf("INFO: Enable VINT FPGA interrupts.\n");
   // PIO Interrupt Enable
   (*(volatile unsigned int*)(ALT_LWFPGASLVS_OFST + PIO_EXT_BASE + 0x8)) = 0xff;
   // FPGA register configurations
   printf("INFO: Video Starts.\n");
   PP_INT_MASK = 0;
   PP_VIDEO_START = 3;

  return status;
}

void vint_isr_callback(uint32_t icciar, void * context)
{
  // interrupt clear register settings will be needed here.
   vint_stat = 1;
}


int main(void)
{
    system_init();
    printf("INFO: VINT demo starts.\n");
    while (vint_stat != 0) // wait for v sync interrupt
    printf("INFO: VINT demo exits.\n");

    return 0;
}

重要なコードは、system_init関数の次の部分です。ここで、インタラプト番号72に対してコールバック関数vint_isr_callbackを登録しています。

    // Setup Interrupt
    socfpga_int_setup(ALT_INT_INTERRUPT_F2S_FPGA_IRQ0, ALT_INT_TRIGGER_LEVEL);
    printf("INFO: Set up ISR.\n");
    // Register slave ISR
    status = alt_int_isr_register(ALT_INT_INTERRUPT_F2S_FPGA_IRQ0, vint_isr_callback, NULL);

インタラプト番号の対応は、alt_interrupt_common.h(/embedded/ip/altera/hps/altera_hps/hwlib/include/alt_interrupt_common.h)に定義されています。72は ALT_INT_INTERRUPT_F2S_FPGA_IRQ0として定義されているのがわかります。

ALT_INT_INTERRUPT_F2S_FPGA_IRQ0  =  72,
ALT_INT_INTERRUPT_F2S_FPGA_IRQ1  =  73,
:

vint_isr_callbackでは、単純にvint_statフラグを1にする処理を記述しています。main関数内でvint_stat == 1を検出すると、プログラムが終了します。

volatile uint32_t vint_stat = 0;

void vint_isr_callback(uint32_t icciar, void * context)
{
  // interrupt clear register settings will be needed here.
   vint_stat = 1;
}

実行結果

U-Boot SPL 2013.01.01 (Jan 20 2016 - 07:19:29)
BOARD : Altera SOCFPGA Cyclone V Board
CLOCK: EOSC1 clock 25000 KHz
CLOCK: EOSC2 clock 25000 KHz
CLOCK: F2S_SDR_REF clock 0 KHz
CLOCK: F2S_PER_REF clock 0 KHz
CLOCK: MPU clock 925 MHz
CLOCK: DDR clock 400 MHz
CLOCK: UART clock 100000 KHz
CLOCK: MMC clock 50000 KHz
CLOCK: QSPI clock 3613 KHz
RESET: WARM
SDRAM: Initializing MMR registers
SDRAM: Calibrating PHY
SEQ.C: Preparing to start memory calibration
SEQ.C: CALIBRATION PASSED
SDRAM: 1024 MiB
ALTERA DWMMC: 0
reading hello-mkimage.bin
reading hello-mkimage.bin
INFO: System Initialization.
INFO: Setting up V-sync interrupt.
INFO: Set up ISR.
INFO: Enable VINT FPGA interrupts.
INFO: Video Starts.
INFO: VINT demo starts.
INFO: System uninit.
INFO: Cleaning up FPGA interrupt.

まとめ

ベアメタルアプリでは、GPIOのサンプルを参考に、コールバック関数の名前と対応するインタラプト番号を変更すればインタラプトを認識できます。

Linuxでのインタラプト・ハンドラの例はこちらです。

タイトルとURLをコピーしました