Skip to main content
kn7
Associate
January 10, 2011
Question

Receiving SPI data through DMA - STM32 internal hardware error ?

  • January 10, 2011
  • 16 replies
  • 3165 views
Posted on January 10, 2011 at 22:55

Receiving SPI data through DMA - STM32 internal hardware error ?

#spi-dma
This topic has been closed for replies.

16 replies

Tesla DeLorean
Guru
May 17, 2011
Posted on May 17, 2011 at 14:21

Try doing it slower. Try using different source/dest buffers. Look at the transaction with a logic analyzer.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
kn7
kn7Author
Associate
May 17, 2011
Posted on May 17, 2011 at 14:21

I've just checked different buffers as well as setting 16-bit SPI data length. It didn't help either. I don't have a logic analyzer...

I also examined my SPI functions on 2 different PCBs with 2 different SD cards and the problem existed with the two cards and PCBs.
kn7
kn7Author
Associate
May 17, 2011
Posted on May 17, 2011 at 14:21

I set the slowest SPI clock possible which is below 400 kHz in my application. It

didn't help. I will try to use different buffers.

kn7
kn7Author
Associate
May 17, 2011
Posted on May 17, 2011 at 14:21

The following code:

DMA1_Channel2->CPAR = (u32) SPI_ADDRESS;

or

DMA1_Channel3->CPAR = (u32) SPI_ADDRESS;

is written in DMA initialization routine. SPI_ADDRESS equeals to SPI data register address (SPI_DR)

To receive data via SPI the CLK clock must be active. The only way to do so is to send ''dummy'' data like it is done by sending data through SPI.

I discovered something strange. It turns out that sending data sometimes works incorrectly as well... I connected an oscilloscope to CLK and MOSI. The CLK signal is ok but i noticed there are corrupted bits sent on MOSI (instead of '1' i get '0' in some of the sent bytes). For example, when i send all bytes of 0x18 value, some of the bytes that i see on the oscilloscope are 0x00.
lowpowermcu
Associate III
May 17, 2011
Posted on May 17, 2011 at 14:21

Hi Robert,

I think that it should be something like this

DMA1_Channel2->CPAR = (u32) SPI_ADDRESS;

or

DMA1_Channel3->CPAR = (u32) SPI_ADDRESS;

Thanks to correct me in any case.

MCU Lüfter

lowpowermcu
Associate III
May 17, 2011
Posted on May 17, 2011 at 14:21

Hi k.robert,

Just one question:

Why channel 2 and channel 3 have the same address, I guess that one should have buffer address and the other the SPI data register address, isn't it ?

  DMA1_Channel2->CMAR = (u32) Buffer;

  DMA1_Channel3->CMAR = (u32) Buffer;

The code isn't commented si it needs much time to understand.

MCU Lüfter

kn7
kn7Author
Associate
May 17, 2011
Posted on May 17, 2011 at 14:21

It seems i solved the problem with sending data. The data length in SPI register (DFF bit) was set to 16-bit wide. In such case DMA->CMAR memory address register should be written with a value which must be an even numer (2 byte aligned). If the addres is not even DMA reads incorrect values which in turn are sent through SPI. I set the correct address and it work fine now. But i still have issues with the receiver...

lowpowermcu
Associate III
May 17, 2011
Posted on May 17, 2011 at 14:21

Hi robert,

In such case, you should check your board, perhaps you have something pulling down the line.

MCU Lüfter

kn7
kn7Author
Associate
May 17, 2011
Posted on May 17, 2011 at 14:21

Hi ANN;

I solved the problems with the receiving. I tried to receive data through DMA which memory size was set to 8-bit while SPI data word size was set to 16-bit. This is why it didn't work. Now it seems it works correctly.

Can you please mention the steps you have taken in order to get the receiving part of SPI work without DMA. I am also trying to do that. But it is not working properly.

 

 

I need to receive in slave mode.

 

 

I've never used slave mode without DMA but i will present the code that works well without DMA for master mode. I think it should also work in slave mode with slight modification.

Sending a byte in master mode:

void Send_SPI_Byte(u8 b)

  while (SPI1->SR & SPI_SR_BSY);

  while (!(SPI1->SR & SPI_SR_TXE));      

  SPI1->DR = b;

  while (SPI1->SR & SPI_SR_BSY);

  while (!(SPI1->SR & SPI_SR_RXNE)); 

  tmp8 = SPI1->DR;

}

The above function may look strange especially because of the flags SPI_SR_BSY that are checked twice. However, the functions NEVER worked when i writte them in other way.

The ''tmp8'' variable must be declared as global (otherwise the compiler will remove the code for '' tmp8 = SPI1->DR'' from you program)

As for slave mode i think the receiving function may look like this:

u8 ReadSlave_SPI_Byte(void)

  while (SPI1->SR & SPI_SR_BSY);

  while (!(SPI1->SR & SPI_SR_TXE));

            

  return (u8) SPI1->DR;    

}

nanayakkaraan
Associate III
May 17, 2011
Posted on May 17, 2011 at 14:21

Hello Robert,

Can you please mention the steps you have taken in order to get the receiving part of SPI work without DMA. I am also trying to do that. But it is not working properly.

I need to receive in slave mode.

Thank you.