cancel
Showing results for 
Search instead for 
Did you mean: 

How do you stop SPI DMA circular transfers in a G474RE

Greg Horler
Associate III

I am using a NUCLEO64-G474RE as an SPI master with DMA (Rx and Tx in circular mode) to interface an ADC CHIP. I am receiving data reliably but wish to stop  and start the SPI/DMA . 

I have used CubeMx to generate the initilisation code and HAL_SPI_TransmitReceive_DMA( ) to start sampling. However I cannot stop the reception.

I have read the relevant sections of RM0440. The only reference to stopping the SPI/DMA is on page 1745 where it states

  1. Disable DMA streams for TX and Rx in the DMA registers, if the streams are used.
  2. Disable the SPI by following the SPI disable proceedure as follows (this is on Page 1743)
      Wait until FTLVL[1:0] = 00 (NO MORE DATA TO TRANSMIT)
      Wait until BSY=0 (THE LAST DATA FRAME IS PROCESSED)
      Disable the SPI (SPE =0);
      Read data until FRLVL[1:0] = 00 (read all the received data)
  3. Disable DMA Tx and Rx buffers by clearing the TXDMAEN and RXDMAEN bits in the SPI_CR2 register, if DMA Tx and/or DMA Rx are used.


I could find no reference to the term "streams" in the DMA section of the data sheet, what are they?

My effort is below, what am I doing wrong? Many thanks in advance.

/* stop the SPI-DMA process */

HAL_SPI_DMAStop(&hspi3); // Disable DMA streams if used what and how???
__nop();

while (((SPI3->SR)&(3<<11))) {}; // Wait until FTLVL[1:0] = 00 (no more data to transmit)

while (((SPI3->SR)&(1<<7))) {}; // Wait until BSY = 0 (the last data frame is processed)

SPI3->CR1 &= ~(1<<7); // Disable the SPI (SPE = 0)

do{
dummy = SPI3->DR; // Keep doing dummy reads of the SPI3 data register
dummy = SPI3->SR; // (this line allows the FRLVL bits to be observed)
} while(((SPI3->SR)&(3<<9))); // until FRLVL[1:0] = 0 i.e. all data received

SPI3->CR2 &= ~(11); // Disable DMA Rx and Tx buffers TXDMAEN = RXDMAEN = 0

GDH
19 REPLIES 19

A single spi channel. The spi clock frequency is 385kHz, to satisfy the Nyquist sampling rate. The DMA is configured as circular, in bytes. The Tx buffer equals the RX = 256 bytes (i.e. 64 samples) though this can vary to accomodate the interleaving frequency of the half and full dma callbacks. The length of the packets returned are 273 bytes, and a packet is transmitted every 3.5ms

I use a USB-CDC (vcom) transfer, not uart

GDH

> I use a USB-CDC (vcom) transfer, not uart

CDC uses Bulk transfer, which does not have guaranteed bandwidth. In other words, your problem may be at the USB side, not the SPI side.

Add some framing to your data.

JW

 Add some framing to your data.  Please be specific?

The data is "framed" in the sense that it conforms to a well constructed packet format that has not failed so far. Each packet is of fixed length and contains fields and delimiters. You will see from the raw data I posted that the spi data payload is contained is contained within braces of each packet. The packets are checked in before tramsmission and checked again by our pc application (and usb signal monitor), we have not had bad or dropped  packets. If we did I would expect gross defects in the packets. I will check this however by printing out the packets (unstead of transmitting them and see if the error manifests itself in the print cosole.

If by framing you mean separsating the data with delimeters then I use the fact that the upper and lower nibble of each four-byte sample is zero and this in effect gives me a delimeter between samples.

 

GDH

Hello again.

I have done some work to establish if the problem exists when the DMA is operating in NORMAL mode...

I also reduced the spi clock frequency 95khz to establish if the clocking has an impact, it shouldn't at this rate.

I set up the micro to work in normal mode and use the half and fully complete interrupts to convert the data received into the SPI3_DMA_Rx buffer into hexadecimal representation and print it directly to the keil console. I also added code to stop the dma, assert the chip select, then drop the chip select low and restart the SPI3_DMA_TXRX. This should result in a friendly message stating the dma is starting, followed by two strings on data on separate lines. The first is the data resulting from the Half complete interrupt, the second from the Complete call back.

The program works but the data is still skipping again, see attached .jpg  The green dot shows where the data goes out of sync. however I observe that the following this error is an overun and extra line. Any comments suggestions?

GDH

The brackets are the framing I was talking about - I did not notice this is screenshot of Tera Term, I though it's your program which already "reassembled" the data, sorry.

I though it is unlikely SPI drained by DMA to overrun.

On second thought, maybe it does not, and maybe it's the way how you format the data for transmission. You appear to use Cube/HAL - do you use RTOS, too? Do you output data using printf()? If both answers are yes, try writing a simple routine which outputs data without printf().

JW

 

 
GDH

Don't know what happened there?

I simplified the code to use a single printf to print a packet index (count) and packet data. This reduces the overhead to simply formatting the received data and a single print. Is this what you meant by >>" writing a simple routine which outputs data without printf()."

I also have an option to conduct multiple samples of the dma using normal mode. The error still there!

BTW  what do you mean by "...writing a simple routine which outputs data without printf(). "

I'm now attempting to establish if the byte shifting occurs with the spi running on its own (i.e. without the dma), I will post when I have some results.  

GDH

Hi all. Sorry for the radio silence. I have managed to create a program that samples data using the DMA and does not suffer from byte shifting. The project is called spi_interupt_test and I've included a 7zip version (the major files only- a full zip of the project exceeds the 5MB upload limit) for those having trouble getting started with the SPI, or, should anyone feel so inclined an example for review. The program can be compiled to run in spi_interupt, spi_dma_normal and spi_dma_circular modes by editing line 100 in main.c to set the value of spiSmplMode.

uint8_t spiSmplMode = 2; // 1 spi interrupt: 2 spi-dma normal: 3 spi-dma circular

This program lends itself to monitoring with an oscilloscope as the continual sampling of the circular DMA is cearly shown when compared to the observed periodic gaps in sampling when using the normal DMA or SPI interrupt.

I also have a stripped down version of the code that produces the byte-shifting errors I have previously described. I am perplexed as to why I cannot find the reason why this should be happening. I would be very happy to share this project with anyone who would like to help solve this riddle. The zipped (z7) project is 7.4MB, so would have to share via an alternative means...

GDH

Curiously, would it make sence to avoid situation that potentialy leads to unstablility than to put heroic efforts trying to solve all phasing errors?

I mean, would it be easier not to break SPI-DMA machine every 3.5 ms, and just "suspend" using Timer to manage spi clock and than just set one bit Timer-disable if pause required? 

Could you provide more details:

what kind of adc, master-slave, bits per word , and brif details on application?

Piranha
Chief II

 

SPI3->CR2 &= ~(11); // Disable DMA Rx and Tx buffers TXDMAEN = RXDMAEN = 0

 

This line definitely doesn't do what you think it does. By default the numbers in C are decimal... And by a pure accident it actually disables the intended #0 and #1 bits, but it also disables the bit #3. This just a perfect example of why the normal CMSIS mandated bit field defines must be used instead of magic numbers.

And what's with the overrun, to a description of which I already gave a link to? Does the code deal with it correctly? Also the advice from the reference manual, where they suggest disabling Rx DMA while the SPI peripheral is still running, seems like an instruction of how to get the overrun... The issue is similar to this one:

https://community.st.com/t5/embedded-software-mcus/bug-stm32-hal-sai-abort-and-dma-stop-logic-is-flawed/td-p/54339