2021-01-15 09:23 AM
I've got erratic behavior of access to H3LIS331DL sensor from my MCU when STOP2 mode is set.
It seems that sometimes, the Interrupt ( INT1 on DRDY) received from theH3LIS331 is not, or very lately processed (maybe after wake up from other reason).
I can see that when the H3LIS331DL interrupt is processed very late (about 7ms after the INT1 signal), sometimes the I2C Data reading (that I can see with digital signal analizer) does not reset the DRDY interrupt from the H3LIS331DL, and then the acquisition process is no more ongoing.
By the way if I set HSI clock either than MSI before entering STOP2 mode the processing seems as fast as if i was not in STOP2 mode... and then every thing is ok ?
Any clues ?
Solved! Go to Solution.
2021-01-18 07:41 AM
My MCU is STM32L462RE, most of the time in STOP2 mode.
Basically I have configured the I2C to be clocked from SYSTICK.
But to have a correct behavior i must set this before entering STOP2 mode:
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);
Strangely this make my acquisition on Interrupt (INT1/DRDY) work correctly at 400Hz (H3LIS config), except that my I2C bus frequency calculated from CubeMX is never exactly 400KHz neither with 24MHz MSI and nor with 16MHz HSI parameters.
Exemple using HSI 16MHz timing parameter (from CubeMx 0x0010061A):
Exemple using HSI 24MHz timing parameter (from CubeMx 0x00200C28):
Below my I2C configuration parameters:
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C1;
PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_SYSCLK;
//PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
//PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_HSI;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
I2cBus1Handle.Instance = I2C1;
//I2cBus1Handle.Init.Timing = 0x00200C28; /*< 400 KHz Generated with CubeMx with SYSCLCK or PCLK1 24 MHz*/
//I2cBus1Handle.Init.Timing = 0x00201759; /*< 200 KHz Generated with CubeMx with SYSCLCK 24 MHz*/
I2cBus1Handle.Init.Timing = 0x0010061A; /*< 400 KHz Generated with CubeMx with HSI wakeup from STOP2 16MHz */
I2cBus1Handle.Init.OwnAddress1 = 0xFF;
I2cBus1Handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
I2cBus1Handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
I2cBus1Handle.Init.OwnAddress2 = 0xFF;
I2cBus1Handle.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
I2cBus1Handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
I2cBus1Handle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
Last, my main system clocks config:
__weak void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_MEDIUMHIGH);
HAL_PWR_DisableBkUpAccess();
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_LSE
|RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
//
RCC_OscInitStruct.MSICalibrationValue = 0;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_9;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_LPTIM1;
PeriphClkInit.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSE;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure the main internal regulator output voltage
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/**Enable MSI Auto calibration
*/
HAL_RCCEx_EnableMSIPLLMode();
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
2021-01-18 02:19 AM
Hi @PGoud ,
which MCU are you using? I'm adding STM32 MCUs topic since I'm not an expert on these MCU configurations.
It could be the case that, for some reason, the DRDY interrupt is not cleared after it is detected, so that the you are facing unwanted delays.
Which is the IO configuration of the INT1 line, from MCU side? You may try to change the PP_OD configuration in CTRL_REG3 (22h) register.
Can you try to check if the "soft" interrupt is raised? To do this, can poll the register INT1_SRC (31h) and see if the IA bit has been raised (after setting the LIR1 bit in the CTRL_REG3 (22h) register): in this case, the interrupt should be cleared just after the reading, and should be raised again just after a new data is available.
"Reading at this address clears the INT1_SRC IA bit (and the interrupt signal on the INT 1 pin) and allows the refreshment of data in the INT1_SRC register if the latched option is chosen". (datasheet p. 31)
I also suggest you to set the BDU bit of CTRL_REG4 (23h) register equal to 1, so that the DRDY interrupt is not updated between MSB and LSB reading, if not already done.
>> By the way if I set HSI clock either than MSI before entering STOP2 mode the processing seems as fast as if i was not in STOP2 mode... and then every thing is ok?
Everything is working well if you use the HSI clock?
-Eleon
2021-01-18 07:41 AM
My MCU is STM32L462RE, most of the time in STOP2 mode.
Basically I have configured the I2C to be clocked from SYSTICK.
But to have a correct behavior i must set this before entering STOP2 mode:
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);
Strangely this make my acquisition on Interrupt (INT1/DRDY) work correctly at 400Hz (H3LIS config), except that my I2C bus frequency calculated from CubeMX is never exactly 400KHz neither with 24MHz MSI and nor with 16MHz HSI parameters.
Exemple using HSI 16MHz timing parameter (from CubeMx 0x0010061A):
Exemple using HSI 24MHz timing parameter (from CubeMx 0x00200C28):
Below my I2C configuration parameters:
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_I2C1;
PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_SYSCLK;
//PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
//PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_HSI;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
I2cBus1Handle.Instance = I2C1;
//I2cBus1Handle.Init.Timing = 0x00200C28; /*< 400 KHz Generated with CubeMx with SYSCLCK or PCLK1 24 MHz*/
//I2cBus1Handle.Init.Timing = 0x00201759; /*< 200 KHz Generated with CubeMx with SYSCLCK 24 MHz*/
I2cBus1Handle.Init.Timing = 0x0010061A; /*< 400 KHz Generated with CubeMx with HSI wakeup from STOP2 16MHz */
I2cBus1Handle.Init.OwnAddress1 = 0xFF;
I2cBus1Handle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
I2cBus1Handle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
I2cBus1Handle.Init.OwnAddress2 = 0xFF;
I2cBus1Handle.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
I2cBus1Handle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
I2cBus1Handle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
Last, my main system clocks config:
__weak void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct;
RCC_ClkInitTypeDef RCC_ClkInitStruct;
RCC_PeriphCLKInitTypeDef PeriphClkInit;
HAL_PWR_EnableBkUpAccess();
__HAL_RCC_LSEDRIVE_CONFIG(RCC_LSEDRIVE_MEDIUMHIGH);
HAL_PWR_DisableBkUpAccess();
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI|RCC_OSCILLATORTYPE_LSE
|RCC_OSCILLATORTYPE_MSI;
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.MSIState = RCC_MSI_ON;
//
RCC_OscInitStruct.MSICalibrationValue = 0;
RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_9;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_RTC|RCC_PERIPHCLK_LPTIM1;
PeriphClkInit.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSE;
PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure the main internal regulator output voltage
*/
if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
/**Configure the Systick interrupt time
*/
HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);
/**Configure the Systick
*/
HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);
/**Enable MSI Auto calibration
*/
HAL_RCCEx_EnableMSIPLLMode();
/* SysTick_IRQn interrupt configuration */
HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}
2021-01-22 03:24 AM
Hi @PGoud ,
so you did solved your issue with this correction, right?
__HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_HSI);
Can I now refer to your last post on community about the INT behavior??
-Eleon
2021-01-22 06:52 AM
Yes you can refer to it, has my main issue was solved about H3LIS331DL usage/functions.
But the "Why" it works is a bit "fuzzy" for me.
But these questions may be not tied to H3LIS331DL, but about "I2C working during an interrupt (INT1) in STOP2 mode" ?
Maybe I should have post that elsewhere.
So close and refer to this post as you will.
Again many thanks.
Pierre-emmanuel