This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSPM0G1505: Minimum reset of SPI peripheral

Part Number: MSPM0G1505

As discussed in the related question, it's not possible to clear the TX FIFO when the SPI is set as a peripheral.  I'd like to be able to allow a controller to communicate with my peripheral whenever it likes via SPI.  I'd like to use the SPI IDLE interrupt that is triggered on a rising edge of Chip Select to point a DMA channel to the next set of data to be transmitted.  However, because I can't know how much data the controller has read from my peripheral, I can't know if there's anything left in the FIFO.  I have been told that I need to reset the SPI peripheral after each transaction in order to flush the FIFO ready for the next transaction.

What is the minimum amount of "reset" I need to perform to empty the TX FIFO so that I can get it to a clean state?  Can I just toggle the ENABLE bit in CTL1?  Do I need to set RESETASSERT in RSTCTL?  I'd like to avoid as much reconfiguration as possible - both from the point of view of keeping potential SPI downtime to a minimum, and to avoid any possibility of IO glitching, etc.

  • And off the back of further testing, I realise that the IDLE interrupt might not be linked to the Chip Select.  What's the right way to even tell when a controller has ended a transaction?

  • Hi Alan,

    Toggling the enable bit in SPI CTL1 register wont result in the TX FIFO clearing. So far, it looks like you need to reset the SPI peripheral to flush the buffer. You can do this using the DL_SPI_reset() function. I implemented it by using the reset function, then re-enabling power and reconfiguring the peripheral. Then the FIFO is cleared and the peripheral is available and functioning again.

    As for the IDLE signal, it should be related to the chip select. The SPI IDLE interrupt indicates that the SPI peripheral has finished transfers and is changed to IDLE mode. The SPI chip select should also become false when the transfers are complete. According to our TRM, the IDLE interrupt is tied to the STAT.BUSY register, which become true when the SPI is actively transmitting or receiving data, or when the TX FIFO is not empty. So when the MSPM0 is functioning as the peripheral, and the SPI transmissions are complete, the IDLE interrupt should occur effectively to indicate the end of transmission.

  • Dylan

    Thanks for the feedback - I'll try implementing the reset as you've described.

    I was confused by the description stating that the peripheral would remain BUSY while the "transmit FIFO is not empty".  Since my problem is that I need to keep putting data into the TX FIFO in case the controller keeps requesting it, does that mean that the peripheral will stay BUSY even after the chip select line is released by the controller due to that data?

    Alan

  • I see what you mean. I think that is just some unclear wording in the TRM, I'll make a note for this. You can see more detailed descriptions of when the device enters idle mode in sections 17.2.3.1 and 17.2.3.2 of the TRM as well, and the BUSY bit is just intended to detect when the bus is idle. So generally speaking, when the controller stops driving data on the bus (by reading or writing), the bus will enter idle mode, the BUSY bit will return to 0, and the IDLE interrupt will occur.

  • Dylan

    I've configured a DMA channel to keep writing changing data into the TX FIFO, and enabled the IDLE interrupt.  When I configure an external SPI controller to read words across multiple transactions I can see the changing data that is being fed by the DMA.  However, I do not get the IDLE interrupt being raised.  (I do see the IDLE interrupt while configuring the SPI peripheral, so I'm reasonably sure I'm configuring it correctly).  This suggests that the TRM wording might be correct - that having data in the TX FIFO is enough to stop the IDLE interrupt triggering and therefore stop me detecting the end of a transaction.  I'd be happy to be proved wrong, though!

    I've also had a try at configuring a GPIO interrupt on the rising edge of the chip select (while it's being "used" by the SPI peripheral) but again I don't see the interrupt being triggered.  Is it possible to mix-n-match GPIO/peripheral functionality like that?

  • Hi Alan,

    I went back to test this myself after seeing your comment and it looks like you're right, the TRM is not mis-worded and the idle interrupt wont fire as long as the TX FIFO is full. I tried an implementation pretty similar to yours and never saw the idle interrupt fire, then added a time delay to reload the FIFO and started to see the idle interrupt fire. So you are correct that you'll need to utilize another method for detecting the end of activity from your SPI controller.

    Trying to think of other methods to detect the end of transmission, another option could be to utilize a timer in combination with the RX interrupt. Using that, you could just wait a set amount of time for the next read/RX interrupt, and if none occurs you reset the peripheral to clear the buffer. There may be an easier way to do this that I am not thinking of though. I will update the thread if I think of a better solution.

    Edit: Realized I didn't answer your secondary question. It is possible to manually operate and monitor the chip select signal. You could put the device into 3 wire mode and use a GPIO to monitor chip select, and then you can use that to determine the remaining TX and RX behavior from the controller. So in that way it is possible to mix and match. I don't think it is possible if your goal is to leave it in 4-wire mode, and then also use the CS pin as a GPIO at the same time. I don't see why that would be necessary though. 3-wire mode should work for what you've described.

  • Dylan

    Thanks for confirming my results.  I think that I will go down the route you've suggested of using a timer after the RX interrupt - there is a built in RX timeout that looked like it should be able to do the job, except its time range is too limiting for my needs so I'll implement it with a separate timer.

    I'd hoped to be able to keep the SPI in 4-wire mode and still be able to trigger an interrupt from the CS line.  Using it as you've suggested in 3-wire mode is possible, but is too slow for my needs - initial tests suggest I will not always be able to enable the SPI peripheral after CS-low (to allow it to start driving the POCI line) fast enough.

    I'll mark your earlier response as the right answer to the initial question, although there's been some useful corrections/follow-ups since then.