cancel
Showing results for 
Search instead for 
Did you mean: 

[Solved] STM32H743 SAI DMA Receiving only '0's

angus schmaloer
Associate III

Hey,

I configured the stm32h743 to transfer data with sai2 and read the same data with sai1. Sai2 is in IT mode and works fine (checked it with a logic analyzer).

The SAI2 is totally working in IT mode, but when I put it in DMA mode i only receive 0's. Yes, i set the input buffer in D2, its address is 0x30000000 in the SRAM1.

the interrupts all work good, no tranfer errors ect.

This in my SAI init code:

__HAL_SAI_RESET_HANDLE_STATE(&SaiInputHandle);
 
  SaiInputHandle.Instance            = SAI1_Block_A;
  SaiInputHandle.Init.AudioMode      = SAI_MODESLAVE_RX;
  SaiInputHandle.Init.Synchro        = SAI_ASYNCHRONOUS;
  SaiInputHandle.Init.OutputDrive    = SAI_OUTPUTDRIVE_DISABLE;
  SaiInputHandle.Init.NoDivider      = SAI_MASTERDIVIDER_DISABLE;
  SaiInputHandle.Init.FIFOThreshold  = SAI_FIFOTHRESHOLD_HF;
  //SaiInputHandle.Init.AudioFrequency = AUDIO_FREQUENCY;
  SaiInputHandle.Init.Protocol       = SAI_FREE_PROTOCOL;
  SaiInputHandle.Init.DataSize       = SAI_DATASIZE_32;
  SaiInputHandle.Init.FirstBit       = SAI_FIRSTBIT_MSB;
  SaiInputHandle.Init.ClockStrobing  = SAI_CLOCKSTROBING_FALLINGEDGE;
  SaiInputHandle.Init.MonoStereoMode = SAI_MONOMODE;
 
  SaiInputHandle.FrameInit.FrameLength       = 128;
  SaiInputHandle.FrameInit.ActiveFrameLength = 1;
  SaiInputHandle.FrameInit.FSDefinition      = SAI_FS_STARTFRAME;
  SaiInputHandle.FrameInit.FSPolarity        = SAI_FS_ACTIVE_LOW;
  SaiInputHandle.FrameInit.FSOffset          = SAI_FS_BEFOREFIRSTBIT;
 
  SaiInputHandle.SlotInit.FirstBitOffset = 0;
  SaiInputHandle.SlotInit.SlotSize       = SAI_SLOTSIZE_DATASIZE;
  SaiInputHandle.SlotInit.SlotNumber     = 4;
  SaiInputHandle.SlotInit.SlotActive     = (SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1 | SAI_SLOTACTIVE_2 | SAI_SLOTACTIVE_3);
 
 
  /* DeInit SAI PDM input */
  HAL_SAI_DeInit(&SaiInputHandle);
 
  /* Init SAI PDM input */
  if(HAL_OK != HAL_SAI_Init(&SaiInputHandle))
  {
    Error_Handler();
  }
 
  /* Enable SAI to generate clock used by audio driver */
  __HAL_SAI_ENABLE(&SaiInputHandle);

And here is my dma init code;

/* Enable SAI clock */
	  __HAL_RCC_SAI1_CLK_ENABLE();
 
    /* Enable GPIO clock */
    __HAL_RCC_GPIOE_CLK_ENABLE();
 
    /* pins configuration: Data */
    GPIO_Init.Pin 		= GPIO_PIN_4 | GPIO_PIN_5 | GPIO_PIN_6;
    GPIO_Init.Mode 		= GPIO_MODE_AF_PP;
    GPIO_Init.Pull 		= GPIO_NOPULL;
    GPIO_Init.Speed 	= GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_Init.Alternate = GPIO_AF6_SAI1;
    HAL_GPIO_Init(GPIOE, &GPIO_Init);
 
    /* Enable the DMA clock */
    __HAL_RCC_DMA1_CLK_ENABLE();
 
    /* Configure the hdma_sai_tx handle parameters */
    SaiInputDmaHandle.Instance 				   = DMA1_Stream1;
 
	SaiInputDmaHandle.Init.Request        	   = DMA_REQUEST_SAI1_A;
    SaiInputDmaHandle.Init.Direction           = DMA_PERIPH_TO_MEMORY;
    SaiInputDmaHandle.Init.PeriphInc           = DMA_PINC_DISABLE;
    SaiInputDmaHandle.Init.MemInc              = DMA_MINC_ENABLE;
    SaiInputDmaHandle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
    SaiInputDmaHandle.Init.MemDataAlignment    = DMA_PDATAALIGN_WORD;
    SaiInputDmaHandle.Init.Mode                = DMA_CIRCULAR;
    SaiInputDmaHandle.Init.Priority            = DMA_PRIORITY_VERY_HIGH;
    SaiInputDmaHandle.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;
    SaiInputDmaHandle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_HALFFULL;
    SaiInputDmaHandle.Init.MemBurst            = DMA_MBURST_SINGLE;
    SaiInputDmaHandle.Init.PeriphBurst         = DMA_PBURST_SINGLE;
 
    /* Deinitialize the Stream for new transfer */
    HAL_DMA_DeInit(&SaiInputDmaHandle);
 
    /* Configure the DMA Stream */
    HAL_DMA_Init(&SaiInputDmaHandle);
 
    /* Associate the DMA handle */
    __HAL_LINKDMA(&SaiInputHandle, hdmarx, SaiInputDmaHandle);
 
 
    /* SAI DMA IRQ Channel configuration */
    HAL_NVIC_SetPriority(DMA1_Stream1_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(DMA1_Stream1_IRQn);
 
    /* Peripheral interrupt init*/
    HAL_NVIC_SetPriority(SAI1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(SAI1_IRQn);

1 ACCEPTED SOLUTION

Accepted Solutions

Hey,

That does, indeed, not make sense, because it ain't right what i said (it did looked like it though).

I figured it out.

It's the freaking debugger that messed it all up. Wasted at least 2 a 3 full days on it.

i have two buffers in SRAM1 (0x300000...), because DMA1 and DMA2 can only access D2.

ALIGN_32BYTES (uint32_t audioInBuf0[32]) __attribute__((section(".sram_d2")));
  ALIGN_32BYTES (uint32_t audioInBuf1[32]) __attribute__((section(".sram_d2")));

I also made two buffers that are placed into the DTCM (0x200000...) like all other code and vars, ect.

In the both HAL_SAI_RxCpltCallback and HAL_SAI_RxM1CpltCallback (for the second data buffer) i wrote the data in the buffers that are in SRAM1 to the buffers that were in the "normal" DTCM.

The debugger showed that the audioInBuf0 and audioInBuf1 had all "0" values, BUT the data in the buffers in the "normal" DTCM showed the right data that was copied form audioInBuf0 and audioInBuf1.

So i guess/figured that the debugger "can't" show the data from the SRAM1 even though the data is right there in the buffers. Kinda messed up and hard to find out when you believe your debugger

EDIT!!!!

Maybe because i added

SCB_InvalidateDCache_by_Addr

without enabling cache.

now that i enabled cache, i can see the data in the debugger

View solution in original post

8 REPLIES 8

> SaiInputDmaHandle.Init.MemDataAlignment = DMA_PDATAALIGN_WORD;

?

JW

angus schmaloer
Associate III

@Community member​ i dont understand what you mean with the "?".

but, i use DMA_PDATAALIGN_WORD because i want to read (multiple) 32bit data.

"?" means "could this line be the culprit?"

> SaiInputDmaHandle.Init.MemDataAlignment = DMA_PDATAALIGN_WORD;

I don't speak Cubish, but as far as I know its wretched "design", it's unlikely two init struct fields share the same constant.

There might be other problems I haven't spotted, too.

JW

@Community member​ aah, yes, thanks for the correction.

But, it still doesn't work.

I figured out that the problem only occurs when the DMA is in Circular mode. When its in normal mode it works fine.

Right now i configured the DMA as double buffer DMA transfer, which also doesn't work. Both the interrupts totally work with the two buffers, but i have the same problem, the data is always "0" in the debugger. When you use the double buffer mode, the tranfer is automatically in Circulair mode.

So i think there is an error/problem with the circulair mode or, the obvious awnser, there is something wrong with my code in circulair mode.

That does not really make sense.

What's the value you write to the DMA NDTR? What happens if you switch DMA FIFO off?

JW

Hey,

That does, indeed, not make sense, because it ain't right what i said (it did looked like it though).

I figured it out.

It's the freaking debugger that messed it all up. Wasted at least 2 a 3 full days on it.

i have two buffers in SRAM1 (0x300000...), because DMA1 and DMA2 can only access D2.

ALIGN_32BYTES (uint32_t audioInBuf0[32]) __attribute__((section(".sram_d2")));
  ALIGN_32BYTES (uint32_t audioInBuf1[32]) __attribute__((section(".sram_d2")));

I also made two buffers that are placed into the DTCM (0x200000...) like all other code and vars, ect.

In the both HAL_SAI_RxCpltCallback and HAL_SAI_RxM1CpltCallback (for the second data buffer) i wrote the data in the buffers that are in SRAM1 to the buffers that were in the "normal" DTCM.

The debugger showed that the audioInBuf0 and audioInBuf1 had all "0" values, BUT the data in the buffers in the "normal" DTCM showed the right data that was copied form audioInBuf0 and audioInBuf1.

So i guess/figured that the debugger "can't" show the data from the SRAM1 even though the data is right there in the buffers. Kinda messed up and hard to find out when you believe your debugger

EDIT!!!!

Maybe because i added

SCB_InvalidateDCache_by_Addr

without enabling cache.

now that i enabled cache, i can see the data in the debugger

Is that area at 0x30000000 cached?

JW

angus schmaloer
Associate III

No, i commented it out, because i have read that it could give problems.

/* Enable the CPU Cache */
  //CPU_CACHE_Enable();

also i have put this before i call the DMA transfer function

SCB_InvalidateDCache_by_Addr(Get_SAI1A_Buffer(), BUFFLEN);

 Also, if it was cached, then the DMA wouldn't/couldn't receive the data and then the buffer in the SRAM1 couldn't give the data to the buffer in the "normal" DTCM