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.

MSP430 SPI RX ISR

I am having issues with the SPI port. I will try to explain what I am trying to do.

I have two MSP430 experimenter boards. They are connected to each other's UCB0 SPI port (see hardware block diagram). I have written code to perform the following. When the Slave detects a button has been pressed (interrupt driven) it generates an SPI packet (spi_packet.h) and then pulls the Chip Select line high. The Master detects the Chip Select high line (interrupt driven) and starts to read the SPI packet from the slave. After receiving the entire SPI packet, it decodes it and turns an LED on or off depending on the parameter sent in the packet.

Now I will try to explain my problem.

The Slave devices uses a circular buffer to store the SPI packets it is going to send to the Master. So ever time a button is pressed a SPI packet is pushed into the circular buffer. Currently each SPI packet is 5 bytes long. Each SPI packet has a 2 byte header (0xDEAD). The Master performs a while((rx_byte = spi_read()) != 0xDE); on the first byte. For some reason the Slave device is receiving an SPI receive interrupt right after I press "go" in the debugger. This screws everything up as I have not received an interrupt from the Master. I clear the SPI receive interrupt flag (IE2  |= (UCB0RXIE);) during SPI initialization (spi_init()).

Any thoughts on why this may be occurring?

Thanks in advance for your assistance.

  • ducati said:


    The Slave devices uses a circular buffer to store the SPI packets it is going to send to the Master. So ever time a button is pressed a SPI packet is pushed into the circular buffer. Currently each SPI packet is 5 bytes long. Each SPI packet has a 2 byte header (0xDEAD). The Master performs a while((rx_byte = spi_read()) != 0xDE); on the first byte. For some reason the Slave device is receiving an SPI receive interrupt right after I press "go" in the debugger. This screws everything up as I have not received an interrupt from the Master. I clear the SPI receive interrupt flag (IE2  |= (UCB0RXIE);) during SPI initialization (spi_init()).

     

    Are you using the 4xx or 5xx experimenter board?

    Also are you using USCI channel A for anything? Please note that both channels A&B share the same RX interrupt vector.

    Do you start the slave before the master or is the master already running?

    You should take a Master & Slave SPI example from www.ti.com/msp430codeexamples and run them as-is to verify this issue does not occur. This will establish a baseline understanding of what does work. Then you can incrementally add in portions of your code until the issue arises.

  • You do not write which MSP you use. Different MSPs have different hardware modules for SPI. The older ones have UART modules which support either UART, SPI or - partly - I2C, the newer ones implement an USCI module which all support UART or SPI and I2C or SPI. On these USCI modules, RX and TX for each submodule share the same ISR vector while in the olders, RX and TX did have separate vectors.

    But maybe the problem is something completely different. SPI is a bidirectional synchronous master/slave communication. That means, the slave can only send data to the master if the master sends a clock signal. And since there is only one clock signal and no protocol to determine direction of the transfer, but separate lines for both directions, it also means that ecery time you send a byte, you're receiving a byte. And every time you want to receive a byte, you'll need to send a byte. This is one way of a synchronous connection. I2C does it differently, it has only one line for sending and receiving and has no chip select too. There the slave is adressed and the direction is determined by the data sent by the master at the start of a transfer.

    So with SPI, if your master does rx_byte = spi_read()) != 0xDE this means that the master will send a dummy byte (usually FF) in order to receive a byte. And of course your slave will receive this dummy byte and generate an RX interrupt.

    So your communication must be based on tokens for both directions, not only the DE byte for detection of a byte header.

    Also, it is quite unusual to have a dedicated slave busy flag. Normally, the SPI will always respond but if the slave is busy or has nothing to send, the master will receive an FF byte. The normal way to do things with SPI (opf course you can always do your own thing) is to pull down CS by the master (!) to signal the slave that you will start communication with it (there can be several slaves attached to the same SOMI and SIMO and CLK lines, each with its won CS line).

    Pulling down CS will synchronize master and slave and defined the nect clock pulse as start of a byte. it will also enable the slaves SOMI output driver (all other slaves on the same lSOMI lines have CS high and their outputs disabled) and activate the slaves shift register logic for input an doutput.

    Now the master start sending dummy bytes and will receive a (dummy) FF, if the slave is busy or not responding, or a status byte (non-FF unless FF means busy too). Once the slave signals that it is no longer busy, the master can send a 'real' byte (non-FF) with the command. If no commands are needed at all, the master will continue sending dummy bytes and receive either dummy responses or valid data, e.g. your packets. This is more or less the way this is handled e.g. in teh MMC or SD  card SPI protocol. Less complex devices such as D/A converters might just take one or more bytes between CS low and CS high and latch them into their function register, giving no data on SOMI at all.

    Once again: CS goes from the master to the slave and needs to be controlled manually by your program on the master. It is NOT automatically set/reset by the SPI hardware, as you can address any number of slaves just by pulling different CS signals low. You can use ANY normal I/O for this. The dedeicated CS line is only used when the SPI is in slave mode. Even more, if you activate the CS line with PxSEL and it goes low, one some MSPs this will switch the SPI hardware into slave mode even if you want it to be the master. Check the users guide section of your processor type. If you select 3-wire SPI slave mode (if available on your processor), then the slave won't use CS at all and will always send and receive data when CLK is being clocked. But this bears a risk of losing sync as the CS transition won't synchronize start of a byte anymore.

    To summarize: 1) CS is controlled manually by the master and goes form master to slave (you painted it the other way in your diagram). 2) BF is superfluous. You can, however, attach it to an IRQ capable port ont he master and issue an interrupt if the slave wants to tell it has data. 3) each time the master wants to receive a byte, it also sends a byte. And the slave will issue an RX interrupt after one byte has been transfered. The TX interrupt is issued when the byte in the TX register is moved to the TX output shift hardware in the moment the SPI hardware begins sending and at the same tiem receiving a byte.

     

  • Ducati,

    A quick suggestion:  It is possible that if both devices are powered at the same time, the slave sees some transitions in the data/ clock lines when the master USCI is being configured and assumes that it is a part of the expected transaction.

    If you check out some of the code examples on the TI page, you will see that the slave is either reset or re-initialized after the master device is setup.

    One way to do this would be to look for the CS line or some GPIO (connecting the master and slave) to indicate that the master is ready and reset the USCI module before starting a transaction.

    Alternatively you can also wait for the master clock to become active and reset the USCI before the first bit is received (make sure that the slave CPU is fast enough to complete the reset and receive the first bit). This should clear any pending IFGs.

    Regards,

    Priya

**Attention** This is a public forum