-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
ports/stm32: Add memory map with attributes for different MCU families. #16644
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
This is cool and would be very useful. |
@dpgeorge Any thoughts? |
@iabdalkader can you point out on the "patches to all of those driver" that you mentioned in your post. |
Those patches are not applicable for all cases, otherwise I would have sent them as fixes. For example DAC uses DMA, in |
Exactly, here we have the issue with dac.write_timed(dacBuf, dacTimer, mode=dac.CIRCULAR) for the Nucleo STM32F767ZI board. |
Yes, it is. This patch may fix it for you, but it's not a good long-term solution. The proper fix is this feature proposed here. diff --git a/ports/stm32/dac.c b/ports/stm32/dac.c
index 54d5acc6c..dcbd93516 100644
--- a/ports/stm32/dac.c
+++ b/ports/stm32/dac.c
@@ -198,6 +198,10 @@ static void dac_start_dma(uint32_t dac_channel, const dma_descr_t *dma_descr, ui
#endif
}
+ #ifdef __DCACHE_PRESENT
+ MP_HAL_CLEAN_DCACHE(buf, len);
+ #endif
+
dma_nohal_deinit(dma_descr);
dma_nohal_init(dma_descr, DMA_MEMORY_TO_PERIPH | dma_mode | dma_align);
dma_nohal_start(dma_descr, (uint32_t)buf, base + dac_align, len); |
@iabdalkader thank you for reply. |
Every driver here can be affected by cache or other memory related issues. That's what I'm trying to fix with this new feature. |
I think the crucial aspect of this, and perhaps the most glossed over portion, is the proposal for the ability to alloc memory from a pool with the given attributes. Since an SRAM/PSRAM hybrid (we're working toward this on RP2) is, from the perspective of userspace, a total lottery (caveat that if you alloc early you'll probably be in SRAM if there's enough and if it's up-front) then there's nothing the end-user can really do if a driver requires DMA-accessible RAM, fast RAM, page-aligned RAM etc but expects a Can we get away with adding new syntax for this? Allocation decorators? 😆 @memory.SRAM(align=1024)
buffer = bytearray(1024)
@memory.any(align=1024, dma=True)
buffer = bytearray(1024) Or a context manager? with memory.any(align=1024, dma=True):
buffer1 = bytearray(1024)
buffer2 = bytearray(1024) |
I haven't thought about exposing this functionality to Python code, I was mainly concerned with C code/drivers, but I can see how this might be very useful for Python drivers, or even regular code that requires a small amount of fast memory. As for syntax, I personally prefer the decorators over the context, but I guess we could have both. Either way, the memory map support has to exist first in C. |
I've thought about context managers as a clean syntax for times when python needs ram from a particular source, or aligned etc, that has my vote! There's slight complications in that it would probably need to be thread aware to ensure the hint passed to the gc by the context manager only affects the current thread, but otherwise should be fairly straightforward. |
Currently no, the conceit is that it could be so on MicroPython but then we never know if that might cause some future turmoil if CPython allows them on statements. A context manager is probably the safest bet.
And, indeed, step one is to mark up RAM with the appropriate attributes! |
Passing buffers to ESP32S3's SIMD unit could also benefit from this - my DSP code was spending an awful amount of time to handle unaligned loads and stores, and it was faster (in every sense of the word) to move buffer management to the C side so I could have a properly aligned buffer to pass to SIMD code. |
Description
There's a general DMA/Cache-management issue with the MicroPython's stm32 port; most drivers make assumptions about the memory (cachable or not DAM-acessible or not) which probably works fine for all (most?) of the default linker scripts, which happen to place everything in one memory region, but when buffers are moved around, drivers starts failing.
A few examples to demonstrate the issue (there are many more in sdcard, I2C etc..):
DAC should flush buffer before DMA call if memory is cacheable and fail if it's not DMA-accesible:
micropython/ports/stm32/dac.c
Line 201 in a4ab847
SPI regular transfer (fallback) path should be taken if the memory is not accessible by DMA:
micropython/ports/stm32/spi.c
Line 588 in a4ab847
For example:
if (len == 1 || query_irq() == IRQ_STATE_DISABLED || !dma_is_accessible(src)) {
SDCARD check here is over-simplistic: On H7 SDMMC2's DMA has access to all memory while SDMMC1's DMA can only access D1 memory:
micropython/ports/stm32/sdcard.c
Line 527 in a4ab847
Something like this issue ports/stm32: Make ETH DMA buffer attributes configurable. #16633 could've been avoided, or at least easily detected, if there was a runtime assert that memory is "dmable".
All of those drivers, and others, should Not do any cache-management if memory is Not cacheable.
The problem will only get worse as we add more MCUs/ports with more complex memory and will not scale well in the future. Note I've been maintaining patches to all of those drivers, to fix these issues, but it starting to get out of hand.
Proposed fix:
To fix this issue, I propose we implement some sort of memory map per MCU family, override-able per-board (if needed), with attributes per region: cacheable, DAM-accessible, TCM, external etc.. And a new generic API to query those attributes. It would be great if this mechanism is generic somehow, so it can be reused by future ports with more complex memory.
Other aspects
Having this memory map/attributes query could also help in other areas. For example, it could help
gc
allocate memory based on attributes (gc_alloc(size, MP_MEMORY_REGION_ATTR_TCM/EXTERNAL
). Thengc
could loop through gc blocks and try to fulfill such request with something like:if mp_memory_region_get_attributes(gc_block_start) & attr...
Toy API:
Implementation
I'd be very happy to work on this, but I need feedback on the API first before.
Code of Conduct
Yes, I agree
The text was updated successfully, but these errors were encountered: