emWin memory management bug. ...Ex() functions.

This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

  • emWin memory management bug. ...Ex() functions.

    My program takes images from SD one by one and shows it in GUI.
    For reading SD I use FAT FS library. SD connected to controller by SDIO.


    I tried two approaches - with WM and without it.
    My LCD glass has size 320x240, and I show BMP images that have size 300x225 and 16bpp.
    So, one line of such image requires 600B.
    Everything works fine, (images loads, and displays on LCD) except emWin's memory management.
    Every time program changes picture it consumes irreversible 612B of allocated for GUI memory (checked by GUI_ALLOC_GetNumFreeBytes()).
    Nothing can restore memory - I tried GUI_Clear, GUI_ClearRect. In case of WM: WM_InvalidateWindow, WM_DeleteWindow, WM_Deactivate, WM_SetCallback(dialog, 0).
    I tried this program under RTOS and without it with the same result.

    My code for get data function:

    static int _GetData(void * p, const U8 ** ppData, unsigned NumBytesReq, U32 Offset) {
    unsigned int NumBytesRead;
    // if (NumBytesReq > sizeof(_acBuffer)) //Check buffer size in case of static buffer
    // NumBytesReq = sizeof(_acBuffer);
    taskENTER_CRITICAL(); //Prevent the possibility to break SD read process
    // osThreadSetPriority(ImgCyclerHandle, osPriorityRealtime); //Prevent the possibility to break SD read process - other approach
    f_lseek((FIL *) p, Offset); //Set file pointer to the required position
    f_read((FIL *) p, (void *) _acBuffer, NumBytesReq, &NumBytesRead); //Read data into buffer
    // osThreadSetPriority(ImgCyclerHandle, osPriorityNormal); //Restore GUI thread priority
    taskEXIT_CRITICAL();
    *ppData = (const U8 *) _acBuffer; //Set pointer to the buffer
    return NumBytesRead;
    }

    Function that demonstrate images:

    void Show_img_from_SD(TCHAR const* img_name) {
    _acBuffer = (U8*) calloc(BYTES_IN_LINE, sizeof(U8));
    /*Register the file system object to the FatFs module*/
    /*
    * param 1 Pointer to the file system object (NULL:unmount)
    * param 2 Logical drive number to be mounted/unmounted
    * param 3 0:Do not mount (delayed mount), 1:Mount immediately
    */
    if (f_mount(&fileSystem, (TCHAR const*) SD_Path, 0) == FR_OK) {

    /*Open file image with read access*/
    /*
    * param 1 Pointer to the blank file object
    * param 2 Pointer to the file name
    * param 3 Access mode and file open mode flags
    */
    res = f_open(&ImgFile, img_name, FA_OPEN_EXISTING | FA_READ);
    if (res == FR_OK)
    GUI_BMP_DrawEx(_GetData, &ImgFile, 0, 0);
    f_close(&ImgFile);
    }
    f_mount(NULL, (TCHAR const*) SD_Path, 0);
    free(_acBuffer);
    }


    RTOS thread looks like:

    void Img_cycler_thread(void const * argument) {
    uint8_t img_counter = 0;
    GUI_DispStringAt("Free GUI mem.:", 0, 225);
    GUI_DispStringAt("Img. num.:", 230, 225);
    for (;;) {
    GUI_Clear();
    GUI_ClearRect(0,0, XSIZE_PHYS, YSIZE_PHYS);
    Show_img_from_SD("10_300x225_16bpp.bmp");
    GUI_DispDecAt((I32) GUI_ALLOC_GetNumFreeBytes(), 90, 225, 6);
    img_counter++;
    GUI_DispDecAt((I32) img_counter, 300, 225, 3);

    osDelay(500); //let other threads to work

    GUI_Clear();
    GUI_ClearRect(0,0, XSIZE_PHYS, YSIZE_PHYS);
    Show_img_from_SD("9_300x225_16bpp.bmp");

    GUI_DispDecAt((I32) GUI_ALLOC_GetNumFreeBytes(), 90, 225, 6);
    img_counter++;
    GUI_DispDecAt((I32) img_counter, 300, 225, 3);

    osDelay(500); //let other threads to work
    }
    }

    Memory allocated for emWin:
    #define GUI_NUMBYTES (20*1024)


    --

    After 23-th cycle, GUI runs out of memory and ceases to show images, but touch still working. GUI not halts.

    Full projects (version with RTOS and whithout) you can take here:
    yadi.sk/d/yuOcpdoAvnNZ9

    In case of WM my key functions looks like:

    void Load_image_WM(WM_HWIN image, TCHAR const* img_name) {
    _acBuffer = (U8*) calloc(BYTES_IN_LINE, sizeof(U8));
    if (f_mount(&fileSystem, (TCHAR const*) SD_Path, 1) == FR_OK) { //mount drive
    res = f_open(&ImgFile, img_name, FA_OPEN_EXISTING | FA_READ); //open file
    if (res == FR_OK)
    IMAGE_SetBMPEx(image, _GetData, &ImgFile); //pump file to LCD
    // f_close(&ImgFile);
    }
    // f_mount(NULL, (TCHAR const*) SD_Path, 0);
    free(_acBuffer);
    }


    static const GUI_WIDGET_CREATE_INFO Main_Window_DialogCreate[] = {
    { WINDOW_CreateIndirect, "Window", 0x1000,
    0, 0,
    WINDOW_WIDTH, WINDOW_HEIGHT, 0, 0x0, 0 },
    { IMAGE_CreateIndirect, "Image", GUI_ID_IMAGE0,
    0, 0,
    IMAGE_WIDTH, IMAGE_HEIGHT,
    0, 0, 0 } };


    void WIDGETS_Callback(WM_MESSAGE * pMsg) { //Custom callback function
    switch (pMsg->MsgId) {
    case WM_INIT_DIALOG:
    image = WM_GetDialogItem(pMsg->hWin, GUI_ID_IMAGE0);
    Load_image_WM(image, img_name);
    break;
    case WM_DELETE:
    WM_Invalidate(image);
    //... there was many other functions, I tried different approaches
    break;
    default:
    WM_DefaultProc(pMsg);
    }
    }


    WM_HWIN Create_img_dialog(TCHAR const* img_name_input) {
    GUI_Clear(); //clear screen for the beginning
    #if GUI_SUPPORT_MEMDEV
    WM_SetCreateFlags(WM_CF_MEMDEV);
    #endif
    img_name = img_name_input;
    WM_HWIN dialog = GUI_CreateDialogBox(Main_Window_DialogCreate, GUI_COUNTOF(Main_Window_DialogCreate), WIDGETS_Callback, WM_HBKWIN, 0, 0);
    return dialog;
    }

    Implementation in thread:


    void Img_cycler_thread_WM(void const * argument) {
    WM_HWIN dialog;
    dialog = Create_img_dialog("9_300x225_16bpp.bmp");

    for (;;)
    {
    GUI_ClearRect(0,0, XSIZE_PHYS, YSIZE_PHYS);
    Load_image_WM(image, "7_300x225_16bpp.bmp");
    osDelay(500); //let other threads to work
    WM_Update(dialog);

    GUI_ClearRect(0,0, XSIZE_PHYS, YSIZE_PHYS);
    Load_image_WM(image, "8_300x225_16bpp.bmp");
    osDelay(500); //let other threads to work
    WM_Update(dialog);


    // dialog = Create_img_dialog("9_300x225_16bpp.bmp");
    // osDelay(500); //let other threads to work
    // WM_SetCallback(dialog, 0);
    // WM_InvalidateWindow(dialog);
    // WM_DeleteWindow(dialog);
    // WM_Deactivate();
    // GUI_Clear();
    //
    // GUI_DispDecAt((I32) GUI_ALLOC_GetNumFreeBytes(), 0, 225, 6);
    // GUI_DispDecAt((I32) GUI_ALLOC_GetNumUsedBytes(), 60, 225, 6);
    //
    // dialog = Create_img_dialog("10_300x225_16bpp.bmp");
    // osDelay(500); //let other threads to work
    // WM_SetCallback(dialog, 0);
    // WM_InvalidateWindow(dialog);
    // WM_DeleteWindow(dialog);
    // WM_Deactivate();
    // GUI_Clear();
    //
    // GUI_DispDecAt((I32) GUI_ALLOC_GetNumFreeBytes(), 0, 225, 6);
    // GUI_DispDecAt((I32) GUI_ALLOC_GetNumUsedBytes(), 60, 225, 6);
    }
    }



    Implementation without RTOS:

    WM_HWIN dialog;
    dialog = Create_img_dialog("9_300x225_16bpp.bmp");
    while (1) {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    GUI_Exec();
    GUI_TOUCH_Exec();

    Load_image_WM(image, "7_300x225_16bpp.bmp");
    HAL_Delay(500);
    WM_Update(dialog);

    Load_image_WM(image, "8_300x225_16bpp.bmp");
    HAL_Delay(500);
    WM_Update(dialog);
    }
    /* USER CODE END 3 */
    }

    ----
    I have pretty little hope for help, writing this post.
    Last time I appealed to this forum, support engineer Til, just tried to pick me on some details in my code and makes demagogy about commercial relationships.
  • Hello Constantine,

    You are right there was a bug in GUI_BMP_DrawEx() when the buffer used in the _GetData function wasn't big enough. This has been fixed and will be released with the next bug fix version (V5.36d) of emWin.

    We were able to avoid the bug if _acBuffer was big enough to hold one line of the image and the number of bytes read should were equal to the number of bytes required.

    Regards,
    Sven
  • Last time I appealed to this forum, support engineer Til, just tried to pick me on some details in my code and makes demagogy about commercial relationships.


    Dear Constantine,

    please be aware we are a commecial company which gives support via email to our customers which have a valid software license.
    You don't have an emWin license and your are not an emWin customer. Therefore I tried to explain you that you are using STemWin and not emWin.
    The differnce is the commercial relationship. Please let me know if this is still unclear.

    Also this forum is not a support forum. We try to answer here as much as possible but the general support is handled via email.
    In your case you could contact the ST support via email.

    But anyhow we are happy to help you and answer any friendly forum post :) .

    Best regards,
    Til
  • Hello, Til.
    This is still unclear.
    As STM said, STemWin is emWin library that they licensed from segger for its customers.
    This means, that every time I buy MCU from STM, I indirectly pay to STM for emWin library. That is why STM's MCUs cost twice as much than LPC's for example.
    Every time, I try to post message with bug description on STM's forum, they appeal to emWin and to this forum.

    STM provides emWin manual with STemWin library. All functions look completelly the same.

    And as I see through this forum they have the same bugs. For example, look these threads for similar bug description:
    Problem with GUI_JPEG_DrawScaledEx(GUI_GET_DATA_FUNC * pfGetData, void * p, int x0, int y0, int Num, int Denom)

    LISTVIEW_DeleteRow NOT real free the Row's used memory

    Should I find more examples from LPC forum?

    So, dear Til, at present moment I want you clearly to write me (better on email) that you or your company refuse to provide any support for STemWin. After that, I will say sorry to you personal and to your company here (in this forum) and on my site, and delete my account from this forum.
    I take this paper and together with our company's lawer go to the court and return all money that we had spent on R'n'D.

    B.R. Constantine.
  • Thanks a lot, Shoenen.
    I looked a lot through your comments, you are always very informative and professional.
    Can I realize from your comment now, that I should try to increase _acBuffer? And it maybe will lead to proper behaviour of GUI_BMP_DrawEx() function?

    Does function IMAGE_SetBMPEx() have the same bug?
    As I can assume both these functions have the similar code?

    B.R. Constantine.

    The post was edited 1 time, last by Constantine ().

  • SEGGER - Schoenen wrote:

    We were able to avoid the bug if _acBuffer was big enough to hold one line of the image and the number of bytes read should were equal to the number of bytes required.

    And again, I'm not enginious))
    I have BMP with sizes 300x225, 16bpp. So I should create _acBuffer with size exactly 600bytes?
    Ok. This is pretty clear for me.

    But! When I debug through _GetData function I noticed that first time, ...Ex() function requires 64 bytes from _GetData.
    Is it normal?


    So, tommorow I should try:
    - return to my _GetData function:
    if (NumBytesReq > sizeof(_acBuffer)) //Check buffer size in case of static buffer
    NumBytesReq = sizeof(_acBuffer);



    - and initialize _acBuffer as:
    static U8 _acBuffer [NUM_BYTES_IN_LINE_OF_CURRENT_IMG] = {0};

    B.R. Constantine.
  • Dear Til,
    as I understand you are some kind of licensing specialist.
    As I see from Shoen's replies there is some bug in some old library.

    Could you explain how to initialize process of fixing through STM?
    Should I write them an official letter? Maybe you can initialize this process?
    Do you provide some fixes for old libraries? How all this works between your companies?

    So all my questions lead to simple one: how can I receive fixed library not paying any extra money?

    Cause if my company has to buy new library from your company directly, I definetelly change platform to some cheaper one. (STM's M7 costs more than 20$)
    But it enlarges R'n'D term, that is very unplesant for my boss and may lead for me to be fired. (All R'n'D will be moved to outsource)

    B.R. Constantine.
  • As STM said, STemWin is emWin library that they licensed from segger for its customers.
    This means, that every time I buy MCU from STM, I indirectly pay to STM for emWin library. That is why STM's MCUs cost twice as much than LPC's for example.
    STM provides emWin manual with STemWin library. All functions look completelly the same.

    Sure, from the technical side STemWin and emWin are the same but not from the license side.
    When you buy a ST CPU you get a free license of STemWin and not for emWin.
    Please have a look in the STemWin license agreement which comes with the STemWin download.

    Every time, I try to post message with bug description on STM's forum, they appeal to emWin and to this forum.

    I fully understand this not a good situation for you. Therefore we try to help here as much as possible.

    Could you explain how to initialize process of fixing through STM?
    Should I write them an official letter? Maybe you can initialize this process?
    Do you provide some fixes for old libraries? How all this works between your companies?

    ST builds the STemWin library on their own based on the latest emWin sources.
    In general please contact the ST support.
    But in this case I will try to help you in order to speed up things.

    But it enlarges R'n'D term, that is very unplesant for my boss and may lead for me to be fired. (All R'n'D will be moved to outsource)

    I am pretty sure we will find a solution thereby you can keep your job.
    I will send you an email with my contact details.
    That will make it easier to find a proper solution for you.

    Best regards,
    Til
  • Hi, Shoenen.
    This is just three of 15 that I use.
    All of them I converted from .jpg by myself, so I'm pretty sure that they have 16bpp 300x225.
    Maybe I should try other sizes or bpp?

    Main issue in this case will be, that in final PLC I intend to use images with resolution 560x320.
    I already created GUI for 800x480 display, now I'm debugging some additional functions.
    It will be very sad for me if I will be forced to use another GUI library. It will bury pretty big piece of my job.
    I really hope for some help with my issues.


    B.R. Constantine.
    Files
  • SEGGER - Til wrote:

    ST builds the STemWin library on their own based on the latest emWin sources.
    In general please contact the ST support.
    But in this case I will try to help you in order to speed up things.
    Ok, Til.
    Now I begin to understand what you are trying to explain me. I'm pretty in-fusible)))
    So, you said that STM has source code (C + Asm) of your library that they can change.
    I thought, that STM received complete precompiled libraries from your engineers for every core.
    This means that it is possible to fix this issue, just implementing some heap_4.c-type memory management?

    The post was edited 2 times, last by Constantine ().

  • Ok. Finally I found RTOSless workaround, I tested it, it works fine.


    GUI_Init();
    GUI_Clear();

    uint8_t img_counter = 0;
    while (1) {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    GUI_Exec();
    GUI_TOUCH_Exec();

    GUI_DispStringAt("GUI mem. free:", 0, 230);
    GUI_DispStringAt("Img. num.:", 230, 230);

    Show_img_from_SD("7_300x225_16bpp.bmp");
    img_counter++;
    GUI_DispDecAt((I32) img_counter, 300, 230, 3);
    GUI_DispDecAt((I32) GUI_ALLOC_GetNumFreeBytes(), 90, 230, 6);
    HAL_Delay(500);

    Show_img_from_SD("8_300x225_16bpp.bmp");
    img_counter++;
    GUI_DispDecAt((I32) img_counter, 300, 230, 3);
    GUI_DispDecAt((I32) GUI_ALLOC_GetNumFreeBytes(), 90, 230, 6);
    HAL_Delay(500);

    /*
    * This is workaround of known emWin bug
    * look for this thread:
    * emWin memory management bug. ...Ex() functions.
    */
    if (GUI_ALLOC_GetNumFreeBytes() < 2 * 1024) {
    GUI_DispDecAt((I32) GUI_ALLOC_GetNumFreeBytes(), 90, 230, 6);
    GUI_Exit();
    GUI_Init();
    GUI_DispDecAt((I32) GUI_ALLOC_GetNumFreeBytes(), 90, 230, 6);
    }
    }

    But under RTOS, I can implement couple GUI_Exit -> GUI_Init, but only without image cycling. Together these functions lead to hardFault.

    I'm asking again emWin's engineers (in fifth time) to help me with this couple in FreeRTOS environment.
    I'm pretty sure that they will not found solution that could be applied to current library version.
    But they still ignoring my request, trying to create fix for this bug. This fix I will receive in best case after a half of a year. In present I have library version 5.28 provided by STM, fix will be applied to 5.36d version.
    I can't buy emWin, cause it cost more than I have in a year.
    Pretty good situation. Thanks for help guys. You are acting pretty fair and friendly.
    I hope you will receive your bonus after you create this fix with my participation.

    B.R. Constantine.

    The post was edited 2 times, last by Constantine ().