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 noticed that when I set SPI_POLARITY_HIGH, the SCK line never idle-high. I tried to fix it with internal pull-up in GPIO init but then again, never fixes the MODF problem.