cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 SAI DMA; Transfer Error

CFran.1
Associate II

0693W00000ANn8jQAD.png

/* Peripheral DMA init*/
    
    hdma_sai1_a.Instance = DMA1_Stream0;
    hdma_sai1_a.Init.Request = DMA_REQUEST_SAI1_A;
    hdma_sai1_a.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_sai1_a.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_sai1_a.Init.MemInc = DMA_MINC_ENABLE;
    hdma_sai1_a.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    hdma_sai1_a.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
    hdma_sai1_a.Init.Mode = DMA_CIRCULAR;
    hdma_sai1_a.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_sai1_a.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    if (HAL_DMA_Init(&hdma_sai1_a) != HAL_OK)
    {
      Error_Handler();
    }
 
    /* Several peripheral DMA handle pointers point to the same DMA handle.
     Be aware that there is only one channel to perform all the requested DMAs. */
    __HAL_LINKDMA(hsai,hdmarx,hdma_sai1_a);
 
    __HAL_LINKDMA(hsai,hdmatx,hdma_sai1_a);
 
    }
int main(void)
{
  /* USER CODE BEGIN 1 */
 
  /* USER CODE END 1 */
  /* USER CODE BEGIN Boot_Mode_Sequence_0 */
    int32_t timeout; 
  /* USER CODE END Boot_Mode_Sequence_0 */
 
/* USER CODE BEGIN Boot_Mode_Sequence_1 */
  /* Wait until CPU2 boots and enters in stop mode or timeout*/
  timeout = 0xFFFF;
  while((__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) != RESET) && (timeout-- > 0));
  if ( timeout < 0 )
  {
  Error_Handler();
  }
/* USER CODE END Boot_Mode_Sequence_1 */
  /* MCU Configuration--------------------------------------------------------*/
 
  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();
 
  /* USER CODE BEGIN Init */
 
  /* USER CODE END Init */
 
  /* Configure the system clock */
  SystemClock_Config();
/* USER CODE BEGIN Boot_Mode_Sequence_2 */
/* When system initialization is finished, Cortex-M7 will release Cortex-M4 by means of
HSEM notification */
/*HW semaphore Clock enable*/
__HAL_RCC_HSEM_CLK_ENABLE();
/*Take HSEM */
HAL_HSEM_FastTake(HSEM_ID_0);
/*Release HSEM in order to notify the CPU2(CM4)*/
HAL_HSEM_Release(HSEM_ID_0,0);
/* wait until CPU2 wakes up from stop mode */
timeout = 0xFFFF;
while((__HAL_RCC_GET_FLAG(RCC_FLAG_D2CKRDY) == RESET) && (timeout-- > 0));
if ( timeout < 0 )
{
Error_Handler();
}
/* USER CODE END Boot_Mode_Sequence_2 */
 
  /* USER CODE BEGIN SysInit */
 
  /* USER CODE END SysInit */
 
  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_SAI1_Init();
  MX_CRC_Init();
  MX_PDM2PCM_Init();
  MX_USART3_UART_Init();
  /* USER CODE BEGIN 2 */
 
  //volatile shared_data_t * const shared_data = (shared_data_t *)0x38000000;
 
  /* USER CODE END 2 */
 
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
 
  __HAL_SAI_ENABLE(&hsai_BlockA1);
 
  if(HAL_SAI_Receive_DMA(&hsai_BlockA1, (uint8_t*)pdmBuffer, AUDIO_BUFFER_SIZE) != HAL_OK){
	  Error_Handler();
  }
 
  while (1)
  {
 
	 while(dmaFlag != HALF){}
 
	 dmaFlag = NONE;
 
	 while(dmaFlag != FULL){}
 
	 dmaFlag = NONE;
 
    /* USER CODE END WHILE */
 
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}
ALIGN_32BYTES (uint16_t pdmBuffer[AUDIO_BUFFER_SIZE]) __attribute__((section(".RAM_D3")));
ALIGN_32BYTES (uint16_t pcmBuffer[AUDIO_BUFFER_SIZE]);

I'm following the SAI DMA example in the project file for one of the stm32h7's. The issue is, no matter what I am always getting a Transfer Error immediately after I start HAL_SAI_Receive_DMA(); I placed a break point at the IRQ_Handler. I am completely confused on what else I need to do.

Things I made sure to do

  • DMA Word Align
  • DMA Increment Memory
  • 32Byte Align Buffers
  • Put the DMAbuffer, pdm, in RAM3

Right now, I'm not even trying to read data, just trying to get the DMA ping pong to work. I know about the cache coherency for when I do need to read the data, but like I said I can't even get DMA to cycle through my main program.

1 ACCEPTED SOLUTION

Accepted Solutions

M0AR points to 0x2000'0480, that's not SRAM3 but DTCM. In 'H7, DMA does not have access to TCM. Review you linker script.

JW

View solution in original post

5 REPLIES 5

> I placed a break point at the IRQ_Handler

Read out content of relevant DMA registers when in there, and post here.

Also, if the transfer size (incorrectly called "alignment" in the DMA init struct) is word, why do you have uint16_t as the buffer type? IMO it overflows the buffer, but that shouldn't cause DMA transfer error.

JW

0693W00000ANnHlQAL.pngIs this what you wanted a picture of? Or were you asking for something else? I can expand them and retake if need be.

Because I goofed and misread their example, I originally had it the same size of the buffer but I must have misread theirs when comparing. I just retested it and its still broken.

M0AR points to 0x2000'0480, that's not SRAM3 but DTCM. In 'H7, DMA does not have access to TCM. Review you linker script.

JW

Wait, is it because of S0M0AR? I thought me doing the alignment and attribute would prevent the peripheral from placing data at location 0x2xxxxxx. Why is it not taking the place of SRAM3?

I completely understand this, but I thought doing the ALIGN_32BYTES (uint16_t pdmBuffer[AUDIO_BUFFER_SIZE]) __attribute__((section(".RAM_D3")));

would make sure to correct this. I've never messed around with the linker before, do you have any documents?

Also thank you very much, I appreciate you helping! Normally I wouldn't be this sloppy, but I thought that error would have been taken care of with the above statement