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.

Problems with SPI between TMS570 and PIC18

Other Parts Discussed in Thread: TMS570LS20216, HALCOGEN

After many weeks of trying I've been unable to decipher how the SPI on the TMS570LS20216 works.  I currently have the USB dev board attached via 3 pin SPI to a PIC dev board, the PIC as master and the TMS570 set as slave.

In the end I need the TMS570 to run independently and respond to ad-hoc requests from the PIC for data from different TMS570 peripherals.

However I currently can not get the two to consistently talk to each other. I have the TMS570 set to 8 bit transmission word, with clock polarity set to high (the two refuse to work entirely when set to low), trigger events are disabled, one shot and CS is not used.

To replicated the intended role of the TMS570, after starting the debugger I have the TMS570 start up the GIO, SPI and global interrupts and then wait in an infinite loop.

At the same time the PIC is started with its own debugger; sets up all the relevant peripherals, loads an array with a 2 byte command, causes an interrupt on the TMS570 (via GIOA0) and finally sends the 2 byte command using a loop and the transfer complete flag.

On the oscilloscope I can see the PIC sending the CLK signal and the 2 byte command but nothing is being returned from the TMS570.  I have also used delays on the PIC to ensure the TMS570 is ready to receive/send but with no luck.

In the TRM a comparability mode is mentioned, I've seen it talked about in the forums too, how is this set up in HALCoGen?

What is the meaning of Length in the Transfer Groups, at 0, does this mean the spiIsTransferComplete function will return a 1 as soon as the first transmission word is received, while a 1 will mean after 2 transmission words have been received etc.

As for the read function setup by HALCoGen, I assume it does not need to have the SPI module exercised, it merely copies the data currently in the RX/SPI buffers to the desired array.

Older devices required the SPI buffers to be cleared before any data is sent/read, is this taken care of with the spiSetData, spiTransfer and spiGetData functions provided by HALCoGen?

As  a side note, if the help in either HALCoGen or CCS contained any information, it would have been very helpful.

  • H Alex,

    Thanks for posting your question i will look into to this and reply to you as soon as possible

    -Hari

  • HI Alex,

    The scenario you have mentioned should be easily realized in 3 pin slave compatibility mode. Looks like their might be some problem in the SPI initialization routine.Could you send us your CCS project so the we could look into your SPI code.

    -Hari

  • Hi Hari,

    To make the communication more concise I've included the use of the GPIOA1 pin to indicate when the TMS570 is ready.

    The entire project can be found in this zip file: 5037.USB-SPI-SLAVE-2INT.zip

    I would be very grateful if you could also answer the questions in my original post as well, that way I can understand how HALCoGen generates its code, namely:

    1. How is SPI compatibility mode set up, there is no mention of it in HALCoGen's help or interface

    2. Does setting the "Length" to 0 under "SPI1 Transfer Groups" disable the use of the SPIDAT0/1 and SPIBUF buffers?

    3. Does the spiGetData function require the exercising of the SPI module, or is it simply an array copying function?

    4. Does the SPI module need to have its RX/TX buffers flushed before use?

    and in addition:

    5. Why does CCS not recognise the register names used in the TRM?

  • Alex,

    I've looked at your project, and I think I've found your problem.

    Your code is using Transfer Group 0.
    You have selected "TRG_NEVER" for Trigger Event. It has to be "TRG_ALWAYS".
    Trigger source = TRG_DISABLED is correct.

    This configuration means that you are using software trigger and as soon as you call the spiTranfer routine, the transfer group is enable and active.

    Please make this change and let me know the result.

    Best Regards,

    Jean-Marc

  • Hi Jean-Marc,

    It looked as if that had solved the problem but the system has returned to the state it was in before.

    To elaborate further on its behaviour the first time the TMS and PIC runs the PIC runs to the end of its code (starts up SPI and then awaits for the appropriate signals (GIOA1 low) to start the transfer/receive loop, it then resets GIOA0 high), however the TMS gets stuck in the "spiIsTransferComplete" function. 

    The  second time the two programs are run it seems to work but it is equally as likely that the TMS570 will cycle through its code (even without the PIC running).  The SPI clock on the PIC is not running and the GIOA0 pin is still held high and yet the TMS570 seems skip out of the infinite loop to the GIO interrupt, run through the "spiTransfer" function (nothing is actually sent) and then copy the received data (nothing actually received) and present the junk data (presumably junk from the TMS570) in the output array.

    Also since the new HALCoGEN release it has been producing two instances of phantomInterrupt, one in esm.c while the other in sys_phantom.c, so i've been deleting sys_phantom.c to get CCS to compile

  • I've got to say it looks like there is a delay in the TMS570 which is causing the reception of data to be out of sink, somehow the last bit/bits are getting into the next frame of the transfer group.

    As for the TMS570 still not transmitting data here is my updated project:

    6371.USB-SPI-SLAVE-2INT.zip

  • Alex,

    If I remember your SPI configuration, format 0 is set with Clock phase = 0 and Clock Polarity = 1.

    Here is an extract from the TRM/MIBSPI documentation.

    Please can you confirm that this is the mode used by your PIC master?
    The problem you are experiencing is definitively a clock definition issue between the master and slave spi.

    I will answer your other questions in separate posts.

    Thanks and Regards,

    Jean-Marc

  • Hi Jean-Marc,

    For the PIC there are 3 settings, CKP which sets the idle polarity, CKE which acts as the the Phase modulator and SMP which sets when the PIC samples the incoming data.  The four different modes can be seen in the image below:

    From this information which combinations would you suggest?

    To be honest I'm at a loss, maybe I don't understand the terminology that is begin employed.

    To my understanding for example Polarity  = 0, Phase  = 1 should work with CKP = 0, CKE = 1 & SMP = 1, however the wording indicates that the PIC would be 1 bit (MSB) out of sink, however I'm not sure how the slave can pre-empt the master starting the transfer unless there is some initialisation that goes on beforehand.

    Thanks in advance

  • Alex,

    Based on the waveform you send to me I will recommend using the following setup:

    PIC: CKP=0, CKE=0, SMP=0.

    TMS570 POL=0, PHASE=0.

    In your spi_code() function, I did a modification.
    This routine in called when the PIC toggles GIOA0.

    1] First you prepare the data to be send to the PIC (TMS570 is slave)
        The spiSetData does only access the MIBSPI data memory, setting the data field and a flag bit to specify that the buffer is valid.
    2] At that point you can call the spiTransfer routine. This will make the transfer group 0 enable and ready to transmit.
         Because the TMS570 is configured as slave, nothing will happen until the master starts generating the clock.
    3] At that point, you can set the GIOA1 to signify to the PIC (master) that the transmission can start.
        I assume that at the point the PIC is ready to start the transfer, and it will start the clock.
    4] On the TMS570 side, we have to wait for the completion of Transfer Group 0.
    5]  When this is done, it is necessary to read from the MIBSPI received RAM the data.
    6] Than it is time to signify the PIC that we are done by toggling GIOA1 to 0.

    #3 was happening before #2 in your original code.

    There is still something not correct in this sequence.
    After the wait for the end of transfer group 0, it is necessary to clear the flag.

    Here is the modified version of spi_code()

    void spi_code (void)
        {
            /* Write rubbish to ram for transfer */
            spiSetData(spiREG1,SPI1group,tele_rubbish_out);
            y=2;
            
            /* Once PIC starts to send data, transfer rubbish */
            spiTransfer(spiREG1,SPI1group);
            y=3;

            gioSetBit(gioPORTA,1,1);                        //Tell PIC that the TMS570 is now ready (GPIOA1)

            /* Wait until transfer is complete - returns 1 when complete. */
            while (!(spiIsTransferComplete(spiREG1,SPI1group)));

            spiREG1->INTFLGRDY = 0x0001;
                                                 // Clear flag for End of Transfer Group 0
            y=4;
               
            /* Transfer has completed, received data placed in tele_data_in */
            spiGetData(spiREG1,SPI1group,tele_data_in);   
            y=5;
            
            SPI++;
            
            gioToggleBit(gioPORTA,1);                        //Toggles GPIOA1, in this case to 0
        }


    I have checked this code using 2 TMS570 one in Master (to emulate the PIC) and one in Slave.
    For clarification, here is the code for the MASTER.

        while(1)
        {
       spiSetData(spiREG1,SPI1group,data_out);           // Write the data to be send to Slave

         gioSetBit(gioPORTA,0,1);
         gioSetBit(gioPORTA,0,0);                                                  // This pulse will trigger an interrupt on the Slave side.
                                                                                                // spi_code() will be executed

         while (gioGetBit(gioPORTA,1)==0);                                     // Wait for handshake from Slave (Slave is ready, data are in buffer, waiting for the clock)

         spiTransfer(spiREG1,SPI1group);                                       // Master can start transfer data.
           do
         {
          result = spiIsTransferComplete(spiREG1,SPI1group);            // Wait until transfer completed.
          count++;
         } while(result==0);
           spiREG1->INTFLGRDY = 0x0001;                                             // Clear the flag.
         while (gioGetBit(gioPORTA,1)==1);                                              // wait for handshake from Slave
        }

    Can you have a try and let me know.

    Regards,

    Jean-Marc

  • Hi Jean-Marc,

    Thank you for looking into this, it turns out that it was a problem with the development boards (I've not looked into exactly what caused the problem), since my last post I received the engineering model of my design and my original code works perfectly on it. 

    To confirm I have the waveform registers set up as

    PIC: CKP=0, CKE=0, SMP=0.

    TMS570 POL=0, PHASE=0.

    The code also works without the GIOA handshakes, though I will keep them in for greater control.

    Thanks again for looking into my problem.

    Kind regards,

    Alex