embeddedsw icon indicating copy to clipboard operation
embeddedsw copied to clipboard

FreeRTOS Hello World no interrupts to trigger ticks

Open tlf30 opened this issue 1 year ago • 18 comments

When testing with a microblaze core that has a AXI timer, freertos fails to get tick interrupts with the hello world example and the example simply hangs on the first vTaskDelay.

image

image image

Is there additional configuration required?

image image

tlf30 avatar Jun 29 '24 21:06 tlf30

Hi @tlf30, How are you generating the freertos_hello_world application? if we use template flow(Generating new domain along with application) all the required configuration will be set by the flow, looks like you have created the hello_world application for the already existing platform in this case need to enable XILTIMER_en_interval_timer to true , Modify the configuration and regenerate the application and let us know the test results.

kedareswararao avatar Jul 01 '24 03:07 kedareswararao

Hello @kedareswararao, I am using a platform that I generated. It is a simple platform with two axi timers, axi uart lite, and a microblaze core connected to some ram.

I have tested with XILTIMER_en_interval_timer set to both true and false on my original project, thought that perhaps it was because I had fast interrupts enabled on the interrupt controller. I recreated the hardware from scratch with fast interrupts disabled. This has made no difference, and I have re-tested with XILTIMER_en_interval_timer set to true/false.

I am attaching my xsa here for reference. This is my first time using a Xilinx FPGA along with the tooling, so I am sure I have something wrong somewhere. If there is some specific files that I can provide for troubleshooting, please let me know.

design_1_wrapper.zip

EDIT: Current design for reference: image

tlf30 avatar Jul 01 '24 04:07 tlf30

@kedareswararao if it makes any difference, when I create the platform using the xsa file, I select FreeRTOS for the operating system. I would assume that it should setup all the needed parameters in the platform. The XILTIMER_en_interval_timer are set to false by default. But as mentioned I've tested with it set to true as well.

Any help is greatly appreciated. Thanks, Trevor

tlf30 avatar Jul 02 '24 19:07 tlf30

Still working on this. As a note, I was able to test the hardware interrupts by creating a platform as a standalone OS, and using the following test code to ensure that the IRQ was getting processed by the microblaze core.

#include <xil_types.h>
#include <xuartlite_l.h>
#include <xintc.h>
#include <xparameters.h>

/* uartlite interrupt service routine */
void uart_int_handler(void *baseaddr_p) {
	char c;
    //xil_printf("Got IRQ \r\n");
	/* till uart FIFOs are empty */
	while (!XUartLite_IsReceiveEmpty(XPAR_AXI_UARTLITE_0_BASEADDR)) {
		/* read a character */
		c = XUartLite_RecvByte(XPAR_AXI_UARTLITE_0_BASEADDR);
		/* print character on hyperterminal (STDOUT) */
		xil_printf ("Character: %c \r\n", c);
	}
}

static XIntc IntcInstance; /* The instance of the Interrupt Controller */

int main(void)
{

    xil_printf ("Loading\r\n");

	// /* Enable Uartlite interrupt */
	XUartLite_EnableIntr(XPAR_AXI_UARTLITE_0_BASEADDR);


    int status;
    status = XIntc_Initialize(&IntcInstance, XPAR_XINTC_0_BASEADDR);
    xil_printf("XIntc_Initialize: %d \r\n", status);

    status = XIntc_Connect(&IntcInstance, XPAR_FABRIC_XUARTLITE_0_INTR, (XInterruptHandler) uart_int_handler, (void*)  XPAR_AXI_UARTLITE_0_BASEADDR);
    xil_printf("XIntc_Connect: %d \r\n", status);

    status = XIntc_Start(&IntcInstance, XIN_REAL_MODE);
    xil_printf("XIntc_Start: %d \r\n", status);

    XIntc_Enable(&IntcInstance, XPAR_FABRIC_XUARTLITE_0_INTR);

    /*
	 * Initialize the exception table.
	 */
	Xil_ExceptionInit();

	/*
	 * Register the interrupt controller handler with the exception table.
	 */
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler) XIntc_InterruptHandler, &IntcInstance);

	/*
	 * Enable exceptions.
	 */
	Xil_ExceptionEnable();

    xil_printf("Ready for input\r\n");
	/* Wait for interrupts to occur */
	while (1);
}

At this point, I think that either something is not set correctly by the platform wizard when creating a freertos platform, or the hello world example is missing something. I spent a couple hours this morning diving around the code and it seemed like the IRQs were simply not getting to the freertos IRQ handler, but I was getting deeper into the code than I really wanted to for a "first cup of coffee" debugging session.

tlf30 avatar Jul 04 '24 21:07 tlf30

I don't have the SDK installed here, and it has been a while... but if I remember right, as well as enabling the interrupt on the peripheral, and enabing the interrupt controller, and connecting and registering the interrupt handler and starting the interrupt controller (!) you also need to enable the interrupts in the microblaze itself. I think there is a enable_interrupts() function (maybe in microblaze.h?)

martinjthompson avatar Jul 05 '24 14:07 martinjthompson

Yes, that is called via Xil_ExceptionEnable. I attempted to manually enable interrupts in the freertos example using my test above as a working reference. I have not been successful in doing so. I've not found any examples where the interrupts needed to be manually enabled for FreeRTOS, everything I've read indicates that the example should just work as long as the AXI timer exists and interrupts are setup in hardware.

tlf30 avatar Jul 06 '24 15:07 tlf30

Hello @kedareswararao, I am using a platform that I generated. It is a simple platform with two axi timers, axi uart lite, and a microblaze core connected to some ram.

I have tested with XILTIMER_en_interval_timer set to both true and false on my original project, thought that perhaps it was because I had fast interrupts enabled on the interrupt controller. I recreated the hardware from scratch with fast interrupts disabled. This has made no difference, and I have re-tested with XILTIMER_en_interval_timer set to true/false.

I am attaching my xsa here for reference. This is my first time using a Xilinx FPGA along with the tooling, so I am sure I have something wrong somewhere. If there is some specific files that I can provide for troubleshooting, please let me know.

design_1_wrapper.zip

EDIT: Current design for reference: image

Hi @tlf30 , Generated the freertos_hello_world for the xsa provided, Cross verified the defines in xparameters.h file and configuration in the xiltimer everything seems proper, Looks like it's a design issue, to cross check whether it's a design issue or not please test the same use case with the vitis classic tool which can be launched using vitis --classic option if the freertos_hello_world elf generated using this tool also not working means it's a design issue please raise a Support request so that corresponding team can help you on debugging the design.

Regards, Kedar.

kedareswararao avatar Jul 08 '24 06:07 kedareswararao

Hello Kedar, I'm having issues getting Vitis classic to load, it just locks up on the deprecation notice. image

I'll keep trying to find a way to fix it. I'm doing a clean install on another computer right now.

Using a standalone platform. I was able to build a test case to verify the timers are working properly. I had no issues getting the timer interrupts to function.

#include <xil_types.h>
#include <xuartlite_l.h>
#include <xintc.h>
#include <xparameters.h>
#include "xiltimer.h"
#include "xtmrctr.h"
#include "xintc.h"
#include "xil_exception.h"


/* uartlite interrupt service routine */
void uart_int_handler(void *baseaddr_p) {
	char c;
    //xil_printf("Got IRQ \r\n");
	/* till uart FIFOs are empty */
	while (!XUartLite_IsReceiveEmpty(XPAR_AXI_UARTLITE_0_BASEADDR)) {
		/* read a character */
		c = XUartLite_RecvByte(XPAR_AXI_UARTLITE_0_BASEADDR);
		/* print character on hyperterminal (STDOUT) */
		xil_printf ("Character: %c \r\n", c);
	}
}

void TimerCounterHandler(void *CallBackRef, u8 TmrCtrNumber)
{
	XTmrCtr *InstancePtr = (XTmrCtr *)CallBackRef;

	xil_printf ("Timer expired\r\n");
}

static XIntc IntcInstance; /* The instance of the Interrupt Controller */
static XTmrCtr TimerCounterInst;   /* The instance of the Timer Counter */

int main(void)
{

    xil_printf ("Loading\r\n");

	// /* Enable Uartlite interrupt */
	XUartLite_EnableIntr(XPAR_AXI_UARTLITE_0_BASEADDR);

    int status;
    status = XTmrCtr_Initialize(&TimerCounterInst, XPAR_AXI_TIMER_0_BASEADDR);
    xil_printf("XTmrCtr_Initialize: %d \r\n", status);
    
    status = XIntc_Initialize(&IntcInstance, XPAR_XINTC_0_BASEADDR);
    xil_printf("XIntc_Initialize: %d \r\n", status);

    status = XIntc_Connect(&IntcInstance, XPAR_FABRIC_XUARTLITE_0_INTR, (XInterruptHandler) uart_int_handler, (void*)  XPAR_AXI_UARTLITE_0_BASEADDR);
    xil_printf("XIntc_Connect UART: %d \r\n", status);

    status = XIntc_Connect(&IntcInstance, XPAR_FABRIC_AXI_TIMER_0_INTR,	(XInterruptHandler) XTmrCtr_InterruptHandler, (void *) &TimerCounterInst);
    xil_printf("XIntc_Connect Timer0: %d \r\n", status);

    status = XIntc_Start(&IntcInstance, XIN_REAL_MODE);
    xil_printf("XIntc_Start: %d \r\n", status);

    status = XTmrCtr_SelfTest(&TimerCounterInst, 0);
    xil_printf("XTmrCtr_SelfTest: %d \r\n", status);

    XIntc_Enable(&IntcInstance, XPAR_FABRIC_XUARTLITE_0_INTR);
    XIntc_Enable(&IntcInstance, XPAR_FABRIC_AXI_TIMER_0_INTR);

    /*
	 * Initialize the exception table.
	 */
	Xil_ExceptionInit();

	/*
	 * Register the interrupt controller handler with the exception table.
	 */
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler) XIntc_InterruptHandler, &IntcInstance);

	/*
	 * Enable exceptions.
	 */
	Xil_ExceptionEnable();

    //Setup timer
    XTmrCtr_SetHandler(&TimerCounterInst, TimerCounterHandler,  &TimerCounterInst);
    XTmrCtr_SetOptions(&TimerCounterInst, 0,  
    XTC_INT_MODE_OPTION 
    | XTC_AUTO_RELOAD_OPTION
    );
    XTmrCtr_SetResetValue(&TimerCounterInst, 0, 0xF0000000);
    XTmrCtr_Start(&TimerCounterInst, 0);

    xil_printf("Ready for input\r\n");
	/* Wait for interrupts to occur */
    int count = 0;
	while (1) {
        int time;
        time = XTmrCtr_GetValue(&TimerCounterInst, 0);
        if (count > 10000) {
            xil_printf("Time: %x\r\n", time);
            count = 0;
        } else {
            count++;
        }
    }
}

tlf30 avatar Jul 09 '24 19:07 tlf30

you can look this website https://github.com/Xilinx/embeddedsw/blob/master/ThirdParty/bsp/freertos10_xilinx/examples/freertos_intr_example.c It looks there is a bug https://adaptivesupport.amd.com/s/question/0D52E00006hpqKNSAY/%E5%88%86%E4%BA%AB%E5%9C%A8freertos%E7%9A%84main%E5%87%BD%E6%95%B0%E9%87%8C%E5%88%9D%E5%A7%8B%E5%8C%96%E8%AE%BE%E5%A4%87%E4%B8%8D%E8%83%BD%E6%94%B6%E5%88%B0%E4%B8%AD%E6%96%AD?language=zh_CN

Grenaf avatar Jan 25 '25 09:01 Grenaf

Has this issue been resolved in 2024.2? I am having the a similar (same?) problem.

I have an XSA design that works with a standalone application (including working interrupts) but the freertos hello world example does not work on a new platform and domain created with the same XSA. Just like @tlf30 reported, the example hangs on the first call to vTaskDelay.

I looked into the code posted by @Grenaf. It appears this patch is applied in the Vitis 2024.2 code base.

seth-ngc avatar Aug 13 '25 11:08 seth-ngc

FYI - After fighting with the decaying Vitis 2024.2 Classic, the design works. I was able to run the Freertos Hello World example on my original XSA without any modification to the FPGA design or software source code.

This is clearly a Vitis Unified issue.

For posterities sake, I had to use xsct at the terminal, because the Vitis 2024.2 Classic IDE was unable to find xsct in the path to perform the builds. (How was the IDE able to launch yet xsct was not in the path? We may never know...)

seth-ngc avatar Aug 13 '25 12:08 seth-ngc

Thanks for confirming. We will take it over from here and see what have we missed in unified Vitis. We will update on this shortly.

anirudha1977 avatar Aug 13 '25 15:08 anirudha1977

Hi,

We’ve noticed that we are receiving GitHub notifications for your project, but we are not directly involved with it. Could you help us understand why these notifications are being sent to our team, and remove us from the notification list moving forward?

Please let me know if you need any details from our side to resolve this.

David Munday

On Wed, Aug 13, 2025 at 8:15 AM anirudha1977 @.***> wrote:

anirudha1977 left a comment (Xilinx/embeddedsw#301) https://github.com/Xilinx/embeddedsw/issues/301#issuecomment-3184343600

Thanks for confirming. We will take it over from here and see what have we missed in unified Vitis. We will update on this shortly.

— Reply to this email directly, view it on GitHub https://github.com/Xilinx/embeddedsw/issues/301#issuecomment-3184343600, or unsubscribe https://github.com/notifications/unsubscribe-auth/AA727DSYQRZU24NH3OWQ67L3NNJBLAVCNFSM6AAAAABV3FVJO2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTCOBUGM2DGNRQGA . You are receiving this because you are subscribed to this thread.Message ID: @.***>

andrei-simion avatar Aug 13 '25 17:08 andrei-simion

@anirudha1977

Any updates?

seth-ngc avatar Aug 20 '25 19:08 seth-ngc

Image

Hello tlf30, this is Wenxuan Fan here. I meet similar questions just like you. I think the key point of this kind questions is XPAR_XILTIMER_ENABLED macro. I have answered similar questions before,you can refer to the following websites,https://adaptivesupport.amd.com/s/question/0D7KZ000000pB5L0AU/detail。

I notice that you are using AXI peripherals in Vivado. The use of xiltimer library may enable the XPAR_XILTIMER_ENABLED macro definition in the Vitis BSP (Board Support Package) code, which affects the code body of the FreeRTOS_SetupTickInterrupt function. FreeRTOS_SetupTickInterrupt will call the static XScuTimer xTimer and XScuGic xInterruptController instances. The FreeRTOS scheduler relies on the execution of xStatus = XScuGic_Connect( &xInterruptController, XPAR_SCUTIMER_INTR, (Xil_ExceptionHandler) FreeRTOS_Tick_Handler, ( void * ) &xTimer );. Therefore, you should check whether the static XScuTimer xTimer; and XScuGic xInterruptController; instances are being called by other programs. You can find this code in portZynq7000.c.

you can see this code,this is my solution,there are two things you should check,Does the FreeRTOS scheduler use a timing interrupt to start task invocation, and peripheral initialization should be placed after calling vTaskStartScheduler。This is my code:

/*
    Copyright (C) 2017 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
    Copyright (c) 2012 - 2022 Xilinx, Inc. All Rights Reserved.
	SPDX-License-Identifier: MIT
 
 
    http://www.FreeRTOS.org
    http://aws.amazon.com/freertos
 
 
    1 tab == 4 spaces!
*/
 
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "timers.h"
/* Xilinx includes. */
#include "xil_printf.h"
#include "xparameters.h"
/* User includes. */
#include "common.h"
 
/* The Tx and Rx tasks as described at the top of this file. */
static void Task0Funtion( void *pvParameters );
static void Task1Funtion( void *pvParameters );
static void Task2Funtion( void *pvParameters );
/*-----------------------------------------------------------*/
 
static TaskHandle_t Task0Handle;
static TaskHandle_t Task1Handle;
static TaskHandle_t Task2Handle;
 
int main( void )
{
	xil_printf( "Hello from Freertos example main\r\n" );
	xTaskCreate( 	Task0Funtion, 					/* The function that implements the task. */
					( const char * ) "task0", 		/* Text name for the task, provided to assist debugging only. */
					configMINIMAL_STACK_SIZE, 	/* The stack allocated to the task. */
					NULL, 						/* The task parameter is not used, so set to NULL. */
					tskIDLE_PRIORITY+1,			/* The task runs at the idle priority. */
					&Task0Handle );
 
	xTaskCreate( 	Task1Funtion, 					/* The function that implements the task. */
					( const char * ) "task1", 		/* Text name for the task, provided to assist debugging only. */
					configMINIMAL_STACK_SIZE, 	/* The stack allocated to the task. */
					NULL, 						/* The task parameter is not used, so set to NULL. */
					tskIDLE_PRIORITY+1,			/* The task runs at the idle priority. */
					&Task1Handle );
 
	xTaskCreate( Task2Funtion,
				 ( const char * ) "task2",
				 configMINIMAL_STACK_SIZE,
				 NULL,
				 tskIDLE_PRIORITY + 1,
				 &Task2Handle );
	/* Start the tasks and timer running. */
	vTaskStartScheduler();
	for( ;; );
}
 
 
/*-----------------------------------------------------------*/
static void Task0Funtion( void *pvParameters )
{
	for( ;; )
	{
		/*********************************************************************SCU Init*********************************************************************/
		ScuGic_Init();
		
		/*********************************************************************IIC Init*********************************************************************/
		PS_IIC_Init(&IIC0,XPAR_XIICPS_0_DEVICE_ID,100000);
		PS_IIC_Init(&IIC1,XPAR_XIICPS_1_DEVICE_ID,100000);
		
		/*********************************************************************SPI Init*********************************************************************/
		PS_SPI_Init(&SPI0, XPAR_XSPIPS_0_DEVICE_ID, XSPIPS_CLK_PRESCALE_64, XSPIPS_MASTER_OPTION | XSPIPS_CLK_PHASE_1_OPTION);
		PS_SPI_Init(&SPI1, XPAR_XSPIPS_1_DEVICE_ID, XSPIPS_CLK_PRESCALE_64, XSPIPS_MASTER_OPTION | XSPIPS_CLK_PHASE_1_OPTION);		
		/*********************************************************************UART Init*********************************************************************/
		PS_UART_Init(&UartPs0,XPAR_PS7_UART_0_DEVICE_ID, XUARTPS_OPER_MODE_NORMAL, 115200);
		PS_UART_Intr_Init(&UartPs0, PS_UART0_IRQ_ID, 8, (void *)PS_UART0_IRQ_Handler);
		
		/*********************************************************************GPIO Init*********************************************************************/
		PS_GPIO_Init();
		
		/*********************************************************************LED Init*********************************************************************/
		PSLED_Init();
		
		/*********************************************************************KEY Init*********************************************************************/
		PSKEY_Init();
 
		vTaskDelete( Task0Handle );
	}
}
 
/*-----------------------------------------------------------*/
static void Task1Funtion( void *pvParameters )
{
	for( ;; )
	{
		PSLED_TOGGLE(PSLED1_PIN_NUMBER);
		xil_printf( "TASK1\r\n" );
		vTaskDelay( pdMS_TO_TICKS( 1000 ) );
	}
}
 
/*-----------------------------------------------------------*/
static void Task2Funtion( void *pvParameters )
{
	for( ;; )
	{
		PSLED_TOGGLE(PSLED2_PIN_NUMBER);
		xil_printf( "TASK2\r\n" );
		vTaskDelay( pdMS_TO_TICKS( 1000 ) );
	}
}

portZynq7000.c FreeRTOS_SetupTickInterrupt function like this.

/* Timer used to generate the tick interrupt. */
#ifndef XPAR_XILTIMER_ENABLED
static XScuTimer xTimer;
#endif
XScuGic xInterruptController; 	/* Interrupt controller instance */
 
/*-----------------------------------------------------------*/
 
#ifndef XPAR_XILTIMER_ENABLED
void FreeRTOS_SetupTickInterrupt( void )
{
BaseType_t xStatus;
extern void FreeRTOS_Tick_Handler( void );
XScuTimer_Config *pxTimerConfig;
XScuGic_Config *pxGICConfig;
const uint8_t ucRisingEdge = 3;
 
	/* This function is called with the IRQ interrupt disabled, and the IRQ
	interrupt should be left disabled.  It is enabled automatically when the
	scheduler is started. */
 
	/* Ensure XScuGic_CfgInitialize() has been called.  In this demo it has
	already been called from prvSetupHardware() in main(). */
	pxGICConfig = XScuGic_LookupConfig( XPAR_SCUGIC_SINGLE_DEVICE_ID );
	xStatus = XScuGic_CfgInitialize( &xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress );
	configASSERT( xStatus == XST_SUCCESS );
	( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */
 
	/* The priority must be the lowest possible. */
	XScuGic_SetPriorityTriggerType( &xInterruptController, XPAR_SCUTIMER_INTR, portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT, ucRisingEdge );
 
	/* Install the FreeRTOS tick handler. */
	xStatus = XScuGic_Connect( &xInterruptController, XPAR_SCUTIMER_INTR, (Xil_ExceptionHandler) FreeRTOS_Tick_Handler, ( void * ) &xTimer );
	configASSERT( xStatus == XST_SUCCESS );
	( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */
 
	/* Initialise the timer. */
	pxTimerConfig = XScuTimer_LookupConfig( XPAR_SCUTIMER_DEVICE_ID );
	xStatus = XScuTimer_CfgInitialize( &xTimer, pxTimerConfig, pxTimerConfig->BaseAddr );
	configASSERT( xStatus == XST_SUCCESS );
	( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */
 
	/* Enable Auto reload mode. */
	XScuTimer_EnableAutoReload( &xTimer );
 
	/* Ensure there is no prescale. */
	XScuTimer_SetPrescaler( &xTimer, 0 );
 
	/* Load the timer counter register.
	 * The Xilinx implementation of generating run time task stats uses the same timer used for generating
	 * FreeRTOS ticks. In case user decides to generate run time stats the timer time out interval is changed
	 * as "configured tick rate * 10". The multiplying factor of 10 is hard coded for Xilinx FreeRTOS ports.
	 */
#if (configGENERATE_RUN_TIME_STATS == 1)
	XScuTimer_LoadTimer( &xTimer, XSCUTIMER_CLOCK_HZ / (configTICK_RATE_HZ * 10) );
#else
	XScuTimer_LoadTimer( &xTimer, XSCUTIMER_CLOCK_HZ / configTICK_RATE_HZ );
#endif
 
	/* Start the timer counter and then wait for it to timeout a number of
	times. */
	XScuTimer_Start( &xTimer );
 
	/* Enable the interrupt for the xTimer in the interrupt controller. */
	XScuGic_Enable( &xInterruptController, XPAR_SCUTIMER_INTR );
 
	/* Enable the interrupt in the xTimer itself. */
	FreeRTOS_ClearTickInterrupt();
	XScuTimer_EnableInterrupt( &xTimer );
}
/*-----------------------------------------------------------*/

Finally, I need to point out that I am using the VITIS 2022.2 software platform. Note that when the XSA file generated by Vivado is updated, you must update the BSP folder and its sub - files bound to your XSA in the Vitis embedded platform. Unfortunately, the update of the XSA file will not automatically update the VITIS BSP PLATFORM, so we must update it manually. I hope my answer can inspire you.

Good luck to you!

Grenaf avatar Aug 21 '25 02:08 Grenaf

If you want to have a deeper understanding of this issue, you can refer to my experimental process. However, I wrote it in Chinese, and you can translate it into English on your own. The effect of the routine modified by me based on the Xilinx official FreeRTOS Hello World case is shown in the figure below. You can check this website https://oshwhub.com/article/xilinxfreertos10uartinterrupt-interruption-experiment.

Image

Grenaf avatar Aug 21 '25 02:08 Grenaf

@anirudha1977

Any updates? I think I can make the FreeRTOS scheduler interrupt and the UART interrupt respond simultaneously. The problem is indeed related to the XPAR_XILTIMER_ENABLED macro definition. My development environment is Vitis2022.2, and the enabling of the XPAR_XILTIMER_ENABLED macro definition is related to the checking of the xiltimer library.This is the effect of my experiment https://oshwhub.com/article/xilinxfreertos10uartinterrupt-interruption-experiment. My FreeRTOS APP project was created from the FreeRTOS Hellworld template project and then modified.

Image

xiltimer will enable the XPAR_XILTIMER_ENABLED macro definition. Both BSP projects and APP projects have this option, so you should press ctrl+h to search in your project to see if #define XPAR_XILTIMER_ENABLED is enabled. Assuming you have enabled this macro definition, we can analyze: ifndef XPAR_XILTIMER_ENABLED static XScuTimer xTimer; endif。Therefore, XScuTimer xTimer will not run in FreeRTOS_SetupTickInterrupt, so the task scheduling of FreeRTOS will not be started regularly, and other interrupts and timer scheduling interrupts will not be able to respond simultaneously. You can check this website https://adaptivesupport.amd.com/s/question/0D54U00008S3pQlSAJ/vitis-unified-20241-and-freertos?language=en_US.

/* Timer used to generate the tick interrupt. */
#ifndef XPAR_XILTIMER_ENABLED
static XScuTimer xTimer;
#endif
XScuGic xInterruptController; 	/* Interrupt controller instance */

/*-----------------------------------------------------------*/

#ifndef XPAR_XILTIMER_ENABLED
void FreeRTOS_SetupTickInterrupt( void )
{
BaseType_t xStatus;
extern void FreeRTOS_Tick_Handler( void );
XScuTimer_Config *pxTimerConfig;
XScuGic_Config *pxGICConfig;
const uint8_t ucRisingEdge = 3;

	/* This function is called with the IRQ interrupt disabled, and the IRQ
	interrupt should be left disabled.  It is enabled automatically when the
	scheduler is started. */

	/* Ensure XScuGic_CfgInitialize() has been called.  In this demo it has
	already been called from prvSetupHardware() in main(). */
	pxGICConfig = XScuGic_LookupConfig( XPAR_SCUGIC_SINGLE_DEVICE_ID );
	xStatus = XScuGic_CfgInitialize( &xInterruptController, pxGICConfig, pxGICConfig->CpuBaseAddress );
	configASSERT( xStatus == XST_SUCCESS );
	( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */

	/* The priority must be the lowest possible. */
	XScuGic_SetPriorityTriggerType( &xInterruptController, XPAR_SCUTIMER_INTR, portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT, ucRisingEdge );

	/* Install the FreeRTOS tick handler. */
	xStatus = XScuGic_Connect( &xInterruptController, XPAR_SCUTIMER_INTR, (Xil_ExceptionHandler) FreeRTOS_Tick_Handler, ( void * ) &xTimer );
	configASSERT( xStatus == XST_SUCCESS );
	( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */

	/* Initialise the timer. */
	pxTimerConfig = XScuTimer_LookupConfig( XPAR_SCUTIMER_DEVICE_ID );
	xStatus = XScuTimer_CfgInitialize( &xTimer, pxTimerConfig, pxTimerConfig->BaseAddr );
	configASSERT( xStatus == XST_SUCCESS );
	( void ) xStatus; /* Remove compiler warning if configASSERT() is not defined. */

	/* Enable Auto reload mode. */
	XScuTimer_EnableAutoReload( &xTimer );

	/* Ensure there is no prescale. */
	XScuTimer_SetPrescaler( &xTimer, 0 );

	/* Load the timer counter register.
	 * The Xilinx implementation of generating run time task stats uses the same timer used for generating
	 * FreeRTOS ticks. In case user decides to generate run time stats the timer time out interval is changed
	 * as "configured tick rate * 10". The multiplying factor of 10 is hard coded for Xilinx FreeRTOS ports.
	 */
#if (configGENERATE_RUN_TIME_STATS == 1)
	XScuTimer_LoadTimer( &xTimer, XSCUTIMER_CLOCK_HZ / (configTICK_RATE_HZ * 10) );
#else
	XScuTimer_LoadTimer( &xTimer, XSCUTIMER_CLOCK_HZ / configTICK_RATE_HZ );
#endif

	/* Start the timer counter and then wait for it to timeout a number of
	times. */
	XScuTimer_Start( &xTimer );

	/* Enable the interrupt for the xTimer in the interrupt controller. */
	XScuGic_Enable( &xInterruptController, XPAR_SCUTIMER_INTR );

	/* Enable the interrupt in the xTimer itself. */
	FreeRTOS_ClearTickInterrupt();
	XScuTimer_EnableInterrupt( &xTimer );
}

Grenaf avatar Sep 18 '25 02:09 Grenaf

Hi,您好:    我收到了您邮件,等我看完邮件以后,第一时间给您回复。