cancel
Showing results for 
Search instead for 
Did you mean: 

STM32WBA54 SAI Slave mode DMA cannot stop and reinitiate

HuangFan
Associate II

STM32WBA54 SAI work in slave mode with DMA: SAI1_Block_A Slave out, SAI1_Block_B Slave in. 

test code as:

  MX_SAI1_Init();

//in

  __HAL_LINKDMA(&hsai_BlockB1, hdmarx, handle_GPDMA1_Channel2);
  MX_RxQueue_Config();
  HAL_DMAEx_List_SetCircularMode(&RxQueue);
  HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel2, &RxQueue);
  if (HAL_SAI_Receive_DMA(&hsai_BlockB1, (uint8_t *) aSrcBuff, SAI_MAX_BUFF_SIZE*2) != HAL_OK)
  {
 
   }
 
//Out
__HAL_LINKDMA(&hsai_BlockA1, hdmatx, handle_GPDMA1_Channel1);
  MX_TxQueue_Config();
  HAL_DMAEx_List_SetCircularMode(&TxQueue);
HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel1, &TxQueue);
if (HAL_SAI_Transmit_DMA(&hsai_BlockA1, (uint8_t *)aSnkBuff, SAI_MAX_BUFF_SIZE*2) != HAL_OK)
 {
 }
 
TxDMA = HAL_SAI_DMAStop(&hsai_BlockA1);
RxDMA = HAL_SAI_DMAStop(&hsai_BlockB1); 
TxSai = HAL_SAI_DeInit(&hsai_BlockA1);
RxSai = HAL_SAI_DeInit(&hsai_BlockB1);
 
HAL_SAI_DMAStop() and HAL_SAI_DeInit() all return HAL_ERROR;
 
Debug into the function and find that SAI_Disable() inside always return HAL_TIMEOUT for CR1_SAIEN cannot be cleared. But if SAI work in Master mode, it will be OK. In my test, there is no SAI mater or slave was connected, from my understanding, when SAI was in Slave mode and there is no Master to provide the CLK, the function  HAL_SAI_Transmit_DMA() start the DMA transfer but the transfer will be blocked for not CLK. And at this situation the SAI will waiting for the CLK to complete the transfer or the CR1_SAIEN bit cannot be cleared, am I right? 
 
while in Master mode the HAL_SAI_Transmit_DMA() could Start the DMA transfer successfully, and the SAI DMA could stop and de-initiate successfully.  
 
In my project, the SAI need to Support both Master and Slave mode, use the appropriate mode according to connected device. And I've already finished the Master mode, the SAI could be stop successfully if audio was off and restart SAI if audio was on. but When In Slave mode, SAI cannot be stopped the de-initiate successfully and this will also affect restarting the SAI.
 
what could I do to stop the SAI in slave mode? 
 
 

static HAL_StatusTypeDef SAI_Disable(SAI_HandleTypeDef *hsai)
{
uint32_t count = SAI_DEFAULT_TIMEOUT * (SystemCoreClock / 7U / 1000U);
HAL_StatusTypeDef status = HAL_OK;

/* Disable the SAI instance */
__HAL_SAI_DISABLE(hsai);

do
{
/* Check for the Timeout */
if (count == 0U)
{
/* Update error code */
hsai->ErrorCode |= HAL_SAI_ERROR_TIMEOUT;
status = HAL_TIMEOUT;
break;
}
count--;
} while ((hsai->Instance->CR1 & SAI_xCR1_SAIEN) != 0U);

return status;
}

1 ACCEPTED SOLUTION

Accepted Solutions
TMANE.1
ST Employee

Hi,

 

I understand the situation, and I see a workaround that could apply for some specific use case:

 

If the BCLK line is in high Z due to the missing master (or master configuration), it is possible to get out of this situation (pending transfers) by generating few edges on the BLCK, for example with a loop for enabling the GPIO pull up, then pull down few times while the GPIO still in alternate function (GPIOx_PUPDR)

View solution in original post

3 REPLIES 3
TMANE.1
ST Employee

Hello Huang,

 

I can reproduce the issue and have the same conclusion.  I read from the reference manual that "SAIEN bit remains high until the SAI is completely switched off at the end of the current audio frame transfer", so probably without the BCLK we never end the current audio frame transfer, I am waiting the confirmation of this behavior (internal ID 221613)

 

Did you tried to reconfigure the SAI after performing an IP reset from the RCC ?  (APB2RSTR  /  SAI1RST).

 

Best regards,

HuangFan
Associate II

Hi TMANE,

Set APB2RSTR  /  SAI1RST could reset the SAI successfully. 

But this settings will cause both SAI1_Block_A and SAI1_Block_B reset simultaneously, if I want to just stop audio out(SAI1_Block_A ) and keep audio in(SAI1_Block_B), I have to re-initialize audio in(SAI1_Block_B) and lost some audio in data.

 

TMANE.1
ST Employee

Hi,

 

I understand the situation, and I see a workaround that could apply for some specific use case:

 

If the BCLK line is in high Z due to the missing master (or master configuration), it is possible to get out of this situation (pending transfers) by generating few edges on the BLCK, for example with a loop for enabling the GPIO pull up, then pull down few times while the GPIO still in alternate function (GPIOx_PUPDR)