Memory not freed (vTaskDelete)

Hi Community, as a beginner, I am working through the examples in the eBook “Using the FreeRTOS Real Time Kernel”. I am not using the Simulator, but an ATMega32, so instead of  “vPrintString”, I use the serial port as output. In Example 9, only Task1 is created in main, Task2 is created in Task1 with a higher priority. Task2 only prints out “Task 2 running” and then deletes itself  with “vTaskDelete( xTask2Handle );” As I understand, the idle task should free the memory automatically after the Task is deleted. But my output looks like this: Task 1 is running
Task 2 is running
Task 1 is running
Task 2 is running
Task 1 is running
Task 2 is running
Task 1 is running
Task 2 is running
Task 1 is running
Task 2 is running
Task 1 is running
Task 2 is running
Task 1 is running
Task 1 is running
Task 1 is running
Task 1 is running
….(only Task1 after this) When I use double the stack when calling xTaskCreate(), Task 2 is active only half the time than in the example above. So it seems the memory does not get freed by the idle Task like it should and after a while Task2 cannot be created anymore due to lacking stack. Thank you very much for your help ! My main.c :
#include <stdlib.h>
#include <string.h>
#ifdef GCC_MEGA_AVR
    /* EEPROM routines used only with the WinAVR compiler. */
    #include <avr/eeprom.h>
#endif
#include "FreeRTOS.h"
#include "task.h"
#include "serial.h"
/* We should find that each character can be queued for Tx immediately and we
don't have to block to send. */
#define comNO_BLOCK                     ( ( portTickType ) 0 )
#define comSTACK_SIZE                   configMINIMAL_STACK_SIZE
#define mainCOM_TEST_BAUD_RATE          ( ( unsigned long ) 38400 )
#define comBUFFER                       ( ( ( unsigned portBASE_TYPE ) (strlen(pcTextForTask1) ) + ( unsigned portBASE_TYPE ) 1 ) *2)
/* Define the strings that will be passed in as the task parameters.  These are
defined const and off the stack to ensure they remain valid when the tasks are
executing. */
const char *pcTextForTask1 = "rnTask 1 is running";
const char *pcTextForTask2 = "rnTask 2 is running";
/* Handle to the com port used by the task */
static xComPortHandle xPort = NULL;
/* The two task functions. */
void vTask1( void *pvParameters );
void vTask2( void *pvParameters );
/* Used to hold the handle of Task2. */
xTaskHandle xTask2Handle;
/****************************************************************************/
int main( void )
{
    /* Create the first task at priority 1.  This time the task parameter is
        not used and is set to NULL.  The task handle is also not used so likewise
        is also set to NULL. */
        xSerialPortInitMinimal ( mainCOM_TEST_BAUD_RATE, comBUFFER );
        xTaskCreate( vTask1, (signed portCHAR * )"Task 1", 100, (void *)pcTextForTask1, 1, NULL );
        vTaskStartScheduler();
        for ( ;; );
        return 0;
}
/****************************************************************************/
void vTask1( void *pvParameters)
{
    char *StringToSend = (char *) pvParameters;
    signed char ByteToSend;
    for( ;; )
    {
        for( ByteToSend = 0; StringToSend[ByteToSend] != ''; ByteToSend++ )
        {
            xSerialPutChar( xPort, StringToSend[ByteToSend], comNO_BLOCK );
        }
    xTaskCreate( vTask2, (signed portCHAR *)"Task 2", 100, (void *)pcTextForTask2, 2, &xTask2Handle );
    vTaskDelay( 500 / portTICK_RATE_MS );
    }
}
/****************************************************************************/
void vTask2( void *pvParameters )
{
    /* Task2 does nothing but delete itself.  To do this it could call vTaskDelete()
    using a NULL parameter, but instead and purely for demonstration purposes it
    instead calls vTaskDelete() with its own task handle. */
    char *StringToSend = (char *) pvParameters;
    signed char ByteToSend;
    for ( ByteToSend = 0; StringToSend[ByteToSend] != ''; ByteToSend++ )
    {
        xSerialPutChar( xPort, StringToSend[ByteToSend], comNO_BLOCK );
    }
    vTaskDelete( xTask2Handle );
}
/****************************************************************************/

Memory not freed (vTaskDelete)

Depending on the FreeRTOS version you might have a problem that xTask2Handle is not being assigned until after vTask2 has executed. That is because vTask2 has a priority above vTask1 that creates vTask2 (so vTask2 will start running as soon as it is created). Try changing the code so vTaskDelete(xTask2Handle) is replaced with vTaskDelete(NULL); Does that help?

Memory not freed (vTaskDelete)

That was a fast response… :-) I am using FreeRTOS 7.0.0 and unfortunately it does not make a difference when I change it to “vTaskDelete( NULL );” But my understanding is correct ? The memory should get freed by the idle task without my code, no need to use the IdleHook or “vTaskCleanUpResources” or anything ? This is my FreeRTOSconfig.h, maybe there is something wrong in here:
#define configUSE_PREEMPTION        1
#define configUSE_IDLE_HOOK         0
#define configUSE_TICK_HOOK         0
#define configCPU_CLOCK_HZ          ( ( unsigned long ) 8000000 )
#define configTICK_RATE_HZ          ( ( portTickType ) 1000 )
#define configMAX_PRIORITIES        ( ( unsigned portBASE_TYPE ) 4 )
#define configMINIMAL_STACK_SIZE    ( ( unsigned short ) 85 )
#define configTOTAL_HEAP_SIZE       ( (size_t ) ( 1500 ) )
#define configMAX_TASK_NAME_LEN     ( 16 )
#define configUSE_TRACE_FACILITY    0
#define configUSE_16_BIT_TICKS      1
#define configIDLE_SHOULD_YIELD     1
#define configQUEUE_REGISTRY_SIZE   0
/* Co-routine definitions. */
#define configUSE_CO_ROUTINES       0
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#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
Thank you very much !

Memory not freed (vTaskDelete)

Yes, the idle task should free the memory provided it gets time on the cpu. Try putting a break point in the idle task (prvIdleTask() I think in tasks.c) to see if it ever executes.