cancel
Showing results for 
Search instead for 
Did you mean: 

Is there a way to make SPI NSS hardware output produce a steady state low without NSSP during SPI transaction without manual config and toggle of CSN GPIO?

EMarv.1
Associate II

Interface of STM32L476RG to TI CC1200 SPI. Using MCU registers with NSS produces short acceptable CSN to clock start interval but I cannot get rid of the high pulse between frames which causes the CC1200 to malfunction. Manually configuring and toggling The CSN GPIO produces an unacceptably long delay between start of CSN low and start of SPI clock pulses but transactions work. My project requires optimized SPI transaction speed as there are many seperate 2 byte transactions that need to take place in as short a duration as possible. Inserting the CSN toggle into the HAL_SPI_TransmitReceive_IT or HAL_SPI_TransmitReceive functions shortens the duration between CSN-clock and visa versa but still adds significantly longer interval than the HAL NSS hardware output. 2 byte transactions are significantly longer than necessary.

Section 42.4.5 of the HAL STM32l476 user manual states the following-

“Hardware NSS management (SSM = 0): in this case, there are two possible configurations. The configuration used depends on the NSS output configuration (SSOE bit in register SPIx_CR1).

– NSS output enable (SSM=0,SSOE = 1): this configuration is only used when the MCU is set as master. The NSS pin is managed by the hardware. The NSS signal is driven low as soon as the SPI is enabled in master mode (SPE=1), and is kept low until the SPI is disabled (SPE =0). A pulse can be generated between continuous communications if NSS pulse mode is activated (NSSP=1). The SPI cannot work in multimaster configuration with this NSS setting.

– NSS output disable (SSM=0, SSOE = 0): if the microcontroller is acting as the master on the bus, this configuration allows multimaster capability. If the NSS pin is pulled low in this mode, the SPI enters master mode fault state and the device is automatically reconfigured in slave mode. In slave mode, the NSS pin works as a standard “chip select�? input and the slave is selected while NSS line is at low level.�?

Above implies that the below initialization will produce a NSS/CSN low with a pulse between frames. Which it does.

hspi2.Instance = SPI2;

hspi2.Init.Mode = SPI_MODE_MASTER;

hspi2.Init.Direction = SPI_DIRECTION_2LINES;

hspi2.Init.DataSize = SPI_DATASIZE_8BIT;

hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;

hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;

hspi2.Init.NSS = SPI_NSS_HARD_OUTPUT;

hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;

hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;

hspi2.Init.TIMode = SPI_TIMODE_DISABLE;

hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

hspi2.Init.CRCPolynomial = 7;

hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;

hspi2.Init.NSSPMode = SPI_NSS_PULSE_ENABLED;

Registers after Init:

CR1=0x11c

CR2=0x170c

NSS hardware output with NSSP enabled

0693W00000JOD90QAH.png

And implies that the below initialization will produce a NSS/CSN low without a pulse between frames. Which it does not.

hspi2.Instance = SPI2;

hspi2.Init.Mode = SPI_MODE_MASTER;

hspi2.Init.Direction = SPI_DIRECTION_2LINES;

hspi2.Init.DataSize = SPI_DATASIZE_8BIT;

hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;

hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;

hspi2.Init.NSS = SPI_NSS_HARD_OUTPUT;

hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;

hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;

hspi2.Init.TIMode = SPI_TIMODE_DISABLE;

hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

hspi2.Init.CRCPolynomial = 7;

hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;

hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLED;

Registers after Init:

CR1=0x11c

CR2=0x1704

NSS hardware output with NSSP disabled

0693W00000JOD9UQAX.png Manual Toggle

0693W00000JOD9yQAH.png 

1 ACCEPTED SOLUTION

Accepted Solutions

Just to be clear, I think you are saying that whether I use code within the SPI_transmit_receive function to manually config and toggle the CS GPIO or enable/disable the peripheral- the interval between CS low/high and clock pulse start/stop will likely end up ~ the same. So might as well leave SPE alone, disable NSS and use manual GPIO output. Correct?

View solution in original post

8 REPLIES 8
TDK
Guru

> Is there a way to make SPI NSS hardware output produce a steady state low without NSSP during SPI transaction without manual config and toggle of CSN GPIO?

No, not on that chip. You can do so on the STM32H7.

Your examples appear to be working exactly how the RM states, as far as I can tell. CS is low as long as the peripheral is enabled (not at long as it's active).

If you feel a post has answered your question, please click "Accept as Solution".

> CS is low as long as the peripheral is enabled (not at long as it's active).

Interesting that when NSSP is enabled CS goes low within a few hundred nanoseconds of clock pulse start. Yet, the peripheral is enabled long before that. Oh, maybe what you and RM are leading me to is that the high I am seeing before the first frame is the NSSP going low between frames??

Would enabling and disabling (SPE=1 and SPE=0) emediatly before/after SPI transaction be a possible way to shorten CS- start/end of clock pulse interval?

Disabling/enabling the peripheral will give you the desired CS behavior but at that point you’re effectively forcing it to act like a GPIO pin. Hence the common recommendation to initialize and use it as such.
If you feel a post has answered your question, please click "Accept as Solution".

Just to be clear, I think you are saying that whether I use code within the SPI_transmit_receive function to manually config and toggle the CS GPIO or enable/disable the peripheral- the interval between CS low/high and clock pulse start/stop will likely end up ~ the same. So might as well leave SPE alone, disable NSS and use manual GPIO output. Correct?

Yes, precisely.
If you need very tight timing or fast code, writing your own SPI driver is going to be necessary vs relying on HAL.
Although, typical there is not a constraint on the time between CS low and the first clock pulse, so it’s typically not an issue.
If you feel a post has answered your question, please click "Accept as Solution".

NSS, when SPI is master (and NSS is not software and output enable and not pulse mode), is *controlled* by SPI while SPE=1, and is set to 0 as soon as the first transmission starts. In other words, you could use it for framing by clearing SPE after the frame, but that *threestates* the pin, which is a surprise for most users.

The main challenge is to time the end of packet properly.. In some applications, it may not be the best idea to rely on BSY flag.

JW

Thank you for confirming. Just trying to avoid custom code where possible and appreciate you confirming that there was not a trick I could use to make HAL driver function the way CC1200 needs no NSSP CS and short. You're right, normally I would not be concerned about an extra ~10us per transaction. However, this is for a fast FHSS system so between each hop or TX/RX 10 to 15 individual 1 byte registers must be set plus FIFO buffer or read write. FIFO efficeincy% not effected much due to large number of bytes xfered but those short packets made 10 times longer will cause me to loose just enough effeciency to have to increase RX BW just a little for desired throughput causing a slight loss in RX sensitivity which I am trying to avoid.

Much appreciated. The links you provided in your answer have helped me avoid the pitfalls mentioned. based on some initial testing/mod of HAL SPI driver, it looks like using manual GPIO and optimizing start of CS low is not much of an issue for transaction startup and using HAL_SPI_STATE_BUSY_RX with custom delay to account for shift register will work to optimize termination. Thanks again for the extra forsight/detail.