FreeRTOS PL to PS Interrupt (ZYNQ Zedboard)

I’m working with FreeRTOS on a ZYNQ (Zedboard).
I have the problem that my InterruptHandler does not get called after the “enable ap_done interrupt” of my ipcore gets high…

Does anyone have an idea whats wrong?

here my setup:

Code:



/* GIC Interrupt Controller */
XScuGic_Config *pxGICConfig;
BaseType_t xStatus;
XScuGic xInterruptController; 	/* Interrupt controller instance */
const uint8_t ucRisingEdge = 3;
void FreeRTOS_Counter_Handler( void *pvNotUsed );
static XCounter xCounter;

int main( void )
{
		prvSetupHardware();
		xil_printf( "Hello from Freertos+TCP++ example main\r\n" );
		xTaskCreate( 	prvIPCoreTask,
						"IPCORE",
						configMINIMAL_STACK_SIZE,
		                NULL,
		                tskIDLE_PRIORITY + 2,
						&xIPCoreTask );


	       /* Start the RTOS scheduler. */
	       vTaskStartScheduler();
}

static void prvIPCoreTask( void *pvParameters )
{

    XCounter_Config *counter_config = XCounter_LookupConfig(XPAR_COUNTER_0_DEVICE_ID);;
	xStatus = XCounter_CfgInitialize(&xCounter, counter_config);
	configASSERT( xStatus == XST_SUCCESS );
	( void ) xStatus;

	xPortInstallInterruptHandler(XPAR_FABRIC_COUNTER_0_INTERRUPT_INTR, FreeRTOS_Counter_Handler,( void * ) &xCounter);
	XScuGic_SetPriorityTriggerType( &xInterruptController, XPAR_FABRIC_COUNTER_0_INTERRUPT_INTR, configMAX_API_CALL_INTERRUPT_PRIORITY << portPRIORITY_SHIFT, ucRisingEdge );
	vPortEnableInterrupt(XPAR_FABRIC_COUNTER_0_INTERRUPT_INTR);


	XCounter_InterruptEnable(&xCounter, 0x1);
	XCounter_InterruptGlobalEnable(&xCounter);

	XCounter_Set_delay_time(&xCounter,1000);

	xil_printf( "Before: %d\n", XCounter_InterruptGetStatus(&xCounter));
	XCounter_Start(&xCounter);

	for( ;; )
	{
		xil_printf( "after: %d\n", XCounter_InterruptGetStatus(&xCounter));
		vTaskDelay( pdMS_TO_TICKS( DELAY_1_SECOND ) );;
	}
}

void FreeRTOS_Counter_Handler( void *pvNotUsed )
{
	xil_printf( "Counter Event\r\n" );
}

static void prvSetupHardware( void )
{
BaseType_t xStatus;
XScuGic_Config *pxGICConfig;

	/* Ensure no interrupts execute while the scheduler is in an inconsistent
	state.  Interrupts are automatically enabled when the scheduler is
	started. */
//	portDISABLE_INTERRUPTS();

	/* Obtain the configuration of the GIC. */
	pxGICConfig = XScuGic_LookupConfig( XPAR_SCUGIC_SINGLE_DEVICE_ID );

	/* Sanity check the FreeRTOSConfig.h settings are correct for the
	hardware. */
	configASSERT( pxGICConfig );
	configASSERT( pxGICConfig->CpuBaseAddress == ( configINTERRUPT_CONTROLLER_BASE_ADDRESS + configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET ) );
	configASSERT( pxGICConfig->DistBaseAddress == configINTERRUPT_CONTROLLER_BASE_ADDRESS );

	/* Install a default handler for each GIC interrupt. */
	xStatus = XScuGic_CfgInitialize( &xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress );
	configASSERT( xStatus == XST_SUCCESS );
	( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */


	/* The Xilinx projects use a BSP that do not allow the start up code to be
	altered easily.  Therefore the vector table used by FreeRTOS is defined in
	FreeRTOS_asm_vectors.S, which is part of this project.  Switch to use the
	FreeRTOS vector table. */
	vPortInstallFreeRTOSVectorTable();

}



I doubt that xil_printf can be called in an ISR. Better don’t do so.
Is your task running properly ? Using the minimal stack size for a task is very often inappropriate. Especially if the task code uses printf family functions which are known to be stack hungry at least. Some even use the heap internally. Another reason why those functions usually can’t be used in ISRs .

I took the printf out of the ISR but still doesn’t get called…
The Task runs properly. I increased the Stack size to 1000.

so I testet the ipcore in a simple standaloneproject and the interrupt ISR is also not called. whats wrong with my code?

void FreeRTOS_Counter_Handler( void *pvNotUsed )
{
	int a = 1;

}

int main()
{
    init_platform();

   	pxGICConfig = XScuGic_LookupConfig( XPAR_SCUGIC_SINGLE_DEVICE_ID );
   	XScuGic_CfgInitialize( &xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress );
    XCounter_Config *counter_config = XCounter_LookupConfig(XPAR_COUNTER_0_DEVICE_ID);;
    XCounter_CfgInitialize(&xCounter, counter_config);

    XCounter_InterruptEnable(&xCounter, 0x1);
    XCounter_InterruptGlobalEnable(&xCounter);
    XScuGic_Connect( &xInterruptController, XPAR_FABRIC_COUNTER_0_INTERRUPT_INTR, (Xil_ExceptionHandler) FreeRTOS_Counter_Handler, ( void * ) &xCounter );
    XScuGic_SetPriorityTriggerType( &xInterruptController, XPAR_FABRIC_COUNTER_0_INTERRUPT_INTR, 4, 0x3 );
    XScuGic_Enable( &xInterruptController, XPAR_FABRIC_COUNTER_0_INTERRUPT_INTR );

    XCounter_Set_delay_time(&xCounter,1000);

    XCounter_Start(&xCounter);

    print("Hello World\n\r");
    print("Successfully ran Hello World application");

    while(1){

    }
    cleanup_platform();
    return 0;
}

Puhh … hard to tell. What if it’s not the code but the counter/IP core not firing or not being connected to the GIC properly resp. as expected ?
But I’m not an FPGA guy nor do I use FreeRTOS on Zynq so I can just guess … sorry !

I suspect the issue is in the Vivado side. There is a dangling input to the concat block. The last time I did this (with Vivado 2019.1) two bad things happened: #1, the dangling input read high all the time, so if it gets enabled you get in a loop unless the input is set for edge sensitive. #2 and probably your issue, the hardware export enumerated the IRQ number wrong. It just skipped the unused input so was one or two off. Try adding a pulldown (using a constant block) to the unused input to the unused input to the xlconcat_0 block.
If for some reason you can’t change the vivado project, figure out the IRQ number manually and used that.