HardFault GUI_Draw_PNG (func _Draw)

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

    • HardFault GUI_Draw_PNG (func _Draw)

      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:
      1. move the PNG load to that window's WM_PAINT handler
      2. 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)
      3. 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

      1. GUI_HWIN WMX_CreatehWin(WMX* pX, WMX* pP) {
      2. if (pP > 0) {
      3. pX->hWin = WM_CreateWindowAsChild(
      4. 0, 0, WMX_DEFAULT_WIDTH, WMX_DEFAULT_HEIGHT,
      5. hWinX(pP),
      6. WM_CF_HIDE,
      7. _cb,
      8. sizeof(WMX*));
      9. }
      10. else {
      11. pX->hWin = WM_CreateWindow(
      12. 0, 0, WMX_DEFAULT_WIDTH, WMX_DEFAULT_HEIGHT,
      13. WM_CF_HIDE,
      14. _cb,
      15. sizeof(WMX*));
      16. }
      17. if(pX){
      18. if(pX->hWin){
      19. WM_SetUserData(pX->hWin, &pX, sizeof(WMX*));
      20. }
      21. }
      22. return pX->hWin;
      23. }
      24. static void _default(WMX* this) {
      25. WMX_SETTINGS* pSet = (WMX_SETTINGS*)this->Settings;
      26. WMX_EVENTS* pEV = (WMX_EVENTS*)this->Events;
      27. WMX_PRIVATE* pPrv = (WMX_PRIVATE*)this->Private;
      28. reset(pSet);
      29. reset(pEV);
      30. reset(pPrv);
      31. WMX_Default((WMX*)this);
      32. this->Callback = _cb;
      33. GUI_BorderStyle_SetBorderStyle(&pSet->Panel.Border, 0, GUI_WHITE, 1, 0);
      34. pSet->Panel.Color = GUI_TRANSPARENT;
      35. pSet->Panel.Image.Visible = 1;
      36. WMX_SetBackgroundFromFile(this, ASSETSOURCEPATH "\\Images\\WMX_Bgnd_CoreDiagnostics.jpg", 0);
      37. pSet->Panel.Image.Position.x = 0;
      38. pSet->Panel.Image.Position.y = 0;
      39. pSet->RefreshInterval = WMX_COREDIAGNOSTICS_REFRESHINTERVAL;
      40. WMX_Maximise((WMX*)this);
      41. }
      42. WMX* WMX_CoreDiagnostics_Create(WMX* pParent) {
      43. WMX* this;
      44. this = (WMX*)malloc(sizeof(WMX));
      45. reset(this);
      46. this->Settings = (WMX_SETTINGS*)malloc(sizeof(WMX_SETTINGS));
      47. this->Events = (WMX_EVENTS*)malloc(sizeof(WMX_EVENTS));
      48. this->Private = (WMX_PRIVATE*)malloc(sizeof(WMX_PRIVATE));
      49. WMX_CreatehWin(this, pParent);
      50. _default(this);
      51. WMX_AppHelper_AddButtons(this, _buttonsdef, (WMX_BUTTON**)_buttons, countof(_buttons));
      52. #if 1
      53. osThreadSetPriority (osThreadGetId(), osPriorityRealtime);
      54. WMX_AppHelper_AddImagesFromDisk(this, _imagedef, _hImages, countof(_imagedef));
      55. osThreadSetPriority (osThreadGetId(), osPriorityNormal);
      56. #endif
      57. return this;
      58. }
      59. void WMX_AppHelper_AddImagesFromDisk(WMX* parent, IMAGEFROMDISK_t * imagedef, GUI_MEMDEV_Handle * hImage, uint16_t count) {
      60. while (count--) {
      61. *hImage++ = GUI_ImageManager_Load(&System_ImageList, imagedef->Filename);
      62. imagedef++;
      63. }
      64. }
      65. GUI_MEMDEV_Handle GUI_ImageManager_Load(GUI_ImageManager_t * imagelist, char * filename) {
      66. int xSize;
      67. int ySize;
      68. FILE * file;
      69. uint32_t readlen;
      70. MEMPOOL_ALLOC_RESULT_t mem;
      71. GUI_JPEG_INFO info;
      72. GUI_ImageManager_Entry_t * pImage;
      73. char ftype[MAXSTRLEN];
      74. uint8_t filetype = FTYPE_UNKNOWN;
      75. //try and find it in list
      76. pImage = _find(imagelist, filename);
      77. if (pImage) {
      78. return pImage->hMemDev;
      79. }
      80. //if not found load it
      81. //get empty slot as pList
      82. pImage = _allocate(imagelist);
      83. if (!pImage) {
      84. return 0;
      85. }
      86. pImage->hMemDev = 0;
      87. pImage->Path[0] = cNULL;
      88. FS_GetFiletype(filename, ftype);
      89. if (!strcmp(ftype, "png")) {
      90. #if defined(MDK) && (BUILD_SUPPORT_PNG == BUILD_YES)
      91. filetype = FTYPE_PNG;
      92. #endif
      93. }
      94. else if (!strcmp(ftype, "jpg")) {
      95. filetype = FTYPE_JPEG;
      96. }
      97. if (!filetype) {
      98. return 0;
      99. }
      100. file = FS_FOpen(filename, "rb");
      101. if (file) {
      102. mem = MemPool_X_Alloc(POOL_1MB, POOL_1MB_SIZE);
      103. readlen = FS_FRead(mem.Memory, 1, mem.Size, file);
      104. FS_FClose(file);
      105. if (readlen < mem.Size) {
      106. switch (filetype) {
      107. #ifdef MDK
      108. case FTYPE_PNG:
      109. xSize = GUI_PNG_GetXSize(mem.Memory, readlen);
      110. ySize = GUI_PNG_GetYSize(mem.Memory, readlen);
      111. break;
      112. #endif
      113. case FTYPE_JPEG:
      114. GUI_JPEG_GetInfo(mem.Memory, readlen, &info);
      115. xSize = info.XSize;
      116. ySize = info.YSize;
      117. break;
      118. }
      119. pImage->hMemDev = GUI_MEMDEV_Create(0, 0, xSize, ySize);
      120. if (pImage->hMemDev) {
      121. GUI_MEMDEV_Select(pImage->hMemDev);
      122. switch (filetype) {
      123. #ifdef MDK
      124. case FTYPE_PNG:
      125. GUI_PNG_Draw(mem.Memory, readlen, 0, 0);
      126. break;
      127. #endif
      128. case FTYPE_JPEG:
      129. GUI_JPEG_Draw(mem.Memory, readlen, 0, 0);
      130. break;
      131. }
      132. GUI_MEMDEV_Select(0); //back to LCD
      133. strcpy(pImage->Path, filename);
      134. }
      135. }
      136. MemPool_X_Free(&mem);
      137. }
      138. return pImage->hMemDev;
      139. }
      Display All
    • Hi

      ...just to add that I moved GUI_PNG_Draw such that is is handled by the _cb (WM_USER_DATA). It works fine from there, too. It is just a direct call from the same thread, in same function as hWin was allocated that seems to fail.

      Given that it works fine from WM_USER_DATA I am semi-happy. Only semi- as I am still a little concerned I have just moved the problem to some other place or day.

      Thanks
      Mark