Stm32f4 + dma + freertos + double buf print problem

Description

Hi, I have a problem when I tried to optimice my_flush_cb function. I am using SPI by DMA, sending the buffer to display controller (RA8875). I have configured an FreeRTOS LVGL_task, where the lv_task_handler is updating each 5ms.

When I use my_flush_cb function in blocking mode, writing line by line of the buffer switching a FLAG in the wr_cplt_callback to increment the line to print, it works well. But i want to send the complete buffer setting an active windows and making lv_disp_flush_ready in the callback. When I made this, the display print until the last line and LVGL_task get block there, and never end to print the display.

I could solved this setting a taskDelay(5) in my_flush_cb function, but this make the print slow.

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

I am unsing an STM32F412 and Keil compiler

What LVGL version are you using?

V7.3

What do you want to achieve?

I want to accelerate my the draw map, using lv_disp_flush_ready in the wr complete callback of SPI by DMA transfer and double buffer.

I leave you an example code where you can see how it is working, and a picture where you can find the print problem

void my_flush_cb(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
    width = area->x2 - area->x1;   
    height = area->y2 - area->y1;  
    uint32_t count = (width+1)*(height+1)*2;
    new_buf_to_print=1;
    RA8875_Active_Window(area->x1,area->x2 ,area->y1 ,area->y2);
    RA8875_setXY(area->x1, area->y1); 
    RA8875_send((uint16_t *)color_p,count+1);  
  
//  ---------------------------- 
//            FLAG=0;
//        while(FLAG==0)
//                ;
//    ---------or--------------
//        vTaskDelay(10);
 
}    

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
  UNUSED(hspi);
    LCD_CS_GPIO_Port->BSRR = LCD_CS_Pin;
   FLAG=1;
   if(new_buf_to_print==1){
       new_buf_to_print=0;
       lv_disp_flush_ready(&disp_drv);
   }
}

void vApplicationTickHook(void)
{
   lv_tick_inc(1);
}
void vTaskLVGL( void *pvParameters )
{
    lv_init();
    lv_init_objects();
    for(;;){
        vTaskDelay(5);
        lv_task_handler();
    }
   vTaskDelete(NULL);
}

Screenshot and/or video

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

Thank you

In my_flush_cb you set new_buf_to_print = 0

In HAL_SPI_TxCpltCallback you have the

if(new_buf_to_print==1){

Seems to me, that you never can call lv_disp_flush_ready

Robekras. I just changed it, I made a mistake while copying the code. That global variable was initialized when I declared it equal to 0. So when my_flush_cb is called, it goes high, to indicate in the callback that the SPI was used to print to the screen, and then turn flag to low state .
Thanks

It still might be worth adding a printf (if you can use it inside an interrupt handler) above lv_disp_flush_ready to be sure that it gets called. That would be the most likely culprit.

I was debugging the code and I found that the task stay wating in the while(vdb->flushing). It is extrange because the screen reach to print until the last buffer portion, but block there, and never end. So callback is working, but is there a momement that not?

static void lv_refr_vdb_flush(void)
{
    lv_disp_buf_t * vdb = lv_disp_get_buf(disp_refr);

    /*In double buffered mode wait until the other buffer is flushed before flushing the current
     * one*/
    if(lv_disp_is_double_buf(disp_refr)) {
        while(vdb->flushing) {
            if(disp_refr->driver.wait_cb) disp_refr->driver.wait_cb(&disp_refr->driver);
        }
    }
...
}

That means that lv_disp_flush_ready is not being called on the last buffer.

Yes, that means that lv_disp_flush_ready is not being called on the last buffer, also I put a counter and i could to proove that SPI_cpltcallback isn’t entering.
I can’t understand why if i put a wait loop as an while() or for() after the SPI transfer by DMA, spi_cpltcallback running on the last buffer and lv_disp_flush_ready is called.
Could it be a setting of interrupts with FreeRTOS?

I’ve taken a look at my ARM projects.

Priority for the interrupts is set within the FreeRTOSConfig.h.
Priorities should be same or greater as configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
e.g.
#define config_UART1_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 0)
or
#define config_UART1_INTERRUPT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 1)