cancel
Showing results for 
Search instead for 
Did you mean: 

STM32(G4) SPI Chip-Select: Set low after MOSI is High and does not stay low(Pulses)

Hello,

at the moment I try to get a Sensor working, I use the HAL_SPI_TransmitReceive_IT and HAL_SPI_TransmitReceive_DMA functions.:

0693W00000HotmmQAB.png 

The settings I used are:

  • Mode: Full Duplex Master
  • NSS: Hardware Output; has Low-Enables Slave-Select.
  • Frame-Format: Motorola
  • Data-Size: 8 Bits
  • First Bit: MSB First
  • CPOL: 0 = Low ; Clock Polarity starts low,
  • CPHA: 0= 1st Edge ; Clock Phase is the first edge

I have discovered two things that I did not expect:

  1. The nSS(negative Chip-Select) is active after the MOSI, how can that be changed, so I get a longer CS?
  2. The nSS(negative Chip-Select) does not stay low, how can I change it to stay long for the duration of the entire transfer?

0693W00000HotoOQAR.png0693W00000Hotp2QAB.png 

If I change ti TI mode the Signals look like the following diagram, which is not matching the specification either.

0693W00000Hotq0QAB.png 

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

Can someone give some suggestions on how to fix the issue or the limitations of the SPI-Controller of the STM32(G4)?

Thanks a lot.

Best Regars, Seppeltronics

8 REPLIES 8
TDK
Guru

NSS is not a CS pin on the master side. It is an awkward hardware implementation.

Change the pin to a GPIO output and manage it manually. Set it low before a transfer and high after.

The reason it's pulsing now is probably because you have TI mode enabled.

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

Hello @TDK​ ,

NSS should be "Negative Slave Select", or in other words "negative Chip-Select". I guess by awkward you mean it does not work properly? Do you know more Details?

I use DMA, so I may not immediatly be in the "HAL_SPI_TxRxCpltCallback", ...

The Pictures shown is Motorola-Mode, maybe it is putting the CS to High because it is 8-Bit Mode?:

0693W00000HotoOQAR.png 

0693W00000Hotp2QAB.png 

Thanks a lot for your reply.

Best Regards, Seppeltronics

TDK
Guru

I mean that it does not work the way you're expecting it to work, assuming you want it to go low just prior to the transaction and high just after. The details are in the reference manual, but the short answer is that it is low as long as the SPI is enabled (barring TI mode, which has the pulse on the first bit). And the HAL library generally doesn't disable the peripheral between HAL_SPI_* calls.

0693W00000HouBmQAJ.png 

I guess I could have done better at directly addressing your questions:

> The nSS(negative Chip-Select) is active after the MOSI, how can that be changed, so I get a longer CS?

You really can't in general. However, MOSI changing states while NSS is high has no effect on the transfer and is perfectly acceptable.

> The nSS(negative Chip-Select) does not stay low, how can I change it to stay long for the duration of the entire transfer?

You likely have TI mode enabled. However, managing CS as a GPIO pin is the better option.

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

What you show in the first screenshot is NSS Pulse Mode (it is better to use terms from RM rather than any Cube lingo, not everybody uses Cube).

NSS is mostly unusable as automatic framing. As TDK said, set it to Out and handle "manually".

JW

gdori.1
Associate II

"...it [NSS pin] is low as long as the SPI is enabled"

That is so dumb!

I spent half a day trying to figure it out. First there was no real description of what "NSS" means in the HAL manual. I finally figured out that (I assume) it means *SS (low active Slave Select). I do understand that SPI is a "de facto standard" which means that it is only, really, a suggestion, and can be changed. But in all previous implementations, I've seen it as a low going chip select for each data frame, then high in between frames. That's what all my slave SPI devices expect. This is the first time I have not seen it implemented that way. Doing it manually (because ST chips do not do it automatically) is silly as fair as I'm concerned.

I think I'll move on to another vendor.

TDK
Guru

The reference manual is the proper place to understand how the chips work in detail. On the H7 (and possibly other newer families), the NSS pin can be used as a single chip CS signal.

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

I have the same issues as with HAL_SPI_TransmitReceive_IT(). In polling mode everything works fine, I handle the NSS, as mentioned

 HAL_GPIO_WritePin(GPIOA, SPI1_NSS_Pin, GPIO_PIN_RESET);

 data = HAL_SPI_TransmitReceive_IT(&hspi1, tx_data, rx_data, 2);

 HAL_GPIO_WritePin(GPIOA, SPI1_NSS_Pin, GPIO_PIN_SET);

However, in interrupt mode NSS is pulses in and not like it pulses in TI_MODE after every byte. Also, I do not have configured in TI_MODE.

0693W00000bh8MJQAY.pngAs can be seen from the above image the blue signal is NSS pin, which is configure as GPIO Output. Something in HAL_SPI_TransmitReceive_IT() is toggle the pin, and check the register SSM and SSI SSOE are all correct at least from what I can determine from the datasheet and SFRs.

Anybody have an idea what can be the isseu?

Hello,

it seem as the STM32's SPI is not what I expected. The way I currently solved it is:

I have some defines, just in case I ever get it wo work:

#define ABP2_SPI_CS_HARDWARE 0 // Do not modify
#define ABP2_SPI_CS_SOFTWARE 1 // Do not modify
 
#define ABP2_SPI_CS_CONTROL ABP2_SPI_CS_SOFTWARE // Modify to Control the Code

Before I communicate I set the nSS line to zero(select the slave):

HAL_StatusTypeDef Abp2SpiReadStatus( )
{
    Abp2SpiTxData[0] = ABP2_SPI_CMD_NOP;
 
    #if ABP2_SPI_CS_CONTROL == ABP2_SPI_CS_SOFTWARE
        HAL_GPIO_WritePin(SpiAbp2Nss_GPIO_Port, SpiAbp2Nss_Pin, GPIO_PIN_RESET);//Try to set SPI CS-LOW
    #endif
 
    return (HAL_SPI_TransmitReceive_DMA(pAbp2IfHspi, Abp2SpiTxData,
            Abp2SpiRxData, ABP2_SPI_STATUS_BYTES));
}

Because I use a callback on cempletion (no polling) I reset it there:

//FIXME: Why does "HAL_StatusTypeDef TxRxCpltCallback(SPI_HandleTypeDef *hspi)" not work
 
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
    // If the Callback comes from the ABP2 SPI Transfer
    if (hspi->Instance == pAbp2IfHspi->Instance)
    {
        Abp2TxRxCpltCallbackIsr();
    }
}
HAL_StatusTypeDef Abp2TxRxCpltCallbackIsr(  )
{
 
#if ABP2_SPI_CS_CONTROL == ABP2_SPI_CS_SOFTWARE
    HAL_GPIO_WritePin(SpiAbp2Nss_GPIO_Port, SpiAbp2Nss_Pin, GPIO_PIN_SET); //Try to set SPI CS-HIGH
#endif
 ......

That's how I did it, maybe there are better ways, if so, please let me know. I think you should do it in a simlilar way and put the Pin to "not select slave" in the IT-Callback.

Keep us updated 😎 .

Best Regards, Seppel