ESP32-S3 DMA (EDMA) with PSRAM and LCD

accessays
Posts: 4
Joined: Sat Oct 30, 2021 1:11 pm

ESP32-S3 DMA (EDMA) with PSRAM and LCD

Postby accessays » Sat Oct 30, 2021 5:23 pm

Hello,

I am trying to get DMA working with PSRAM on ESP32-S3. From what I gather, it employs EDMA (as does ESP32-S2), which allows direct data transfer between PSRAM and peripherals, e.g. LCD. However, I've been unable to get it working properly. I used code from LVGL example in esp-idf as a base to make a simple program which just fills part of the screen with a solid color (the display I use has an R61529 controller which is not supported by esp-idf). It works just fine if the buffer I use is allocated in internal RAM (a single solid color as expected), but has weird glitchy effects if using PSRAM (random noise). I am sure some data is still sent in the PSRAM case, as the random noise clearly visible.

I've tried to change the data in the framebuffer after each render by memsetting the buffer in the on_color_trans_done callback. In PSRAM case, this just leads to small streaks of appearing in random places on the display (within the rendered area, which is just part of the whole).

Here is how I allocate the framebuffer:
NB: I would assume I'd need to allocate with MALLOC_CAP_DMA even with internal RAM, but somehow everything works even without that.

Code: Select all

// internal RAM allocation
char *framebuffer = heap_caps_malloc(LCD_H_RES * 40 * 2, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
// PSRAM allocation
char *framebuffer = heap_caps_malloc(LCD_H_RES * 40 * 2, MALLOC_CAP_8BIT|MALLOC_CAP_SPIRAM);
// PSRAM allocation, aligned
char *framebuffer = heap_caps_aligned_alloc(16, LCD_H_RES * 40 * 2, MALLOC_CAP_8BIT|MALLOC_CAP_SPIRAM);
I get the same issues irregardless of whether I use aligned alloc or not. I checked code for esp32-camera, as it had some mentions of EDMA, and saw that some sort of alignment was done there. Not sure if I am doing it properly, however.

Any ideas?

ESP_Sprite
Posts: 9769
Joined: Thu Nov 26, 2015 4:08 am

Re: ESP32-S3 DMA (EDMA) with PSRAM and LCD

Postby ESP_Sprite » Sun Oct 31, 2021 3:48 am

Likely you're not flushing your cache. There's a cache between the PSRAM and the CPU. The CPU accesses the PSRAM through that cache, but EDMA directly accesses the PSRAM without going through the cache, meaning stuff can get 'stuck' in that cache: thr CPU has written it, but the cache hasn't flushed it to PSRAM yet, so the EDMA doesn't see it. You can force a flush using something like:

Code: Select all

Cache_WriteBack_Addr((uint32_t)el_panel->fb[0], el_panel->fb_size);

accessays
Posts: 4
Joined: Sat Oct 30, 2021 1:11 pm

Re: ESP32-S3 DMA (EDMA) with PSRAM and LCD

Postby accessays » Sun Oct 31, 2021 6:57 pm

ESP_Sprite wrote:
Sun Oct 31, 2021 3:48 am
Likely you're not flushing your cache. There's a cache between the PSRAM and the CPU. The CPU accesses the PSRAM through that cache, but EDMA directly accesses the PSRAM without going through the cache, meaning stuff can get 'stuck' in that cache: thr CPU has written it, but the cache hasn't flushed it to PSRAM yet, so the EDMA doesn't see it. You can force a flush using something like:

Code: Select all

Cache_WriteBack_Addr((uint32_t)el_panel->fb[0], el_panel->fb_size);
Thank you! That did help. I am now facing new issues, however.

I'm continuously rendering to the LCD, and swapping the active buffer after each render. I would expect to see a tearing slideshow, which I do at lower frequencies (2 MHz). Going above 4 MHz, however, results in the image not being updated at all, or only very rarely. Sometimes it gets updated in intervals of a few seconds. Usually it just gets stuck at some color. This could be due to the controller not being able to handle higher data rates, but I doubt it. If I add some delays around the place, it seems to start working again. Plus, the display gets initialized properly, so I'd bet the controller can handle those data rates.

Another strange point is the number of frames sent. I use a volatile flag to make sure no frames are currently in transit, which gets reset in on_color_trans_done callback. I also set trans_queue_depth to 1 in esp_lcd_panel_io_i80_config_t, just in case.
Display size is 480x320, 2 bytes per pixel. At 2-4 MHz I get the expected framerate of 6-14 FPS respectively. At 5 MHz this breaks and I get a reported FPS of 32; the screen doesn't get updated consistently anymore. The frame counter is incremented every time a frame is sent to the queue.

Yet another issue is that, when a frame does occasionally get drawn at those higher frequencies, it has a part of the other buffer visible.
buffer-issue.jpg
buffer-issue.jpg (2.31 MiB) Viewed 6517 times
When the next buffer manages to get rendered, the colors are inverted. The buffers do not overlap, and they are never modified after being created, initialized and cache flushed.
The count of these pixels from the previous buffer is around 4096, so 8192 bytes.

Who is online

Users browsing this forum: No registered users and 92 guests