DMA2D Transfer Complete (TCIF=1) but destination AXI SRAM is always 0
Hi everyone,
I am currently developing an image capture project using the STM32N657 (Cortex-M55) and have encountered an extremely bizarre DMA2D write issue (a silent failure).
-
Goal: Use DMA2D (M2M_PFC) to convert an RGB565 buffer to RGB888 and write it to CPUAXI_RAM1 (0x34080000).
[Problem Description] I wrote a "minimal isolation test" to bypass all camera/GPDMA variables. I forced the CPU to fill the source buffer with pure white (0xFFFFFFFF), and then manually triggered the DMA2D to transfer it to the destination buffer. The Result: The DMA2D finishes successfully. The DMA2D->ISR register reads 0x00000002 (the TCIF Transfer Complete Interrupt Flag is set, and there are NO Transfer Errors). However, the destination buffer remains completely filled with 0x00000000.
[Troubleshooting Done] To isolate the issue, I have verified the following, but the problem persists:
-
CPU Read/Write Test (Pass): Before triggering the DMA2D, I forced the CPU to write 0xDEADBEEF to the destination address and read it back. It worked perfectly. This proves the AXI SRAM clock is enabled and the physical memory is alive.
-
MPU & Cache (Verified): The destination address is covered by MPU Region 15 configured as Non-cacheable. To be absolutely certain, I am calling SCB_CleanInvalidateDCache_by_Addr() on both buffers before the transfer, and SCB_InvalidateDCache_by_Addr() after the transfer to force the CPU to read physical memory.
-
RIF/RISAF Security Framework (Configured): * I configured the DMA2D's RIMC attributes to NSEC | PRIV to align with the memory access level.
-
I set the RISAF (SRAM firewall) filtering to DISABLE (and also tried setting Read/Write Whitelist to 0xFF), ensuring the hardware firewall is not blocking the write.
-
-
Register State (Verified): By pausing the program right after the transfer, I verified that OMAR and FGMAR contain the exact, correctly aligned physical addresses of my buffers. No pointer casting issues are present.
Despite the hardware reporting a successful transfer and all permissions seemingly being granted, absolutely no data is written to the AXI SRAM by the DMA2D.
Are there any hidden AXI Interconnect mechanisms, TrustZone/RIF blind spots, or Cortex-M55 specific coherency rules in the STM32N6 architecture that would cause a DMA2D write to be "silently dropped" while still returning a TCIF?
1. Buffer Declarations & DMA2D Init (dma2d.c):
uint32_t full_frame_buf[57600] __attribute__((section(".noncacheable"), aligned(32)));
uint32_t line_buf[2560] __attribute__((section(".non_cacheable_data"), aligned(32)));
// DMA2D configured as M2M_PFC, Output: RGB888, Input: RGB565
hdma2d.Init.Mode = DMA2D_M2M_PFC;
hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB888;
hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_RGB565;
hdma2d.LayerCfg[1].InputAlpha = 0xff;
2. Isolation Test inside main():
// ================= Ultimate Isolation Test =================
__disable_irq();
// 1. Force source buffer to white
for(int i = 0; i < 2560; i++) {
line_buf[i] = 0xFFFFFFFF;
}
SCB_CleanInvalidateDCache();
// 2. Clear BUSY lock and start DMA2D
hdma2d.State = HAL_DMA2D_STATE_READY;
DMA2D->CR &= ~DMA2D_CR_START;
uint32_t test_src=(uint32_t)&line_buf[0];
uint32_t test_dest = (uint32_t)full_frame_buf;
volatile HAL_StatusTypeDef start_res = HAL_DMA2D_Start(&hdma2d, test_src, test_dest, 320, 8);
// 3. Wait for hardware transfer to finish
while((DMA2D->CR & DMA2D_CR_START) != 0) {
__NOP();
}
// 4. Check ISR (Result is 2 -> TCIF is set!)
volatile uint32_t debug_isr = DMA2D->ISR;
// 5. Explicitly invalidate D-Cache
SCB_InvalidateDCache_by_Addr((uint32_t *)full_frame_buf, 7680);
// 6. Read result (Truth value is still 0x00000000)
volatile uint32_t truth_val = full_frame_buf[0];
__NOP();
__enable_irq();
// ===========================================================
3. RIF/RISAF & MPU Configurations:
/* RIMC Configuration for DMA2D */
RIMC_MasterConfig_t RIMC_master = {0};
RIMC_master.MasterCID = RIF_CID_0;
RIMC_master.SecPriv = RIF_ATTRIBUTE_SEC | RIF_ATTRIBUTE_PRIV;
HAL_RIF_RIMC_ConfigMasterAttributes(RIF_MASTER_INDEX_DMA2D, &RIMC_master);
/* RISAF Configuration for AXI RAM */
RISAF_BaseRegionConfig_t risaf_base_config;
risaf_base_config.EndAddress = 0x3ffff;
risaf_base_config.Filtering = RISAF_FILTER_ENABLE;
risaf_base_config.ReadWhitelist = 255;
risaf_base_config.WriteWhitelist = 255;
risaf_base_config.Secure = RIF_ATTRIBUTE_SEC;
risaf_base_config.PrivWhitelist = 255;
risaf_base_config.StartAddress = 0x0000;
HAL_RIF_RISAF_ConfigBaseRegion(RISAF3, RISAF_REGION_1, &risaf_base_config); // CPUAXI_RAM1
HAL_RIF_RISAF_ConfigBaseRegion(RISAF2, RISAF_REGION_1, &risaf_base_config); // CPUAXI_RAM0
/* MPU Configuration */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER15;
MPU_InitStruct.BaseAddress = 0x34080000;
MPU_InitStruct.LimitAddress = 0x340C0000;
MPU_InitStruct.AttributesIndex = MPU_ATTRIBUTES_NUMBER0;
MPU_InitStruct.AccessPermission = MPU_REGION_ALL_RW;
// MPU Attribute 0 is configured as INNER_OUTER(MPU_NOT_CACHEABLE)
Any guidance on why DMA2D successfully completes but leaves the physical SRAM empty would be greatly appreciated. Thank you!
