cancel
Showing results for 
Search instead for 
Did you mean: 

stm32g0 lptim1 low power sleep

jlthompson
Associate III

I want to use LPTIM1 of the STM32G0x1 to wake up the MCU, if it's not already awake, and start a DMA multichannel single conversion. I think I know how to do the DMA/ADC part after getting the ADC_MultiChannelSingleConversion example running; I'll the code from that project to this one later.. But the most part is waking up. Here's the relevant part of what I have:

int main(void)
{

  /* USER CODE BEGIN 1 */
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_LPTIM1_Init();
  /* USER CODE BEGIN 2 */
  /* Enable Power Clock */
  __HAL_RCC_PWR_CLK_ENABLE();
  
  RCC->IOPSMENR  = 0x0000u;
  RCC->AHBSMENR  = 0x00300u;

  RCC->APBSMENR1 = 0x9000u;
  RCC->APBSMENR2 = 0x0000u;
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	if (HAL_LPTIM_TimeOut_Start_IT(&hlptim1, PERIOD, TIMEOUT) != HAL_OK)
	{
	 Error_Handler();
	}

    /* Reduce the System clock to below 2 MHz */
    SystemClock_Decrease();

    /* Enter Sleep Mode, wake up is done once User push-button is pressed */
    HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);

    /* ... Low-power SLEEP mode ... */
    __WFI();
    /* System is Low Power Run mode when exiting Low Power Sleep mode,
       disable low power run mode and reset the clock to initialization configuration */ 
    HAL_PWREx_DisableLowPowerRunMode();

    /* Configure the system clock for the RUN mode */
    SystemClock_Config();

    /* Re-init LED4 to toggle during Run mode */
    if (LED_FLASH_PERIOD == ++led_flash_count)
    {
    	led_flash_count = 0;
    	HAL_GPIO_TogglePin(LED_4_GPIO_Port, LED_4_Pin);
    }
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE2);

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.LSIState = RCC_LSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

 I can tell the MCU goes to sleep because the STMLInk connection is lost, but it never wakes up. What am I missing?

When the MCU wakes up, I want the LPTim1 interrupt handler to call HAL_ADC_Start_DMA. While awake, I'll see if I've collected all the data I need. That will take much longer than the LPTIM1 Timeout period, but I need the periodic conversions to continue to collect ADC at the same time. Is this possible, and how?

Thanks!

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Super User

Sounds like systick is not paused.

1 kHz / 10 / 2 = 50 Hz

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

8 REPLIES 8
jlthompson
Associate III

Also, I think I want LPTIM1 to operate as a simple internal clock counter, but I can't figure out how to configure it for that using the IDE Pinout & Configuration tool. How is that done?

I selected 'Counts internal clock events', but the function definition is disabled, so I can't call it.

I figured out the cause of some of my issues. I started with an example project, and those do unusual things with file locations. For example, there's an invisible Inc folder with main.h. If all you want to do is run the example, great. But I don't advise using it as the starting point for your project; borrow the concepts and maybe a few code snippets. That's why I could not find the definition for the  HAL_LPTIM_Counter_Start_IT function I was trying to use.

 

I've also got the Low Power Sleep mode nearly working; at least the going to sleep and waking up part works. The only thing is off is that the LED flash rate is much lower than I anticipated when I use the code for  LowPowerRunMode than when I don't:

  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
#if 1
	  HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
#else
	    /* Reduce the System clock to below 2 MHz */
	    SystemClock_Decrease();

	    HAL_PWREx_EnableLowPowerRunMode();

	    /* Enter Sleep Mode, wake up is done once User push-button is pressed */
	    HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);

	    /* ... Low-power SLEEP mode ... */
	    __WFI();
	    /* System is Low Power Run mode when exiting Low Power Sleep mode,
	       disable low power run mode and reset the clock to initialization configuration */
	    HAL_PWREx_DisableLowPowerRunMode();

	    /* Configure the system clock for the RUN mode */
	    SystemClock_Increase();

#endif
	  if (LED_FLASH_PERIOD_MS == ++led_period_count)
	  {
		  led_period_count = 0;
		  HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin);
	  }
  }
  /* USER CODE END 3 */
}

I'm still trying to figure that out. Any suggestions?

Sarra.S
ST Employee

Hello @jlthompson

>> The only thing is off is that the LED flash rate is much lower than I anticipated 

What LED flash rate do you expect, and what value are you actually observing?

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Thanks for the response, Sarra!

 

With #if of line 6 above set to 1, I get a 50 Hz rate. With the #if set to 0, I get a 14.8 Hz rate, neither of which make sense. 

I'm using the LIS to give LPTIM1 a 32 kHz clock. The LPTIM1 prescalar is set to DIV32, so it should be counting 1 kHz clock cycles for a period of 1 ms. I'm calling HAL_LPTIM_Counter_Start_IT(&hlptim1, 100); so I would expect an interrupt every 100 ms.  I'm using the led_period_count variable to count up to LED_FLASH_PERIOD_MS, which is a misnomer, that is set to 10. So, 10 counts x 100 ms = 1000 ms. Because the counter is reset when it hits 10 and then the LED pin is toggled, I expected to see a 2 Hz flash rate.

I'm sure I'm doing some very basic thing very wrong. I just can't figure out what. And there's no example 'on point' for reference, at least not that I've been able to discover after several hours of searching.

 

TDK
Super User

Sounds like systick is not paused.

1 kHz / 10 / 2 = 50 Hz

If you feel a post has answered your question, please click "Accept as Solution".

LIke this:

	  	HAL_SuspendTick();
	  	
	    /* Reduce the System clock to below 2 MHz */
	    SystemClock_Decrease();

	    HAL_PWREx_EnableLowPowerRunMode();

	    /* Enter Sleep Mode, wake up is done when LPTIM1 auto-reloads */
	    HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);

	    /* System is Low Power Run mode when exiting Low Power Sleep mode,
	       disable low power run mode and reset the clock to initialization configuration */
	    HAL_PWREx_DisableLowPowerRunMode();

	    /* Configure the system clock for the RUN mode */
	    SystemClock_Increase();
	    
	  	HAL_ResumeTick();

That gives me 14.66 Hz.

I think It's working! I used

HAL_LPTIM_Counter_Start_IT(&hlptim1, 10);
while (1)
{
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
#if 0
    HAL_SuspendTick();
    HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
    HAL_ResumeTick();
#else
    /* Reduce the System clock to below 2 MHz */
    SystemClock_Decrease();

    HAL_SuspendTick();

    AL_PWREx_EnableLowPowerRunMode();

    /* Enter Sleep Mode, wake up is done when LPTIM1 auto-reloads */
    HAL_PWR_EnterSLEEPMode(PWR_LOWPOWERREGULATOR_ON, PWR_SLEEPENTRY_WFI);

    /* System is Low Power Run mode when exiting Low Power Sleep mode,
    disable low power run mode and reset the clock to initialization configuration */
    HAL_PWREx_DisableLowPowerRunMode();

    HAL_ResumeTick();

    /* Configure the system clock for the RUN mode */
    SystemClock_Increase();

#endif
    if (10 == ++led_period_count)
    {
        led_period_count = 0;
        HAL_GPIO_TogglePin(LED_GREEN_GPIO_Port, LED_GREEN_Pin);
    }
}

And got 100 ms between toggles for a 5 Hz rate, for both sleep and low-power sleep modes.