cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H747 I2S slave mode

lukasma
Associate III

Hello,

I have a setup where I use an STM32H747XIH6U and an ADAU1361 codec on the I2S-interface. I want to use the PDM-mics on the ADAU, and in order to do that, ADAU has to be in I2S master mode according to the datasheet. Consequently, STM has to be in slave mode. However, in slave mode STM does not generate an MCK, which for some reason is required by ADAU, even though it is supposedly in master mode (it uses the MCK input to generate its internal clocks both in slave and master mode, apparently). So, my question is: Is there a way to output a MCK in STM slave I2S mode anyways? I'm using CubeMX to generate code, and from there it is not possible to configure I2S in full-duplex slave and have a MCK. Can I use another clock, or is there some other workaround?

1 ACCEPTED SOLUTION

Accepted Solutions
lukasma
Associate III

Well, turns out that when we configured PLL2 to provide the clock for MCO2, we used dividers which were not even, According to the reference manual, you don't get a duty cycle of 50 % in that case. Switching these to even numbers instead now gives a duty cycle around 51.3 %, which is a great improvement. We would like it to be more smack on 50 %, but maybe it doesn't matter if we can get it to work

View solution in original post

15 REPLIES 15
Roger SHIVELY
ST Employee

Hello @lukasma ,

There has been a case created to resolve this question and we will be reaching out to you directly.

Regards,
Roger

AScha.3
Chief

Hi,

In such case the "master clock" is (for high quality audio) a separate low noise oscillator, close to the dac or ADAU1361 here. Not from a cpu with its on chip "noise" .

The ADAU1361 then doing its I2S master timing and the cpu just has to give it the data as slave.

I do this same way to play audio with a H743 , reading from sd-card, to a ES9038 dac in master mode, with its 

45.1584 MHz AS318 master clock .

-> http://www.accusilicon.com/docs/AS318BM.pdf

But if you just want test it, use an MCO on the cpu and set it to a frequency the ADAU1361 can use.

If you feel a post has answered your question, please click "Accept as Solution".
LCE
Principal

As a start or workaround, take another I2S peripheral and only use it to create MCLK.

This has the advantage of being independent from oversampling ratios.

/* MCLK from I2S3 on / off */
#define MCLK_I2S3_OFF		SPI3->CR1 &= ~SPI_CR1_SPE
#define MCLK_I2S3_ON		SPI3->CR1 |= SPI_CR1_SPE


/* SPI3 / I2S3
 *	independent MCLK source
 *		because SAI and I2S want fixed and too high oversampling ratios
 */
void I2S3_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct = { 0 };
	uint32_t u32Div = 0;

	/* I2S3 clock enable */
	__HAL_RCC_SPI3_CLK_ENABLE();

	/* I2S3 GPIO Configuration
		PC7		------> I2S3_MCK
	*/
	GPIO_InitStruct.Pin 		= I2S3_MCLK_Pin;
	GPIO_InitStruct.Mode 		= GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull 		= GPIO_NOPULL;
	GPIO_InitStruct.Speed 		= GPIO_SPEED_FREQ_HIGH;
	GPIO_InitStruct.Alternate 	= I2S3_MCLK_AF;
	HAL_GPIO_Init(I2S3_MCLK_GPIO_Port, &GPIO_InitStruct);

/* I2S3 = SPI3 register settings
 *	to get MCLK output
 *	clock input is I2S_CKPIN, set with RCC
 */
	SPI3->CR1 = 0;			/* unused for I2S */
	SPI3->CR2 = 0;			/* unused for I2S */

/* I2SCFGR: configuration register
 *	most important settings here
 * 	DMA and I2S enable are set when started
 *	MCKOE		= 1		MCLK is ON, on/off is done with SPI_CR1_SPE
 * 	ODD			= 0 	unused, for divider I2SDIV
 * 	I2SDIV		= 1 	divider, start with 1 -> 25.6 MHz
 * 	DATFMT		= 0 	data alignment - don't care
 * 	WSINV		= 0 	LRCK hi/lo - don't care
 * 	FIXCH		= 0 	data length - don't care
 * 	CKPOL 		= 1 	clock polarity ?
 *	CHLEN 		= 1		data length - don't care ?
 * 	DATLEN 		= 10 	32-bit - don't care ?
 * 	PCMSYNC		= 0 	PCM short / long sync - don't care
 *	I2SSTD 		= 00	standard - don't care
 *	I2SCFG 		= 011	master RX - master is must to turn on MCLK
 *	I2SMOD 		= 1 	I2S instead of SPI
 */

/* I2SCFGR: configuration register */
	SPI3->I2SCFGR = I2S_CFGR_MCLK_OUT_ONLY;

/* get I2S3 MCLK frequency */
	if( 	 __HAL_RCC_GET_SPI3_SOURCE() == RCC_SPI3CLKSOURCE_PIN )  u32I2SxMclk = RCC_VCO_CLOCK_AUDIO_200K;
	else if( __HAL_RCC_GET_SPI3_SOURCE() == RCC_SPI3CLKSOURCE_PLL2 ) u32I2SxMclk = RCC_PLL2_CLOCK_AUDIO;
	else if( __HAL_RCC_GET_SPI3_SOURCE() == RCC_SPI3CLKSOURCE_PLL3 ) u32I2SxMclk = RCC_PLL3_CLOCK_AUDIO;
	else u32I2SxMclk = 0;
	u32Div = (SPI3->I2SCFGR & SPI_I2SCFGR_I2SDIV) >> SPI_I2SCFGR_I2SDIV_Pos;
	if( u32Div == 0 ) u32Div = 1;
	u32I2SxMclk /= (2 * u32Div);

/* I2S3 MCLK enable - later with SAI DMA start */
#if( 1 )
/* DEBUG */
	MCLK_I2S3_ON;
#endif
}

Thanks, I'll try this solution. However, there will probably not be any external oscillator in the final solution, as that causes other issues in our case. So if it works, we are likely to go with this as the final solution. There won't be as much flexibility with this solution as other solutions, be we don't have too many options actually.

lukasma
Associate III

Okay, so I've tried for a while with MCO2 on my STM32H747I-DISCO devboard. The clock is extracted from the microSD connector CN12, but it looks more like an analog clock than a digital one; it is not a square wave, at least. The frequency is set to 49.152 MHz to achieve a sampling frequency of 48 kHz on the adau1361, and maybe the pin connected to the microSD connector doesn't support such high speeds? Or, there might be something fishy with the measurement setup. I don't really know, I have consulted a lot with my team but we can't really seem to find what's the issue with this clock/pin. Do you have any ideas?

LCE
Principal

50 MHz is not so simple to measure correctly, or to make it visible as it actually is.

Is your scope fast enough?
Good 10:1 low cap probe?
Probe with spring tip to GND instead of the typical 10 cm cable?

And you should check the schematics if there's anything else connected, any loads or termination.

You can also check the PCB files of the Disco-Board, because of the many options the routing is sometimes a little "crazy".

+ Port/pin speed is set to high or very-high ?  (Then mco puts out > 100MHz without problems.)

+ You cannot have a > 10cm wire free air with such a radio frequency ! (its in upper SW range ! )

Another reason for the separate master-clock oscillator close to the ADAU .

If more than few cm distance with 50MHz signal needed, use a screened cable , RS174 or so, screen on gnd both ends.

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

The "Maximum output speed" is set to very high in CubeMX, and now I'm measuring directly on the microSD-connector, so only PCBA traces involved (and oscilloscope probe, of course). It is not the most high-tech oscilliscope, just a small Tektronix TDS2024B. I have it in 10x mode, so it should be able to measure up to 200 MHz frequencies.

lukasma
Associate III

We have now tried to measure the clock with a Lecroy HDO6104B using av ZS1500 active probe. The duty cycle of the MCO2 is around 61% for a number of different frequencies. We have tried with 49.152 MHz, as we want in the final application, but also with 48 MHz, 30 MHz and 80 MHz. Still, the duty cycle is around 61%, and the edges oscillate, making it look like a square wave with a superimposed sine wave. The measurement setup can not be much better now from our side, so we are left to wonder what might be going wrong with SW/HW?