Wednesday, November 22nd 2017, 6:12am UTC+1

You are not logged in.

  • Login
  • Register

Dear visitor, welcome to SEGGER Forum. If this is your first visit here, please read the Help. It explains how this page works. You must be registered before you can use all the page's features. Please use the registration form, to register here or read more information about the registration process. If you are already registered, please login here.

Constantine

Beginner

Date of registration: Sep 1st 2016

Posts: 29

Location: Moscow

Occupation: Finding workarounds for multiple emWin bugs. I am became a professional at this.

1

Tuesday, September 27th 2016, 12:31pm

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:
https://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.

SEGGER - Schoenen

Super Moderator

Date of registration: Aug 13th 2015

Posts: 410

2

Tuesday, September 27th 2016, 2:49pm

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

SEGGER - Til

Super Moderator

Date of registration: Nov 14th 2007

Posts: 261

3

Tuesday, September 27th 2016, 4:40pm

Quoted

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

Constantine

Beginner

Date of registration: Sep 1st 2016

Posts: 29

Location: Moscow

Occupation: Finding workarounds for multiple emWin bugs. I am became a professional at this.

4

Tuesday, September 27th 2016, 11:17pm

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.

Constantine

Beginner

Date of registration: Sep 1st 2016

Posts: 29

Location: Moscow

Occupation: Finding workarounds for multiple emWin bugs. I am became a professional at this.

5

Tuesday, September 27th 2016, 11:25pm

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.

This post has been edited 1 times, last edit by "Constantine" (Sep 27th 2016, 11:29pm)


Constantine

Beginner

Date of registration: Sep 1st 2016

Posts: 29

Location: Moscow

Occupation: Finding workarounds for multiple emWin bugs. I am became a professional at this.

6

Tuesday, September 27th 2016, 11:52pm

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.

Constantine

Beginner

Date of registration: Sep 1st 2016

Posts: 29

Location: Moscow

Occupation: Finding workarounds for multiple emWin bugs. I am became a professional at this.

7

Wednesday, September 28th 2016, 12:03am

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.

Constantine

Beginner

Date of registration: Sep 1st 2016

Posts: 29

Location: Moscow

Occupation: Finding workarounds for multiple emWin bugs. I am became a professional at this.

8

Wednesday, September 28th 2016, 12:07am

Else one, Shoen.
Could you look my another thread:
GUI_Exit() -> GUI_Init() BUG


For many engineers in my situation it could be suitable solution to reinit GUI.
In any case GUI is not the main part of real-time application. It is possible to have 0.5 sec gap in it.

B.R. Constantine.

Constantine

Beginner

Date of registration: Sep 1st 2016

Posts: 29

Location: Moscow

Occupation: Finding workarounds for multiple emWin bugs. I am became a professional at this.

9

Wednesday, September 28th 2016, 9:38am

Good morning, Shoenen.
I tried what you offered yesterday, it doesn't help - please look my implementation.
Constantine has attached the following image:
  • 2016-09-28_10-35-45.png

SEGGER - Til

Super Moderator

Date of registration: Nov 14th 2007

Posts: 261

10

Wednesday, September 28th 2016, 9:54am

Quoted

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.

Quoted

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.

Quoted

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.

Quoted

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

SEGGER - Schoenen

Super Moderator

Date of registration: Aug 13th 2015

Posts: 410

11

Wednesday, September 28th 2016, 11:27am

Hi Constantine,

can you attach the BMP file you want to display?

How did you created the file?

Regards,
Sven

Constantine

Beginner

Date of registration: Sep 1st 2016

Posts: 29

Location: Moscow

Occupation: Finding workarounds for multiple emWin bugs. I am became a professional at this.

12

Wednesday, September 28th 2016, 4:35pm

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.
Constantine has attached the following files:

Constantine

Beginner

Date of registration: Sep 1st 2016

Posts: 29

Location: Moscow

Occupation: Finding workarounds for multiple emWin bugs. I am became a professional at this.

13

Wednesday, September 28th 2016, 4:55pm

How did you created the file?
I used this converter:
http://www.easy2convert.com/jpg2bmp/

If it could be the cause of issue I will try to convert it using Photoshop.
Our advertisement section has a license.

Constantine

Beginner

Date of registration: Sep 1st 2016

Posts: 29

Location: Moscow

Occupation: Finding workarounds for multiple emWin bugs. I am became a professional at this.

14

Wednesday, September 28th 2016, 5:05pm

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?

This post has been edited 2 times, last edit by "Constantine" (Sep 28th 2016, 6:03pm)


Constantine

Beginner

Date of registration: Sep 1st 2016

Posts: 29

Location: Moscow

Occupation: Finding workarounds for multiple emWin bugs. I am became a professional at this.

15

Thursday, September 29th 2016, 10:45am

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.

This post has been edited 2 times, last edit by "Constantine" (Sep 29th 2016, 2:32pm)


Constantine

Beginner

Date of registration: Sep 1st 2016

Posts: 29

Location: Moscow

Occupation: Finding workarounds for multiple emWin bugs. I am became a professional at this.

16

Wednesday, October 12th 2016, 5:19pm

Dear friends!
I replaced emWin in my project by uGFX.
It is nearly free and pretty reliable:
https://community.ugfx.io/topic/422-exte…e/#comment-3099

And everything works fine.
I offer this like workaround of this bug.
B.R. Constantine.