How to use NSS hardware (SPI) on stm32f4?

So I tried to use the NSS hardware signal with the HAL library, but I can not find any function to make the NSS output low or high. I also tried to find the answer in the HAL documentation, but there is no information either. All examples on the Internet contain only NSS software. How are you supposed to use hardware NSS?

+8
source share
3 answers

I read somewhere that NSS is disabled as long as the SPI master is turned on and lights up again if the SPI master is disabled. I tried this using the HAL library (Cube / CubeMX) from ST using STM32L476 and polling SPI1. Initialization before and de-initialization after the transmission did NOT set Pin NSS - but it took a long time:

Init structure:

hspi1.Instance = SPI1; hspi1.Init.Mode = SPI_MODE_MASTER; hspi1.Init.Direction = SPI_DIRECTION_2LINES; hspi1.Init.DataSize = SPI_DATASIZE_8BIT; hspi1.Init.CLKPolarity = SPI_POLARITY_HIGH; hspi1.Init.CLKPhase = SPI_PHASE_2EDGE; hspi1.Init.NSS = SPI_NSS_HARD_OUTPUT; hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8; hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB; hspi1.Init.TIMode = SPI_TIMODE_DISABLE; hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; hspi1.Init.CRCPolynomial = 7; hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE; hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; 

Transmission Sequence:

 HAL_SPI_Init( &hspi1 ); HAL_SPI_TransmitReceive( &hspi1, btx, brx, l, 5 ); // timeout 5msec; while( hspi1.State == HAL_SPI_STATE_BUSY ); // wait for xmission complete HAL_SPI_DeInit( &hspi1 ); 

So, I decided to establish contact manually using GPIO (using SPI_NSS_SOFT in init):

 HAL_GPIO_WritePin( NSS1_GPIO_Port, NSS1_Pin, GPIO_PIN_RESET ); // NSS1 low HAL_SPI_TransmitReceive( &hspi1, btx, brx, l, 5 ); // timeout 5msec; while( hspi1.State == HAL_SPI_STATE_BUSY ); // wait xmission complete HAL_GPIO_WritePin( NSS1_GPIO_Port, NSS1_Pin, GPIO_PIN_SET ); // NSS1 high 

I used blocking transmission (without DMA or interruption) because it was fast enough and no other tasks were expected. Installing DMA was unacceptably longer to send only 24 bytes at a frequency of 20 MHz. That would be an acceptable alternative.

As far as I can see in the STM32L4xx instruction manual in chapter 38.4.12 / 13, automatic NSS becomes high after each byte / word transmission and therefore is not suitable for longer streams that keep the NSS low for the entire transmission.

+7
source

You can use the NSS pin as a standard GPIO and control it using the interrupt routine. You must do this part using software. Set Nss low first and then send your frame (HAL_SPI_Transmit) After the subordinate receives the whole frame, use HAL_SPI_RxCpltCallback and put Nss in this interrupt.

Remember to connect the GPIO pin to the Nss pin on the slave.

+2
source

See the reference guide for your STM32 chip. I don’t know if they are the same, but one for my (STM32WB55xx) and one for which I managed to find a public web link ( STM32F0 ) ...

See the SPI functional description for managing NSS pins (section 28.5.5 for the STM32F0 document I am associated with) for three modes:

  • NSS software control (SPIx_CR1 register SSM bit = 1). The internal slave selection information is controlled by the internal SSI bit in register SPIx_CR1. External NSS output is free for use by applications.

  • NSS hardware control (SSM bit = 0). This has two possible configurations depending on the SSOE bit in the SPIx_CR1 register:

    • NSS output resolution (SSOE = 1). Used only if the MCU is the primary. The NSS signal becomes low as soon as the SPI is turned on in the master mode (SPE = 1), and is kept low until the SPI is turned off (SPE = 0). A pulse can be generated between continuous communications if the NSS pulse mode is activated. This NSS parameter cannot work in a multi-host configuration
    • Disable NSS output (SSOE = 0). If the MCU is the leader, this allows you to use the capabilities of several masters. If the NSS is down, the SPI goes into a failed state of the main mode, and the device automatically reconfigures to slave mode. In slave mode, the NSS pin acts as the standard "chip select" input, and the slave is selected when the NSS line is low.

Looking at the headers for my SoC, the program mode is SSM = 1 (NSS software control). Hard output mode: SSM = 0 and SSOE = 1 (NSS output resolution). Hard input mode - all zeros (disable NSS output).

If you use hard output, you can also see the NSS pulse mode (section 28.5.12 in the STM32F0 document that I am associated with). He describes (with a timing chart) how the system will keep NSS low most of the time, pulsing it high between data frames. If your device uses NSS / CS to synchronize data frames, this can be useful. Or maybe not, if your device responds to an increase in NSS, interrupting the current operation, as the text, apparently, indicates that it will be an NSS pulse between each transmitted word, and not between buffers.

Unfortunately, this does not look like the most flexible implementation. Depending on your application, it may be easier for you to leave it in soft mode and just switch the NSS output through GPIO.

0
source

Source: https://habr.com/ru/post/1244382/


All Articles