Page 1 of 1

Using printf inside Task

Posted: Thu Jul 18, 2019 9:01 pm
by GDX1024
I'm trying to use the printf inside a Task from freeRTOS and I can't. Outside the task, in the app_main(), it goes ok. But inside the task it starts printing a lot of information that I didn't ask for.

  1. [
  2. #include "freertos/FreeRTOS.h"
  3. #include "esp_system.h"
  4. #include "esp_event.h"
  5. #include "esp_event_loop.h"
  6. #include "nvs_flash.h"
  7. #include "driver/gpio.h"
  8.  
  9. void mytask(void *pvParameter){
  10.   while(1){
  11.     printf("hola, task!\n");
  12.     vTaskDelay(1000/portTICK_PERIOD_MS);
  13.   }
  14. }
  15.  
  16. void app_main(void)
  17. {
  18.     nvs_flash_init();
  19.  
  20.     xTaskCreate(&mytask, "blink_task", 512, NULL, 5, NULL);
  21. }
  22. ]
  23.  
  24. I don't know if I have to configure something. Any information would help a lot.

Re: Using printf inside Task

Posted: Thu Jul 18, 2019 10:26 pm
by ESP_igrr
You probably need to increase the stack size to 2048 or more.

Re: Using printf inside Task

Posted: Fri Jul 19, 2019 1:23 am
by GDX1024
Yes. It was the stack. The esp was rebooting and starting all over again, and than printing the error again so fast that I could not see the stack message. I can't believe I need 2k of memory to print "hello, world".

thank you.

Re: Using printf inside Task

Posted: Fri Jul 19, 2019 10:02 am
by ESP_igrr
Indeed, printf implementation does need a fair amount of stack to work, regardless of what the format string is. Actually if the printf statement doesn't use any format arguments, the compiler should be able to optimize it, converting it into "puts". I wonder why this hasn't happened here (possibly related to Debug/Release setting in menuconfig).

You can also choose to use "nano" implementation of formatting functions, which uses less stack space and has smaller code size. It doesn't support all C99 format string features, though.

Re: Using printf inside Task

Posted: Fri Jul 19, 2019 6:33 pm
by fly135
In my experience, using printf adds 1K to the stack requirement for a task.

John A

Re: Using printf inside Task

Posted: Fri Jul 19, 2019 8:39 pm
by rudi ;-)
it would be almost superior to an auto mode function for that.
is it not known how much stack you will need in the moment when precompiled?
( free stack.... used stack... needed stack.. )
that's what the compiler should be able to tackle more intellectually.

does RTOS not have a compile mode supporting stack overflow detection?


btw: have not tried the code yet, just read it perhabs this helps too:
using uxTaskGetStackHighWaterMark function to determine how much stack has actually been used.. that interrupts also use the stack of the task that is interrupted


best wishes
rudi ;-)

Re: Using printf inside Task

Posted: Sat Jul 20, 2019 12:29 am
by mikemoy
btw: have not tried the code yet, just read it perhabs this helps too:
using uxTaskGetStackHighWaterMark function to determine how much stack has actually been used.. that interrupts also use the stack of the task that is interrupted
I implement GetTaskHighWaterMarkPercent in every program I do. You just may never know just how close to the edge your running if you don't use this.

Example....

Code: Select all

#define STACK_SIZE_xtask1		2048
#define STACK_SIZE_xtask2		4096

TaskHandle_t TaskHandle_xtask1;
TaskHandle_t TaskHandle_xtask2;



//********************************************************************
//  	
// ********************************************************************
void xtask1(void * parameter)
{
	uint32_t x = 0;
	
	for (;;)
	{
		printf("xtask1 Running: %u\r\n", x++);
		
		vTaskDelay(250 / portTICK_PERIOD_MS);
	}
}
//********************************************************************
//  	
// ********************************************************************
void xtask2(void * parameter)
{
	uint32_t x = 0;
	
	for (;;)
	{
		printf("xtask2 Running: %u\r\n", x++);
		
		vTaskDelay(125 / portTICK_PERIOD_MS);
	}
}

/* -----------------------------------------------------------------------------
  GetTaskHighWaterMarkPercent( TaskHandle_t task_handle, uint32_t stack_allotment )

 	Input Params:
    - task_handle: The task handle name
   	- stack_allotment:  How much stack space did you allocate to it when you created it

  Returns: float with the % of stacke used
  Example:   printf("Stack Used %04.1f%%\r\n", GetTaskHighWaterMarkPercent(xTask1, 2048) );
  Notes:
 -----------------------------------------------------------------------------*/
float GetTaskHighWaterMarkPercent( TaskHandle_t task_handle, uint32_t stack_allotment )
{
  UBaseType_t uxHighWaterMark;
  uint32_t diff;
  float result;

  uxHighWaterMark = uxTaskGetStackHighWaterMark( task_handle );

  diff = stack_allotment - uxHighWaterMark;

  result = ( (float)diff / (float)stack_allotment ) * 100.0;

  return result;
}
//
//
//
void app_main()
{
	
	xTaskCreate(xTask1, "xTask1", STACK_SIZE_xtask1, NULL, 5, &TaskHandle_xtask1);	
	xTaskCreate(xTask2, "xTask2", STACK_SIZE_xtask2, NULL, 4, &TaskHandle_xtask2);	
	
	while(1)
	{
			TickType_t xTime1 = xTaskGetTickCount();
		
		
			uint8_t temp1 =  (uint8_t)GetTaskHighWaterMarkPercent(TaskHandle_xtask1, STACK_SIZE_xtask1);
			uint8_t temp2 =  (uint8_t)GetTaskHighWaterMarkPercent(TaskHandle_xtask2, STACK_SIZE_xtask2);
		
			printf("\r\n************************************************\r\n");
			printf("Tick:         %06.1f\r\n", (float)xTime1 / 100.00);
			printf("xTask1:       %03u%%\r\n", temp1);
			printf("xTask2:       %03u%%\r\n", temp1);
			
			if(temp1 > 90)
			{
				printf("!!! WARNING xTask1 Stack Useage to HIGH !!!\r\n");
			}
			
			
			vTaskDelay(250 / portTICK_PERIOD_MS);	
	}
	
}