Hi everyone!
I start working in a company that has a equipment with a code that already works fine. I was asked to include a string in one splash screen and then I did. No problem! Then I was pointed again to change the text of this string. The old one had 9 bytes long and when I changed the string to some 18 bytes long, the code started crashinng when a call to lv_disp_load_scr(ui_splash)
occurs. ui_splash is a poiter to an object of lv_obj_t type and is created with ui_splash = lv_obj_create(NULL);
.
What MCU/Processor/Board and compiler are you using?
- The code runs on a device with one STM32FH573 with 640K of RAM and 2M of flash with one ST7735S display using SPI with DMA and everything configured correctly.
- Compiler is arm-none-eabi-gcc 12.2 that comes with the CubeIDE.
What LVGL version are you using?
- This project uses the version 8.3
/***************************
* CURRENT VERSION OF LVGL
***************************/
#define LVGL_VERSION_MAJOR 8
#define LVGL_VERSION_MINOR 3
#define LVGL_VERSION_PATCH 6
#define LVGL_VERSION_INFO ""
What do you want to achieve?
Make the code run with the correct string into the splash screen.
What have you tried so far?
- I explained in the text body below.
- As well as I turned the LV_LOGS on and all the lv_conf helpers to analyse memory and so one… Nothing seems to explain the root cause of this problem
Code to reproduce
- Sorry guys I have a contract with the company in which I can’t expose the source code…
The code starts, everything goes well, then I call lv_obj_del(ui_splash);
and after initialize the next screen that creates all the lv_obj_t objects with success, the code lv_disp_load_scr(ui_next_screen);
is called to load that screen. But inside this functionn the crash happens. More specifically in:
Thread #1 (Suspended : Signal : SIGINT:Interrupt)
HardFault_Handler() at stm32h5xx_it.c:107 0x8002ef4
<signal handler called>() at 0xffffffa8
lv_obj_get_parent() at lv_obj_tree.c:296 0x803167c
lv_obj_get_screen() at lv_obj_tree.c:264 0x80315c6
lv_obj_get_disp() at lv_obj_tree.c:277 0x80315f4
scr_load_internal() at lv_disp.c:471 0x80261d2
lv_scr_load_anim() at lv_disp.c:230 0x8025caa
lv_disp_load_scr() at lv_disp.c:84 0x8025b18
AnotherScreenInit() at AnotherScreen.c:13 0x8023e7c
SMGoToScreen() at ScreenManager.c:222 0x8023d96
SMOverwriteScreen() at ScreenManager.c:89 0x8023b5e
SplashScreenTick() at SplashScreen.c:28 0x8025772
SMTickHandler() at ScreenManager.c:142 0x8023bb8
UiRun() at UiController.c:290 0x8018aea
SystemControllerRun() at SystemController.c:116 0x8018484
device_main() at device_main.c:84 0x8022182
main() at main.c:128 0x800207e
The central question here is → if I stop call lv_obj_del
commenting the code, everythign works fine! But, if I keep the code, even deleting the lv objects, the code works until I start printing a string with more than 11 characters.
- this is the function where the splash screen is initialized…
void ui_splash_screen_init(void)
{
char str_firm[20];
ui_splash = lv_obj_create(NULL);
lv_obj_clear_flag(ui_splash, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_set_style_bg_color(ui_splash, lv_color_hex(0xFBDD56), LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(ui_splash, 255, LV_PART_MAIN | LV_STATE_DEFAULT);
ui_logo = lv_img_create(ui_splash);
lv_img_set_src(ui_logo, &ui_img_logo_png);
lv_obj_set_width(ui_logo, LV_SIZE_CONTENT);
lv_obj_set_height(ui_logo, LV_SIZE_CONTENT);
lv_obj_set_align(ui_logo, LV_ALIGN_CENTER);
lv_obj_clear_flag(ui_logo, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE |
LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM |
LV_OBJ_FLAG_SCROLL_CHAIN);
// ### THIS IS THE CODE I ADDED AND WORKS UNTIL THE STRING NEEDED TO BE CHANGED TO ANOTHER WITH JUST FEW BYTES MORE
sprintf(str_firm, "HERE GOES W"); //Here everything goes perfectly!
//sprintf(str_firm, "HERE GOES WRONG"); //Here if uncomment thi line, the crash occurs
ui_versionMsg = lv_label_create(ui_splash);
lv_obj_set_width(ui_versionMsg, LV_SIZE_CONTENT);
lv_obj_set_height(ui_versionMsg, LV_SIZE_CONTENT);
lv_obj_set_align(ui_versionMsg, LV_ALIGN_TOP_MID);
lv_label_set_text(ui_versionMsg, str_firm);
lv_obj_set_y(ui_versionMsg, 110);
lv_obj_clear_flag(ui_versionMsg, LV_OBJ_FLAG_PRESS_LOCK | LV_OBJ_FLAG_CLICK_FOCUSABLE | LV_OBJ_FLAG_GESTURE_BUBBLE |
LV_OBJ_FLAG_SNAPPABLE | LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC | LV_OBJ_FLAG_SCROLL_MOMENTUM |
LV_OBJ_FLAG_SCROLL_CHAIN);
lv_obj_set_style_text_color(ui_versionMsg, lv_color_hex(0x4D4B5C), (lv_style_selector_t)LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_opa(ui_versionMsg, 255, (lv_style_selector_t)LV_PART_MAIN | LV_STATE_DEFAULT);
lv_obj_set_style_text_font(ui_versionMsg, &lv_font_montserrat_10, (lv_style_selector_t)LV_PART_MAIN | LV_STATE_DEFAULT);
//###
}
Then the sequence is:
void SplashScreenInit() {
if (!m_instance->m_isInitialized)
{
ui_splash_screen_init(); //the code execute this successfully!
m_instance->m_isInitialized = true;
}
lv_disp_load_scr(ui_splash); //here as well... successfully!
.
.
.
}
Now the logic is that the screen manager is called asking to change the screen. I dont know why but the screen manager uses a stack to keep control of the screens:
void SMOverwriteScreen(ScreenType newScreen)
{
Screen *currentScreen;
if((currentScreen = SMGetCurrentScreen()) != NULL)
{
if (currentScreen->m_type == newScreen)
{
return;
}
if (currentScreen->DeInit != NULL)
{
// One curious fact is that if I uncomment the code `sprintf(str_firm, "HERE GOES WRONG");` that makes everything crash and stop calling Deinit() commenting the line below
// everything get working back.
currentScreen->DeInit(); //current screen is ui_splash that only sets the m_isInitialized to false and deletes the ui_splash object.
}
}
if (StackPop(&stack.m_stack) != NULL)
{
if (StackPush(&stack.m_stack,newScreen))
{
SMGoToScreen(newScreen); //here is the new screen that will load...
}
}
}
And you see here:
void SMGoToScreen(ScreenType screenType)
{
if (screenType == ScreenTypeNone)
{
return;
}
screenTable[screenType].Init(); //And the code executes this function that is the initialization of the new screen to be showed
}
That .Init()
is a pointer to a function to initialise the next screen as you see below:
void AnotherScreenInit()
{
if (!m_instance->m_isInitialized)
{
ui_another_screen_init();
m_instance->m_isInitialized = true;
}
lv_disp_load_scr(ui_next_screen); //The code crashes here
}
and
void ui_another_screen_init(void)
{
ui_next_screen = lv_obj_create(NULL);
lv_obj_clear_flag(ui_next_screen,
LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_PRESS_LOCK |
LV_OBJ_FLAG_SCROLLABLE | LV_OBJ_FLAG_SCROLL_ELASTIC |
LV_OBJ_FLAG_SCROLL_MOMENTUM);
ui_next_stuff = lv_obj_create(ui_next_screen);
lv_obj_set_width(ui_next_stuff, 68);
lv_obj_set_height(ui_next_stuff, 34);
lv_obj_set_x(ui_next_stuff, 26);
lv_obj_set_y(ui_next_stuff, 69);
.
.
.
//This is only for demonstration purposes
}
Thanks in advance…