Author Topic: STM32F4 SPI Slave with hw NSS and HAL  (Read 11970 times)

0 Members and 1 Guest are viewing this topic.

Offline simbenTopic starter

  • Newbie
  • Posts: 3
  • Country: de
STM32F4 SPI Slave with hw NSS and HAL
« on: April 12, 2017, 07:16:09 am »
Hello,

I've been watching EEVblog for a long time and decided to register to the forum, as I am facing some nasty problems with my SPI on my STM32F407. I configured the SPI1 with CubeMX as a slave with hardware NSS. But I can't receive any data. All physical connections are working fine. So are the transmitted data from the host. I checked them with an logic analyzer as well as with an oscilloscope.
So as there were no evidence of an physical error in my circuit and no all data were sent properly I checked my program on the mcu.

First I just read the input pins and they also indicated that all data were applied to the correct pins.

Next step I checked if I could transmit data. There the problems began. No data were stored into my buffer variables. So I began to dig a little bit deeper. Debugging yield to the cunclusion that HAL_SPI_STATE_BUSY_RX is always true. So my guess is, that because of HAL_SPI_STATE_BUSY_RX is always true the HAL_SPI_RECEIVE() isn't finished and will never be executed HAL_SPI_RxCpltCallback().

Does anyone know such issues? More important, does anyone know how such a problem?

Already thank you for your help and below you find the config code for my spi

Code: [Select]
void MX_SPI1_Init(void)
{

  hspi1.Instance = SPI1;
  hspi1.Init.Mode = SPI_MODE_SLAVE;
  hspi1.Init.Direction = SPI_DIRECTION_2LINES;
  hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
  hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
  hspi1.Init.CLKPhase = SPI_PHASE_2EDGE;
  hspi1.Init.NSS = SPI_NSS_HARD_INPUT;
  hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
  hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
  hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
  hspi1.Init.CRCPolynomial = 10;
  if (HAL_SPI_Init(&hspi1) != HAL_OK)
  {
    Error_Handler();
  }

}

void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
{

  GPIO_InitTypeDef GPIO_InitStruct;
  if(spiHandle->Instance==SPI1)
  {
  /* USER CODE BEGIN SPI1_MspInit 0 */

  /* USER CODE END SPI1_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_SPI1_CLK_ENABLE();

    /**SPI1 GPIO Configuration
    PA4     ------> SPI1_NSS
    PA5     ------> SPI1_SCK
    PA6     ------> SPI1_MISO
    PA7     ------> SPI1_MOSI
    */
    GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    /* Peripheral interrupt init */
    HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(SPI1_IRQn);
  /* USER CODE BEGIN SPI1_MspInit 1 */

  /* USER CODE END SPI1_MspInit 1 */
  }
  ......
}
 

Offline mbless

  • Regular Contributor
  • *
  • Posts: 227
  • Country: 00
Re: STM32F4 SPI Slave with hw NSS and HAL
« Reply #1 on: April 12, 2017, 12:56:28 pm »
How about posting rest of the code? We can't tell how you are handling the receive part without it  :-//

Does the SPI peripheral reach the READY state after initialization?
 

Offline simbenTopic starter

  • Newbie
  • Posts: 3
  • Country: de
Re: STM32F4 SPI Slave with hw NSS and HAL
« Reply #2 on: April 12, 2017, 03:47:37 pm »
Yes, it reaches the ready state once after init.
I basically stripped down my whole project that I only call HAL_SPI_Receive(&hspi2, (uint8_t *)spi_rx, 3,100) before the main loop. After the completed transmission

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi){
   HAL_GPIO_TogglePin(output_GPIO_Port, output_Pin);
   HAL_SPI_Receive(&hspi2, (uint8_t *)spi_rx, 3,100);

}

should be called. But this won't happen while HAL_SPI_STATE_BUSY_RX is high. In case you wonder of different peripheral numbers, i copied this from a test setup with another mcu I am working on right now.

The whole config is generated with CubeMX. I use the newest version of CubeMx and the newest mcu firmware.

Furthermore I tested it with an Nucleo64-F302R8 Board. Same problem here.

Did you manage to get a SPI slave to work on an STM32 with HAL drivers?
 

Offline jnz

  • Frequent Contributor
  • **
  • Posts: 593
Re: STM32F4 SPI Slave with hw NSS and HAL
« Reply #3 on: April 12, 2017, 05:30:24 pm »
I really don't mind the HAL as much as other people, but anytime I run into something like this, I pull up the reference manual and start dialing into what the registers should actually be line by line of the transfer. I don't really see any way around it. Hopefully you're not one of those people that thinks debuggers are a tool they can get away without using.
 

Offline krho

  • Regular Contributor
  • *
  • Posts: 223
  • Country: si
Re: STM32F4 SPI Slave with hw NSS and HAL
« Reply #4 on: April 12, 2017, 05:56:34 pm »
This sound very familiar with me  |O for the past week with HAL nucleo-413 and QuadSPI.
The difference being that I can see the transmitted data on the scope. And additional 9 clock cycles, but IO1 line is always high (It's low while the "command" is being transmitted).
« Last Edit: April 12, 2017, 05:59:41 pm by krho »
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9890
  • Country: us
Re: STM32F4 SPI Slave with hw NSS and HAL
« Reply #5 on: April 12, 2017, 08:58:35 pm »
I didn't do anything fancy, I just let CubeMX create all the code and I used my Digilent Digital Discovery to send a packet.  I only accepted one byte and echoed it to the UART.  Works well...

Code: [Select]

MX_GPIO_Init();  -- Cube Code
MX_USART2_UART_Init();  -- same
MX_SPI1_Init(); -- end of Cube Code

-- my code VVV

HAL_SPI_Receive(&hspi1,data,1,HAL_MAX_DELAY);  -- wait to receive one char
HAL_UART_Transmit(&huart2,data,1,HAL_MAX_DELAY; -- print the char

HAL_UART_Transmit(&huart2,msg,sizeof(msg),HAL_MAX_DELAY); -- done with SPI Slave, print "Hello World!"


I haven't spent enough time to get the STM32F4 Discovery to send something as it is receiving.  More to study.

Since I am using SPI1:

NSS=PA15
SCK=PA5
MISO=PA6
MOSI=PA7
 

Online thm_w

  • Super Contributor
  • ***
  • Posts: 6386
  • Country: ca
  • Non-expert
Re: STM32F4 SPI Slave with hw NSS and HAL
« Reply #6 on: April 12, 2017, 09:51:51 pm »
You configured with &hspi1 but your receive code you wrote was &hspi2.
Code: [Select]
if (HAL_SPI_Init(&hspi1) != HAL_OK)
HAL_SPI_Receive(&hspi2, (uint8_t *)spi_rx, 3,100);


Code: [Select]
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi){
   HAL_GPIO_TogglePin(output_GPIO_Port, output_Pin);
   HAL_SPI_Receive(&hspi2, (uint8_t *)spi_rx, 3,100);
}

Calling this function in the interrupt callback doesn't make sense. Please decide which method to use, and look at the sample projects for IT or for polling mode in the HAL examples.

HAL_SPI_Receive is a polling function:

Code: [Select]
* @brief  Receive an amount of data in blocking mode.
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)

Also, for your SPI transmit test, is it possible to transmit in slave mode without an input clock? Are you supplying that?
« Last Edit: April 12, 2017, 09:54:23 pm by thm_w »
Profile -> Modify profile -> Look and Layout ->  Don't show users' signatures
 

Offline simbenTopic starter

  • Newbie
  • Posts: 3
  • Country: de
Re: STM32F4 SPI Slave with hw NSS and HAL
« Reply #7 on: April 12, 2017, 10:21:18 pm »
Quote
You configured with &hspi1 but your receive code you wrote was &hspi2.
Code: [Select]

if (HAL_SPI_Init(&hspi1) != HAL_OK)
HAL_SPI_Receive(&hspi2, (uint8_t *)spi_rx, 3,100);

Like I said, second code was from a project with another mcu to varify my mistake. So this wasn't the problem.

Quote
Code: [Select]

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi){
   HAL_GPIO_TogglePin(output_GPIO_Port, output_Pin);
   HAL_SPI_Receive(&hspi2, (uint8_t *)spi_rx, 3,100);
}


Calling this function in the interrupt callback doesn't make sense. Please decide which method to use, and look at the sample projects for IT or for polling mode in the HAL examples.

You are right, but same here, it was from the second project I made, and I forgot to change it. In my final code I've used IT. But why shouldn't it make sense? For example on my UART I do it the same way and it works fine. As far as I understood I have to recall HAL_SPI_Receive_IT after it was executed to wait for new incoming data.

Quote
Also, for your SPI transmit test, is it possible to transmit in slave mode without an input clock? Are you supplying that?
I will test this tomorrow morning.


 

Online thm_w

  • Super Contributor
  • ***
  • Posts: 6386
  • Country: ca
  • Non-expert
Re: STM32F4 SPI Slave with hw NSS and HAL
« Reply #8 on: April 12, 2017, 11:09:23 pm »
You are right, but same here, it was from the second project I made, and I forgot to change it. In my final code I've used IT. But why shouldn't it make sense? For example on my UART I do it the same way and it works fine. As far as I understood I have to recall HAL_SPI_Receive_IT after it was executed to wait for new incoming data.

I see what you are saying, if you want to setup the next receive.
Having HAL_SPI_Receive_IT in that location should work then.
Profile -> Modify profile -> Look and Layout ->  Don't show users' signatures
 

Offline mbless

  • Regular Contributor
  • *
  • Posts: 227
  • Country: 00
Re: STM32F4 SPI Slave with hw NSS and HAL
« Reply #9 on: April 13, 2017, 12:32:02 am »
Is the MCU only receiving data? If so, try setting the direction to SPI_DIRECTION_2LINES_RXONLY.

Also, take the HAL_SPI_Receive_IT to its simplest form: receive 1 byte and use HAL_MAX_DELAY. Do you read anything with that?
 

Offline newbrain

  • Super Contributor
  • ***
  • Posts: 1719
  • Country: se
Re: STM32F4 SPI Slave with hw NSS and HAL
« Reply #10 on: April 13, 2017, 09:41:54 pm »
For example on my UART I do it the same way and it works fine. As far as I understood I have to recall HAL_SPI_Receive_IT after it was executed to wait for new incoming data.

Calling blocking APIs in an interrupt routine (or callback, same thing) is almost never a good idea.
Even in the UART case, it will prevent all other incoming interrupts at lower (i.e. numerically higher) or same priority to be served.
Specifically, the timeout will not work if the peripheral interrupt is at the same priority of the SysTick one, as in your code, so it might block forever.

PPP_Receive_IT is instead generally safe.

But If you want more help, please post a reasonably complete piece of code demonstrating the problem: since it's mostly MXCube generated, I don't think you'll be giving away any secret...
Nandemo wa shiranai wa yo, shitteru koto dake.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf