2024-08-08 07:03 AM
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.
2024-08-09 08:17 AM - edited 2024-08-09 08:19 AM
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.
2024-08-09 10:26 AM
@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?