ESP32 FreeRTOS suggestion

Hi,

I don’t know if it is the right forum to ask.

I am using the example code from this link: “https://blog.littlevgl.com/2019-02-02/use-ipod-nano6-lcd-for-littlevgl”.

The “i2s_lcd.c” driver, provided by espressif, is a little complicated, so i am trying to understand to modify it.
I dont want to use dynamic memory allocation, so i converted to static allocation.
At first it’s working, i think only the function “void i2s_lcd_write_cmd (uint8_t cmd)” stopped working, i dont know why.
I also want to change the functionality of this driver a bit if i am not lost a lot.

From what i measured, the function “int i2s_lcd_write_data( void* src, size_t size, TickType_t ticks_to_wait, bool swap)”, only return after sending all data.
This way the use of dma doesn’t make much sense.

So…

what i want to do:
I created two equal sized buffer(1/10 lcd size each buffer).
I want to send the two data buffers using dma.
Littlevgl write the first buffer and send using dma.
While dma are send the first buffer the littlevgl library write the second buffer.
And so on…

Question:
How can switch the two buffers ?
i need to somehow test that the buffer1 has just been sent and the littlevgl library finished wrote in the buffer2.

I understand very little of rtos.
I should use something like this: “https://www.freertos.org/RTOS_Task_Notification_As_Binary_Semaphore.html” ???

How to integrate with the littlevgl library ?

I’m a little lost.

Thank’s.

LittlevGL should pass you a pointer to the correct buffer. You can use that to know what you are supposed to send next.

I need size too.
Because i need to fill dma descriptor according to the buffer size that littlevgl pass to me.

I think that i have to use this code as a base:

void ili9341_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
{
uint8_t data[4];

/*Column addresses*/
ili9341_send_cmd(0x2A);
data[0] = (area->x1 >> 8) & 0xFF;
data[1] = area->x1 & 0xFF;
data[2] = (area->x2 >> 8) & 0xFF;
data[3] = area->x2 & 0xFF;
ili9341_send_data(data, 4);

/*Page addresses*/
ili9341_send_cmd(0x2B);
data[0] = (area->y1 >> 8) & 0xFF;
data[1] = area->y1 & 0xFF;
data[2] = (area->y2 >> 8) & 0xFF;
data[3] = area->y2 & 0xFF;
ili9341_send_data(data, 4);

/*Memory write*/
ili9341_send_cmd(0x2C);


uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);

ili9341_send_color((void*)color_map, size * 2);

}

How does littlevgl know which buffer to write and which buffer to not write ?

Because the buffer that dma are using dont can be changed.

Did you look at the Display buffer and Display driver sections on the docs?

It’s been a while since i looked.

I’m currently trying to make esp32 work with a new i2s driver.

I am actually trying to write the i2s driver(parallel 8 bits) for now.

Hi,

Would it look something like this ?

Thank’s.

    lv_color_t buffer_a[15360];    // 1/5 display.
    lv_color_t buffer_b[15360];    // 1/5 display.

    static lv_disp_buf_t disp_buf;
    lv_disp_buf_init ( &disp_buf, buffer_a, buffer_b, 15360 );

    lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.flush_cb = ili9341_display_flush;
    disp_drv.buffer = &disp_buf;
    lv_disp_drv_register(&disp_drv);


void ili9341_display_flush ( lv_disp_drv_t * drv, const lv_area_t * area )
{
    /*Set Column addresses*/
    /*Set Page addresses*/
    /*Memory write instruction*/
    
    uint32_t length = (uint32_t) ( lv_area_get_width(area) * lv_area_get_height(area) );


    if ( drv->buffer->buf_act == &buffer_a )
    {
        i2s_lcd_write_data ( 2 * length, 0 );
    }
    else if ( drv->buffer->buf_act == &buffer_b )
    {
        i2s_lcd_write_data ( 2 * length, 1 );  
    }
    else
    {
        printf("bug");
        return;
    }

}

“drv->buffer->buf_act” are the buffer that littlevgl is writing or the buffer that was passed to the function “void ili9341_display_flush ( lv_disp_drv_t * drv, const lv_area_t * area )” ?

Someone ???

Hi @Baldhead,

I think that if you share with us what you did and what you tried, what works for you and what doesn’t, you’d get more responses.

For example, did you try working with the double buffer mode as describe in the docs?
You say “it’s been a while since I looked”. Did you look again?? What did you try? What was the result?

Did you examine lvgl source code? Did you search where buf_act is updated? Did you have difficulties figuring out how it works? What were your difficulties?

In my opinion, just “shooting out” questions like this is less effective and has lower chances to get someone to look into it and respond.

On the other hand, if you show everyone that you made an effort to try things, research, read the docs the examples and the library source code, and still you have a problem there - you’ll have a higher chances someone would respond.

Some good tips on how to ask a good question, which applies to any forum not only on SO: https://stackoverflow.com/help/how-to-ask (See the “Search and research” in bold?)

2 Likes

Hi,

It wasn’t me who wrote the library.

I just want to know:

“drv->buffer->buf_act” are the buffer that littlevgl is writing or the buffer that was passed to the function(it was already written) "void ili9341_display_flush ( lv_disp_drv_t * drv, const lv_area_t * area )” ?

Then i find a way to synchronize the buffers using freertos or only flags. Because i want to send one buffer using dma while the other buffer the cpu is updating.

Also, “buf_act” show a note that is for internal library use.

Thank’s.

I also needed to check the source code an it was quite easy to find by searching for “References to buf_act”.

This line clearly shows that buf_act is passed to flush_cb so it must be the buffer which was written by LittlevGL.

Thank’s Kisvegabor.

Sorry if i was stupid.

Would you tell me if this function is called by lib or i need to call it ?

LV_ATTRIBUTE_FLUSH_READY void lv_disp_flush_ready(lv_disp_drv_t * disp_drv)
{
    disp_drv->buffer->flushing = 0;

    /*If the screen is transparent initialize it when the flushing is ready*/
#if LV_COLOR_SCREEN_TRANSP
    if(disp_drv->screen_transp) {
        memset(disp_drv->buffer->buf_act, 0x00, disp_drv->buffer->size * sizeof(lv_color32_t));
    }
#endif
}

And the piece of code below.
The cpu stay locked here ?

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

Thank’s.

You need to call it yourself at the end of your disp_flush function. The documentation for the flush_cb callback mentions this.

Yes; that is expected until you call lv_disp_flush_ready (which internally sets vdb->flushing to 0).