cancel
Showing results for 
Search instead for 
Did you mean: 

How to inject your own data into the I2S line with DMA

CLeo.1
Senior II

Hi guys, as the question suggests,

Mentioned by many, to fully learn how the I2S behave I must use my own valid data, so I can see what happens to it.

I am having a bit of problems getting this guy to worked, I want this to implement a DMA to emulate the setup I am going to use.

The problem I am currently having is the data doesn't transmit or doesnt want to be transmitted.

The Way that I have it setup is that I converted my I2S to a Master Transmit, as data will be in memory instead of being received by external hardware

I transfer a sine wave look up header to a "RxBuff" via a DMA in Memory to Memory mode

From there when the DMA sends the Half... complete interrupts I transfer the values from "RxBuff" to a "TxBuff" then the DMA should transfer the "TxBuff" contents to the I2S3 TXR registers, however when I scan the lines I see no data coming out.

My understanding how this should work but is not, is when transferring the RxBuff contents into the TxBuff contents the I2S should have made a request to the DMA and the DMA then should fullfill that request to send it into the TXDR register however I am not sure thats happening

My concerns is that I read memory-to-memory Circ mode is forbidden so am I suppose to not get a continuous sinewave? just a one shot?

Main.C

https://pastebin.com/vYMLAWG6

I2S and DMA configuration

https://pastebin.com/wwxBJAw6

Transferring RxBuff to TxBuff

https://pastebin.com/UqPpVQrx

2 REPLIES 2

Which STM32?

Proceed step by step. Start from an empty project. Don't forget to set appropriate I2S clock (in some mcus it is marked confusingly by the APB bus number, not the I2S module number). Set respective pins in GPIO. Try I2S Tx "manually" first - just set up I2S as Master Transmitter, it has to start to transmit immediately when you enable Tx. Write data into DR in the debugger and observe the pins.

Then write the DMA but Tx only. Observe DMA registers - NDTR has to change.

You can do much of this in debugger, without writing any code (or incrementally writing more, after having tried in debugger).

Only after that try more.

JW

PS. Style: don't perform many subsequent RMW operations on one register. Read it into temporary variable, perform whatever change you want, and write back. In most of the cases, you don't need to read anything either, and a single write of a single constant is enough:

DMA2_Stream4->CR = (0x2 << DMA_SxCR_CHSEL_Pos)
			| (0x0 << DMA_SxCR_MBURST_Pos)
			| (0x0 << DMA_SxCR_PBURST_Pos)
			| (0x0 << DMA_SxCR_PL_Pos)
			| (0x0 << DMA_SxCR_PINCOS_Pos)
			| (0x0 << DMA_SxCR_MSIZE_Pos)
			| (0x0 << DMA_SxCR_PSIZE_Pos)
			| (0x1 << DMA_SxCR_MINC_Pos)
			| (0x0 << DMA_SxCR_PINC_Pos)
			| (0x0 << DMA_SxCR_CIRC_Pos)
			| (0x1 << DMA_SxCR_DIR_Pos)
			| (0x1 << DMA_SxCR_TCIE_Pos)
;

Don't RMW into the DMA flag-clear register - write 1 directly into required bits:

DMA2->HIFCR = DMA_HIFCR_CTCIF4_Msk

CLeo.1
Senior II

Noted, will do the code clean up in a later time. Thank you for the advice. I got it working, however I finding weird things on the I2S bus

Sending 0xFF (16 bits) with DATLEN = 16 and CHLEN = 32, works perfect. Starts after 1 SCLK, after 16 bits the left over 16 bits are set to 0 due to CHLEN > DATLEN. Its also MSB.

0693W000006EkbPQAS.png 

Sending 0xFFFFFF (24 bits). Whats going on here? It looks like I am missing a byte in the beginning? DATLEN = 24 CHLEN = 32,

0693W000006EkbeQAC.png