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.

SPI, end of transmission detection



I am using an MSP430 of the 5xx family, and currently implementing the SPI interface as master.

I concentrated on burst mode so far. My strategy is to use the TXIFG interrupt flag and associated ISR to fill in the TX buffer as soon as it is free. Setting the /CS signal back up is my problem.

What I tested was to set /CS inactive as soon as the last transmission was done (RXIFG). This does not work, since the interrupt occurs before the last clock signal goes back down (the SPI interface is setup with clock low when inactive, data line valid on the clock's rising edges). It is a requirement that the /CS does not go back to inactive before the last falling edge of the clock (plus a margin).

The example code from TI looks like this:

---

 

void TI_CC_SPIWriteBurstReg(char addr, char *buffer, char count)

{

  unsigned int i;


  TI_CC_CSn_PxOUT &= ~TI_CC_CSn_PIN;        // /CS enable

  while (!(UCB0IFG&UCTXIFG));               // Wait for TXBUF ready

  UCB0TXBUF = addr | TI_CCxxx0_WRITE_BURST; // Send address

  for (i = 0; i < count; i++)

  {

    while (!(UCB0IFG&UCTXIFG));               // Wait for TXBUF ready

    UCB0TXBUF = buffer[i];                  // Send data

  }

  while (UCB0STAT & UCBUSY);                // Wait for TX to complete

  TI_CC_CSn_PxOUT |= TI_CC_CSn_PIN;         // /CS disable

}

---

Polling while writing is nothing I want to do (urk!), and polling UCBUSY at the end feels also bad.

Is there any other way? I would love to have an interrupt on UCBUSY, or any other interrupt telling me that the last clock cycle is finished.

---

EDIT: worse than that: UCBUSY resets before the clock goes back to low, therefore the requirement is not fulfilled (clock low before /CS inactive). Checking the level on the clocks IO pin works, but it is still polling:

while (PxIN & BITx);

I am not even sure if reading the input register for a pin that is configured as output and SPI-clock is a specified behavior.

 

  • If you really don't like polling the SCLK pin via PxIN (which is OK specified behavior), then maybe you could try driving the clock line low yourself just long enough to negate /CS.  Like this:

     

    PxSEL &= ~SCLK_PIN;

    PyOUT |= SLAVE_CS_PIN;

    PxSEL |= SCLK_PIN;

     

    And be sure the PxOUT and PxDIR bits for SCLK_PIN are set correctly (1 and 0, respectively).

    But I'm not sure polling is that bad when it comes to SPI, which is usually pretty fast.  Most MSP430 software designs I've seen use "blocking" I/O for SPI in a single-threaded environment (no O/S).  In that case, the only reason to avoid polling is to put the processor to sleep.  That won't buy you much if you're just waiting for half an SPI bit time.

    Jeff

  • Nice answer, I will try that.

    Since the transmission is managed in ISR, polling at the end of the last character blocks other interrupts (no OS). But point taken, half a SPI period is not that much. I am reluctant to the idea of polling in an ISR, the solution is of course to take it out to the main loop (it would still be polling, but doing other main loop stuff in between).

    I could not find the PxIN behavior while PxSEL and PxDIR are both 1, in the 5xx specification. What worries me is:

    slau208h.pdf, 10.2.1: "Each bit in each PxIN register reflects the value of the input signal at the corresponding I/O pin when the pin is configured as I/O function."

    Do you please have references for your info about this behavior being specified?

  • I couldn't agree more about polling in the ISR.  As you concluded, the polling of PxIN would be done back in the main loop, after the RX ISR decided it had received the final character and flagged and/or woke up the main loop.

    For lower CPU overhead and to support faster SPI throughput, you might consider switching to use DMA.  With ISRs, you have two interrupts per SPI byte time.  With DMA, it would interrupt you only after the final RX byte has arrived.  You'd use two DMA channels.

    My reference for the defined / specified behavior is the pseudo schematics for the port pins in the device-specific data sheet.  The quote from slau208 refers to port pins where the input buffer can be disabled when the pin is not configured as I/O.  On SCLK, the port hardware can't disable the input buffer when the USCI owns the pin because the USCI module needs to use SCLK as an input when in slave mode.  So you are safe to poll that input.

    Jeff

  • When you're master, simply check the USCI busy bit. It is set even after RXIFG and goes low after the final edge (when TXBUF is empty). It will be polling still, bu tmore reliable than polling the clock pin.

    Jedd is right if he says that the port input is still active as it is required as input in slave mode, but depending on the implementation, it might still be that the input logic is disabled when the pin is in out mode (which it is when you're master).

    To avoid polling, you can connect the clock pin to a P1 or P2 pin and configure the port for input edge interrupt. In the last RX ISR call, you activate the interrupt and get notified as soon as the final rising edge occurs. It does, however, not make much sense if your SPI clock is in the magnitude of MCLK. Then busy waiting is definitely better, as it will oply be a few MCLK cycles and probably much faster than entering and exiting LPM once more (for SPICLK >= MCLK/2, even the IST entering overhead would be more than the required delay).

    However, there are some slaves which require CS to be kept low for some time after the final byte, or the transmission will be still considered as canceled. CS and its exact usage and meaning are not specified by the generic SPI standard. Only that no slave may speak or listen when its CS is high.

  • @Jens-Michael: As I pointed out in the edit of my original post, the busy bit does not work like this at least in my code. It is reset 4 us after the last rising edge of the clock, while the high-time of the clock is 18 us.

    For testing, this is what I do at the last RXIFG interrupt:

        while (UCB0STAT & UCBUSY);

        SPI_CSn_PORT |= SPI_CSn_PIN;

    CSn goes high before the last clock goes low.

    "It is set even after RXIFG and goes low after the final edge": it is indeed set even after RXIFG. But this is not my problem, my problem is that it is set too early. RXIFG is set after the last *rising* edge of the clock. I want to detect the last *falling* edge. 


  • Gauthier ��stervall said:
    RXIFG is set after the last *rising* edge of the clock. I want to detect the last *falling* edge. 

    This sounds odd. RXIFG can only come when the last bit has been received. And this can only happen at the AND of a clock cycle.
    The usuyl thing is:

    Master puts output on SIMO.
    master asserts the clock
    slave reads bit from SIMO
    slave puts out bit on SOMI
    master de-asserts the clock and reads bit from SOMI.

    This means that when teh byte has been received, the clock cycle is completed.

    So what you observe seems to be an incompatibility in the clock polarity or clock phase setting. Did you try different combinations of UCCKPL and UCCKPH bits?
    Note that the TI interpretation of one of these bits (SPI mode number) is inverted to the Motorola interpretation.

    Also, the typical setting of the SPI clock is UCCKPL=1, which means the clock is inactive high. This also means that the high-going edge is the end of the clock pulse.

    Gauthier ��stervall said:
    As I pointed out in the edit of my original post, the busy bit does not work like this at least in my code.

    Strange. The meaning of this bit is that the hardware doesn't do anything, including no more clock edges. The internal state machine has returned to idle state.
    It simply doesn't fit.

    I didn't read your edit. Often, I have the brwoser and several topics open for hourse before I finally manage to answer. Often, I forget to update the window befor eanswering, so I miss the changes that happened in between. Else I had pointed to the phase/polarity thing earlier.

  • Jens-Michael Gross said:

    The usuyl thing is:

    Master puts output on SIMO.
    master asserts the clock
    slave reads bit from SIMO
    slave puts out bit on SOMI
    master de-asserts the clock and reads bit from SOMI.

    Both parties (master and slave) latch incoming data on the same clock edge.  The MSP430 (as slave) and most slaves wait for the next clock edge (opposite polarity, often called the output-changing edge) to drive the next bit.  Most masters (including MSP430) and some very fast slaves don't wait for the output-changing edge; instead, they wait a prescribed delay (say 10 ns) and then drive the next bit "automatically".  This optimization helps meet the other end's input data setup time requirement.

    Jens-Michael Gross said:

    This means that when teh byte has been received, the clock cycle is completed.

    Not necessarily.  From the diagram below you can see that when CKPH is 1, there's still half a clock cycle left after the USCI is "done".  It has shifted out all 8 bits and read in all 8 bits.  It's reasonable to me that the USCI would negate UCBUSY after the hold time on the final output bit is done.  I think that's what Gauthier has observed.  It would probably have been better for UCBUSY to wait for that last clock edge, however.

    Jeff

  • Exactly what Jeff says, I couldn't have explained my problem better :)

    Also, the description of the UCCKPL bit is:

    "0   The inactive state is low"

    The clock is high while UCBUSY is low, which means that the clock is by definition active while the SPI interface is not (or not busy). I does not feel very consistent.

    Of course I can accept that it is done that way in the hardware. I am only very surprised that there is no way to tell for sure that the SPI interface - including its clock - is idling.

     

  • Jeff Tenney said:
    From the diagram below you can see that when CKPH is 1, there's still half a clock cycle left after the USCI is "done"

    I know this diagram, and I don't really trust it.
    With CKPH set, it is sampling the RX bit before there was a clock pulse at all. That means that teh slave has to output the first bit with the falling edge of CS/STE. Sounds odd.
    However, it might be still possible.
    Yet the STE line in there makes no sense at all. STE is NOT set by the hardware, it is an input ONLY and it does NOT init or control anything in the tansfer logic. In slave mode, it is just disabling the input and output driver of SOMI and CLK. it does not even synchronize the transfer. So its existence in this diagram ranges from meaningless to misleading.

    Then there is the fact that (in master mode) the maximum SPI clock frequency is USCICLK/1. That means that there are no 'sub-clock cycles' which can be used to control any things like the longer MSB with CKPH=1. There's too much that doesn't really fit so I don't trust this diagram. It's nice for visualizing the basic workings, but in detail it's untrustworthy.

    Anyway, in this thread there was never mentioned which values was programmed for CKPH or CKPL. So the buest guess was to assume they aren't set. Also, the usual combination is to set CKPL and leave CKPH clear (as this is the Motorola default mode 0, and the most used one)

    However, I agree that BUSY should go low after the final edge and not before. At least that's what one woudl expect.

    However, with CKPH set, the transfer is completed at the forelast clock edge. The final edge is jsut a releasing of the clock line (and is rather a preparation of the next transfer).
    The question is, is this mode really needed? Or is perhaps the otehr way, CKPH clear and CKPL set) the correct mode to use? As you can see, the edges and sampling points are identical, just the final edge moves from the end (behind busy=0) to the start of the transfer and the idle state is different.

    However, I don't know what slave is used, so anything may be wrong or right.

    All I can say is that with all teh SPI slaves I had so far, CKPH low and CKPL high was the working setting and there the BUSY bit works as intended.

     

  • I should have specified the values of CKPH and CKPL that I am using:

    CKPH = 1
    CKPL = 0 

    The slave requires low clock while inactive (and specifies minimum time between the negative edge on SCLK to /CS high), and sampling of data on rising edge. It also requires the master to wait for a low level on the MISO pin after /CS got active (in other words this slave does output the first bit on the falling edge of CS).

    It might not be the usual mode, but the specification of the slave is clear about that.

  • Those settings are pretty standard for SPI devices like serial flash and ADCs.  Those settings correspond to Motorola's mode 0.  Many of these mode 0 devices (though not yours) are also compatible with mode 3 (CKPH=0 CKPL=1) because both modes use the rising clock edge as the active edge.

    And yes, in mode 0 the slave starts driving the first bit on /CS.  Same for mode 2 (CKPH=1 CKPL=1).  When MSP430 is slave in these modes, the STE line causes the MSP430 to start driving the first bit too.  The diagram is trying to show that.  It does seem that the diagram is trying to convey too much information, but it works OK with a little extra consideration.

    Jeff

  • Jeff Tenney said:
    the STE line causes the MSP430 to start driving the first bit too.

    Well, not directly. I releases the output driver. The first bit may be forwarded to the input of the output driver already. Unfortunately, STE is no replacement for a real CS input when in slave mode.

    STE is asynchronous to the clock signal and does not cause any action in slave mode. It just disables the clock input and SOMI output.

    Nevertheless, it seems that this is indeed a bug in the USCI state machine that should be checked by the engineers. And perhaps added to the errata sheets.
    On second thought, the description of the UCBUSY bit is correct:

    USCI busy. This bit indicates if a transmit or receive operation is in progress.

    And indeed, UCBUSY clears when both, TX and RX operation are complete. The last byte in TXBUF is sent and the received byte has arrived in RXBUF. No more transmit or receive operation is in progress. Teh description does not tell about the clock cycle.

    So what you get is exactly what was described. It does not, however, match what one would expect. So the documentation could be updated to make this clear(er).

    If busy waiting for the final clock edge wastes too much time (e.g. when SPI clock is REALLY slow = MANY MCLK cycles), one could connect the clock to a port1/2 pin and set up the port pin for falling edge interrupt. In the RX ISR, this interrupt can be enabled, so once the final edge comes, anothe rinterrupt is generated. This will also add some delay (interrupt latency) before CS is de-asserted in the ISR then.

    Jeff Tenney said:
    Many of these mode 0 devices (though not yours)

    How do you know? I haven't seen any mentioning of the actual slave in this thread. So maybe it does?

    Gauthier ��stervall said:
    It also requires the master to wait for a low level on the MISO pin after /CS got active (in other words this slave does output the first bit on the falling edge of CS).

    Not necessarily.
    It basically means: after assertign CS, the master has to wait until the slave acknowledges that it is ready by pulling MISO low. Some devices do this. This does not mean that this low signal is indeed the MSB of the first byte the slave wants to send. (or, perhaps, the first byte is a don't care anyway).
    In fact, this description includes the possibility that between asserting CS and the low signal on MISO any time may pass. This rather looks like a handshake mechanism that is abusing the SPI bus line (saving a separate ready line) and not the start of the transfer.

    If I could take a look at the slave datasheet, things would be much easier.

    Did you ever try CKPH=0; CKPL=0; ? Maybe it works, depending on the hold times and delays.

    Nevertheless, it makes no difference whether you can wait for the busy bit or the CLK port bit, both is busy-waiting.

  • Jens-Michael Gross said:

    Many of these mode 0 devices (though not yours) are also compatible with mode 3 (CKPH=0 CKPL=1)

    How do you know? I haven't seen any mentioning of the actual slave in this thread. So maybe it does?

    [/quote]

    The peripheral in this thread apparently requires the clock to idle low (not high).  In mode 3 (CKPH=0 CKPL=1), the clock idles high.

    Typical SPI peripherals usually support exactly one or two of the four SPI modes.  If a peripheral supports two modes, those modes share one attribute: the clock edge (positive or negative) on which to latch data.  While a peripheral is typically "hard-wired" to latch data on either the positive or negative clock edge, it often does not care whether the clock idles high or low.  Thus many peripherals support Motorola mode 0 and 3, and many peripherals support mode 1 and 2.  Because the peripheral in this thread requires that the clock idle low, it supports only mode 0, not modes 1, 2, or 3.

    Jeff

     

  • Jeff Tenney said:
    The peripheral in this thread apparently requires the clock to idle low (not high).  In mode 3 (CKPH=0 CKPL=1), the clock idles high.

    Oh, yes, you're right. Mode 3 is off then. Or you manually pull it low once the transfer is done :)

    however, based on the hold times, phase could be changed too. The 'latch on edge' does not necessarily mean that the same signal isn't (still/already) available on the other edge. It somewhat depends on implementation but might work. Or it leads to a missing first bit. Both is possible and depends on the two partners.
    With maxium SPI clock == UCLK/1, there are only two moments when a signal can be latched/output. At one of the clock edges. There are no intermediate steps. So both devices might work with this or that phase.

    However, I already stated that it makes no difference whether busy-waiting for UCBUSY or for the clock port bit.

    Let's fix the fact that UCBUSY is reset after all TX and RX is done, but not necessarily after the USCI is completely idle. What is no less and no more than what the documentation tells.

  • USCI busy. This bit indicates if a transmit or receive operation is in progress.

    In progress is a bit ambiguous. You seem to interpret it as some bit is being received / transmitted, while I interpret it as the SPI is not idle. The transmission changes the clock, so for me the transmission is done only when it leaves the clock alone.

    Jens-Michael Gross said:

    Did you ever try CKPH=0; CKPL=0; ? Maybe it works, depending on the hold times and delays.

    I don't want to use a mode that is not specified. One day it works, then the manufacturer changes the behavior that was not specified (therefore still fulfilling the specification) and you're having big problems.

    Jens-Michael Gross said:

    Nevertheless, it makes no difference whether you can wait for the busy bit or the CLK port bit, both is busy-waiting.

    Besides the fact that one happens at the last rising edge, the other at the last falling edge. But both are as you way busy-waiting.

  • Gauthier ��stervall said:
    Besides the fact that one happens at the last rising edge, the other at the last falling edge. But both are as you way busy-waiting.

    If busy would work as you (and I) expected, both would happen mroe or less at the same time, so even less of a difference :)

    Gauthier ��stervall said:
    In progress is a bit ambiguous.

    I wholeheartedly agree.

    Gauthier ��stervall said:
    You seem to interpret it as some bit is being received / transmitted

    Literally, that's what it means. After the last incoming bit is sampled, the last outgoing bit is sent, no transfer operation is under progress anymore. The final clock edge is plain cleanup.

    Gauthier ��stervall said:
    while I interpret it as the SPI is not idle

    That's what one (including me) would expect. However, it's not what the docs meant. In USART mode, it i specifically expressed as 'UART is idle'.
    I agree that a more detailed explanation is necessary here. And a really 'busy/idle' bit would be preferrable.

    Aou can write the docs team a message, explaining this. They will most likely change the docs after checking with the engineers. (I know they will, as some changes are based on my own reports).

**Attention** This is a public forum