cancel
Showing results for 
Search instead for 
Did you mean: 

Software configuration of SPI NSS to run multi-slave one master SPI system for STM32L412 chip

rsoc
Associate III

I am hoping to understand more the process behind this. From what I understand, the NSS can be in either a hardware or software configuration. Reading the reference manual [Section 40.4.5], it appears that if the NSS is placed in software management mode, it acts as a normal GPIO. However, when it is placed in hardware mode, I get a little fuzzy. I know that i need NSS output enable, as I am the master of the system. However, I dont understand how this works from the software perspective.

I tried to implement this in my code (that is the NSS hardware alternate function mode, attached below) and i successfully send signals for the MOSI and clock, but the NSS never goes high. I verified this through a logic analyzer which i can provide if needed. The code i provide is specifically regarding the configuration of the GPIOs, as I am confident in the code to send the signal: i.e. the NSS is configured hardware control through the alternate function and I shouldn't need to do anything else in the transmit?

I guess what I am asking out of this is if there is something wrong with my understanding of what NSS is, or something wrong with how I have configured the GPIOs for SPI, that someone advise?

void SPI_MspInit(SPI_HandleTypeDef *hspi)
{
GPIO_InitTypeDef  GPIO_InitStruct;
 
  if (hspi->Instance == SPIx)
  {
  /*##-1- Enable peripherals and GPIO Clocks #################################*/
  /* Enable GPIO TX/RX clock */
  RCC->AHB2ENR |= (1 << 1);  // set AHB1ENR[0], IO port A clock enabled
  uint32_t tmpreg = (RCC->AHB2ENR & (1 << 1)); // read it back to delay 
 
  /* Enable SPI clock */
  RCC->APB1ENR1 |= (1 << 14);  // set AHB1ENR[0], IO port A clock enabled
  tmpreg = (RCC->APB1ENR1 & (1 << 14)); // read it back to delay 
 
    /*##-2- Configure peripheral GPIO ##########################################*/
    /* SPI SCK GPIO pin configuration  */
    GPIO_InitStruct.Pin       = GPIO_PIN_10;
    GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull      = GPIO_PULLDOWN;
    GPIO_InitStruct.Speed     = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(SPIx_SCK_GPIO_PORT, &GPIO_InitStruct);
 
    /* SPI MISO GPIO pin configuration  */
    GPIO_InitStruct.Pin = GPIO_PIN_14;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(SPIx_MISO_GPIO_PORT, &GPIO_InitStruct);
 
    /* SPI MOSI GPIO pin configuration  */
    GPIO_InitStruct.Pin = GPIO_PIN_15;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStruct);
 
    /* SPI NSS pin configuration  */
    GPIO_InitStruct.Pin = GPIO_PIN_12;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
    HAL_GPIO_Init(SPIx_MOSI_GPIO_PORT, &GPIO_InitStruct);
 
    /*##-3- Configure the NVIC for SPI #########################################*/
    /* NVIC for SPI */
    HAL_NVIC_SetPriority(SPIx_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(SPIx_IRQn);
  }
}

3 REPLIES 3

The "native" NSS output from master is relatively useless. You simply use as many GPIO Outputs as you have slaves, connected to the slaves' NSS, and pull them down "manually" whenever you want to talk to a particular slave.

You need to set NSS to software and the internal level to high in the master, though, otherwise it will switch to slave.

HW

The problem is I am limited on GPIOs and was relying on the native NSS to help me out with some of this. I will have close to 5 different SPI slave peripherals, and dont have enough GPIOs. I was hoping to wire the each slave's chip select to the single SPI2 NSS and work off that. Is that not possible?

And how do you plan to connect MISO from the slaves?

Simply wiring them together works only if the slaves have individual NSS, as inactive NSS on slave threestates MISO.

You can of course invent your own scheme, but this is the usual way to do it.

JW