Priorities with Queue and Semaphore from ISR

Hello,
I have two tasks prvTxTask and prvRxTask with the same priority tskIDLE_PRIORITY + 2.
Each 0.5 second prvTxTask send a string to prvRxTask using queue, they work well.

I have one more task vTask_Video_DMA_App with a higher priority than the others have. this task is waiting for semaprore to be released by WriteCallBack function.
The interruptions happens each 33 ms aprox. In the call back function I added a counter in such way the the interruption happens slowly, 1 second aprox.

Below te code in short form


int main( void )
{

	if(xTaskCreate( 	prvTxTask, ( const char * ) "Tx", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, &xTxTask ) != pdPASS)
	{
		xil_printf("Tx Task was not created\r\n");
		for(;;);
	}

	if(xTaskCreate( prvRxTask, ( const char * ) "GB", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, &xRxTask ) != pdPASS)
	{
		xil_printf("Rx Task was not created\r\n");
		for(;;);

	}

	if( xTaskCreate( vTask_Video_DMA_App, ( const char * ) "VDMA", 10*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 3, &xHandler_VDMA ) != pdPASS )
	{
		xil_printf("VDMA Task was not created\r\n");
		for(;;);

	}

	xQueue = xQueueCreate( 	4,sizeof( HWstring ) );

	configASSERT( xQueue );

	vTaskStartScheduler();
	for( ;; );
}


static void prvTxTask( void *pvParameters )
{
	xil_printf("Tx Task started\r\n");
	for( ;; )
	{
		/* Delay for 1 second. */
		vTaskDelay( pdMS_TO_TICKS(500) );

		xil_printf("Entering Task Tx\r\n");

		if(xQueueSend( xQueue, HWstring, 0L )){
			xil_printf("xQueueSend\r\n");
		}else{
			xil_printf("Tx waiting\r\n");
		}

		xil_printf("Leaving Task Tx\r\n");
	}
}

static void prvRxTask( void *pvParameters )
{
	char Recdstring[15] = "";

	xil_printf("Rx Task started\r\n");
	for( ;; )
	{	xil_printf("Entering Task Rx\r\n");

		if(xQueueReceive( xQueue,	Recdstring, portMAX_DELAY ))
		{
			xil_printf( "Rx task received string from Tx task\r\n", Recdstring );
		}

		xil_printf("Leaving Task Rx\r\n");
	}
}


void vTask_Video_DMA_App(void *args){
	
	xil_printf("Task VDMA Started\r\n");

	SemVDMAWr = xSemaphoreCreateBinary();

	if(SemVDMAWr==NULL){
		xil_printf("Could not create semaphore SemVDMAWr\n");
		return XST_FAILURE;
	}

	for(;;){

		xil_printf("Entering Task VDMA\r\n");
		if( xSemaphoreTake( SemVDMAWr, portMAX_DELAY) == pdTRUE ){
			xil_printf("VDMA: Semphr took \r\n");
		}
		xil_printf("Leaving Task VDMA\r\n\n\n");
	}
}


static void WriteCallBack(void *CallbackRef, u32 Mask)
{

	static BaseType_t xHigherPriorityTaskWoken2 = pdFALSE;
	static int counterTx = 0;

	xHigherPriorityTaskWoken2 = pdFALSE;
	counterTx++;

	if(counterTx > 30){

		counterTx = 0;
		xSemaphoreGiveFromISR(SemVDMAWr, &xHigherPriorityTaskWoken2);
	}
	portYIELD_FROM_ISR( xHigherPriorityTaskWoken2);
}

As a result , vTask_Video_DMA_App works as it is expected , however , prvTxTask never come out of vtaskDelay() , so nothing is sent to queue , and prvRxTask is always waiting for a message from queue.
It is not supposed that meanwhile prvRxTask and vTask_Video_DMA_App are susppended waiting for their respective triggers, prvTxTask will be ready to run once the time delay passed?

btw, if I set all the tasks with the same priority value , all task start but then they stopped work.

I hope you could tell me what i am missing, or what is the best way make all three task work?
Thanks in advanced

my FreeRTOSConfig.h is :

#ifndef _FREERTOSCONFIG_H
#define _FREERTOSCONFIG_H

#include "xparameters.h" 

#include "bspconfig.h" 

#define configUSE_PREEMPTION 1

#define configUSE_MUTEXES 1

#define INCLUDE_xSemaphoreGetMutexHolder 1

#define configUSE_RECURSIVE_MUTEXES 1

#define configUSE_COUNTING_SEMAPHORES 1

#define configUSE_TIMERS 1

#define configUSE_IDLE_HOOK 0

#define configUSE_TICK_HOOK 0

#define configUSE_DAEMON_TASK_STARTUP_HOOK 0

#define configUSE_MALLOC_FAILED_HOOK 1

#define configUSE_TRACE_FACILITY 1

#define configUSE_NEWLIB_REENTRANT 0

#define configSTREAM_BUFFER 0

#define configMESSAGE_BUFFER 0

#define configSUPPORT_STATIC_ALLOCATION 0

#define configUSE_16_BIT_TICKS 0

#define configUSE_APPLICATION_TASK_TAG 0

#define configUSE_CO_ROUTINES 0

#define configTICK_RATE_HZ (100)

#define configMAX_PRIORITIES (8)// default : 8

#define configMAX_CO_ROUTINE_PRIORITIES 2

#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 200)

#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 65536 ) )

#define configMAX_TASK_NAME_LEN 10

#define configIDLE_SHOULD_YIELD 1

#define configUSE_TIME_SLICING 1

#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES - 1)

#define configTIMER_QUEUE_LENGTH 10

#define configTIMER_TASK_STACK_DEPTH ((configMINIMAL_STACK_SIZE) * 2)

#define configASSERT( x ) if( ( x ) == 0 ) vApplicationAssert( __FILE__, __LINE__ )

#define configUSE_QUEUE_SETS 1

#define configUSE_TASK_NOTIFICATIONS 1

#define configCHECK_FOR_STACK_OVERFLOW 2

#define configUSE_TASK_FPU_SUPPORT 2

#define configQUEUE_REGISTRY_SIZE 10

#define configUSE_STATS_FORMATTING_FUNCTIONS 1

#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0

#define configGENERATE_RUN_TIME_STATS 0

#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()

#define portGET_RUN_TIME_COUNTER_VALUE()

#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1

#define configUSE_TICKLESS_IDLE	0
#define configTASK_RETURN_ADDRESS    prvTaskExitError
#define INCLUDE_vTaskPrioritySet             1
#define INCLUDE_uxTaskPriorityGet            1
#define INCLUDE_vTaskDelete                  1
#define INCLUDE_vTaskCleanUpResources        1
#define INCLUDE_vTaskSuspend                 1
#define INCLUDE_vTaskDelayUntil              1
#define INCLUDE_vTaskDelay                   1
#define INCLUDE_eTaskGetState                1
#define INCLUDE_xTimerPendFunctionCall       1
#define INCLUDE_pcTaskGetTaskName            1
#define INCLUDE_xTaskGetHandle               1
#define portPOINTER_SIZE_TYPE	uint32_t
#define portTICK_TYPE_IS_ATOMIC 1
#define configMESSAGE_BUFFER_LENGTH_TYPE uint32_t
#define configSTACK_DEPTH_TYPE uint32_t
#define configMAX_API_CALL_INTERRUPT_PRIORITY (18)// default: 18

#define configINTERRUPT_CONTROLLER_BASE_ADDRESS         ( XPAR_PS7_SCUGIC_0_DIST_BASEADDR )
#define configINTERRUPT_CONTROLLER_CPU_INTERFACE_OFFSET ( -0xf00 )
#define configUNIQUE_INTERRUPT_PRIORITIES                32
void vApplicationAssert( const char *pcFile, uint32_t ulLine );
void FreeRTOS_SetupTickInterrupt( void );
#define configSETUP_TICK_INTERRUPT() FreeRTOS_SetupTickInterrupt()

void FreeRTOS_ClearTickInterrupt( void );
#define configCLEAR_TICK_INTERRUPT()	FreeRTOS_ClearTickInterrupt()

#define portSET_INTERRUPT_MASK_FROM_ISR()	ulPortSetInterruptMask()
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(x)	vPortClearInterruptMask(x)
#ifdef FREERTOS_ENABLE_TRACE
#include "FreeRTOSSTMTrace.h"
#endif /* FREERTOS_ENABLE_TRACE */

#endif

Seems like a memory corruption somewhere. Can you try to increase the configMINIMAL_STACK_SIZE value just for testing?

#define configMINIMAL_STACK_SIZE ( 1024 )

Hi @aggarg , thank fro replying, i changed configMINIMAL_STACK_SIZE as you suggested, but nothing changed
I attached the output in terminal, please ignore “W_ERR”

Hi @JCesar,
It appears that the VDMA task is continuously executing due to its higher priority, preventing the other two tasks from running. I’m uncertain about when the WriteCallBack() function would be invoked in this scenario.

If possible, could you kindly assist by introducing a delay within the VDMA task? This might allow the other tasks to have an opportunity to execute, potentially resolving the issue.

Thank you.

One other big comment is that if xil_printf does a “busy wait” for sending, as it likely does if it isn’t a FreeRTOS specifically designed routine, that is likely burning a lot of time in the higher priority task keeping the other tasks from running.

The vendor supplied routines are handy for quick work, but you do need to look at what their efficiency implications are when using them in RTOS environments they were not specifically designed for.

The interruption occurs when the Video DMA stores a frame in memory, which happens approximately every 30ms. I added a counter in the WriteCallBack() function for debugging purposes.

If added a delay in the VDMA task, all task start but then are stopped
Screenshot from 2024-07-25 19-58-54

If in prvTxTask I remove the delay and VDMA task without delay everything works.

@richard-damon so i should avoid the use of this function, and use a function that usart?.
Additionally , i seems that there is a problem with vtaskdelay with the interruptions.

You want to use a function that puts the data into a buffer and then sends out to “whatever” with interrupts. It may be easier to use a Uart Driver as there is more likely information on how to use those with interrupts. If xil_printf goes out the JTAG port, it becomes the question of what documentation they have to make that be interrupt based.

A quick check that you can do - replace all the print statements with separate counter increments and then examine the counters in the debugger. For example -

uint32_t rxTaskEnterCounter = 0;
uint32_t rxTaskReceivedStringCounter = 0;
uint32_t rxTaskExitCounter = 0;

static void prvRxTask( void *pvParameters )
{
	char Recdstring[15] = "";

	for( ;; )
	{
		rxTaskEnterCounter++;

		if(xQueueReceive( xQueue,	Recdstring, portMAX_DELAY ))
		{
			rxTaskReceivedStringCounter++;
		}

		rxTaskExitCounter++;
	}
}

Furthermore, could you help define configASSERT in your configuration. Doing so would allow us to catch potential errors at an early stage, which could be greatly beneficial.

Thank you.

@richard-damon actually, this program has two working parts:
A) Two tasks, prvRxTask and prvTxTask, are working connected with a queue.
B) Task VDMA works with interruptions that happend every 30ms.

@aggarg nothing changed
@ActoryOu As i see, in the configASSERT is defined, how should i use it?

The process A ,with and without vTaskDelay( pdMS_TO_TICKS(500) ), works well by separated,
But I noticed that if I run only the task VDMA , it only works as long as I dont use vTaskDelay in task VDMA.

And A and B together work well as long as i don’t use vTaskDelay.

It seems that there something between vTaskDelay and VDMA interruptions. The code for interruptions is below:

static int SetupIntrSystem_WR_RD(XAxiVdma *AxiVdmaPtr, u16 ReadIntrId, u16 WriteIntrId)
{
	int Status;
	
	/* Instance of the Interrupt Controller */
	XScuGic *IntcInstancePtr = &xInterruptController;
	Status = xPortInstallInterruptHandler( ReadIntrId, (XInterruptHandler) XAxiVdma_ReadIntrHandler, AxiVdmaPtr);

	XScuGic_SetPriorityTriggerType(IntcInstancePtr, ReadIntrId, 0xA0, 0x3);//(configMAX_API_CALL_INTERRUPT_PRIORITY + 1) << portPRIORITY_SHIFT
	XScuGic_SetPriorityTriggerType(IntcInstancePtr, WriteIntrId, 0xA0, 0x3);

	/*
	 * Connect the device driver handler that will be called when an
	 * interrupt for the device occurs, the handler defined above performs
	 * the specific interrupt processing for the device.
	 */
	Status = XScuGic_Connect(IntcInstancePtr, ReadIntrId, (Xil_InterruptHandler)XAxiVdma_ReadIntrHandler, AxiVdmaPtr);
	if (Status != XST_SUCCESS) {
		return Status;
	}

	Status = XScuGic_Connect(IntcInstancePtr, WriteIntrId, (Xil_InterruptHandler)XAxiVdma_WriteIntrHandler, AxiVdmaPtr);
	if (Status != XST_SUCCESS) {
		return Status;
	}
	/*
	 * Enable the interrupt for the DMA device.
	 */
	XScuGic_Enable(IntcInstancePtr, ReadIntrId);
	XScuGic_Enable(IntcInstancePtr, WriteIntrId);
	Xil_ExceptionInit();
	/*
	 * Connect the interrupt controller interrupt handler to the hardware
	 * interrupt handling logic in the processor.
	 */
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,
				(Xil_ExceptionHandler)XScuGic_InterruptHandler,
				IntcInstancePtr);
	/*
	 * Enable interrupts in the Processor.
	 */
	Xil_ExceptionEnable();
	/* Register callback functions
	 */

	XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_GENERAL, ReadCallBack, (void *)AxiVdmaPtr, XAXIVDMA_READ);

	XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_ERROR, ReadErrorCallBack, (void *)AxiVdmaPtr, XAXIVDMA_READ);

	XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_GENERAL, WriteCallBack, (void *)AxiVdmaPtr, XAXIVDMA_WRITE);

	XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_ERROR, WriteErrorCallBack, (void *)AxiVdmaPtr, XAXIVDMA_WRITE);

	return XST_SUCCESS;
}

In code above there is the part Writing frame and Reading frame interruption from VDMA, both interruptions work, but just to simplified in VDMA i only use the semaphore SemVDMAWr.

Another thing is that the interrupt controller instance xInterruptController defined in portZynq7000.c is not initialized. As far I read in many sites , FreeRTOS initializes the interrupt controller instance xInterruptController, that why it is not initialize the XScugic instance, and indeed FreeRTOS commutes tasks.
That’s why before add VDMA interruptions to FreeRTOS, I needed to use :

XScuGic *IntcInstancePtr = &xInterruptController;
Status = xPortInstallInterruptHandler( ReadIntrId, (XInterruptHandler)XAxiVdma_ReadIntrHandler, AxiVdmaPtr);

just only to initialize the xInterruptController. xInterruptController is declared as extern in the VDMA.c file

BUT if xInterruptController is not initialized, what is FreeRTOS initialize to commute tasks?

Here are links where i used
https://support.xilinx.com/s/question/0D52E00006iHj5lSAC/freertos-multiple-tasks-not-responding-when-mixed-with-a-semaphore?language=en_US

https://forums.freertos.org/t/multiple-tasks-not-responding-when-mixed-with-a-semaphore/10242/2

Hi @JCesar,
Thank you for your inquiry. I appreciate you taking the time to clarify the situation regarding the configASSERT. I apologize for any confusion caused by my earlier misunderstanding.

If it’s not too much trouble, could you kindly assist me in verifying the counter recommended by @aggarg?

Additionally, I would like to respectfully inquire about the possibility of the timer not functioning correctly for any reason. If the timer ticks cannot be incremented by the timer, it may not be feasible to calculate the delay time for task A accurately. Could you please lend your assistance in investigating this potential issue?

Thank you.

The following is the definition of the VDMA task the you shared -

void vTask_Video_DMA_App(void *args){
	
	xil_printf("Task VDMA Started\r\n");

	SemVDMAWr = xSemaphoreCreateBinary();

	if(SemVDMAWr==NULL){
		xil_printf("Could not create semaphore SemVDMAWr\n");
		return XST_FAILURE;
	}

	for(;;){

		xil_printf("Entering Task VDMA\r\n");
		if( xSemaphoreTake( SemVDMAWr, portMAX_DELAY) == pdTRUE ){
			xil_printf("VDMA: Semphr took \r\n");
		}
		xil_printf("Leaving Task VDMA\r\n\n\n");
	}
}

I do not see any vTaskDelay here. Can you share the complete code?

One potential problem that I see is that you create SemVDMAWr in VDMA task. Do you ensure that the interrupt that uses SemVDMAWr does not fire before SemVDMAWr is crated? You can consider moving the creation of SemVDMAWr to main before starting the scheduler.

Sorry for answering late.
@aggarg the vTaskDelay() in vTask_Video_DMA_App is just for debugging, I made many versions adding vTaskDelay() in the tasks just to understand what is going on here. I attached the compete code at the bottom of the message

Yes, I did it , but nothing changed , all tasks work perfectly as long as I don’t use vTaskDelay()

In debugging mode, I noticed that:

  • If I use the all tasks without vTaskDelay , everything work well, but FreeRTOS_Tick_Handler() is not called, but FreeRTOS_SWI_Handler → vTaskSwitchContext() is called .
  • If I don’t create the task vTask_Video_DMA_App, The FreeRTOS_Tick_Handler() is called only if i use vTaskDelay().
  • If I use VDMA interruptions and vTaskDelay() , The FreeRTOS_Tick_Handler() is not called. but FreeRTOS_SWI_Handler → vTaskSwitchContext() is called, and vTask_Video_DMA_App() is called also.

I am confused, it is not supposed that The FreeRTOS_Tick_Handler() has to be called ? even if vTaslDelay is not used?

I added FreeRTOS_SetupTickInterrupt() in the SetupIntrSystem_WR_RD() function just in case, but nothing changed

Here is the code :


int main( void )
{

	SemVDMARd = xSemaphoreCreateBinary(); // Declared as Global variable
	SemVDMAWr = xSemaphoreCreateBinary(); // Declared as Global variable


	if(xTaskCreate( 	prvTxTask, ( const char * ) "Tx", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, &xTxTask ) != pdPASS)
	{
		xil_printf("Tx Task was not created\r\n");
		for(;;);
	}

	if(xTaskCreate( prvRxTask, ( const char * ) "GB", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, &xRxTask ) != pdPASS)
	{
		xil_printf("Rx Task was not created\r\n");
		for(;;);

	}
	
	if( xTaskCreate( vTask_Video_DMA_App, ( const char * ) "VDMA", 10*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 3, &xHandler_VDMA ) != pdPASS )
	{
		xil_printf("VDMA Task was not created\r\n");
		for(;;);
	}
	
	xQueue = xQueueCreate( 	4,sizeof( HWstring ) );

	configASSERT( xQueue );

	vTaskStartScheduler();
	for( ;; );
}


static void prvTxTask( void *pvParameters )
{

	for( ;; )
	{
		TxTaskEnterCounter++;
		vTaskDelay(pdMS_TO_TICKS(500));

		if(xQueueSend( xQueue, HWstring, 0L )){
			TxTaskSendStringCounter++;
		}
		TxTaskExitCounter++;
	}
}

static void prvRxTask( void *pvParameters )
{
	char Recdstring[15] = "";
	const TickType_t x1second = pdMS_TO_TICKS( DELAY_1_SECOND );

	//xil_printf("Rx Task started\r\n");
	for( ;; )
	{	RxTaskEnterCounter++;
		Tick_Cnt_dbg = xTaskGetTickCount();
		if(xQueueReceive( xQueue,	Recdstring,  portMAX_DELAY))//portMAX_DELAY
		{
			RxTaskReceivedStringCounter++;
		}
		RxTaskExitCounter++;
	}
}

The VDMA code and the interruption config ( as suggested in zynq-7020-interrupts-under-freertos :

void vTask_Video_DMA_App(void *args){
	int status;
	int Index;
	u32 Addr;

	XAxiVdma myVDMA;
	ptr_myVDMA = &myVDMA;
	XAxiVdma_Config *config = XAxiVdma_LookupConfig(XPAR_AXIVDMA_0_DEVICE_ID);
	XAxiVdma_DmaSetup ReadCfg;
	XAxiVdma_DmaSetup WriteCfg;

	uint32_t VDMA_TaskEnterCounter = 0;
    uint32_t VDMA_TookSmphr = 0;
	uint32_t VDMA_TaskExitCounter = 0;

	xil_printf("Task VDMA Started\r\n");


	if(SemVDMARd==NULL){
		xil_printf("Could not create semaphore SemVDMARd\n");
		for(;;);
	}

	if(SemVDMAWr==NULL){
		xil_printf("Could not create semaphore SemVDMAWr\n");
		for(;;);
		}

	status = XAxiVdma_CfgInitialize(&myVDMA, config, config->BaseAddress);
    if(status != XST_SUCCESS){
    	xil_printf("DMA Initialization failed");
    	for(;;);
    }

    status = XAxiVdma_SetFrmStore(&myVDMA, myVDMA.MaxNumFrames, XAXIVDMA_WRITE);
	if (status != XST_SUCCESS) {

		xil_printf(
		    "Setting Frame Store Number Failed in Write Channel"
							" %d\r\n", status);

		for(;;);
	}

	status = XAxiVdma_SetFrmStore(&myVDMA, myVDMA.MaxNumFrames, XAXIVDMA_READ);
	if (status != XST_SUCCESS) {

		xil_printf(
		    "Setting Frame Store Number Failed in Read Channel"
							" %d\r\n", status);

		for(;;);
	}

	// READ CHANNEL CONFIG
    ReadCfg.VertSizeInput = VSize;
    ReadCfg.HoriSizeInput = HSize*Bytes_Per_Data;
    ReadCfg.Stride = HSize*Bytes_Per_Data;
    ReadCfg.FrameDelay = 0;
    ReadCfg.EnableCircularBuf = 1;
    ReadCfg.EnableSync = 1;
    ReadCfg.PointNum = 0;
    ReadCfg.EnableFrameCounter = 0;
    ReadCfg.FixedFrameStoreAddr = 0;
    ReadCfg.GenLockRepeat = 0;
    status = XAxiVdma_DmaConfig(&myVDMA, XAXIVDMA_READ, &ReadCfg);
    if (status != XST_SUCCESS) {
    	xil_printf("Read channel config failed %d\r\n", status);
    	for(;;);
    }
    Addr = (u32)&(Buffer[0]);
    for(Index = 0; Index < myVDMA.MaxNumFrames; Index++) {
		ReadCfg.FrameStoreStartAddr[Index] = Addr;
		Addr +=  FrameSize;
	}

	status = XAxiVdma_DmaSetBufferAddr(&myVDMA, XAXIVDMA_READ,ReadCfg.FrameStoreStartAddr);
	if (status != XST_SUCCESS) {
		xil_printf("Read channel set buffer address failed %d\r\n", status);
		for(;;);
	}
	XAxiVdma_IntrEnable(&myVDMA, XAXIVDMA_IXR_COMPLETION_MASK, XAXIVDMA_READ);


    WriteCfg.VertSizeInput = VSize;
    WriteCfg.HoriSizeInput = HSize*Bytes_Per_Data;
    WriteCfg.Stride = HSize*Bytes_Per_Data;
    WriteCfg.FrameDelay = 0;
    WriteCfg.EnableCircularBuf = 1;
    WriteCfg.EnableSync = 1;
    WriteCfg.PointNum = 0;
    WriteCfg.EnableFrameCounter = 0;
    WriteCfg.FixedFrameStoreAddr = 0;
    WriteCfg.GenLockRepeat = 0;
    status = XAxiVdma_DmaConfig(&myVDMA, XAXIVDMA_WRITE, &WriteCfg);
    if (status != XST_SUCCESS) {
    	xil_printf("Write channel config failed %d\r\n", status);
    	for(;;);
    }

    Addr = (u32)&(Buffer[0]);
    for(Index = 0; Index < myVDMA.MaxNumFrames; Index++) {
    	WriteCfg.FrameStoreStartAddr[Index] = Addr;
		Addr +=  FrameSize;
	}

	status = XAxiVdma_DmaSetBufferAddr(&myVDMA, XAXIVDMA_WRITE,WriteCfg.FrameStoreStartAddr);
	if (status != XST_SUCCESS) {
		xil_printf("write channel set buffer address failed %d\r\n", status);
		for(;;);
	}

	XAxiVdma_IntrEnable(&myVDMA, XAXIVDMA_IXR_COMPLETION_MASK, XAXIVDMA_WRITE);

	memset((void *)Buffer, 0,FrameSize);
	Xil_DCacheFlush();
	//Xil_DCacheFlushRange(WriteFrameAddr, FRAME_HORIZONTAL_LEN * FRAME_VERTICAL_LEN * WriteCount);


	status = SetupIntrSystem_WR_RD(&myVDMA, WRITE_INTR_ID, READ_INTR_ID);


	if (status != XST_SUCCESS) {

		xil_printf(
		    "Setup interrupt system failed %d\r\n", status);

		for(;;);
	}

	status = XAxiVdma_DmaStart(&myVDMA, XAXIVDMA_WRITE);
	if (status != XST_SUCCESS) {
		xil_printf("Start Write transfer failed %d\r\n", status);

		for(;;);
	}
	status = XAxiVdma_DmaStart(&myVDMA,XAXIVDMA_READ);
	if (status != XST_SUCCESS) {
		if(status == XST_VDMA_MISMATCH_ERROR) xil_printf("Start Read transfer failed %d\r\n",status);
		for(;;);
	}
	
	// Binary semaphores are set in main()

	for(;;){
		VDMA_TaskEnterCounter++;
        //vTaskDelay( pdMS_TO_TICKS(500) ); JUTS FOR DEBUGGING
		if( xSemaphoreTake( SemVDMAWr, portMAX_DELAY) == pdTRUE ){//portMAX_DELAY
			VDMA_TookSmphr++;
			//xil_printf("VDMA: Semphr took \r\n");
		}
		VDMA_TaskExitCounter++;
	}
}

static void WriteCallBack(void *CallbackRef, u32 Mask)
{
	static BaseType_t xHigherPriorityTaskWoken2 = pdFALSE;
	static int counterTx = 0;

	xHigherPriorityTaskWoken2 = pdFALSE;
	counterTx++;
	//xSemaphoreGiveFromISR(SemVDMAWr, &xHigherPriorityTaskWoken2);

	if(counterTx > 30){

		counterTx = 0;
		xSemaphoreGiveFromISR(SemVDMAWr, &xHigherPriorityTaskWoken2);
	}
	portYIELD_FROM_ISR( xHigherPriorityTaskWoken2);

}

static void WriteErrorCallBack(void *CallbackRef, u32 Mask)
{

	xil_printf("W_ERR\r\n");
}

static void ReadCallBack(void *CallbackRef, u32 Mask)
{
	static BaseType_t xHigherPriorityTaskWoken = pdFALSE;
	static int counterRx = 0;

	xHigherPriorityTaskWoken = pdFALSE;
	counterRx++;

	if(counterRx>100){
		xSemaphoreGiveFromISR(SemVDMARd, &xHigherPriorityTaskWoken);
	}
	portYIELD_FROM_ISR( xHigherPriorityTaskWoken);
}

static void ReadErrorCallBack(void *CallbackRef, u32 Mask)
{
	/* User can add his code in this call back function */
	xil_printf("R_ERR\r\n");

}

static int SetupIntrSystem_WR_RD(XAxiVdma *AxiVdmaPtr, u16 ReadIntrId, u16 WriteIntrId)
{
	int Status;

	configSETUP_TICK_INTERRUPT();
		/* Instance of the Interrupt Controller */
	XScuGic *IntcInstancePtr = &xInterruptController;
	Status = xPortInstallInterruptHandler( ReadIntrId, (XInterruptHandler) XAxiVdma_ReadIntrHandler, AxiVdmaPtr);
	Status = xPortInstallInterruptHandler( WriteIntrId, (XInterruptHandler) XAxiVdma_WriteIntrHandler, AxiVdmaPtr);

	XScuGic_SetPriorityTriggerType(IntcInstancePtr, ReadIntrId, 0xA0, 0x3);//(configMAX_API_CALL_INTERRUPT_PRIORITY + 1) << portPRIORITY_SHIFT
	XScuGic_SetPriorityTriggerType(IntcInstancePtr, WriteIntrId, 0xA0, 0x3);


	//Xil_ExceptionInit();
	// Connect the interrupt controller interrupt handler to the hardware interrupt handling logic in the processor.
	//Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,IntcInstancePtr);
	Xil_ExceptionEnable();//Enable interrupts in the Processor.

	/* Register callback functions
	 */

	XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_GENERAL, ReadCallBack, (void *)AxiVdmaPtr, XAXIVDMA_READ);

	XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_ERROR, ReadErrorCallBack, (void *)AxiVdmaPtr, XAXIVDMA_READ);

	XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_GENERAL, WriteCallBack, (void *)AxiVdmaPtr, XAXIVDMA_WRITE);

	XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_ERROR, WriteErrorCallBack, (void *)AxiVdmaPtr, XAXIVDMA_WRITE);


	vPortEnableInterrupt(ReadIntrId);
	vPortEnableInterrupt(WriteIntrId);

	return XST_SUCCESS;
}

Here is your task code with error checking removed for readability -

/* Task Priority = 1. */
static void prvTxTask( void *pvParameters )
{
	for( ;; )
	{
		xQueueSend( xQueue, HWstring, 0L );
	}
}

/* Task Priority = 2. */
static void prvRxTask( void *pvParameters )
{
	char Recdstring[15] = "";

	for( ;; )
	{
		xQueueReceive( xQueue,	Recdstring,  portMAX_DELAY);
	}
}

The execution trace will look like this -

  1. prvRxTask will start running first as this is of higher priority.
  2. prvRxTask will block on xQueueReceive.
  3. prvTxTask will now run as it is next high priority ready task.
  4. prvTxTask will send an item to the queue using xQueueSend.
  5. The send operation will unblock prvRxTask, which will run immediately.
  6. prvRxTask will run the loop again and block on xQueueReceive.

This same cycle will continue to repeat and the idle task (or any other priority 0 task) will never run. Adding a vTaskDelay to prvTxTask will give other priority 0 tasks a chance to run.

Even with this code, the tick interrupt should fire continuously, assuming that tick interrupt has been configured correctly. Can we first confirm that without going into the complication of DMA?

FreeRTOS_Tick_Handler has dependency on vTaskDelay and should be called. It may be the cause of your problem. Lets debug that first.

@aggarg Yes, commenting the part where the task vTask_Video_DMA_App is created.
Without VDMA , the tick interrupt is fired only if I use vTaskdelay()

Well, as I can see in debug mode, the configSETUP_TICK_INTERRUPT() is called

where TimerCounterHandler is assigned with lowest interrupt priority (30)

// In FreeRTOSConfig.h
#define configSETUP_TICK_INTERRUPT() FreeRTOS_SetupTickInterrupt()

// In portZynq7000.c
void FreeRTOS_SetupTickInterrupt( void )
{
	/* Limit the configTICK_RATE_HZ to 1000 if user configured greater than 1000 */
	uint32_t Tick_Rate = (configTICK_RATE_HZ > 1000) ? 1000 : configTICK_RATE_HZ;

	/*
	 * 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)
	/* XTimer_SetInterval() API expects delay in milli seconds
         * Convert the user provided tick rate to milli seconds.
         */
	XTimer_SetInterval(XTIMER_DELAY_MSEC/(Tick_Rate * 10));
#else
	/* XTimer_SetInterval() API expects delay in milli seconds
         * Convert the user provided tick rate to milli seconds.
         */
	XTimer_SetInterval(XTIMER_DELAY_MSEC/Tick_Rate);
#endif
	XTimer_SetHandler(TimerCounterHandler, 0,
			portLOWEST_USABLE_INTERRUPT_PRIORITY << portPRIORITY_SHIFT);
}

Maybe it is a basic question, This timer is started by FreeRTOS somewhere?

the function vPortStartScheduler (which will be defined in the port) is supposed to do everything needs to start the scheduler, including starting the timer. It normally will call a function like your FreeRTOS_SetupTickInterrupt to setup the timer, so it can easily be replaced to use some other timer, and that function should include starting the timer.

The function FreeRTOS_SetupTickInterrupt should do that in your case. Are you not enabling the interrupt there? If not, where is it enabled?

It is not expected and we need to find out why it is happening.

Another issue here is that xQueueSend with no timeout will trash the CPU. The TO may wish to try replacing the 0 in the call to xQueueSend with port_MaxDelay.

Hi,
@aggarg , I was wrong here

I meant that without VDMA task , the tick interrupt FreeRTOS_Tick_Handler is fired ( with or without vTaskDelay ) as expected.
But, with VDMA task, the tick interrupt is not fired, however, all three task are commuted working well.
But, as i mentioned before, if I add vTaskDelay in any task, that task is stopped to work.

@RAc If I set any nonzero timeout, the prvTxTask is stopped ( if VDMA task is created)

To be more precise , prvTxTask , prvRxTask and VDMA task work normal with vTaskDelay, if i don’t add interruptions , So I must be doing something wrong here in SetupIntrSystem_WR_RD that turns off the tick interrupt

static int SetupIntrSystem_WR_RD(XAxiVdma *AxiVdmaPtr, u16 ReadIntrId, u16 WriteIntrId)
{
	int Status;

	configSETUP_TICK_INTERRUPT();
		/* Instance of the Interrupt Controller */
	XScuGic *IntcInstancePtr = &xInterruptController;
	Status = xPortInstallInterruptHandler( ReadIntrId, (XInterruptHandler) XAxiVdma_ReadIntrHandler, AxiVdmaPtr);
	Status = xPortInstallInterruptHandler( WriteIntrId, (XInterruptHandler) XAxiVdma_WriteIntrHandler, AxiVdmaPtr);

	XScuGic_SetPriorityTriggerType(IntcInstancePtr, ReadIntrId, 0xA0, 0x3);//(configMAX_API_CALL_INTERRUPT_PRIORITY + 1) << portPRIORITY_SHIFT
	XScuGic_SetPriorityTriggerType(IntcInstancePtr, WriteIntrId, 0xA0, 0x3);


	//Xil_ExceptionInit();
	// Connect the interrupt controller interrupt handler to the hardware interrupt handling logic in the processor.
	//Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_IRQ_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,IntcInstancePtr);
	Xil_ExceptionEnable();//Enable interrupts in the Processor.

	/* Register callback functions
	 */

	XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_GENERAL, ReadCallBack, (void *)AxiVdmaPtr, XAXIVDMA_READ);

	XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_ERROR, ReadErrorCallBack, (void *)AxiVdmaPtr, XAXIVDMA_READ);

	XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_GENERAL, WriteCallBack, (void *)AxiVdmaPtr, XAXIVDMA_WRITE);

	XAxiVdma_SetCallBack(AxiVdmaPtr, XAXIVDMA_HANDLER_ERROR, WriteErrorCallBack, (void *)AxiVdmaPtr, XAXIVDMA_WRITE);


	vPortEnableInterrupt(ReadIntrId);
	vPortEnableInterrupt(WriteIntrId);

	return XST_SUCCESS;
}