cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F7 - using SPI (slave) with DMA to set a flag (I.E. no interrupts)

Richard Tarbell_2
Associate II

We are trying to use SPI1 as a slave to receive 11 bytes of data per transaction.

I.E. SPI1_RX --> my_data_array[11]

When an 11-byte transaction is received, we want the DMA to raise a flag that we will check (we can't afford to use interrupts, as this is for a motor control application, and other interrupts can mess with our 50usec current control loop).

When I try to configure this as a project in CubeMX, the "DMA Global Interrupt" checkbox comes in the project as pre-checked, and I cannot uncheck it. Does this mean that we MUST use an interrupt to signal that the DMA is done transferring?

16 REPLIES 16

> When I try to configure this as a project in CubeMX, the "DMA Global Interrupt" checkbox comes in the project as pre-checked, and I cannot uncheck it. Does this mean that we MUST use an interrupt to signal that the DMA is done transferring?

No. It just means that Cube/CubeMX is written this way.

By using a "library" you are bound to use whatever facilities the "libary"'s authors meant you to use.

The DMA interrupt does not need to be enabled, and you can check the DMA Transfer Complete flag DMA_LISR/HISR.TCIFx any time later. Read the DMA chapter in RM.

JW

RMcCa
Senior II

The dma always sets its transfer complete flag when the ntdr reaches zero. You can read the status register and the ntdr at anytime. It's up to you whether it causes an interrupt or not and how the dma behaves when the transfer is complete.

Ditch hal and set the registers yourself. ​

berendi
Principal

There is an important rule: You can have either strict timing requirements or CubeMX/HAL in one project, but not both.

Read the SPI functional description/Data transmission and reception procedures chapter in the reference manual, it has a section on Communication using DMA, and follow the instructions there.

Richard Tarbell_2
Associate II

Thank you ALL for your help - I've got progress!

So right now, I AM receiving the first 11-byte transaction from the SPI slave (great!) - I DO see my_data[11] update with correct values. After this, when a second transaction is sent, my data buffer (my_data[11]) does not change, even though the SPI1 registers do change. This tells me that the SPI is still receiving data, but the DMA itself isn't transferring it.

I'm not using interrupts for this (at least not yet). I also see that my DMA2 -> S1NDTR changed from 11 to 0 after the first transaction. When I change this back to 11 using the debugger, it still does not perform additional DMA transactions.

--> I believe I'm not "resetting" the DMA properly, after a transaction has been performed.

Try resetting the DMA interrupt flags (LISR or HISR)

> Try resetting the DMA interrupt flags (LISR or HISR)

... using LIFCR/HIFCR.

0690X00000BugJpQAJ.png

JW

Richard Tarbell_2
Associate II

Thank you for your help again! OKAY, I have reset the DMA interrupt flags by writing "1"s to the appropriate LIFCR register positions.

--> When I call HAL_DMA_Start() the first time at code startup, everything works, and my return status is HAL_OK.

--> After my first DMA transaction, I clear the DMA interrupt flags, and I call HAL_DMA_Start() again. This time, it returns HAL_BUSY, so the stream never enables again. Should I keep calling HAL_DMA_Start() until I get a HAL_OK status?

I don't Cube.

OTOH, Cube is open source, so you can figure this out yourself.

Note, that you are already not using it as it was intended.

JW

RMcCa
Senior II

Yeah, don't know about hal, but certainly the busy status is trying to tell you something. Saying what? Think about it for a while and study the reference manual.

You could try polling for it clear but methinks you will be waiting for a very long time.​