cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L0 SPI Mode always return MODF

TSu.1
Associate II

Greetings,

I tried to setup a L0 using SPI to connect with LSM6DSR, all codes are generated using CubeMX (also the driver code for LSM6DSR with X-CUBE-MEMS1)

The weird thing is, when ever it tries to utilize SPI functions (Transmit, Receive, and Transmit/Receive), it will always return HAL_SPI_ERROR_MODF.  The SPI1 only have LSM6DSR connected, no other slaves, the only master is the L0.

The SPI is setup as below, generated by CubeMX but I think there shouldn't be a problem:

 

__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_HIGH;
  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;
  if (HAL_SPI_Init(hspi) != HAL_OK)
  {
    ret = HAL_ERROR;
  }

  return ret;
}

 

 

The initalization code:

 

static int32_t IMU_Init(void){
  //Initialize LSM6DSR
  LSM6DSR_IO_t            io_ctx;
  uint8_t                 id;
  static LSM6DSR_Object_t lsm6dsr_obj_0;
  int32_t ret = BSP_ERROR_NONE;

    /* Configure the accelero driver */
  io_ctx.BusType     = LSM6DSR_SPI_4WIRES_BUS; /* SPI with CS */
  io_ctx.Address     = NULL; //Doesn't have an address for SPI
  io_ctx.Init        = BSP_SPI1_Init;
  io_ctx.DeInit      = BSP_SPI1_DeInit;
  io_ctx.ReadReg     = BSP_SPI1_SendRecv;
  io_ctx.WriteReg    = BSP_SPI1_SendRecv;
  io_ctx.GetTick     = BSP_GetTick;

  if (LSM6DSR_RegisterBusIO(&lsm6dsr_obj_0, &io_ctx) != LSM6DSR_OK)
  {
    ret = BSP_ERROR_UNKNOWN_COMPONENT;
  }
  else if (LSM6DSR_ReadID(&lsm6dsr_obj_0, &id) != LSM6DSR_OK) 
  {
    ret = BSP_ERROR_UNKNOWN_COMPONENT;
    Error_Handler();
  }
  else if (id != LSM6DSR_ID)
  {
    ret = BSP_ERROR_UNKNOWN_COMPONENT;
  }
  else
  {
    // Customization Part:
    // Enable Accelerometer only

    // Disable the Gyro
    if(LSM6DSR_GYRO_Disable(&lsm6dsr_obj_0) != LSM6DSR_OK)
    {
      ret = BSP_ERROR_COMPONENT_FAILURE;
    }

    //Setup Accelero
    if(LSM6DSR_ACC_SetOutputDataRate(&lsm6dsr_obj_0, 104.0f) != LSM6DSR_OK)
    {
      ret = BSP_ERROR_COMPONENT_FAILURE;
    }
    if(LSM6DSR_ACC_SetFullScale(&lsm6dsr_obj_0, LSM6DSR_ACC_SENSITIVITY_FS_4G) != LSM6DSR_OK)
    {
      ret = BSP_ERROR_COMPONENT_FAILURE;
    }

    //Setup Interrupt for wake up

    //Enable Accelero
    if(LSM6DSR_ACC_Enable(&lsm6dsr_obj_0) != LSM6DSR_OK)
    {
      ret = BSP_ERROR_COMPONENT_FAILURE;
    }

  }
  return ret;
}

 

 I also notice that when I set SPI_POLARITY_HIGH, the SCK line never idle high. I tried to fix it with internal up in GPIO init but then again, never fixes the MODF problem.

2 REPLIES 2
Imen.D
ST Employee

Hello @TSu.1 ,

Do you use the SS pin?  

Verify SS Pin Configuration if it is as an output and is driven high in master mode.

Check all SPI bus connections for any loose or faulty wiring.

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen

@Imen.D ,

SS pin was used, like this:

 

IMU_ChipSelect();
IMU_Init();
IMU_ChipDeselect();

 

 

I tried hardware NSS, doesn't work.

 

I tried with I2C and interestingly, doesn't work either! It even affected my other sensor's I2C driver code (it worked fine when using the regular MX_I2C1_Init() ). I2C Master Transmit didn't return HAL_OK like before. Is there a bug somewhere in the generated BSP driver code?