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.

Operating several slave devices through single SPI

Other Parts Discussed in Thread: TMS320F28335

Hello,

 

I'm using TMS320F28335 board with DSP/BIOS. I need to control 2 devices through single SPI. It is arranged such that SPISIMOA and SPICLKA outputs are shared between these two devices. I have a GPIO pin for each device that replaces SPISTEA functionality, so I need to control them manually.

I've been able to make the system work by adding time delay between writing data to SPI and switching PINs but that solution is not elegant and needs tuning with the change of baud rate. Additionally it consumes extra time that can be spent efficiently.

I've tried to do the same with interrupts but no success.  I didn't use FIFO buffers in that case, below are the corresponding parts of the code

SpiaRegs.SPICCR.all =0x000F;
SpiaRegs.SPICTL.all =0x000E;
SpiaRegs.SPISTS.all=0x0000;
SpiaRegs.SPIBRR =0x0003;

SpiaRegs.SPIPRI.bit.FREE = 1;

PieCtrlRegs.PIEIER6.bit.INTx1 = 1;  
PieCtrlRegs.PIEIER6.bit.INTx2 = 1;
IER |= 0x0020;


Void spi_send(Uint16 a)
{

    GpioDataRegs.GPACLEAR.bit.GPIO23 = 1; //enable receive for the 1st device
    //---Send data
    SpiaRegs.SPITXBUF = a;
    SpiaRegs.SPICTL.bit.SPIINTENA = 1;
   
    SEM_pendBinary(&SemSpi, SYS_FOREVER);
   
    GpioDataRegs.GPASET.bit.GPIO23 = 1; //disable receive for the 1st device

    GpioDataRegs.GPACLEAR.bit.GPIO19= 1; //enable receive for the 2nd device
    //---Send data
    SpiaRegs.SPITXBUF = a;
    SpiaRegs.SPICTL.bit.SPIINTENA = 1;
   
    SEM_pendBinary(&SemSpi, SYS_FOREVER);
   
    GpioDataRegs.GPASET.bit.GPIO19 = 1; //disable receive for the 2nd device

}

//Serves an interrupt
Void Inter_SPI(Void)
{

    SEM_postBinary(&SemSpi);
    SpiaRegs.SPICTL.bit.SPIINTENA = 0;
    PieCtrlRegs.PIEACK.all |= PIEACK_GROUP6;

}

Are there any suggestions for an elegant solution preferably with FIFO buffers?

Thanks in advance,
Alexander

  • Alexander,

    Are you sure your not working on the same application as I am, perhaps in the hours when I am at home?  Your post was a dead ringer for the situation I am facing currently.

    I too am tryign to control multiple devices by way of SPI and have had to put spin - delay loops in the system to make it work and do not want to do this.  I attempted to use the SPI FIFO,s but have run into different trouble.  The XMIT FIFO is supposed to be a 16 deep buffer to that you can write to, much like an an extra deep transmit buffer.  Simply enabling the FIFO and making repeated writes to the SPITXBUF will place the data in the FIFO.  The SPIFFTX register is supposed to have a FIL level and and status that says how many bytes are currently in the FIFO.  You can then use the FIFO interrupts to send you an interrupt when the FIFO has gone below the fill level.  I am finding, though, that the FIFO doesn't seem to provide the required functionality. 

    At the start of my transmission, I assert the GPIO line (GPIO 19, 22, or 23) depending on the device as a slave select.  I then transmit the message and attempt to use the FIFO interrupt, with the fill level set to 0 (for interrupt when it goes empty).  When I receive the interrupt, I de-assert the GPIO line.  Watching the logic analyzer is showing that the GPIO line gets asserted and de-asserted even before the first byte has been transmitted out of the SPI port (HUH?).  Further debugging shows that if I sit in a while loop that looks at the FIFO status that is non zero for almost all of the transmission time.  Clearly there is something amis here, but I have not found out what.

    The solution I am contemplating is using a periodic interrupt to talk to the device at 2x the rate at which I want to poll the SPI devices.  I am thinking of running a two state, state machine that alternates between transmits and recieves on successive interrupts.  Using the timer interrupt in this fashon will avoid the need to use delay loops.

    Were you ever able to get a working solution?  If you found a better means to make this work, would you be willing to share?

     

  • Hello,

    From my experience of using FIFO it shows the current level of messages in it. Moreover the trick as I understood is that when you are inserting 3 messages in a row for example, the DSP shows that there are 2 in FIFO as one is already in the process of transmitting. So in my case with 2 devices it causes some troubles.

    I have tried to disable FIFO and simply wait in infinite loop for the SPITXINT flag set to 1 but the signal is spoiled for the second device. I didn't bother to understand why.

    Of course I will put more effort in solving these problem and post solution here if I'll have one.

  • Noway2, Regarding de-asserting problem when using FIFO - do you clear interrupt flag after you fill the FIFO buffer?

  • Sorry for the delay in the reponse, I got pulled off this issue for a while.

    The interrupt gets cleared at the bottom of the ISR, along with the PIEACK.

    Instead of working with the TX fifo, I decided to try using the Rx fifo and have run into another oddity.

    Here is the scenario.  I transmit 5 bytes via SPI. I then set the RXFIFO fill value to 5 and I correctly receive the RX FiFo interrupt.  If I set the fil level to the number transmitted +1 I do NOT get the interrupt.  This confirms that I am getting interrupt upon the receipt (and transmission) of the correct number of characters.  The interrupt is as follows:

    ___________________________________________________________________

     SEM_post(&SEM_spiRx); //release the semaphore for the next iteration

     SpiaRegs.SPIFFRX.bit.RXFFIENA = 0;
     SpiaRegs.SPIFFRX.bit.RXFFOVFCLR=1;  // Clear Overflow flag
     SpiaRegs.SPIFFRX.bit.RXFFINTCLR=1;  // Clear Interrupt flag
     PieCtrlRegs.PIEACK.all|=0x20;       // Issue PIE ack
    ___________________________________________________________________

    The main line code was pending on the semaphore and when this returns from the interrupt, I call a function that flushes the RX Fifo, since it was a transmit with a dummy recieve.  The code is as follows:

     Uint16 dummyCnt = 0;
     while(SpiaRegs.SPIFFRX.bit.RXFFST == 0)
      {
      dummyCnt++;
     }

     for (int ii = 0; ii < length; ii++)
      {
      Uint16 dummyRx = SpiaRegs.SPIRXBUF; //Read a byte out of the Rx fifo
      }
    ___________________________________________________________________

    If I example dummyCnt at the end of this routine, I typically see a value of about 311.  This means that AFTER the RX FIFO interrupt triggered, indicating that the fill value was met, tbut hat the stat register STILL indicated that it was at ZERO!

    What is going on here?