Skip to main content
Associate
May 21, 2026
Solved

STM32G491KE received SPI data always 0xFF

  • May 21, 2026
  • 3 replies
  • 113 views

Hello

I have custom PCB with STM32G491KE connected to an LSM6SV80X IMU directly via SPI. I'm having an issue with not being able to receive any data from the IMU, the the read value is always 0xFF which I've read is usually an issue with the slave/subnode/agent device not responding. 

Here's how the SPI interface is configured (via CubeMX with X-CUBE-MEMS1)

__weak HAL_StatusTypeDef MX_SPI1_Init(SPI_HandleTypeDef* hspi)
{
 HAL_StatusTypeDef ret = HAL_OK;

 hspi->Instance = SPI1;
 hspi->Init.Mode = SPI_MODE_MASTER;
 hspi->Init.Direction = SPI_DIRECTION_2LINES;
 hspi->Init.DataSize = SPI_DATASIZE_8BIT;
 hspi->Init.CLKPolarity = SPI_POLARITY_LOW;
 hspi->Init.CLKPhase = SPI_PHASE_1EDGE;
 hspi->Init.NSS = SPI_NSS_SOFT;
 hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
 hspi->Init.FirstBit = SPI_FIRSTBIT_MSB;
 hspi->Init.TIMode = SPI_TIMODE_DISABLE;
 hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
 hspi->Init.CRCPolynomial = 7;
 hspi->Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
 hspi->Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
 if (HAL_SPI_Init(hspi) != HAL_OK)
 {
 ret = HAL_ERROR;
 }

 return ret;
}

From the datasheet of the IMU I can say:

  • That mode 0 and 3 are supported so the clock phase and clock polarity should be fine, but I have tested on both modes (same outcome)
  • The SPI diagrams from the IMU datasheet show 8-bit messages
  • The supported clock rate is up to 10MHz, and the clock on the G4 is 16MHz, with a pre-scaler of 2 that produces a clock of 8MHz < 10MHz. Going to 4MHz didn't change the outcome. 
  • SPI is full duplex master on the G4, so using 4 wires, which is supported by the IMU and its default configuration in its registers 
  • MSB first matches the IMU datasheet 

Furthermore, the pins are configured for no pull down/up and alternative function with push-pull. GPIO OSPEED is set to medium as the default was low which seemed slow. There is no external circuitry between the MCU and the IMU. 

VDD and VDDIO on the IMU are both powered via 3V3 and the G4 is also powered from the same 3V3.

Nicc_0-1779402803552.png

CubeMX generated an SPI send and SPI Recv functions to use with the interface generated using X-CUBE-MEMS1 but I swear they would not work as is since the write and read don't send the register value so I wrote my own using HAL. The odd parameters for the function is due to a generated struct expecting a function pointer of this type. That's why reg is 16 bits instead of 8 and dummy is cast to void (dummy is the device address used if the interface is configured for I2C). 

int32_t my_SPI1_Send(uint16_t dummy, uint16_t reg, uint8_t * pData, uint16_t length){
 (void)dummy;
 uint8_t reg8 = (uint8_t)reg;
 HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
 HAL_SPI_Transmit(&hspi1, &reg8, 1, BUS_SPI1_POLL_TIMEOUT);
 HAL_SPI_Transmit(&hspi1, (uint8_t*) pData, length, BUS_SPI1_POLL_TIMEOUT);
 HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
 return 0;
}

int32_t my_SPI1_Recv(uint16_t dummy, uint16_t reg, uint8_t * pData, uint16_t length){
 (void)dummy;
 reg |= 0x0080;
 uint8_t reg8 = (uint8_t)reg;
 HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
 HAL_SPI_Transmit(&hspi1, &reg8, 1, BUS_SPI1_POLL_TIMEOUT);
 HAL_SPI_Receive(&hspi1, pData, length, BUS_SPI1_POLL_TIMEOUT);
 HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);
 return 0;
}

Any data received is always 0xFF. All functions return fine (HAL_OK) but the data is always all ones. I've read this can be from the subnode device not doing anything with the MISO line. I've stepped through the code and the register and data to send are both good. It is important to mention I made two PCBs and the behaviour is the same (I've not done every test on both boards but neither work and receive only 0xFF) so it's hard to imagine it's damage unless I'm very unfortunate. A configuration issue, some HW issue, or some esoteric SPI thing are the only options I can imagine is going on at this point.  

Fearing HAL could be doing something, I wrote a very slim register version, here just grabbing the WHO_AM_I register but same outcome. (__IO is a alias for volatile)

uint8_t reg = 0x80 | LSM6DSV80X_WHO_AM_I;
uint8_t whoami = 0xAA;
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_RESET);
hspi1.Instance->CR1 |= SPI_CR1_SPE;
while (!(SPI1->SR & SPI_SR_TXE)) {};
*(__IO uint8_t *)&hspi1.Instance->DR = (* (uint8_t *)reg);
while (!(SPI1->SR & SPI_SR_RXNE)) {};
(* (uint8_t *)whoami) = *(__IO uint8_t *)&hspi1.Instance->DR;
while (SPI1->SR & SPI_SR_BSY) {};
HAL_GPIO_WritePin(SPI1_CS_GPIO_Port, SPI1_CS_Pin, GPIO_PIN_SET);

Unfortunately the pins that I selected on the G4 (PA6, PA7) cannot be configured for I2C so swapping SPI for I2C is not an option.

I have not scoped any of the signal lines yet... and I still can but the PCB is very very small and would require scraping some of the soldermask off so I'm trying to fix it before it comes to that. 

Thank you

Best answer by Nicc

Thank you @waclawek.jan and @Andrew Neil for the suggestions, I was able to figure out the problem. 
I was checking the registers as suggested for the SPI IO and found that MISO, MOSI, and CLK were being initialized properly, but when I tired to do the same for CS it would never get there and get stuck in an infinite loop I had written. 

I was preforming a check on the who_am_i register on the IMU to make sure the device was communicating properly after I had setup the SPI pins but before I had initialized the CS pin (since I was doing that in software) so the configuration was correct but the subnode device wasn't responding because the CS pin was not toggling. 
I feel silly but I hope it will help someone else in the future to remind them it might just be something so simple as the CS pin.

3 replies

Andrew Neil
Super User
May 22, 2026

Have you used a scope and/or logic analyser to see what's actually happening on the wires?

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
waclawek.jan
Super User
May 22, 2026

+1 to using the oscilloscope/LA; but you can/should also read out and check/post the relevant GPIO and/or SPI registers content, and also a good exercise may be to try to bit-bang the interface.

JW

NiccAuthorAnswer
Associate
May 22, 2026

Thank you @waclawek.jan and @Andrew Neil for the suggestions, I was able to figure out the problem. 
I was checking the registers as suggested for the SPI IO and found that MISO, MOSI, and CLK were being initialized properly, but when I tired to do the same for CS it would never get there and get stuck in an infinite loop I had written. 

I was preforming a check on the who_am_i register on the IMU to make sure the device was communicating properly after I had setup the SPI pins but before I had initialized the CS pin (since I was doing that in software) so the configuration was correct but the subnode device wasn't responding because the CS pin was not toggling. 
I feel silly but I hope it will help someone else in the future to remind them it might just be something so simple as the CS pin.