LoPoSo/RealOne/Core/Src/main.c

376 lines
8.6 KiB
C

/* Project L476_ats_blink for STM32L476 mounted on Nucleo board:
* the user LED (mounted on pin PA-5) is flashed every second for 50 ms.
* The time base is provided by Systick (1000 ticks per second).
* The clock configuration is the default one (Sysclk = 80 MHz, derived from MSI and PLL).
*/
/* Includes ------------------------------------------------------------------*/
#include "main.h"
// #if defined(USE_FULL_ASSERT)
// #include "stm32_assert.h"
// #endif /* USE_FULL_ASSERT */
#include "gpio.h"
// systick interrupt handler
volatile uint32_t msTicks = 0;
volatile uint8_t expe = 0;
volatile uint8_t blue_mode = 0;
void SysTick_Handler()
{
if ( BLUE_BUTTON() ){
blue_mode = 1 ;
}
msTicks++; /* See startup file startup_LPC17xx.s for SysTick vector */
if (msTicks == 5 * expe){
LED_GREEN(0);
}else if(msTicks >= 200){
msTicks = 0;
LED_GREEN(1);
}
if(expe == 2 || expe == 4){
CLK_TOGGLE();
}
}
int main(void)
{
// config GPIO
GPIO_init();
// if (RCC->BDCR & RCC_BDCR_LSEON) {
LL_APB1_GRP1_EnableClock( LL_APB1_GRP1_PERIPH_PWR );
LL_PWR_EnableBkUpAccess();
//expe = register RTC
expe = RTC->BKP0R;
if (expe == 0) {
SystemClock_Config_24M_LSE();
expe = 1;
LL_APB1_GRP1_EnableClock( LL_APB1_GRP1_PERIPH_PWR );
LL_PWR_EnableBkUpAccess();
RTC->BKP0R = expe;
}
if (BLUE_BUTTON()){
expe ++;
blue_mode = 0;
if (expe > 8) expe = 1;
RTC->BKP0R = expe;
}
// }else{
// }
LL_PWR_DisableBkUpAccess();
switch(expe){
case 1:
/* Configure the system clock */
SystemClock_Config_80M();
//Setup Sleep mode
LL_LPM_EnableSleep();
break;
case 2:
/* Configure the system clock */
SystemClock_Config_24M_LSE();
break;
case 3:
SystemClock_Config_24M_LSE_FL3_VS2();
LL_LPM_EnableSleep();
break;
case 4:
SystemClock_Config_24M_LSE_FL3_VS2();
case 5:
SystemClock_Config_24M_LSE_FL3_VS2();
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP0);
break;
case 6:
SystemClock_Config_24M_LSE_FL3_VS2();
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP1);
break;
case 7:
SystemClock_Config_24M_LSE_FL3_VS2();
LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2);
break;
case 8:
SystemClock_Config_24M_LSE_FL3_VS2();
LL_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN);
break;
}
// init systick timer (tick period at 1 ms)
LL_Init1msTick( SystemCoreClock );
LL_SYSTICK_EnableIT();
//LL_LPM_EnableSleepOnExit();
while (1) {
if (blue_mode){
switch(expe){
case 5:
case 6:
case 7:
LL_LPM_EnableDeepSleep();
RTC_wakeup_init_from_stop(20);
__WFI();
blue_mode = 0;
SystemClock_Config_24M_LSE_FL3_VS2();
LL_Init1msTick( SystemCoreClock );
LL_SYSTICK_EnableIT();
break;
case 8:
LL_LPM_EnableDeepSleep();
RTC_wakeup_init_from_standby_or_shutdown(10);
case 1:
case 3:
__WFI();
break;
case 2:
case 4:
LL_RCC_MSI_EnablePLLMode();
break;
}
}else{
if (expe > 4) {
LL_LPM_EnableSleep();
__WFI();
}
}
}
}
void SystemClock_Config_24M_LSE_FL3_VS2(void){
LL_APB1_GRP1_EnableClock( LL_APB1_GRP1_PERIPH_PWR );
LL_FLASH_SetLatency(LL_FLASH_LATENCY_3);
while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_3)
{
}
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE2);
LL_RCC_MSI_Enable();
/* Wait till MSI is ready */
while(LL_RCC_MSI_IsReady() != 1)
{
}
LL_PWR_EnableBkUpAccess();
// LL_RCC_ForceBackupDomainReset();
LL_RCC_ReleaseBackupDomainReset();
LL_RCC_LSE_SetDriveCapability(LL_RCC_LSEDRIVE_LOW);
LL_RCC_MSI_EnableRangeSelection();
LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_6);
LL_RCC_MSI_SetCalibTrimming(0);
// LL_RCC_MSI_EnablePLLMode();
LL_RCC_LSE_Enable();
/* Wait till LSE is ready */
while(LL_RCC_LSE_IsReady() != 1)
{
}
LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
LL_RCC_EnableRTC();
LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_MSI, LL_RCC_PLLM_DIV_1, 24, LL_RCC_PLLR_DIV_4);
LL_RCC_PLL_EnableDomain_SYS();
LL_RCC_PLL_Enable();
/* Wait till PLL is ready */
while(LL_RCC_PLL_IsReady() != 1)
{
}
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
/* Wait till System clock is ready */
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
{
}
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
LL_SetSystemCoreClock(24000000);
/* Update the time base */
if (HAL_InitTick (TICK_INT_PRIORITY) != HAL_OK)
{
// Error_Handler();
}
}
/**
* @brief System Clock Configuration
* @retval None
* 24Mhz + RTC + LSE
*/
void SystemClock_Config_24M_LSE(void)
{
LL_APB1_GRP1_EnableClock( LL_APB1_GRP1_PERIPH_PWR );
LL_FLASH_SetLatency(LL_FLASH_LATENCY_1);
while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_1)
{
}
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
LL_RCC_MSI_Enable();
/* Wait till MSI is ready */
while(LL_RCC_MSI_IsReady() != 1)
{
}
LL_PWR_EnableBkUpAccess();
// LL_RCC_ForceBackupDomainReset();
LL_RCC_ReleaseBackupDomainReset();
LL_RCC_LSE_SetDriveCapability(LL_RCC_LSEDRIVE_LOW);
LL_RCC_MSI_EnableRangeSelection();
LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_6);
LL_RCC_MSI_SetCalibTrimming(0);
// LL_RCC_MSI_EnablePLLMode();
LL_RCC_LSE_Enable();
/* Wait till LSE is ready */
while(LL_RCC_LSE_IsReady() != 1)
{
}
LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
LL_RCC_EnableRTC();
LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_MSI, LL_RCC_PLLM_DIV_1, 24, LL_RCC_PLLR_DIV_4);
LL_RCC_PLL_EnableDomain_SYS();
LL_RCC_PLL_Enable();
/* Wait till PLL is ready */
while(LL_RCC_PLL_IsReady() != 1)
{
}
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
/* Wait till System clock is ready */
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
{
}
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
LL_SetSystemCoreClock(24000000);
/* Update the time base */
if (HAL_InitTick (TICK_INT_PRIORITY) != HAL_OK)
{
// Error_Handler();
}
}
void SystemClock_Config_80M(void)
{
LL_FLASH_SetLatency(LL_FLASH_LATENCY_4);
while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_4)
{
}
LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1);
LL_RCC_MSI_Enable();
/* Wait till MSI is ready */
while(LL_RCC_MSI_IsReady() != 1)
{
}
LL_RCC_MSI_EnableRangeSelection();
LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_6);
LL_RCC_MSI_SetCalibTrimming(0);
LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_MSI, LL_RCC_PLLM_DIV_1, 40, LL_RCC_PLLR_DIV_2);
LL_RCC_PLL_EnableDomain_SYS();
LL_RCC_PLL_Enable();
/* Wait till PLL is ready */
while(LL_RCC_PLL_IsReady() != 1)
{
}
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL);
/* Wait till System clock is ready */
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
{
}
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1);
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
LL_SetSystemCoreClock(80000000);
/* Update the time base */
if (HAL_InitTick (TICK_INT_PRIORITY) != HAL_OK)
{
// Error_Handler();
}
}
// partie commune a toutes les utilisations du wakeup timer
static void RTC_wakeup_init( int delay )
{
LL_RTC_DisableWriteProtection( RTC );
LL_RTC_WAKEUP_Disable( RTC );
while ( !LL_RTC_IsActiveFlag_WUTW( RTC ) )
{ }
// connecter le timer a l'horloge 1Hz de la RTC
LL_RTC_WAKEUP_SetClock( RTC, LL_RTC_WAKEUPCLOCK_CKSPRE );
// fixer la duree de temporisation
LL_RTC_WAKEUP_SetAutoReload( RTC, delay ); // 16 bits
LL_RTC_ClearFlag_WUT(RTC);
LL_RTC_EnableIT_WUT(RTC);
LL_RTC_WAKEUP_Enable(RTC);
LL_RTC_EnableWriteProtection(RTC);
}
// Dans le cas des modes STANDBY et SHUTDOWN, le MPU sera reveille par reset
// causé par 1 wakeup line (interne ou externe) (le NVIC n'est plus alimenté)
void RTC_wakeup_init_from_standby_or_shutdown( int delay )
{
RTC_wakeup_init( delay );
// enable the Internal Wake-up line
LL_PWR_EnableInternWU(); // ceci ne concerne que Standby et Shutdown, pas STOPx
}
// Dans le cas des modes STOPx, le MPU sera reveille par interruption
// le module EXTI et une partie du NVIC sont encore alimentes
// le contenu de la RAM et des registres étant préservé, le MPU
// reprend l'execution après l'instruction WFI
void RTC_wakeup_init_from_stop( int delay )
{
RTC_wakeup_init( delay );
// valider l'interrupt par la ligne 20 du module EXTI, qui est réservée au wakeup timer
LL_EXTI_EnableIT_0_31( LL_EXTI_LINE_20 );
LL_EXTI_EnableRisingTrig_0_31( LL_EXTI_LINE_20 );
// valider l'interrupt chez NVIC
NVIC_SetPriority( RTC_WKUP_IRQn, 1 );
NVIC_EnableIRQ( RTC_WKUP_IRQn );
}
// wakeup timer interrupt Handler (inutile mais doit etre defini)
void RTC_WKUP_IRQHandler()
{
LL_EXTI_ClearFlag_0_31( LL_EXTI_LINE_20 );
}