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 does not transmit

I'm using F28335 in my active DSP loudspeakers project and I need it to communicate via SPI (as master) with other uC-s in the system. I spent the whole yesterday (10+ hours) trying to make my 28335 send out any SPI but (it seems) with no success. I must be missing sth simple but fundamental. But I have gone through all available examples and I’m lost what I can be missing.

The key observation is it seems to receive data I'm writing into the transmission registers but it is stuck there. I have tried both the plain and the FIFO version. For the non-FIFO in the loopback mode when I put a value into SPIDAT it never gets into the SPIRXBUF (I’m watching the registers section in CCS4 in the debug mode via XDS100). Also the the SPISTS bit 6 never gets to one which I assume should take place when the value has been shifted out and stay so till I read off the SPIRXBUF. In the FIFO mode all the values (with loopback on) I write to SPITXBUF simply increase the counter bits in the SPIFFTX and again no life in SPIRXBUF nor SPISTS.bit_6. I have read the documentation 3-4 times already and I feel I have run out of ideas and power.

I have put all the code that is relevant for the SPI part below maybe you can spot out the omission. Or maybe I should try out some exemplary simple SPI project but I could not find anything fully self-contained (I mean some SPI loopback examples in the sprc530.zip package that I took as the basis still need to be supplemented with some system and interrupts setup and this part may be the culprit). 

Pawel

 

#include "DigAmp4ChSbb-Settings.h"                // supplies settings for this project

#include "PeripheralHeaderIncludes.h"    // include headers for this used device

 

main ()

{

 

            DeviceInit();

            SPI0();

}

 

 

 

void DeviceInit(void)

{

            WDogDisable();            // Disable the watchdog initially

            DINT;                            // Global Disable all Interrupts

            IER = 0x0000;   // Disable CPU interrupts

            IFR = 0x0000;    // Clear all CPU interrupt flags

 

           

            PLLset(0x8); // 25 MHz quartz-driven

           

                                   

// Initialise interrupt controller and Vector Table

// to defaults for now. Application ISR mapping done later.

            PieCntlInit();                 

            PieVectTableInit();

 

   EALLOW; // below registers are "protected", allow access.

 

// HIGH / LOW SPEED CLOCKS prescale register settings

   SysCtrlRegs.HISPCP.all = 0x0002;                  // Sysclk / 4 (25 MHz)

   SysCtrlRegs.LOSPCP.all = 0x0002;                 // Sysclk / 4 (25 MHz)               

   SysCtrlRegs.PCLKCR0.bit.SPIAENCLK=1;     // SPI-A

}

 

 

 

void SPI0(void)

{

  int i;

 

            SpiaRegs.SPICCR.all =0x0F;                  // Reset on, rising edge, 16-bit char bits 

            SpiaRegs.SPICTL.all =0x0006;                                // Enable master mode, normal phase,

                                                 // enable talk, and SPI int disabled.

            SpiaRegs.SPIBRR =0x007F;                                          // LSPCLK/(SPIBRR+ 1)                                                                                    

    SpiaRegs.SPIPRI.all = 0x00;                // Set so breakpoints don't disturb xmission

// Initialize SPI FIFO registers

   SpiaRegs.SPIFFTX.all=0xE040;

   SpiaRegs.SPIFFRX.all=0x204F;

   SpiaRegs.SPIFFCT.all=0x0;

 

   GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1;  // GPIO16 = SPICLKA

   GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 1;  // GPIO17 = SPIS0MIA

   GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1;  // GPIO18 = SPICLKA

   GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 1;  // GPIO19 = SPISTEA

 

 

    SpiaRegs.SPICCR.all =0x9F;                      // 0x80 - Leave reset, + 0x10 - loopback mode

    SpiaRegs.SPIDAT=12;

    spi_xmit(0x34);

 }

 

 

void spi_xmit(Uint16 a)

{

 

    SpiaRegs.SPITXBUF=a;

 

 

 

 

void PLLset(Uint16 val)

{

   volatile Uint16 iVol;

 

   // Make sure the PLL is not running in limp mode

   if (SysCtrlRegs.PLLSTS.bit.MCLKSTS != 0)

   {

      // Missing external clock has been detected

      // Replace this line with a call to an appropriate

      // SystemShutdown(); function.

      asm("        ESTOP0");

   }

 

   if (SysCtrlRegs.PLLCR.bit.DIV != val)

   {

 

      EALLOW;

      // Before setting PLLCR turn off missing clock detect logic

      SysCtrlRegs.PLLSTS.bit.MCLKOFF = 1;

      SysCtrlRegs.PLLCR.bit.DIV = val;

      EDIS;

      WDogDisable();

      EALLOW;

      SysCtrlRegs.PLLSTS.bit.MCLKOFF = 0;

      EDIS;

    }

}

 

 

 

void PieCntlInit(void)

{

    // Disable Interrupts at the CPU level:

    DINT;

 

    // Disable the PIE

    PieCtrlRegs.PIECTRL.bit.ENPIE = 0;

 

            // Clear all PIEIER registers:

            PieCtrlRegs.PIEIER1.all = 0;

            PieCtrlRegs.PIEIER2.all = 0;

            PieCtrlRegs.PIEIER3.all = 0;     

            PieCtrlRegs.PIEIER4.all = 0;

            PieCtrlRegs.PIEIER5.all = 0;

            PieCtrlRegs.PIEIER6.all = 0;

            PieCtrlRegs.PIEIER7.all = 0;

            PieCtrlRegs.PIEIER8.all = 0;

            PieCtrlRegs.PIEIER9.all = 0;

            PieCtrlRegs.PIEIER10.all = 0;

            PieCtrlRegs.PIEIER11.all = 0;

            PieCtrlRegs.PIEIER12.all = 0;

 

            // Clear all PIEIFR registers:

            PieCtrlRegs.PIEIFR1.all = 0;

            PieCtrlRegs.PIEIFR2.all = 0;

            PieCtrlRegs.PIEIFR3.all = 0;      

            PieCtrlRegs.PIEIFR4.all = 0;

            PieCtrlRegs.PIEIFR5.all = 0;

            PieCtrlRegs.PIEIFR6.all = 0;

            PieCtrlRegs.PIEIFR7.all = 0;

            PieCtrlRegs.PIEIFR8.all = 0;

            PieCtrlRegs.PIEIFR9.all = 0;

            PieCtrlRegs.PIEIFR10.all = 0;

            PieCtrlRegs.PIEIFR11.all = 0;

            PieCtrlRegs.PIEIFR12.all = 0;

}          

 

 

void PieVectTableInit(void)

{

            int16     i;

            Uint32 *Source = (void *) &ISR_ILLEGAL;

            Uint32 *Dest = (void *) &PieVectTable;

                       

            EALLOW;         

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

                        *Dest++ = *Source;      

            EDIS;

 

            // Enable the PIE Vector Table

            PieCtrlRegs.PIECTRL.bit.ENPIE = 1;     

}

  • Hi Pawel,

     

    The GpioCtrlRegs are EALLOW/EDIS protected, so you need to set/clear this bit before/after writing to certain registers (GPIO control registers, PLL, TRIPZONE, PIE, ....)

     

    Regards, Mitja

  • Hi Mitja,

    thanks for the reply. I actually put together a couple of dispersed code sections dealing with SPI and did not notice EALLOW/ EDIS enclosed the PLL and GPIO setting. But for a double-check I enclosed specifically the GPIO setting into EALLOW/ EDIS bit but did not help, unfortunately ... The same behaviour - SPIDAT/SPITXBUF seem to keep daa for themselves. But maybe I'm making wrong assumptions about the SPI behaviour - if I run it stepwise in the debug mode what should happen after a write to SPIDAT/SPITXBUF when the SOMI/MISO is floating - should SPIDAT/SPITXBUF get 0x00 or 0xFF and SPISTS.bit6 on or sth else ?

    Pawel

  • In order to get SPI working in stepwise mode you should modify SPIPRI bits accordingly. As they are set now, the CPU halt also halts SPI clock, so in order to see bits and clock on the SPI pins you probably need to make more steps (depending on baud rate)

    Mitja

  • Bull's eye - the code was fine but I could not see the results in RX buffer and SPISTS because it needed some time to update - a short for() loop after trasmitting did the trick. Actually I had played with SPIRI as well but it turned out neither 0x00 nor 0x20 worked although the documentation seemed to suggest those values exactly  are to manage SPI with breakpoints and consequently my stepwise testing (although clearly the most elegant way to do this is via interrupts). So, I finally put the SPISTS testing in the transmission bit and it works:

     

     

     

     

    void

     

     

    {

    SpiaRegs.SPITXBUF=a;
    while (!(SpiaRegs.SPISTS.all & 0x40)) {};

    }

    spi_xmit(Uint16 a)

    Now time to leave loopback and try it out with a real SPI receiver, so some more questions might come...

    Great thanks, Mitja, for your time and sharing the expertise.

    Best regards, Pawel