Showing results for 
Search instead for 
Did you mean: 

STM32H7 I2S no data on Data line

Associate II


I am interfacing audio Codec SGTL5000 with STM32H7 Nucleo board. I2S peripheral is initialized using the HAL init function. I converted a wav file to a C array and trying to transmit that to the Codec. STM32 is configured as Master TX and Codec is configured as slave. The driver code is generated from CubeMX. Data is configured for 16 bit data format.

When I try to transfer the audio data, I do not to see any data on the I2S data line of the controller. After further debugging, I see that in the function HAL_I2S_Transmit(), on the specific line:

*ptxdr_16bits = *((uint16_t *)hi2s->pTxBuffPtr);

the TXDR register is supposed to get updated with the 16-bit data. But on checking the register values in debugger, I see that this register is not updated. After this line is executed, on logic analyzer, I can see that the SCLK and LRCLK clocks are generated at the correct frequencies and these clocks keep running forever. But as there is not data to be transferred in TXDR, there is no activity on the data line.

I have spent a good amount of time debugging but with no success. Please suggest if I am missing something.



> HAL_I2S_Transmit()

And does your code call this function?



well, you try to send a word over I2S to a codec - thats a strange idea.

usually ... I2S is a continuous stream of data , send "nothing" is send always "zeros" , so stream never stops. So standard way would be, to use a buffer and send data with circular dma continuous from this buffer. and if codec should get some adc data also, a transmit and receive happen at same time.

i use - cpu is master and dac is slave , i2s set for 16bit /stereo at 44,1 or 48k sample rate -

HAL_I2S_Transmit_DMA(&hi2s5, (uint16_t *) playbuf , (sizeof(playbuf))/2);

int16_t playbuf[4096*2] is the buffer with data to send, using callbacks.

so...first try to start sending a dma controlled stream to the dac.

Yes. HAL_I2S_Transmit() is called periodically from the application and sends the data generated from the wav file.

Associate II


Thanks for the reply.

HAL_I2S_Transmit() is called periodically to ensure a continuous stream of data. What is baffling me is that in this HAL function, any attempt to update the TXDR register is just ignored by the processor. For experimentation, I also tried updating the specific memory location for TXDR (0x40013020) through pointer but it stays at all 0s as seen using debugger memory. Unless the required data is not loaded in TXDR, it is not expected to see any audio data output.

I did start with DMA but as DMA has some other issues, I moved to blocking calls. Also, our setup does not involve any ADC inputs.

Lead III

Time to show some source code.

I'm using SAI and I2S on a STM32H723 / H735, and it has no issues whatsoever with these peripherals or DMA.


on H7 the SPI (-> I2S) is not same as in smaller cpu (F4 );

i tried sending just by write to TXDR (as i did on F303 ) - but nothing happens! no data send...

so i used the HAL functions , worked ok . (and looking at TXDR in debug might not work at all, because there is a fifo and IF (!) the spi sending on a write, the register/fifo will be empty on next read access - you can only "see" something, if it stays there and is not sended out.

and dma working fine, just switch off D-cache at first. (later you can do the cache management- if you need/like )

As AScha.3 wrote above, the SPI/I2S on H7 is overcomplicated and picky. You may want to read carefully the I2S portion of SPI chapter in RM, maybe concentrating on Internal FIFOs and Handling of underrun situation subchapters, or maybe even more.

SPI2S_TXDR is write-only, you cannot read back what you've written to it.