Seems like a bug in HAL DMA driver
I am transferring 307200 bytes (640x480 gray) from DCMI to AXI SRAM using DMA1. When I do single transfer mode to do snapshot captures the DMA driver state never changes back from BUSY to READY so I can't start another.
I did 'fix' it with a hack in the HAL code for now but the problem seems in part from the fact that circular mode is forced by hardware when using double buffer mode. Double buffer mode is required when the transfer is larger than 64KWords and two transfers are required for the 307KB I need. Therefore then ending condition is never met because the driver checks that circular mode is off or on to know if the single transfer was complete and driver state should be changed back to READY.
This is in HAL_DMA_IRQHandler() from stm32h7xx_hal_dma.c from STM32Cube_FW_H7_V1.5.0
//
// ME: Here it checks if double buffer mode. If so, it starts the second half transfer
//
if(((((DMA_Stream_TypeDef *)hdma->Instance)->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0U)
{
/* Current memory buffer used is Memory 0 */
if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CT) == 0U)
{
if(hdma->XferM1CpltCallback != NULL)
{
/* Transfer complete Callback for memory1 */
hdma->XferM1CpltCallback(hdma);
}
}
/* Current memory buffer used is Memory 1 */
else
{
if(hdma->XferCpltCallback != NULL)
{
/* Transfer complete Callback for memory0 */
hdma->XferCpltCallback(hdma);
}
}
}
else
{
// ME: problem - circular is forced on when using double
// buffered so this never hits to go back to READY state:
if((((DMA_Stream_TypeDef *)hdma->Instance)->CR & DMA_SxCR_CIRC) == 0U)
{
/* Disable the transfer complete interrupt */
((DMA_Stream_TypeDef *)hdma->Instance)->CR &= ~(DMA_IT_TC);
/* Process Unlocked */
__HAL_UNLOCK(hdma);
/* Change the DMA state */
hdma->State = HAL_DMA_STATE_READY;
}
if(hdma->XferCpltCallback != NULL)
{
/* Transfer complete callback */
hdma->XferCpltCallback(hdma);
}
}