The nuance that makes your I2S not work…
… and about which for some reason nothing is written anywhere.
Some time ago I sat down to master the I2S interface for working with a high-quality audio DAC. I already had a lot of experience working with various SPI chips, I2C chips, methods of working in blocking mode, non-blocking mode via interrupts, non-blocking mode via DMA. In general, it seemed to me that nothing could surprise me anymore. But this is why we love the world of electronics and computers – it can surprise even the most sophisticated developer.
I use the CMSIS library, and I look at the information about working with the device directly in the RefManual to get information first-hand. I2S is part of the SPI module in my beloved STM32F446. The first impression was that only the pins were different, but the essence does not change. You put data in the send register, and the device itself handles everything as it should.
I configured the module, launched the program and even checked the timing diagrams on the oscilloscope. Everything was fine. Only the DAC, instead of some test nonsense, gave out 0. Well, it's time to figure it out.
I started reading what people were writing on the internet. People on the internet weren't writing anything new that wasn't written in the stm32 refmanual. So, the problem is in the hardware.
I bought another I2S DAC in case mine was broken for some reason. That didn't help either.
I had to write to my friend who had already started the I2S DAC. I described my problem to him, he also did not understand why nothing worked for me. However, he kindly generated a test firmware for my stone and my pins.
The firmware started, started generating some sine with incorrect recording of symbolic information (but it was clear that the friend wanted to generate a sine). And then a smaaaaall nuance was revealed, which everyone forgot to write about for some reason.
SPI, I2C, USB, USART and other protocols work on the principle of “the initiative excites the initiator”. You have an SPI DAC. You send it a command “set the voltage value to V/2”, for example. And then you keep silent for a thousand years. The DAC stands silently and holds the value it was told to hold. Until it is de-energized, of course. The same situation applies to other protocols. They communicate only when they have something to say. But I2S is not like that!
In I2S communication, the Master must continuously, and with the correct clocks, constantly send the value that it wants the DAC to hold. Without this, as you understand, nothing will work at all.
It is uneconomical to occupy the processor with such useless work. That is why DMA is forced to do it. The DMA module is shown 2 cells in the memory (after all, it is I2S stereo): here the I2S DAC values will be stored. The DMA channel is launched in cyclic mode so that it continuously dumps numbers from the stone's memory into the DAC. You change the data inside the memory at your own pace (or even not change it at all), and the DMA foams at the mouth and sends them to the air. And everything works fine, if the clocks are configured and so on.
Before writing this article, I checked Google results on the I2S topic once again, but I still couldn't find a description of this little nuance. That's why I'm publishing the text. If you know this, then you need any articles on the topic, or a ref manual for the stone.
In the end, I chose a four-channel 16-bit SPI DAC for my device. But that's a completely different story, which I plan to tell in another post.
Thank you for your attention and good luck with your research!