GUI_Exit() -> GUI_Init() BUG

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

  • GUI_Exit() -> GUI_Init() BUG

    Cause emWin library definitely has a memory allocation bug (look my another thread, take project for live example),
    I am trying to free memory by crude power, I make this inclusion in my code:

    if (GUI_ALLOC_GetNumFreeBytes() < 2 * 1024) {
    GUI_Exit();
    GUI_Init();
    }

    GUI_Exit() works fine, LCD becomes blank.
    But when I try to reinitialize GUI, emWin goes again to function LCD_X_Config and mcu catch hard reset at the attempt of repeated driver configuration:


    void LCD_X_Config(void) {
    GUI_DEVICE *pDevice;
    CONFIG_FLEXCOLOR pConfig = { 0 };
    GUI_PORT_API PortAPI = { 0 };

    // Set display driver and color conversion
    pDevice = GUI_DEVICE_CreateAndLink(GUIDRV_FLEXCOLOR, GUICC_565, 0, 0);

    //Configure driver
    pConfig.Orientation = GUI_SWAP_XY | GUI_MIRROR_X;

    GUIDRV_FlexColor_Config(pDevice, &pConfig); //here it halts because of pDevice= 0x0.

    // Display driver configuration
    LCD_SetSizeEx(0, XSIZE_PHYS, YSIZE_PHYS);
    LCD_SetVSizeEx(0, XSIZE_PHYS, YSIZE_PHYS);

    //Set pointers for write-read hardware function
    PortAPI.pfWrite16_A0 = LCD_set_register;
    PortAPI.pfWrite16_A1 = LCD_write_data;
    PortAPI.pfWriteM16_A1 = LcdWriteDataMultiple;

    PortAPI.pfRead16_A1 = LCD_read_data;
    PortAPI.pfReadM16_A1 = LcdReadDataMultiple;

    // Find the current LCD and initialize GUIDRV
    GUIDRV_FlexColor_SetFunc(pDevice, &PortAPI, GUIDRV_FLEXCOLOR_F66708, GUIDRV_FLEXCOLOR_M16C0B16);

    //Add touch function
    unsigned TouchOrientation = ((GUI_SWAP_XY * LCD_GetSwapXY()) | (GUI_MIRROR_X * LCD_GetMirrorX()));
    GUI_TOUCH_SetOrientation(TouchOrientation);
    /*
    * int GUI_TOUCH_Calibrate(int Coord, int Log0, int Log1, int Phys0, int Phys1);
    * Coord GUI_COORD_X for X-axis, GUI_COORD_Y for Y-axis.
    * Log0 Logical value 0 in pixels.
    * Log1 Logical value 1 in pixels.
    * Phys0 A/D converter value for Log0.
    * Phys1 A/D converter value for Log1.
    */
    GUI_TOUCH_Calibrate(GUI_COORD_X,
    0, YSIZE_PHYS,
    AD_VAL_LOG_0_Y_COORD, AD_VAL_LOG_1_Y_COORD);
    GUI_TOUCH_Calibrate(GUI_COORD_Y,
    0, XSIZE_PHYS,
    AD_VAL_LOG_0_X_COORD, AD_VAL_LOG_1_X_COORD);

    }

    For information:
    My emWin library has version 5.28.

    I looked in manual (p.48) - no any clue for this issue.
    Images
    • 2016-09-27_20-45-55.png

      26.95 kB, 1,234×381, viewed 946 times

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

  • Hello Constantine,

    I can't reproduce this problem with the latest version of emWin.
    When calling these functions in this order GUI_Init() - GUI_Exit() - GUI_Init(), I have always the same amount of memory available after GUI_Init().

    Between version 5.28 and 5.36 there were some changes to GUI_Exit() which might have solved the problem.

    Unfortunately it is not in our hand to keep the libraries provided by other companies up to date.

    Regards,
    Sven
    Please read the forum rules before posting.

    Keep in mind, this is *not* a support forum.
    Our engineers will try to answer your questions between their projects if possible but this can be delayed by longer periods of time.
    Should you be entitled to support you can contact us via our support system: segger.com/ticket/

    Or you can contact us via e-mail.
  • Ok, thanks Sven, I understand.
    But, on present moment I found some additional details by this issue:
    When I reduce size of emWin memory from 20kB to 10kB, I can to way through both function GUI_X_Config() and LCD_X_Config() to the end (without trouble with zero pointer), but final result the same - hardFault. Now it halts somewhere in invisible (indebuggable) part of code. So it seems, that it is some kind of continuation of issue with memory management.

    Now I'm going to try this functions: 1)without FreeRTOS and 2)at the very beginning (before it runs out of memory).
    I will post my results.

    /*
    other thread:
    emWin memory management bug. ...Ex() functions.

    */
  • Yes, Sven, as I expected:
    I add such code like you at the beginning of main:

    ...
    some periph init
    ...
    LCD_init();
    ....

    while (1) {
    GUI_Init();
    GUI_DispStringAt("GUI mem. used:", 0, 0);
    GUI_DispDecAt((I32) GUI_ALLOC_GetNumUsedBytes(), 100, 0, 6);
    GUI_DispStringAt("GUI free mem.:", 0, 10);
    GUI_DispDecAt((I32) GUI_ALLOC_GetNumUsedBytes(), 100, 10, 6);
    GUI_Exit();
    HAL_Delay(1000);
    }
    And it works perfect.
    It faults only when I trying to reinit GUI after it runs out of memory.
    So this is clearly the consequence of memory management issue.

    That is why you can't reproduce such error.

    I will try some other approaches, but will be glad if you give me some additional clues).

    B.R. Constantine.

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

  • Good morning, everyone.

    I think I found source of trouble in this thread.
    Exit-Init couple works great without RTOS and produces hardFault under RTOS.
    Tried to find-out some errors in RTOS implementation, but for me everything looks right:
    file GUI_X_OS.c:


    #include "GUI.h"
    #include "main.h"
    #include "cmsis_os.h"

    static osMutexId osMutex;
    static osSemaphoreId osSemaphore;

    int GUI_X_GetTime(void){
    return ((int) xTaskGetTickCount());
    }

    void GUI_X_Delay(int ms)
    {
    vTaskDelay(ms);
    }

    void GUI_X_Init(void) {
    //LCD_reset();
    //LCD_initialize();
    }

    void GUI_X_ExecIdle(void) {
    }

    void GUI_X_InitOS(void)
    {
    /* Create Mutex lock */
    osMutexDef(MUTEX);

    /* Create the Mutex used by the two threads */
    osMutex = osMutexCreate(osMutex(MUTEX));

    /* Create Semaphore lock */
    osSemaphoreDef(SEM);

    /* Create the Semaphore used by the two threads */
    osSemaphore = osSemaphoreCreate(osSemaphore(SEM), 1);
    }

    void GUI_X_Unlock(void)
    {
    osMutexRelease(osMutex);
    }

    void GUI_X_Lock(void)
    {
    osMutexWait(osMutex, osWaitForever);
    }

    U32 GUI_X_GetTaskId(void)
    {
    return ((U32) osThreadGetId());
    }

    void GUI_X_WaitEvent(void)
    {
    osSemaphoreWait(osSemaphore, osWaitForever);
    }

    void GUI_X_SignalEvent(void)
    {
    osMutexRelease(osSemaphore);
    }

    void GUI_X_Log(const char *s) {}
    void GUI_X_Warn(const char *s) {}
    void GUI_X_ErrorOut(const char *s) {}
  • I've found the source of error in implementation of re-initialization routine.
    GUI_Init after GUI_Exit works fine in FreeRTOS environment until you call for block thread function, in case of CMSIS implementation, it will be osDelay().
    I tried to apply queue, to remove any blocking routines from thread that handles re-initialization, but it doesn't help.
    The idea was pretty simple: the first thread sends in queue number of picture to show, the second tread waits for object in queue, if it appears it unblocks and show picture (number of picture it receives from queue). In this time re-initialization thread is suspended. When emWin runs out of memory, it unblocks reinitialization thread, that contains Exit->Init couple.

    But I can say definitely that when I use thread without blocking routines, for example:

    //implemented for display 320x240

    void Img_cycler_thread(void const * argument) {
    uint8_t img_counter = 0;
    osEvent event;

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

    for (;;) {

    /* Get the message from the queue */
    event = osMessageGet(gateKeeperQueue, portMAX_DELAY); //0 -> no time-out
    if (event.status == osEventMessage) {

    GUI_ClearRect(0, 0, 300, 225);
    Show_img_from_SD(file_name[event.value.v]);

    GUI_DispDecAt((I32) GUI_ALLOC_GetNumFreeBytes(), 90, 230, 6);
    img_counter++;
    GUI_DispDecAt((I32) img_counter, 160+90, 230, 3);
    if (GUI_ALLOC_GetNumFreeBytes() < 2 * 1024) {
    GUI_DispDecAt((I32) GUI_ALLOC_GetNumFreeBytes(), 90, 230, 6);
    taskENTER_CRITICAL();
    GUI_Exit();
    GUI_Init();
    taskEXIT_CRITICAL();
    GUI_DispDecAt((I32) GUI_ALLOC_GetNumFreeBytes(), 90, 230, 6);
    }
    }
    }
    }

    this workaround works good.

    If somebody encountered same emWin's bug, please contact me, maybe together we can achieve better workaround:
    laskov82@gmai.com