diff --git a/include/etc/pwr_save_configuration.h b/include/etc/pwr_save_configuration.h index 20c0a29..82ab5bc 100644 --- a/include/etc/pwr_save_configuration.h +++ b/include/etc/pwr_save_configuration.h @@ -48,7 +48,7 @@ //#define INHIBIT_CUTOFF /** - * Intermediate STOP2 cycle lenght within L7 or L6 mode. + * Intermediate STOP2 cycle length within L7 or L6 mode. */ #define PWR_SAVE_STOP2_CYCLE_LENGHT_SEC 30u diff --git a/include/pwr_save.h b/include/pwr_save.h index b81360c..349aa4e 100644 --- a/include/pwr_save.h +++ b/include/pwr_save.h @@ -117,7 +117,10 @@ 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_after_stop2_rtc_wakeup_it(void); int pwr_save_check_stop2_cycles(void); +void pwr_save_exit_after_last_stop2_cycle(void); int pwr_save_switch_mode_to_c0(void); int pwr_save_switch_mode_to_c1(void); void pwr_save_switch_mode_to_c2(void); diff --git a/include/rte_main.h b/include/rte_main.h index a3ebef0..a663866 100644 --- a/include/rte_main.h +++ b/include/rte_main.h @@ -7,15 +7,15 @@ #include "message.h" //!< Set immediately after waking up in RTC interrupt handler -#define RTE_MAIN_WOKEN_UP_RTC_INTERRUPT 1u +#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 +#define RTE_MAIN_WOKEN_UP_AFTER_LAST_SLEEP 2u //!< Set after everything was reinitialized from -#define RTE_MAIN_WOKEN_UP_EXITED 4u +#define RTE_MAIN_WOKEN_UP_EXITED 4u -#define RTE_MAIN_GO_TO_SLEEP 8u +#define RTE_MAIN_GO_TO_INTERMEDIATE_SLEEP 8u #define RTE_MAIN_REBOOT_SCHEDULED_APRSMSG 1u @@ -45,6 +45,8 @@ extern uint8_t rte_main_trigger_radio_event_log; //!< Trigger some reinitialization after waking up from deep sleep extern uint8_t rte_main_woken_up; +extern uint8_t rte_main_woken_up_for_telemetry; + extern uint8_t rte_main_reboot_req; extern uint8_t rte_main_reboot_scheduled_diag; diff --git a/include/software_version.h b/include/software_version.h index 42be3ef..aa52477 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 "EC03" -#define SW_DATE "17102024" +#define SW_VER "EC04" +#define SW_DATE "21102024" #define SW_KISS_PROTO "C" extern const char software_version_str[5]; diff --git a/src/main.c b/src/main.c index 4fb2c60..b213e3f 100644 --- a/src/main.c +++ b/src/main.c @@ -7,7 +7,7 @@ #include #endif -#ifdef STM32L471xx +#ifdef STM32L471xx ///////// #include #include #include @@ -37,7 +37,9 @@ #include "ntp.h" #include "gsm_comm_state_handler.h" -#endif + +#include "./etc/pwr_save_configuration.h" +#endif //////// #include #include @@ -290,6 +292,8 @@ static uint8_t main_kiss_response_message[32]; static io_vbat_state_t main_battery_measurement_res; +static uint8_t main_continue_loop = 0; + //!< Array to extract events from NVM into. *2 is applied to have more room for data sent to API static event_log_exposed_t main_exposed_events[MAIN_HOW_MANY_EVENTS_SEND_REPORT * 3]; #endif @@ -1521,13 +1525,29 @@ int main(int argc, char* argv[]){ backup_reg_set_monitor(0); #if defined(PARAMETEO) - if (rte_main_woken_up == RTE_MAIN_WOKEN_UP_RTC_INTERRUPT) { - pwr_save_after_stop2_rtc_wakeup_it(); - } - else if (rte_main_woken_up == RTE_MAIN_WOKEN_UP_AFTER_RTC_IT) { + if (rte_main_woken_up == RTE_MAIN_GO_TO_INTERMEDIATE_SLEEP) { + // this sleep is used by @link{pwr_save_after_stop2_rtc_wakeup_it} to + // go to the intermediate sleep in L4 powersave mode, when xxx seconds + // long sleep is divided into 'PWR_SAVE_STOP2_CYCLE_LENGHT_SEC' to + // serwice IWDG in between + system_clock_configure_auto_wakeup_l4(PWR_SAVE_STOP2_CYCLE_LENGHT_SEC); + pwr_save_enter_stop2(); } - if (rte_main_woken_up == RTE_MAIN_WOKEN_UP_EXITED) { + else if (rte_main_woken_up == RTE_MAIN_WOKEN_UP_RTC_INTERRUPT) { + // controller is woken up from sleep in stop2 mode, now it must + // be checked if this was the last sleep in the row, or micro + // must go to sleep (stop2 mode) once again + pwr_save_after_stop2_rtc_wakeup_it(); + } + else if (rte_main_woken_up == RTE_MAIN_WOKEN_UP_AFTER_LAST_SLEEP) { + system_clock_configure_l4(); + + pwr_save_exit_after_last_stop2_cycle(); + + rte_main_woken_up = RTE_MAIN_WOKEN_UP_EXITED; + } + else if (rte_main_woken_up == RTE_MAIN_WOKEN_UP_EXITED) { // restart ADCs io_vbat_meas_enable(); @@ -1555,6 +1575,8 @@ int main(int argc, char* argv[]){ rte_main_woken_up = 0; + rte_main_reset_gsm_modem = 1; + main_check_adc = 1; // reinitialize UART used to communicate with GPRS modem @@ -1562,9 +1584,6 @@ int main(int argc, char* argv[]){ backup_reg_set_monitor(1); } - else if (rte_main_woken_up == RTE_MAIN_GO_TO_SLEEP) { - - } else { #endif @@ -2160,7 +2179,11 @@ int main(int argc, char* argv[]){ // inhibit any power save switching when modem transmits data if (!main_afsk.sending && rte_main_woken_up == 0 && packet_tx_is_gsm_meteo_pending() == 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, rte_main_battery_voltage); + pwr_save_pooling_handler(main_config_data_mode, main_config_data_basic, packet_tx_get_minutes_to_next_wx(), rte_main_average_battery_voltage, rte_main_battery_voltage, &main_continue_loop); + } + + if (main_continue_loop == 0) { + continue; } if ((main_config_data_mode->wx_dust_sensor & WX_DUST_SDS011_PWM) > 0) { diff --git a/src/pwr_save.c b/src/pwr_save.c index 61506d5..a8e711a 100644 --- a/src/pwr_save.c +++ b/src/pwr_save.c @@ -132,11 +132,76 @@ static void pwr_save_clear_powersave_idication_bits() { pwr_save_lock_rtc_backup_regs(); } +/** + * This function initializes everything related to power saving features + * including programming Flash memory option bytes + */ +void pwr_save_init(config_data_powersave_mode_t mode) { + + // make a pointer to option byte + uint32_t* option_byte = (uint32_t*)0x1FFF7800; + + // content of option byte read from the flash memory + uint32_t option_byte_content = *option_byte; + + // definition of bitmask + #define IWDG_STBY_STOP (0x3 << 17) + + // 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) { + + // unlock write/erase operations on flash memory + FLASH->KEYR = 0x45670123; + FLASH->KEYR = 0xCDEF89AB; + + // wait for any possible flash operation to finish (rather impossible here, but ST manual recommend doing this) + while((FLASH->SR & FLASH_SR_BSY) != 0); + + // unlock operations on option bytes + FLASH->OPTKEYR = 0x08192A3B; + FLASH->OPTKEYR = 0x4C5D6E7F; + + // set the flash option register (in RAM!!) + 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; + + // wait for option bytes to be updated + while((FLASH->SR & FLASH_SR_BSY) != 0); + + // lock flash memory + FLASH-> CR |= FLASH_CR_LOCK; + + // forcre reloading option bytes + FLASH->CR |= FLASH_CR_OBL_LAUNCH; + + } + + // reset a status register + backup_reg_reset_all_powersave_states(); + backup_reg_reset_inhibit_periodic_pwr_switch(); + + // switch power switch handler inhibition if it is needed + switch (mode) { + case PWSAVE_NONE: + break; + case PWSAVE_NORMAL: + case PWSAVE_AGGRESV: + backup_reg_inhibit_periodic_pwr_switch(); + break; + } + + +} + /** * Entering STOP2 power save mode. In this mode all clocks except LSI and LSE are disabled. StaticRAM content * is preserved, optionally GPIO and few other peripherals can be kept power up depending on configuration */ -static void pwr_save_enter_stop2(void) { +void pwr_save_enter_stop2(void) { // set 31st monitor bit backup_reg_set_monitor(31); @@ -182,11 +247,89 @@ static void pwr_save_enter_stop2(void) { } +/** + * This function is called in two places within a pooler. + * 1st: just after the micro wakes up from STOP2 deep sleep caused by low battery + * voltage and returns from an interrupt + * from RTC interrupt handler. + * 2nd: just after the micro wakes up from STOP2 caues by aggressive powersave + * configuration. + */ +void pwr_save_after_stop2_rtc_wakeup_it(void) { + + // if yes set curent state + rte_main_woken_up = RTE_MAIN_WOKEN_UP_AFTER_LAST_SLEEP; + +// // check if this is an intermediate wakeup from STOP2 +// pwr_save_check_stop2_cycles(); +// +// system_clock_configure_l4(); +// +// pwr_save_exit_after_last_stop2_cycle(); + + // reload internal watchdog + main_reload_internal_wdg(); + + // 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) { + backup_reg_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(); + rte_main_woken_up = RTE_MAIN_GO_TO_INTERMEDIATE_SLEEP; + } + else { + backup_reg_set_monitor(14); + + rte_main_woken_up = RTE_MAIN_WOKEN_UP_AFTER_LAST_SLEEP; + rte_main_woken_up_for_telemetry = 1; + + max31865_set_state_after_wkup(); // TODO: tatry variant + } + +} + +/** + * Used after each of 30 seconds long STOP2 sleep, to check + * how many sleeps the micro must be put in, to complete + * L6/L7 powersave mode + */ +//int 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) { +// backup_reg_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 { +// backup_reg_set_monitor(14); +// +// // we are done sleeping so exit from this loop +// break; +// } +// } +//} + /** * This function has to be called after last 30 second long cycle of STOP2 sleep, * to bounce all frames transmission counters. */ -static void pwr_save_exit_after_last_stop2_cycle(void) { +void pwr_save_exit_after_last_stop2_cycle(void) { uint32_t counter = 0; @@ -269,128 +412,6 @@ static void pwr_save_exit_after_last_stop2_cycle(void) { backup_reg_set_monitor(29); } -/** - * This function is called in two places within a pooler. - * 1st: just after the micro wakes up from STOP2 deep sleep caused by low battery - * voltage and returns from an interrupt - * from RTC interrupt handler. - * 2nd: just after the micro wakes up from STOP2 caues by aggressive powersave - * configuration. - */ -static void pwr_save_after_stop2_rtc_wakeup_it(void) { - // 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_after_last_stop2_cycle(); - - rte_main_woken_up = RTE_MAIN_WOKEN_UP_EXITED; - } - -} - -/** - * This function initializes everything related to power saving features - * including programming Flash memory option bytes - */ -void pwr_save_init(config_data_powersave_mode_t mode) { - - // make a pointer to option byte - uint32_t* option_byte = (uint32_t*)0x1FFF7800; - - // content of option byte read from the flash memory - uint32_t option_byte_content = *option_byte; - - // definition of bitmask - #define IWDG_STBY_STOP (0x3 << 17) - - // 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) { - - // unlock write/erase operations on flash memory - FLASH->KEYR = 0x45670123; - FLASH->KEYR = 0xCDEF89AB; - - // wait for any possible flash operation to finish (rather impossible here, but ST manual recommend doing this) - while((FLASH->SR & FLASH_SR_BSY) != 0); - - // unlock operations on option bytes - FLASH->OPTKEYR = 0x08192A3B; - FLASH->OPTKEYR = 0x4C5D6E7F; - - // set the flash option register (in RAM!!) - 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; - - // wait for option bytes to be updated - while((FLASH->SR & FLASH_SR_BSY) != 0); - - // lock flash memory - FLASH-> CR |= FLASH_CR_LOCK; - - // forcre reloading option bytes - FLASH->CR |= FLASH_CR_OBL_LAUNCH; - - } - - // reset a status register - backup_reg_reset_all_powersave_states(); - backup_reg_reset_inhibit_periodic_pwr_switch(); - - // switch power switch handler inhibition if it is needed - switch (mode) { - case PWSAVE_NONE: - break; - case PWSAVE_NORMAL: - case PWSAVE_AGGRESV: - backup_reg_inhibit_periodic_pwr_switch(); - break; - } - - -} - -/** - * Used after each of 30 seconds long STOP2 sleep, to check - * how many sleeps the micro must be put in, to complete - * L6/L7 powersave mode - */ -int 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) { - backup_reg_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 { - backup_reg_set_monitor(14); - - // we are done sleeping so exit from this loop - break; - } - } -} - int pwr_save_switch_mode_to_c0(void) { @@ -890,9 +911,11 @@ config_data_powersave_mode_t pwr_save_pooling_handler( const config_data_mode_t uint8_t * continue_loop) { // this function should be called from 10 seconds pooler + *continue_loop = 1; + int8_t reinit_sensors = 0; - int8_t reinit_gprs = 0; + //int8_t reinit_gprs = 0; packet_tx_counter_values_t counters; @@ -968,7 +991,8 @@ config_data_powersave_mode_t pwr_save_pooling_handler( const config_data_mode_t pwr_save_switch_mode_to_l7(60 * PWR_SAVE_CUTOFF_SLEEP_TIME_IN_MINUTES); // RTC interrupt is between this call and previous one (switching to l7) - pwr_save_after_stop2_rtc_wakeup_it(); + //pwr_save_after_stop2_rtc_wakeup_it(); + *continue_loop = 0; return psave_mode; } @@ -1117,8 +1141,10 @@ config_data_powersave_mode_t pwr_save_pooling_handler( const config_data_mode_t // if there is more than two minutes to send wx packet pwr_save_switch_mode_to_l7((timers->wx_transmit_period * 60) - (WAKEUP_PERIOD_BEFORE_WX_FRAME_IN_MINUTES * 60)); + *continue_loop = 0; + // GSM module is kept turned on, but the connection must be reastablished - reinit_gprs = 1; + //reinit_gprs = 1; } else { // TODO: Workaround here for HW-RevB!!! @@ -1163,7 +1189,9 @@ config_data_powersave_mode_t pwr_save_pooling_handler( const config_data_mode_t // if there is more than WAKEUP_PERIOD_BEFORE_WX_FRAME_IN_MINUTES minutes to wx packet pwr_save_switch_mode_to_l7((timers->wx_transmit_period * 60) - (WAKEUP_PERIOD_BEFORE_WX_FRAME_IN_MINUTES * 60)); // TODO: !!! - reinit_gprs = 1; + *continue_loop = 0; + + //reinit_gprs = 1; } else { @@ -1189,7 +1217,9 @@ config_data_powersave_mode_t pwr_save_pooling_handler( const config_data_mode_t // if there is more than WAKEUP_PERIOD_BEFORE_WX_FRAME_IN_MINUTES minutes to send wx packet pwr_save_switch_mode_to_l7((timers->wx_transmit_period * 60) - (WAKEUP_PERIOD_BEFORE_WX_FRAME_IN_MINUTES * 60)); - reinit_gprs = 1; + *continue_loop = 0; + + //reinit_gprs = 1; } else { if (pwr_save_seconds_to_wx <= 30) { @@ -1222,14 +1252,14 @@ config_data_powersave_mode_t pwr_save_pooling_handler( const config_data_mode_t backup_reg_set_monitor(16); - pwr_save_after_stop2_rtc_wakeup_it(); + //pwr_save_after_stop2_rtc_wakeup_it(); backup_reg_set_monitor(13); - if (reinit_gprs != 0) { - // reset GSM modem, internally this also check if GSM modem is inhibited or not - rte_main_reset_gsm_modem = 1; - } +// if (reinit_gprs != 0) { +// // reset GSM modem, internally this also check if GSM modem is inhibited or not +// rte_main_reset_gsm_modem = 1; +// } if (reinit_sensors != 0) { // reinitialize all i2c sensors diff --git a/src/rte_main.c b/src/rte_main.c index 7f711b1..6aa321f 100644 --- a/src/rte_main.c +++ b/src/rte_main.c @@ -55,6 +55,8 @@ uint8_t rte_main_trigger_radio_event_log = 0; //!< Trigger some reinitialization after waking up from deep sleep uint8_t rte_main_woken_up = 0; +uint8_t rte_main_woken_up_for_telemetry = 0; + //!< Current battery voltage as 10mV increments uint16_t rte_main_battery_voltage;