This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TM4C129ENCPDT: TI-RTOS USB example. Memory is not released

Part Number: TM4C129ENCPDT
Other Parts Discussed in Thread: EK-TM4C1294XL

Hi,

In the code example below, I open the USB stick, check whether it is connected and then close it again.

But every time the function usbCopy () was executed, 20 bytes of the HeapMemory are no longer released.

The usbCopy function is called within a task. This task has a stack size of 2048 bytes

I have an EK-TM4C1294XL Launch Pad and use TI-RTOS version: TI-RTOS 2.16.1.14.

This code comes from the TI sample project. If the BIOS_exit(0) is deleted in the TI USB sample project and a waiting loop is inserted, you can also see that 20 bytes are missing.

What can be the reason? I ask for help

void usbCopy(void)
{
    // Variables for the CIO functions
	USBMSCHFatFs_Handle usbmschfatfsHandle;
	USBMSCHFatFs_Params usbmschfatfsParams;


    // Mount and register the USB Drive
    USBMSCHFatFs_Params_init(&usbmschfatfsParams);
    usbmschfatfsParams.serviceTaskStackPtr = usbServiceTaskStack;
    usbmschfatfsParams.serviceTaskStackSize = sizeof(usbServiceTaskStack);
    usbmschfatfsHandle = USBMSCHFatFs_open(0, USB_DRIVE_NUM, &usbmschfatfsParams);
    if (usbmschfatfsHandle == NULL) {
        //System_abort("Error starting the USB Drive\n");
    }
    else {
        System_printf("Drive %u is mounted\n", USB_DRIVE_NUM); System_flush();
    }


    // Need to block until a USB Drive has been enumerated
    if (!USBMSCHFatFs_waitForConnect(usbmschfatfsHandle, 10000)) {
        System_printf("No USB drive present, aborting...\n");System_flush();
        return;
    }

    System_printf("usb close\n"); System_flush();


    USBMSCHFatFs_close(usbmschfatfsHandle);

}

  • Hi,

      I will forward your question to our USB expert. Please expect some delay. In the meantime, can you confirm if you have run the TI-RTOS fatsdusbcopy example as is and do you see any problem?

  • Hi,

    But every time the function usbCopy () was executed, 20 bytes of the HeapMemory are no longer released.

    The usbCopy function is called within a task. This task has a stack size of 2048 bytes

      I'm not an expert in the file system and how the SYS/BIOS handles the heap. But looking at your code I'm not sure what you are trying to do. You create a usbCopy task and in this task you only try to mount the USB stick drive and then immediately close it? Another thing in your code is that why did you remove the System_abort() as shown in the fatsdusbcopy example. If you fail to mount the drive or the enumeration you should call the System_abort so the SYS/BIOS can initiate some internal cleanup. Did you pass the USBMSCHFatFs_open and the USBMSCHFatFs_waitForConnect?

    System_abort() — Your application can call this function when it needs to abort abnormally and return an error message. This function allows you to return a string describing the error that occurred. When this function is called, the System gate is entered, the SupportProxy's abort function is called, and then System.abortFxn is called. No exit functions bound via System_atexit() or the ANSI C Standard Library atexit() functions are called.

  • Hello,
    Thank you for your answer.

    I continued testing with the example project and believe I have found the problem.


    I have the example project "fatsdusbcopy_EK_TM4C129EXL_TI_TivaTM4C129ENCPDT"
    changed so that a file is created on the USB stick and the content of the array is written to this file.

    This process is repeated every 3 seconds.
    If I stop the program and look at the size of the heap memory used, the memory is completely released again. Everything works.

    If I now, add the two lines to the xxx.cfg file:


    var Global = xdc.useModule ('ti.ndk.config.Global');
    Global.autoOpenCloseFD = true;


    20 bytes are not released again after each run of the "copyArrayToUsb ()" function.

    In my real project, Global.autoOpenCloseFD = true is set. That's why these 20 bytes always disappear from my heap.

    How can I solve this?

    /*
     * Copyright (c) 2015, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /*
     *  ======== fatsdusbcopy.c ========
     */
    
    /* XDCtools Header files */
    #include <xdc/std.h>
    #include <xdc/runtime/System.h>
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Task.h>
    
    /* TI-RTOS Header files */
    #include <ti/drivers/GPIO.h>
    #include <ti/drivers/USBMSCHFatFs.h>
    
    /* Example/Board Header files */
    #include "Board.h"
    
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    /* Buffer size used for the file copy process */
    #define CPY_BUFF_SIZE       2048
    
    /* String conversion macro */
    #define STR_(n)             #n
    #define STR(n)              STR_(n)
    
    /* Drive number used for FatFs */
    #define SD_DRIVE_NUM           0
    #define USB_DRIVE_NUM          1
    
    #define TASKSTACKSIZE          1024
    /*
     * Static task stack for the USBMSCHFatFs USB driver
     * This allows the application to reduce the required system Heap.
     */
    static uint8_t usbServiceTaskStack[1024];
    
    const char outputfileusb[] = "fat:"STR(USB_DRIVE_NUM)":output.txt";
    
    const char textarray[] = \
    "***********************************************************************\n"
    "0         1         2         3         4         5         6         7\n"
    "01234567890123456789012345678901234567890123456789012345678901234567890\n"
    "This is some text to be inserted into the inputfile if there isn't\n"
    "already an existing file located on the media.\n"
    "If an inputfile already exists, or if the file was already once\n"
    "generated, then the inputfile will NOT be modified.\n"
    "***********************************************************************\n";
    
    Task_Struct task0Struct;
    Char task0Stack[TASKSTACKSIZE];
    
    unsigned char cpy_buff[CPY_BUFF_SIZE];
    
    /*
     *  ======== taskFxn ========
     *  Task to perform a file copy
     *
     *  Task tries to open an existing file inputfile[]. If the file doesn't
     *  exist, create one and write some known content into it.
     *  The contents of the inputfile[] are then copied to an output file
     *  outputfile[]. Once completed, the contents of the output file are
     *  printed onto the system console (stdout).
     *
     *  Task for this function is created statically. See the project's .cfg file.
     */
    
    Void copyArrayToUsb(Void)
    {
        USBMSCHFatFs_Handle usbmschfatfsHandle;
        USBMSCHFatFs_Params usbmschfatfsParams;
    
        /* Variables for the CIO functions */
        FILE *dst;
    
        /* Variables to keep track of the file copy progress */
        unsigned int bytesRead = 0;
        unsigned int bytesWritten = 0;
        unsigned int filesize;
        unsigned int totalBytesCopied = 0;
    
        /* Mount and register the USB Drive */
        USBMSCHFatFs_Params_init(&usbmschfatfsParams);
        usbmschfatfsParams.serviceTaskStackPtr = usbServiceTaskStack;
        usbmschfatfsParams.serviceTaskStackSize = sizeof(usbServiceTaskStack);
        usbmschfatfsHandle = USBMSCHFatFs_open(Board_USBMSCHFatFs0,
                                               USB_DRIVE_NUM,
                                              &usbmschfatfsParams);
        if (usbmschfatfsHandle == NULL) {
            System_abort("Error starting the USB Drive\n");
        }
        else {
            System_printf("Drive %u is mounted\n", USB_DRIVE_NUM);
        }
    
        /* Need to block until a USB Drive has been enumerated */
        if (!USBMSCHFatFs_waitForConnect(usbmschfatfsHandle, 10000)) {
            System_abort("No USB drive present, aborting...\n");
        }
    
    
        /* Create a new file object for the file copy */
        dst = fopen(outputfileusb, "w");
        if (!dst) {
            System_printf("Error opening \"%s\"\n", outputfileusb);
            System_abort("Aborting...\n");
        }
        else {
            System_printf("Starting file copy\n");
        }
    
        filesize = sizeof(textarray);
    
    
    
        /*  Copy the contents from the src to the dst */
        while (true)
        {
            /*  Write to dst file */
            bytesWritten = fwrite(textarray, 1, filesize, dst);
            if (bytesWritten < bytesRead) {
                System_printf("Disk Full\n");
                break; /* Error or Disk Full */
            }
    
            /*  Update the total number of bytes copied */
            totalBytesCopied += bytesWritten;
    
            if(totalBytesCopied >= filesize){
            	break;
            }
        }
    
        fflush(dst);
    
    
        /* Close both inputfile[] and outputfile[] */
        fclose(dst);
    
    
        /* Now output the outputfile[] contents onto the console */
        dst = fopen(outputfileusb, "r");
        if (!dst) {
            System_printf("Error opening \"%s\"\n", outputfileusb);
            System_abort("Aborting...\n");
        }
    
        /* Print file contents */
        while (true) {
            /* Read from output file */
            bytesRead = fread(cpy_buff, 1, CPY_BUFF_SIZE, dst);
            if (bytesRead == 0) {
                break; /* Error or EOF */
            }
            /* Write output */
            System_printf("%s", cpy_buff);
            System_flush();
        }
    
        /* Close the file */
        fclose(dst);
    
    
    
        /* Stopping the USB Drive */
        USBMSCHFatFs_close(usbmschfatfsHandle);
        System_printf("Drive %u unmounted\n", USB_DRIVE_NUM);
        System_flush();
    
    }
    
    
    Void taskFxn(UArg arg0, UArg arg1)
    {
    
        while(1)
        {
        	Task_sleep(3000);
    
        	copyArrayToUsb();
        }
    }
    
    /*
     *  ======== main ========
     */
    int main(void)
    {
        Task_Params taskParams;
    
        /* Call board init functions */
        Board_initGeneral();
        Board_initGPIO();
        Board_initUSBMSCHFatFs();
    
        /* Construct file copy Task thread */
        Task_Params_init(&taskParams);
        taskParams.stackSize = TASKSTACKSIZE;
        taskParams.stack = &task0Stack;
        taskParams.instance->name = "fatsdUSBCopyTask";
        Task_construct(&task0Struct, (Task_FuncPtr)taskFxn, &taskParams, NULL);
    
    
    
        System_printf("Starting the FatSD USB Copy example\n");
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }
    

  • Hi,

      Please refer to the usage of Global.autoOpenCloseFD below. You can find more details in the NDK API user's guide. I think the problem is that you are calling copyArrayToUsb() as a function from within a task (taskFxn) rather than as a dynamically-created task from within a running task. So try to create a task for copyArrayToUsb() from inside the taskFxn() task and I hope that solves the problem. Read the user's guide on the conditions when the autoOpenCloseFD  is supported. 

    3.1.2.2 Auto-Initializing the File Descriptor Environment
    For TI-RTOS Kernel users who configure their application using XGCONF or a *.cfg configuration file, the
    calls to fdOpenSession and fdCloseSession can be configured to be called automatically. This is achieved
    by setting the following configuration parameter:


    var Global = xdc.useModule('ti.ndk.config.Global.xdc');
    Global.autoOpenCloseFD = true;


    Setting this parameter to true causes calls to fdOpenSession and fdCloseSession to be made
    automatically in the TI-RTOS Kernel Task module's create hook function and exit hook function,
    respectively.


    Note that the Global.autoOpenCloseFD parameter is only supported for dynamically-created Tasks
    created from within a Task context (that is, from within another running Task function). Tasks created
    statically in the configuration or dynamically in main() or a Hwi or Swi thread do not support this feature.

  • In my real project, Global.autoOpenCloseFD = true is set. That's why these 20 bytes always disappear from my heap.

    I have repeated the issue, with tirtos_tivac_2_16_01_14.

    When Global.autoOpenCloseFD is set true, that causes the NDK to:

    • Install a task create hook, which calls fdOpenSession()
    • Install a task exit hook, which calls fdCloseSession()

    When the USBMSCHFatFs functions are used, this causes a task to be dynamically created:

    1. A call to USBMSCHFatFs_open() ends up calling Task_construct() to dynamically create the USBMSCHFatFsTiva_serviceUSBHost() task, storing the task handle in taskHCDMain.
    2. The USBMSCHFatFsTiva_serviceUSBHost() task is in tirtos_tivac_2_16_01_14/products/tidrivers_tivac_2_16_01_13/packages/ti/drivers/usbmschfatfs/USBMSCHFatFsTiva.c and handles the USB Stack's statemachine. This task contains a while (true) loop, i.e. the task itself doesn't exit.
    3. A call to USBMSCHFatFs_close() ends up calling Task_destruct() on the taskHCDMain handle.

    The cause of the memory leak appears to be when USBMSCHFatFs_open() creates the task then the NDK task create hook calls fdOpenSession() which allocates some memory. However, when USBMSCHFatFs_close() calls Task_destruct to delete the task fdCloseSession() is not called. This is because the NDK installs a task exit hook, but not a task delete hook.

  • How can I solve this?

    As per my previous post, found the memory leak occurs when Task_destruct() is called on the taskHCDMain support task. Since the NDK doesn't install a task delete hook, without modifying the TI-RTOS source I found a work-around is to modify the user project to install a delete hook.

    In the .cfg file added the following:

    Task.addHookSet({
       deleteFxn: '&ti_ndk_config_global_taskDeleteHook',
    });
    

    And in the fatsdusbcopy.c added the following:

    #include <ti/ndk/inc/usertype.h>
    #include <ti/ndk/inc/socketndk.h> /* For fdCloseSession() */
    
    Void ti_ndk_config_global_taskDeleteHook(ti_sysbios_knl_Task_Handle h)
    {
        if (h != ti_sysbios_knl_Task_getIdleTask()) {
            /* close FD table session for the user.  Don't call if idle task */
            fdCloseSession(h);
        }
    }
    

    Where the contents of the ti_ndk_config_global_taskDeleteHook() was based upon ti_ndk_config_global_taskExitHook() in tirtos_tivac_2_16_01_14/products/ndk_2_25_00_09/packages/ti/ndk/config/Global.xdt

    I have tested the modification in the attached project, and used the RTOS Object Viewer -> HeapMem -> Detailed view to check the totalFreeSize now remains the same value after every call to copyArrayToUsb()

    Not sure if TI consider the memory leak a bug which should be corrected.

    fatsdusbcopy_EK_TM4C1294XL_TI.zip