Zynq-7000 FreeRTOS(二)中斷:PL中斷請求


  總結Zynq-7000的PL發送給PS一個中斷請求,為FreeRTOS中斷做准備。

  UG585的P225顯示了系統的中斷框圖,如下圖所示。

圖:ZYNQ器件的中斷框圖

  UG585的P227畫出來中斷控制器的框圖,如下圖所示。PL PS 部分的中斷經過 ICD 控制器分發器后同時進入 CPU1 CPU0

圖:中斷控制器示意圖

  UG585的P57,PL PS 部分一共有 20 個中斷可以使用。 其中 4 個是快速中斷。 如下表所示。

表:PL的中斷信號 

 

  ZYNQ的每一個CPU還有16個軟件中斷,Software Generated Interrupts (SGI) ,UG585的P229顯示了SGI,如下圖所示。

表:ZYNQ的軟件中斷SGI

 

  文檔在P229,描述了CPU私有端口中斷CPU Private Peripheral Interrupts (PPI) 和共享中斷Shared Peripheral Interrupts (SPI) ,這些中斷都是固定死的, 不能修改。 PPI中有 2 PL 到 每個CPU 的快速中斷 nFIQ ,ID號為28和31(nIRQ)。共享中斷就是 PL 的中斷可以發送給 PS 處理。  這里不再貼圖。
  PS的設置如下圖。

  Block Design如下圖。

  黑金AX7010 開發板的 PL 部分板載了 4 個用戶按鍵(KEY1~KEY4), 按鍵的信號連接到 ZYNQ的 BANK34 和 BANK35 的 IO 上。 按鍵都為低電平有效, 沒有按下時,信號為高;按鍵按下時,信號為低。 4 個用戶按鍵的原理圖如下圖所示。

圖:黑金開發板按鍵原理圖

 代碼:

#include <stdio.h>
#include "xscugic.h"
#include "xil_exception.h"

#define INT_CFG0_OFFSET 0x00000C00

// Parameter definitions
#define SW1_INT_ID              61
#define SW2_INT_ID              62

#define INTC_DEVICE_ID          XPAR_PS7_SCUGIC_0_DEVICE_ID
#define INT_TYPE_RISING_EDGE    0x03
#define INT_TYPE_HIGHLEVEL      0x01
#define INT_TYPE_MASK           0x03

static XScuGic INTCInst;

static void SW_intr_Handler(void *param);
static int IntcInitFunction(u16 DeviceId);

static void SW_intr_Handler(void *param)
{
    int sw_id = (int)param;
    printf("SW%d int\n\r", sw_id);
}

void IntcTypeSetup(XScuGic *InstancePtr, int intId, int intType)
{
    int mask;

    intType &= INT_TYPE_MASK;
    mask = XScuGic_DistReadReg(InstancePtr, INT_CFG0_OFFSET + (intId/16)*4);
    mask &= ~(INT_TYPE_MASK << (intId%16)*2);
    mask |= intType << ((intId%16)*2);
    XScuGic_DistWriteReg(InstancePtr, INT_CFG0_OFFSET + (intId/16)*4, mask);
}

int IntcInitFunction(u16 DeviceId)
{
    XScuGic_Config *IntcConfig;
    int status;

    // Interrupt controller initialisation
    IntcConfig = XScuGic_LookupConfig(DeviceId);
    status = XScuGic_CfgInitialize(&INTCInst, IntcConfig, IntcConfig->CpuBaseAddress);
    if(status != XST_SUCCESS) return XST_FAILURE;

    // Call to interrupt setup
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                                 (Xil_ExceptionHandler)XScuGic_InterruptHandler,
                                 &INTCInst);
    Xil_ExceptionEnable();

    // Connect SW1~SW3 interrupt to handler
    status = XScuGic_Connect(&INTCInst,
                             SW1_INT_ID,
                             (Xil_ExceptionHandler)SW_intr_Handler,
                             (void *)1);
    if(status != XST_SUCCESS) return XST_FAILURE;

    status = XScuGic_Connect(&INTCInst,
                             SW2_INT_ID,
                             (Xil_ExceptionHandler)SW_intr_Handler,
                             (void *)2);
    if(status != XST_SUCCESS) return XST_FAILURE;



    // Set interrupt type of SW1~SW3 to rising edge
    IntcTypeSetup(&INTCInst, SW1_INT_ID, INT_TYPE_RISING_EDGE);
    IntcTypeSetup(&INTCInst, SW2_INT_ID, INT_TYPE_RISING_EDGE);


    // Enable SW1~SW3 interrupts in the controller
    XScuGic_Enable(&INTCInst, SW1_INT_ID);
    XScuGic_Enable(&INTCInst, SW2_INT_ID);


    return XST_SUCCESS;
}

int main(void)
{
    print("PL int test\n\r");
    IntcInitFunction(INTC_DEVICE_ID);
    while(1);
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM