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.

MSP430F2272 - SPI: no reset of UCB0TXIFG after writing data to UCB0TXBUF

Other Parts Discussed in Thread: MSP430F2272

Hello,

I'm using a MSP430F2272 and work with IAR Workbench. I have a problem in SPI mode of UCB0.

Here is a short description what I try to do:

- Write 0xFF to UCB0TXBUF ('by hand')
- Enable the interrupt for UCB0
- Handle the next four bytes of SPI communication in the interrupt service routine

After enabling the interrupt, the ISR immediately overwrites the 0xFF which is still in the UCB0TXBUF, because the UCB0TXIFG was not reset.

Why is the UCB0TXIFG not reset when I write data to UCB0TXBUF 'by hand'? What do I do wrong?

Thanks for your help!

  • Marcel Bamert said:

    After enabling the interrupt, the ISR immediately overwrites the 0xFF which is still in the UCB0TXBUF, because the UCB0TXIFG was not reset.
    Why is the UCB0TXIFG not reset when I write data to UCB0TXBUF 'by hand'? What do I do wrong?

    Nothing. You only misinterpret what you see.

    When you clear SWRST and write something to TXBUF, it will immediately transferred into the output shift register and TXBUF is immediately ready for the next data byte. So when no transfer is currently ongoing, but the USCI is ready to send something, then you can write twice to TXBUF before TXIFG is cleared.
    This way you don't have to wait for one byte being sent before you can stuff the next one into the output buffer. It greatly increases the throughput, but you need to know how to handle it.

    P.s.: The USI module does it differently. There the output register IS the output shift register. So you won't get anywhere near the USCI throughput with an USI, asn an USI interrupt happens after the last transfer is complete.

  • That's also the reason why you want to wait on the UCBUSY flag in the UCxSTAT register to make sure that the transmit is actually over in case of the USCI (for setting the chip select line for example)

  • Thanks for your answer!

    In the attached picture you can see what I try to do. At number 1 I write 0xFF to TXBUF by hand and enable the TX interrupt. At number 2 the interrupt writes 0x21 to TXBUF and problably overwrites 0xFF. At number 3 the next interrupt is handled.

    I can't see the 0xFF on the oscilloscope.

  • Marcel Bamert said:
    I can't see the 0xFF on the oscilloscope.

    Nor can I, but what I see are things that do not really fit.

    You should post your code. (but today is my last day in the office, so while it may be I'm looking in from home, don't expect me to answer this year)

  • Thanks for your answer!

    Here is a description of the basic function:
    A main board is communicating with 6 slave boards over SPI. It does use an addressing byte instead of chip select lines. All slaves are on the same bus. After receiving 6 bytes the affected slave (right address) acklowedges the request by puting 0xFF into TXBUF while the master is clocking out 2 times 0x81 (see picture). (Sometimes I can see the 0xFF by the second 0x81). For that reason it turns on its SOMI pin.
    At the same time the 'gFlagRxSPI' is set and a answer is generated in the main loop. If the answer is generated correctly the interrupt for TX is enabled. And then the ISR is handling the next 4 bytes.

    The problem now is that the ISR 'overwrites' the 0xFF in the TXBUF with the first answer byte (0x21).

  • Marcel Bamert said:
    It does use an addressing byte instead of chip select lines.

    That's a rather weird abuse of SPI. The CS line is there to enable/disable slave output as well as defining the transfer boundary (since SPI does not have start/stopbits). In your setup, if the slaves erroneously detect a superflupus clock edge/glitch (e.g. during port setup) they will be out of sync forever and misinterpret whatever you will send.

    Also, the response of 0xff is weird too. Per default, an unconnected SPI line is high and the master will read 0xff is there is no slave answering.

    Anothe rproblem is timing. If the slave is silent until it receives its address byte, but then has to answer immediately, it might not have enough time to recognitze that it has been addressed, switch on the output and feed the output register before the master has already sent the next clock edge (and the USCI has started sending an unspecified byte).

    Most setups where more than one slave is connected with only one CS line use a daisy-chain mechanism, wher the last byte received from teh previous one (or master) is shifted out to the next one in sync, so they all appear as one large 16, 32bit or such sized SPI register. The maste rwill then send data for all slaves in the chain (last slave first) and receive datatfrom all (first slave first). The slaves accept the received data (or start listening/sending), based on one single CS line. (still mroe than one chain can be on the same bus using more than one CS line)

    However, what you want to do could be done with a slightly changed protocol:

    Master sends 6 byte of command (with address), then keeps sending a dummy byte (0xff, usually). The slave has 0xff in its TXBUF by default. When having received the command, performed any action and activated the output pin, it writes an 'ack' byte (!=0xff) to TXbuf, followed by any data bytes, then 0xff again and disables the output.

    The master will continue writing dummy byte suntil it receives the ack byte, knowing that data starts with the following byte, no matter how long the slave needed to prepare the data.

    This approach is similar to the one used for MMC/SD cards in serial (SPI) mode, when neither master nor card controller can know exactly after how many clock pulses (of variable clock speed) the data of a read process or the status of a write process will be available.

    But back to the original problem: well, your code mixes up busy-waiting approach with interrupt-based approach (and omits the 'waiting' part of busy-waiting)

    The meaning of the TX ISR is that it is called when TXBUF is empty. Then you write to TXBUF onnce 8and only once) and exit the ISR.

    However, you write to TXBUF more than once in the ISR without checking whether it is empty again, you write to TXBUF from inside the RX ISR too (in fillSPIArray), again without checking whether it is empty.

    And finally, you toggle your debug pin on several places, making its meaning on the scope ambiguous.

    Actually I don't fully understand your code (admittedly, I don't have the time for a full analysis of what happens when, also the part of what is in gDataSPIBusTx is missing) .

    I guess you made your approach overly complex and now it shoots itself into the foot.

**Attention** This is a public forum