tuupola / esp_effects

Old school demo effects for ESP32
MIT No Attribution
42 stars 5 forks source link

Slow and crashing on ESP32 #17

Open VictorLamoine opened 4 months ago

VictorLamoine commented 4 months ago

I'm using a ESP32 WROOM board and a ILI9341 TFT display.

#
# Hardware Agnostic Graphics Library (HAGL)
#
CONFIG_HAGL_TJPGD_NEEDS_BYTESWAP=y
# end of Hardware Agnostic Graphics Library (HAGL)

#
# Hardware Agnostic Graphics Library HAL (MIPI)
#

#
# Display orientation
#
CONFIG_MIPI_DCS_ADDRESS_MODE_MIRROR_Y_SELECTED=y
# CONFIG_MIPI_DCS_ADDRESS_MODE_MIRROR_X_SELECTED is not set
# CONFIG_MIPI_DCS_ADDRESS_MODE_SWAP_XY_SELECTED is not set
# CONFIG_MIPI_DCS_ADDRESS_MODE_FLIP_X_SELECTED is not set
# CONFIG_MIPI_DCS_ADDRESS_MODE_FLIP_Y_SELECTED is not set
# end of Display orientation

CONFIG_MIPI_DCS_ADDRESS_MODE_MIRROR_Y=0x80
CONFIG_MIPI_DCS_ADDRESS_MODE_MIRROR_X=0x00
CONFIG_MIPI_DCS_ADDRESS_MODE_SWAP_XY=0x00
CONFIG_MIPI_DCS_ADDRESS_MODE_FLIP_X=0x00
CONFIG_MIPI_DCS_ADDRESS_MODE_FLIP_Y=0x00
# CONFIG_MIPI_DCS_PIXEL_FORMAT_24BIT_SELECTED is not set
# CONFIG_MIPI_DCS_PIXEL_FORMAT_18BIT_SELECTED is not set
CONFIG_MIPI_DCS_PIXEL_FORMAT_16BIT_SELECTED=y
# CONFIG_MIPI_DCS_PIXEL_FORMAT_12BIT_SELECTED is not set
# CONFIG_MIPI_DCS_PIXEL_FORMAT_8BIT_SELECTED is not set
# CONFIG_MIPI_DCS_PIXEL_FORMAT_3BIT_SELECTED is not set
CONFIG_MIPI_DISPLAY_PIXEL_FORMAT=0x55
CONFIG_MIPI_DISPLAY_DEPTH=16
CONFIG_HAGL_HAL_NO_BUFFERING=y
# CONFIG_HAGL_HAL_USE_DOUBLE_BUFFERING is not set
# CONFIG_HAGL_HAL_USE_TRIPLE_BUFFERING is not set
CONFIG_MIPI_DISPLAY_WIDTH=240
CONFIG_MIPI_DISPLAY_HEIGHT=320
CONFIG_MIPI_DISPLAY_OFFSET_X=0
CONFIG_MIPI_DISPLAY_OFFSET_Y=0
# CONFIG_MIPI_DISPLAY_INVERT is not set
# CONFIG_MIPI_DCS_ADDRESS_MODE_BGR_SELECTED is not set
CONFIG_MIPI_DCS_ADDRESS_MODE_BGR=0x00
CONFIG_MIPI_DISPLAY_SPI_CLOCK_SPEED_HZ=40000000
CONFIG_MIPI_DISPLAY_SPI_MODE=0
CONFIG_ESP32_HSPI_HOST_SELECTED=y
# CONFIG_ESP32_VSPI_HOST_SELECTED is not set
CONFIG_MIPI_DISPLAY_SPI_HOST=0x01
CONFIG_MIPI_DISPLAY_PIN_MISO=-1
CONFIG_MIPI_DISPLAY_PIN_MOSI=23
CONFIG_MIPI_DISPLAY_PIN_CLK=18
CONFIG_MIPI_DISPLAY_PIN_CS=15
CONFIG_MIPI_DISPLAY_PIN_DC=2
CONFIG_MIPI_DISPLAY_PIN_RST=4
CONFIG_MIPI_DISPLAY_PIN_BL=32
CONFIG_MIPI_DISPLAY_PIN_BL_ACTIVE=1
CONFIG_MIPI_DISPLAY_PWM_BL=-1
# end of Hardware Agnostic Graphics Library HAL (MIPI)

The provided example is very slow (0 FPS) and crashes. I'm not sure exactly what to expect in terms of speed. Here is a short video.

--- esp-idf-monitor 1.4.0 on /dev/ttyUSB0 115200 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
[0;32mI (195) esp_image: segment 4: paddr=0004d2dc vaddr=40089a98 size=05354h ( 2133�ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0030,len:7172
load:0x40078000,len:15540
load:0x40080400,len:4
0x40080400: _init at ??:?

ho 8 tail 4 room 4
load:0x40080404,len:3904
entry 0x40080640
I (30) boot: ESP-IDF v5.2.1-dirty 2nd stage bootloader
I (31) boot: compile time May  2 2024 11:33:44
I (31) boot: Multicore bootloader
I (35) boot: chip revision: v1.0
I (39) boot.esp32: SPI Speed      : 40MHz
I (44) boot.esp32: SPI Mode       : DIO
I (48) boot.esp32: SPI Flash Size : 2MB
I (53) boot: Enabling RNG early entropy source...
I (58) boot: Partition Table:
I (62) boot: ## Label            Usage          Type ST Offset   Length
I (69) boot:  0 nvs              WiFi data        01 02 00009000 00006000
I (77) boot:  1 phy_init         RF data          01 01 0000f000 00001000
I (84) boot:  2 factory          factory app      00 00 00010000 00100000
I (92) boot: End of partition table
I (96) esp_image: segment 0: paddr=00010020 vaddr=3f400020 size=1413ch ( 82236) map
I (132) esp_image: segment 1: paddr=00024164 vaddr=3ffb0000 size=02414h (  9236) load
I (136) esp_image: segment 2: paddr=00026580 vaddr=40080000 size=09a98h ( 39576) load
I (154) esp_image: segment 3: paddr=00030020 vaddr=400d0020 size=1d2b4h (119476) map
I (195) esp_image: segment 4: paddr=0004d2dc vaddr=40089a98 size=05354h ( 21332) load
I (211) boot: Loaded app from partition at offset 0x10000
I (211) boot: Disabling RNG early entropy source...
I (222) cpu_start: Multicore app
I (231) cpu_start: Pro cpu start user code
I (231) cpu_start: cpu freq: 160000000 Hz
I (231) cpu_start: Application information:
I (234) cpu_start: Project name:     esp_effects
I (240) cpu_start: App version:      e224459-dirty
I (245) cpu_start: Compile time:     May  2 2024 13:57:12
I (251) cpu_start: ELF file SHA256:  08e717853...
I (257) cpu_start: ESP-IDF:          v5.2.1-dirty
I (262) cpu_start: Min chip rev:     v0.0
I (267) cpu_start: Max chip rev:     v3.99 
I (271) cpu_start: Chip rev:         v1.0
I (276) heap_init: Initializing. RAM available for dynamic allocation:
I (284) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM
I (289) heap_init: At 3FFB32C0 len 0002CD40 (179 KiB): DRAM
I (296) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM
I (302) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM
I (308) heap_init: At 4008EDEC len 00011214 (68 KiB): IRAM
I (316) spi_flash: detected chip: generic
I (319) spi_flash: flash io: dio
W (323) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (337) main_task: Started on CPU0
I (347) main_task: Calling app_main()
I (2347) main: SDK version: v5.2.1-dirty
I (2347) main: Heap when starting: 298844
I (3247) mipi_display: Enabling backlight pin 32
I (3247) mipi_display: Display initialized.
I (3247) main: Heap after HAGL init: 289024
I (3247) main_task: Returned from app_main()
I (3247) main: 3 METABALLS    0.0 FPS
I (4477) main: Heap after plasma init: 205292
I (14477) main: PALETTE PLASMA 0.0 FPS
I (14527) main: Heap after rotozoom init: 282480
I (24527) main: ROTOZOOM       0.0 FPS
Guru Meditation Error: Core  1 panic'ed (StoreProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x400d639c  PS      : 0x00060130  A0      : 0x800d5a80  A1      : 0x3ffbb1a0  
0x400d639c: deform_init at /media/victor/Data/Documents/code/esp_idf/esp_effects/main/deform.c:94

A2      : 0x3ffb2b98  A3      : 0xc016cbe4  A4      : 0x3fb504f3  A5      : 0x00000000  
A6      : 0x00000000  A7      : 0x00000000  A8      : 0xffffffd7  A9      : 0xffffffe0  
A10     : 0x0000003f  A11     : 0x3fb504f3  A12     : 0x00000014  A13     : 0x000000ef  
A14     : 0x0000012b  A15     : 0x00000000  SAR     : 0x0000000f  EXCCAUSE: 0x0000001d  
EXCVADDR: 0x00000000  LBEG    : 0x4000c2e0  LEND    : 0x4000c2f6  LCOUNT  : 0x00000000  
0x4000c2e0: memcpy in ROM
0x4000c2f6: memcpy in ROM

Backtrace: 0x400d6399:0x3ffbb1a0 0x400d5a7d:0x3ffbb1d0 0x400872bd:0x3ffbb200
0x400d6399: deform_init at /media/victor/Data/Documents/code/esp_idf/esp_effects/main/deform.c:92
0x400d5a7d: switch_task at /media/victor/Data/Documents/code/esp_idf/esp_effects/main/main.c:148
0x400872bd: vPortTaskWrapper at /home/victor/software/esp-idf-v5.2.1/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:134

ELF file SHA256: 08e717853

Rebooting...

This example works well, is the display writing speed what is expected? Video

#include "sdkconfig.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/event_groups.h>
#include <esp_log.h>

#include <font6x9.h>
#include <aps.h>
#include <fps.h>
#include <hagl_hal.h>
#include <hagl.h>

static hagl_backend_t *display;

void
app_main()
{
    vTaskDelay(2000 / portTICK_PERIOD_MS);

    display = hagl_init();
    hagl_clear(display);

    // Draw lines
    for (uint16_t i = 1; i < 100; i++) {
        int16_t x0 = rand() % display->width;
        int16_t y0 = rand() % display->height;
        int16_t x1 = rand() % display->width;
        int16_t y1 = rand() % display->height;
        hagl_color_t color = rand() % 0xffff;

        hagl_draw_line(display, x0, y0, x1, y1, color);
        vTaskDelay(10 / portTICK_PERIOD_MS);
    }

    // Draw disks
    for (uint16_t i = 1; i < 100; i++) {
        int16_t x0 = rand() % display->width;
        int16_t y0 = rand() % display->height;
        int16_t radius = rand() % 50;
        hagl_color_t color = rand() % 0xffff;

        hagl_fill_circle(display, x0, y0, radius, color);
        vTaskDelay(10 / portTICK_PERIOD_MS);
    }

    // Draw texts
    for (uint16_t i = 1; i < 100; i++) {
        int16_t x0 = rand() % display->width;
        int16_t y0 = rand() % display->height;
        hagl_color_t color = rand() % 0xffff;

        wchar_t message[] = L"Hello World";
        hagl_put_text(display, message, x0, y0, color, font6x9);
    }

    while(1)
    {
       vTaskDelay(2000 / portTICK_PERIOD_MS);
    };
}

Any idea of what is going wrong here?

VictorLamoine commented 4 months ago

The other demos are working fine, deform_init most probably goes out of memory but I've not tried to debug more yet. I'm more curious about the slow speed of drawing issue 😄

VictorLamoine commented 4 months ago

Enabling the double buffering solves the FPS issue, I now get ~ 20 FPS 👍🏼 Triple buffering seems to require too much memory for my µC!

tuupola commented 4 months ago

Depending on the effect you should get around 25FPS with 320x240 display.

https://vimeo.com/419551395

Looking at your config you do not have buffering enabled. You need to enable double buffering to have any decent speeds.

CONFIG_HAGL_HAL_USE_DOUBLE_BUFFERING=y

You could try to use the M5Stack config as basis for your board: https://github.com/tuupola/esp_effects/blob/master/sdkconfig.m5stack

VictorLamoine commented 4 months ago

For future viewers of this issue, my little demo updated with double buffering support:

#include "sdkconfig.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/event_groups.h>
#include <esp_log.h>

#include <font6x9.h>
#include <aps.h>
#include <fps.h>
#include <hagl_hal.h>
#include <hagl.h>

static EventGroupHandle_t event;
static hagl_backend_t *display;

static const uint8_t RENDER_FINISHED = (1 << 0);

void
flush_task(void *params)
{
    while (1) {
        EventBits_t bits = xEventGroupWaitBits(
            event,
            RENDER_FINISHED,
            pdTRUE,
            pdFALSE,
            0
        );

        /* Flush only when RENDER_FINISHED is set. */
        if ((bits & RENDER_FINISHED) != 0 ) {
            hagl_flush(display);
        }

        vTaskDelay(20 / portTICK_PERIOD_MS);
    }

    vTaskDelete(NULL);
}

void
app_main()
{
    vTaskDelay(2000 / portTICK_PERIOD_MS);

    event = xEventGroupCreate();

#ifdef HAGL_HAS_HAL_BACK_BUFFER
    xTaskCreatePinnedToCore(flush_task, "Flush", 4096, NULL, 1, NULL, 0);
#endif

    display = hagl_init();
    hagl_clear(display);
    xEventGroupSetBits(event, RENDER_FINISHED);

    // Draw lines
    for (uint16_t i = 1; i < 100; i++) {
        int16_t x0 = rand() % display->width;
        int16_t y0 = rand() % display->height;
        int16_t x1 = rand() % display->width;
        int16_t y1 = rand() % display->height;
        hagl_color_t color = rand() % 0xffff;

        hagl_draw_line(display, x0, y0, x1, y1, color);
        xEventGroupSetBits(event, RENDER_FINISHED);
    }

    vTaskDelay(10 * portTICK_PERIOD_MS);

    // Draw disks
    for (uint16_t i = 1; i < 100; i++) {
        int16_t x0 = rand() % display->width;
        int16_t y0 = rand() % display->height;
        int16_t radius = rand() % 50;
        hagl_color_t color = rand() % 0xffff;

        hagl_fill_circle(display, x0, y0, radius, color);
        xEventGroupSetBits(event, RENDER_FINISHED);
    }

    vTaskDelay(10 * portTICK_PERIOD_MS);

    // Draw texts
    for (uint16_t i = 1; i < 100; i++) {
        int16_t x0 = rand() % display->width;
        int16_t y0 = rand() % display->height;
        hagl_color_t color = rand() % 0xffff;

        wchar_t message[] = L"Hello World";
        hagl_put_text(display, message, x0, y0, color, font6x9);
        xEventGroupSetBits(event, RENDER_FINISHED);
    }
}

It works great, thanks a lot for the hard work!