Skip to main content
STM32Freakz
Associate II
September 7, 2020
Question

SPI Multi-master NSS Setup

  • September 7, 2020
  • 5 replies
  • 5715 views

Hello

Im trying to implement stm32 spi multi-master function on a stm32f765 according to the below presentation

0693W000003QsuWQAS.png

I keep getting MODF error when transmitting as a master, that would indicate that the slave sets the masters NSS pin low. Even if I set the NSS pin permantently high, by hooking it to a 3,3v pin , I get the same error!

below is my setup:

--------MSP SETUP--------------------------------------
GPIO_InitStruct.Pin = SPI_CS_Pin;
 GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
 GPIO_InitStruct.Mode = GPIO_MODE_INPUT | GPIO_MODE_IT_RISING;
 GPIO_InitStruct.Pull = GPIO_PULLUP;
 HAL_GPIO_Init(SPI_CS_GPIO_Port, &GPIO_InitStruct);
 
 // SPI master com trigger GPIO pin configuration
 GPIO_InitStruct.Pin = SPI_MASTER_TRIG_Pin;
 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP ;
 HAL_GPIO_Init(SPI_MASTER_TRIG_Port, &GPIO_InitStruct);
--------MSP SETUP--------------------------------------
 
------------SPI Handle setup--------------------------
 
static void setupSPIbaseStruct(SPI_HandleTypeDef *pSpiHandle, uint32_t mode)
{
 pSpiHandle->Instance = SPI2;
 if (mode == SPI_MODE_MASTER) {
 pSpiHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
 }else{
 pSpiHandle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
 }
 pSpiHandle->Init.Direction = SPI_DIRECTION_2LINES;
 pSpiHandle->Init.CLKPhase = SPI_PHASE_2EDGE;
 pSpiHandle->Init.CLKPolarity = SPI_POLARITY_HIGH;
 pSpiHandle->Init.DataSize = SPI_DATASIZE_8BIT;
 pSpiHandle->Init.FirstBit = SPI_FIRSTBIT_MSB;
 pSpiHandle->Init.TIMode = SPI_TIMODE_DISABLE;
 pSpiHandle->Init.CRCCalculation = SPI_CRCCALCULATION_ENABLE;
 pSpiHandle->Init.CRCPolynomial = 7;
 pSpiHandle->Init.NSSPMode = SPI_NSS_PULSE_DISABLED;
 pSpiHandle->Init.NSS = SPI_NSS_HARD_INPUT;
 pSpiHandle->Init.Mode = mode ;
}
------------SPI Handle setup--------------------------

what Im I doing wrong?

This topic has been closed for replies.

5 replies

waclawek.jan
Super User
September 7, 2020

Read out and check/post content of SPI and relevant GPIO registers.

JW

STM32Freakz
Associate II
September 7, 2020

Thank you for reply

A read out of NSS pin inside of error callback says pin is high, contrary to what should have triggered the error in question(MODF) modf(1) bit is set in Spihandle.ErrorCode

CR1 : 1010000100110011 / 0xa133

CR2: 1011100000000 / 0x1700

SR : 10 / 0x2

ErrorCode: 1 / 0x1

GPIO port IDR = 1

I don´t know if there´s any other relevant information?

waclawek.jan
Super User
September 7, 2020

Which pin is used for NSS? How is that pin's MODER and AFR set in GPIO?

JW

STM32Freakz
Associate II
September 8, 2020

The setup is the one I pasted in the code, the SPI_CS_Pin refers to GPIO_PIN_9 and SPI_CS_GPIO_Port to port GPIOB

and alternate function in use is AF5 according to the table below0693W000003QzClQAK.png

  1. GPIO_InitStruct.Pin = SPI_CS_Pin;
  2. GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;
  3. GPIO_InitStruct.Mode = GPIO_MODE_INPUT | GPIO_MODE_IT_RISING;
  4. GPIO_InitStruct.Pull = GPIO_PULLUP;
  5. HAL_GPIO_Init(SPI_CS_GPIO_Port, &GPIO_InitStruct);

waclawek.jan
Super User
September 8, 2020

I don't use Cube/HAL and don't understand it.

Read out and check/post the relevant register's content.

You want the pin to be set to AF in GPIO_MODER, and to proper AF in GPIO_AFR. My guess is, that this:

> GPIO_InitStruct.Mode = GPIO_MODE_INPUT | GPIO_MODE_IT_RISING;

does not do that.

JW

STM32Freakz
Associate II
September 8, 2020

So i guess we are on different sides of it, I can´t fully interpret the content of those registers:

GPIOx->MODER =  0xaaa06aa0 / 10101010101000000110101010100000
 
AFR = 0x40020020 / 1000000000000100000010000100000
 AFR[0] = 0xa666900 / 1010011001100110100100000000
 
 AFR[1] = 0x55bbbb00 / 1010101101110111011101100000000

What am I looking for? Thank you for helping!

EDIT: I see now that because Im setting Mode to GPIO_MODE_INPUT, the step where Alternate function is set is skipped. The reason why I set it to GPIO_MODE_INPUT and not GPIO_MODE_AF_PP was that I got strange behavior with the pin getting set half way (~2,2V / floating behavior), which disappeared when I set it to input.

waclawek.jan
Super User
September 8, 2020

How did you read that out? Did you use the debugger's register view?

AFR[1] = 0x40020020

This is suspiciously address of GPIOA->AFR[0].

JW

STM32Freakz
Associate II
September 8, 2020

I updated the answer just before your post

I simply had a break point inside the setup function after the pin config

If your referring to the SFR view, that view does not show the GPIO registers:

0693W000003QzqMQAS.png

waclawek.jan
Super User
September 8, 2020

> What am I looking for?

We are talking about PB9, so you want to look in MODER at bits 18 and 19 (i.e. 9*2 and 9*2+1 - two bits per pin are used), they are 0b00 which means Input, and are supposed to be 0b10 for AF. Then we would be looking at bits 4 to 9 in AFR[1] (4 bits per pin, that is 32 bits for pins PB0..PB7 in AFR[0] and 32 bits for pins PB8..PB15 in AFR[1].

Having no pin set to AF corresponding to the SPI2_NSS means, that internally that node is set to 0 - which immediately after enabling SPI switches it to slave mode.

> The reason why I set it to GPIO_MODE_INPUT and not GPIO_MODE_AF_PP was that I got strange behavior with the pin getting set half way (~2,2V / floating behavior), which disappeared when I set it to input.

I don't understand. If the PB9 is set as AF in MODER and AF5 in AFR[1], and SPI module is set so that NSS is input (i.e. SPI_CR2.SSOE=0), the PB9 pin works in exactly the same way as when it's set to Input. If not, some of those 3 things are not set in that way.

Do you have a pullup on that pin?

JW

STM32Freakz
Associate II
September 8, 2020

I had setting Mode= GPIO_MODE_AF_PP | GPIO_MODE_IT_RISING , this meant that when the HAL function HAL_GPIO_Init checked if AF should be used, the result was faulty ->no AF was set.

Anyway, now I have scaled back to only using AF

GPIOx->MODER = 0xaaa86aa0/ 10101010101010000110101010100000

AFR = 0x40020400/ 1000000000000100000010000000000

    AFR[0] = 0xa666900/ 1010011001100110100100000000

    AFR[1] = 0x55bbbb50/ 1010101101110111011101101010000

    

Which is correct right?

The problem now is that the slave does not have a way to detect end of message(thats why I had "|GPIO_MODE_IT_RISING " and then a EXTI interrupt), RxCPLT callback is never called either