Flush_cb not executed onSTM32F46DISC

flush_cb not being executed

STM32F746DISC, makefile, Notepad++, gcc

Create driver for Discovery board

I created the driver using https://github.com/Shadofisher/STM32F746_LittleVGL as a base. The examples were used to wrap the code in Micropython. Compile is good and functions visible in Micropython. Init() executes without any problem but the flush_cb is never executed. I tried both registering the driver in C and Micropython but the same result. There is a LED on board that I use to see the activity, but there is no change in LED status. Anybody who have done the driver for 746DISC board?

Code to reproduce

Add the relevant code snippets here.

The code block(s) should be between ```c and ``` tags:

#define LAYER0_ADDRESS               (0xc0000000)

static uint32_t * my_fb = (uint32_t *)LAYER0_ADDRESS;

void CopyBuffer(const uint32_t *pSrc, uint32_t *pDst, uint16_t x, uint16_t y, uint16_t xsize, uint16_t ysize)
{
	HAL_GPIO_WritePin(GPIOI, GPIO_PIN_1, GPIO_PIN_SET); /* LED ON */
	uint32_t row;
	
	for(row = y; row < y + ysize; row++ ) {
		memcpy(&pDst[row * 480 + x], pSrc, xsize * 2);
		pSrc += xsize;
	} 
	HAL_GPIO_WritePin(GPIOI, GPIO_PIN_1, GPIO_PIN_RESET); /* LED OFF */
}

static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
 
	CopyBuffer((const uint32_t *)color_p, my_fb, area->x1, area->y1, lv_area_get_width(area), lv_area_get_height(area));

    /* IMPORTANT!!!
     * Inform the graphics library that you are ready with the flushing*/
    lv_disp_flush_ready(disp_drv);
}

STATIC mp_obj_t init(void) {

	    
	//static lv_disp_buf_t disp_buf;
	//static lv_color_t buf_1[LV_HOR_RES_MAX * LV_VER_RES_MAX];            /*A screen sized buffer*/
    //static lv_color_t buf_2[LV_HOR_RES_MAX * LV_VER_RES_MAX];            /*An other screen sized buffer*/
    //lv_disp_buf_init(&disp_buf, buf_1, NULL, LV_HOR_RES_MAX * LV_VER_RES_MAX);   /*Initialize the display buffer*/
	//lv_disp_buf_init(&disp_buf, (lv_color_t *)0xC0000000, (lv_color_t *)0xC0050000, 130560);

    //lv_disp_drv_t disp_drv;                         /*Descriptor of a display driver*/
    //lv_disp_drv_init(&disp_drv);                    /*Basic initialization*/

    //disp_drv.hor_res = 480;
    //disp_drv.ver_res = 272;
	

    /*Used to copy the buffer's content to the display*/
    //disp_drv.flush_cb = disp_flush;

    /*Set a display buffer*/
    //disp_drv.buffer = &disp_buf;

    /*Finally register the driver*/
    //lv_disp_drv_register(&disp_drv);
	
	disp_init(); /* This part set the LTDC and DMA2D peripherals */

    return mp_const_none;
}

// Define a Python reference to the function above
STATIC MP_DEFINE_CONST_FUN_OBJ_1(init_obj, init);
DEFINE_PTR_OBJ(disp_flush);
// Define all properties of the example module.
// Table entries are key/value pairs of the attribute name (a string)
// and the MicroPython object reference.
// All identifiers and strings are written as MP_QSTR_xxx and will be
// optimized to word-sized integers by the build system (interned strings).
STATIC const mp_rom_map_elem_t ltdc_globals_table[] = {
    { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ltdc) },
    { MP_ROM_QSTR(MP_QSTR_init), MP_ROM_PTR(&init_obj) },
    { MP_ROM_QSTR(MP_QSTR_disp_flush), MP_ROM_PTR(&PTR_OBJ(disp_flush))},
};
STATIC MP_DEFINE_CONST_DICT(ltdc_module_globals, ltdc_globals_table);

// Define module object.
const mp_obj_module_t ltdc_cmodule = {
    .base = { &mp_type_module },
    .globals = (mp_obj_dict_t*)&ltdc_module_globals,
};

// Register the module to make it available in Python
MP_REGISTER_MODULE(MP_QSTR_ltdc, ltdc_cmodule, MODULE_LTDC_ENABLED);

// For the Micropython code : 

import lvgl as lv
import ltdc
import lvstm32

lv.init()
ltdc.init()

disp_buf1 = lv.disp_buf_t()
buf1_1 = bytearray(480*272)
lv.disp_buf_init(disp_buf1,buf1_1, None, len(buf1_1)//4)
disp_drv = lv.disp_drv_t()
lv.disp_drv_init(disp_drv)
disp_drv.buffer = disp_buf1
disp_drv.flush_cb = ltdc.disp_flush
disp_drv.hor_res = 480
disp_drv.ver_res = 272
lv.disp_drv_register(disp_drv)

scr = lv.obj()
btn = lv.btn(scr)
btn.align(lv.scr_act(), lv.ALIGN.CENTER, 0, 0)
label = lv.label(btn)
label.set_text("Hello World!")
lv.scr_load(scr)
 

Screenshot and/or video

If possible, add screenshots and/or videos about the current state.

This PR was being worked on before: https://github.com/littlevgl/lv_binding_micropython/pull/72

@amirgon Is there any issue with the way @jang is wrapping disp_flush?

Hi @jang!

First, as @embeddedt suggested, please have a look at STM32F7DISC PR.

I would be happy to see that PR merged, we have some discussion there about the display buffer RAM. External RAM may be too slow, SRAM is not managed by Micropython… Do you have any opinion about this?

About your code, lets try to debug it:
I can see you are using lvstm32 for scheduling calls to lv.tick_inc and lv.task_handler. That’s good.
Please try to call lv.tick_inc and lv.task_handler explicitly. Is flush_cb called when calling lv.task_handler?

  • If it is, then Micropython scheduling is not working for you. Maybe it’s not enabled on your Micropython fork. Maybe it doesn’t get a chance to get called. Maybe REPL is blocking it.
  • If it is not, then something is wrong with the driver registration. Try to set disp_drv.flush_cb to a
    simple python function that prints something instead of ltdc.disp_flush. Does it work?

Hi @amirgon and embeddedt
Thanks for your help. I am a hardware guy and is a newbie to anything other than assembler, so please excuse my lack of knowledge in this field. Your skills, effort and contribution is highly respected and appreciated.

I used the main rep https://github.com/littlevgl/lv_micropython.git
Unfortunately the NVIC suggestion as well as replacing the flush callback with other print also did not work.
image

I also cloned the fork from @prolomb mentioned in the other PR
https://github.com/prolomb/micropython/tree/lvgl_driver_STM32F7DISC but it would not build “out the box”.

Hi @amirgon and @prolomb
Got it working.
What I did was to use https://github.com/littlevgl/lv_micropython.git as base and make the additions precisely as described by @prolomb in the PR, added the driver in the lib and also needed to delete the #define MICROPY_PY_LVGL (1) on line 176 of mpconfigport.h.
Now I can play with LVGL. Thank you guys very much.

1 Like

Hi @jang

Congratulations you got it working.

Could you please explain a little; in which directories you put which library files and how to apply the patched lv_binding_micropython to lv_micropython source repository.

In the PR there are 15 files, 10 of them are new library files that look like to go (finally) in a new stm32 directory in lv_microphthon/drivers folder, 3 example files look to be patched and staying in lv_binding_micropython_examples directory together with the new example3.py, it is also clear that 6 files in lv_micropython source have to be modified as explained in the PR, but I couldn’t understand what to do with the patched lv_conf.h because I couldn’t find yet any clear explanation on how to apply the lv_binding_micropython to micropython.

I appreciate very much if someone explains or shows me how/to guide on how to apply the lv_binding_micropython to micropython source code.

Thanks in advance.

Hi @ta1db!
“lv_binding_micropython” is a statically linked library in Micropython, which includes lvgl and the binding code between lvgl and Micropython.

Please have a look at lv_micropython which is a fork of Micropython with lv_binding_micropython library as a git submodule.
You can find more information in the README file.

Hi @amirgon
I see, I couldn’t think lv_binding_micropython as a git submodule in a remote repository. Now the situation is more understandable for me.
@jang I appreciate if you can also make a few comments.
Thanks to all of you.

Hi @ta1db,
It was very confusing to me because I had no experience with Micropython.
The recipe which worked for me was to clone the lv_micropython repo.
Then take the micropython/lib/lv_binding_micropython/driver/stm32/ from @prolomb
and drop it in lv_micropython/lib/lv_bindings/driver/stm32/.
Do the rest of the PR and edit line 176 of mpconfigport.h.
I hope you have success.

Hi @jang
Thank you for your kind return.
As I said after I learned lv_binding_micropython is a git submodule binding micropython and lvgl, everything became understandable for me. I already tested a ready build found here it works well but there is a bug, lvgl fellows are trying to fix the bug here , I am waiting fixing of the bug, afterwards I will make my own build. Now I am doing experiments with lv_port_stm32f746_disco_sw4stm32
My primary intention is to learn and experiment the lvgl, there is no an urgent project at my side, I am experimenting with lvgl in C already, will continue with Micropython, I will also test the lv_port_linux_frame_buffer
Kind regards…