After calling one time the vTaskDelay, the tasks wont wakeup

Hi!
I use the latest FreeRTOS kernel code (v10.3.1) into STM32F44r6 to academic research and i have one little problem with vTaskDelay function.

I have three tasks, with decrescent priorities:

Task-1 (Prio 4); // Periodic Task
Task-2(Prio 3); // Periodic Task
Task-3(Prio 2); // Not Periodic Task

Task-3 only send some logs from kernel trace macros, that’s the reason why it’s not periodic. I store the trace macros with respective cycle cpu time events into a linked list and send the data on serial port to my computer for metrics. Task-1 and Task-2 are the system tasks and do all the job for me.

So, in one time on Task-1 and Task-2 i call the function vTaskDelay, to block the current task running on CPU and schedule to another task. The function tasks are similar, so for didatic reason i will write here only one function. Here is the code:

void v1Task1_AND_v1Task2_Handler(void *params) {
	TickType_t xLastWakeTime;
	const TickType_t xFrequency = 10;
	xLastWakeTime = xTaskGetTickCount();
	for (;;) {
		vTaskDelayUntil(&xLastWakeTime, xFrequency);
            // do some stuff
  		vTaskDelay(pdMS_TO_TICKS(1));
	}
}

And here is the Task-3:

void v1Task3_Handler(void *params){
while(1){
		while(queue_has_points()){
			p = peek_point();
			print_msg(p.code);
			print_msg(p.task);
		}
	}
}

When the Task-1 and Task-2 call the vTaskDelay, they enter into blocked state and never runs again. So, forever Task-3 executes.

I have checked if timer interrupt(systick) works when it happens. And yes, Systick works.

Could you help me, please?

Thank you!

Can you please confirm the tick interrupt is working. If it isn’t then the system won’t see time change, so tasks that are blocked with a timeout will never unblock.

To do that you can leave the system running for a short while, pause it in the debugger, then view the xTickCount variable in FreeRTOS/Source/tasks.c. Let the system run for a short time longer, then do the same to see if xTickCount has changed by a reasonable amount.

1 Like

Hi Richard! Thank you for your help.

I have watched the xTickCount while the CPU runs. The variable change in every xTickIncrementCount() like expected, also the timer interrupt. All looks like ok with the Systick Interrupt and timer measurement.

In the debugger can you see how xNextTaskUnblockTime compares to xTickCount? That might guide the next troubleshooting step.

2 Likes

Thanks Jeff!

I did what you recommended. I found that the xSwitchRequired variable is not changed to true with each xTickIncrement() run. Do you know what that means? I know that xSwitchRequired is for trigger the context switching interrupt but do you know what is the cause of this failure?

The value of xNextTaskUnblockTime is 2902982727.

1 Like

This value is too high compared to xTickCount. You are probably corrupting xLastWakeTime. I would guess the bug is somewhere in here:

Have you followed the suggestions here https://www.freertos.org/FAQHelp.html to check for things like stack overflow, having configASSERT() defined, etc? Also, try taking the print statements out as that may be a cause of malloc() being called or a huge stack frame, depending on how it is implemented.

2 Likes

I used malloc and free functions for linked list on trace macros. And this are “corrupting” the other variables.

pvPortMalloc and vPortFree are not working for my linked list until 10 positions. After then, the function pvPortMalloc stucks in configAssert(). That’s why i used the malloc and free.

I’ll look in the old forum posts on how to resolve this issue.

So, I will close the post and I would like to thank you for helping me with this problem.

Thanks!

Thank you Richard for help me with this.

Yes. The cause of all this is the malloc and free functions. I explained to Jeff whats going on. Take a look on my answer.

Thank you!

The functions malloc and free are likely not thread safe unless you have done something to make them so. You said you had an a configAssert() using pvPortMalloc, what was the assert that was fired? That may point to part of the problem (unless it was falling victim of the same corruption)

Thank you for your help Richard.
The assert is present at vPortEnterCritical(void) on port.c, line 403;

void vPortEnterCritical( void )
{
	portDISABLE_INTERRUPTS();
	uxCriticalNesting++;

	/* This is not the interrupt safe version of the enter critical function so
	assert() if it is being called from an interrupt context.  Only API
	functions that end in "FromISR" can be used in an interrupt.  Only assert if
	the critical nesting count is 1 to protect against recursive calls if the
	assert function also uses a critical section. */
	if( uxCriticalNesting == 1 )
	{
		configASSERT( ( portNVIC_INT_CTRL_REG & portVECTACTIVE_MASK ) == 0 );
	}
}

When task will resume at 11 iteration for link a node on list, the uxCriticalNesting is equal 1, and CPU stucks on assert (probably waiting an interruption?)

The pvPortMalloc and vPortFree are called outside the task context. The new node is linked on trace macro event.

Here i show the entire code:

void point_trace(char *code, char *task, unsigned long cpu_cycle) {
	struct Node *new_point = NULL;

	/* Setting the memory space for new event */
	new_point = pvPortMalloc(sizeof(struct Node));

	if (new_point) {

		/* Inserting data */
		new_point->next = 0x00;
		new_point->code = code;
		new_point->cpuCycles = cpu_cycle; // Getting the time of point.
		new_point->task = task;

		if (root) {
			last->next = new_point; /* List with one or more element*/
			last = last->next;
		} else {
			root = new_point; /* Empty List*/
			last = new_point;
		}

		size_list++;
	}
}

Here is where i call this function:

“trace.h”
#define traceTASK_SWITCHED_IN() point_trace(pxCurrentTCB->pcTaskName, TASK_IN_CODE, DWT->CYCCNT)

And finally, i call the header file “trace.h” at bottom of file “FreeRTOSConfig.h”

The heap is heap4.c .

What that asset tells is that the vPortEnterCritical is being called from an ISR while it should not have been. Where is that call coming from i.e. what is the call stack at that point?

traceTASK_SWITCHED_IN is called from vTaskSwitchContext which is called from an ISR (PENDSV_Handler in your case as STM32F44 is Cortex-M4 MCU). pvPortMalloc is not safe to be called from an ISR - that may be the cause of the problem. To verify, would you please try removing the call to pvPortMalloc from point_trace and instead use static memory?

Thanks.