Increase page change performance on application with no external RAM

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

    • Increase page change performance on application with no external RAM

      Hello,

      I'm setting up a GUI application sample with STemWin on a custom board with an STM32F401 microcontroller which controls a display that mounts its controller (ST7789v) and I've managed to print on a screen the classic "Hello world" example.
      The board doesn't have any external RAM for frame buffering so only the available memory is the internal RAM (about 64KB, it will only be used for the libraries, not enough space for a complete frame) and the internal display device memory.
      Since the display controller is communicating with Intel 8080 I have setup the LCD_X_Config as:

      Source Code

      1. void LCD_X_Config(void)
      2. {
      3. GUI_DEVICE * pDevice;
      4. CONFIG_FLEXCOLOR Config = {0};
      5. GUI_PORT_API PortAPI = {0};
      6. //
      7. // Set display driver and color conversion
      8. //
      9. pDevice = GUI_DEVICE_CreateAndLink(GUIDRV_FLEXCOLOR, GUICC_M565, 0, 0);
      10. //
      11. // Display driver configuration, required for Lin-driver
      12. //
      13. LCD_SetSizeEx (0, XSIZE_PHYS , YSIZE_PHYS);
      14. LCD_SetVSizeEx(0, VXSIZE_PHYS, VYSIZE_PHYS);
      15. //
      16. // Orientation
      17. //
      18. #if (NUM_BUFFERS > 1)
      19. GUI_MULTIBUF_ConfigEx(0, NUM_BUFFERS);
      20. #endif
      21. GUIDRV_FlexColor_Config(pDevice, &Config);
      22. //
      23. // Set controller and operation mode
      24. //
      25. PortAPI.pfWrite16_A0 = LcdWriteReg;
      26. PortAPI.pfWrite16_A1 = LcdWriteData;
      27. PortAPI.pfWriteM16_A1 = LcdWriteDataMultiple;
      28. PortAPI.pfReadM16_A1 = LcdReadDataMultiple;
      29. GUIDRV_FlexColor_SetFunc(pDevice, &PortAPI, GUIDRV_FLEXCOLOR_F66709, GUIDRV_FLEXCOLOR_M16C0B16);
      30. }
      Display All

      With the implementation of the top level functions:

      Source Code

      1. /********************************************************************
      2. *
      3. * LcdWriteReg
      4. *
      5. * Function description:
      6. * Sets display register
      7. */
      8. static void LcdWriteReg(U16 Data)
      9. {
      10. LCD_X_8080_16_Write00_16(Data);
      11. }
      12. /********************************************************************
      13. *
      14. * LcdWriteData
      15. *
      16. * Function description:
      17. * Writes a value to a display register
      18. */
      19. static void LcdWriteData(U16 Data)
      20. {
      21. LCD_X_8080_16_Write01_16(Data);
      22. }
      23. /********************************************************************
      24. *
      25. * LcdWriteDataMultiple
      26. *
      27. * Function description:
      28. * Writes multiple values to a display register.
      29. */
      30. static void LcdWriteDataMultiple(U16 * pData, int NumItems)
      31. {
      32. while (NumItems--)
      33. {
      34. LCD_X_8080_16_WriteM01_16(pData, NumItems);
      35. pData++;
      36. }
      37. }
      38. /********************************************************************
      39. *
      40. * LcdReadDataMultiple
      41. *
      42. * Function description:
      43. * Reads multiple values from a display register.
      44. */
      45. static void LcdReadDataMultiple(U16 * pData, int NumItems)
      46. {
      47. while (NumItems--)
      48. {
      49. LCD_X_8080_16_ReadM01_16(pData, NumItems);
      50. pData++;
      51. }
      52. }
      Display All
      And the lower level functions which basically control the pins of the interface (DCX, CS, WRX, Data).

      First frame is shown correctly on the display and it takes a very short time to draw the entire page.
      The problem arises when I want to change something or when I simply want to change the color of the background like:

      Source Code

      1. GUI_SetBkColor(GUI_RED);
      2. GUI_Clear();
      This leads to a very slow refresh of the page with a visible redrawing of the display from the top to the bottom (it takes a couple of seconds).

      Is it possible to improve this behavior (am I missing something?) and which is the best solution to develop a GUI with different pages for targets with no frame buffer like this?

      Thank you!

      Mark
    • Hi Mark,

      The LCD_X_8080 functions, do they use bit banging (toggling the IO pins of the MCU) or do these functions use a dedicated hardware module (e.g. a 8080 module on the MCU)?

      Bit banging is pretty slow and will cause a visible build up on the screen. I recommend to use a hardware module for this.

      Please note, it is not necessary to use an 8080 interface with this driver. You could also use SPI for example. Of course, this depends on the available interfaces of the LCD controller.

      Regards,
      Sven
    • SEGGER - Schoenen wrote:

      Hi Mark,

      The LCD_X_8080 functions, do they use bit banging (toggling the IO pins of the MCU) or do these functions use a dedicated hardware module (e.g. a 8080 module on the MCU)?

      Bit banging is pretty slow and will cause a visible build up on the screen. I recommend to use a hardware module for this.

      Please note, it is not necessary to use an 8080 interface with this driver. You could also use SPI for example. Of course, this depends on the available interfaces of the LCD controller.

      Regards,
      Sven
      Hi Sven,

      thank you for your quick answer.

      The LCD_X_8080 functions use bit-banging, I'm not sure I have other options with this hardware, it is the first time I use this kind of displays with internal memory.
      Here it is one of the functions as an example:

      Source Code

      1. /*********************************************************************
      2. *
      3. * LCD_X_8080_16_OutData
      4. *
      5. * Purpose:
      6. * Write data out
      7. */
      8. void LCD_X_8080_16_OutData(U16 data) {
      9. // from bit 0 to bit 12
      10. GPIOA->ODR = data;
      11. // from 13 to 15
      12. GPIOB->ODR = (data >> 13);
      13. }
      14. /*********************************************************************
      15. *
      16. * LCD_X_8080_16_Write00_16
      17. *
      18. * Purpose:
      19. * Write to controller, with A0 = 0 (Command)
      20. */
      21. void LCD_X_8080_16_Write00_16(U16 c) {
      22. //DISPLAY_DCX_LOW;
      23. //DISPLAY_CS_LOW;
      24. //DISPLAY_WRX_LOW;
      25. DCX_GPIO_Port->BSRR = (uint32_t)DCX_Pin << 16U;
      26. CS_GPIO_Port->BSRR = (uint32_t)CS_Pin << 16U;
      27. WRX_GPIO_Port->BSRR = (uint32_t)WRX_Pin << 16U;
      28. LCD_X_8080_16_OutData(c);
      29. //DISPLAY_WRX_HI;
      30. //DISPLAY_CS_HI;
      31. WRX_GPIO_Port->BSRR = WRX_Pin;
      32. CS_GPIO_Port->BSRR = CS_Pin;
      33. }
      Display All
      In the meantime I set-up the "DrawPolygon sample" and both the first drawing of the page and the update of single polygon are OK.
      If I increase the area of the Rect to be redrawn the slow redrawing appears again.


      Source Code

      1. y = 90;
      2. ...
      3. // Display resolution is 240x320
      4. GUI_ClearRect(100, y, 220, y + 85);
      5. //GUI_ClearRect(0, 0, 240, 320); -> This will lead to the slow redrawing
      6. GUI_SetColor(GUI_BLUE);
      7. GUI_FillPolygon (&_aPointArrow[0], 7, X_START, y + 80);
      8. ...

      Do you have any other suggestions to avoid this effect to happen?

      Does the usage of Window manager makes the redrawing operations more efficient?

      Thanks a lot!

      Mark
    • Hello,

      one of the boards I work with is also a device with STM32F207 (120MHz, 128 kB SRAM) MCU and 240x320 LCD with ILI9341 controller using 16-bit 8080I bus. No external ram. No cache for display driver. Not much "faster" system than yours.

      Check the following moments in your code:

      1. Increase 8080I bus performance:
      DCX pin: set it to "1" in your "Readdata" function and toggle it "0" -> "1" in "Writecmd" function. Do not operate with it in "Writedata" function.
      WRX pin: set it to "1" in "Readdata" and toggle it "0" -> "1" in "Writecmd" and "Writedata" function.

      2. If possible ensure maximum system frequency for MCU.

      3. Use Window manager with simple windows / dialogs.

      And most important thing: call WM_SetCreateFlags(WM_CF_MEMDEV).

      This will enable drawing operations with windows using memory device per default.

      There is too few internal ram for a single memory device but this option uses automatical banding for memory devices by Window manager.

      All these actions provide pretty fast GUI drawing on my side.

      Alex.

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

    • LexaGb wrote:

      Hello,

      one of the boards I work with is also a device with STM32F207 (120MHz, 128 kB SRAM) MCU and 240x320 LCD with ILI9341 controller using 16-bit 8080I bus. No external ram. No cache for display driver. Not much "faster" system than yours.

      Check the following moments in your code:

      1. Increase 8080I bus performance:
      DCX pin: set it to "1" in your "Readdata" function and toggle it "0" -> "1" in "Writecmd" function. Do not operate with it in "Writedata" function.
      WRX pin: set it to "1" in "Readdata" and toggle it "0" -> "1" in "Writecmd" and "Writedata" function.

      2. If possible ensure maximum system frequency for MCU.

      3. Use Window manager with simple windows / dialogs.

      And most important thing: call WM_SetCreateFlags(WM_CF_MEMDEV).

      This will enable drawing operations with windows using memory device per default.

      There is too few internal ram for a single memory device but this option uses automatical banding for memory devices by Window manager.

      All these actions provide pretty fast GUI drawing on my side.

      Alex.
      Thank you Alex for your contribution, very appreciated.

      As you guessed there were some redundancies in my code in the 8080I bus which were the cause of the slow system response.
      Next step is to try if the WM is working properly as well.

      I've managed to setup the board with a 2.8 inches display with an ST7789v display controller and it looks like is working fine.

      I'm having some issues with another display of 3.5 inches with an ILI9488 display controller (8-bit parallel)
      Colors seems OK (even though the image looks stretch but I suppose the cause it might be wrong controller parameters setup) but fonts are NOT working (I see random pixels written instead of the text).

      Fonts are only working if I put


      Source Code

      1. GUI_SetTextMode(GUI_TM_TRANS);
      before the DispStringAt() command.

      Without this even the simplest "Hello world" demo is not working.

      Any ideas or suggestions on something that is missing in my configuration?

      Thank you!

      Mark
    • Hello,

      well, actually, I didn't work with ILI9488, maybe there's the problem with reading back pixel data in the right format, so we can think about the things:

      1. Check if code in your 8-bit functions (Readdata, WriteData etc...) is quite accurate and consistent with dedicated pixel data format which is set to ILI9488 during initialization (565 or 666).

      2. Check if pixel data format complies with the configured color conversion routine.

      3. If needed check if the function GUIDRV_FlexColor_SetReadFunc...() is using with the right parameters for reading back pixel data.

      4. Check if the function GUIDRV_FlexColor_SetFunc() is using with the right parameters (bus width etc...).

      Alex.