1
\$\begingroup\$

My software appears to be working as expected, but the BSY flag is not clearing in the SPI register.

Background:

I am trying to get SPI working with DMA on the STM32. After figuring out that the DMA is picky about which channel you use for which peripheral, I got things working as expected. I read somewhere that it's important to ensure the SPI BuSY flag is cleared before starting another transfer. I am examining the registers using the ST/LINK v2 and for whatever reason, the SPI BSY flag is remaining set and if I have an IF statement in my code to confirm that it's cleared before continuing, the code hangs. I'm aware of the "Heisenbug" of observing the SPI_SR/DR registers with a debugger.

At first I tried using full duplex with SPI and the two DMA channels with the pins connected together and a TX and RX array. After the transfer, the RX array is a perfect copy of the TX array. Thinking that the issue may have been an expected clock-edge missing, I disconnected the two pins and set the SPI to TX only and commented out all of the RX DMA and SPI code. The issue persists.

Two things to note are that the BUSY flag is often the only thing set in the SR register. However, if I disabled the check for the BUSY flag and start the DMA transfer again, upon subsequent calls to the interrupt service routine, the RXNE and TXE buffers seem to arbitrarily change between 1 and 0, with the expected state of them both being empty being more common and the SPI_DR seems to sometimes get an arbitrary value. I don't see the overrun flag set.

Why doesn't the BUSY flag get cleared?

\$\endgroup\$

4 Answers 4

2
\$\begingroup\$

What exactly is throttling the SPI transfers? If you're using DMA directly (rather than triggered by a timer or something else), then as soon as the SPI is free, the DMA peripheral would start another transfer. As a result, being busy all the time would be expected.

According to the manual for the STM32F1xx series, section 25.3.7 (other series should have similar behavior):

When communication is not continuous, the BSY flag is low between each communication.

When communication is continuous:

● in master mode, the BSY flag is kept high during all the transfers

\$\endgroup\$
2
  • \$\begingroup\$ I'm still a little confused. I made the assumption that the specified DMA_BufferSize would transmit, the interrupt would fire and the SPI transfer would complete momentarily afterwards. Do I need to explicitly DISABLE the SPI channel in the ISR? Also, in one of my tests, according to the documentation, I was doing something wrong by having both channels 2 (RX) and 3 (TX) of DMA1 active simultaneously. With the pins of the device tied together, it appeared to work in full duplex. Was this because of the latency of the SPI transfer allowing both RX and TX to be serviced by DMA? \$\endgroup\$
    – Alan Samet
    Commented Jun 16, 2014 at 12:19
  • 1
    \$\begingroup\$ @AlanSamet No, using TX and RX DMA channels simultaneously with SPI is perfectly normal for the full-duplex SPI bus. \$\endgroup\$
    – JimmyB
    Commented Feb 17, 2017 at 13:51
1
\$\begingroup\$

It means that you should check DMA transfer complete flag, then disable SPI DMA request while(!DMA_GetFlagStatus(DMA1_FLAG_TC3)); SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, DISABLE); I think TXDMAEN: Tx buffer DMA enable When this bit is set, the DMA request is made whenever the TXE flag is set.

\$\endgroup\$
0
\$\begingroup\$

It looks like I've figured it out. I had a circular buffer set and I foolishly assumed that the buffer size would send only the length of the buffer. A little deductive reasoning and I would've realized that I'd need a length to send as well in order for it to behave that way.

Is there a way to trigger it on a timer without using an ISR?

\$\endgroup\$
1
  • 2
    \$\begingroup\$ What does this have to do with the original question? You started out by saying your code worked as expected, but the busy flag was bugging you. I think you need to edit your question to explain what exactly is it that you're trying to do. \$\endgroup\$
    – swineone
    Commented Jun 17, 2014 at 13:51
0
\$\begingroup\$

If your initial code was generated with STM32CubeMX, than you might have issue with wrong init sequence of MX_SPIx_Init() and MX_DMA_Init().

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.