cancel
Showing results for 
Search instead for 
Did you mean: 

STM32G491KE received SPI data always 0xFF

Nicc
Visitor

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

0 REPLIES 0