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.

Is there a good way to reset the spi fifo?

I have two piccolo DSPs talking to each other over SPI.  One requirement I have is that I need the slave DSP to constantly load the TXFIFO so that when the master does a transaction it is getting the newest possible data.  As far as I can tell you can't get control of the FIFO pointer directly so I've been toggling the SPIFFTX.bit.TXFIFO bit before trying to load it.  For example:

(*spi_reg_).SPIFFTX.bit.TXFIFO = 0;
(*spi_reg_).SPIFFTX.bit.TXFIFO = 1;

(*spi_reg_).SPITXBUF = tx_[0];
(*spi_reg_).SPITXBUF = tx_[1];
(*spi_reg_).SPITXBUF = tx_[2];

But this doesn't seem to work very well.  Is there a "good" way to flush and reset the FIFO? Particularly for a slave device?

  • Kevin,

    The TX FIFO reset bit should do the trick.

    What do you mean that it "does not seem to work very well"? Is the functionality of this bit not working?

    You can verify the functionality by putting a few words into FIFO. Monitor the TX FIFO status bits, and then toggle the TX FIFO reset bit.

    See SPI FIFO Description section of the SPI User Guide item #8.

    Here is some very basic code you can try out.

    spi_fifo_reset_test.c
       // Initialize SPI FIFO registers
       SpiaRegs.SPIFFTX.all=0xE040;		// TXFFIL = 0, clear int flag, enable TXFIFO,enable FIFO enhancements
       SpiaRegs.SPIFFRX.all=0x2044;		// RXFFIL = 4, clear int flag, enable RXFIFO
       SpiaRegs.SPIFFCT.all=0x0;		// no delay
       // Init Spi registers
       SpiaRegs.SPICCR.all =0x000F;	             // Reset on, rising edge, 16-bit char bits
       SpiaRegs.SPICTL.all =0x0002;    		     // Enable SLAVE mode, normal phase,
       // enable talk, and SPI int disabled.
       SpiaRegs.SPIBRR =0x007F;
       SpiaRegs.SPICCR.all =0x009F;		         // Relinquish SPI from Reset
       SpiaRegs.SPIPRI.bit.FREE = 1;                // Set so breakpoints don't disturb xmission
    
       // Step 5. User specific code:
       // Interrupts are not used in this example. 
       SpiaRegs.SPITXBUF = 0xFFFF;
       SpiaRegs.SPITXBUF = 0xFFFF;
       SpiaRegs.SPITXBUF = 0xFFFF;
    
       // check txfifo level
       int txffil_a = 0;
       int txffil_b = 0;
       int txffil_c = 0;
       txffil_a = (SpiaRegs.SPIFFTX.all & 0x1F00) >>8;
    
       SpiaRegs.SPIFFTX.bit.TXFIFO = 0;
       txffil_b = (SpiaRegs.SPIFFTX.all & 0x1F00) >>8;
       SpiaRegs.SPIFFTX.bit.TXFIFO = 1;
       txffil_c = (SpiaRegs.SPIFFTX.all & 0x1F00) >>8;

    After the code sequence runs, txffil_a will be 2. meaning there are 3 words in the FIFO, txffil_b and txffil_c are both 0. This is consistent with the expected behavior since the FIFO reset will reset the fifo pointer.

    -Mark

  • What I mean by it doesn't work well is that when I run my code tx_[0] isn't loaded into SPIDAT for the next transmission.  To get my snippet of code to clock out the value from tx_[0] I have to force SPIDAT = tx_[0].  I guess the problem I'm having is that SPIDAT isn't loaded with the new FIFO value until the master clocks out SPIDAT - which is garbage data.  But I don't want to hijack SPIDAT while it's in the process of clocking out if I happen to try and update the FIFO.  I check the state of the chip-select line before resetting the TXFIFO but this is still dangerous and in fact is causing periodic collisions still when the transmission starts just after the check and while loading the TXFIFO.  I'm not sure how to protect this other than give up trying to refresh the TXFIFO asynchronously and only load new values after old ones have been clocked out.  This is not idea though and adds a whole cycle of delay to things....