Skip to main content
DYann.1
Senior II
November 9, 2023
Solved

DMA with SAI

  • November 9, 2023
  • 30 replies
  • 10654 views

Hello,

I would like to use DMA with SAI but I am having difficulty writing the code. Can you check if my code is correct and why I cannot retrieve the RX values ?

 

 /* USER CODE BEGIN 2 */

 HAL_SAI_RegisterCallback(&hsai_BlockA1, HAL_SAI_RX_HALFCOMPLETE_CB_ID, HAL_SAI_RxHalfCpltCallback);
 HAL_SAI_RegisterCallback(&hsai_BlockA1, HAL_SAI_RX_COMPLETE_CB_ID, HAL_SAI_RxCpltCallback);
 fresult= HAL_SAI_Init(&hsai_BlockA1);
 if (fresult != HAL_OK)
 	{
 	return HAL_ERROR;
 	}
 fresult = HAL_SAI_Receive_DMA(&hsai_BlockA1, (uint8_t *)playbuf_RX, (sizeof(playbuf_RX))/4);

 HAL_SAI_RegisterCallback(&hsai_BlockB1, HAL_SAI_TX_HALFCOMPLETE_CB_ID, HAL_SAI_TxHalfCpltCallback);
 HAL_SAI_RegisterCallback(&hsai_BlockB1, HAL_SAI_TX_COMPLETE_CB_ID, HAL_SAI_TxCpltCallback);
 fresult= HAL_SAI_Init(&hsai_BlockB1);
 if (fresult != HAL_OK)
	{
 	return HAL_ERROR;
	}

 fresult = HAL_SAI_Transmit_DMA(&hsai_BlockB1, (uint8_t *)playbuf , (sizeof(playbuf))/4);

 

With CubeMX I have configured 2 DMAs.

DYann1_0-1699536737285.png

One to send the data and the other to read the data again.
I think I'm missing something for the callback but I don't know how to use it to retrieve the values.

Thank you for your helps. 

Regards.

This topic has been closed for replies.
Best answer by DYann.1

Now it's ok

DYann1_2-1699975477522.png

DYann1_3-1699975686560.png

I just to change the configuration and I configure the SAI in DMA only for transmission but not for reception.

30 replies

ST Technical Moderator
November 10, 2023

Hello @DYann.1 ,

Can you please share more details (Clock, GPIO config.., device used?)

Did you try and test the SAI example provided within Cube firmware?

Imen

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
DYann.1
DYann.1Author
Senior II
November 10, 2023

Hi Imen,

Thank you for your feedback but I my goal is not to check the example programs. I've seen 2 examples and it doesn't match what I'm doing. Especially since there was no '.ioc' file so we can't see anything. So I can give to you my configuration and the purpose of my test. I just want to send the data through the SAI (playbuf) and retrieve (playbuf_RX) it in a table to validate the operation of my SAI. I created 2 buffers one for sending and the other for receiving. I looped the TX with the RX together

DYann1_0-1699608791451.png

I configured the SAI with DMA, one for sending and the other for receiving :

DYann1_1-1699609020941.png

If I initialize my sending table then in principle I must have the same values ​​as in my receiving table right ?

Thank you for your helps.

AScha.3
Super User
November 10, 2023

ok, i see start -> transmit dma...

but no start :   HAL_SAI_Receive_DMA(SAI...) - try. (and maybe better, start receive first, then transmit .)

If you feel a post has answered your question, please click on " Best Answer ".
DYann.1
DYann.1Author
Senior II
November 10, 2023

Hi AScha,

Are you sure ? In my code I initialized the slave before the master like this :

fresult = HAL_SAI_Receive_DMA(&hsai_BlockA1, (uint8_t *)playbuf_RX, (sizeof(playbuf_RX))/4);

AScha.3
Super User
November 10, 2023

ah, didnt see it,  ok.   but i would put the  HAL_SAI_Receive_DMA() just close to transmit start..

 (might change nothing...just try.)

 

HAL_SAI_Recieve_DMA...
HAL_SAI_Transmit_DMA...

 

 

If you feel a post has answered your question, please click on " Best Answer ".
DYann.1
DYann.1Author
Senior II
November 10, 2023

Just one thing : how to know that the RX_buffer is completely filled (there is no Flag to indicate?) and how to recover the data? Do I have to create another function or is it managed automatically by the SAI DMA callback ?

In my While loop I have only this code and nothing else  :

 while (1)
 {
 /* USER CODE END WHILE */
	 HAL_Delay(100);
 /* USER CODE BEGIN 3 */
 }
 /* USER CODE END 3 */
}

 Really, I think something is missing.

ST Technical Moderator
November 10, 2023

Hi @DYann.1 ,

If you are using STM32H7 with DMA, please check this article: DMA is not working on STM32H7 devices.

Regards

Imen

In order to give better visibility on the answered topics, please click on 'Best answer' on the reply which solved your issue or answered your question. Thanks
DYann.1
DYann.1Author
Senior II
November 10, 2023

Hi Imen,

No I have a evaluation board STM32L552E-EV but I use with another CODEC only. Can you tell me if the DMA will not work on the SAI too ?

DYann.1
DYann.1Author
Senior II
November 13, 2023

Hi,

I'll come back for the signals :

FS_B

DYann1_0-1699869186263.png

SCK_B

DYann1_2-1699869249826.png

MCLK_B

DYann1_5-1699869317735.png

I also detected if the buffer_RX is correctly filled by flashing the LED with the code below :

 while (1)
 {
 /* USER CODE END WHILE */
	 HAL_SAI_TxHalfCpltCallback (&hsai_BlockA1);
	 {HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
	 HAL_Delay(200);}

 /* USER CODE BEGIN 3 */
 }

But I can't find the expected values. You really have no idea where this could come from ? Thank you for your helps.

LCE
Principal II
November 13, 2023

You don't understand the callback's purpose:

It's not something you call to check, it should be called automatically when the DMA triggers the half- / complete interrupts. Check the HAL files.

 

Just because the examples do not exactly fit your purpose, you should look at theses and understand what's going on. Are there no SAI playback / record examples for L5 ?

DYann.1
DYann.1Author
Senior II
November 13, 2023

Hi,

There is an example with the evaluation card but there is no '.ioc' file and it is not easy to understand the configuration of the SAI and the peripherals.

It seems to me that it was you who told me to do this test, by sending an initialized table and making a connection between the TX and the RX. I have a TX array initialized but the values ​​are not found in the RX array. Most likely the test configuration is not correct or I have incorrectly initialized my arrays. 

LCE
Principal II
November 13, 2023

Why that effin' ioc file?
You need to understand the underlying code!
Nobody said it's going to be easy. ;)

Yes, I said it's a good way for testing the SAI, because it keeps any external ICs out of the code.
But sure you can try something else.

DYann.1
DYann.1Author
Senior II
November 13, 2023

I've already looked at the example provided with the evaluation card but I don't understand it very well. I thought that connecting TX with RX is simpler for me but ultimately nothing is simple.

LCE
Principal II
November 13, 2023

Look at the examples, step by step:

1) What are they doing there in general?

2) How's RX set up and started?

3) How's TX set up, then started?

4) What's happening in the callbacks / ISRs? (which they hopefully use, meaning that DMA with interrupts is used)

DYann.1
DYann.1Author
Senior II
November 14, 2023

Hi,

Thank you for your helps, I'll look for the documentation for that. I modified my code to know if the transmission is correct via the HAL_SAI_TxHalfCpltCallback function :

 

 while (1)
 {
 /* USER CODE END WHILE */
	void HAL_SAI_TxHalfCpltCallback (SAI_HandleTypeDef *hsai)
	 {HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_3);
	 HAL_Delay(200);}

 /* USER CODE BEGIN 3 */
 }

 

So for me something is wrong with the transmission since the LED never flashes.

LCE
Principal II
November 14, 2023

You got it completely wrong...
You are declaring a function within the while loop - and the compiler does not complain? Interesting.

DYann.1
DYann.1Author
Senior II
November 14, 2023

Hi,

I'm not sure if you're right, no errors during compilation :

DYann1_0-1699972697337.png

I saw a tutorial and you can do this to find out if the transmission is going well. The proof is that I have no errors during compilation.

LCE
Principal II
November 14, 2023

And again, usually callback functions are not for you to call them, it's another function that does that, in the HAL case it should be called by the DMA / SAI complete ISR. Try to find where the callback is called within the HAL functions.

Maybe the interrupts you need are not active?

DYann.1
DYann.1Author
Senior II
November 14, 2023

I think this function is useful to know if the transmission is going well. 

DYann1_1-1699973137662.png

Why am I looking at this function ? Because the DMA is configured in circular. After I can check for RX.

Normally the interrupts is automatically generated by cubemx right ? How to check this interruption ?