Lvgl getting stuck on "while(vdb->flushing)"

Description

My super loop is getting stuck on

    if(lv_disp_is_double_buf(disp_refr) == false) {
        while(vdb->flushing)
            ;
    }

inside of static void lv_refr_area_part(const lv_area_t * area_p)
in lv_refr.c

What MCU/Processor/Board and compiler are you using?

SAME54 Xplained Pro (atsame54p20a) in Atmel Studio 7 (ASF4) (gcc)
Display driver: ili9488
Display: Some random 480x320 lcd touch tft off of amazon

What do you expect?

I assume this is because the flush function isn’t being called, but I have it registered with the driver:

	project_init();
	ili9488_init();
	lv_init();
	
	static lv_disp_buf_t disp_buf;
	static lv_color_t buf[LV_HOR_RES_MAX * 10];                     /*Declare a buffer for 10 lines*/
	lv_disp_buf_init(&disp_buf, buf, NULL, LV_HOR_RES_MAX * 10);    /*Initialize the display buffer*/
	
	lv_disp_drv_t disp_drv;               /*Descriptor of a display driver*/
	lv_disp_drv_init(&disp_drv);          /*Basic initialization*/
	disp_drv.flush_cb = ili9488_flush;    /*Set your driver function*/
	disp_drv.buffer = &disp_buf;          /*Assign the buffer to the display*/
	lv_disp_drv_register(&disp_drv);      /*Finally register the driver*/
	
	lv_obj_t * slider1 = lv_slider_create(lv_scr_act(), NULL);
	lv_slider_set_value(slider1, 70, LV_ANIM_ON);

Where exactly should this flag be set from to signify the buffer has been flushed? If it’s sitting in a while loop, I don’t know of any interrupts I’ve enabled for lvgl to use to get out of this.

You need to call lv_disp_flush_ready at the end of your ili9488_flush function.

1 Like

I thought about that, but it was already there =/

Here is my ili9488_flush function:

void ili9488_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
	
	/*Return if the area is out the screen*/
	if(area->x2 < 0) return;
	if(area->y2 < 0) return;
	if(area->x1 >  - 1) return;
	if(area->y1 > LV_HOR_RES - 1) return;

	/*Truncate the area to the screen*/
	int32_t act_x1 = area->x1 < 0 ? 0 : area->x1;
	int32_t act_y1 = area->y1 < 0 ? 0 : area->y1;
	int32_t act_x2 = area->x2 > LV_HOR_RES - 1 ? LV_HOR_RES - 1 : area->x2;
	int32_t act_y2 = area->y2 > LV_VER_RES - 1 ? LV_VER_RES - 1 : area->y2;
	//ili9488_fill(act_x1, act_y1, act_x2, act_y2, *color_p);
	//Set the rectangular area
	ili9488_send_cmd(0x2A);
	ili9488_send_word(act_x1 >> 8);
	ili9488_send_word(0xFF & act_x1);
	ili9488_send_word(act_x2 >> 8);
	ili9488_send_word(0xFF & act_x2);

	ili9488_send_cmd(0x2B);
	ili9488_send_word(act_y1 >> 8);
	ili9488_send_word(0xFF & act_y1);
	ili9488_send_word(act_y2 >> 8);
	ili9488_send_word(0xFF & act_y2);

	ili9488_send_cmd(0x2c);
	int16_t i;
	uint16_t full_w = area->x2 - area->x1 + 1;
	
	
	p_disp_intf_set_gpio_level(P_LCD_nCS, 0);
	#if LV_COLOR_DEPTH == 16
	uint16_t act_w = act_x2 - act_x1 + 1;
	for(i = act_y1; i <= act_y2; i++) {
		p_disp_intf_wr_word_arr((uint16_t *)color_p, act_w);

		color_p += full_w;
	}
	p_disp_intf_set_gpio_level(P_LCD_nCS, 1);
	#else
	int16_t j;
	for(i = act_y1; i <= act_y2; i++) {
		for(j = 0; j <= act_x2 - act_x1 + 1; j++) {
			p_disp_intf_wr_byte((uint8_t*)&color_p[j]);
			color_p += full_w;
		}
	}
	#endif

	lv_disp_flush_ready(disp_drv);
}

I set a breakpoint inside of this callback, and it never gets called

Oh my god I’m so dumb

was supposed to be

Sorry… I’ve been working on this for days and am tired. Can’t believe I missed that.

Ok I fixed that, but it’s still getting caught in that original while loop. Now it never hits the callback, or at least my debugger won’t let me hit breakpoints inside of that callback:

/*Return if the area is out the screen*/
	if(area->x2 < 0) return;
	if(area->y2 < 0) return;
	if(area->x1 >  - 1) return;
	if(area->y1 > LV_HOR_RES - 1) return;

Should that not be

	/*Return if the area is out the screen*/
	if(area->x2 < 0) return;
	if(area->x1 > ILI9488_HOR_RES - 1) return;
	if(area->y2 < 0) return;
	if(area->y1 > ILI9488_VER_RES - 1) return;

??

I’m using this as a reference, https://github.com/littlevgl/lv_drivers/blob/master/display/SSD1963.c

So I wouldn’t think so, but I will try that

Update: Still hangs in the while loop. Here is my new flush function:

//uint8_t buffConv[320*3] = {};
void ili9488_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
	
	/*Return if the area is out the screen*/
	if(area->x2 < 0) return;
	if(area->x1 > LV_HOR_RES - 1) return;
	if(area->y2 < 0) return;
	if(area->y1 > LV_VER_RES - 1) return;

	/*Truncate the area to the screen*/
	int32_t act_x1 = area->x1 < 0 ? 0 : area->x1;
	int32_t act_y1 = area->y1 < 0 ? 0 : area->y1;
	int32_t act_x2 = area->x2 > LV_HOR_RES - 1 ? LV_HOR_RES - 1 : area->x2;
	int32_t act_y2 = area->y2 > LV_VER_RES - 1 ? LV_VER_RES - 1 : area->y2;
	//ili9488_fill(act_x1, act_y1, act_x2, act_y2, *color_p);
	//Set the rectangular area
	ili9488_send_cmd(0x2A);
	ili9488_send_word(act_x1 >> 8);
	ili9488_send_word(0xFF & act_x1);
	ili9488_send_word(act_x2 >> 8);
	ili9488_send_word(0xFF & act_x2);

	ili9488_send_cmd(0x2B);
	ili9488_send_word(act_y1 >> 8);
	ili9488_send_word(0xFF & act_y1);
	ili9488_send_word(act_y2 >> 8);
	ili9488_send_word(0xFF & act_y2);

	ili9488_send_cmd(0x2c);
	int16_t i;
	uint16_t full_w = area->x2 - area->x1 + 1;
	
	
	p_disp_intf_set_gpio_level(P_LCD_nCS, 0);
	#if LV_COLOR_DEPTH == 16
	uint16_t act_w = act_x2 - act_x1 + 1;
	for(i = act_y1; i <= act_y2; i++) {
		p_disp_intf_wr_word_arr((uint16_t *)color_p, act_w);

		color_p += full_w;
	}
	p_disp_intf_set_gpio_level(P_LCD_nCS, 1);
	#else
	int16_t j;
	for(i = act_y1; i <= act_y2; i++) {
		for(j = 0; j <= act_x2 - act_x1 + 1; j++) {
			p_disp_intf_wr_byte((uint8_t*)&color_p[j]);
			color_p += full_w;
		}
	}
	#endif

	lv_disp_flush_ready(disp_drv);
}

Ok so apparently atmel studio was building a cached file for the ili9488, so the initial change actually did solve the issue. It just kept resetting the code back to the initial problem after every build. Deleting my debug folder and cleaning the project has solved the issue (and applying the fix).

Thanks for the help and sorry this problem was so ridiculous. I still don’t actually have the screen working, but at least this problem is resolved.

I have not worked with the ili9488 but noticed you use LV_HOR_RES and LV_VER_RES in your driver.

Firstly lvgl_conf.h uses LV_HOR_RES_MAX and LV_VER_RES_MAX.
Secondly are you sure that LV_COLOR_DEPTH etc are correctly set in accordance with how you have the display controller configured.
I would define

ILI9488_HOR_RES and ILI9488_VER_RES to define the display capabilities and use those in the your driver file. But that in and of itself I don’[t think explains the problem you are seeing.

Have you tested the driver flush function by filling the buffer and calling it directly ?

LV_COLOR_DEPTH is correct at 16.

I added ILI9488_HOR_RES and ILI9488_VER_RES myself because I didn’t really know what LV_HOR_RES and LV_VER_RES were doing. I should change that back for sure.

And I haven’t tested the driver flush myself because I’m not exactly sure what I should use for dummy args.

Update: I tested the flush callback, and it didn’t work. I might even have a broken screen. I’ll have to order another to confirm =/

You can try this,

lv_area_t area = {
    .x1 = 0, .x2 = LV_HOR_RES_MAX-1,
    .y1 = 0, .y2 = 9,
};
for( int i = 0; i < LV_HOR_RES_MAX * 10; ++i )
{
    /* This is the buffer you gave to lv_disp_buf_init */
    buf[i] = LV_COLOR_WHITE;
}
ili9488_flush( NULL, &area, buf );

and change in the driver

    if( disp_drv )
        lv_disp_flush_ready(disp_drv);

Should fill the first 10 lines of your display with a white block.
If that does not work then you need to relook at the driver.or you may have a hardware issue…

Thanks. I tried this and no dice. I’m going to chalk this up to a hardware issue. I have a SSD1963+screen at work I am going to try your test on though, as I was having different issues on it.

The correct functions to be using are lv_disp_get_hor_res and lv_disp_get_ver_res. These will ensure that your driver works properly in an environment with multiple displays.

Provided that you’re only using one display, you can stick with LV_HOR_RES and LV_VER_RES.

1 Like