Showing results for 
Search instead for 
Did you mean: 

STM32U5A5: DMA to SAI2 does not work - why?

Senior III

I want to send audio samples (received via SAI1 from PDM MIC) to SAI2_SD_B as SPDIF out.

It does not work, because: the DMA does not seem to write the DR in SAI2:

  • the memory is filled with audio samples
  • the DMA seems to run (I get the HAL_SAI_TxCpltCallback and I can see via debugger that the DMA pointers are moving)
  • but the SPDIF sends all zero: on scope, the SPDIF output is all as zero words

Remark: it is on a STM32U5A5RJT6Q (LQFP64 package): the datasheet "says": not a SAI2 there (just one SAI) - but not true - it works also with SAI2, even CubeMX does not let me configure SAI2 pins (also wrong in CubeMX tool). But I can configure SAI2 and see it working (in Polling and INT mode, just the DMA fails).

So, my impression: the circular buffer and DMA does not work. No idea why not: the code is generated by CubeMX.

This topic is related to this thread:

Solved: STM32U5xx: SPDIF out - how to configure? - STMicroelectronics Community

Here is the DMA config I use: Why does it send all as zero (or does not send anything into SAI2_B DR)?

        /* Peripheral DMA init - SAI2_SD_B as SPDIF - use CH5 */
        NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
        NodeConfig.Init.Request = GPDMA1_REQUEST_SAI2_B;
        NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
        NodeConfig.Init.Direction = DMA_MEMORY_TO_PERIPH;
        NodeConfig.Init.SrcInc = DMA_SINC_INCREMENTED;
        NodeConfig.Init.DestInc = DMA_DINC_FIXED;
        NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD;
        NodeConfig.Init.DestDataWidth = DMA_SRC_DATAWIDTH_WORD;
        NodeConfig.Init.SrcBurstLength = 1;
        NodeConfig.Init.DestBurstLength = 1;
        NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0|DMA_DEST_ALLOCATED_PORT0;
        NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
        NodeConfig.Init.Mode = DMA_NORMAL;
        NodeConfig.TriggerConfig.TriggerPolarity = DMA_TRIG_POLARITY_MASKED;
        NodeConfig.DataHandlingConfig.DataExchange = DMA_EXCHANGE_NONE;
        NodeConfig.DataHandlingConfig.DataAlignment = DMA_DATA_RIGHTALIGN_ZEROPADDED;
        if (HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel5) != HAL_OK)

        if (HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel5, NULL, &Node_GPDMA1_Channel5) != HAL_OK)

        if (HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel5) != HAL_OK)

        handle_GPDMA1_Channel5.Instance = GPDMA1_Channel5;
        handle_GPDMA1_Channel5.InitLinkedList.Priority = DMA_LOW_PRIORITY_MID_WEIGHT;
        handle_GPDMA1_Channel5.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
        handle_GPDMA1_Channel5.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT0;
        handle_GPDMA1_Channel5.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
        handle_GPDMA1_Channel5.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
        if (HAL_DMAEx_List_Init(&handle_GPDMA1_Channel5) != HAL_OK)

        if (HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel5, &List_GPDMA1_Channel5) != HAL_OK)

        __HAL_LINKDMA(hsai, hdmatx, handle_GPDMA1_Channel5);

        if (HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel5, DMA_CHANNEL_NPRIV) != HAL_OK)

It is the same for the SAI1 DMA, using channel 4, with quite similar config (just direction is reversed), but also PORT0 used there. Is this a conflict? (even the channel is a different one).

Why is the circular DMA buffer config not working for Memory-to-SAI2_B?