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.

TMS470R1B1M-HT SPI continuous transmission

Other Parts Discussed in Thread: DAC8814EVM, DAC8814, TMS470R1B1M

Hi,

I have a PC software to write 1 byte command and read 7K bytes a time from TMS470 through SPI ( similar as a memory dump ).  TMS470 acts as SPI slave.  PC use SPI continuous read mode to read data out with continuous CLK, meaning there is no gap between each 8 bit CLK.  Similar to the SPI flash memory read command.


Is the TMS470 hardware possible to send out SPI bytes with continuous SPI clock?  I cannot make it work yet.

Thanks, Jian

  • Hello Jian,

    Can you please help me answer the below questions ?

    a. Frequency of ICLK ?

    b. Frequency of SPI Master Clock ?

    c. Whats the scheme you are using in the TMS470 SPI for data transmission ? DMA, interrupt etc ?

    Please let us know.

  • Hi,

    ICLK is 30MHz.

    SPI master clock 10MHz.

    I am using interrupt for TMS470 SPI data transmission.

    The following is my code.  It requires a gap between each byte of clock to transmit each data byte.  But I need to transmit data byte continuously with continuous master clock(no gap between each bytes of clock).

    At initialization, I have:

    void InitSPI2 ( void )
    {
      SPI2CTRL1 = 0x48;   // SPI baud = 10MHz, CHARLEN = 8
      SPI2CTRL2 = 0x01;   // ext clock, SPI in reset, SIMO input, SOMI output, not in powerdown mode, mode 0
      SPI2PC6 = 0x1E;     // SPIENA GPIO; SPISCS, SOMI, SIMO, CLK SPI func
      SPI2PC1 = 0x00;     // SPIENA input
      SPI2CTRL3 = 0x02;   // SPIENA is a value; DMA not used, overrun intrrpt disable, flag=0, RXINTEN enable, flag=0
      REQMASK |= (1 << CIM_SPI2); // Enable SPI2 channel end-transfer/overrun
      SPI2CTRL2 |= 0x10;  // activate SPI
    }

    The ISR for SPI is as follows:

    uint8_t spi_rd_arr[10] = {0};
    void SPI2_ISR ( void )
    {
      uint32_t temp;

      if ( ( SPI2CTRL3 & RX_INT_FLAG ) != 0 )
      {
        if ( spi_cnt < 1 )  // get the command byte from PC and save to spi_rd_arr[]
        {
          temp = SPI2BUF;  // clear flag
          spi_rd_arr[spi_cnt] = temp;
          if ( spi_cnt == 0U )
          {
            SPI2Comm( &(spi_rd_arr[0]), &(read_buf_d[0]) ); // compose 6673 bytes transmit data(read_buf_d[]) from command byte received(spi_rd_arr[0]).
          }
        }
        else // start transmitting byte by byte
        {
          SPI2CTRL3 |= RX_INT_FLAG;  // clear flag
          spi_tx_cnt = spi_cnt - 1;
          SPI2DAT0 = read_buf_d[spi_tx_cnt];  // transmit from read_byf_d[] byte by byte.
          spi_tx_cnt++;   // count is 1 more than array size, the extra 1 is received char
        }
        spi_cnt++;  // add 1 from spi_tx_cnt
        if ( spi_tx_cnt == 6673 ) // spi transmit finish, reset for next cycle of command byte receive and 6673 byte data transmission.
        {
          spi_cnt = 0U;
          spi_tx_cnt = 0U;     
        }
      }
    }

    Thanks a lot!!

  • Jian,

    DMA would be the best method to use, apart from that there may be a dependency on the SPI Clock coming in to the slave as well as the ICLK frequency.

    Can you pls try the same experiment by reducing the SPI clock, may be 1MHz keeping the ICLK at 30MHz, try the same and let us know the result.

  • Hi,

    I tried to decrease the SPI clock to 150KHz, the result is the same.  The problem is that how I can make TMS470 to send data correctly with continuous SPI clock, meaning no gap between each byte SPI clock.

    Jian

  • Jian,

    Would you please share the spec of the communication protocol your PC uses? Then we can check if it is compatible with TMS470 SPI.

    Thanks and regards,

    Zhaohong

  • Zhaohong,

    I spent almost a  month on this issue already.

    Basically the original PC protocol was used to read SPI flash chip.  First drive CS low, write flash starting address 0x100000, then read 1MB flash data with continuously SPI clock, then drive CS high. 

    I changed PC protocol as follows: drive CS low, write byte 0x05 to TMS470.  after around 100us to 200us wait time(so TMS470 can read external memory and fill out transmit array), issue 6656 bytes CLK continuously to read from TMS470 data, then drive CS high.

    The problem I have is that the data received on PC looks complete different from what is inside TMS470.  I connected 4 pins between PC side and TMS470: CS, CLK, MOSI, MISO.  I set TMS470 as SPI slave.  I used 3 pin option, 4 pin option with SPISCS.  Not working.

    Should I use 4-pin option with SPIENA?  With SPIENA pin connected to CS pin from PC side?

    Thanks, Jian

  • Jian,

    On TMS470 SPI, a gap of two SPI clock cycles is normally required between each SPI data. I do not think that your current set up will work.

    We may be able to come up with some ideas to help you if your can share the SPI flash spec. How do you hook SPI to PC? I assume that you are using some kind of converter. We need to see the spec/user guide of the converter too. The assumption here is that you can write/read the SPI flash correctly with this converter.

    SPIENA is a signal SPI slave sends to the SPI master indicating that it is ready to receive/transmit data. It is only useful if the SPI master supports the handshaking feature.

    Thanks and regards,

    Zhaohong

  • Zhaohong,

    I am using a USB-to-SPI cable: C232HM from FTDI as converter.  data sheet: http://www.ftdichip.com/Support/Documents/DataSheets/Cables/DS_C232HM_MPSSE_CABLE.PDF

    I am also using open-source libmpsse driver for fast SPI data transfer.  Website: https://code.google.com/p/libmpsse/

    I downloaded latest: libmpsse-1.3.tar.gz from https://code.google.com/p/libmpsse/downloads/list

    I am using spiflash.c as template in the src\examples folder.

    I did try the driver from FTDI vendor, but it is too slow to read data from SPI interface.  We need to read 1GB data from our embedded system in 1 hour and save to a file in PC.

    the flash spec is: http://www.winbond.com/NR/rdonlyres/4D2BF674-7427-4FC8-AEF0-1A534DF74F16/0/W25Q80BV.pdf

    Please see page 25 for read data spec.

    If you need more info, please let me know.

    Thanks for the help, Jian

  • Jian,

    I took at look at the documents.

    The fast SPI mode (supported on SPI flash) is not compatible with TMS470 SPI. You can only use standard SPI mode. I would suggest you to use the driver from FTDI.There must some APIs which takes less overhead. I may be able to make some suggestions If you can send the userguide for the driver.

    To save 1GB data in one hour, the SPI link has to be run at about 3MHz. I would suggest you to set the SPI clock to 10 or 15 MHz to have enough spare time. The SPI data size should be16 bits. The SPI port from this FTDI chip does not support handshaking so that you cannot use SPIENA pin. You need to find some other method to make sure that TMS470 SPI is ready before PC to start SPI transfer.

    Thanks and regards,

    Zhaohong

  • Zhaohong,

    I used the API from FTDI vendor at the beginning.  MCU read 1 byte and send 6664 bytes data through interrupt each time, data is correct.  From scope graphs, with 150KHz clock, 1 bytes takes 50us clock, 100us idle time in between.  With 1MHz clock, 1byte takes 8us clock, 82us idle time between clocks.  If I use 10MHz clock, the situation is worse.  Gap between each clock bytes are huge.   I can send you the graphs if you want.  I am using AN188 to do the SPI read, write from the website:  http://www.ftdichip.com/Support/Documents/AppNotes/AN_188_C232HM_MPSSE_Cable_in_USB_to_SPI-Interface.pdf

    The driver API and application code can be downloaded from page 8.

    After I ask the idle time question to ftdi support, I got response from ftdi tech support as follows:

    ====================start

    Jian:

    Here are the SPI performance specs from the developer.   I was in error when I told you the interface could support 3.75 MBytes/sec

     

    Here are some readings that were obtained while testing for full-duplex mode(i.e. SPI_ReadWrite)

     

    Clock        Transfer rate

    ---------------------------------

    5 KHz        4715 bits/sec

    1 MHz       240 kilo bits/sec

    30MHz      315 kilo bits/sec

     

    The marginal improvement in throughput reduces when the clock is already in the mega hertz range.

    ===============================end

    So their API speed is not fast enough.  Then I tried to use open source FTDI driver(with fast SPI mode).  If fast SPI mode cannot be used, I am stuck.

    I do set clock speed as 10MHz as you mentioned for the speed.  I don't know why you say SPI data size has to be 16 bits.  I am using 4 pin with CS option.  It works fine with ftdi vendor driver except speed issue.  So I can do without SPIENA pin.

    Zhaohong, I know you have good experience on SPI, any suggestion?

    Regards, James

  • Jian,

    I spent some time on the documents. Without knowing the details of the API implementation, I would like to make the following suggestion on the basis of commonsense guesses.

    (1) Use "#define SPI_TRANSFER_OPTIONS_SIZE_IN_BYTES 0x00000002" to make SPI data size to 16 bit. You mentioned the gap observed between each SPI data. If the data size is 8 bit, you see a gap every 8 bit. When the data size is 16 bit, there will one gap every 16 bit. You will reduce the number of gaps by half.

    (2) Call the API only one time to receive all the data. this will minimize the overhead in calling API. Do not call the API for receiving individual SPI data. You may need to change the statement "#define SPI_DEVICE_BUFFER_SIZE 256" to make the buffer large enough to save all the data you intend to receive.

    Since it is not a TMS470 issue, you can check the speed by running test on PC itself. The speed can be measured by hooking up a oscilloscope on the SPI clock pin. You should see a a gap every 16 clocks. To make it easier to see on a scope, you can call the API in an endless loop.

    Thanks and regards,

    Zhaohong

  • Zhaohong,

    I plan to try another USB-SPI adaptor with can insert 2 SPI clock cycle idle time between adjacent clock bytes.  The adaptor can use full duplex mode: it can transmits data to slave and receives data from slave simultaneously.

    Is the TMS470 SPI 4-pin option with SPISCS able to support full duplex mode if set as slave?  If so, how to use it to achieve the scheme that receive 1 byte command from master send 7KB response after 10ms process time?

    Thanks, Jian

  • Jian,

    On TMS470, all SPI modes are duplex. In other words, transmit and receive always happen simultaneously. To make a slave SPI ready, you need to write the first data into the trnamit data register. The data will be clocked out when the master clock arrives at the slave. SPI master needs to send data out in order to receive data from slave.

    For your scenario,

    (1) make SPI slave ready by writing a staus or dummy data in the SPI slave transmit register.

    (2) SPI master sends the command byte. In the meantime, SPI master receives the status/dummy data from SPI slave.

    (3) The data for SPI slave to transmit should be ready within 10ms after receiving the commnad byte. Write first data to the SPI slave  transmit register.

    (4) SPI master start receiving slave data by transmitting a dummy data to slave. The master has to send one byte for each byte it receives. On the slave side, if the receive data register is not read, a RX overrun error flag will be set. You need to read eeach dummy data if you do not want to see this error flag.

    There are two chanllenges. The first one is to set up SPI slave early enough for receiving the first command byte. The second one is that the data needs to be ready with 10 ms after receiving the command byte. the data needs to be ready on the slave side before SPI master sends dummy data for receiving data from SPI slave.

    Thanks and regards,

    Zhaohong

  • Zhaohong,


    I used a new USB-SPI adapter as SPI master (clock=10MHz).  To test, PC write 0x05 to TMS470 and then read 3 bytes from MCU.  The 3 bytes are 0xBB, 0xAA, 0xAA.  But PC software actually read back 0xBB, 0x00, 0x01.  Not sure why?


    As you indicated, the 10MHz clock has idle time of 3 bits between each clock bytes.  Also a dummy byte(0x00) was written to SPI slave transmit register SPI2DAT0.  SPI mode 0 is used.

    5773.SPI_waveform.xlsx

    The waveforms are attached.  Also the source code is as follows (in SPI2_ISR, spi_cnt should be 4, but show 3):

    ============

    int main(void)
    {
      __disable_interrupt();
     
      PCR = CLKDIV_2;                         // ICLK = SYSCLK / 2 = 29.4912MHz
      GCR = ZPLL_CLK_DIV_PRE_1;               // SYSCLK = 8 x fOSC = 8*7.3728 = 58.9824MHz
      PCR |= PENABLE;                         // Enable peripherals
      InitSPI2( );
      __enable_interrupt( );                   // enable interrupts
      while(1)
      {
      }
    }

    void InitSPI2 ( void )
    {
      SPI2CTRL1 = 0x48;   // SPI baud = 10MHz, CHARLEN = 8
      SPI2CTRL2 = 0x01;   // ext clock, SPI in reset, SIMO input, SOMI output, not in powerdown mode, mode 0
      SPI2PC6 = 0x1E;     // SPIENA GPIO; SPISCS, SOMI, SIMO, CLK SPI func
      SPI2PC1 = 0x00;     // SPIENA input
      SPI2CTRL3 = 0x02;   // SPIENA is a value; DMA not used, overrun intrrpt disable, flag=0, RXINTEN enable, flag=0
      REQMASK |= (1 << CIM_SPI2); // Enable SPI2 channel end-transfer/overrun
      SPI2CTRL2 |= 0x10;  // activate SPI
     
      SPI2DAT0=0;
    }


    uint8_t rd = 0;
    void SPI2_ISR ( void )
    {
      uint32_t temp;

      if ( ( SPI2CTRL3 & RX_INT_FLAG ) != 0 )
      {
        if ( spi_cnt < 1 )
        {
          temp = SPI2BUF;  // clear flag
          rd = temp;  // receive 0x05 from PC
          SPI2DAT0=0xbb;  // prepare to send 1st char to PC
        }
        else
        {
          temp = SPI2BUF;  // clear flag
          rd = temp;
          SPI2DAT0 = 0xAA;  //send 0xAA to PC
        }
        spi_cnt++;  
      }
    }

  • Jian,

    Your waveform indicates that the bus has a big capacitance loading. The wires may too long. First, you need to make sure if this setup works at low frequency. I would suggest you to run the SPI clock at 10KHz to see if everything works.

    Thanks and regards,

    Zhaohong

  • Zhaohong,

    Under 10MHz.  From PC SPI master side, I changed the clock idle time between clock bytes to 14us and read 256 bytes of data from TMS470, the data looks correct.  But if I change to 6us, 1 or 2 bytes out of 256 bytes data are random data.  Can you tell me the electrical spec on the min clock idle time when TMS470 acts as SPI slave?  I cannot find it anywhere.

    Thanks, Jian

  • Zhaohong,

     

    Sorry I did not tie the PCB grounds together, that is why the waveform shows capacitance effect.

     

    I find the data correctness is related to the idle time length between SPI clock bytes.  Under 10MHz, from PC SPI master side, I changed the clock idle time between clock bytes to 10us and read 256 bytes of data from TMS470 slave, the data is correct.  But if I change to 8us, 1 or 2 bytes out of 256 bytes data are random data.  May I ask what is the TMS470 doing in this 10us?  We are trying to find the source of this 10us delay.  Is it constant under different SPI clock frequency?  Is there any way to make it shorter?  It is the bottleneck of memory dumping.  It will take 4hours to dump 1GBytes data if TMS470 need a 10us wait time for each byte read.  Please see the waveform attached.6082.SPI_waveform.xlsx

     

    I studied the app note SLAA317: interfacing the DAC8814EVM to TMS470 Processors.  On page 2, section 4.1, it says DAC8814 is updated by TMS470 at a 1.2MHz rate, with 30MHz SPI clk.  From app note, each sample is 18 bits.  Each sample require time is 30MHz/1.2MHz=25bits.  So idle time between each sample is 25-18=7bits under 30MHz SPI clock, which is much less than 10us.  Why this idle time is so short?  I am confused.

     

    They can use 30MHz SPI clock.  From SPNS109A page 41, TMS470R1B1M SPI clock cycle time minimum is 100ns, which is 10MHz max frequency.  How do they set up to 30MHz?

     

    Zhaohong, I need your help.

    Regards, Jian

  • Hi,


    Any suggestions on this issue?

    Regards, Jian