mirror of
https://github.com/arendst/Tasmota.git
synced 2026-10-26 22:11:22 +00:00
LVGL add logging before crash when heap allocation fails (#25170)
This commit is contained in:
1 parent
43c6ca3686
commit
da51c9b1db
6 files changed
+66
-22
No files matched your search
@@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
|
||||
- Support MAC OUI wildcard for command MI32Keys in case multiple devices use same bindkey like IoTorero: `mi32keys 0C3D5EFFFFFF=48656c6c6f204254486f6d65210d0a00`
|
||||
- uDisplay support for SPI QSPI displays (#25156)
|
||||
- LVGL/HASPmota visual touch pointer (dot under finger) (#25158)
|
||||
- LVGL add logging before crash when heap allocation fails
|
||||
|
||||
### Breaking Changed
|
||||
- BTHome un-reverse MAC address usage for command `MI32Keys` to make it consistent
|
||||
|
||||
@@ -125,7 +125,7 @@ bool lv_colorwheel_set_hsv(lv_obj_t * obj, lv_color_hsv_t hsv)
|
||||
if(hsv.s > 100) hsv.s = 100;
|
||||
if(hsv.v > 100) hsv.v = 100;
|
||||
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return false);
|
||||
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||
|
||||
if(colorwheel->hsv.h == hsv.h && colorwheel->hsv.s == hsv.s && colorwheel->hsv.v == hsv.v) return false;
|
||||
@@ -160,7 +160,7 @@ bool lv_colorwheel_set_rgb(lv_obj_t * obj, lv_color_t color)
|
||||
*/
|
||||
void lv_colorwheel_set_mode(lv_obj_t * obj, lv_colorwheel_mode_t mode)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return);
|
||||
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||
|
||||
colorwheel->mode = mode;
|
||||
@@ -175,7 +175,7 @@ void lv_colorwheel_set_mode(lv_obj_t * obj, lv_colorwheel_mode_t mode)
|
||||
*/
|
||||
void lv_colorwheel_set_mode_fixed(lv_obj_t * obj, bool fixed)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return);
|
||||
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||
|
||||
colorwheel->mode_fixed = fixed;
|
||||
@@ -192,7 +192,7 @@ void lv_colorwheel_set_mode_fixed(lv_obj_t * obj, bool fixed)
|
||||
*/
|
||||
lv_color_hsv_t lv_colorwheel_get_hsv(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return (lv_color_hsv_t){0});
|
||||
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||
|
||||
return colorwheel->hsv;
|
||||
@@ -205,7 +205,7 @@ lv_color_hsv_t lv_colorwheel_get_hsv(lv_obj_t * obj)
|
||||
*/
|
||||
lv_color_t lv_colorwheel_get_rgb(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return lv_color_black());
|
||||
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||
|
||||
return lv_color_hsv_to_rgb(colorwheel->hsv.h, colorwheel->hsv.s, colorwheel->hsv.v);
|
||||
@@ -218,7 +218,7 @@ lv_color_t lv_colorwheel_get_rgb(lv_obj_t * obj)
|
||||
*/
|
||||
lv_colorwheel_mode_t lv_colorwheel_get_color_mode(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return LV_COLORWHEEL_MODE_HUE);
|
||||
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||
|
||||
return colorwheel->mode;
|
||||
@@ -231,7 +231,7 @@ lv_colorwheel_mode_t lv_colorwheel_get_color_mode(lv_obj_t * obj)
|
||||
*/
|
||||
bool lv_colorwheel_get_color_mode_fixed(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return false);
|
||||
lv_colorwheel_t * colorwheel = (lv_colorwheel_t *)obj;
|
||||
|
||||
return colorwheel->mode_fixed;
|
||||
|
||||
@@ -88,7 +88,7 @@ lv_obj_t * lv_stripes_create(lv_obj_t * parent)
|
||||
|
||||
void lv_stripes_set_stripe_color(lv_obj_t * obj, lv_color_t color)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return);
|
||||
lv_stripes_t * stripes = (lv_stripes_t *)obj;
|
||||
|
||||
if(lv_color_eq(stripes->stripe_color, color)) return;
|
||||
@@ -98,7 +98,7 @@ void lv_stripes_set_stripe_color(lv_obj_t * obj, lv_color_t color)
|
||||
|
||||
void lv_stripes_set_stripe_opa(lv_obj_t * obj, lv_opa_t opa)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return);
|
||||
lv_stripes_t * stripes = (lv_stripes_t *)obj;
|
||||
|
||||
if(stripes->stripe_opa == opa) return;
|
||||
@@ -108,7 +108,7 @@ void lv_stripes_set_stripe_opa(lv_obj_t * obj, lv_opa_t opa)
|
||||
|
||||
void lv_stripes_set_stripe_width(lv_obj_t * obj, int32_t width)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return);
|
||||
lv_stripes_t * stripes = (lv_stripes_t *)obj;
|
||||
|
||||
if(width < 1) width = 1;
|
||||
@@ -119,7 +119,7 @@ void lv_stripes_set_stripe_width(lv_obj_t * obj, int32_t width)
|
||||
|
||||
void lv_stripes_set_gap_width(lv_obj_t * obj, int32_t width)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return);
|
||||
lv_stripes_t * stripes = (lv_stripes_t *)obj;
|
||||
|
||||
if(width < 0) width = 0;
|
||||
@@ -130,7 +130,7 @@ void lv_stripes_set_gap_width(lv_obj_t * obj, int32_t width)
|
||||
|
||||
void lv_stripes_set_angle(lv_obj_t * obj, int32_t angle)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return);
|
||||
lv_stripes_t * stripes = (lv_stripes_t *)obj;
|
||||
|
||||
angle %= 360;
|
||||
@@ -142,7 +142,7 @@ void lv_stripes_set_angle(lv_obj_t * obj, int32_t angle)
|
||||
|
||||
void lv_stripes_set_offset(lv_obj_t * obj, int32_t offset)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return);
|
||||
lv_stripes_t * stripes = (lv_stripes_t *)obj;
|
||||
|
||||
if(stripes->offset == offset) return;
|
||||
@@ -156,42 +156,42 @@ void lv_stripes_set_offset(lv_obj_t * obj, int32_t offset)
|
||||
|
||||
lv_color_t lv_stripes_get_stripe_color(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return lv_color_black());
|
||||
lv_stripes_t * stripes = (lv_stripes_t *)obj;
|
||||
return stripes->stripe_color;
|
||||
}
|
||||
|
||||
lv_opa_t lv_stripes_get_stripe_opa(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return LV_OPA_TRANSP);
|
||||
lv_stripes_t * stripes = (lv_stripes_t *)obj;
|
||||
return stripes->stripe_opa;
|
||||
}
|
||||
|
||||
int32_t lv_stripes_get_stripe_width(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return 0);
|
||||
lv_stripes_t * stripes = (lv_stripes_t *)obj;
|
||||
return stripes->stripe_width;
|
||||
}
|
||||
|
||||
int32_t lv_stripes_get_gap_width(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return 0);
|
||||
lv_stripes_t * stripes = (lv_stripes_t *)obj;
|
||||
return stripes->gap_width;
|
||||
}
|
||||
|
||||
int32_t lv_stripes_get_angle(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return 0);
|
||||
lv_stripes_t * stripes = (lv_stripes_t *)obj;
|
||||
return stripes->angle;
|
||||
}
|
||||
|
||||
int32_t lv_stripes_get_offset(lv_obj_t * obj)
|
||||
{
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_CHECK_OBJ(obj, MY_CLASS, return 0);
|
||||
lv_stripes_t * stripes = (lv_stripes_t *)obj;
|
||||
return stripes->offset;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @file tasmota_lv_assert.h
|
||||
*
|
||||
* Custom LVGL assert handler for Tasmota, included by lv_conf_internal.h
|
||||
* when LV_ASSERT_USE_CUSTOM_INCLUDE is 1 (see tasmota_lv_conf.h).
|
||||
*
|
||||
* Replaces LVGL's default `while(1);` with a call that prints heap state
|
||||
* and aborts, so a failed assert gives a decodable backtrace and a reboot
|
||||
* instead of a silent hang. Implemented in xdrv_54_lvgl.ino.
|
||||
*/
|
||||
#ifndef TASMOTA_LV_ASSERT_H
|
||||
#define TASMOTA_LV_ASSERT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void lv_tasmota_assert_failed(void) __attribute__((noreturn));
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#define LV_ASSERT_HANDLER lv_tasmota_assert_failed();
|
||||
|
||||
#endif /*TASMOTA_LV_ASSERT_H*/
|
||||
@@ -2439,7 +2439,7 @@
|
||||
#define LV_USE_ASSERT 0
|
||||
|
||||
/** LV_ASSERT_MALLOC */
|
||||
#define LV_USE_ASSERT_MALLOC 0
|
||||
#define LV_USE_ASSERT_MALLOC 1
|
||||
|
||||
/** LV_ASSERT_NULL */
|
||||
#define LV_USE_ASSERT_NULL 0
|
||||
@@ -2471,7 +2471,7 @@
|
||||
/** Include the header given by LV_ASSERT_CUSTOM_INCLUDE, which must define
|
||||
* a custom LV_ASSERT_HANDLER.
|
||||
*/
|
||||
#define LV_ASSERT_USE_CUSTOM_INCLUDE 0
|
||||
#define LV_ASSERT_USE_CUSTOM_INCLUDE 1 // TASMOTA
|
||||
|
||||
#if LV_ASSERT_USE_CUSTOM_INCLUDE
|
||||
/** Optional header to override assert-related macros.
|
||||
@@ -2480,7 +2480,7 @@
|
||||
* Statement to execute when an assertion fails.
|
||||
* e.g. #define LV_ASSERT_HANDLER my_assert_failed(__FILE__, __LINE__);
|
||||
*/
|
||||
#define LV_ASSERT_CUSTOM_INCLUDE ""
|
||||
#define LV_ASSERT_CUSTOM_INCLUDE "tasmota_lv_assert.h" // TASMOTA
|
||||
|
||||
#endif /*LV_ASSERT_USE_CUSTOM_INCLUDE*/
|
||||
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp_rom_sys.h" // esp_rom_printf, used by lv_tasmota_assert_failed
|
||||
|
||||
// callback type when a screen paint is done
|
||||
typedef void (*lv_paint_cb_t)(int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint8_t *pixels);
|
||||
@@ -400,6 +402,21 @@ extern "C" {
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
// LVGL assert handler (LV_ASSERT_HANDLER, see tasmota/lvgl_berry/tasmota_lv_assert.h)
|
||||
// Print heap state without allocating, then abort() to get a backtrace and a reboot
|
||||
void lv_tasmota_assert_failed(void) {
|
||||
esp_rom_printf("\nLVG: assert failed, heap internal free %u largest %u",
|
||||
heap_caps_get_free_size(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT),
|
||||
heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT));
|
||||
if (heap_caps_get_total_size(MALLOC_CAP_SPIRAM) > 0) {
|
||||
esp_rom_printf(", psram free %u largest %u",
|
||||
heap_caps_get_free_size(MALLOC_CAP_SPIRAM),
|
||||
heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM));
|
||||
}
|
||||
esp_rom_printf("\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
#ifdef USE_LVGL_PNG_DECODER
|
||||
// for PNG decoder, use same allocators as LVGL
|
||||
void* lodepng_malloc(size_t size) { return lvbe_malloc(size); }
|
||||
|
||||
Reference in new issue
Block a user