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.

SPI1 Chip Select not working as expected (CCSv5.1)

Guru 15580 points
Other Parts Discussed in Thread: OMAP-L138

I am trying to use SPI1 and CS1 on my OMAP-L138 board but am having trouble properly configuring the chip select 1 registers (I am using CCSv5.1.0.07001). Here is my SPI config.

SPIGCR1=Master

 

SPIPC0 0x01010E02 Memory Mapped Register: Pin Control Register 0

_RESV_1 ******************** Reserved

SOMIFUN 0x1 - SPI SOMI function

SIMOFUN 0x1 - SPI SIMO function

CLKFUN 0x1 - SPI CLK function

ENAFUN 0x0 - GPIO ENA function

SCS0FUN7 0x0 - GPIO SCS7 function

SCS0FUN6 0x0 - GPIO SCS6 function

SCS0FUN5 0x0 - GPIO SCS5 function

SCS0FUN4 0x0 - GPIO SCS4 function

SCS0FUN3 0x0 - GPIO SCS3 function

SCS0FUN2 0x0 - GPIO SCS2 function

SCS0FUN1 0x1 - SPI SCS1 function

SCS0FUN0 0x0 - GPIO SCS0 function

Note that when step through the code and set SCS0FUN1=0x1 I can see the SPI1_SCSn_1 line toggle high, which is what I would expect. However, when I set SPIDAT1.CSNR=0, the SPI1_SCSn_1 line goes low, which I guess is OK. But when I set SPIDEF.CSDEF1=1 I do *not* see the SPI1_SCSn_1 line toggle back to a high state. The SPI1_SCSn_1 then stays low and never toggles during data transmissions.

Also, I am confused by the SPIDEF.CSDEFn register values shown in the Registers View of CCS. The only CSDEF register shown is CSDEF0. Why are the others (CSDEF1 - CSDEF7) not showing up? I cannot see the correct value that I am trying to set in CSDEF1....? As shown below, CSDEF0 is low (which is what I set it to), but where is CSDEF1 and what is its value?

 

SPIDEF 0x00000010 Memory Mapped Register: Default Chip select Regsiter

_RESV_1 ******************************* Reserved

CSDEF0 0x0 - LOW Chip select default pattern

Thx,

MikeH

 

 

 

 

  • Not quite sure of what you are trying to do. I'll throw out some points. Ignore the points you already know.

    The CS line is automatically controlled by the SPI controller. It will assert the CS line during a transmission and deassert when idle.

    The CS line may be setup to stay asserted between two closely spaced words. See this register.
    SPIDAT1.CSHOLD
    The inter-word time threshold is set in T2CDELAY. Otherwise the CS is deasserted between words.

    The polarity of the CS line are controlled by these registers. They should set oppositely.
    SPIDAT1.CSNR=0xFF
    SPIDEF.CSDEF=0x00
    or
    SPIDAT1.CSNR=0x00
    SPIDEF.CSDEF=0xFF
    I have idea why TI would allow you to set them to the same value.

    You have to keep a shadow copy of SPIDAT1 around when you send data. I still new to this as well. Note quite sure when I can use SPIDAT0 vs SPIDAT1.

    If possible, I'd suggest enabling all the CS lines and use the PINMUX to connect to the external pins.
    SPIPC0.SCS0FUN=0xFF
    In theory, there should be no harm? Takes all the guess work out during the initial debugging.

  • Hi Norman,

    Norman Wong said:
    Not quite sure of what you are trying to do.

    I am trying to use a single SPI port (SPI1) to talk to two different slave devices. CS0 is assigned to the SPI Flash, and CS1 is tied to a slave spi port on another chip (Chip2).

    Norman Wong said:
    The CS line is automatically controlled by the SPI controller. It will assert the CS line during a transmission and deassert when idle.

    Check.

    Norman Wong said:
    The CS line may be setup to stay asserted between two closely spaced words. See this register.
    SPIDAT1.CSHOLD
    The inter-word time threshold is set in T2CDELAY. Otherwise the CS is deasserted between words.

    Check, check.

    Norman Wong said:
    The polarity of the CS line are controlled by these registers. They should set oppositely.
    SPIDAT1.CSNR=0xFF
    SPIDEF.CSDEF=0x00
    or
    SPIDAT1.CSNR=0x00
    SPIDEF.CSDEF=0xFF
    I have idea why TI would allow you to set them to the same value.

    Check. Agreed.

    Norman Wong said:
    You have to keep a shadow copy of SPIDAT1 around when you send data.

    Or you can use the Logic PD BSL code which does this for you. It also keeps track of when/if the CS needs to be held until the next transmission.

    Norman Wong said:
    Note quite sure when I can use SPIDAT0 vs SPIDAT1.

    SPIDAT0 simply sends the lower 16 bits out the SPI port without changing any options. SPIDAT1 allows you to change various config parameters (upper 16 bits) with each transaction, if needed.

    Norman Wong said:
    If possible, I'd suggest enabling all the CS lines and use the PINMUX to connect to the external pins.
    SPIPC0.SCS0FUN=0xFF
    In theory, there should be no harm? Takes all the guess work out during the initial debugging.

    Not a bad idea.

    I guess the crux of my question is "how do I dynamically talk to two different slave devices from a single SPI port?". It appears that the answer is " you need to dynamically reconfigure the PINMUX that connects the desired CS line to the pin connected to the slave". Which begs the additional question, "If all CSn lines were enabled, and all CSn lines were connected to external devices, would *all* CS lines toggle during a single transmission (ie, you have no way other than PINMUX to select which CSn line gets through to its associated slave)? Seems like a poor design. You should be able to put a CS byte in, for example, the upper bits of SPIDAT1, to activate any given CSn line.

    Thanks for the thoughts.

    MikeH

     

  • Ahh. I think I understand. I would guess that you could set the specific SPIPC0.SCS0FUN[n] bit when selecting a slave device. The question is what is the level of the pin when the pin is a GPIO and not SCS. I think you need to setup the pin as GPIO out with the desired deassert level, eg.

    SPIPC1.SCS0DIR[n] = 1 for output
    SPIPC4.SCS0SET[n] = 1 for deassert is high
    SPIPC5.SCS0CLR[n] = 1 for deassert is low

    Should only have to do that once for each slave device on initialization. I was suggesting enabling all CS as a means of debug. Doesn't work if you actually have different devices attached to each CS. Misunderstood.

  • Hi MikeH, I think you will find StarterWare useful: http://software-dl.ti.com/dsps/dsps_public_sw/c6000/web/omapl138_starterware/latest/index_FDS.html

    In case you aren't familiar, this is a no-OS driver for ARM and DSP which has SPI examples and configurations.

    I would recommend you use this code, which provides more flexibility than then Logic BSL.

    Jeff

  • Jeff,

    Good to hear from you again!

    Thanks for the pointer to StarterWare. Looks interesting. However, it has the same problem as the Logic BSL code. It sets up the SPI port for a *single* slave device (see SetUpSPI line 365 "    SPIDat1Config(SOC_SPI_1_REGS, (SPI_CSHOLD | SPI_DATA_FORMAT0), cs);". My application needs to dynamically switch from one slave device to another. I have successfully added a spi_cs_sel enum to the spi_config_t structure in the Logic BSL that lets me specify which CS line I want to use for the SPI transmission for *each* SPI transmission. It works quite well.

    Again, the problem I had gets back to our discussion of "crappy" documentation. As Norman can attest (see earlier posts), it is NOT clear from the SPI docs how to configure and use the SPI port to communicate with more than one slave device. I guess this exercise is left up to the student....:)

    I'm now off resurrecting my efforts on BOOTing the OMAP-L138 using an AISgen'd file. I'm sure I'll have more questions for you in the near future. Stay tuned....:). Thanks!

     

  • Good to hear. I thought you were still stuck at the part where the CS line wasn't toggling at all during operation, but I guess you got that part figured out too.

    We've added a lot more documentation since you last attempted to boot, so make sure to check it out here: http://processors.wiki.ti.com/index.php/OMAP-L138_Bootloader

    Thanks

    Jeff

  • Jeff,

    jc-ti said:
    I thought you were still stuck at the part where the CS line wasn't toggling at all during operation

    No. That was a combination of PINMUX and Logic PD SOM issues (they changed the pinout for CS0). I now have SPIFlash on CS0 and my "other" chip on CS1 independently addressable.

    jc-ti said:
    We've added a lot more documentation since you last attempted to boot,

    Wow. Very impressive stuff! Gee, I feel like I may have had a hand in this.....:). Getting very close to booting my fully working application(s)! 

    Thanks again for the help!

     

     

  • MikeH,

    Here are some answers and tips to some of your questions:

    "Also, I am confused by the SPIDEF.CSDEFn register values shown in the Registers View of CCS. The only CSDEF register shown is CSDEF0. Why are the others (CSDEF1 - CSDEF7) not showing up?"

    There is only a single SPIDEF register and the CSDEF[7:0] bits enable you to select what the state of the SPI_SCS[7:0] pins be when no transmissions are performed. (typically you want this to be set to '1', since the CS is an active low signal, you don't want other CS pins toggling when you talk to a particular CS pin (which you can individually select in the SPIDAT1 register bits CSNR[7:0] for each of your transfers.

    SPIPC0.SCS0FUN[7:0] bits are used to select a pin from being a functional or GPIO pin, so in your situation you want this value to be a '0x3' to enable CS0/CS1 as CS functional for the SPI instance that you are using (becareful here not to confuse SPI0 and SPI1 instantiations of the device as they have their own CSx signals).

    When talking to 2 slave devices (like your case), I would configure the SPIDEF.CSDEF=0x3.

    Then select the individual CSx that you want to talk to in the SPIDAT1.CSNR bits (for each word write, keep in mind that if you need to hold the CSx during consecutive writes, you can make use of the CSHOLD bit "which stay active, until a control field with new data and control information is loaded into SPIDAT1"  or you can manually turn it off on your last tranfer if you want to, but by definition when you change teh DFSEL to select a different CS pin this should automatically turn the CSHOLD condition of the previous write.

    You should not need to do this type of behavior via the PINMUX, in fact just make sure that the PINMUX allows you to have the CS pins.  

    regards,

    miguel

     

  • Miguel,

    Miguel A. Alanis said:
    When talking to 2 slave devices (like your case), I would configure the SPIDEF.CSDEF=0x3.

    Miguel A. Alanis said:
    Then select the individual CSx that you want to talk to in the SPIDAT1.CSNR bits

    This is exactly what I ended up doing. 

    These "tips" need to be part of your documentation. Controlling multiple slave devices is a very common application.

     

  • They are part of the SPIDEF/SPIDAT register description documentation.  I called them 'tips' since I provided the actual value for you for your specific use case.

    regards,

    miguel