How to reset a SPI port in the XS1 using /CS signal ?

If you have a simple question and just want an answer.
User avatar
BEBDigitalAudio
Experienced Member
Posts: 82
Joined: Thu Nov 11, 2010 7:45 pm

How to reset a SPI port in the XS1 using /CS signal ?

Post by BEBDigitalAudio »

Hello to all XCore members

I am facing a serious problem with the SPI 1.4.0 slave component from XMOS. It does not seem to take properly into account the /SPICS signal when the main thread is started.

The main loop starts with the following sequence :

    // Wait until CS is asserted
    nSPICS when pinseq(0):>void;
    // Wait until SPICLK is in idle state
    SPICLK when pinseq(1):>void;

The port deserializes data using a 32 bits buffered port in the while() loop, but it never checks again the SPICS signal. But SPI requires that communication shall be reset (incoming data is discarded and the bit counter must be restarted to 0) when /SPICS goes high again.

If I set the /SPICS signal high, the XS1 port just stops taking the clock into account and stops deserializing. So, if I reset the SPI Master (the XS1 is a slave in my application) without resetting the XS1 while it was receiving data, the data are shifted (for example, if I reset the master while the XS1 had received 5 bits, I will get the next data in the XS1 after 27 clocks the next time, not 32, because the bit counter in the port keeps the last value, while it shall be reset when /SPICS is set to 1)

Is there a way to force the deserializer in a port to be reset to 0 when the /SPICS signal goes high (data from deserializer is the incomplete of course, but at least the deserializer is reset properly) ?

I have taken a look to the XS1 Library documentation, but I can't find anything to reset a buffered port

Thanks by advance for your help

Benoit



User avatar
infiniteimprobability
XCore Legend
Posts: 1126
Joined: Thu May 27, 2010 10:08 am

Post by infiniteimprobability »

You can discard any data in the buffer using clearbuf(void port p);

That will reset the serialiser and you will be in synch again!

It's prototyped in xs1.h - worth having a scan through this file. All sorts of useful intrinsics in there for advanced usage!

/**
 * Clears the buffer used by a port. Any data sampled by the port which has not
 * been input by the processor is discarded. Any data output by the processor which
 * has not been driven by the port is discarded. If the port is in the process
 * of serialising output, it is interrupted immediately.
 * If a pending output would have caused a change in direction of the port then
 * that change of direction does not take place. If the port is driving a value
 * on its pins when clearbuf() is called then it continues to drive
 * the value until an output statement changes the value driven.
 * \param p The port whose buffer is to be cleared.
 */
void clearbuf(void port p);
User avatar
BEBDigitalAudio
Experienced Member
Posts: 82
Joined: Thu Nov 11, 2010 7:45 pm

Post by BEBDigitalAudio »

The clearbuf() function does not work at all as expected...

Here is the code section I have added to reset the shift registers when CS line goes high :

        // Scan nSPICS while we wait until the data being received
        // If the nSPICS line is released, we clear the buffers
        nSPICS:>CSState;
        if (CSState==1)
        {
            clearbuf (SPI_SDI);
            clearbuf (SPI_SDO);

            // Immediately reload the output buffer with dummy data
            SPI_SDO<:0xFFFFFFFF;

            // Wait until CS line goes down again
            nSPICS when pinseq(0):>void;

            // Prepare next word to transmit (the shift register contains the dummy word for now)
            // Load only new output data if no valid data is already in the variable
            // A call to getNextMIDIByteToTransmit() has been done just before the check of CS line
            // so the variable may already contain something valid
            if (OutputData==0xFFFFFFFF)
                OutputData=bitrev(getNextMIDIByteToTransmit(0));
        }
 

When CS line goes high, I clear the buffers and wait until CS line goes down again. But what I see when this section is enabled is that the shift registers are being reset at any moment, and all serial data going in and out are garbled. The rest of my code is the SPI component provided by XMOS (version 1.4), and this works as long as I do not check the CS line (if I comment the section given herebefore). But I need to check the CS line, otherwise  the SPI component does not comply to SPI specification (officially, a rising edge on CS shall reset the buffers which is not handled by XMOS source code)

If you have any idea... I am getting crazy with this problem.

Thanks by advance

Benoit