STM32F4 SPI Slave with hw NSS and HAL - Page 1
Forum section: electronics / general

author: simben
author_rank: Newbie
timestamp: April 12, 2017, 07:16:09 am
content: 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 spiCode: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 ConfigurationPA4 ------> SPI1_NSSPA5 ------> SPI1_SCKPA6 ------> SPI1_MISOPA7 ------> 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 */}......}

author: mbless
author_rank: Regular Contributor
timestamp: April 12, 2017, 12:56:28 pm
content: How about posting rest of the code? We can't tell how you are handling the receive part without itDoes the SPI peripheral reach the READY state after initialization?

author: simben
author_rank: Newbie
timestamp: April 12, 2017, 03:47:37 pm
content: 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 transmissionvoid 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?

author: jnz
author_rank: Frequent Contributor
timestamp: April 12, 2017, 05:30:24 pm
content: 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.

author: krho
author_rank: Regular Contributor
timestamp: April 12, 2017, 05:56:34 pm
content: This sound very familiar with mefor 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).

author: rstofer
author_rank: Super Contributor
timestamp: April 12, 2017, 08:58:35 pm
content: 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:MX_GPIO_Init(); -- Cube CodeMX_USART2_UART_Init(); -- sameMX_SPI1_Init(); -- end of Cube Code-- my code VVVHAL_SPI_Receive(&hspi1,data,1,HAL_MAX_DELAY); -- wait to receive one charHAL_UART_Transmit(&huart2,data,1,HAL_MAX_DELAY; -- print the charHAL_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=PA15SCK=PA5MISO=PA6MOSI=PA7

author: thm_w
author_rank: Super Contributor
timestamp: April 12, 2017, 09:51:51 pm
content: You configured with &hspi1 but your receive code you wrote was &hspi2.Code:if (HAL_SPI_Init(&hspi1) != HAL_OK)HAL_SPI_Receive(&hspi2, (uint8_t *)spi_rx, 3,100);Code: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:* @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?

author: simben
author_rank: Newbie
timestamp: April 12, 2017, 10:21:18 pm
content: QuoteLike I said, second code was from a project with another mcu to varify my mistake. So this wasn't the problem.QuoteYou 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.QuoteI will test this tomorrow morning.

author: thm_w
author_rank: Super Contributor
timestamp: April 12, 2017, 11:09:23 pm
content: Quote from: simben on April 12, 2017, 10:21:18 pmI see what you are saying, if you want to setup the next receive.Having HAL_SPI_Receive_IT in that location should work then.

author: mbless
author_rank: Regular Contributor
timestamp: April 13, 2017, 12:32:02 am
content: 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?

author: newbrain
author_rank: Super Contributor
timestamp: April 13, 2017, 09:41:54 pm
content: Quote from: simben on April 12, 2017, 10:21:18 pmCalling 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...