Does LVGL need (or can it work with) another event loop?

Hi @detly

I haven’t worked with Linux very much at all so please excuse my lack of knowledge of the specific functions/semantics for Linux…

If I understand what your asking correctly I don’t think you need any third party libraries to achieve your goal.

I would create a native thread for LVGL which initialises it and then periodically calls lv_task_handler() I would then create a global message queue using the native environment to receive messages/events from other parts of the system to update the GUI at runtime. Next I would create a task function for LVGL which is used to process the message queue and is executed by the LVGL task scheduler, this is registered with a call to lv_task_create() This task is called periodically by the LVGL scheduler I have found in my systems a period of 30mS usually gives a good performance, but depending on your CPU and other system load you may need to change this. One thing to make sure is that you never call any blocking functions from the GUI message/event queue to avoid disrupting the responsiveness of the GUI. To deal with calls to blocking activities triggered from the GUI I normally create a second native thread which monitors a similar global message/event queue that LVGL can post non blocking requests to it then carries out access to things like the file system, flash, nework etc. I then run this thread at a lower priority than the GUI which keeps the GUI nice and responsive at all times.

Here are some code snippets for the first part of my description, hopefully this makes sense:

declare linux message queue  your_queue; (Global)

void gui_thread(void *p) {

	lv_disp_drv_t	disp_drv;
	lv_disp_buf_t	disp_buf;

	// Initialise Video Hardware
	set_video_prams( ... );
	// Initialise GUI
	lv_init();
	lv_disp_drv_init(&disp_drv);
	lv_disp_buf_init(&disp_buf, (void*)LV_VDB_ADR, (void*)LV_VDB2_ADR, (LV_HOR_RES_MAX*LV_VER_RES_MAX));
	disp_drv.flush_cb = your_disp_flush;
	disp_drv.buffer = &disp_buf;
	lv_disp_drv_register(&disp_drv);
    gui_create();  // Your code to create GUI
	create and initialise your_queue;
	while(1) {
		lv_task_handler();
		// Linux non blocking delay call for say 5mS (usleep() or nanosleep() I expect)
	}
}


void gui_create( void ) {

	// Create your objects and place them on the screen etc...
    lv_task_create((void*)process_msg_q, 30, LV_TASK_PRIO_LOW, NULL );  // Create a task in LVGL to listen to a message queue and perform GUI related requests
 	
}


static void process_msg_q ( void ) {

	uint16_t 			msg;

	while( ( linux_message_queue_receive( your_queue, &msg ) ) ) { // IMPORTANT: THIS MUST BE A NON-BLOCKING RECEIVE FUNCTION

			switch( msg ) {

				case UPDATE_PART1_OF_GUI:			//  Your own requests to update parts of the gui
					update_gui_part1();
					break;

				case UPDATE_PART2_OF_GUI:
					update_gui_part2();
					break;

				case UPDATE_PART3_OF_GUI:
					update_gui_part3();
					break;

				.....
				
				
				case UPDATE_GUI_THEME:
					update_gui_theme();
					break;

				default:
					break;
			}
		}
	}
}

I hope this all makes sense, and is helpful.

I you have any questions please ask…

Kind Regards,

Pete