cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F446 I2S stuck on Busy

FLewz.1
Associate III

Hi,

I've been trying to get I2S to work without using the HAL to get to know the MCU a bit more. I configured the Peripheral as mentioned in the reference manual, but whenever I write to the SPI->DR the status is stuck on busy.

This is my init function

	RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;	// enable GPIOA Port CLK; PA4 I2S1-WS; PA5 I2S1-CK; PA7 I2S1-SD
	GPIOA->MODER |= GPIO_MODER_MODE4_1
					| GPIO_MODER_MODE5_1
					| GPIO_MODER_MODE7_1;
	GPIOA->MODER &= ~(GPIO_MODER_MODE4_0 | GPIO_MODER_MODE5_0 | GPIO_MODER_MODE7_0);
	GPIOA->AFR[0] |= (GPIO_AF5_SPI1 << GPIO_AFRL_AFSEL4_Pos);
	GPIOA->AFR[0] |= (GPIO_AF5_SPI1 << GPIO_AFRL_AFSEL5_Pos);
	GPIOA->AFR[0] |= (GPIO_AF5_SPI1 << GPIO_AFRL_AFSEL7_Pos);
 
	RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;		// enable I2S Peripheral CLK
	SPI1->I2SPR  |= SPI_I2SPR_I2SDIV & 47u; // set I2S Prescaler to 47
	SPI1->I2SPR  &= ~SPI_I2SPR_ODD;			// set I2S ODD to 0
	SPI1->I2SCFGR &= ~SPI_I2SCFGR_CKPOL;	// set Clock Polarity to LOW when IDLE
	SPI1->I2SCFGR |= SPI_I2SCFGR_I2SMOD;	// set Mode to I2S
	SPI1->I2SCFGR |= SPI_I2SCFGR_I2SCFG_1;  // set Mode to I2S Master Transmit
	SPI1->I2SCFGR &= ~SPI_I2SCFGR_DATLEN;	// set Data Length to 16 Bit
	SPI1->I2SCFGR |= SPI_I2SCFGR_CHLEN;	// set Channel Length to 32 Bit
	SPI1->I2SCFGR &= ~SPI_I2SCFGR_I2SSTD;	// set Channel to Philips Standard
//	SPI1->CR2 |= SPI_CR2_TXEIE;
//	NVIC_EnableIRQ(SPI1_IRQn);
	SPI1->I2SCFGR |= SPI_I2SCFGR_I2SE;		// enable I2S

In my main i simply check if TXE is set and then write a new value to the DR but since it never clears there is nothing happening there either.

What am I doing wrong?

1 ACCEPTED SOLUTION

Accepted Solutions

And can you see the sample frequency on LRCK?

Try to measure directly on the pin (suspecting bad solder joints) and check for shorts - unless this is a "known good" board such as Nucleo or Disco. Try to set the pin to GPIO output and wiggle it, measuring level on the output.

Coincidentally I'm working on I2S1 on a 'F446 and do have PA4/PA5 as LRCK/BICK, and can confirm that yes they do work when AFR=5.

If you're stuck, read out and check/post all the relevant registers content.

JW

View solution in original post

17 REPLIES 17

Do you have the I2S2 (yes, confusingly named, referring to "I2S on APB2", which is the case of SPI1) clock set up in RCC_DCKCFGR, and if PLL clock is used, do you have that PLL up and running?

Then, observe the pins using oscilloscope/LA for clock activity.

Finally, if everything fails, read out all the SPI/I2S and relevant RCC and GPIO registers content and check/post.

Also, observe the 2.1.5 Delay after an RCC peripheral clock enabling erratum.

JW

PS. Style: don't do changes gradually into a register if there's no specific need for it. Read it into a temporary variable and do the changes there, or simply write a single expression generating the literal to be written into the register.

> Do you have the I2S2 (yes, confusingly named, referring to "I2S on APB2", which is the case of SPI1) clock set up in RCC_DCKCFGR, and if PLL clock is used, do you have that PLL up and running?

Oh so that explains why nothing would work, when trying to get the clock configured manually, because I assumed I had to write to I2S1!

I got frustrated and took the clock config from a cube generated project. Now it is not stuck on the busy state anymore, but I still can't get sound out.

Unfortunately I only have a multimeter to measure frequency. On the word clock I get a reading of ~49.8 kHZ which is not good, but would suffice for me to get a sound out of it. I can't get a reading from the bit clock, but since the word clock is derived from it, this should be ok as well,right?

Edit: I could verify on a Teensy 4.0 board, that my I2s module works, which I doubted at this point, and that my multimeter was capable of measuring into the tens of Mhz.

So now the problem is, that I don't see a frequency on the BCLK pin PA5, so it seems there is something wrong here. I upped the speed to highest, but no luck.

The register values for the relevant GPIOA Pins (4,5,7, all same values)

MODER - 0x02

OTYPER - 0x00

PUPDR - 0x00

ODR - 0x00

LCKR - 0x00

AFRL - 0x05

Edit2:

> The I2Sx clock is always the system clock

What is this phrase on p. 878 of the reference manual 0390 supposed to mean? I was led to believe, that the I2S Clock is my main clock i.e. 144 MHz. But I can see, that in the clock configuration there is a perippheral clock for the I2S and SAI Modules

And can you see the sample frequency on LRCK?

Try to measure directly on the pin (suspecting bad solder joints) and check for shorts - unless this is a "known good" board such as Nucleo or Disco. Try to set the pin to GPIO output and wiggle it, measuring level on the output.

Coincidentally I'm working on I2S1 on a 'F446 and do have PA4/PA5 as LRCK/BICK, and can confirm that yes they do work when AFR=5.

If you're stuck, read out and check/post all the relevant registers content.

JW

FLewz.1
Associate III

So I just tried to pick I2S2, and everything works perfectly. There must be something wrong with my pins, although this is a nucleo board and I am fairly sure I didn't put multiple functions unto one pin.

PA5 is the green LED, so it should be easy to test whether it's alive.

> The I2Sx clock is always the system clock

Yes, this is wrong.

Unfortunately, ST's documentation is not famous for being clear and concise. This appears to be some leftover from a different STM32 model's description - I see this sentence in 'F0 RM (where it's true). A similar sentence is in 'F3's RM0316, where it's not true.

@Imen DAHMEN​ , can this please be chalked up for correction? Thanks.

JW

FLewz.1
Associate III

The green LED was always on, and I didn't get a frequency on that pin, so it was always low. All of this while having the pin in AF5.

FLewz.1
Associate III

To piggyback on this: What is the configuration to get the behaviour described in the RM as '16-bit data frame extended to 32-bit channel frame'?

Right now I have CHLEN to 0 and DATLEN to 0, so that Data length and channel lenght are both 16 bit, however measuring the time between two TXE interrupts I get a big variation in cycles from ~1550 to ~1670 at a SysClock of 180 MHz. The BCLK is correct at 48 kHz.

Hello @Community member​ ,

Thank you for pointing this out to me.

I raised it internally for correction.

Thanks @FLewz.1​  and @Community member​  for your contribution.

Imen

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen

Thanks, Imen.

Jan