Skip to main content
Associate II
June 22, 2026
Question

STM32N6 DCMI DMA config issues

  • June 22, 2026
  • 1 reply
  • 64 views

Hello ST team,

I'm facing the issue with STM32N6 DCMI DMA configurations, I could see the data flowing down from the cmos & clocking at 50MHZ. I could spot the first 4 pixels data (2 words) on live watch window. the next word data is intermittent & getting into DMA error 0x41,

The cube MX (6.17.0) unable to generate the DMA init functions appropriately for DCMI, however i’ve added the Config explicitly,  

Any suggestions on the below configurations?
 

/**

* @brief DCMI Initialization Function

* @param None

* @retval None

*/

static void MX_DCMI_Init(void)

{



/* USER CODE BEGIN DCMI_Init 0 */



/* USER CODE END DCMI_Init 0 */



/* USER CODE BEGIN DCMI_Init 1 */



/* USER CODE END DCMI_Init 1 */

hdcmi.Instance = DCMI;

hdcmi.Init.SynchroMode = DCMI_SYNCHRO_HARDWARE;

hdcmi.Init.PCKPolarity = DCMI_PCKPOLARITY_FALLING;

hdcmi.Init.VSPolarity = DCMI_VSPOLARITY_LOW;

hdcmi.Init.HSPolarity = DCMI_HSPOLARITY_LOW;

hdcmi.Init.CaptureRate = DCMI_CR_ALL_FRAME;

hdcmi.Init.ExtendedDataMode = DCMI_EXTEND_DATA_12B;

hdcmi.Init.JPEGMode = DCMI_JPEG_DISABLE;

hdcmi.Init.ByteSelectMode = DCMI_BSM_ALL;

hdcmi.Init.ByteSelectStart = DCMI_OEBS_ODD;

hdcmi.Init.LineSelectMode = DCMI_LSM_ALL;

hdcmi.Init.LineSelectStart = DCMI_OELS_ODD;

if (HAL_DCMI_Init(&hdcmi) != HAL_OK)

{

Error_Handler();

}

/* USER CODE BEGIN DCMI_Init 2 */



/* USER CODE END DCMI_Init 2 */



}



/**

* @brief GPDMA1 Initialization Function

* @param None

* @retval None

*/

static void MX_GPDMA1_Init(void)

{



/* USER CODE BEGIN GPDMA1_Init 0 */

HAL_StatusTypeDef status;

/* USER CODE END GPDMA1_Init 0 */



/* Peripheral clock enable */

__HAL_RCC_GPDMA1_CLK_ENABLE();



/* GPDMA1 interrupt Init */

HAL_NVIC_SetPriority(GPDMA1_Channel15_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(GPDMA1_Channel15_IRQn);



/* USER CODE BEGIN GPDMA1_Init 1 */

/* Initialize GPDMA1 Channel 0 for DCMI */

handle_GPDMA1_Channel15.Instance = GPDMA1_Channel15;



/* DCMI hardware request */

handle_GPDMA1_Channel15.Init.Request = GPDMA1_REQUEST_DCMI_PSSI;



/* Block request at single/burst level */

handle_GPDMA1_Channel15.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;



/* Peripheral to memory direction */

handle_GPDMA1_Channel15.Init.Direction = DMA_PERIPH_TO_MEMORY;



/* Source (DCMI) increment: fixed, Destination (RAM) increment: enabled */

handle_GPDMA1_Channel15.Init.SrcInc = DMA_SINC_FIXED;

handle_GPDMA1_Channel15.Init.DestInc = DMA_DINC_INCREMENTED;



/* Word (32-bit) data width for both source and destination

to match DCMI peripheral register width */

handle_GPDMA1_Channel15.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;

handle_GPDMA1_Channel15.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;



/* High priority */

handle_GPDMA1_Channel15.Init.Priority = DMA_HIGH_PRIORITY;



/* Single transfer */

handle_GPDMA1_Channel15.Init.SrcBurstLength = 1;

handle_GPDMA1_Channel15.Init.DestBurstLength = 1;



/* Allocated ports */

handle_GPDMA1_Channel15.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0 | DMA_DEST_ALLOCATED_PORT0;



/* Block transfer mode */

handle_GPDMA1_Channel15.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;



/* Normal mode */

handle_GPDMA1_Channel15.Init.Mode = DMA_NORMAL;



/* Initialize the DMA channel */

status = HAL_DMA_Init(&handle_GPDMA1_Channel15);

if (status != HAL_OK) {

return status;

}



/* Link the DMA to the DCMI peripheral */

__HAL_LINKDMA(&hdcmi, DMA_Handle, handle_GPDMA1_Channel15);



return HAL_OK;

/* USER CODE END GPDMA1_Init 1 */

/* USER CODE BEGIN GPDMA1_Init 2 */



/* USER CODE END GPDMA1_Init 2 */



}




/**

* @brief RIF Initialization Function

* @param None

* @retval None

*/

static void SystemIsolation_Config(void)

{



/* USER CODE BEGIN RIF_Init 0 */



/* USER CODE END RIF_Init 0 */



/* set all required IPs as secure privileged */

__HAL_RCC_RIFSC_CLK_ENABLE();



/* RIF-Aware IPs Config */



/* set up GPDMA configuration */

/* set GPDMA1 channel 15 used by DCMI */

if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel15,DMA_CHANNEL_SEC|DMA_CHANNEL_PRIV|DMA_CHANNEL_SRC_SEC|DMA_CHANNEL_DEST_SEC)!= HAL_OK )

{

Error_Handler();

}



/* set up GPIO configuration */

HAL_GPIO_ConfigPinAttributes(GPIOA,GPIO_PIN_3,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOA,GPIO_PIN_4,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOA,GPIO_PIN_5,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOA,GPIO_PIN_7,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOA,GPIO_PIN_9,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOA,GPIO_PIN_10,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOA,GPIO_PIN_11,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOB,GPIO_PIN_10,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOB,GPIO_PIN_11,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOC,GPIO_PIN_1,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOC,GPIO_PIN_6,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOC,GPIO_PIN_8,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOC,GPIO_PIN_9,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOC,GPIO_PIN_12,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOC,GPIO_PIN_13,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOD,GPIO_PIN_8,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOD,GPIO_PIN_9,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOE,GPIO_PIN_4,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOE,GPIO_PIN_8,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOF,GPIO_PIN_0,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOF,GPIO_PIN_1,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOF,GPIO_PIN_3,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOF,GPIO_PIN_4,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOF,GPIO_PIN_5,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOF,GPIO_PIN_6,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOF,GPIO_PIN_9,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOF,GPIO_PIN_10,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOF,GPIO_PIN_12,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOF,GPIO_PIN_13,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOF,GPIO_PIN_15,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOG,GPIO_PIN_0,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOG,GPIO_PIN_1,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOH,GPIO_PIN_3,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOP,GPIO_PIN_13,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOP,GPIO_PIN_14,GPIO_PIN_SEC|GPIO_PIN_NPRIV);

HAL_GPIO_ConfigPinAttributes(GPIOP,GPIO_PIN_15,GPIO_PIN_SEC|GPIO_PIN_NPRIV);



/* USER CODE BEGIN RIF_Init 1 */



/* USER CODE END RIF_Init 1 */

/* USER CODE BEGIN RIF_Init 2 */



/* USER CODE END RIF_Init 2 */



}



/**

* @brief This function handles GPDMA1 Channel 15 global interrupt.

*/

void GPDMA1_Channel15_IRQHandler(void)

{

/* USER CODE BEGIN GPDMA1_Channel15_IRQn 0 */



/* USER CODE END GPDMA1_Channel15_IRQn 0 */

HAL_DMA_IRQHandler(&handle_GPDMA1_Channel15);

/* USER CODE BEGIN GPDMA1_Channel15_IRQn 1 */

dma_counter++;

HAL_NVIC_ClearPendingIRQ(GPDMA1_Channel15_IRQn);

/* USER CODE END GPDMA1_Channel15_IRQn 1 */

}



/**

* @brief This function handles DCMI/PSSI global interrupt.

*/

void DCMI_PSSI_IRQHandler(void)

{

/* USER CODE BEGIN DCMI_PSSI_IRQn 0 */



/* USER CODE END DCMI_PSSI_IRQn 0 */

HAL_DCMI_IRQHandler(&hdcmi);

/* USER CODE BEGIN DCMI_PSSI_IRQn 1 */

dcmi_counter++;

/* USER CODE END DCMI_PSSI_IRQn 1 */

}

Thanks,
Madhu

1 reply

ST Employee
June 22, 2026

Hello Madhu_S,

For Error Codes 

DMA error 0x41 is a bitmask. In the HAL, HAL_DMA_ERROR_NO_XFER is 0x00000001 and HAL_DMA_ERROR_DTE is 0x00000040, so 0x41 = 0x40 | 0x01 — data transfer error combined with a "no transfer in progress" error. You can read the raw error at any time with HAL_DMA_GetError(&handle_GPDMA1_Channel15) and compare against the HAL_DMA_ERROR_* defines in stm32n6xx_hal_dma.h.

On the DCMI side, check HAL_DCMI_GetError(&hdcmi) — the relevant flags to look for are:

HAL_DCMI_ERROR_OVR — FIFO overrun, meaning data is arriving faster than DMA can drain it
HAL_DCMI_ERROR_SYNC — sync signal issue
HAL_DCMI_ERROR_TIMEOUT — capture stalled
If you're hitting HAL_DCMI_ERROR_OVR that's a strong sign the DMA can't keep up with the incoming pixel rate, which points directly to the burst and mode config rather than a signal integrity issue.

Before going full continuous though — try snapshot mode first.

Use DCMI_MODE_SNAPSHOT with a very small transfer size (say 16 or 32 words) and see if it completes cleanly. This tells you immediately whether you're dealing with a frequency/signal problem, a security/bus fault, or purely a throughput problem. If snapshot works at small sizes and starts failing as you increase the size, that narrows it to a DMA capacity or memory access issue.

And this is important for N6 GPDMA: a single DMA transfer is limited to 65535 data items (effectively 64KB for word-width transfers). If your frame size exceeds that you cannot do it in one shot — you need a linked-list configuration with two nodes covering the full frame. 

Continuous Mode: 

you must use DMA_LINKEDLIST_CIRCULAR and nodes 

Br,

CJE