Problem using GUI_GIF_Draw() with graphical memory assigned to SDRAM

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

    • Problem using GUI_GIF_Draw() with graphical memory assigned to SDRAM

      Hello to everyone,

      let me please ask a question.

      I had requested with this question to ST community but I didn't receive a helpful answer. Maybe someone can help me with my problem on this forum.

      I'm using precompiled emWin library (STemWin) for GUI development on a custom board with SDRAM and LCD panel.

      My chip is STM32F777ZIT6.
      SDRAM chip is MT48LC32M16A2 (64 MByte) connected to the chip through FMC bank1 (start address is 0xC0000000).
      LCD panel is G104XVN01.0 (10.4 inch, 1024x768) connected to the chip through LTDC using RGB-LVDS transceiver.

      I successfully configured and initialized emWin ("Hello, world" etc... basical drawing functions from 2D graphical library...). But my problem is drawing a GIF when allocating memory in SDRAM.

      I created a simple project with one framebuffer layer. I split SDRAM memory space in half to simplify the project: lower 32 MBytes allocated to emWin, higher 32 MBytes allocated to framebuffer layer 0. Also I made a simple GIF picture (green text "This is a GIF" on the yellow background), unoptimized it as described in emWin manual, then used Bitmap Converter and converted the GIF to C-array with BIN2C for using with GUI_GIF_Draw().

      Some configuration options and code sections:

      C Source Code

      1. ...
      2. #define COLOR_CONVERSION_0 GUICC_M565
      3. #define DISPLAY_DRIVER_0 GUIDRV_LIN_16
      4. #define GUI_NUM_LAYERS 1
      5. ...
      6. #define LCD_LAYER0_FRAME_BUFFER 0xC2000000
      7. ...
      8. #define GUI_NUMBYTES 0x2000000
      9. ...
      10. static U32 extMem[GUI_NUMBYTES / 4] __attribute__ ((section(".sdram_data"))); // ".sdram_data" is a SDRAM section in linker *.ld file, start address is 0xC0000000
      11. ...
      12. void GUI_X_Config(void)
      13. {
      14. GUI_ALLOC_AssignMemory(extMem, GUI_NUMBYTES); // Assign memory for emWin
      15. }
      16. ...
      Display All
      I'm using System Workbench IDE. Watch window in IDE shows correct addresses (extMem shows 0xC0000000 and layer_prop[0].address shows 0xC2000000).


      Code section with main():

      C Source Code

      1. extern const unsigned char _acpictgif[4790UL + 1] = {...GIF array...};
      2. ...
      3. int status;
      4. ...
      5. int main(void)
      6. {
      7. MPU_Config();
      8. SCB_EnableICache();
      9. SCB_EnableDCache();
      10. ...
      11. // Code sections with MCU, HAL, System clock, GPIO, Peripherals, emWin configuration, nothing interesting...
      12. ...
      13. // Start showing the GIF
      14. GUI_Clear();
      15. status = GUI_GIF_Draw(_acpictgif, 4790UL + 1, 0, 0);
      16. while (1) {
      17. GUI_Delay(100);
      18. }
      19. }
      Display All


      First I configured the MPU regions (in my view it is "WRITE THROUGH")

      C Source Code

      1. void MPU_Config(void)
      2. {
      3. /* Disables the MPU */
      4. LL_MPU_Disable();
      5. /**Initializes and configures the Region and the memory to be protected
      6. */
      7. // WT
      8. LL_MPU_ConfigRegion(LL_MPU_REGION_NUMBER0, 0x0, 0xC0000000, LL_MPU_TEX_LEVEL0|LL_MPU_REGION_SIZE_64MB|LL_MPU_REGION_FULL_ACCESS|LL_MPU_INSTRUCTION_ACCESS_ENABLE|LL_MPU_ACCESS_NOT_SHAREABLE|LL_MPU_ACCESS_CACHEABLE|LL_MPU_ACCESS_NOT_BUFFERABLE);
      9. LL_MPU_EnableRegion(LL_MPU_REGION_NUMBER0);
      10. /**Initializes and configures the Region and the memory to be protected
      11. */
      12. LL_MPU_ConfigRegion(LL_MPU_REGION_NUMBER1, 0x0, 0xC2000000, LL_MPU_TEX_LEVEL0|LL_MPU_REGION_SIZE_32MB|LL_MPU_REGION_FULL_ACCESS|LL_MPU_INSTRUCTION_ACCESS_DISABLE|LL_MPU_ACCESS_NOT_SHAREABLE|LL_MPU_ACCESS_CACHEABLE|LL_MPU_ACCESS_NOT_BUFFERABLE);
      13. LL_MPU_EnableRegion(LL_MPU_REGION_NUMBER1);
      14. }
      Display All

      And got this one. status = 1. That is an error. Only first few lines of the GIF are displayed:
      [img]https://forum.segger.com/index.php/Attachment/2604-IMG-4643-JPG/?tiny=1[/img]

      Next I reconfigured MPU regions (in my view it is "WBWA"):

      C Source Code

      1. void MPU_Config(void)
      2. {
      3. /* Disables the MPU */
      4. LL_MPU_Disable();
      5. // WBWA
      6. LL_MPU_ConfigRegion(LL_MPU_REGION_NUMBER0, 0x0, 0xC0000000, LL_MPU_TEX_LEVEL1|LL_MPU_REGION_SIZE_32MB|LL_MPU_REGION_FULL_ACCESS|LL_MPU_INSTRUCTION_ACCESS_ENABLE|LL_MPU_ACCESS_NOT_SHAREABLE|LL_MPU_ACCESS_CACHEABLE|LL_MPU_ACCESS_BUFFERABLE);
      7. LL_MPU_EnableRegion(LL_MPU_REGION_NUMBER0);
      8. /**Initializes and configures the Region and the memory to be protected
      9. */
      10. LL_MPU_ConfigRegion(LL_MPU_REGION_NUMBER1, 0x0, 0xC2000000, LL_MPU_TEX_LEVEL1|LL_MPU_REGION_SIZE_32MB|LL_MPU_REGION_FULL_ACCESS|LL_MPU_INSTRUCTION_ACCESS_DISABLE|LL_MPU_ACCESS_NOT_SHAREABLE|LL_MPU_ACCESS_CACHEABLE|LL_MPU_ACCESS_BUFFERABLE);
      11. LL_MPU_EnableRegion(LL_MPU_REGION_NUMBER1);
      12. /* Enables the MPU */
      13. LL_MPU_Enable(LL_MPU_CTRL_PRIVILEGED_DEFAULT);
      14. }
      Display All

      And got this one. status = 0. No errors but the GIF contains distortion artifacts:
      [img]https://forum.segger.com/index.php/Attachment/2605-IMG-4644-JPG/?tiny=1[/img]

      Next I reassigned extMem to internal RAM:

      C Source Code

      1. static U32 extMem[GUI_NUMBYTES / 4]; // __attribute__ ... deleted. extMem now is in internal RAM.

      Had to reduce GUI_NUMBYTES to 130 KBytes as the chip has only 512 KBytes of infernal RAM.

      C-array containing GIF data and frame buffer location for layer 0 remain unchanged. The only change is extMem relocation from SDRAM to internal RAM.

      And I got a fine picture:
      [img]https://forum.segger.com/index.php/Attachment/2606-IMG-4642-JPG/?tiny=1[/img]

      Seems that MPU regions not properly configured in case of extMem allocation in SDRAM. And furthermore, functions GUI_BMP_Draw() and GUI_DrawBitmap() work properly regardless of extMem allocation. The problem appears only when drawing a GIF.

      Can anyone tell a proper MPU configuration?

      It is critical for my development to use GIFs as they have compact size and the board has only internal flash on the chip (2 MB).

      In addition, I'm going to use Window Manager and use GIFs as background images with different widgets over it. So I need to use Memory Devices for fast painting when invalidating windows and I should have sufficient RAM for that purposes as internal RAM is not enough.

      My project attached.

      Thanks for your time.
      Images
      • IMG_4643.JPG

        74.5 kB, 640×480, viewed 132 times
      • IMG_4644.JPG

        74.25 kB, 640×480, viewed 102 times
      • IMG_4642.JPG

        76.8 kB, 640×480, viewed 106 times
      Files

      The post was edited 7 times, last by LexaGb ().

    • Hi,

      I had a similar problem with F7 cache and I use the following MPU-config for external SDRAM:

      C Source Code

      1. hal_mpu_disable();
      2. // das externen RAM (Bild-Puffer und HEAP)
      3. // ---- Write-back, no write allocate ----
      4. MPU->RNR = MPU_RNR_REGION_NUMBER0;
      5. MPU->RBAR = 0x60000000;
      6. MPU->RASR = MPU_RASR_INSTRUCTION_ACCESS_ENABLE
      7. | MPU_RASR_PERMISSION_FULL_ACCESS
      8. | MPU_RASR_TEX_LEVEL0
      9. | MPU_RASR_ACCESS_SHAREABLE
      10. | MPU_RASR_ACCESS_CACHEABLE
      11. | MPU_RASR_ACCESS_BUFFERABLE
      12. | MPU_RASR_SUB_REGION(0)
      13. | MPU_RASR_REGION_SIZE_8MB
      14. | MPU_RASR_ENABLE;
      15. hal_mpu_enable(MPU_PRIVILEGED_DEFAULT);
      Display All
    • Configure MPU for sdram region.

      /**
      * @brief Configure the MPU attributes as Write Through for SRAM1/2.
      * @note The Base Address is 0xC0000000 since this memory interface is the AXI.
      * The Region Size is 8MB, it is related to SRAM1 and SRAM2 memory size.
      * @param None
      * @retval None
      */
      static void MPU_SDRAM_Config (void)
      {
      MPU_Region_InitTypeDef MPU_InitStruct;

      /* Disable the MPU */
      HAL_MPU_Disable();

      /* Configure the MPU attributes for SDRAM */
      MPU_InitStruct.Enable = MPU_REGION_ENABLE;
      MPU_InitStruct.BaseAddress = 0xC0000000;
      MPU_InitStruct.Size = MPU_REGION_SIZE_8MB;
      MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
      MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
      MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
      MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
      MPU_InitStruct.Number = MPU_REGION_NUMBER0;
      MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
      MPU_InitStruct.SubRegionDisable = 0x00;
      MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_DISABLE;

      HAL_MPU_ConfigRegion(&MPU_InitStruct);

      /* Enable the MPU */
      HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);
      }

      This should help.

      Best Regards,
      Rohit
    • Hello, Bastl!
      Hello, Rohit!

      Thank you for your response.

      Unfortunately, these configurations don't help.
      I'm using STM LL library for MPU configuration.

      Bastl's configuration:

      C Source Code

      1. ...
      2. LL_MPU_ConfigRegion(LL_MPU_REGION_NUMBER0, 0x0, 0xC0000000, LL_MPU_TEX_LEVEL0|LL_MPU_REGION_SIZE_64MB|LL_MPU_REGION_FULL_ACCESS|LL_MPU_INSTRUCTION_ACCESS_ENABLE|LL_MPU_ACCESS_SHAREABLE|LL_MPU_ACCESST_CACHEABLE|LL_MPU_ACCESS_BUFFERABLE);
      3. LL_MPU_EnableRegion(LL_MPU_REGION_NUMBER0);
      4. ...

      Rohit's configuration:

      C Source Code

      1. ...
      2. LL_MPU_ConfigRegion(LL_MPU_REGION_NUMBER0, 0x0, 0xC0000000, LL_MPU_TEX_LEVEL1|LL_MPU_REGION_SIZE_64MB|LL_MPU_REGION_FULL_ACCESS|LL_MPU_INSTRUCTION_ACCESS_DISABLE|LL_MPU_ACCESS_NOT_SHAREABLE|LL_MPU_ACCESS_NOT_CACHEABLE|LL_MPU_ACCESS_NOT_BUFFERABLE);
      3. LL_MPU_EnableRegion(LL_MPU_REGION_NUMBER0);
      4. ...

      In both cases there is an empty screen and GUI_GIF_Draw() returns 1 :(

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

    • Hello LexaGb,

      I would suggest to reduce the region-size to the size and address of the drawing-Buffer. Maybe you influence other software-part with the region-size of 64MB. Did you maybe link your stacks also to the external RAM?
      I linked my stacks to the internal RAM and disable the cache for this memory using the MPU:

      C Source Code

      1. // internes SRAM
      2. // ---- Non-cacheable ----
      3. MPU->RNR = MPU_RNR_REGION_NUMBER1;
      4. MPU->RBAR = 0x20000000;
      5. MPU->RASR = MPU_RASR_INSTRUCTION_ACCESS_ENABLE
      6. | MPU_RASR_PERMISSION_FULL_ACCESS
      7. | MPU_RASR_TEX_LEVEL1
      8. | MPU_RASR_ACCESS_NOT_SHAREABLE
      9. | MPU_RASR_ACCESS_NOT_CACHEABLE
      10. | MPU_RASR_ACCESS_NOT_BUFFERABLE
      11. | MPU_RASR_SUB_REGION(0)
      12. | MPU_RASR_REGION_SIZE_512KB
      13. | MPU_RASR_ENABLE;
      Display All
      It is just a speculation... :/
    • Hello, Golf!

      Thank you for your response.

      Yes, external SDRAM bus width is 16 bit. But I checked it in -8, -16, -32 bit access modes and all the data (uint8_t, uint16_t, uint32_t types) writes and reads correctly.

      I have STM32F429Discovery board and there is also SDRAM with 16-bit memory bus width (IS42S16400J). But all the code works fine on the board.