cancel
Showing results for 
Search instead for 
Did you mean: 

Does the Nucleo STM32G431 have a bug with the I2S (receive)?

evenlund
Associate III

I am using the latest versions of STM32CubeIDE and updated firmware for STM32G431. I am trying to setup the Nucleo STM32G431 with I2S master for a microphone with DMA in circular mode, very similar to what "YetANotherElectronicsChannel" did in this video (just omitting the transmit part): https://www.youtube.com/watch?v=lNBrGOk0XzE.

I have made this work fine with the Nucleo F446RE, but when using the G431 only the HAL_I2S_RxHalfCpltCallback seems to be started. Moreover I get no data into the memory given to the DMA.

Is there a bug in the software? I see that the #if defined(SPI_I2S_SUPPORT) is grayed out in the stm32g4xx_hal_i2s.c file (contrary to what I have for F446RE), proably meaning that it is not defined earlier. I have tried commenting out the #if defined and #endif, but there seems to be no difference.

Has anywone set up the G431 successfully with I2S master receive and DMA?

13 REPLIES 13
evenlund
Associate III

I have now setup the I2S3 in the same manner like the I2S2 and the I2S3 is working perfectly in stereo, but the I2S3 behave in the exact same way with no data (0 value) saved to the variable that DMA should fill. I am starting to suspect that the DMA is not setup or working correctly. I have setup both I2S's exactly the same in STM32cubeide/cubemx with circular mode and data width of half word. I am showing the code for reading the buffers below. Any clue of what is wrong?

void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s){
	if (hi2s->Instance==SPI2)
	{
		lsample1=(int)(rxBuf1[0]<<16|rxBuf1[1]);
		rsample1=(int)(rxBuf1[2]<<16|rxBuf1[3]);
		//HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
	}
	else
	{
		lsample2=(int)(rxBuf2[0]<<16|rxBuf2[1]);
		rsample2=(int)(rxBuf2[2]<<16|rxBuf2[3]);
		//HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
	}
}
 
void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s){
	if (hi2s->Instance==SPI2)
	{
		lsample1=(int)(rxBuf1[4]<<16|rxBuf1[5]);
		rsample1=(int)(rxBuf1[6]<<16|rxBuf1[7]);
		//HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
	}
	else
	{
		lsample2=(int)(rxBuf2[4]<<16|rxBuf2[5]);
		rsample2=(int)(rxBuf2[6]<<16|rxBuf2[7]);
		//HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
	}
}

Debug as usually - read out and check/post SPI/I2S, relevant DMAMUX, DMA and GPIO registers' content. Cube is open source.

JW

evenlund
Associate III

I appreciate you trying to help me! Unfortunately I find it difficult to being seen/get help or get an overview of other users questions too on this forum. And I don't think there is a way to reach out to ST directly to ask questions that may be related to bugs for a particular MCU.

I have at my best efforts tried to look into register settings during debugging, but I am unsure what are correct settings to get things running. Are there any overviews for the order of how the I2S should be set up with DMA and the corresponding register settings? My way of trying to spot such errors is either to compare registers between two different MCUs (one working) or, for this case, comparing on the registers for a functional and a non-functional I2S. So far I see no differences.

> comparing on the registers for a functional and a non-functional I2S.

Sounds like a good approach.

> So far I see no differences.

Okay, so show them.

JW

evenlund
Associate III

I don't get much out of observing these registers except for that the SPI2 DR register is never changing from 0, the SPI used by the I2S with a problem.

I start the I2S reception with

  HAL_I2S_Receive_DMA(&hi2s2, rxBuf1, 4);
  HAL_I2S_Receive_DMA(&hi2s3, rxBuf2, 4);

Have a go at what you think is the problem - here are some screenshots:

After MX_I2S*_inits:

SPIs

0693W000005BmZ1QAK.pngDMAMUX

0693W000005BmaiQAC.pngDMA1

0693W000005BmcZQAS.png 

After first RxHalfCpltCallback:

SPIs

0693W000005BmeVQAS.pngDMA1 (DMAMUX is unchanged)

0693W000005BmfYQAS.pnghist data structures

0693W000005BmXZQA0.pngLater RxHalfCpltCallback:

0693W000005BmheQAC.png0693W000005BmiNQAS.pngIn RxCpltCallback:

0693W000005Bmj6QAC.png0693W000005BmhpQAC.png 

Piranha
Chief II

"Testing shows the presence, not the absence of bugs." /Edsger Dijkstra/

Take a note that such issues can happen because of this:

https://community.st.com/s/question/0D50X0000C5Tns8SQC/bug-stm32-hal-driver-lock-mechanism-is-not-interrupt-safe

And yes - that means that almost the whole HAL library is flawed and unreliable.

I appreciate you pointing me to this post. Do you suggest I change the code directly with your suggested code (first post) or will I have to wait for a full rewrite of the HAL library 😉 ? Will this possibly fix my problem?

Even though there is some hate towards the HAL library I think that it beats manually setting register bitfields in the correct order, having to carefully read the full 600 page manual before you can do anything practical with the MCU. I also like that you can reuse setups and code between different MCU families. I think there is a reason for arduinos popularity beyond price and functionality.

You haven't shown us the respective GPIO registers' content. DR being stuck at 0 - while everything otherwise indicates I2S and DMA running OK - sounds much like data pin for the given I2S not being set in GPIO.

As for interrupts appear to be missing, try a much slower I2S clock, that could perhaps reveal if it's the bloated Cube code or something else.

JW

evenlund
Associate III

Thank you for your insight!

Here are the GPIO registers just after the I2S init:

0693W000005BunfQAC.png0693W000005BunpQAC.png0693W000005Buo9QAC.png 

In the first RxCpltCallback only these registers changes:0693W000005BuoOQAS.png0693W000005BuoxQAC.png 

In successive callbacks only the IDR registers of GPIOA, GPIOB and GPIOF changes. Crossing fingers that there is a simple fix.