Inconsistent SPI_Master behavior relative to sleep and debugging | Cypress Semiconductor
Inconsistent SPI_Master behavior relative to sleep and debugging
Please note I am going to scour through the new PSoC3/5 sleep appnote AN77900. But in the mean time, I wanted to go ahead and get this out there. It may or may not (likely not) be solved for me after reading and studying AN77900, which may take a while.
My design is a little more complicated than described here, so I'm only describing what I'm pretty sure are the germane parts.
I have an SPI_Master component (V2.20) placed and configured for 16 bits. I start it at the beginning of my program. I have a software loop that does a WriteTxData(). After the WriteTXData(), I wait for SPI to become idel again before completing the loop iteration. Within the loop, I toggle a debug output pin so that I can tell on my scope each time that the loop iterates. (See Footnote 1 for non-germane detail).
As described above, the ss (Slave Select) pin will go low for each 16-bit SPI output. This is true whether I'm debugging the program from the Creator, or if I power the target off and on and let it run free (with or without the MiniProg3 attached).
However, there's more intended inside my software loop. I am able to include or exlude this additional stuff by using a #define. The additional stuff relates to sleeping. Inside each iteration, before doing any SPI, CyPmSleep surrounded by CyPmSave/RestoreClocks. When I enable this sleeping and then run the program in the debugger, with no breakpoints and simply running free otherwise, everything behaves as expected. However, when I power the target off and on so that it will run free without being in debug mode (whatever that means), the hardware behaves DIFFERENTLY! The ss pin goes low and stays low. The mosi data repeats the 16 bits over and over again, with only a multi-microsecond delay per set. At first I thought this was my loop iterating and that ss was not returning high. However, when I probed the debug output pin that toggles every iteration, I found that it was NOT toggling. This tells me that my code is stuck on waiting for idle, and the SPI hardware is autonomously repeating the 16-bit output over and over again. With the addition of a 1ms CyDelay(1) call at the end of the loop iteration, and after confirming such delay in the debugger, I confirmed my suspicion that the SPI_Master is autonomously repeating the data output. That is, no such delay was appearing between 16-bit sets.
So, with no sleep involved, the SPI_Master sends out one 16 bit set per call to WriteTXData(). With sleep involved, this continues to work in debug mode, but when free-running without debugging I get this indefinite recurring of 16 bit sets that never goes idle in order to progress to the next loop iteration. I added explicit stop and start of the SPI_Master component before and after sleeping, but this didn't help. The fact that I get expected behavior while debugging makes me think this is less that I'm doing something major wrong and more that theres a very subtle difference when debugging. So, I don't expect to find the solution in the AN77900 app note. I might, and I'll read it. But in the mean time, I'm asking for help in advance about this.
And remember, I'm pretty sure I'm successfully waiting for idle after the WriteTXData(). When debugging, a single 16-bit set is output, the SPI_Master component goes idle, and I complete the iteration. When freshly powered up without debugging, the SPI_Master component appears to never go idle, repeating the 16-bit output set over and over again. And if I remove the sleep via #ifdef, the SPI_Master then acts consistently between debug and free running modes.
1. Note that I discovered that the ReadTxStatus() will *sometimes* (one out of four times in my testing) show idle for a moment after the WriteTXData() call. In these cases, my code flowed through prematurely. So what I do now is immediately after the WriteTxData() call, wait for NOT idle using a single-line while statement. Then immediately after that I use another single-line while statement to wait for Idle. I did try removing the first wait to BECOME idle, thinking there might be a timing difference when debugging. But this didn't change things.