Problem regarding external memory on STM32F746G-DISC board

I am trying to setup external RAM available in the stm32f746g-discovery board.

With reference to this thread: External FLASH and SDRAM Cortex-M
I did this in order to use the external ram for lvgl objects:
# define LV_MEM_ADR 0x90000000

But this cause an HardFault causing the mcu to jump to HardFault_Handler()

I have tried to put an array on the external flash. I have defined a separate section in the linkerscript:

RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 320K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 1024K
QUADSPI (rx)    : ORIGIN = 0x90000000,  LENGTH = 16M
SDRAM (xrw)      : ORIGIN = 0xC0000000, LENGTH = 8M


.ExtFlashSection (NOLOAD) :

and in c file, in the global scope:

__attribute__ ((section (".ExtFlashSection"))) char *x = "Hello Bello Cello!!";

but when i tried to use that string array in my label:

    lv_obj_t *lb = lv_label_create(lv_scr_act(), NULL);
    lv_label_set_text(lb, x);
    lv_obj_set_style_local_text_font(lb, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_montserrat_48);
    lv_obj_align(lb, NULL, LV_ALIGN_CENTER, 0, 0);

It caused a hardfault at line 2, lv_label_set_text.

I have selected custom loader in cubeIDE debug configurations too. Also i have checked LCD_Init(), looks like it initializes the SDRAM too so it should work fine. I have no idea what is causing this and what am i missing :neutral_face:

I have that board, and AFAIK 0x90000000 is QSPI flash. You are probably looking for 0x60000000 if FMC swapping is enabled, and 0xC0000000 otherwise.

yeah you are right I was using QSPI flash address, but still I have tried with 0x60000000 and 0xC0000000 too, same issue.
I haven’t changed anything in the whole project either, except those changes, so I don’t think BSP configures the FMC swapping.
Can you please test it on your side too?

First and foremost, have you generated the code with Cubemx? If yes, you should be warned that the generator doesn’t start the FMC. It only initiates it. So any effort for using it is useless and will lead you to the hard fault handler unless you start it after initiating it. initiating is like put the key into its place and starting is like rotating the key.

Well I am using the already available port for stm32f746g-disc board. Haven’t modified anything in the code, except for those above mentioned.

This one? GitHub - lvgl/lv_port_stm32f746_disco: LVGL ported to STM32F746G-DISCO using STM32CubeIDE

The external SDRAM is already initialized and used for the framebuffer in that port.

That means it already uses the sdram to store LVGL objects right? But when I have tried to increase mem for LVGL though changing LV_MEM_SIZE to 64x1024 the linker gave error that .bss is too small.
Also what about the external flash?

No, just the framebuffer.

That’s because LV_MEM_SIZE controls the heap size, and the heap is in internal SRAM.

The external flash is not used by that port.

1 Like

Thanks for the awesome explanation.
So, if I change that LV_MEM_ADR to external sdram, all the LVGL objects will go to sdram right? And before that it should work, instead of causing hardfault?:confused:

Yes, however, make sure you place the heap after the framebuffer, otherwise they will overlap and corrupt each other.

Well, my first problem is that I can’t fix that hardfault, caused by changing LV_MEM_ADR to sdram, can you help with that?

0x90000000 is the wrong address for that port, but using 0x60100000 should work.

I will try it and report back.

same problem with 0x60100000 too :confused:
Also, does the port inits the QSPI flash too?

No, the port does not use QSPI flash.

same problem with 0x60100000

I forgot that this port initializes the SDRAM in the display driver itself (in my private version I initialize it early on), so the SDRAM wasn’t initialized when lv_init was called. You can apply the following patch to make it work:

diff --git a/hal_stm_lvgl/tft/tft.c b/hal_stm_lvgl/tft/tft.c
index 0e1542b..f61f4d2 100644
--- a/hal_stm_lvgl/tft/tft.c
+++ b/hal_stm_lvgl/tft/tft.c
@@ -356,8 +356,8 @@ static uint8_t LCD_Init(void)
     /* Assert backlight LCD_BL_CTRL pin */
-    BSP_SDRAM_Init();
-    HAL_EnableFMCMemorySwapping();
+    //BSP_SDRAM_Init();
+    //HAL_EnableFMCMemorySwapping();
     uint32_t i;
     for(i = 0; i < (TFT_HOR_RES * TFT_VER_RES) ; i++)
diff --git a/lv_conf.h b/lv_conf.h
index 2bce6f7..2704c87 100644
--- a/lv_conf.h
+++ b/lv_conf.h
@@ -45,7 +45,7 @@
 #  define LV_MEM_SIZE    (64U * 1024U)          /*[bytes]*/
 /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
-#  define LV_MEM_ADR          0     /*0: unused*/
+#  define LV_MEM_ADR          0x60100000     /*0: unused*/
 #else       /*LV_MEM_CUSTOM*/
 #  define LV_MEM_CUSTOM_INCLUDE <stdlib.h>   /*Header for the dynamic memory function*/
 #  define LV_MEM_CUSTOM_ALLOC     malloc
diff --git a/src/main.c b/src/main.c
index 921ccc9..5665700 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1,5 +1,6 @@
 #include "stm32f7xx.h"
+#include "stm32746g_discovery_sdram.h"
 #include "lvgl/lvgl.h"
 #include "hal_stm_lvgl/tft/tft.h"
@@ -22,6 +23,8 @@ int main(void)
     /* Enable D-Cache */
+    BSP_SDRAM_Init();
+    HAL_EnableFMCMemorySwapping();

Yeah, I have noticed that too, and mentioned it on my original post.
Here: lv_port_stm32f746_disco/tft.c at 4f7dda9792996caf965625de02b3f72155f3d461 · lvgl/lv_port_stm32f746_disco · GitHub


And in the port tft_init is called after lv_init.
Isn’t tft_init should be called before lv_init? It makes more sense to me though.

You can’t call it before lv_init, because it tries to register the display with LVGL.

1 Like

Ok, I will try it.

Sorry I forgot to mention that I am using the lvgl V7 release of that port, release/v7 branch to be exact.

As long as HAL_EnableFMCMemorySwapping is called right after BSP_SDRAM_Init, you should still be able to use the address beginning with 6.