2026-06-01 2:05 AM - edited 2026-06-01 2:06 AM
Hello
I have custom board with STM32N657 MCU. There are two image sensors connected to CSI and DCMI interface. The image data is streaming from both sensors. I want to get DCMI image data displayed via USBHS1 and I get DCMI overflow error. I think, the limits of data throughput has been reached for AHB5.
The image data pipeline is as follows:
Phase 1. DCMI->GPDMA CH15->AXISRAM1/2 frame buffer
Phase2. AXISRAM1/2 frame buffer -> GPDMA CH12 -> USBX UVC video buffer
The DCMI data transfer with GPDMA CH15 works fine until USBHS1 starts streaming video data using GPDMA CH12. Then then DCMI fires overflow error.
The bottleneck is 200MHz AHB5 interconnect where DCMI and USBHS1, USBHS2 are connected.
Some calculations to get DMA bus utilisation:
8-bit DCMI parallel interface, 68MHz pixel clock, around 62MB/s raw throughput. GPDMA CH15 highest priority.
200MHz AHB5 clock / 68MHz pixel clock = 2.94 AHB5 cycles per pixel clock.
There is 4 pixel clocks to get 32-bit DCMI Data Register filled, 4 pixels x 2.94 ~ 11.76 AHB5 cycles. How much of this time is taken by GPDMA?
GPDMA read phase 2 cycles (1 address phase, 1 data phase) and write cycle also 2 cycles (plus some acknowledge cycles?) so 4/11.76 ~ 34% DMA bus utilization.
It seems there is some space to include low priority GPDMA CH12 transfer in between.
I tried with DMA single and different burst transfers without success. The GPDMA Port 0 and Port1 can work simultaneously and Port 0 is allocated to read DCMI data register. Transfer allocated DMA Port 1 only for USBHS1 (source and destination) makes no difference. It looks the performance limit has been reached or resources could be used more efficiently?
static void MX_GPDMA1_Init(void)
{
/* USER CODE BEGIN GPDMA1_Init 0 */
/* USER CODE END GPDMA1_Init 0 */
/* Peripheral clock enable */
__HAL_RCC_GPDMA1_CLK_ENABLE();
/* GPDMA1 interrupt Init */
HAL_NVIC_SetPriority(GPDMA1_Channel10_IRQn, 14, 0);
HAL_NVIC_EnableIRQ(GPDMA1_Channel10_IRQn);
HAL_NVIC_SetPriority(GPDMA1_Channel11_IRQn, 14, 0);
HAL_NVIC_EnableIRQ(GPDMA1_Channel11_IRQn);
HAL_NVIC_SetPriority(GPDMA1_Channel12_IRQn, 12, 0);
HAL_NVIC_EnableIRQ(GPDMA1_Channel12_IRQn);
HAL_NVIC_SetPriority(GPDMA1_Channel13_IRQn, 13, 0);
HAL_NVIC_EnableIRQ(GPDMA1_Channel13_IRQn);
HAL_NVIC_SetPriority(GPDMA1_Channel15_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(GPDMA1_Channel15_IRQn);
/* USER CODE BEGIN GPDMA1_Init 1 */
/* USER CODE END GPDMA1_Init 1 */
handle_GPDMA1_Channel13.Instance = GPDMA1_Channel13;
handle_GPDMA1_Channel13.Init.Request = DMA_REQUEST_SW;
handle_GPDMA1_Channel13.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
handle_GPDMA1_Channel13.Init.Direction = DMA_MEMORY_TO_MEMORY;
handle_GPDMA1_Channel13.Init.SrcInc = DMA_SINC_INCREMENTED;
handle_GPDMA1_Channel13.Init.DestInc = DMA_DINC_INCREMENTED;
handle_GPDMA1_Channel13.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
handle_GPDMA1_Channel13.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
handle_GPDMA1_Channel13.Init.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
handle_GPDMA1_Channel13.Init.SrcBurstLength = 4;
handle_GPDMA1_Channel13.Init.DestBurstLength = 4;
handle_GPDMA1_Channel13.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT1|DMA_DEST_ALLOCATED_PORT0;
handle_GPDMA1_Channel13.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel13.Init.Mode = DMA_NORMAL;
if (HAL_DMA_Init(&handle_GPDMA1_Channel13) != HAL_OK)
{
Error_Handler();
}
handle_GPDMA1_Channel12.Instance = GPDMA1_Channel12;
handle_GPDMA1_Channel12.Init.Request = DMA_REQUEST_SW;
handle_GPDMA1_Channel12.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
handle_GPDMA1_Channel12.Init.Direction = DMA_MEMORY_TO_MEMORY;
handle_GPDMA1_Channel12.Init.SrcInc = DMA_SINC_INCREMENTED;
handle_GPDMA1_Channel12.Init.DestInc = DMA_DINC_INCREMENTED;
handle_GPDMA1_Channel12.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
handle_GPDMA1_Channel12.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
handle_GPDMA1_Channel12.Init.Priority = DMA_LOW_PRIORITY_LOW_WEIGHT;
handle_GPDMA1_Channel12.Init.SrcBurstLength = 1;
handle_GPDMA1_Channel12.Init.DestBurstLength = 1;
handle_GPDMA1_Channel12.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT1|DMA_DEST_ALLOCATED_PORT1;
handle_GPDMA1_Channel12.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel12.Init.Mode = DMA_NORMAL;
if (HAL_DMA_Init(&handle_GPDMA1_Channel12) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN GPDMA1_Init 2 */
/* USER CODE END GPDMA1_Init 2 */
}void HAL_DCMI_MspInit(DCMI_HandleTypeDef* hdcmi)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
DMA_NodeConfTypeDef NodeConfig;
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
if(hdcmi->Instance==DCMI)
{
/* USER CODE BEGIN DCMI_MspInit 0 */
//__HAL_RCC_AHBSRAM1_MEM_CLK_ENABLE();
//__HAL_RCC_GPDMA1_CLK_ENABLE();
NodeConfig.SrcAddress = (uint32_t)&DCMI->DR;// 0x58028428;
NodeConfig.DstAddress = (uint32_t)&frameBufferPYTHON480_16kB;
NodeConfig.DataSize = 800*2;
/* USER CODE END DCMI_MspInit 0 */
/** Initializes the peripherals clock
*/
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_DCMIPP;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK)
{
Error_Handler();
}
/* Peripheral clock enable */
__HAL_RCC_DCMI_PSSI_CLK_ENABLE();
__HAL_RCC_GPIOE_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**DCMI GPIO Configuration
PE8 ------> DCMI_D4
PC6 ------> DCMI_D1
PE10 ------> DCMI_D3
PB14 ------> DCMI_D10
PC12 ------> DCMI_D9
PE5 ------> DCMI_D5
PD12 ------> DCMI_D12
PC2 ------> DCMI_D13
PE6 ------> DCMI_VSYNC
PD0 ------> DCMI_HSYNC
PD5 ------> DCMI_PIXCLK
PD7 ------> DCMI_D0
PD8 ------> DCMI_D11
PB7 ------> DCMI_D7
PB6 ------> DCMI_D6
PE0 ------> DCMI_D2
PE1 ------> DCMI_D8
*/
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_10|GPIO_PIN_5|GPIO_PIN_6
|GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF9_DCMI;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_12|GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF9_DCMI;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_14|GPIO_PIN_7|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF9_DCMI;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_12|GPIO_PIN_0|GPIO_PIN_5|GPIO_PIN_7
|GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = GPIO_AF9_DCMI;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/* DCMI DMA Init */
/* GPDMA1_REQUEST_DCMI_PSSI Init */
NodeConfig.NodeType = DMA_GPDMA_2D_NODE;
NodeConfig.Init.Request = GPDMA1_REQUEST_DCMI_PSSI;
NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD;
NodeConfig.Init.SrcBurstLength = 1;
NodeConfig.Init.DestBurstLength = 4;
NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT1;
NodeConfig.Init.TransferEventMode = DMA_TCEM_REPEATED_BLOCK_TRANSFER;
NodeConfig.Init.Mode = DMA_NORMAL;
NodeConfig.RepeatBlockConfig.RepeatCount = 632;
NodeConfig.RepeatBlockConfig.SrcAddrOffset = 0;
NodeConfig.RepeatBlockConfig.DestAddrOffset = 0;
NodeConfig.RepeatBlockConfig.BlkSrcAddrOffset = 0;
NodeConfig.RepeatBlockConfig.BlkDestAddrOffset = -800*2;
NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
NodeConfig.TriggerConfig.TriggerSelection = GPDMA1_TRIGGER_GPDMA1_CH0_TCF;
NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
NodeConfig.SrcSecure = DMA_CHANNEL_SRC_SEC;
NodeConfig.DestSecure = DMA_CHANNEL_DEST_SEC;
if (HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel15) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel15, NULL, &Node_GPDMA1_Channel15) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel15) != HAL_OK)
{
Error_Handler();
}
handle_GPDMA1_Channel15.Instance = GPDMA1_Channel15;
handle_GPDMA1_Channel15.InitLinkedList.Priority = DMA_HIGH_PRIORITY;
handle_GPDMA1_Channel15.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
handle_GPDMA1_Channel15.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
handle_GPDMA1_Channel15.InitLinkedList.TransferEventMode = DMA_TCEM_REPEATED_BLOCK_TRANSFER;
handle_GPDMA1_Channel15.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel15) != HAL_OK)
{
Error_Handler();
}
if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel15, &List_GPDMA1_Channel15) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hdcmi, DMA_Handle, handle_GPDMA1_Channel15);
/* DCMI interrupt Init */
HAL_NVIC_SetPriority(DCMI_PSSI_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(DCMI_PSSI_IRQn);
/* USER CODE BEGIN DCMI_MspInit 1 */
/* USER CODE END DCMI_MspInit 1 */
}
}