Using SPI Chip Select Pin on C674x/OMAP-L1x
This Wiki article was created to provide some clarification on the operation of the chip select pin(s) on OMAP-L137/C674x/AM1707 devices.
The SPI peripheral contains several pins which allow it to interface to slave and master devices. The number of SPI_CS pins varies among different OMAP-L137/C6747/AM1707 devices. Some devices only support a single SPI_CS pin per SPI peripheral and some support multiple CS pins.
|| Function (Master)|
|| Slave in, master out|
|| Slave out, master in|
|| Serial output clock in master mode, input clock in slave mode|
|| Slave ready pin; input in master mode, output in slave mode|
|| Chip select; output in master mode, input in slave mode|
When the SPI is used as a master, the SPI_CS pin(s) are used as outputs. Normally, a user would connect the SPI_CS pins to different slaves. The number of SPI_CS pins needed depends on the number of slaves in the system.
The SPI allows you to configure the following about the SPI_CS pins:
- Chip select polarity: The chip select can be configured as active-low or active-high.
- Chip select hold: You can force the chip select to remain active during consecutive data transfers.
- Chip select setup time (aka C2TDELAY): You can program the SPI to delay the first SPI clock after SPI_CS is activated. The delay is specified in SPI module clock cycles.
- Chip select hold time (aka T2CDELAY): You can program the SPI to delay the deactivation of the SPI_CS pin after the last SPI clock. The delay is specified in SPI module clock cycles.
Configuring SPI_CS Polarity
There is no single bit in the SPI registers which allows you specify the polarity of the SPI_CS pin(s). However, there are two register fields that allow you to specify the state of the SPI_CS pins when a data transfer is active and when there is no data transfer. The SPIDEF.CSDEF bits define the state of the SPI CS pins when there is no data transfer ongoing: 0 means set the pin low and 1 means set the pin high. Similarly, the SPIDAT1.CSNR bits define the state of the SPI CS pins when there is a transfer ongoing: 0 means set the pin low and 1 means set the pin high. Each bit in CSNR and CSDEF corresponds to a CS pin supported on the device. For example, CSNR corresponds to SPI_CS0, CSNR to SPI_CS1, etc. In the case your device only supports one CS pin, only bit 0 of these bit fields applies. If you want the SPI.CS0 pin to be active low, you want to have CSDEF = 1 and CSNR = 0.
Using The Chip Select Hold Feature
Some slave devices require that the chip select pin be kept low for multiple data transfers. You can force the SPI to hold the chip select active during consecutive data transfers through the use of the SPIDAT1.CSHOLD bit. As soon as you set CSHOLD to 1, the SPI will immediately drive the SPI.CS pin to its active state as defined in CSNR. If CSNR = 0, then the SPI.CS0 pin will be driven low and if CSNR = 1, the SPI.CS0 pin will be set high. As long as CSHOLD = 1, the SPI.CS will remain in its active state, and the delays discussed in the next sections will be ignored. You must clear CSHOLD to bring SPI.CS to its inactive state. If there are no active transfers, the CS pin will be deactivated immediately, otherwise, it will remain active until the end of the transfer.
Programming Setup (C2TDELAY) and Hold Time (T2CDELAY)
You can program the SPI to delay the start of the first clock from the time the chip select pin is activated. The delay is specified in SPI module clock cycles and is programmed through the SPIDELAY.C2TDELAY bits. The SPI module clock is sourced by the device PLL. Note that this is different from the SPI serial clock (SPI_CLK). The SPI serial clock is derived from the SPI module clock. The relation between the SPI module clock and the SPI serial clock is specified using the SPIFMT.PRESCALE bits.
SPI_CLK frequency = SPI module clock / [SPIFMT.PRESCALE + 1]
Keep in mind that for large values of PRESCALE the effect of C2TDELAY and T2CDELAY will be minimized as the SPI module clock frequency willl be much larger than the SPI serial clock frequency.
NOTE: The C2TDELAY and T2CDELAY fields are ignored if CSHOLD = 1.
Interfacing To Multiple Slaves
Your end design may require you to interface to multiple SPI slaves. If your device supports multiple SPI chip select inputs, you can connect a different chip select to each slave. If your device only supports a single SPI chip select or if pin mux conflicts don't allow you to use a SPI chip select, you can use device GPIOs as chip selects.
However, when using the GPIO approach care must be taken such that the slave CS pin is not deactivated in the middle of a SPI transfer. SPI transfers are not done when EDMA or CPU writes the last character to the SPI transmit registe since the SPI still has to shift out the data! Often the SPI serial clock will be much slower than the EDMA or CPU clock. Disabling the CS pin in the middle of a transfer may lead to undesired results.
It is not be practical to use SW delays to get around this issue since the size of the delay depends on too many variables: frequency of SPI serial clock, data collisions within the chip bus infrastructure, etc. A good thing is that SPI always shifts data in as it shifts data out, so one possible workaround is to program the CPU to wait until the receive flag is set on the last transfer before the CS pin is deactivated.
If EDMA is used, working around this issue is a bit trickier, but still doable. A dummy receive channel can be setup to read data from the SPI. On the last transfer the channel can be setup to trigger an interrupt to the CPU indicating that the GPIO pin can be safely disabled.
In slave mode, you can only use one chip select pin, the other chip select pins must not be configured for SPI functionality. You can disable the SPI function of unused chip select pins through the SPIPC0.SCS0FUN bits. Each bit in SCS0FUN corresponds to a chip select pin. For example, SCS0FUN corresponds to SPI_CS0, SCS0FUN corresponds to SPI_CS1, etc. Setting SCS0FUN = 0 configures the chip select pin as a GPIO pin and setting it to 0 configures the pin as a SPI pin. Note that the GPIO function embedded in the SPI is different from the GPIO function supported at the chip level. The PINMUX registers of the chip dictate the ultimate function of the pin.
The polarity of the pin is fixed in slave mode as active-low since you must set CSDEF = 1. This also means that you must set CSNR = 0.