Label Text Repeating on Display when movining to v9 using nrfConnect 3.0.1

What do you want to achieve?

I want to simply display “Hello World” on a screen.

What have you tried so far?

I have it running with nrfConnect (Nordic’s VS Code Addin) 2.9.1 which used lvgl 8.*. I moved to 3.1.0 which is lvgl 9.3.0 and the screen shows “Hello World” three times starting in the center (where I expect it to be) and then twice below it.

Code to reproduce

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/display.h>
#include <zephyr/pm/device.h>
#include <zephyr/drivers/pwm.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/logging/log.h>
#include <stdio.h>
#include <app_version.h>
#include <lvgl.h>

LOG_MODULE_REGISTER(app, LOG_LEVEL_DBG);

int count = 0;

// BACKLIGHT MANAGER CODE
#define PWM_LED0    DT_ALIAS(pwm_led0)
static const struct pwm_dt_spec pwm_led0 = PWM_DT_SPEC_GET(PWM_LED0);

int backlight_manager_init(void) 
{

	LOG_DBG("Starting backlight PWM");

		
	if (!pwm_is_ready_dt(&pwm_led0)) {
		LOG_ERR("Error: PWM device %s is not ready", pwm_led0.dev->name);
		return -1;
	}

    return 0;

}

static void set_pwm(const struct pwm_dt_spec *pwmdev, uint8_t percent) {

	LOG_DBG("Setting PWM to %d%%", percent);

	int ret;
	uint32_t step = pwmdev->period / 100;
	uint32_t pulse_width = step * percent;

	if (!device_is_ready(pwmdev->dev)) {
		LOG_ERR("PWM device not ready");
		return;
	}

	ret = pwm_set_pulse_dt(pwmdev, pulse_width);
	if (ret < 0) {
		LOG_ERR("Failed to set pulse width: %i", ret);
		return;
	}
}

void backlight_manager_wake()
{
    set_pwm(&pwm_led0, 100); 
    //set_pwm(&backlight_spec, 1);
}


void backlight_manager_sleep()
{
    set_pwm(&pwm_led0, 0);
}

// DISPLAY MANAGER CODE
static const struct device *display_dev  = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));

int display_manager_init(void) 
{
    LOG_DBG("Initializing display manager");
	if (!device_is_ready(display_dev)) {
		LOG_ERR("Device not ready, aborting test");
		return 0;
	}

    display_blanking_off(display_dev);

    return 0;
}

// VOLTAGE CODE
int change_gpio_voltage(uint32_t target_voltage)
{
    int err = 0;
    
    uint32_t regout = NRF_UICR->VREGHVOUT;
    LOG_INF("change_gpio_voltage: REGOUT = 0x%08x", regout);
    LOG_INF("change_gpio_voltage: target voltage is %d", target_voltage);    
    if ((regout & UICR_VREGHVOUT_VREGHVOUT_Msk)  != target_voltage) {
        LOG_INF("Target voltage not set. Configuring");

        // Set NVMC in write mode:
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
        while (NRF_NVMC->CONFIG != NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos) {
            // Wait...
        }

        // Write the actual UICR Register:
        NRF_UICR->VREGHVOUT = (target_voltage | ~UICR_VREGHVOUT_VREGHVOUT_Msk);
        while (NRF_NVMC->READY == NVMC_READY_READY_Busy) {
            // Wait...
        }

        // Set NVMC back in read mode:
        NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
        while (NRF_NVMC->CONFIG != NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos) {
            // Wait...
        }
        // Check whether it was set successfully:
        if ((NRF_UICR->VREGHVOUT & UICR_VREGHVOUT_VREGHVOUT_Msk) != target_voltage) {
            err = 0;
        }
        // Reset if success. Config will remain on future reboots.
        if (err == 0) {
            NVIC_SystemReset();
        }
    } else {
        LOG_INF("Target voltage already set. No action needed.");
        err = 0;
    }
    return err;

}

// SCREEN HELLO WORLD CODE
static  lv_obj_t *scr_home;

int screen_helloworld_init()
{
	LOG_DBG("Creating home screen");
	scr_home = lv_obj_create(NULL);
	// Used this function as it automatically deletes previous screen.
	// Should work as you did also I think. But have not used lv_scr_load_xxx before
	//lv_screen_load_anim(scr_home, LV_SCR_LOAD_ANIM_NONE, 0, 0, true);
	lv_screen_load(scr_home);

	lv_obj_t *hello_world_label;

	lv_obj_set_style_bg_color(lv_scr_act(), lv_palette_main(LV_PALETTE_GREEN), LV_PART_MAIN);
	lv_obj_set_style_text_color(lv_scr_act(), lv_color_white(), LV_PART_MAIN);

	hello_world_label = lv_label_create(lv_scr_act());

	lv_label_set_text(hello_world_label, "Hello World!");
	lv_obj_align(hello_world_label, LV_ALIGN_CENTER, 0, 0);
	lv_obj_set_style_text_font(hello_world_label, &lv_font_montserrat_16, LV_PART_MAIN);

	return 0;
}



int main(void)
{
    LOG_DBG("Hello World! %s (%s)", CONFIG_BOARD, APP_VERSION_EXTENDED_STRING);
	change_gpio_voltage(UICR_VREGHVOUT_VREGHVOUT_3V0);
	display_manager_init();
	backlight_manager_init();
	screen_helloworld_init();
	backlight_manager_wake();
	while (count < 100) {
		count++;
		LOG_DBG("looping %d", count);
		k_sleep(K_MSEC(1000));
		lv_timer_handler();
	}
	backlight_manager_sleep();
	return 0;
}


and this in the dts/overlay:

/ {
    mipi_dbi {
		compatible = "zephyr,mipi-dbi-spi";
		spi-dev = <&spi4>;
		dc-gpios = <&gpio0 19 GPIO_ACTIVE_HIGH>;
		reset-gpios =  <&gpio0 23 GPIO_ACTIVE_LOW>;
		write-only;
		#address-cells = <1>;
		#size-cells = <0>;
        st7789v_st7789v_tl019fqv01: st7789v@0 {
            compatible = "sitronix,st7789v";
            mipi-max-frequency = <20000000>;
            reg = <0>;
            width = <240>;
            height = <280>;
            x-offset = <0>;
            y-offset = <20>;
            vcom = <0x19>;
            gctrl = <0x35>;
            vrhs = <0x12>;
            vdvs = <0x20>;
            mdac = <0x00>;
            gamma = <0x01>;
            colmod = <0x05>;
            lcm = <0x2c>;
            porch-param = [0c 0c 00 33 33];
            cmd2en-param = [5a 69 02 01];
            pwctrl1-param = [a4 a1];
            pvgam-param = [D0 04 0D 11 13 2B 3F 54 4C 18 0D 0B 1F 23];
            nvgam-param = [D0 04 0C 11 13 2C 3F 44 51 2F 1F 1F 20 23];
            ram-param = [00 F0];
            rgb-param = [CD 08 14];
            //mipi-mode = <MIPI_DBI_MODE_SPI_4WIRE>;
            mipi-mode = "MIPI_DBI_MODE_SPI_4WIRE";
        };
    };
};

I also simply have this in the main while loop:

    lv_timer_handler();

Environment

  • MCU/MPU/Board: nrf5340 board
  • LVGL version: 9.3.0
  • nrfConnect: 3.0.1
  • Zephyr: 4.0.99 (maybe a Nordic patch level)
  • Display: st7789, SPI, mipi_dbi

CONFIG_LV_CONF_MINIMAL=y caused the issue. Needed to add:

CONFIG_LV_TXT_ENC_UTF8=y
CONFIG_LV_FONT_DEFAULT_MONTSERRAT_14=y
CONFIG_LV_USE_FLEX=y
CONFIG_LV_USE_GRID=y
CONFIG_LV_USE_THEME_DEFAULT=y
CONFIG_LV_USE_THEME_SIMPLE=y