From b650142c6ff089e9161a34bff06b8b97b7c7909d Mon Sep 17 00:00:00 2001 From: Mateusz Lubecki Date: Sun, 8 Oct 2023 21:43:35 +0200 Subject: [PATCH] reworking L6/L7 powersave modes with STOP2 sleep completely to engage iwdg --- STM32L476_ParaMETEO/src/subdir.mk | 3 + .../ParaMETEO-STM32L476RG.launch | 2 +- include/etc/pwr_save_configuration.h | 5 ++ include/main.h | 2 +- include/pwr_save.h | 1 + include/rte_main.h | 12 +++ include/software_version.h | 4 +- src/it_handlers.c | 14 ++- src/main.c | 22 ++--- src/pwr_save.c | 90 +++++++++++++++++-- src/rte_main.c | 6 ++ 11 files changed, 123 insertions(+), 38 deletions(-) diff --git a/STM32L476_ParaMETEO/src/subdir.mk b/STM32L476_ParaMETEO/src/subdir.mk index fa73ac9..c00fd37 100644 --- a/STM32L476_ParaMETEO/src/subdir.mk +++ b/STM32L476_ParaMETEO/src/subdir.mk @@ -24,6 +24,7 @@ C_SRCS += \ ../src/rte_pwr.c \ ../src/rte_rtu.c \ ../src/rte_wx.c \ +../src/software_version.c \ ../src/wx_handler.c \ ../src/wx_handler_humidity.c \ ../src/wx_handler_pressure.c \ @@ -51,6 +52,7 @@ OBJS += \ ./src/rte_pwr.o \ ./src/rte_rtu.o \ ./src/rte_wx.o \ +./src/software_version.o \ ./src/wx_handler.o \ ./src/wx_handler_humidity.o \ ./src/wx_handler_pressure.o \ @@ -78,6 +80,7 @@ C_DEPS += \ ./src/rte_pwr.d \ ./src/rte_rtu.d \ ./src/rte_wx.d \ +./src/software_version.d \ ./src/wx_handler.d \ ./src/wx_handler_humidity.d \ ./src/wx_handler_pressure.d \ diff --git a/doc/eclipse_debugger_launch/ParaMETEO-STM32L476RG.launch b/doc/eclipse_debugger_launch/ParaMETEO-STM32L476RG.launch index e5054c6..cbe5fb9 100644 --- a/doc/eclipse_debugger_launch/ParaMETEO-STM32L476RG.launch +++ b/doc/eclipse_debugger_launch/ParaMETEO-STM32L476RG.launch @@ -58,6 +58,6 @@ - + diff --git a/include/etc/pwr_save_configuration.h b/include/etc/pwr_save_configuration.h index b6ef45e..63ec4f6 100644 --- a/include/etc/pwr_save_configuration.h +++ b/include/etc/pwr_save_configuration.h @@ -37,4 +37,9 @@ */ //#define INHIBIT_CUTOFF +/** + * Intermediate STOP2 cycle lenght within L7 or L6 mode. + */ +#define PWR_SAVE_STOP2_CYCLE_LENGHT_SEC 30u + #endif /* INCLUDE_PWR_SAVE_CONFIGURATION_H_ */ diff --git a/include/main.h b/include/main.h index bc962eb..8c0f77d 100644 --- a/include/main.h +++ b/include/main.h @@ -15,7 +15,7 @@ #define SYSTICK_TICKS_PER_SECONDS 100 #define SYSTICK_TICKS_PERIOD 10 -//#define INTERNAL_WATCHDOG +#define INTERNAL_WATCHDOG #define EXTERNAL_WATCHDOG #define PWR_SWITCH_BOTH diff --git a/include/pwr_save.h b/include/pwr_save.h index e9dbc62..f9e75af 100644 --- a/include/pwr_save.h +++ b/include/pwr_save.h @@ -113,6 +113,7 @@ extern int8_t pwr_save_currently_cutoff; void pwr_save_init(config_data_powersave_mode_t mode); void pwr_save_enter_stop2(void); +void pwr_save_check_stop2_cycles(void); void pwr_save_exit_from_stop2(void); int pwr_save_switch_mode_to_c0(void); int pwr_save_switch_mode_to_c1(void); diff --git a/include/rte_main.h b/include/rte_main.h index 9a12336..a3f2770 100644 --- a/include/rte_main.h +++ b/include/rte_main.h @@ -5,6 +5,18 @@ #include #include "stored_configuration_nvm/config_data.h" +//!< Set immediately after waking up in RTC interrupt handler +#define RTE_MAIN_WOKEN_UP_RTC_INTERRUPT 1u + +//!< Set after exiting from RTC interrupt, but before reinitializing clocks +#define RTE_MAIN_WOKEN_UP_AFTER_RTC_IT 2u + +//!< Set after everything was reinitialized from +#define RTE_MAIN_WOKEN_UP_EXITED 4u + +//!< Trigger some reinitialization after waking up from deep sleep +extern uint8_t rte_main_woken_up; + extern uint8_t rte_main_reboot_req; extern uint8_t rte_main_boot_cycles, rte_main_hard_faults; diff --git a/include/software_version.h b/include/software_version.h index 5175420..b26b71b 100644 --- a/include/software_version.h +++ b/include/software_version.h @@ -8,8 +8,8 @@ #ifndef SOFTWARE_VERSION_H_ #define SOFTWARE_VERSION_H_ -#define SW_VER "EA24" -#define SW_DATE "22072023" +#define SW_VER "EB00" +#define SW_DATE "07102023" #define SW_KISS_PROTO "B" extern const char software_version_str[5]; diff --git a/src/it_handlers.c b/src/it_handlers.c index fbb24cd..f313c19 100644 --- a/src/it_handlers.c +++ b/src/it_handlers.c @@ -97,7 +97,11 @@ void it_handlers_set_priorities(void) { #ifdef STM32L471xx void RTC_WKUP_IRQHandler(void) { - main_woken_up = 1; + rte_main_woken_up = RTE_MAIN_WOKEN_UP_RTC_INTERRUPT; + + main_set_monitor(13); + + main_reload_internal_wdg(); // clear pending interrupt NVIC_ClearPendingIRQ(RTC_WKUP_IRQn); @@ -105,14 +109,6 @@ void RTC_WKUP_IRQHandler(void) { RTC->ISR &= (0xFFFFFFFF ^ RTC_ISR_WUTF_Msk); EXTI->PR1 |= EXTI_PR1_PIF20; - - main_set_monitor(12); - - system_clock_configure_l4(); - - pwr_save_exit_from_stop2(); - - } void SPI2_IRQHandler(void) { diff --git a/src/main.c b/src/main.c index 8427547..b266358 100644 --- a/src/main.c +++ b/src/main.c @@ -282,9 +282,6 @@ volatile int i = 0; #endif #if defined(PARAMETEO) -//!< Trigger some reinitnialization after waking up from deep sleep -uint8_t main_woken_up = 0; - //!< Triggers additional check if ADC has properly reinitialized and conversion is working uint8_t main_check_adc = 0; #endif @@ -794,7 +791,6 @@ int main(int argc, char* argv[]){ // configuring an APRS path used to transmit own packets (telemetry, wx, beacons) main_own_path_ln = ConfigPath(main_own_path, main_config_data_basic); -#ifdef INTERNAL_WATCHDOG #if defined(STM32F10X_MD_VL) // enable write access to watchdog registers IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); @@ -822,8 +818,8 @@ int main(int argc, char* argv[]){ // unlock write access to configuratio registers LL_IWDG_EnableWriteAccess(IWDG); - // set prescaler - watchdog timeout on about 16 seconds - LL_IWDG_SetPrescaler(IWDG, LL_IWDG_PRESCALER_128); + // set prescaler - watchdog timeout on about 32 seconds + LL_IWDG_SetPrescaler(IWDG, LL_IWDG_PRESCALER_256); // wait for watchdog registers to update while (LL_IWDG_IsActiveFlag_PVU(IWDG) != 0) { @@ -842,8 +838,6 @@ int main(int argc, char* argv[]){ // do not disable watchdog when MCU halts on breakpoints DBGMCU->APB1FZR1 &= (0xFFFFFFFF ^ DBGMCU_APB1FZR1_DBG_IWDG_STOP); -#endif - #endif // initialize i2c controller @@ -1050,10 +1044,8 @@ int main(int argc, char* argv[]){ umb_0x26_status_request(&rte_wx_umb, &rte_wx_umb_context, main_config_data_umb); } -#ifdef INTERNAL_WATCHDOG // reload watchdog counter main_reload_internal_wdg(); -#endif io_ext_watchdog_service(); @@ -1133,7 +1125,7 @@ int main(int argc, char* argv[]){ main_set_monitor(0); #if defined(PARAMETEO) - if (main_woken_up == 1) { + if (rte_main_woken_up == RTE_MAIN_WOKEN_UP_EXITED) { // restart ADCs io_vbat_meas_enable(); @@ -1160,7 +1152,7 @@ int main(int argc, char* argv[]){ ax25_init(&main_ax25, &main_afsk, 0, message_callback, 0); //TimerConfig(); - main_woken_up = 0; + rte_main_woken_up = 0; main_check_adc = 1; @@ -1522,9 +1514,7 @@ int main(int argc, char* argv[]){ #ifdef PARAMETEO max31865_pool(); #endif - #ifdef INTERNAL_WATCHDOG main_reload_internal_wdg(); - #endif main_two_second_pool_timer = 2000; } @@ -1552,7 +1542,7 @@ int main(int argc, char* argv[]){ } // inhibit any power save switching when modem transmits data - if (!main_afsk.sending && main_woken_up == 0) { + if (!main_afsk.sending && rte_main_woken_up == 0) { pwr_save_pooling_handler(main_config_data_mode, main_config_data_basic, packet_tx_get_minutes_to_next_wx(), rte_main_average_battery_voltage); } @@ -1637,7 +1627,6 @@ void main_service_cpu_load_ticks(void) { } void main_reload_internal_wdg(void){ -#ifdef INTERNAL_WATCHDOG #ifdef STM32F10X_MD_VL // reload watchdog counter @@ -1647,7 +1636,6 @@ void main_reload_internal_wdg(void){ #ifdef STM32L471xx LL_IWDG_ReloadCounter(IWDG); #endif -#endif } uint32_t main_get_nvm_timestamp(void) { diff --git a/src/pwr_save.c b/src/pwr_save.c index d125132..c3d4875 100644 --- a/src/pwr_save.c +++ b/src/pwr_save.c @@ -47,6 +47,11 @@ int8_t pwr_save_seconds_to_wx = 0; int16_t pwr_save_sleep_time_in_seconds = -1; +/** + * Number of 30 seconds cycles of SLEEP2 in L6 and L7 powersave mode + */ +int8_t pwr_save_number_of_sleep_cycles = -1; + /** * Variable stores cutoff state and to save RAM it also keeps a low battery voltage flag */ @@ -110,9 +115,9 @@ void pwr_save_init(config_data_powersave_mode_t mode) { // definition of bitmask #define IWDG_STBY_STOP (0x3 << 17) - // check if IWDG_STDBY and IWDG_STOP is not set in ''User and read protection option bytes'' + // check if IWDG_STDBY and IWDG_STOP is set in ''User and read protection option bytes'' // at 0x1FFF7800 - if ((option_byte_content & IWDG_STBY_STOP) == IWDG_STBY_STOP) { + if ((option_byte_content & IWDG_STBY_STOP) != IWDG_STBY_STOP) { // unlock write/erase operations on flash memory FLASH->KEYR = 0x45670123; @@ -126,7 +131,8 @@ void pwr_save_init(config_data_powersave_mode_t mode) { FLASH->OPTKEYR = 0x4C5D6E7F; // set the flash option register (in RAM!!) - FLASH->OPTR &= (0xFFFFFFFF ^ (FLASH_OPTR_IWDG_STDBY | FLASH_OPTR_IWDG_STOP)); + FLASH->OPTR |= FLASH_OPTR_IWDG_STDBY; + FLASH->OPTR |= FLASH_OPTR_IWDG_STOP; // trigger an update of flash option bytes with values from RAM (from FLASH->OPTR) FLASH->CR |= FLASH_CR_OPTSTRT; @@ -172,6 +178,9 @@ void pwr_save_enter_stop2(void) { // set 31st monitor bit main_set_monitor(31); + // reload internal watchdog + main_reload_internal_wdg(); + // clear main battery voltage to be sure that it'd be updated??? rte_main_battery_voltage = 0; @@ -201,6 +210,8 @@ void pwr_save_enter_stop2(void) { counter++; + rte_main_going_sleep_count = counter; + REGISTER_COUNTERS = (REGISTER_COUNTERS & 0xFFFF0000) | counter; pwr_save_lock_rtc_backup_regs(); @@ -217,6 +228,31 @@ void pwr_save_enter_stop2(void) { } +void pwr_save_check_stop2_cycles(void) { + + while(1) { + // decrement stop2 cycles for current L7 or L6 powersave mode + pwr_save_number_of_sleep_cycles--; + + // if there is time left to exit from depp sleep + if (pwr_save_number_of_sleep_cycles > 0) { + main_set_monitor(15); + + // go back to sleep + // configure how long micro should sleep + system_clock_configure_auto_wakeup_l4(PWR_SAVE_STOP2_CYCLE_LENGHT_SEC); + + pwr_save_enter_stop2(); + } + else { + main_set_monitor(14); + + // we are done sleeping so exit from this loop + break; + } + } +} + /** * This function has to be called within RTC wakepup interrupt. */ @@ -238,6 +274,9 @@ void pwr_save_exit_from_stop2(void) { counter++; + // store current wakeup counter in RTE + rte_main_wakeup_count = counter; + // check counter overflow conditions if (counter > 0xFFFF) { counter = 0; @@ -577,6 +616,11 @@ void pwr_save_switch_mode_to_i5(void) { // this will keep external VHF radio working in HW-RevB void pwr_save_switch_mode_to_l6(uint16_t sleep_time) { + if (sleep_time > 3000u) { + // this is an error situation + sleep_time = 3000u; + } + if (system_is_rtc_ok() == 0) { pwr_save_switch_mode_to_i5(); @@ -587,6 +631,9 @@ void pwr_save_switch_mode_to_l6(uint16_t sleep_time) { return; } + // calculate amount of STOP2 cycles + pwr_save_number_of_sleep_cycles = (int8_t)(sleep_time / PWR_SAVE_STOP2_CYCLE_LENGHT_SEC) & 0x7Fu; + main_set_monitor(28); // disable ADC used for vbat measurement @@ -627,7 +674,7 @@ void pwr_save_switch_mode_to_l6(uint16_t sleep_time) { // lock access to backup pwr_save_lock_rtc_backup_regs(); - system_clock_configure_auto_wakeup_l4(sleep_time); + system_clock_configure_auto_wakeup_l4(PWR_SAVE_STOP2_CYCLE_LENGHT_SEC); // save how long the micro will sleep - required for handling wakeup event pwr_save_sleep_time_in_seconds = sleep_time; @@ -644,6 +691,12 @@ void pwr_save_switch_mode_to_l6(uint16_t sleep_time) { } void pwr_save_switch_mode_to_l7(uint16_t sleep_time) { + + if (sleep_time > 3000u) { + // this is an error situation + sleep_time = 3000u; + } + /////////// if (system_is_rtc_ok() == 0) { pwr_save_switch_mode_to_i5(); @@ -655,6 +708,9 @@ void pwr_save_switch_mode_to_l7(uint16_t sleep_time) { return; } + // calculate amount of STOP2 cycles + pwr_save_number_of_sleep_cycles = (int8_t)(sleep_time / PWR_SAVE_STOP2_CYCLE_LENGHT_SEC) & 0x7Fu; + main_set_monitor(26); // disconnect APRS-IS connection if it is established @@ -699,7 +755,7 @@ void pwr_save_switch_mode_to_l7(uint16_t sleep_time) { pwr_save_lock_rtc_backup_regs(); // configure how long micro should sleep - system_clock_configure_auto_wakeup_l4(sleep_time); + system_clock_configure_auto_wakeup_l4(PWR_SAVE_STOP2_CYCLE_LENGHT_SEC); // save how long the micro will sleep - required for handling wakeup event pwr_save_sleep_time_in_seconds = sleep_time; @@ -962,7 +1018,7 @@ config_data_powersave_mode_t pwr_save_pooling_handler(const config_data_mode_t * // if stations is configured to send wx packet less frequent than every 5 minutes if (minutes_to_wx > 1) { - main_set_monitor(16); + main_set_monitor(17); // if there is more than one minute to wx packet pwr_save_switch_mode_to_l7((timers->wx_transmit_period * 60) - 60); // TODO: !!! @@ -987,7 +1043,7 @@ config_data_powersave_mode_t pwr_save_pooling_handler(const config_data_mode_t * // if station is configured to sent wx packet in every 5 minutes or more often if (minutes_to_wx > 1) { - main_set_monitor(15); + main_set_monitor(17); pwr_save_switch_mode_to_l6((timers->wx_transmit_period * 60) - 60); // TODO: !!! } @@ -1009,7 +1065,7 @@ config_data_powersave_mode_t pwr_save_pooling_handler(const config_data_mode_t * } else { // WX if (minutes_to_wx > 1) { - main_set_monitor(14); + main_set_monitor(17); // if there is more than one minute to send wx packet pwr_save_switch_mode_to_l7((timers->wx_transmit_period * 60) - 60); @@ -1043,6 +1099,24 @@ config_data_powersave_mode_t pwr_save_pooling_handler(const config_data_mode_t * } } + main_set_monitor(16); + + // check if we are just after waking up from STOP2 mode + if (rte_main_woken_up == RTE_MAIN_WOKEN_UP_RTC_INTERRUPT) { + + // if yes set curent state + rte_main_woken_up = RTE_MAIN_WOKEN_UP_AFTER_RTC_IT; + + // check if this is an intermediate wakeup from STOP2 + pwr_save_check_stop2_cycles(); + + system_clock_configure_l4(); + + pwr_save_exit_from_stop2(); + + rte_main_woken_up = RTE_MAIN_WOKEN_UP_EXITED; + } + main_set_monitor(13); if (reinit_sensors != 0) { diff --git a/src/rte_main.c b/src/rte_main.c index 21b7dc9..9f6c1a7 100644 --- a/src/rte_main.c +++ b/src/rte_main.c @@ -19,8 +19,13 @@ uint8_t rte_main_trigger_modbus_status = 0; uint8_t rte_main_trigger_wx_packet = 0; #ifdef PARAMETEO +//!< Trigger some reinitialization after waking up from deep sleep +uint8_t rte_main_woken_up = 0; + +//!< Current battery voltage as 10mV increments uint16_t rte_main_battery_voltage; +//!< Average battery voltage as 10mV increments, lenght configured by VBATT_HISTORY_LN uint16_t rte_main_average_battery_voltage = 0; uint16_t rte_main_wakeup_count = 0; @@ -29,6 +34,7 @@ uint16_t rte_main_going_sleep_count = 0; uint32_t rte_main_last_sleep_master_time = 0; +//!< Set to one after waking up from L7 / L6 powersave mode and uint8_t rte_main_reset_gsm_modem = 0; config_data_powersave_mode_t rte_main_curret_powersave_mode;