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.

C6747 SPI problems

Hi,

I am using the PSP drivers 01.20.00 on the C6747 EVM and can't get the expected output.  I started with the example that is included with the PSP package.  I modified to just transmit a data pattern every second out SPI1 instead of SPI0.  I monitor the SPI pins with a scope.  Using all the default SPI param settings from the example, the operation is (I think) correct except for the CS line.  Configuration uses the following modes:

Spi_OpMode_DMAINTERRUPT and Spi_PinOpMode_SPISCS_4PIN.  When I run the program the CS line remains high and never changes states.  By trial and error, I modified the value of spiParams.spiHWCfgData.csDefault to 0.  ( driver default value is 0xFF, which, by the way isn't even valid according to the SPI users guide).  With a value of 0, the CS line will start low and change to high before the data transmission and then goese back to low at the end of the transmission.  So this is the opposite logic that I would like.  I looked in the source code of the driver and it looks like the CSNR field of SPIDAT1 register is being set to 0xFF (which again is not valid according to the User's Guide).  The Guide describes that a value of 1 drives the pin active high and a value of 0 drives the pin active low.  How can I change the value of this?  It looks like there is no parameter field in the driver APIs that directly control this register/field.  Or is there something else I'm doing wrong?  Has anyone else experienced these issues?

The other issue is the C2T and T2C time delays.  I have these set to 0 (actually the default is 0 and I don't change this).  In the case where the CS seems to be functioning, these delays are very long.  The CS transitions from H to L and there is a 40 microsec delay on the scope before the clock kicks in.  The clock is set at 30 MHz so this would be 1,200 clock cycles if I were to measure the delay in terms of clock delays.  Similarly the T2C delay is about 22 us.  I also toggle a GPIO pin before/after each burst (each issue of GIO_write) and the CS line has only a slightly less delay than that.  Nothing close to what the User's Guide describes as proper operation for the CS.  Thanks in advance for any advice/help.

Mike

  • Hi Mike,

    Are you having there results with the original example of just after you changed it?

    This is a lot happening, so it would help to see the parameters/spi configurations you are using, and maybe a scope shot as well.

    Just an observation, the clock for the spi is set to 3MHz by default, so please make sure you really changed it to 30 MHz (outputClkFreq, Line 80 of the file Spi.c in the driver's project).

  • Mariana,

    Thanks for your assistance on this.  I had moved on to McASP so had to transition back to SPI issues.

    I started looking at this again from the beginning.  Here is my settings for the SPI parameters.  I start off with the driver defaults and modify as per my needs:

      spiParams = Spi_PARAMS;

    spiParams.hwiNumber = 8;
    spiParams.opMode = Spi_OpMode_DMAINTERRUPT;
    spiParams.outputClkFreq = 1000000;
    spiParams.loopbackEnabled = FALSE;
    spiParams.edmaHandle = NULL;

    spiParams.spiHWCfgData.pinOpModes = Spi_PinOpMode_SPISCS_4PIN;
    spiParams.spiHWCfgData.intrLevel = TRUE; /* map ints to INT1 */
    spiParams.spiHWCfgData.csDefault = 1;
    spiParams.spiHWCfgData.configDatafmt[0].charLength = 8;
    spiParams.spiHWCfgData.configDatafmt[0].clkHigh = TRUE ;
    spiParams.spiHWCfgData.configDatafmt[0].lsbFirst = FALSE;
    spiParams.spiHWCfgData.configDatafmt[0].oddParity = FALSE;
    spiParams.spiHWCfgData.configDatafmt[0].parityEnable = FALSE ;
    spiParams.spiHWCfgData.configDatafmt[0].phaseIn = FALSE ;
    spiParams.spiHWCfgData.configDatafmt[0].waitEnable = FALSE;
    spiParams.spiHWCfgData.delay.c2TDelay = 100;
    spiParams.spiHWCfgData.delay.t2CDelay = 100;

    The following figure shows the o-scope capture of the start of the transfer:


    Magenta = clk; Yellow = cs; Green = mosi.

    But the CS to CLK delay isn't working right. In fact, it doesn't matter to what value I set
    spiParams
    .spiHWCfgData.delay.c2TDelay, the delay is the same as what is shown above,
    about 40 us or 40 clock periods. When I halt execution and look at the memory map it,
    has the following entry for SPIPC0: 0x64640000. This is what I expect for the setting above
    in spiParams (e.g. 100). I then change the values to 0, and re-check the memory map. The value of SPIPC0 is now 0,
    but the waveform on the o-scope is the same. So I can't change this timing. I think this is a problem in the driver,
    can you verify please? According to the SPI User's Guide, I should be able to get the delay to about 2 us, you agree?

    Here are all the values in the SP1 MMRs:
    0x01E12000 :00000001 00000003
    0x01E12008 :00000000 0000035F
    0x01E12010 :01000000 01010E01
    0x01E12018 :00000000 01000B01
    0x01E12020 :00000000 00000000
    0x01E12028 :00000000 00000000
    0x01E12030 :01010F01 00000000
    0x01E12038 :00000000 00000000
    0x01E12040 :80000000 80000000
    0x01E12048 :00000000 00000001
    0x01E12050 :00029508 00009500
    0x01E12058 :00009500 00009500
    0x01E12060 :00000000 00000000

    Mike
  • I tried one other thing.  I set up the program to not use EDMA by changing the value of the field "opMode" from Spi_OpMode_DMAINTERRUPT to Spi_OpMode_INTERRUPT.  This made the c2T delay 1.7us, much less than when using EDMA.  And it sill doesn't matter what I set the delay field values, the delay is still the same.  It also doesn't matter what the clock setting is for the SPI.  In DMA mode, the delay is 40us; in CPU interrupt mode, the delay is 1.7us.

    Mike

  • Hi,

    I got the same Problem yesterday and by my experiments I think it has to do with the CSHOLD value in the statement

    Spi_DataParam       dataparam;

     dataparam.flags        = Spi_CSHOLD;

    With this settings I measure a hughe latency between CS-Signal and clock of roughly 5µs. And this is independent of the delay values. If I use

     dataparam.flags        = 0x0;

    I can setup the delay as I wish with the delay values.

    Unfortunately I have to use dataparam.flags        = Spi_CSHOLD; because of my SPI device.

    I hink I waste a lot of time with this latency of ~5µs at the beginning and at the end of the data transfer (10µs together). Is there a possibility to reduce this latency? What is the reason Mike gets 1.7µs and I get 5µs? Any idea?

    Jens

     

     

  • Jens,

    I will re look at this over the next few days.  I don't know that I experimented with flags field.  Couple quick questions for you:

    • What is the clock freq you are using when you measure 5 us latency?
    • are you using EDMA driver with this or CPU interrupt?

    It'd be nice if someone from TI could help verify some of this...

    Mike

  • Hi Mike,

    and thanks for reply,

    I worked with a spi clock frequency of 30MHz in my experiment and used CPU interrupt.

    The influence of CSHOLD can easiely be tested with the example privided by TI.

    It would be very nice to get some feedback from TI.

    Jens

  • Jens,

    I was able to verify your results with the flags field.  When I set it to 0, the C2T and T2C delays are behaving as expected.  The interesting thing is that there is no description in the driver code for setting this value to 0.  The driver code has three #defines used in conjunction with this field:

    #define Spi_CSHOLD ((0x1u))
    #define Spi_GPIO_CS  (0x2u)
    #define Spi_CSHOLD_FOR_MULTI_TRANSCEIVE ((0x2u))
    Obviously, TI has a problem since the last 2 have the same value.  The driver code never checks for a 0 value in this field.  Code gets
     executed as the "else" part of something like:
    if ((Spi_GPIO_CS != (flags & Spi_GPIO_CS)))
    My guess is that there is a bug in the SPI device and that the delays only work when the CSHOLD bit in the SPIDAT1 register is 0.  
    We would need TI to verify this and suggest a workaround.

    The reason why my latency is shorter is possibly due to the location of the code. If you are just running the straight example,
    I think it executes from SDRAM. My program is executing directly from L2 (on-chip) memory. You could try moving your code
     from SDRAM to L2 and see if that decreases latency.

    Mike

    
    
  • Mike,

    you are right: the lantency strongly depents on the memory where I put the code to. Thanks for the input. With most of the code in intern memory I get a delay between CS and Clock of about 1,8µs. Still much to much but beter than 5µs [;)]

    But still we both have the problem with CSHOLD and not beeing able to set the timing of the CS signal.

    Maybe we will get some help or at least an answer from someone at TI......

    Best regards

    Jens

     

  • Hi Mike, Jens,

    I'm investigating it.

  • Let me see if I can help a bit.  I have used the TI SPI peripheral on devices other than C6747 so it should be mostly applicable.  I have not used or inspected the SPI driver though to see exactly what it's doing.  Ok, now that I've put out my disclaimer...  [:P]

    The CSHOLD bit is used to tell the hardware whether or not it should leave the chip select pin asserted between transfers.  For example, if you wanted to transfer multiple words of data and needed the chip select asserted for the duration of the entire transfer you would set CSHOLD=1, write your multiple words of data, and then write CSHOLD=0 so that it de-asserts when you're finished.  So again, I'm not sure how the driver is utilizing the CSHOLD bit.  However, if it's being set and cleared around the transfer then the delay you're seeing is probably just the delay between writes to the SPIDAT1 register.  The delay could potentially be reduced even more if a 32-bit write was performed such that you simultaneously wrote to both the CSHOLD bit and the TXDATA field all at once.  That would enable you to set the bit on the first transfer and clear it on the last transfer (if that's what you want).  Otherwise leave CSHOLD=0 and allow the timing to be dictated by C2T and T2CDELAY.

    FYI, Section 2.5.1.1 makes the following note:

    "The previous value of the CSHOLD bit in the SPI transmit data register (SPIDAT1) must be cleared to 0
    for the C2T delay to be enabled."

    Also, Section 2.5.1.2 makes a similar statement:

    "The current value of the CSHOLD bit in the SPI transmit data register (SPIDAT1) must be cleared to 0 for
    T2C delay to be enabled."

    I hope that helps more than confuses!  [:H]

     

  • Mike,

    The SPI user guide is not clear at all when it comes to the CSDEF and CSNR bit fields.  Each bit in those bit fields is supposed to correspond to a CS pin in the case multiple chip selects were supported by the DSP.  The C6747 SPI however only supports one CS pin, so really only bit 0 of these bit fields applies to your case. 

    CSDEF defines the state of the CS pin when there are no transfers: 0 means set the pin low and 1 means set the pin high .  CSNR defines the state of the CS pin during a transfer: 0 means set the pin low and 1 means set the pin high.  If you want the SPI.CS0 pin to be active low, you want to have CSDEF[0] = 1 and CSNR[0] = 0.  All the other bits in CSDEF and CSNR are don't cares in this case.

    It looks like you are pointing out valid shortcomings with the SPI driver and there are people looking at that.  I am not familiar with the driver myself.  However, I believe the driver allows you to use the SPI.CS pin and GPIO as a chip select pin.  The information I provided, as well as the information in the SPI user guide, refers to the case in which you are using SPI.CS0 as the chip select.

    Hope this helps clarify some things.

    Gus

  • Mike,

    Just to add to what Brad already said...

    As soon as you set CSHOLD to 0, the SPI will immediately drive the SPI.CS pin to its active state as defined in CSNR.  If CSNR[0] = 0, then the SPI.CS0 pin will be driven low and if CSNR[0] = 1, the SPI.CS0 pin will be set high.  Furthermore, as Brad mentioned, as long as CSHOLD = 1, the SPI.CS will remain in its active state, and the delays will be ignored.

    I am certain that the microsecond delay shown in the plots at the beginning of this thread were due to the normal progression of the driver.  Meaning, at some point, as the driver started configuring the SPI, it wrote to SPIDAT1.CSHOLD = 1, and then some time later it initiated the SPI data transfer.  The delay between those two driver actions is what lead to the CS low to clock active delay shown in the scope plots.  At some point the driver must have also cleared CSHOLD and hence the CS pin was driven high.

    As you already saw, if you keep CSHOLD = 0, the delays will behave as expected. 

    Gus

  • One thing to add that Gus pointed out to me is that the C2T delay (and the others) is relative to the SPI module clock (PRESCALE not applied yet), not the serial clock.

  • Hi all,

    and thanks for the answers.

    I played around with the spi a little more and here is what I found:

    if I do not use the BIOS driver and do the SPI programming "by hand" I get what I want. I can use CSHold = 1 and can set up the delay times as I want. That means in my case delays of ~200ns between CS and CLK or last CLK and CS. 

    If I use the driver of the BIOS, I get delays of ~1.7µs at the beginning and the end of the transfer. This reduces the dater transfer rate to much for me.

    This indicates to me, that the CS-Signal is not generated by the SPI hardware but from the driver. I think this is done to be able to use a GPIO - pin for CS.

    Since I will have to use more than 2 CS for each SPI interface, I think I will have to do the programming by hand and not use the driver.

    Regards,

    Jens

     

  • Jens,

    It is possible to get the driver to behave as your "by hand" experiment.  It apparently is not easy to figure out how by looking at the driver code itself.  I've asked the driver developers to update the driver comments/documentation to provide more clarity on this front.

    However, since you do need more than two CS pins, you do need to use the GPIO function of the driver.  If you do not need the delays, then I would recommend you leave CSHOLD = 1 and set the delays to zero.

  • Hi all,

    as far as I understood the driver, it is only possible to choose one GPIO pin as CS-signal for a spi interface. So the driver let me choose between 2 CS-signals. I will need something like 4 or 5 CS-signals on one SPI interface. I think the driver will not be able to handle this ( as said: as far as I understood the driver).

    But it is good to hear that the specialists at TI will have a look at the driver. I would prever to use the driver if I can.

    Jens

  • Jens,

    If I understand your post correctly, I think there is some misunderstanding about the CS operation:

    Jens H. said:

    as far as I understood the driver, it is only possible to choose one GPIO pin as CS-signal for a spi interface. So the driver let me choose between 2 CS-signals. I will need something like 4 or 5 CS-signals on one SPI interface. I think the driver will not be able to handle this ( as said: as far as I understood the driver).

    There is only ONE CS pin for the SPI whose timing can be controlled by the C2T delay, parameters, etc.  The only thing the driver does is allow you to use one other GPIO pin to imitate the CS functionality.  If you need multiple CS signals that all have very short (< 100 ns?) delays between CS active and active clock/data, you may need to rethink the design.  Regarding multiple CS singles, all the driver does is insert extra code that sets a GPIO active/inactive before and after writes to a particular SPI device.  This is different than the CS pin of the SPI whose timing is controlled by the device silicon. 

    I tested this and there is not much difference between surrounding your SPI control APIs with your own function/marco to control a GPIO CS and using the driver.  For example,

          assert_low_SPI1_ENA();
    GIO_write(spiHandle, &dataparam, &size);
    assert_high_SPI1_ENA();

    In this case, I configured the SPI1 Enable pin as a GPIO and am merely toggling it's logic level when performing writes (or reads).  The SPI driver actually pulls in the GPIO library for its "GPIO as CS" functionality.  So it takes up a lot of memory (if that's even a concern for you).  You may want to consider using EDMA3 with the SPI driver and queing up your accesses to the different devices.  This is the most efficient use of CPU resources if speed is critical in your application.  But I believe it will require you to modify the SPI and possibly EDMA3 drivers to reduce latency in the CS active to Clock/Data active timings.

    Mike

  • Jens,

    The current version of the driver only  allows you to use one GPIO pin as CS.  The next release will support any number you desire.  The application will just have to pass the GPIO number to use on each submit request. 

    Btw, do look at Mike's next post.  He is right on wrt to the tradeoffs when using the GPIO feature of the SPI driver.

    Gus