GUI_Init() Infinite Loop

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

    • GUI_Init() Infinite Loop

      Hello,

      I made a custom board using the stm32f407 microcontroller, a 480x272 tft display with the SSD1963 controller, and an external sram chip IS61WV102416BLL.
      Without emWin,
      - I confirmed that I can display an image on the display
      - Write and read back 32-bit data to and from the sram

      The problem is, I am trying to use emWin for the first time with embOS, and I get stuck in an infinite loop after calling GUI_Init(). Using the debugger I found out that I am stuck in an interrupt handler (CAN1_RX1_IRQHandler) after GUIDRV_FlexColor_SetMode16bppC1B16() is called.

      I am not really sure which direction to take to debug this issue. Nowhere in my code do I explicitly enable interrupts (so nothing related to the CAN bus).
      Any help would be appreciated.
      Please let me know if there is any question, thank you.

      main.c

      C Source Code

      1. static OS_STACKPTR int stack_display[768]; /* Task stack */
      2. static OS_TASK tcb_display; /* Task-control-block */
      3. int main(void)
      4. {
      5. OS_Init(); // Initialize embOS
      6. OS_InitHW(); // Initialize required hardware
      7. BSP_Init(); // Initialize LED ports
      8. OS_CREATETASK(&tcb_display, "maintask_display", maintask_display, 100, stack_display);
      9. OS_Start(); // Start embOS
      10. return 0;
      11. }
      Display All



      LCDConf.c

      C Source Code

      1. /*********************************************************************
      2. *
      3. * LCD_X_Config
      4. *
      5. * Function description:
      6. * Called during the initialization process in order to set up the
      7. * display driver configuration.
      8. *
      9. */
      10. void LCD_X_Config(void)
      11. {
      12. GUI_DEVICE * pDevice;
      13. CONFIG_FLEXCOLOR pConfig = { 0, 0, 0, 0, -1 };
      14. GUI_PORT_API PortAPI = {0};
      15. //
      16. // Set display driver and color conversion
      17. //
      18. pDevice = GUI_DEVICE_CreateAndLink(GUIDRV_FLEXCOLOR, GUICC_565, 0, 0);
      19. //
      20. // Configure driver's orientation
      21. //
      22. pConfig.Orientation = GUI_MIRROR_X;
      23. // pConfig.Orientation = GUI_SWAP_XY | GUI_MIRROR_Y;
      24. GUIDRV_FlexColor_Config(pDevice, &pConfig);
      25. //
      26. // Display driver configuration, required for Lin-driver
      27. //
      28. LCD_SetSizeEx (0, XSIZE_PHYS, YSIZE_PHYS);
      29. LCD_SetVSizeEx(0, VXSIZE_PHYS, VYSIZE_PHYS);
      30. //
      31. // Set controller and operation mode
      32. //
      33. PortAPI.pfWrite16_A0 = ssd1963_WriteReg;
      34. PortAPI.pfWrite16_A1 = ssd1963_WriteData;
      35. PortAPI.pfWriteM16_A1 = ssd1963_WriteDataMultiple;
      36. PortAPI.pfRead16_A1 = ssd1963_ReadData;
      37. PortAPI.pfReadM16_A1 = ssd1963_ReadDataMultiple;
      38. // GUIDRV_FlexColor_SetReadFunc66720_B16(pDevice, GUIDRV_FLEXCOLOR_READ_FUNC_II);
      39. GUIDRV_FlexColor_SetFunc(pDevice, &PortAPI, GUIDRV_FLEXCOLOR_F66720, GUIDRV_FLEXCOLOR_M16C1B16);
      40. }
      41. /*********************************************************************
      42. *
      43. * LCD_X_DisplayDriver
      44. *
      45. * Function description:
      46. * This function is called by the display driver for several purposes.
      47. * To support the according task the routine needs to be adapted to
      48. * the display controller. Please note that the commands marked with
      49. * 'optional' are not cogently required and should only be adapted if
      50. * the display controller supports these features.
      51. *
      52. * Parameter:
      53. * LayerIndex - Index of layer to be configured
      54. * Cmd - Please refer to the details in the switch statement below
      55. * pData - Pointer to a LCD_X_DATA structure
      56. *
      57. * Return Value:
      58. * < -1 - Error
      59. * -1 - Command not handled
      60. * 0 - Ok
      61. */
      62. int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void * pData)
      63. {
      64. int r;
      65. (void) LayerIndex;
      66. (void) pData;
      67. switch (Cmd)
      68. {
      69. case LCD_X_INITCONTROLLER:
      70. {
      71. ssd1963_Init();
      72. return 0;
      73. }
      74. default:
      75. r = -1;
      76. }
      77. return r;
      78. }
      Display All

      GUIConf.c

      C Source Code

      1. #include "GUI.h"
      2. #include "BSP_GUI.h"
      3. #include "PIDConf.h"
      4. /*********************************************************************
      5. *
      6. * Defines
      7. *
      8. **********************************************************************
      9. */
      10. //
      11. // Define the available number of bytes available for the GUI
      12. //
      13. #define GUI_NUMBYTES 0x400
      14. #if (defined __ICCARM__) // IAR
      15. static __no_init U32 aMemory[GUI_NUMBYTES / 4] @ ".GUI_RAM";
      16. #elif (defined __SES_ARM) // SES
      17. static U32 aMemory[GUI_NUMBYTES / 4] __attribute__ ((section (".GUI_RAM")));
      18. #else
      19. static U32 aMemory[GUI_NUMBYTES / 4];
      20. #endif
      21. /*********************************************************************
      22. *
      23. * Static code
      24. *
      25. **********************************************************************
      26. */
      27. /*********************************************************************
      28. *
      29. * Public code
      30. *
      31. **********************************************************************
      32. */
      33. /*********************************************************************
      34. *
      35. * GUI_X_Config
      36. *
      37. * Purpose:
      38. * Called during the initialization process in order to set up the
      39. * available memory for the GUI.
      40. */
      41. void GUI_X_Config(void)
      42. {
      43. //
      44. // Assign memory to emWin
      45. //
      46. GUI_ALLOC_AssignMemory(aMemory, GUI_NUMBYTES);
      47. //
      48. // Set default font
      49. //
      50. GUI_SetDefaultFont(GUI_FONT_6X8);
      51. //
      52. // Init touch
      53. //
      54. //#ifndef _WINDOWS
      55. // GUI_PID_SetInitFunc(PID_X_Init);
      56. //#endif
      57. }
      Display All

      And .GUI_RAM lives in the SRAM.

      HTML Source Code

      1. <MemorySegment name="$(ExtSRAM_NAME:ExtSRAM)" >
      2. <ProgramSection alignment="4" load="No" name=".GUI_RAM" />
      3. </MemorySegment>




      Project specs:
      Environment: Segger Embedded Studio
      Microcontroller: stm32f407
      Display driver: SSD1963
      SRAM: IS61WV102416BLL
      Heap Size: 1024 Bytes
      Main Stack Size: 1024 Bytes
      Process Stack Size: 0 Bytes
    • Hi,

      emWin doesn't make use of hardware specific code. The only file where hardware gets initialised is LCDConf.c. Any other parts of emWin are completely independent of any hardware.

      You are calling ssd1963_Init() and other ssd1963 related functions. Maybe there is something inside which initializes a interrupt.

      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.
    • SEGGER - Schoenen wrote:

      Hi,

      emWin doesn't make use of hardware specific code. The only file where hardware gets initialised is LCDConf.c. Any other parts of emWin are completely independent of any hardware.

      You are calling ssd1963_Init() and other ssd1963 related functions. Maybe there is something inside which initializes a interrupt.

      Regards,
      Sven
      The infinite loop happens before ssd1963_Init() is even called.
      It seems to occur right after GUIDRV_FlexColor_SetFunc(pDevice, &PortAPI, GUIDRV_FLEXCOLOR_F66720, GUIDRV_FLEXCOLOR_M16C1B16) is called according to the call stack.

      I tried calling __disable_irq() before calling GUI_Init() in case something else was turning on that interrupt but no luck.
    • Hello,

      I apologize for the long delay.
      After configuring my project settings to match the emWin sample project for STM3240G_EVAL, I have a different issue which is also causing a hardfault.
      If I configure GUI_NUMBYTES to be any value greater than 1223 bytes, I have a hardfault when executing this line

      C Source Code

      1. pDevice = GUI_DEVICE_CreateAndLink(GUIDRV_FLEXCOLOR, GUICC_565, 0, 0);
      and the corresponding call stack is:
      GUI_ALLOC_GetFixedBlock() -> _AddFreeMemory() -> HardFault_Handler()

      Any idea what this failure could be related to?
      Thank you
    • This all sounds to me like you are running out of memory, I too am using a custom board I made myself, with an STM32H7, using emWin, and SES.

      (I posted my startup files I put together for the STM32H7, with all the memory placement and flash placement .xml files, in a thread in the SES forum.)


      Hardfaults will happen easily if you run out of memory, have memory corruption issues, bad pointers, etc..

      1) Check what memory region your stack/heap is assigned to? (ie in the flash_placement.xml)


      2) You need a decent size of memory for emWin, I give it a pool of about 200kB currently, and it's using approx 50kB or so at any one time...

      I'm not entirely familiar with the STM32Fxxx family, so I don't know if it's RAM is all segmented up like the STM32Hxxx series is? but for me, I put my stack/heap into the AXISRAM, since that is the largest contiguous block, at 512kB.

      And there's other smaller RAM areas that I use for other scratch ram and things, you can do all of this in SES if you need to place certain memories or things around, like the emWin..you can tell the compiler to place that 'aMemory[]' array into a certain RAM if you need to...
    • Hi MikeFlyersFan,

      Thank you for your reply.

      1) My stack and heap are located on the internal SRAM (192 +4Kb) which matches the memory segment of the sample project which uses a similar microcontroller with the same memory segments/sizes (stm32f407 vs. stm32f417)

      2) For my project, I am planning on allocating 1Mb of memory for emWin. I just happened to notice that passed 1223 bytes of memory for emWin, the hardfault starts to occur.

      I am using an 2Mb external SRAM chip located at address 0x64000000 which is where is placed aMemory[].
      I suspect memory issue as well but after trying multiple options (matching memory layout of sample project, confirming that I can read/write from and to external SRAM chip), I am a little confused as to where to look.
      I included a few more information about my system in the OP.

      I really appreciate the suggestions, and I am open to trying anything at this point.
      Thanks
    • Ok,

      Just to eliminate things I would move your aMemory to an internal sram, do you have any other sram banks on that chip you can use?

      I too was using that particular SRAM chip on my board, but ended up needing much more ram for a frame buffer (as the STM32H7 has the LTDC controller, hence the need for a frame buffer).... I didn't really have any issues with it, but I never tried to put emWin memory in it either.

      also push your SES stack/heap sizes up as well if you can.. I think I have mine at 4kB right now...

      (as of right now my aMemory is still in my AXISRAM along with the stack/heap.. but if my emWin usage gets higher, I'll move it to another internal ram bank)


      - Mike
    • Thanks for the suggestions.

      After moving .GUI_RAM (where aMemory[] is stored) to internal SRAM and increasing GUI_NUMBYTES to 64kB, I get emWin to initialize and display some text on the display.
      It looks like accessing memory on my external SRAM seems to be the issue. Maybe there is some FSMC timing that I am not respecting. The sample project that I based my project off uses the same SRAM chip and I thought using the same configuration would be sufficient. Do you still have the timings that you used in your previous project? (address setup time, etc..)
      I will once again go over the configuration of my FSMC peripheral (including pin configurations) and update the thread if I find something unusual.

      I really appreciate your help.
    • Hi,

      awesome, glad to hear it's working... yeah, you could be running into timing issues, or maybe even caching issues with the sram?

      in the STM examples (in particular emWin ones) you'll see STMicro usually calls the 'MPU_Config()' function, which sets their external SRAM (or SDRAM) device to be 'WRITE-THROUGH' so that they don't have stale data in the cache that hasn't been flushed to ram...

      this normally is because they are using the external memory for a frame buffer, but could be a similar issue with your setup? may be worth a try just adding that function, see if cacheing is what is messing you up? pretty simple to copy their function and set it up for your sram memory region..

      I didn't have to change the timings in my setup, as I too was using that same SRAM part, so I could just copy the timing from their examples... ie in the SRAM example in the cubemx package, the timing was in there, and it seemed ok..

      - Mike

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

    • Hi,

      I haven't had too much time to work on this project lately, but I just wanted to give an update.
      I have tried calling MPU_Config() before initializing the GUI but with no success.
      My implementation of MPU_Config can be found below:

      C Source Code

      1. void MPU_Config(void)
      2. {
      3. MPU_Region_InitTypeDef MPU_InitStruct;
      4. /* Disable the MPU */
      5. HAL_MPU_Disable();
      6. MPU_InitStruct.Enable = MPU_REGION_ENABLE;
      7. MPU_InitStruct.BaseAddress = 0x64000000;
      8. MPU_InitStruct.Size = MPU_REGION_SIZE_2MB;
      9. MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
      10. MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
      11. MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
      12. MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
      13. MPU_InitStruct.Number = MPU_REGION_NUMBER1;
      14. MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
      15. MPU_InitStruct.SubRegionDisable = 0x00;
      16. MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;
      17. HAL_MPU_ConfigRegion(&MPU_InitStruct);
      18. /* Enable the MPU */
      19. HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
      20. }
      Display All
      I am still investigating the issue and I will update the thread with progress that I make. In the mean time, I am still open for suggestions.
      Thank you