cancel
Showing results for 
Search instead for 
Did you mean: 

GPIO / EXTI interrupts, STOP2 mode and H3LIS331DL

PGoud
Associate III

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 ?

1 ACCEPTED SOLUTION

Accepted Solutions
PGoud
Associate III

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):

  • ON awake mode my I2C clock is 2.2us period ==> 454 KHz
  • ON Interrupt (from STOP2): 3,1 us period ==> 322KHz

Exemple using HSI 24MHz timing parameter (from CubeMx 0x00200C28):

  • ON awake mode my I2C clock is 3,2us period ==> 312 KHz
  • ON Interrupt (from STOP2): 4,3 us period ==> 232KHz

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);
}

View solution in original post

4 REPLIES 4
Eleon BORLINI
ST Employee

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

PGoud
Associate III

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):

  • ON awake mode my I2C clock is 2.2us period ==> 454 KHz
  • ON Interrupt (from STOP2): 3,1 us period ==> 322KHz

Exemple using HSI 24MHz timing parameter (from CubeMx 0x00200C28):

  • ON awake mode my I2C clock is 3,2us period ==> 312 KHz
  • ON Interrupt (from STOP2): 4,3 us period ==> 232KHz

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);
}

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

PGoud
Associate III

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.

  • Why MUST I configure for an HSI wakeup either than my usual MSI, to have my interrrupts INT1 with I2C access correctly processed ?
  • Why can't i get exact 400KHz I2C clock (in RUN mode or on interrupt from STOP2 mode) ?

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