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でのインタラプト・ハンドラの例はこちらです。