Task memory leak?

Version 8.0.0 ATSAMG55 J19 (taget: G55 xPlained) Atmel Studio 7 Description: App consists of 6 xTaskCreate() tasks. One task – CmdProc – polls a touch screen (SPI). Another – TouchPa – processes result of touch screen touch result value (button control on LCD). TheTouchPa process takes about 10 seconds to complete. It includes starting up a fan through GPIO, and reading ADC. The process then enables an ADC timer event that runs for (n) seconds according to the utilTim process (which keeps track of elapsed seconds, like a stopwatch). First time through, everything works fine. Second time TouchPa triggers a hard fault. Before starting I see the following results in the task monitor: ~~~ — task ## 8Monitor R 0 179 1 IDLE R 0 78 7 TouchPa B 1 226 2 ScreenU B 2 176 4 CmdProc B 3 218 5 Tmr Svc B 2 44 8 utilTim S 0 245 6 adc_con S 4 245 3 ~~~ After the process completes, I see the following results in the task monitor: ~~~ — task ## 8Monitor R 0 57 1 IDLE R 0 78 7 CmdProc B 3 97 5 ScreenU B 2 97 4 TouchPa B 1 62 2 Tmr Svc B 2 44 8 adc_con S 4 228 3 utilTim S 0 183 6 ~~~ If I then kick off the process for a second time, my hard fault handler is hit. ~~~ [Hard fault handler – all numbers in hex] R0 = 20000f00 R1 = 20000b60 R2 = 200045f8 R3 = 200045f8 R12 = a5a5a5a5 LR [R14] = 0 subroutine call return address PC [R15] = 0 program counter PSR = 4000000e BFAR = e000ed38 CFSR = 20000 HFSR = 40000000 DFSR = 0 AFSR = 0 SCB_SHCSR = 400 ~~~ The PC of 0 is interesting… I note that some tasks show a reduction in available stack space after they run for the first time. Namely: ~~~ — task ## 8Monitor R 0 57 1 IDLE R 0 78 7 TouchPa B 1 226 2 62 2 ScreenU B 2 174 4 97 4 CmdProc B 3 218 5 97 5 Tmr Svc B 2 44 8 utilTim S 0 245 6 183 6 adc_con S 4 245 3 228 3 ~~~ I’m not doing any mallocs in my code. I suspect the crash is occurring because the TouchPa process runs out of stack. The original setting is: ~~~

define TOUCHPARSETASKPRIORITY ( configMAX_PRIORITIES – 4 )

define TOUCHPARSESTACKSIZE (1024/sizeof(portSTACK_TYPE))

~~~ I increased the stack size to ~~~

define TOUCHPARSETASKPRIORITY ( configMAX_PRIORITIES – 4 )

define TOUCHPARSESTACKSIZE (2048/sizeof(portSTACK_TYPE))

~~~ …and now the process runs a second time. However I get another crash with the system in an idle (polling the touch screen) state. Questions: 1. I have no idea what a safe low-water mark is for stack remaining. Given the numbers above, any suggestions? 2. Is #define configTOTALHEAPSIZE ( ( size_t ) ( 15000 ) ) sufficient? 3. Is there a way to determine what actually triggers the fault? With a PC of 0, it seems hopeless. I thought the vApplicationMallocFailedHook or vApplicationStackOverflowHook would trigger. They don’t.

Task memory leak?

Hi Mark,
  1. I have no idea what a safe low-water mark is for stack remaining. Given the numbers above, any suggestions?
You should know that better than anybody else. What I often do is the following: – give each task an abundant amount of stack space. – Let it run for a really long time, try all possible functions and situations – Measure the maximum usage of the stack space ( try uxTaskGetSystemState() and look for usStackHighWaterMark ) – Make an estimate of the actual usage and add some spare space The live stack check (configCHECK_FOR_STACK_OVERFLOW) works fine, but it may happen that the crash comes before the stack overflow has been detected.
  1. Is #define configTOTALHEAPSIZE ( ( size_t ) ( 15000 ) ) sufficient?
That is easier to measure: there is a hook (vApplicationMallocFailedHook()) which will be called when pvPortMalloc() fails.
  1. Is there a way to determine what actually triggers the fault? With a PC of 0, it seems hopeless. I thought the vApplicationMallocFailedHook or vApplicationStackOverflowHook would trigger. They don’t.
I do not know the part that you are using, but doesn’t it have special registers that get set during an exception, and that have some sort of LR register?

Task memory leak?

Maybe this page is useful to get more information about the crash that you see: http://www.freertos.org/Debugging-Hard-Faults-On-Cortex-M-Microcontrollers.html

Task memory leak?

Hein: I tracked a hard fault to calling vTaskDelay(300) within my TouchPa process. I need a delay in this task, so I substituted msdelay(300). msdelay() is provided by the ASF library and is linked to the CPU’s master clock Now, there is no crash. The documentation says that vTaskDelay() puts the task in which it appears into a blocked state for the delay period. What I can’t understand is why being in a blocked state would cause a crash. Any ideas?? Note that I also implemented a wrapper around my task that accesses SPI. It is important that the access is exclusive. Here’s the code for this. Maybe it will be instructive, or at least helpful to others: ~~~ xSemaphoreSPI = xSemaphoreCreateMutex(); if( xSemaphoreSPI == NULL ) { printf(“Insufficient memory to create xSemaphoreSPInr”); return; }
for (;;)
{
    if( xSemaphoreTake( xSemaphoreSPI, 0 ) == pdPASS )
    {
        printf("Reading TouchPadnr");
        tag_touched = Ft_Gpu_Hal_Rd32(phost, REG_TOUCH_TAG) & 0xFF;
        xSemaphoreGive( xSemaphoreSPI );
    }
    else
    {
        printf("SPI not yet available to read TouchPadnr");
    }
~~~

Task memory leak?

Mark, I can not find ms_delay(), but I do see delay_ms() in Atmel’s ASF. That function is calling cpu_delay_ms(), which is not aware of an OS ( like FreeRTOS ). And so it won’t yield. It will just spin until some time has passed. When you call vTaskDelay(), another task get a chance to run. Could it be that the other task cause the problem?

Task memory leak?

A couple of observations, and request for some clarification. You say the problem is in a call to vTaskDelay, but the code shown doesn’t have a call to vTaskDelay. You are creating a mutex in the task. Is xSemaphoreSPI a global variable or a local variable. If a local variable, a mutex only accessable by 1 task doesn’t get you anything. If global, how does the other task handle the mutex not being created yet if it gets to its need to use it. I try tp create all my mutexes and the like before starting up the scheduler to avoid having to have that sort of issue. It is a bit unusual to have a timeout of 0 for a take, as that somewhat says that you really expect that the resource is always available when you need it. It can make some sense if you have something else to check if it is busy, but then a lot of care needs to be taken that you will still service this device often enough.

Task memory leak?

Richard: Good call on the xSemaphoreSPI init! These are now global (I use a few). The point of their use is to prevent multiple task execution of code ( SPI calls). I’m now initializing these before calling the schedule. vTaskDelay happened later in my code. As you can see I’ve commented these out and replaced with delay_ms()… ~~~ void CmdProcess(void *pvParameters) { static portCHAR szList[256]; UNUSED(pvParameters);
for (;;)
{
    if( xSemaphoreTake( xSemaphoreSPI, 0 ) == pdPASS )
    {
        // vTaskDelay(1);
        delay_ms(1);
        printf("Reading TouchPadnr");
        tag_touched = Ft_Gpu_Hal_Rd32(phost, REG_TOUCH_TAG) & 0xFF;
        if (tag_touched>0)
            printf("VALID TouchPad[%i]nr",tag_touched);
        // vTaskDelay(1);
        delay_ms(1);
        xSemaphoreGive( xSemaphoreSPI );
    }
    else
    {
        printf("SPI not yet available to read TouchPadnr");
    }

    // valid press
    if (tag_touched>0 && tag_touched<99)
    {
        // encapsulate
        if( xSemaphoreTake( xSemaphoreLCDSound, 0 ) == pdPASS )
        {
            printf("***TP: Valid tag_touched[%i]nr",tag_touched);
            Play_Sound(0x23,255);
            delay_ms(50);
            //vTaskDelay(50);
            Stop_Sound();
            sprintf(cUtilStr,"Touched [%i]",tag_touched);
            ProcessTouch(tag_touched);
            xSemaphoreGive( xSemaphoreLCDSound );
        }
    }


    if (utilTimerAlarmState && aTaskState[TASK_UTILTIMER])
    {
        printf("CmdProcess() suspending timer task and processing STOPnr");
        SuspendTask(TASK_UTILTIMER);
        ResetUtilTimer();
        // process a STOP
        tag_touched=TAG_STOP;
        ProcessTouch(tag_touched);
    }

    **//vTaskDelay(200);    // 250mS**
    delay_ms(200);
}
} ~~~ So if I use delay_ms(200) in place of vTaskDelay(200), this is the equivalent of vTaskDelay(0)? Maybe the crash is occurring because of some other contention… FYI, here’s what I’m using in xTaskCreate… ~~~

define TOUCHPARSETASKPRIORITY ( configMAX_PRIORITIES – 1 )

define TOUCHPARSESTACKSIZE (2048/sizeof(portSTACK_TYPE))

define ADCCONVERTTASKPRIORITY ( configMAXPRIORITIES – 1 )

define ADCCONVERTSTACKSIZE (2048/sizeof(portSTACKTYPE))

define SCREENUPDATETASKPRIORITY ( configMAXPRIORITIES – 1 )

define SCREENUPDATESTACKSIZE (1024/sizeof(portSTACKTYPE))

define CMDPROCESSTASKPRIORITY ( configMAXPRIORITIES – 1 )

define CMDPROCESSSTACKSIZE (2048/sizeof(portSTACKTYPE))

define UTILTIMERTASKPRIORITY ( configMAXPRIORITIES – 1 )

define UTILTIMERSTACKSIZE (1280/sizeof(portSTACKTYPE))

// task definitions

define TASKMONITORSTACKSIZE (4096/sizeof(portSTACKTYPE))

define TASKMONITORSTACKPRIORITY (tskIDLEPRIORITY)

~~~ Hopefully these are right (using heap_4.c): ~~~

define configMINIMALSTACKSIZE ( ( uint16_t ) 100 )

define configTOTALHEAPSIZE ( ( size_t ) ( 15000 ) )

~~~

Task memory leak?

If as some poeple point out that delay_ms() does a busy wait for the time, and not actually block for that time, that this task likely NEVER blocks, and thus doesn’t let lower priority task run, as opposed to blocking with the vTaskDelay call. If this stops a lower priority task that is crashing from running, that might explain some of what you see.