LoPoSo/RealOne/Core/Src/main.c
2020-11-22 21:34:50 +01:00

365 lines
9 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() //occurs every 10ms
{
if ( BLUE_BUTTON() ){ //switch to blue mode if blue button was pressed
blue_mode = 1 ;
}
msTicks++; //increment time counter
if (msTicks == 5 * expe){ //turn off led after 50ms*expe
LED_GREEN(0);
}else if(msTicks >= 200){ //turn on led every 2 seconds
msTicks = 0;
LED_GREEN(1);
}
if(expe == 2 || expe == 4){ //output a 50Hz clock on PC10 to evaluate frequency stability for expe 2 & 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; //Load expe number from backup register
if (expe == 0) { //if cold start : setup clock, LSE & set expe to 1
SystemClock_Config_24M_LSE();
expe = 1;
LL_APB1_GRP1_EnableClock( LL_APB1_GRP1_PERIPH_PWR );
LL_PWR_EnableBkUpAccess();
RTC->BKP0R = expe;
}
if (BLUE_BUTTON()){ //if blue_button is pressed at reset, switch to next expe
expe ++;
blue_mode = 0;
if (expe > 8) expe = 1; //rollover to 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 10 ms)
LL_Init1msTick( SystemCoreClock );
LL_SYSTICK_EnableIT();
//LL_LPM_EnableSleepOnExit();
while (1) {
if (blue_mode){
switch(expe){
case 5: //cases 5-7 : start stop mode, and reconfigure at wakeup
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(); //case 8 : shutdown (wakeup=>reset)
RTC_wakeup_init_from_standby_or_shutdown(10);
case 1:
case 3:
__WFI();
break;
case 2:
case 4:
LL_RCC_MSI_EnablePLLMode(); //case 4 : enable MSI calibration
break;
}
}else{
if (expe > 4) { //expe 5-8 : sleep as normal mode
LL_LPM_EnableSleep();
__WFI();
}
}
}
}
/**
* @brief System Clock Configuration
* @retval None
* 24Mhz + RTC + LSE + Flash latency 3 + Voltage scaling 2
*/
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);
}
/**
* @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);
}
/**
* @brief System Clock Configuration
* @retval None
* 80MHz using PLL,default flash latency and voltage scaling
*/
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);
}
// 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 );
}