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