cancel
Showing results for 
Search instead for 
Did you mean: 

About SAI - DMA protocol

carloV
Associate II

Hi,

I need to understand better how the "HAL_SAI_Receive_DMA(&hsai_BlockB1,ADC_Buffer,CodecBuffer_Size)" works.

I've a codec connected to the SAI 1 of a STMH723 MPU and I implemented a Ping-Pong routine to acquire and send the data to the Codec; two Callback function swap the buffers:

uint8_t ADC_Buffer[80000] __attribute__ ((aligned (4)));

 

void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai_BlockB1){

adcp31=(q31_t *)&ADC_Buffer[BUFFER_SIZE_R/2];

RxDataReady1=1;

}

 

void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai_BlockB1){

adcp31=(q31_t *)&ADC_Buffer;

dacp31=(q31_t *)&DAC_Buffer;

RxDataReady=1;

}

 

If I write HAL_SAI_Receive_DMA(&hsai_BlockB1,ADC_Buffer,20000) what happens (in details) ?

 

Thank you

4 REPLIES 4
TDK
Super User

HAL_SAI_RxHalfCpltCallback is called when the first half of the buffer is populated.

HAL_SAI_RxCpltCallback is called when the second half of the buffer is populated.

If these are in circular mode, you will need to process each half-buffer before it starts to be overwritten on the next loop.

There is a 65535 item limit for DMA transfers.

 

If you feel a post has answered your question, please click "Accept as Solution".
carloV
Associate II

Thank you for your fast reply,

I need to sample at 50KHz, 32 bit stereo, with a frequency resolution of 10Hz, then I need a buffer of 5000 uint32 for the left channel and the same for the right channel.

The SAI is connected to a stereo codec, there is a stream of L-R samples between the codec and the SAI, then I 

set  the "uint16_t Size" at   20000  (5000 x 4  uint8); is it correct ?

HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size)

 

uint8_t ADC_Buffer[80000] __attribute__ ((aligned (4)));                          80000 ---> 20000 x 4   (L-R ping-pong)     

HAL_SAI_Receive_DMA(&hsai_BlockB1,ADC_Buffer,20000)   

        

My question is: after how many DMA transfers  is the "HAL_SAI_RxHalfCpltCallback" called ? 

 

 

 

LCE
Principal II

My question is: after how many DMA transfers  is the "HAL_SAI_RxHalfCpltCallback" called ? 

I admit that I don't know for byte buffers...

Is there a specific reason that you are using an byte / uint8_t buffer?

If you are sampling 32-bit anyway, everything gets simpler to further use 32-bit buffers and DMA.
Then half complete is called at half of Size given to DMA.

Here's my SAI RX DMA setup, also for H723 (and one of the few places that I'm using HAL):

	/* Peripheral DMA init */
		hDMA_Sai_1_A.Instance 		= DMA1_Stream0;
		hDMA_Sai_1_A.Init.Request 	= DMA_REQUEST_SAI1_A;

		hDMA_Sai_1_A.Init.Direction 			= DMA_PERIPH_TO_MEMORY;
		hDMA_Sai_1_A.Init.PeriphInc 			= DMA_PINC_DISABLE;
		hDMA_Sai_1_A.Init.MemInc 				= DMA_MINC_ENABLE;
		hDMA_Sai_1_A.Init.Mode 					= DMA_CIRCULAR;
		hDMA_Sai_1_A.Init.Priority 				= DMA_PRIORITY_VERY_HIGH;
		hDMA_Sai_1_A.Init.FIFOMode 				= SAI2S_DMA_FIFO_MODE;
		hDMA_Sai_1_A.Init.FIFOThreshold 		= DMA_FIFO_THRESHOLD_FULL;
		hDMA_Sai_1_A.Init.PeriphDataAlignment 	= DMA_PDATAALIGN_WORD;
		hDMA_Sai_1_A.Init.MemDataAlignment 		= DMA_MDATAALIGN_WORD;
		hDMA_Sai_1_A.Init.MemBurst 				= SAI2S_DMA_MEMORY_BURST;
		hDMA_Sai_1_A.Init.PeriphBurst 			= SAI2S_DMA_PERIPH_BURST;

		if( HAL_DMA_Init(&hDMA_Sai_1_A) != HAL_OK ) Error_Handler_FL(__FILE__, __LINE__);

 

carloV
Associate II

Thank you for your reply,

 

the    HAL_SAI_Receive_DMA(SAI_HandleTypeDef *hsai, uint8_t *pData, uint16_t Size) function requires a uint8_t buffer.