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.

Two way SPI communication, Master missing first byte from slave.

Hi everyone!
 

This issue could been seen as a continuation of a previous thread I started here a month ago however I feel a new thread should be started as the issue remains after going through my code to make sure I have not inadvertently changed or left out any of the code recommended in said thread.  If a moderator feels disagrees please append this to my previous thread.

The Background:


I've been working on getting a PIC18 (set as master) to communicate with a TMS570 (slave).  The aim of the exercise is to have the PIC18 periodically request data from the TMS570, where all data packets will be 4 bytes long.
 
In order to do this an interrupt routine has been set up on the TMS570 where when the PIC18 pulls RB1 high the TMS570 gets ready to receive a 4 byte telecommand, the TMS570 then informs the PIC18 it is ready to receive by pulling another RB2 high.
 
As all telecommands will result in a response from the TMS570 the PIC18 has been coded to wait until RB2 is pulled high a second time to indicate that the TMS570 is now ready to send data back.
 
In the case I have provided below it is a simple routine to inform the PIC18 that the TMS570 is operational (it will be expanded further to include error codes once this issue is resolved)
 

The problem:


So to recap the TMS570 receives all bytes sent by the PIC18, both the Telecommand and the junk bytes sent to stimulate the SPI for the return data, however the PIC18 seems to miss the first byte of each packet sent by the TMS570.  The data return routine is based on the fact that the TMS570 can not send data until the SPI clock is started again and the first byte from PIC18 is sent.  With this in mind the TMS570 places the data into its SPI buffer, then "starts" its transfer (however as the Master has not started the transfer TMS570 will wait) pulls the GIO high and then polls the transfer complete flag.  As for the PIC18 while the TMS570 is preparing its response the PIC18 makes its way to the SPI receive function I've set up, waits until RB2 is pulled high and then starts the SPI transfer immediately.
 
Can you see any errors I have made in my code/logic which would result in the PIC18 missing the first byte sent by the TMS570?

4214.Main.c

7180.EB-SPI-COMMS.zip


Thanks in advance
 
Alex

  • Alex,

    From your SPI set up code, I see that you are using the 3-pin mode. To ensure the integrity of SPI master/slave communication, 4-pin mode with ENA is normally recommended. When ENA pin is used, the SPI slave will set up the correct ENA state after SPI Slave is ready to transmit /receive data. SPI slave is ready after the transmitted data is written into SPI_DAT register or transmit data portion in MibSPI buffer. With ENA pin, SPI master will not generate SPI clock until see ENA pin at correct state. If the SPI master or slave does not support ENA, the device with SPI slave needs to send a handshaking signal (maybe via a general I/O pin) to SPI master device so that it can start transmission safely.

    It seems that you have followed the procedure described above. I am wondering if there are device sync issues at boot up. Right after power-on-reset, TMs570 GIO pins are Hi-Z input and PIC may see it high. If PIC boots up earlier and sees this pin high, PIC may start SPI transfer before TMS570 SPI is ready. Can you add a pull-down resistor on RB2 to prevent this situation? In a debugging environment, you can try starting TMS570 first and then starting PIC.

    Thanks and regards,

    Zhaohong

    Thanks and regards,

  • Hi Zhoahong,

    Yes, i read that the GPIOs were high at start up so a pull down is currently connected to RB2. With regards to the start up order currently the PIC18 is set to start after the tms570, this has been done to reprsent how the system will opperate once fully coded.

    Is the location of the gpio function correct with regards to the operation of the spi transfer function?

    cheers,

    alex

    o

  • Alex,

    The spiIsTransferComplete() only check for the completion flag to be set, but does not clear it.

    The first time after MIBSPI initialization, the flag is clear until the transfer is done. In this case it is working as planned.

    The next time spiIsTransferComplete() is called, it will return immediately because the flag is still set from previous transfer.

    The solution is to add this statement after the call of spiIsTransferComplete():

    spiREG1->INTFLGRDY = 0x0001;     // Clear the INTFLGRDY flag.

    Please have a try and let me know.

    Regards,

    Jean-Marc

  • Hi Jean-Marc,

    I've added the lines to clear the flag after each use of spiIsTransferComplete(), however it has not resolved the issue, the PIC is still missing the first byte the TMS570 sends.

    I believe it is to do with the second triggering of the SPI communication, though I do not see where the problem is coming from, the PIC will not start the clock or send any data on the SPI until the TMS570 states it is ready via RB2, while the TMS570 will prepare the data to send but can not transmit anything until the PIC starts as it is the slave device.

    Any further thoughts, option, I've included delays to see if this resolves anything but unfortunately it has not.

    Cheers,

    Alex

  • Alex,

    Can you insert a breakpoint at your PIC code execution after the first SPI data is sent? You can check the first SPI data PIC receives from TMS570. Then you can stop TMS570 execution and check the received SPI data. Ideally, you should see the second SPI data in the SPI transmit register.  We may be able to put together a clearer picture with this information.

    Thanks and regards,

    Zhaohong

  • Hi Zhaohong,

    As there is no relationship between the naming routine used for registers in the TRM, CSS or the compiler I'm not sure how I'm going to view the required registers in the watch window.

    I've tried the register names used in the TRM, I've also inserted the exact register addresses (found via TRM and data sheet), I've also tried the registers/structure used in spi.c

    The watch window is oblivious to all of these.

    Kind regards,

    Alex

  • Alex,

    On TMS570, all peripheral registers are memory mapped. you can view them in CCS memory window. for example, the start address of SPI1 registers is 0xFFF7F400. You can open a memory wiondow with start address of 0xFFF7F400 and view all SPI1 registers there.

    Thanks and regards,

    Zhaohong

  • Hi Zhaohong,

    Using the Memory window (never thought of using that, I always try and use the watch window..) and placing breakpoints at different places and I can see the data moving out of the RXDATA (@0xFFF7F444) but I can not see any data moving through the TXDATA (@0xFFF7F438) even though the PIC is receiving all bytes after the first.

    Could this be due to the way the TMS570 is halted, i.e it is always in the spiIsTransferComplete() function, isn't the TXDATA register cleared after the data is sent?  Is there an address for the TXBUF mentioned in the TRM?

    Cheers,

    Alex

  • Alex,

    Can you try the following experiment?

    (1) load PIC and TMS570 code to memory. Insert a breakpoint in PIC program after a SPI data is transferred

    (2) Start PIC and TMS570.

    (3) When PIC stops at the breakpoint, check and record the received SPI from TMS570. Then continue execution.

    (4) Repeat (3) till all data is transmitted.

    SPI is a synchronous bus. When SPI master finishes transmitting a data , it also receives a data from slave. If PIC is set to transmit 8 pieces of data, it also receives 8 pieces of data. You said that you missed the first data. Did you only receive 7 pieces of data or the value of the first data is wrong? This experiment enables you to see the received data in each transfer. You do not need to insert any breakpoin on TMS570 side. It is a SPI slave in the test. Focus on what can see fron PIC.

    Thanks and reagrds,

    Zhaohong

  • Hi Zhaohong,

    Yes, this is how I had tested the communications before I wrote the last post, the PIC does not receive a single bit for the first byte, I have observed a skewed response (from incorrect SPI setup) so if the TMS570 was sending anything I would have observed it.

    The code I've written makes use of the synchronous nature of the SPI bus.

    In any case, I have worked around this problem by using 5 bytes to send 4 bytes of data, it may not be ideal but it works......

    On a side note I decided to try and have the second data packet (the response to the telemetry request) sent via a second Transfer Group, i.e. all spi functions had a 1 in place of a 0 for the "group" input.  However the PIC did not receive the bytes intended to be sent via the second transfer group, instead it received the bytes from the first transfer group. 

    I have to say I do not understand the operation of the TMS570 and this is greatly worrying as I will be needing to swap transfer groups when communication with other devices.

    If this sheds any light on what is occurring please let me know.

    Kind regards

    Alex

  • Alex,

    When a SPI master completes transferring 4 pieces of data, it also receives 4 data from SPI slave.  You said that the first Slave data is missing. What is the first data received by SPI master? Assume that you expect to receive 1,2,3,4 from SPI slave. What do you actually receive?

    Thanks and regards,

    Zhaohong

     

  • Hi Zhaohong,

    Ok, maybe I'm using my words too loosely, I apologies.  What I meant is the first byte the TMS570 is meant to send is 0xEE, what it sends is 0x00.

    After that it continues as a SPI communication should.

    I have tried many different first byte values, all result in 0x00.

    Could you also explain why the incorrect transfer group was sent when I attempted to use two transfer groups, the first 4 bytes using transfer group 0, then the next 4 bytes using transfer group 1, all following the following process:

            spiSetData(spiREG1,#,SPI_RUBBISH_OUT);  //Prepare SPI_TELE_RUBBISH_OUT for transfer
            spiTransfer(spiREG1,#);  //Once PIC starts to send data, transfer rubbish
            gioSetBit(gioPORTA,6,1);  //Tell PIC that the TMS570 is now ready (GPIOA6)
            while (!(spiIsTransferComplete(spiREG1,#))) {};  //Wait until transfer is complete
            spiREG1->INTFLGRDY = 0x0001;   //Clear the INTFLGRDY flag.
            spiGetData(spiREG1,#,SPI_DATA_IN);  //Received data placed in SPI_TELE_DATA_IN
            gioSetBit(gioPORTA,6,0);  //Tell PIC that the TMS570 is now ready (GPIOA6)

    where # is either all 0, or all 1.

    Cheers,

    Alex