summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorAngus Gratton <angus@redyak.com.au>2024-02-20 12:14:44 +1100
committerDamien George <damien@micropython.org>2024-03-08 12:19:48 +1100
commit7fd8a6d4bced2fcad11b30189e1fba4c32eaafc5 (patch)
tree1ba28224f774292dd61f8096086a12f8792c4f99 /tests
parent2345c1a04e6d8f8a7376c2c37c0f5248f7629bbb (diff)
stm32/dma: Add D-cache protection for DMA RX operations, including SPI.
This new DMA API corrects possible cache coherency issues on chips with D-Cache, when working with buffers at arbitrary memory locations (i.e. supplied by Python code). The API is used by SPI to fix an issue with corrupt data when reading from SPI using DMA in certain cases. A regression test is included (it depends on external hardware connection). Explanation: 1) It's necessary to invalidate D-Cache after a DMA RX operation completes in case the CPU reads (or speculatively reads) from the DMA RX region during the operation. This seems to have been the root cause of issue #13471 (only when src==dest for this case). 2) More generally, it is also necessary to temporarily mark the first and last cache lines of a DMA RX operation as "uncached", in case the DMA buffer shares this cache line with unrelated data. The CPU could otherwise write the other data at any time during the DMA operation (for example from an interrupt handler), creating a dirty cache line that's inconsistent with the DMA result. Fixes issue #13471. This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
Diffstat (limited to 'tests')
-rw-r--r--tests/ports/stm32_hardware/dma_alignment.py43
-rw-r--r--tests/ports/stm32_hardware/dma_alignment.py.exp2
2 files changed, 45 insertions, 0 deletions
diff --git a/tests/ports/stm32_hardware/dma_alignment.py b/tests/ports/stm32_hardware/dma_alignment.py
new file mode 100644
index 000000000..1836b25d8
--- /dev/null
+++ b/tests/ports/stm32_hardware/dma_alignment.py
@@ -0,0 +1,43 @@
+from machine import SPI
+# Regression test for DMA for DCache coherency bugs with cache line
+# written originally for https://github.com/micropython/micropython/issues/13471
+
+# IMPORTANT: This test requires SPI2 MISO (pin Y8 on Pyboard D) to be connected to GND
+
+SPI_NUM = 2
+
+spi = SPI(SPI_NUM, baudrate=5_000_000)
+buf = bytearray(1024)
+ok = True
+
+for offs in range(0, len(buf)):
+ v = memoryview(buf)[offs : offs + 128]
+ spi.readinto(v, 0xFF)
+ if not all(b == 0x00 for b in v):
+ print(offs, v.hex())
+ ok = False
+
+print("Variable offset fixed length " + ("OK" if ok else "FAIL"))
+
+# this takes around 30s to run, so skipped if already failing
+if ok:
+ for op_len in range(1, 66):
+ wr = b"\xFF" * op_len
+ for offs in range(1, len(buf) - op_len - 1):
+ # Place some "sentinel" values before and after the DMA buffer
+ before = offs & 0xFF
+ after = (~offs) & 0xFF
+ buf[offs - 1] = before
+ buf[offs + op_len] = after
+ v = memoryview(buf)[offs : offs + op_len]
+ spi.write_readinto(wr, v)
+ if (
+ not all(b == 0x00 for b in v)
+ or buf[offs - 1] != before
+ or buf[offs + op_len] != after
+ ):
+ print(v.hex())
+ print(hex(op_len), hex(offs), hex(buf[offs - 1]), hex(buf[offs + op_len]))
+ ok = False
+
+ print("Variable offset and lengths " + ("OK" if ok else "FAIL"))
diff --git a/tests/ports/stm32_hardware/dma_alignment.py.exp b/tests/ports/stm32_hardware/dma_alignment.py.exp
new file mode 100644
index 000000000..e890e0081
--- /dev/null
+++ b/tests/ports/stm32_hardware/dma_alignment.py.exp
@@ -0,0 +1,2 @@
+Variable offset fixed length OK
+Variable offset and lengths OK