Porting WM8731 codec driver from STM32 SPL to LL drivers -- sample rate question


Hi all,

I’ve recently begun the work of taking the WM8731 codec driver found in a lot of Mutable projects from depending on STM’s Standard Peripheral Library to the newer Low Level drivers. As soon as I can verify it’s working I’ll throw it up on GitHub in case they could be useful for someone else wanting to work with the HAL/LL and still use the driver.

Full disclosure, this is a learning exercise for me – I’ve done some work in the past with embedded systems but this is my first time diving into ARM or STM technologies.

Just about everything is compiling now, but the last hurdle is in InitializeAudioInterface(...) and I’m not sure how to proceed. The SPL code uses RCC_PLLI2SConfig(N, R) but the LL equivalent wants N, R, and M: LL_RCC_PLLI2S_ConfigDomain_I2S(M, N, R). I’ve had a look through the manuals and tried to work backwards through the calculations, but I’m not sure how this is supposed to work. Can anyone shed some light on this?


I googled and found this documentation for the function you mentioned. As a semi-educated guess, M could be a parameter allowing fractional frequency division, which may not have been supported in the SPL code. However, there doesn’t seem to be a #define value for M=1, i.e. no division…

You may have done this already, but it might also help if you can find a block diagram of the PLL subsystem somewhere in a datasheet so you get a high level idea of what’s going on.


You can download on the ST website an Excel spreeadsheet where you feed all the parameters and all the clock rates for the entire tree are computed.

Maybe it’s been integrated into the Cube GUI.


I found the spreadsheet and have figured out what the issue is – it’s not the LL drivers, necessarily, but the difference in hardware (I’m using the STM32F411RE).

The Cube GUI does indeed have a version of this spreadsheet. I can use this to get the values and generalize from there.

One thing I’d like to make sure on though – for the I2S MCLK output (assuming F_s = 44.1kHz), should I be aiming for 256 * F_s = 11.29 MHz or F_s * 2 channels * 16 bits = 1.41 MHz?


The purpose of the master clock is to clock the internal computations happening into the codec (input and output filtering). It’s not a bit clock. So the correct rate is Fs x 256. Check page 37 of the datasheet because with some settings the multiplier is not 256.

It’s not the same as the BCLK (bit clock) which is used to delimit each bit of data transferred between the MCU to the codec (and the rate of which is Fs x 2 (channels) x resolution).


Exactly what I needed to hear. Thank you Emilie!

I’ll update this post with the link to the GitHub once they’re up.


The first compiling version is up on github.

I have yet to be able to get the codec initialization to work in hardware – looking with a logic analyzer it doesn’t seem to sending clock anywhere (even I2C). I’m not convinced this is a problem with the port; it’s probably more to do with my inexperience with STM MCUs and not having configured some peripheral or another correctly.

Still, even in this version I hope it can be useful to someone.