SPI slave doesn't transmit, STM32F407VE - Page 1
Forum section: electronics / general

author: ficus
author_rank: Newbie
timestamp: March 21, 2018, 11:22:44 am
content: I have STM32F103C8 as a SPI master and a STM32F407VE as a SPI slave.I haven't worked with SPI enough to find optimal way to write communication mechanism, and earlier work with SPI only on AVR and Texas Instruments C2000 platforms, so STM32 is new for me.That's what I remember about SPI: Master initializes communication, sends data by MOSI with CLK. Slave can answer to request only when master will send something. So - slave should be ready to push data by MISO when CLK will appear. Hope that's right.Transmission and receiving by interrupt works fine. F103 transmits by command HAL_SPI_Transmit() to F407, which receiving data in ISR, every byte, no troubles.But now's my headache begins.Master sends command to slave to get ready for answer. Slave collects data in one array and pushes it to transmit buffer. Master, after 1ms delay sends zeroes to slave just to receive whole array of data from slave. '\n' means the end of transmission.So how I should organize that?Slave receiving command to get ready, that's alright.Slave collected data in one array.What should be next?I use command HAL_SPI_Transmit() and push there whole array. As I hope - this data will be held in SPITx buffer, and when CLK appears - will be pushed through MISO until master stops communication.But it's not working like that. Master receiving nothing.The question is: How slave should transmit data to master? When? What functions should be used?

author: SiliconWizard
author_rank: Super Contributor
timestamp: March 21, 2018, 03:48:51 pm
content: Since you seem to be using the STM32Cube libraries, I suggest looking at their example SPI projects (in the projects subdirectory of the STM32Cube directory).You should probably use the HAL_SPI_TransmitReceive_IT() function.

author: ficus
author_rank: Newbie
timestamp: March 22, 2018, 11:58:03 am
content: Found and solved problem.Slave was receiving command to get ready byte by byte. Every received byte caused interrupt, and in the end of interrupt callback function next receiving interrupt was enabled.After handling interrupt all SPI flags resetting to normal state. So when I was receiving dummy data from master - RxCallback was called, and at the end of processing all SPI flags was reset automatically, so slave couldn't insert anything to SPI Tx register.Now interrupts are enabling only if command still isn't received. If command to get ready received - only flag to get ready is setting on. Data is pushed in function HAL_SPI_Transmit(), and after it stands a function that waits SPI to transmit everything it has in buffers. Only then I turn on SPI Rx interrupt.If I described it too complex - tell me, and I'll try to write it other way.

author: mikerj
author_rank: Super Contributor
timestamp: March 22, 2018, 02:12:47 pm
content: Consider using DMA for an SPI slave, rather than purely interrupt driven.

author: ficus
author_rank: Newbie
timestamp: March 28, 2018, 08:43:40 pm
content: DMA is setting me restrictions in packet length.I have no unified data packet length, so packet can be 2 bytes or 128 bytes, I can't tell before end of receiving. That's why I can't use DMA.Am I wrong? Is there a way not to be limited by packet length?

author: mikerj
author_rank: Super Contributor
timestamp: March 29, 2018, 11:12:26 am
content: So set up the DMA after you receive data from the master. The important factor here is the "turn around time" i.e. the time from receiving the data to the master wanting to read the data back. If you have control over the master then there should be no problem, if its something you have no control over and it's a single cycle turn around with a high speed clock then you may not have time.Obviously to use DMA the data that needs to be accessed must already exist in a contiguous block of memory, rather than values are that calculated "on the fly" in the SPI interrupt.

author: Siwastaja
author_rank: Super Contributor
timestamp: March 31, 2018, 03:36:35 pm
content: You can set up the DMA for the longest expected message, then configure EXTI rising edge interrupt for rising nCS. In this ISR, you can read DMA NDTR (data remaining) to calculate actual received length, and reconfigure DMA/SPI as you wish, for the next transfer. Note that reconfiguring STM32 SPI in variable-length DMA case requires resetting the whole SPI peripheral through RCC reset register, it's the only way to empty the TXFIFO.As STM32 SPI generates DMA request as soon as it's enabled, in some cases, you need to use a similar interrupt for falling nCS to start the DMA at that point, to get "recent enough" data in the SPI TXFIFO. In this case, make sure the slave asserts nCS early enough to allow some processing delay in the ISR, however, you can do the initialization pretty fast if you don't use the bloat libraries.