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.
I'm trying to operate SPI in the slave mode, and I can't seem to get reliable output from the MSP430 to the master. The master device (an FPGA) sends indices 0x00-0x26, and then 0xFF to indicate the end of transfer. There is a pause equal to the transfer time of one byte between each index. The SPI clock is very slow, ~40KHz.
I wasn't getting reliable data from the MSP430, so I started removing things from the program, thinking that I had a pointer arithmetic error somewhere that was stomping on TXBUF and/or RXBUF. However, now I've got almost nothing in the program except disable the watchdog, set the clock, initialize my GPIO, initialize the SPI, and transmit a fixed byte, and I can't get reliable operation. The byte I'm transmitting (0xA5) looks like it gets shifted. I'm monitoring on an oscilloscope and at first I do indeed get 0xA5, but eventually I start getting 0x4B, 0x2D, 0x5A, 0xB4, 0x96, 0x69, etc.
When I pause in the debugger, I still see 0xA5 in UCA0TXBUF, despite the oscilloscope showing that's not what's transmitted. UCA0RXBUF is also corrupted.
I'm aware of the USCI40 error, and I'm not using UCCKPH. I've also tried the solution there to no avail. Any ideas? Is there an integrity test to run on the MSP430 to make sure the hardware is working properly?
Spi init:
UCACTL1 |= UCSWRST; UCACTL0 = UCCKPL + UCMSB + UCMODE_2 + UCSYNC; // P3SEL for my I/O goes here UCACTL1 &= ~UCSWRST; IE2 = UCA0RXIE + UCA0TXIE; // I have tried just UCA0RXIE, and no interrupts as well UCA0TXBUF = 0xA5;
Rx ISR
if (IFG2 & UCA0TXIFG) { cSpiTxIfg++; UCA0TXBUF = 0xA5; // Also tried UCA0TXBUF = UCA0TXBUF, UCA0TXBUF = UCA0RXBUF }
:
if (IFG2 & UCA0RXIFG) { cS
if (IFG2 & UCA0TXIFG) { cSpiTxIfg++; UCA0TXBUF = 0xA5; // Also tried UCA0TXBUF = UCA0TXBUF, UCA0TXBUF = UCA0RXBUF }
The last bit of code (Tx ISR) was supposed to read...
src.zipI'm not sure how useful this attached code will be, it's not the paired down version I've been using. It's a semi-recent version, but it should give you an idea how the functions are split up. Obviously this doesn't have anything disabled. I've disabled pretty much everything in main.c except the SPI and changed both spi.c and i2c.c as detailed in my previous posts (and in various other configurations trying to get something to work). I might also be missing some of the other counters I pasted in the previous code. Let me know if you have questions.
The scope samples the entire SPI transaction with sck, csn, mosi, and miso on the fast analog separate inputs using the SPI bus function, which is set to sample on sck rising edge with csn low. Thresholds are about ~1.5V.
Can you post an image showing an oscilloscope capture of the problem?
Regarding your question about internal testing, you can either connect the MOSI and MISO pins together externally, or set the UCLISTEN bit to enable internal loopback.
Also, I suggest trying UCMODE_0, just to eliminate the possibility that STE timing is somehow causing problems with the transmission.
0871.src.zipI have attached what should be the latest modifications I am running.
I will try and get some time with the unit today to capture the SPI traffic on the scope as well.
The zip file contains several oscilloscope shots (sorry for the quality). 1/yellow is sck, 2/blue is csn, 3/red is mosi (fpga to uC), 4/green is miso (uC to fpga). In these tests I set the TXBUF = 0xA5 in the init routine, and used the tx IRQ to set TXBUF = 0xA5 again. You can see in some of the transfers that the uC will simply change the transmitted byte. If I pause the debugger after the transmit data is no longer valid, TXBUF still shows 0xA5, and RXBUF is corrupted (should be 0-26 or so, or FF, and is not).
Ok, there's something odd going on with the chip select signal there. Your FPGA is outputting while CSN is not active (repeating the same byte as when CSN is active). The MSP430 output doesn't appear to be synchronised to the edges of CSN either (there are some runt pulses at the CSN transitions).
What happens if you keep CSN active all the way through the transfer? Perhaps try that with the MSP430 set to 3-wire mode too.
EDIT: Yes, I think this problem is due to UCMODE_2. The USCI STE functionality doesn't synchronise to a byte boundary or reset the shift registers on an STE edge. Jens-Michael Gross has noted this issue a few times previously, for example: https://e2e.ti.com/support/microcontrollers/msp430/f/166/p/251036/880824#880824.
EDIT2: In fact, I'm not convinced the MSP430 is handling the chip select signal at all, it should be switching MISO to high impedance when CSN is high, but it continues to output (as does the FPGA.)
Jonathan Miller said:The article you link shows PxSEL pins as the culprit. My two MSP430s are talking at the appropriate time, but they're not outputting the appropriate data.
I wasn't referencing the original post in that thread so much as JMG's replies. He points out that the STE signal does nothing to force the USCI to realign itself to the start of a byte. In other words: if the USCI happens to output two bits before being silenced by STE, when STE goes active again it will resume with the following six bits of that byte and the first two bits of the next. From that point on the USCI output will be shifted by two bits, unless the program resets it.
Jonathan Miller said:The FPGA talks to two MSP430 devices on the SPI bus. The FPGA ping-pongs between the two devices to give enough time to load initially. While CSN is high the FPGA is talking to the other MSP430 on the bus (which has the same issue).
Aha, now I understand those scope captures! Simplifying the test setup to just use one MSP430 and the FPGA will definitely help clarify what's going wrong.
I think you're already doing the right thing with the timing of CSN relative to the clock. CSN drops before a falling edge of the clock, so the clock edge triggers the output of the first bit. CSN goes high again after the rising clock edge which triggers sampling of the eighth bit, preventing the USCI from starting to transmit the first bit of the next byte.
It might also help to get captures of the bus state during setup, as it's possible that USCI is being pushed out of step at that point. Transitions on the clock or CSN lines between the USCI being taken out of reset and the start of transmission could knock it out of sync.
Robert,
What interests me is at one point the output is B4, B5, 69.
Lined up:
10110100
10110101 <-- Only a single bit has changed or shifted. Which destroys the A5 pattern.
01101001
I'd be curious to hear your thoughts.
Cameron LaFollette said:What interests me is at one point the output is B4, B5, 69.
Yes, that part has me perplexed too. Hopefully it'll become clearer with some scope captures where CSN stays active throughout.
Robert Cowsill said:I wasn't referencing the original post in that thread so much as JMG's replies. He points out that the STE signal does nothing to force the USCI to realign itself to the start of a byte. In other words: if the USCI happens to output two bits before being silenced by STE, when STE goes active again it will resume with the following six bits of that byte and the first two bits of the next. From that point on the USCI output will be shifted by two bits, unless the program resets it.
Okay. In one of the myriad program iterations I ran Spi_hwInit() (Spi.c), which should reset the SPI state, if I understand correctly. Should doing that at the end of each Rx transfer along with UCATXBUF=UCATXBUF in the Tx ISR be sufficient to cover all errata/reset the SPI for each transfer? Or should I run Spi_hwInit() in the Tx ISR as well?
Robert Cowsill said:Aha, now I understand those scope captures! Simplifying the test setup to just use one MSP430 and the FPGA will definitely help clarify what's going wrong.
Yes, sorry, I should have explained the transfers more completely. That's pretty much everything. The transfers occur every 100ms.
Robert Cowsill said:Cameron LaFolletteWhat interests me is at one point the output is B4, B5, 69.Yes, that part has me perplexed too. Hopefully it'll become clearer with some scope captures where CSN stays active throughout.
The bit progression Cameron posted above looks like either a combinatorial glitch or a timing issue to me.
I still have issues even with CSN low for the entire transfer. However, the data appears more stable. Note that it is not correct, but I couldn't capture any successive bit changes within a SPI transfer as I was able to do before.
Again, if I pause the debugger and look at TXBUF it shows 0xA5 despite something different on the scope, and RXBUF is corrupted (does not contain 00-26, FF).20150721.zip
Robert Cowsill said:It might also help to get captures of the bus state during setup, as it's possible that USCI is being pushed out of step at that point. Transitions on the clock or CSN lines between the USCI being taken out of reset and the start of transmission could knock it out of sync.
Jonathan Miller said:Should doing that at the end of each Rx transfer along with UCATXBUF=UCATXBUF in the Tx ISR be sufficient to cover all errata/reset the SPI for each transfer?
That causes absolute chaos, which is interesting. Maybe another possible combinatorial glitch? I don't see why running Spi_hwInit() and then setting UCATXBUF = 0xA5 should result in garbage on MSP430 transmitted bytes. Again, UCATXBUF register shows 0xA5, RXBUF corrupted.
Adding an if ( UCARXBUF == 0xFF ) { Spi_hwInit(); } resulted in the more stable (but still wrong behavior) of the single CSN low transfer for 00-26, FF.
Jonathan Miller said:I cannot change to 3-wire mode as there are unidirectional buffers involved.
Hi Jonathan, would you give some more detail on this point? I'm not clear on why the MSP430 can't be set to use UCMODE_0, now that there's only one MSP involved and the CSN line is always active (for testing purposes at least).
Robert Cowsill said:Jonathan MillerI cannot change to 3-wire mode as there are unidirectional buffers involved.Hi Jonathan, would you give some more detail on this point? I'm not clear on why the MSP430 can't be set to use UCMODE_0, now that there's only one MSP involved and the CSN line is always active (for testing purposes at least).
Wow, I assumed three-pin mode changed either SOMI/SIMO to SIO as a bi-directional line per the SPI specification, hence my comment. It didn't occur to me that TI would ignore the SPI specification and make up their own clocked data interface and still call it three-wire SPI.
At any rate, data from a single uC doesn't do me any good. I can change the transfer characteristics (I could interleave transfers at 50ms rather than doing them back-to-back at 100ms), but ultimately I need the data from both uCs. I also no longer have easy access to the hardware assets. I can probably get them back, but I'm reticent to do so for what essentially amounts to reverse-engineering the uC's emulated SPI mode by trial and error.
The only useful experiment I can think of at this point is to set a flag in the Rx ISR when I receive the last byte of the transfer (0xFF) and reset the SPI mode. But since when I tried a superset of this experiment by resetting the SPI after every received byte with disastrous results, I have no reasonable expectation that this will work.
Robert Cowsill said:EDIT: Yes, I think this problem is due to UCMODE_2. The USCI STE functionality doesn't synchronise to a byte boundary or reset the shift registers on an STE edge. Jens-Michael Gross has noted this issue a few times previously, for example: https://e2e.ti.com/support/microcontrollers/msp430/f/166/p/251036/880824#880824.
This morning I went and carefully re-read this note and looked at the SPI diagrams in the data sheet. It's clear that the part emulates SPI. From JMG's post, it sounds as if STE effectively functions as a tri-state enable. I theorized that Tx and Rx shift buffers must still be affected by clocks outside of STE (this would also explain why RxBuf was corrupted), so I started looking for a runt pulse on SCK. The board designer was kind enough to blue-wire after lunch so I could scope SCK. Behold:
This is a differential probe output triggered on the falling edge of SCK. The time scale is 20ns so the whole image is a 200ns span. SCK is a 20us period, so obviously there is a hardware problem. But, when you zoom to a normal level everything looks fine. I don't know if it's a broken driver or receiver, but it's definitely a broken piece of hardware.
**Attention** This is a public forum