cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Visitor
Visitor
196 Views
Registered: ‎05-28-2020

PL Interrupts on Zynq in FreeRTOS from Vitis Example

My goal is to set up a simple AXI configurable interrupter in the PL of a Zynq and use it trigger a handler inside freeRTOS running on the PS. The interrupter IP pulls up the irq signal for one cycle in a configurable frequency. The PL is running at 15MHz.

zynq_setup.PNG

I am using the following code to handle interrupts generated the IP. However, the ISR I defined is never called. All functions used to setup the interrupt system return success codes and the scheduled task runs as it should. I found this post: https://forums.xilinx.com/t5/Embedded-Development-Tools/PL-PS-Interrupt-for-Zynq-running-FreeRTOS/td-p/487570 and largely did what I found there and here: https://forums.xilinx.com/t5/Xcell-Daily-Blog-Archived/Adam-Taylor-s-MicroZed-Chronicles-Part-38-Answering-a-question/ba-p/479978. The main difference is that I don't use a GPIO switch to trigger the PL interrupter.

#define FPGA_INT            XPS_IRQ_INT_ID //31
#define INTC_DEVICE_ID      XPAR_SCUGIC_SINGLE_DEVICE_ID

#define INTR_START_ADDR (uint32_t *)XPAR_INTERRUPTER_0_S00_AXI_BASEADDR
#define FREQUENCY_ADDR  (uint32_t *)(XPAR_INTERRUPTER_0_S00_AXI_BASEADDR + 4)
#define DURATION_ADDR   (uint32_t *)(XPAR_INTERRUPTER_0_S00_AXI_BASEADDR + 8)
#define COUNT_ADDR      (uint32_t *)(XPAR_INTERRUPTER_0_S00_AXI_BASEADDR + 12)
/*-----------------------------------------------------------*/

/* Interrupt functions */
static void FPGAIntrHandler(void *CallBackRef);
int SetupInterruptSystem(XScuGic *GicInstancePtr, u32 *FPGAPtr, u16 FPGAIntrId);
static void prvIntrTask(void *pvParameters);

/*-----------------------------------------------------------*/
/*Interrupt variables*/
static XScuGic Intc; //GIC
static u32 FPGA;
static TaskHandle_t xIntrTask;
long interrupt_cnt = 0;
/*-----------------------------------------------------------*/
int main( void )
{

    int xReturn = SetupInterruptSystem(&Intc,&FPGA,FPGA_INT);
    if(xReturn != XST_SUCCESS){
        xil_printf("Setting up interrupts was not successful\r\n");
    }
    else{
        xil_printf("Setting up interrupts was successful\r\n");
    }
    xTaskCreate( prvIntrTask,
                     ( const char * ) "IntrTask",
                     configMINIMAL_STACK_SIZE,
                     NULL,
                     tskIDLE_PRIORITY + 3,
                     &xIntrTask );
    vTaskStartScheduler();
    for( ;; );
}
/*-----------------------------------------------------------*/
static void prvIntrTask(void *pvParameters){ //configures IP
    const TickType_t xDelay = 10000 / portTICK_PERIOD_MS;
    uint32_t *startptr = INTR_START_ADDR;
    uint32_t *durptr = DURATION_ADDR;
    uint32_t *freqptr = FREQUENCY_ADDR;
    uint32_t *countptr = COUNT_ADDR;
    uint32_t duration = 5; //5 seconds of interrupts

    for( ;; ){
        xil_printf("HW_Count = %u\r\n",*countptr);
        xil_printf("ISR_Count = %u\r\n",interrupt_cnt);
        vTaskDelay(xDelay);
        xil_printf("Writing to PL registers \r\n");
        xil_printf("PL Base Address: %x\r\n",startptr);
        *durptr = duration;
        *freqptr = 3; //3 interrupts per second
        *startptr = 1; //starts IP to throw 3 interrupts per second for 5 seconds
    }
}
/*-----------------------------------------------------------*/
int SetupInterruptSystem(XScuGic *GicInstancePtr, u32 *FPGAPtr, u16 FPGAIntrId)
{

        XScuGic_Config *IntcConfig; //GIC config
        Xil_ExceptionInit();

        //initialise the GIC
        IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
        if (NULL == IntcConfig)
        {
            return XST_FAILURE;
        }

        int xResult = XScuGic_CfgInitialize(GicInstancePtr, IntcConfig,
                        IntcConfig->CpuBaseAddress);
        if(xResult != XST_SUCCESS)
        {
            return XST_FAILURE;
        }

        //connect to the hardware
        Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                    (Xil_ExceptionHandler)XScuGic_InterruptHandler,
                    GicInstancePtr);

        //Trigger Rising Edge
        XScuGic_SetPriorityTriggerType(GicInstancePtr, FPGA_INT, 0, 3);

        //set up the interrupt
        XScuGic_Connect(GicInstancePtr, FPGAIntrId,
                        (Xil_ExceptionHandler)FPGAIntrHandler,
                        (void *)FPGAPtr);

        //enable the interrupt at GIC
        XScuGic_Enable(GicInstancePtr, FPGAIntrId);

        // Enable interrupts in the Processor.
        Xil_ExceptionEnableMask(XIL_EXCEPTION_IRQ);
        xil_printf("Interrupt Set Up\n\r");

        return XST_SUCCESS;
    }
/*-----------------------------------------------------------*/
static void FPGAIntrHandler(void *CallBackRef)
{

    xil_printf("FPGA Interrupt Event\n\r");
    interrupt_cnt ++;

}

Sorry for the amount of code, there are quite a few steps involved and I wanted to include most of the context.

Does anybody see, where I am missing something?

Tags (3)
0 Kudos
0 Replies