How to use hardware NSS (SPI) on stm32f4?

mkom picture mkom · Mar 3, 2016 · Viewed 33.3k times · Source

So I tried to use hardware NSS signal with HAL library, but I can't find any function to make NSS pin have low or high level. I also tried to find the answer in HAL documentation, but there is no information too. All examples in the Internet contain only software NSS. How one is supposed to use hardware NSS?

Answer

peets picture peets · Jul 10, 2016

Somewhere I read that NSS is driven low as long as the SPI Master is enabled and driven high again if the SPI Master is disabled. I tried it using the HAL library (Cube/CubeMX) from ST with a STM32L476 and polling SPI1. Initialization before and de-initialization after transmission did NOT set the NSS Pin - but took much 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;

Transmit 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 setting the pin 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 (no DMA or Interrupt) because it was fast enough and no other tasks waiting. DMA setup proved to take unacceptably longer time to send only 24 bytes at 20MHz. IT would be an acceptable alternative.

As far as I can see in the STM32L4xx manual Chapter 38.4.12/13 the automatic NSS goes high after each byte/word transmission and thus is not well usable for longer streams holding NSS low for the whole transmission.