/**
  ******************************************************************************
  * @file           : main.c
  * @author         ：SINOMCU-AE
  * @brief          : Main program body
  *  
  *          This file provides example code for Power stop mode WFE and printf by uart:
  * Run 5S,than enter stop LDO low power mode,Press Key2(PB4,EXIT line4) up core go on.
  * For details, see "readme.txt"
  *         
  ******************************************************************************
   * @attention 
  *                           DISCLAIMER
  * The present firmware which is for guidance only aims at providing customers
  * with coding information regarding their products in order for them to save
  * time. As a result, SinoMCU shall not be held liable for any direct,indirect
  * or consequential damages with respect to any claims arising from the content 
  * of such firmware and/or the use made by customers of the coding information 
  * contained herein in connection with their products.
  *
  * <h2><center>&copy; Copyright (c) 2021 sinomcu All rights reserved.</center></h2>
  *
  ******************************************************************************
  */  
  
#include "system_define.h"

#define SYSCLK_USE_PLL_48M        0         // 1:sysclk PLL48M,0:HSI 8M 

#define COUNT_PERIOD              500       // count period in ms
#define ENTER_STOP_DELAY_COUNT    10        // ENTER_STOP_DELAY_COUNT * COUNT_PERIOD
#define DELAY_FOR_UART_SEND       2         // unit ms

int main(void) 
{
  __IO uint32_t run_count = 0;
  uint8_t stop_enter_count = 0;
  
  //MS32_DBGMCU_EnableDBGStopMode();

#if(defined(SYSCLK_USE_PLL_48M) && SYSCLK_USE_PLL_48M) 
  sysclk_init();                            // sysclk 48M,HSI 8M /2*12;if not call this function,default HSI 8M
#endif
  SystemCoreClockUpdate();                  // get System Core Clock
    
  sys_tick_init();
  gpio_init();
  exit_line_init();
#if(defined(EN_PRINT_UART) && EN_PRINT_UART) 
  MS32_RCC_SetUSARTClockSource(MS32_RCC_USART1_CLKSOURCE_HSI);       // uart clk HSI 8M   
  usart1_uart_init(115200);
#endif
  
  printf("\r\n\r\n*****Power STOP WFE Exit PB4 Example*****");
  printf("\r\n--Inf:System Core Clock %d Hz.",SystemCoreClock); 

  Start_User_MS_SF_Timer(COUNT_PERIOD);
  while(1) {
  
    if(Get_State_User_MS_SF_Timer() == SF_TIMER_OV) {
      Start_User_MS_SF_Timer(COUNT_PERIOD);                          // clear Software timer OV
      LED1_TOGGLE();
      run_count++;
      printf("\r\n--Inf: running count:%d",run_count);

      stop_enter_count++;
      if(stop_enter_count == ENTER_STOP_DELAY_COUNT) {               // enter low power count 5S
        stop_enter_count =0;
        LED1_OFF(); 
        printf("\r\n--Inf:Enter STOP WFE;PB4 Key Exit Low Power!"); 
        MS32_mDelay(DELAY_FOR_UART_SEND);
        
        LED2_ON();                                                   // LED2 light on 
        // LDO LowPower mode,enter stop mode WFE
        MS32_PWR_EnterSTOPMode_WFE(PWR_LOWPOWERREGULATOR_ON); 
#if(defined(SYSCLK_USE_PLL_48M) && SYSCLK_USE_PLL_48M) 
        sysclk_init();                                               // stop mode need reinit clock,if sysclock not HSI
#endif         
        LED2_OFF();                                                  // exit low power mode LED2 OFF
      }
    }
  }
}

/**
  * @brief  SystemClock_Config HSI/2 to PLL*12 sysclk 48M
  * @param  None
  * @retval None
  */
void sysclk_init(void) {
  MS32_RCC_OscInitTypeDef osc_cfg;
  MS32_RCC_PllInitTypeDef pll_cfg;
  MS32_RCC_ClkInitTypeDef clk_cfg;

  // get and clear reset flag 
  MS32_RCC_GetResetFlag(ENABLE);
  
  // osc config 
  osc_cfg.HSIState = MS32_RCC_HSI_ON;
  osc_cfg.HSEState = MS32_RCC_HSE_OFF;
  osc_cfg.LSIState = MS32_RCC_LSI_OFF;
//  osc_cfg.LSEState = MS32_RCC_LSE_ON_DRV_H;
  MS32_RCC_OscConfig(&osc_cfg);
  
  // pll config 
  pll_cfg.PLLState  = MS32_RCC_PLL_ON;
  pll_cfg.PLLSource = MS32_RCC_PLL_SOURCE_HSI_DIV_2;       // HSI/2 4M
  pll_cfg.PLLMUL    = MS32_RCC_PLL_MUL12;
  pll_cfg.PREDIV    = MS32_RCC_PLL_PREDIV_DIV1;
  MS32_RCC_PllConfig(&pll_cfg);
  
  // sysclk config 
  clk_cfg.SYSCLKSource   = MS32_RCC_SYSCLK_SOURCE_PLL;
  clk_cfg.AHBCLKDivider  = MS32_RCC_SYSCLK_DIV1;
  clk_cfg.APB1CLKDivider = MS32_RCC_HCLK_DIV1;
  MS32_RCC_ClockConfig(&clk_cfg);
}

/**
  * @brief Enters STOP mode WFE.
  * @note  In Stop mode, all I/O pins keep the same state as in Run mode.
  * @note  When exiting Stop mode by issuing an interrupt or a wakeup event,
  *         the HSI RC oscillator is selected as system clock.
  * @note  When the voltage regulator operates in low power mode, an additional
  *         startup delay is incurred when waking up from Stop mode.
  *         By keeping the internal regulator ON during Stop mode, the consumption
  *         is higher although the startup time is reduced.
  * @param Regulator Specifies the regulator state in STOP mode.
  *          This parameter can be one of the following values:
  *            @arg PWR_MAINREGULATOR_ON: STOP mode with regulator ON
  *            @arg PWR_LOWPOWERREGULATOR_ON: STOP mode with low power regulator ON
  * @retval None
  */
void MS32_PWR_EnterSTOPMode_WFE(uint32_t Regulator) {
  // Enable PWR clock
  MS32_APB1_GRP1_EnableClock(MS32_APB1_GRP1_PERIPH_PWR);

  // Select the regulator state in STOP mode
  MS32_PWR_SetPowerMode(Regulator);
  // Set SLEEPDEEP bit of Cortex System Control Register
  MS32_LPM_EnableDeepSleep();

  // Request Wait For Event
  __SEV();
  __WFE();
  __WFE();
}

/******************************** END OF FILE *********************************/
