Flushing the cache (writeback)
Flushing the cache (writeback)
Hi,
So, it all started (as a newbie to ESP32 and Arduino IDE) when I found difficulty finding a GFX library for my board (Guition ESP32-S3-4848S040) and what files need to be modified related to the assignment of ESP pins to the LCD interface, and for the initialisation sequence for the ST7701 panel driver.
This is an ESP32-S3 based board with attached 480x480 touch panel, that has a 3-wire SPI and 16-pin RGB interface.
I have some code from a different manufacturer to that of the board I have, and it initialises the LCD and draws colour bars (and reads the touch panel, displaying the x,y).
Anyway, so I decided I wanted to write direct to the LCD frame buffer. This turned out easier than expected (perhaps even easier if you already know!). I wrote (hacked) a little code that searched the GDMA for the channel that was used for the LCD. Then using this info, looked in memory for the DMA linked list, got the address of the display buffer, and can now write direct to the screen.
As you know, the GDMA accesses the external memory (where the frame store is located - too wasteful for internal SRAM, and also a huge waste of internal bus resources) directly - bypassing the DCache. But the CPU has to go via this cache to get to external. So the problem is...
1) I can write to the frame buffer, but a lot of the data gets stuck in cache. I mean, it comes out eventually after doing more writes to different addresses, or forcing a load of reads, but there must be a way of forcing a cache writeback that's more efficient. I see a function called Cache_WriteBack_Addr, but don't know what it does (or how long it takes to execute), and what library I need to include.
2) Second question: in the GDMA linked list description in the esp tech ref manual (page 360 of the doc I have), bit 31 of DW0 defines the owner. What does this mean in reality? I know the GDMA can access the buffer (there is a display after all), and the CPU can write to the buffer too.
Thanks for any info.
So, it all started (as a newbie to ESP32 and Arduino IDE) when I found difficulty finding a GFX library for my board (Guition ESP32-S3-4848S040) and what files need to be modified related to the assignment of ESP pins to the LCD interface, and for the initialisation sequence for the ST7701 panel driver.
This is an ESP32-S3 based board with attached 480x480 touch panel, that has a 3-wire SPI and 16-pin RGB interface.
I have some code from a different manufacturer to that of the board I have, and it initialises the LCD and draws colour bars (and reads the touch panel, displaying the x,y).
Anyway, so I decided I wanted to write direct to the LCD frame buffer. This turned out easier than expected (perhaps even easier if you already know!). I wrote (hacked) a little code that searched the GDMA for the channel that was used for the LCD. Then using this info, looked in memory for the DMA linked list, got the address of the display buffer, and can now write direct to the screen.
As you know, the GDMA accesses the external memory (where the frame store is located - too wasteful for internal SRAM, and also a huge waste of internal bus resources) directly - bypassing the DCache. But the CPU has to go via this cache to get to external. So the problem is...
1) I can write to the frame buffer, but a lot of the data gets stuck in cache. I mean, it comes out eventually after doing more writes to different addresses, or forcing a load of reads, but there must be a way of forcing a cache writeback that's more efficient. I see a function called Cache_WriteBack_Addr, but don't know what it does (or how long it takes to execute), and what library I need to include.
2) Second question: in the GDMA linked list description in the esp tech ref manual (page 360 of the doc I have), bit 31 of DW0 defines the owner. What does this mean in reality? I know the GDMA can access the buffer (there is a display after all), and the CPU can write to the buffer too.
Thanks for any info.
-
- Posts: 2046
- Joined: Mon Oct 17, 2022 7:38 pm
- Location: Europe, Germany
Re: Flushing the cache (writeback)
As to 1): https://docs.espressif.com/projects/esp ... Pv6size_ti (Ballpark figure: My S3 takes about 2500-3000 CPU clock cycles @ 160MHz to complete flushing 1kB from cache to PSRAM.)
and 2): Haven't actually tried it, but supposedly the DMA transfer should abort/fail if the CPU is set as the 'owner' of a DMA block; hence the CPU needs to make sure it sets the owner to 'DMA' before a transfer, and may choose to 'lock out' DMA by setting the owner to 'CPU' when it's processing the buffer and cannot have the DMA access the memory. (The CPU can access the memory at all times, but the DMA must have 'permission' to do so.)
and 2): Haven't actually tried it, but supposedly the DMA transfer should abort/fail if the CPU is set as the 'owner' of a DMA block; hence the CPU needs to make sure it sets the owner to 'DMA' before a transfer, and may choose to 'lock out' DMA by setting the owner to 'CPU' when it's processing the buffer and cannot have the DMA access the memory. (The CPU can access the memory at all times, but the DMA must have 'permission' to do so.)
Re: Flushing the cache (writeback)
Thanks. That explains what owner means.
Regarding Cache_WriteBack_Addr, what files should be included in my sketch (I'm using Arduino IDE)?
Regarding Cache_WriteBack_Addr, what files should be included in my sketch (I'm using Arduino IDE)?
-
- Posts: 916
- Joined: Mon Jul 22, 2019 3:20 pm
Re: Flushing the cache (writeback)
https://github.com/search?q=repo%3Aespr ... &type=code
Looks like it is <esp32s3/rom/cache.h>
Looks like it is <esp32s3/rom/cache.h>
Re: Flushing the cache (writeback)
Thanks.
Is there any special library I need to install, as simply including cache.h causes a compiler error (file not found)?
Is there any special library I need to install, as simply including cache.h causes a compiler error (file not found)?
-
- Posts: 916
- Joined: Mon Jul 22, 2019 3:20 pm
Re: Flushing the cache (writeback)
You need to match the version and SoC. Using an esp32-s3 on v3.1.1 (current master), it is at <esp32s3/rom/cache.h>. Please actually look at the search link that I posted.
Re: Flushing the cache (writeback)
Thanks, I should've clicked further.
Now I have the assembler source for the cache writeback, but it has revealed another hole (in my knowledge). The assembler source references an ESP32S3 register called EXTMEM_DCACHE_SYNC_ADDR_REG. I cannot find any reference to this in the ESP32 technical manual.
But don't worry, I'm on a different track with my solution.
Now I have the assembler source for the cache writeback, but it has revealed another hole (in my knowledge). The assembler source references an ESP32S3 register called EXTMEM_DCACHE_SYNC_ADDR_REG. I cannot find any reference to this in the ESP32 technical manual.
But don't worry, I'm on a different track with my solution.
-
- Posts: 2046
- Joined: Mon Oct 17, 2022 7:38 pm
- Location: Europe, Germany
Re: Flushing the cache (writeback)
"Manually" syncing the cache is actually straight forward on the S3:
You write the start address of the memory region you want sync'ed to EXTMEM_DCACHE_SYNC_ADDR_REG, write the number of cache lines ("blocks", see EXTMEM_DCACHE_CTRL_REG) to sync to EXTMEM_DCACHE_SYNC_SIZE_REG, then trigger the desired operation by writing a '1' to the corresponding bit (e.g. EXTMEM_DCACHE_WRITEBACK_ENA) in EXTMEM_DCACHE_SYNC_CTRL_REG.
The operation then runs asynchronously (CPU can continue to do other stuff!) and clears the EXTMEM_DCACHE_..._ENA bit when it's done.
However, when programming the registers directly, you have to take care to do it in a thread-safe manner, and note that other code using the msync IDF-API or the ROM function may cause a conflict.
You write the start address of the memory region you want sync'ed to EXTMEM_DCACHE_SYNC_ADDR_REG, write the number of cache lines ("blocks", see EXTMEM_DCACHE_CTRL_REG) to sync to EXTMEM_DCACHE_SYNC_SIZE_REG, then trigger the desired operation by writing a '1' to the corresponding bit (e.g. EXTMEM_DCACHE_WRITEBACK_ENA) in EXTMEM_DCACHE_SYNC_CTRL_REG.
The operation then runs asynchronously (CPU can continue to do other stuff!) and clears the EXTMEM_DCACHE_..._ENA bit when it's done.
However, when programming the registers directly, you have to take care to do it in a thread-safe manner, and note that other code using the msync IDF-API or the ROM function may cause a conflict.
Re: Flushing the cache (writeback)
That's really useful info, ta.
Where are these registers documented? I have the espressif tech ref manual for the S3, but that address range is marked as reserved.
Where are these registers documented? I have the espressif tech ref manual for the S3, but that address range is marked as reserved.
-
- Posts: 2046
- Joined: Mon Oct 17, 2022 7:38 pm
- Location: Europe, Germany
Re: Flushing the cache (writeback)
All the info I have is from the comments at the register definitions in the header file, and rom/cache.h.
Yet the recommended way to interact with the cache is via the IDF's Memory Synchronization API.
Yet the recommended way to interact with the cache is via the IDF's Memory Synchronization API.
Who is online
Users browsing this forum: No registered users and 107 guests