[v8] Crash when calling lv_task_handler with non-static display driver

Hello, i started with porting LVGL now for my small project and i am running in some errors unfortunately

Description

It is based on an ILI9341 Display, FreeRTOS, and a STM32F767. I want now to Just get it set up and running. The Problem is now that after my initialization the STM32 goes to the Hard Fault Error. The first call of lv_task_handler(); is causing this error. I am sure it is some misconfiguration on my side, but i cant find it :pensive:

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

STM32F767 / STM32CubeIDE

What do you want to achieve?

Basically at the moment just a working LVGL setup, maybe some Text to test the porting

What have you tried so far?

I already tried to switch to FreeRTOS Malloc and alloc, but it didnt improve. Any help will be appreciated.
If anybody needs to access the whole code i can provide a github link.
Thank you !

Code to reproduce

LVGL Init:

  lv_init();
  /*Initialize `disp_buf` with the buffer(s) */
 	lv_disp_draw_buf_init(&disp_buf, buf_1, buf_2, MY_DISP_HOR_RES*10);
 	lv_disp_drv_t disp_drv;                 /*A variable to hold the drivers. Can be local variable*/
 	    lv_disp_drv_init(&disp_drv);            /*Basic initialization*/
 	    disp_drv.draw_buf = &disp_buf;            /*Set an initialized buffer*/
 	    disp_drv.flush_cb = my_flush_cb;        /*Set a flush callback to draw to the display*/
 	    lv_disp_t * disp;
 	    disp = lv_disp_drv_register(&disp_drv); /*Register the driver and save the created display objects*/

 	    /* USER CODE END 2 */

  /* Init scheduler */
  osKernelInitialize();

The Draw function:

void my_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    /*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
   /* int32_t x, y;
    for(y = area->y1; y <= area->y2; y++) {
        for(x = area->x1; x <= area->x2; x++) {
            put_px(x, y, *color_p)
            color_p++;
        }
    }*/

    ili9341_fill_block(_lcd, color_p, area->x1, area->y1, area->x2, area->y2);

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

The Handler Thread

void LVGL_Handler_Function(void *argument)
{
  /* USER CODE BEGIN LVGL_Handler_Function */
  /* Infinite loop */
  for(;;)
  {
	  lv_task_handler();
	  osDelay(5);
  }
  /* USER CODE END LVGL_Handler_Function */
}

Config File

#if 1/*Set it to "1" to enable content*/

#ifndef LV_CONF_H
#define LV_CONF_H
/*clang-format off*/

#include <stdint.h>


/*====================
   COLOR SETTINGS
 *====================*/

/*Color depth: 1 (1 byte per pixel), 8 (RGB332), 16 (RGB565), 32 (ARGB8888)*/
#define LV_COLOR_DEPTH     16
#define LV_HOR_RES_MAX 320
#define LV_VER_RES_MAX 240
/*Swap the 2 bytes of RGB565 color. Useful if the display has a 8 bit interface (e.g. SPI)*/
#define LV_COLOR_16_SWAP   0

/*Enable more complex drawing routines to manage screens transparency.
 *Can be used if the UI is above an other layer, e.g. an OSD menu or video player.
 *Requires `LV_COLOR_DEPTH = 32` colors and the screen's `bg_opa` should be set to non LV_OPA_COVER value*/
#define LV_COLOR_SCREEN_TRANSP    0

/*Images pixels with this color will not be drawn if they are  chroma keyed)*/
#define LV_COLOR_CHROMA_KEY    lv_color_hex(0x00ff00)         /*pure green*/

/*=========================
   MEMORY SETTINGS
 *=========================*/

/*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/
#define LV_MEM_CUSTOM      0
#if LV_MEM_CUSTOM ==0
/*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
#  define LV_MEM_SIZE    (32U * 1024U)          /*[bytes]*/

/*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
#  define LV_MEM_ADR          0     /*0: unused*/
#else       /*LV_MEM_CUSTOM*/
#  define LV_MEM_CUSTOM_INCLUDE <FreeRTOS.h>   /*Header for the dynamic memory function*/
#  define LV_MEM_CUSTOM_ALLOC     pvPortMalloc
#  define LV_MEM_CUSTOM_FREE      vPortFree
#  define LV_MEM_CUSTOM_REALLOC   vPortReAlloc
#endif     /*LV_MEM_CUSTOM*/

/*Use the standard `memcpy` and `memset` instead of LVGL's own functions. (Might or might not be faster).*/
#define LV_MEMCPY_MEMSET_STD    0

1 Like

Some code LVGL on the STM32F407VET6 with FreeRTOS

main.c

type or paste code here
/* USER CODE BEGIN 4 */
static int8_t i = 6;

void tick_thread (void)
{
  if(--i != 0) {return;}
  i = 6;
  lv_tick_inc(5);      /*Tell LVGL that 5 milliseconds were elapsed*/
}

/* USER CODE END 4 */

stm32f4xx_it.c

type or paste code here
/**
  * @brief This function handles TIM1 trigger and commutation interrupts and TIM11 global interrupt.
  */
void TIM1_TRG_COM_TIM11_IRQHandler(void)
{
  /* USER CODE BEGIN TIM1_TRG_COM_TIM11_IRQn 0 */
  tick_thread();									// tick for LVGL
  /* USER CODE END TIM1_TRG_COM_TIM11_IRQn 0 */
  HAL_TIM_IRQHandler(&htim11);
  /* USER CODE BEGIN TIM1_TRG_COM_TIM11_IRQn 1 */

  /* USER CODE END TIM1_TRG_COM_TIM11_IRQn 1 */
}

/* USER CODE BEGIN 1 */

Sorry, videos quality

Ahh I see. I am already calling the lv_tick_inc(1); in vApplicationTickHook, which is called every ms (i can verify in my debugger

I don’t use the FreeRTOS task handler tick. Please see on stm32f4xx_it.c :

  * @brief This function handles TIM1 trigger and commutation interrupts and TIM11 global interrupt.
  */
void TIM1_TRG_COM_TIM11_IRQHandler(void)
{
  /* USER CODE BEGIN TIM1_TRG_COM_TIM11_IRQn 0 */
  tick_thread();									// tick for LVGL
  /* USER CODE END TIM1_TRG_COM_TIM11_IRQn 0 */
  HAL_TIM_IRQHandler(&htim11);
  /* USER CODE BEGIN TIM1_TRG_COM_TIM11_IRQn 1 */

  /* USER CODE END TIM1_TRG_COM_TIM11_IRQn 1 */
}

I found the code line wher the device is crashing in lv_ref.c:

 disp_refr->driver->rounder_cb(disp_refr->driver, &tmp);

But this doesnt really make sence why it is even going in there, since i am not using a rounder

UPDATE: I now stopped FreeRTOS Execution, and called LVhandler in the while(1) loop instead of in a task. This seems working. So it has to do something with the FreeRTos Task, which somehow gets stuck.
My idea was a stack overflow, hence i increased stack size of the task to 2048 but it didnt change.
So even drawing works, but only before i start the RTOS, after the RTOS is started, and something has to be drawn it results in an hardfault

It seems that your display driver is being overwritten. If you are using v8 or newer you need to make sure disp_drv is declared as a static variable.

2 Likes

Thats it! Thanks

Great!

I edited your post title to hopefully be visible to future searchers as I suspect this will be a common issue. If you would prefer that I revert it, let me know.

1 Like