Hi
I'm getting a HardFault when I load a PNG as part of my window create code. I do not get this crash if I do one of these:
I tried a simple osDelay(1000ms) before the PNG_Draw (to force a long yield). This did not work.
I have tried PNG 5.28, 5.46, 5.48. All faulted. My proving tests (1-3, above) were with 5.46. emWin core is 5.46.5.
I tried commenting out the GUI_WINSUPPORT sections in _Draw (I did not recompile guilib as I cannot: GUI_WINSUPPORT is compiled into the MDK-released lib as 1).
I HAVE NOT tried using a background thread (ie not the emWin thread) load all of my PNG memory objects. It is possible that this would cure the problem but I would still hope to have a resolution (or comment at least).
The crash is happening in the drawing loop within _Draw. It is not crashing in the same spot in that function leading me to consider something in an external (ie not my code) thread or timer as the problem. I cannot work out what it could be as both the create and paint run from the same thread. I have only a single thread handling all emWin. My task has plenty of stack (only 56 of 120000 used at call to _Draw), and emWin has plenty of resources (around 13MB with, I expect, 10-12MB available at the time of crash).
Code is below
Thanks
Mark
------
My create() function is my WMX_CoreDiagnostics_Create (see code). The GUI_PNG_Draw is accessed from GUI_ImageManager_Load which is called from WMX_AppHelper_AddImagesFromDisk (see below).
My PNG_Draw is in my func just after I get a new hWin. It is NOT in a WM_CREATE handler as I still need to port to using WM_USER_DATA.
GUI_ImageManager_Load first loads the entire file to a locked memory area. This locked memory area is not only locked: it is only used by this function in my application and this function is only accessed within the single emWin thread. I have confirmed (by bkpt) that there is only 1 instance of my GUI_ImageManager_Load active when the fault occurs.
Display All
I'm getting a HardFault when I load a PNG as part of my window create code. I do not get this crash if I do one of these:
- move the PNG load to that window's WM_PAINT handler
- avoid thread-release in the create() function by changing the thread priority (RTX5) to my highest before calling the PNG_Draw (I then set it back to my emWin normal)
- use JPEG (my loader func handles both, proving out my core functionality and localizing this to something odd with GUI_PNG_Draw)
I tried a simple osDelay(1000ms) before the PNG_Draw (to force a long yield). This did not work.
I have tried PNG 5.28, 5.46, 5.48. All faulted. My proving tests (1-3, above) were with 5.46. emWin core is 5.46.5.
I tried commenting out the GUI_WINSUPPORT sections in _Draw (I did not recompile guilib as I cannot: GUI_WINSUPPORT is compiled into the MDK-released lib as 1).
I HAVE NOT tried using a background thread (ie not the emWin thread) load all of my PNG memory objects. It is possible that this would cure the problem but I would still hope to have a resolution (or comment at least).
The crash is happening in the drawing loop within _Draw. It is not crashing in the same spot in that function leading me to consider something in an external (ie not my code) thread or timer as the problem. I cannot work out what it could be as both the create and paint run from the same thread. I have only a single thread handling all emWin. My task has plenty of stack (only 56 of 120000 used at call to _Draw), and emWin has plenty of resources (around 13MB with, I expect, 10-12MB available at the time of crash).
Code is below
Thanks
Mark
------
My create() function is my WMX_CoreDiagnostics_Create (see code). The GUI_PNG_Draw is accessed from GUI_ImageManager_Load which is called from WMX_AppHelper_AddImagesFromDisk (see below).
My PNG_Draw is in my func just after I get a new hWin. It is NOT in a WM_CREATE handler as I still need to port to using WM_USER_DATA.
GUI_ImageManager_Load first loads the entire file to a locked memory area. This locked memory area is not only locked: it is only used by this function in my application and this function is only accessed within the single emWin thread. I have confirmed (by bkpt) that there is only 1 instance of my GUI_ImageManager_Load active when the fault occurs.
Source Code
- GUI_HWIN WMX_CreatehWin(WMX* pX, WMX* pP) {
- if (pP > 0) {
- pX->hWin = WM_CreateWindowAsChild(
- 0, 0, WMX_DEFAULT_WIDTH, WMX_DEFAULT_HEIGHT,
- hWinX(pP),
- WM_CF_HIDE,
- _cb,
- sizeof(WMX*));
- }
- else {
- pX->hWin = WM_CreateWindow(
- 0, 0, WMX_DEFAULT_WIDTH, WMX_DEFAULT_HEIGHT,
- WM_CF_HIDE,
- _cb,
- sizeof(WMX*));
- }
- if(pX){
- if(pX->hWin){
- WM_SetUserData(pX->hWin, &pX, sizeof(WMX*));
- }
- }
- return pX->hWin;
- }
- static void _default(WMX* this) {
- WMX_SETTINGS* pSet = (WMX_SETTINGS*)this->Settings;
- WMX_EVENTS* pEV = (WMX_EVENTS*)this->Events;
- WMX_PRIVATE* pPrv = (WMX_PRIVATE*)this->Private;
- reset(pSet);
- reset(pEV);
- reset(pPrv);
- WMX_Default((WMX*)this);
- this->Callback = _cb;
- GUI_BorderStyle_SetBorderStyle(&pSet->Panel.Border, 0, GUI_WHITE, 1, 0);
- pSet->Panel.Color = GUI_TRANSPARENT;
- pSet->Panel.Image.Visible = 1;
- WMX_SetBackgroundFromFile(this, ASSETSOURCEPATH "\\Images\\WMX_Bgnd_CoreDiagnostics.jpg", 0);
- pSet->Panel.Image.Position.x = 0;
- pSet->Panel.Image.Position.y = 0;
- pSet->RefreshInterval = WMX_COREDIAGNOSTICS_REFRESHINTERVAL;
- WMX_Maximise((WMX*)this);
- }
- WMX* WMX_CoreDiagnostics_Create(WMX* pParent) {
- WMX* this;
- this = (WMX*)malloc(sizeof(WMX));
- reset(this);
- this->Settings = (WMX_SETTINGS*)malloc(sizeof(WMX_SETTINGS));
- this->Events = (WMX_EVENTS*)malloc(sizeof(WMX_EVENTS));
- this->Private = (WMX_PRIVATE*)malloc(sizeof(WMX_PRIVATE));
- WMX_CreatehWin(this, pParent);
- _default(this);
- WMX_AppHelper_AddButtons(this, _buttonsdef, (WMX_BUTTON**)_buttons, countof(_buttons));
- #if 1
- osThreadSetPriority (osThreadGetId(), osPriorityRealtime);
- WMX_AppHelper_AddImagesFromDisk(this, _imagedef, _hImages, countof(_imagedef));
- osThreadSetPriority (osThreadGetId(), osPriorityNormal);
- #endif
- return this;
- }
- void WMX_AppHelper_AddImagesFromDisk(WMX* parent, IMAGEFROMDISK_t * imagedef, GUI_MEMDEV_Handle * hImage, uint16_t count) {
- while (count--) {
- *hImage++ = GUI_ImageManager_Load(&System_ImageList, imagedef->Filename);
- imagedef++;
- }
- }
- GUI_MEMDEV_Handle GUI_ImageManager_Load(GUI_ImageManager_t * imagelist, char * filename) {
- int xSize;
- int ySize;
- FILE * file;
- uint32_t readlen;
- MEMPOOL_ALLOC_RESULT_t mem;
- GUI_JPEG_INFO info;
- GUI_ImageManager_Entry_t * pImage;
- char ftype[MAXSTRLEN];
- uint8_t filetype = FTYPE_UNKNOWN;
- //try and find it in list
- pImage = _find(imagelist, filename);
- if (pImage) {
- return pImage->hMemDev;
- }
- //if not found load it
- //get empty slot as pList
- pImage = _allocate(imagelist);
- if (!pImage) {
- return 0;
- }
- pImage->hMemDev = 0;
- pImage->Path[0] = cNULL;
- FS_GetFiletype(filename, ftype);
- if (!strcmp(ftype, "png")) {
- #if defined(MDK) && (BUILD_SUPPORT_PNG == BUILD_YES)
- filetype = FTYPE_PNG;
- #endif
- }
- else if (!strcmp(ftype, "jpg")) {
- filetype = FTYPE_JPEG;
- }
- if (!filetype) {
- return 0;
- }
- file = FS_FOpen(filename, "rb");
- if (file) {
- mem = MemPool_X_Alloc(POOL_1MB, POOL_1MB_SIZE);
- readlen = FS_FRead(mem.Memory, 1, mem.Size, file);
- FS_FClose(file);
- if (readlen < mem.Size) {
- switch (filetype) {
- #ifdef MDK
- case FTYPE_PNG:
- xSize = GUI_PNG_GetXSize(mem.Memory, readlen);
- ySize = GUI_PNG_GetYSize(mem.Memory, readlen);
- break;
- #endif
- case FTYPE_JPEG:
- GUI_JPEG_GetInfo(mem.Memory, readlen, &info);
- xSize = info.XSize;
- ySize = info.YSize;
- break;
- }
- pImage->hMemDev = GUI_MEMDEV_Create(0, 0, xSize, ySize);
- if (pImage->hMemDev) {
- GUI_MEMDEV_Select(pImage->hMemDev);
- switch (filetype) {
- #ifdef MDK
- case FTYPE_PNG:
- GUI_PNG_Draw(mem.Memory, readlen, 0, 0);
- break;
- #endif
- case FTYPE_JPEG:
- GUI_JPEG_Draw(mem.Memory, readlen, 0, 0);
- break;
- }
- GUI_MEMDEV_Select(0); //back to LCD
- strcpy(pImage->Path, filename);
- }
- }
- MemPool_X_Free(&mem);
- }
- return pImage->hMemDev;
- }