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;