cancel
Showing results for 
Search instead for 
Did you mean: 

How can I configure 2 DMA for 2 i2s modules? [Solved]

tcg
Associate III

Hi, I am trying to use a 4 I2s microphone. And I am using cubemx.

I made work both of them with a sinple DMA transfer.

I used I2s half duplex reciever 16of32bits sample rate 48Khz and DMA for 48*2 samples with uint16_t format. For that I used DMA1 stream 0, pheriferal to memory, half word... circular.

Then I used HAL_I2S_RxCpltCallback to make things in mi code.

All works well.

The problem is when I include another I2S module (i2s3),

I sused cubemx to obtain same configuration but in this case I used DMA1 stream 2.

then

 MX_GPIO_Init();

 MX_DMA_Init();

 MX_I2S2_Init();

 MX_I2S3_Init();

HAL_I2S_Receive_DMA(&hi2s2,(uint16_t *)data_i2s2,I2S_BUFFERSIZE);

   // HAL_I2S_Receive_DMA(&hi2s3,(uint16_t *)data_i2s3,I2S_BUFFERSIZE);

It is possible make different dma streams in parallel.

I am afraid becouse i have just to realice that stmf401re has only one DMA module.

Can you help me with this?

1 ACCEPTED SOLUTION

Accepted Solutions
tcg
Associate III

Solved

Thanks @Community member​ 

0693W00000aISpmQAG.jpg0693W00000aISrhQAG.jpg---------------------------------------------------------------------------------------------------

void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)

{

uint16_t fakemodetest=0;

uint32_t index;

uint16_t ini_loop=0;

uint16_t end_loop=(I2S_BUFFERSIZE/(2*2))-1;

if (hi2s == &hi2s2) {

for(index=ini_loop; index<=end_loop; index++)

{

if (fakemodetest==1)

{

Bufffake8[(4*index)]  = data_i2s2[(2*index)];

Bufffake8[(4*index)+1] = data_i2s2[(2*index)+1];

}

else

{

dmaBuffer[(4*index)]  = data_i2s2[(2*index)];

dmaBuffer[(4*index)+1] = data_i2s2[(2*index)+1];

}

}

}

else if (hi2s == &hi2s3) {

for(index=ini_loop; index<=end_loop; index++)

{

dmaBuffer[(4*index)+2]  = data_i2s3[(2*index)];

dmaBuffer[(4*index)+3]  = data_i2s3[(2*index)+1];

}

}

}

void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)

{

uint16_t fakemodetest=0;

uint32_t index;

uint16_t ini_loop=(I2S_BUFFERSIZE/(2*2))-1;

uint16_t end_loop=(I2S_BUFFERSIZE/2)-1;

if (hi2s == &hi2s2) {

for(index=ini_loop; index<=end_loop; index++)

{

if (fakemodetest==1)

{

Bufffake8[(4*index)]=data_i2s2[(2*index)];

Bufffake8[(4*index)+1]=data_i2s2[(2*index)+1];

}

else

{

dmaBuffer[(4*index)]  = data_i2s2[(2*index)];

dmaBuffer[(4*index)+1] = data_i2s2[(2*index)+1];

}

}

flag_Cplti2s2=1;

}

else if (hi2s == &hi2s3) {

for(index=ini_loop; index<=end_loop; index++)

{

dmaBuffer[(4*index)+2]=data_i2s3[(2*index)];

dmaBuffer[(4*index)+3]=data_i2s3[(2*index)+1];

}

flag_Cplti2s3=1;

 }

if ((flag_Cplti2s2==1)&(flag_Cplti2s3==1)&(fakemodetest==0)){

flag_Cplti2s2=0; flag_Cplti2s3=0;

HAL_GPIO_WritePin(USBTransfer_GPIO_Port,USBTransfer_Pin,GPIO_PIN_SET);

Send_Audio_to_USB((int16_t *)dmaBuffer, CH_BUFFERSIZE);

HAL_GPIO_WritePin(USBTransfer_GPIO_Port,USBTransfer_Pin,GPIO_PIN_RESET);

}

if ((flag_Cplti2s2==1)&(fakemodetest==1)){

Send_Audio_to_USB((int16_t *)Bufffake8, CH_BUFFERSIZE);

flag_Cplti2s2=0;

}

}

View solution in original post

6 REPLIES 6
tcg
Associate III

It seems that i2s module are only linked with DMA1, and other modules like TIM, ADC, are linked with DMA2. is it possible to associate one I2S to DMA1 and I2s to DMA2? It is possible paralelize streams for sameDMA controller? kind regards,T

> It is possible make different dma streams in parallel.

Yes.

I don't understand, how did you configure DMA for I2S2_Rx - there's no connectivity to I2S2_Rx (=SPI2_RX) in DMA1 Stream 0.

SPI2_Rx can be used only with DMA1 Stream 3.

0693W00000aIPWFQA4.png 

> Is it possible to associate one I2S to DMA1 and I2s to DMA2?

No.

JW

tcg
Associate III

Hi, thanks for your fast response.

Yes it is muy fault.

-I2s2 DMA1 stream 3

-I2s3 DMA1 stream 0,2

I could work well with I2s2

 HAL_I2S_Receive_DMA(&hi2s2,(uint16_t *)data_i2s2,I2S_BUFFERSIZE);

But when i include I2s3 DMA all star to work bad.

  HAL_I2S_Receive_DMA(&hi2s2,(uint16_t *)data_i2s2,I2S_BUFFERSIZE);

   // HAL_I2S_Receive_DMA(&hi2s3,(uint16_t *)data_i2s3,I2S_BUFFERSIZE)

Futhermore I do not how works with

void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)

{

UNUSED(hi2s);

I2S_AUDIO_Process();

}

How I can control that both dma are finished by HAL_I2S_RxCpltCallback

It seems that i have to remove that UNUSED and try to make some flags for each transaction.

is it relevant put different priopry for both DMA?

Thanks for you help, @Community member​ 

Kind regads, TCG

*****

void I2S_AUDIO_Process(void)

{

uint32_t index;

uint16_t modetest=1;

HAL_GPIO_WritePin(USBTransfer_GPIO_Port,USBTransfer_Pin,GPIO_PIN_SET);

for(index=0; index<=I2S_BUFFERSIZE/2; index++)

{

dmaBuffer[(4*index)]=data_i2s2[(2*index)];

dmaBuffer[(4*index)+1]=data_i2s2[(2*index)+1];

dmaBuffer[(4*index)+2]=data_i2s3[(2*index)];

dmaBuffer[(4*index)+3]=data_i2s3[(2*index)+1];

}

Send_Audio_to_USB((int16_t *)dmaBuffer, CH_BUFFERSIZE);

HAL_GPIO_WritePin(USBTransfer_GPIO_Port,USBTransfer_Pin,GPIO_PIN_RESET);

}

> But when i include I2s3 DMA all star to work bad.

What is "bad"?

I don't use Cube/HAL, but in HAL_I2S_RxCpltCallback() you are supposed to test, from which I2S came the callback, and process only data of that I2S. Something like (again, I don't use Cube/HAL so I don't know the exact "wording"):

void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s) {
  if (hi2s->Instance == I2S2) {
    // copy data for i2s2 
  } else {
    // copy data for i2s3
    // and maybe send to usb here, if you are okay with this order
  }
}
 
 

JW

tcg
Associate III

Hi @Community member​ ,

That is the behaviour with 2 i2s channels and 2 sine in ram .

0693W00000aISM6QAO.jpg0693W00000aISIHQA4.jpgThen when i include the other i2s 4 channel are working but a bad use of HAL_I2S_RxCallback is producing some 0's in channel 1 (due to 0.5). Those produce a noise in the audio channel. Futhermore CH3 and Ch4 looks well but a iron effect is produced in the channel.

0693W00000aISN8QAO.jpg0693W00000aISNDQA4.jpg0693W00000aISNXQA4.jpgI think that including your feedback it could ork well.

The problem is that hi2s2 is not defined and i do not know how compare this instance.

0693W00000aISNwQAO.pngthat is the struct of hi2s

0693W00000aISPxQAO.png 

I think that reparing this and including a halfconversion callback it will work

thank a lot;tcg

tcg
Associate III

Solved

Thanks @Community member​ 

0693W00000aISpmQAG.jpg0693W00000aISrhQAG.jpg---------------------------------------------------------------------------------------------------

void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)

{

uint16_t fakemodetest=0;

uint32_t index;

uint16_t ini_loop=0;

uint16_t end_loop=(I2S_BUFFERSIZE/(2*2))-1;

if (hi2s == &hi2s2) {

for(index=ini_loop; index<=end_loop; index++)

{

if (fakemodetest==1)

{

Bufffake8[(4*index)]  = data_i2s2[(2*index)];

Bufffake8[(4*index)+1] = data_i2s2[(2*index)+1];

}

else

{

dmaBuffer[(4*index)]  = data_i2s2[(2*index)];

dmaBuffer[(4*index)+1] = data_i2s2[(2*index)+1];

}

}

}

else if (hi2s == &hi2s3) {

for(index=ini_loop; index<=end_loop; index++)

{

dmaBuffer[(4*index)+2]  = data_i2s3[(2*index)];

dmaBuffer[(4*index)+3]  = data_i2s3[(2*index)+1];

}

}

}

void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)

{

uint16_t fakemodetest=0;

uint32_t index;

uint16_t ini_loop=(I2S_BUFFERSIZE/(2*2))-1;

uint16_t end_loop=(I2S_BUFFERSIZE/2)-1;

if (hi2s == &hi2s2) {

for(index=ini_loop; index<=end_loop; index++)

{

if (fakemodetest==1)

{

Bufffake8[(4*index)]=data_i2s2[(2*index)];

Bufffake8[(4*index)+1]=data_i2s2[(2*index)+1];

}

else

{

dmaBuffer[(4*index)]  = data_i2s2[(2*index)];

dmaBuffer[(4*index)+1] = data_i2s2[(2*index)+1];

}

}

flag_Cplti2s2=1;

}

else if (hi2s == &hi2s3) {

for(index=ini_loop; index<=end_loop; index++)

{

dmaBuffer[(4*index)+2]=data_i2s3[(2*index)];

dmaBuffer[(4*index)+3]=data_i2s3[(2*index)+1];

}

flag_Cplti2s3=1;

 }

if ((flag_Cplti2s2==1)&(flag_Cplti2s3==1)&(fakemodetest==0)){

flag_Cplti2s2=0; flag_Cplti2s3=0;

HAL_GPIO_WritePin(USBTransfer_GPIO_Port,USBTransfer_Pin,GPIO_PIN_SET);

Send_Audio_to_USB((int16_t *)dmaBuffer, CH_BUFFERSIZE);

HAL_GPIO_WritePin(USBTransfer_GPIO_Port,USBTransfer_Pin,GPIO_PIN_RESET);

}

if ((flag_Cplti2s2==1)&(fakemodetest==1)){

Send_Audio_to_USB((int16_t *)Bufffake8, CH_BUFFERSIZE);

flag_Cplti2s2=0;

}

}