Search code examples
audiobufferstm32microcontrollerdma

SAI1 DMA Callback Issue STM32H723


I'm currently working on a project using the STM32H723VE microcontroller and have run into a problem with the SAI1 peripherals.

So far SAI4 in slave transmit mode and I2S1 in slave receive mode are working correctly. SAI4 uses RAM D3, SAI1 and I2S use RAM D2 via DMA. However, when I add SAI1 in slave transmit mode to the code, all DMA operations for SAI4 and I2S1 stop working. When I disable DMA for SAI1, everything starts working again. For all DMAs, the data width is configured to 'word' and their mode is set to 'circular'.

I have tried to debug the code and this is what I have observed so far:

  • SAI4 and I2S1 work as long as SAI1 DMA isn't working.
  • SAI4 and I2S1 can read and write to the buffer
  • SAI1 initializes without error
  • HAL_SAI_Transmit_DMA(&hsai_BlockA1...) never returns an error code, it's always HAL_OK
  • SAI1 never calls the callback functions HAL_SAI_TxHalfCpltCallback() or HAL_SAI_TxCpltCallback().
  • As soon as the SAI1 DMA operation should be started all data in the I2S1 buffer stays the same and doesn't change anymore.

The exact moment when the problem occurs is when HAL_SAI_Transmit_DMA(&hsai_BlockA1...) : switches from

     /* Process Unlocked */
    __HAL_UNLOCK(hsai);

to

    return HAL_OK;
  }

which is at the end of the function HAL_SAI_Transmit_DMA(&hsai_BlockA1...).

Code Snippets:

Below is the RAM allocation for the DMA in the .._FLASH.ld file:

  .dma_d2_buffer : /* Space before ':' is critical */
  {
    *(.dma_d2_buffer)
  } >RAM_D2
  
  .dma_d3_buffer : /* Space before ':' is critical */
  {
    *(.dma_d3_buffer)
  } >RAM_D3

Important code from the main.c:

#if defined( __ICCARM__ )
  #define DMA_D2_BUFFER \
      _Pragma("location=\".dma_d2_buffer\"")
#else
  #define DMA_D2_BUFFER \
      __attribute__((section(".dma_d2_buffer"), used, aligned (4)))
#endif

#if defined( __ICCARM__ )
  #define DMA_D3_BUFFER \
      _Pragma("location=\".dma_d3_buffer\"")
#else
  #define DMA_D3_BUFFER \
      __attribute__((section(".dma_d3_buffer"), used, aligned (4)))
#endif


DMA_D2_BUFFER int32_t inDataI2s[BUFFER_SIZE];
DMA_D2_BUFFER int32_t outDataSai1[BUFFER_SIZE/2];
DMA_D3_BUFFER int32_t outDataSai4[BUFFER_SIZE/2];



int main(void)
{...

...
  status = HAL_I2S_Receive_DMA(&hi2s1, (uint16_t *) inDataI2s, BUFFER_SIZE);
  status = HAL_SAI_Transmit_DMA(&hsai_BlockA1, (uint8_t *) outDataSai1, BUFFER_SIZE/2);
  status = HAL_SAI_Transmit_DMA(&hsai_BlockB1, (uint8_t *) outDataSai1, BUFFER_SIZE/2);
  status = HAL_SAI_Transmit_DMA(&hsai_BlockA4, (uint8_t *) outDataSai4, BUFFER_SIZE/2);
  status = HAL_SAI_Transmit_DMA(&hsai_BlockB4, (uint8_t *) outDataSai4, BUFFER_SIZE/2);

while (1)
  {
  }
}

void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s) {
    bufferIndex = 0;
    processData();
}

void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s) {
    bufferIndex = BUFFER_SIZE/2;
    processData();
}

void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) {
    saiCallback=1;
}

void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) {
    saiCallback=2;
}

Solution

  • I found the error. It was a bad STM32. I did A/B testing and uploaded the exact same code to two different STM32H723VE and one called the callback function from SAI1 and the other just stopped working.

    I found this very interesting because I did not expect this to be the error since all other peripherals and even the RAM worked perfectly. How does it happen that only one peripheral stops working due to a hardware problem?