diff --git a/STM32L476_ParaMETEO/src/subdir.mk b/STM32L476_ParaMETEO/src/subdir.mk index 9709106..840c327 100644 --- a/STM32L476_ParaMETEO/src/subdir.mk +++ b/STM32L476_ParaMETEO/src/subdir.mk @@ -26,6 +26,7 @@ C_SRCS += \ ../src/rte_rtu.c \ ../src/rte_wx.c \ ../src/software_version.c \ +../src/variant_parameteo.c \ ../src/wx_handler.c \ ../src/wx_handler_humidity.c \ ../src/wx_handler_pressure.c \ @@ -55,6 +56,7 @@ OBJS += \ ./src/rte_rtu.o \ ./src/rte_wx.o \ ./src/software_version.o \ +./src/variant_parameteo.o \ ./src/wx_handler.o \ ./src/wx_handler_humidity.o \ ./src/wx_handler_pressure.o \ @@ -84,6 +86,7 @@ C_DEPS += \ ./src/rte_rtu.d \ ./src/rte_wx.d \ ./src/software_version.d \ +./src/variant_parameteo.d \ ./src/wx_handler.d \ ./src/wx_handler_humidity.d \ ./src/wx_handler_pressure.d \ diff --git a/include/backup_registers.h b/include/backup_registers.h index f387eec..94425e3 100644 --- a/include/backup_registers.h +++ b/include/backup_registers.h @@ -16,23 +16,6 @@ #include #endif -// backup registers (ParaTNC) -// 0 -> -// 2 -> boot and hard fault count -// 3 -> controller configuration status -// 4 -> -// 5 -> -// 6 -> weather and telemetry timers & counters - -// backup registers (ParaMETEO) -// 0 -> powersave status - not handled here -// 1 -> last sleep rtc time -// 2 -> last wakeup rtc time -// 3 -> controller configuration status -// 4 -> wakeup events MSB, sleep events LSB -// 5 -> monitor -// 7 -> weather and telemetry timers & counters - #define REGISTER_MONITOR RTC->BKP5R /** @@ -90,9 +73,13 @@ uint32_t backup_reg_is_periodic_pwr_switch_inhibited(void); uint32_t backup_reg_get_last_sleep_duration(void); void backup_reg_set_last_sleep_duration(uint32_t); -uint8_t backup_reg_get_telemetry(void); -void backup_reg_set_telemetry(void); +void backup_reg_reset_counters(void); +uint8_t backup_reg_get_telemetry(void); +void backup_reg_set_telemetry(uint8_t); + +void backup_reg_get_packet_counters(uint8_t * beacon_counter, uint8_t * meteo_counter, uint8_t * meteo_gsm_counter); +void backup_reg_set_packet_counters(uint8_t beacon_counter, uint8_t meteo_counter, uint8_t meteo_gsm_counter); diff --git a/include/main.h b/include/main.h index a94f5d3..5b33eed 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/packet_tx_handler.h b/include/packet_tx_handler.h index b690e8a..75487f4 100644 --- a/include/packet_tx_handler.h +++ b/include/packet_tx_handler.h @@ -21,7 +21,7 @@ typedef struct packet_tx_counter_values_t { } packet_tx_counter_values_t; void packet_tx_send_wx_frame(void); -void packet_tx_configure(uint8_t meteo_interval, uint8_t beacon_interval, config_data_powersave_mode_t powersave); +void packet_tx_init(uint8_t meteo_interval, uint8_t beacon_interval, config_data_powersave_mode_t powersave); void packet_tx_restore_from_backupregs(void); void packet_tx_tcp_handler(void); void packet_tx_handler(const config_data_basic_t * const config_basic, const config_data_mode_t * const config_mode); diff --git a/include/variant.h b/include/variant.h new file mode 100644 index 0000000..48f8535 --- /dev/null +++ b/include/variant.h @@ -0,0 +1,17 @@ +/* + * variant.h + * + * Created on: Oct 24, 2023 + * Author: mateusz + */ + +#ifndef VARIANT_H_ +#define VARIANT_H_ + +#include "stdint.h" + +int variant_validate_is_within_ram(uint32_t address); + + + +#endif /* VARIANT_H_ */ diff --git a/src/backup_registers.c b/src/backup_registers.c index b4c0c35..d8642d3 100644 --- a/src/backup_registers.c +++ b/src/backup_registers.c @@ -7,17 +7,46 @@ #include "backup_registers.h" +#include "variant.h" + #ifdef STM32L471xx -#define REGISTER RTC->BKP0R -#define REGISTER_LAST_SLEEP RTC->BKP1R -#define REGISTER_LAST_WKUP RTC->BKP2R -#define REGISTER_COUNTERS RTC->BKP4R -#define REGISTER_LAST_SLTIM RTC->BKP6R +#define REGISTER RTC->BKP0R +#define REGISTER_LAST_SLEEP RTC->BKP1R +#define REGISTER_LAST_WKUP RTC->BKP2R +#define REGISTER_COUNTERS RTC->BKP4R +#define REGISTER_LAST_SLTIM RTC->BKP6R +#define REGISTER_PACKET_COUNTERS RTC->BKP7R #endif #define BACKUP_REG_INHIBIT_PWR_SWITCH_PERIODIC_H 1u #define BACKUP_REG_ALL_PWRSAVE_STATES_BITMASK (0xFFu << 2) +// backup registers (ParaTNC) +// 0 -> +// 2 -> boot and hard fault count +// 3 -> controller configuration status +// 4 -> telemetry counter +// 5 -> +// 6 -> weather counters + + +// backup registers (ParaMETEO) +// 0 -> powersave status +// 1 -> last sleep rtc time +// 2 -> last wakeup rtc time +// 3 -> controller configuration status +// 4 -> wakeup events MSB, sleep events LSB +// 5 -> monitor +// 6 -> last sleep time +// 7 -> weather and telemetry timers & counters + +// 7th register map +// xxxxyyAA - telemetry frames counter +// xxxxyAyy - value of packet_tx_meteo_counter limited to 15 +// xxxxAyyy - value of packet_tx_meteo_gsm_counter limited to 15 +// xxAAyyyy - value of packet_tx_beacon_counter +// Axxxyyyy - checksum + static void backup_reg_unclock(void) { // enable access to backup domain PWR->CR1 |= PWR_CR1_DBP; @@ -28,7 +57,54 @@ static void backup_reg_lock(void) { } /** - * + * Calculates checksum from register content + * @param reg + * @return + */ +inline static uint8_t backup_reg_calculate_checksum(uint32_t reg) { + + uint8_t out = 0u; + + uint32_t temp = 0u; + + temp += (reg & 0xFu); + temp += ((reg & 0xF0u) >> 4); + temp += ((reg & 0xF00u) >> 8); + temp += ((reg & 0xF000u) >> 12); + temp += ((reg & 0xF0000u) >> 16); + temp += ((reg & 0xF00000u) >> 20); + temp += ((reg & 0xF000000u) >> 24); + + temp = ~temp; + + out = (temp & 0xFu); + + return out; +} + +inline static uint8_t backup_reg_get_checksum(uint32_t reg) { + + uint8_t out = 0u; + + out = ((reg & 0xF0000000u) >> 28); + + return out; +} + +inline static void backup_reg_set_checksum(volatile uint32_t * reg, const uint8_t checksum) { + + if (variant_validate_is_within_ram((const uint32_t)reg) != 0) { + // clear existing checksum + (*reg) &= (0xFFFFFFFF ^ 0xF0000000); + + // store new checksum + (*reg) |= ((checksum & 0xF) << 28); + } +} + +/** + * Get the value of a register keeping a status which configuration + * sector is valid, and which is loaded * @return */ uint32_t backup_reg_get_configuration(void) { @@ -47,20 +123,32 @@ uint32_t backup_reg_get_configuration(void) { return out; } +/** + * Set a register, which contains an information which configuration sector + * is valid, and which one has been loaded. It is mostly used to reset + * the register back to zero. + * @param value + */ void backup_reg_set_configuration(uint32_t value) { + backup_reg_unclock(); + #ifdef PARATNC BKP->DR3 = value; #endif #ifdef PARAMETEO - backup_reg_unclock(); - RTC->BKP3R = value; +#endif backup_reg_lock(); -#endif + } +/** + * Set certain bit in the register containing current configuration state. + * This is used to store a state of all configuration sectors. + * @param value + */ void backup_reg_set_bits_configuration(uint32_t value) { #ifdef PARATNC BKP->DR3 |= value; @@ -77,24 +165,30 @@ void backup_reg_set_bits_configuration(uint32_t value) { #endif } +/** + * Clears certain bit in the register containing current configuration state. + * This is used to keep information that CRC checksum of a sector is no longer + * valid. + * @param value + */ void backup_reg_clear_bits_configuration(uint32_t value) { + // enable access to backup domain + backup_reg_unclock(); + #ifdef PARATNC BKP->DR3 &= (0xFFFF ^ value); #endif #ifdef PARAMETEO - // enable access to backup domain - backup_reg_unclock(); - RTC->BKP3R &= (0xFFFFFFFFu ^ value); +#endif backup_reg_lock(); -#endif } /** - * + * Resets all powersave mode flags. */ void backup_reg_reset_all_powersave_states(void) { @@ -108,6 +202,12 @@ void backup_reg_reset_all_powersave_states(void) { } +/** + * Checks if controller is currently in given powersave mode using + * information from dedicated backup register + * @param state + * @return one if controller is in given powersave state + */ int backup_reg_is_in_powersave_state(uint32_t state) { int out = 0; #ifdef PARAMETEO @@ -119,6 +219,11 @@ int backup_reg_is_in_powersave_state(uint32_t state) { return out; } +/** + * Set that controller is currently in given powersave state, it should be + * used along with \link #backup_reg_reset_all_powersave_states + * @param state + */ void backup_reg_set_powersave_state(uint32_t state) { #ifdef PARAMETEO backup_reg_unclock(); @@ -129,6 +234,10 @@ void backup_reg_set_powersave_state(uint32_t state) { #endif } +/** + * Returns current powersave state + * @return + */ uint16_t backup_reg_get_powersave_state(void) { int out = 0; @@ -140,7 +249,7 @@ uint16_t backup_reg_get_powersave_state(void) { } /** - * + * Return counter value with current number of wakeup events * @return */ uint32_t backup_reg_get_wakeup_counter(void) { @@ -154,6 +263,10 @@ uint32_t backup_reg_get_wakeup_counter(void) { return out; } +/** + * Set current value of wakeup events + * @param in + */ void backup_reg_set_wakeup_counter(uint32_t in) { backup_reg_unclock(); @@ -165,7 +278,7 @@ void backup_reg_set_wakeup_counter(uint32_t in) { } /** - * + * Return counter value with current number of sleep events * @return */ uint32_t backup_reg_get_sleep_counter(void) { @@ -178,6 +291,10 @@ uint32_t backup_reg_get_sleep_counter(void) { return out; } +/** + * Set current value of sleep events + * @param in + */ void backup_reg_set_sleep_counter(uint32_t in) { backup_reg_unclock(); @@ -190,7 +307,7 @@ void backup_reg_set_sleep_counter(uint32_t in) { /** - * + * Returns a timestamp of last sleep event */ uint32_t backup_reg_get_last_sleep_timestamp(void) { @@ -203,6 +320,9 @@ uint32_t backup_reg_get_last_sleep_timestamp(void) { return out; } +/** + * Stores a timestamp of a sleep event from current RTC time + */ void backup_reg_set_last_sleep_timestamp(void) { #ifdef PARAMETEO @@ -216,9 +336,9 @@ void backup_reg_set_last_sleep_timestamp(void) { } /** - * + * Disables an inhibition of VBATT_S switching, when controller is in + * powersave mode in which weather sensors shall be kept powered down. */ - void backup_reg_reset_inhibit_periodic_pwr_switch(void) { backup_reg_unclock(); @@ -229,6 +349,10 @@ void backup_reg_reset_inhibit_periodic_pwr_switch(void) { backup_reg_lock(); } +/** + * Enables an inhibition of VBATT_S switching, when controller is in + * powersave mode in which weather sensors shall be kept powered down. + */ void backup_reg_inhibit_periodic_pwr_switch(void) { backup_reg_unclock(); @@ -240,6 +364,10 @@ void backup_reg_inhibit_periodic_pwr_switch(void) { } +/** + * Returns if VBATT_S switching inhibition is currently enabled + * @return + */ uint32_t backup_reg_is_periodic_pwr_switch_inhibited(void) { int out = 0; @@ -253,7 +381,7 @@ uint32_t backup_reg_is_periodic_pwr_switch_inhibited(void) { } /** - * + * gets last wakeup timestamp * @return */ uint32_t backup_reg_get_last_wakeup_timestamp(void) { @@ -265,6 +393,9 @@ uint32_t backup_reg_get_last_wakeup_timestamp(void) { return out; } +/** + * Stores a timestamp of a wakeup event from current RTC time + */ void backup_reg_set_last_wakeup_timestamp(void) { #ifdef PARAMETEO @@ -301,3 +432,137 @@ void backup_reg_set_last_sleep_duration(uint32_t in) { #endif } +/** + * Set register containing packet counters, used when a configuration + * is reset to default + */ +void backup_reg_reset_counters(void) { +#ifdef PARAMETEO + backup_reg_unclock(); + + REGISTER_PACKET_COUNTERS = 0u; + + backup_reg_lock(); +#endif +} + +/** + * Gets last telemetry frames counter stored in backup registers + * @return last telemetry counter or zero if backup registers contains crap + */ +uint8_t backup_reg_get_telemetry(void) { + + uint8_t out = 0u; + +#ifdef PARAMETEO + + uint32_t reg_value = REGISTER_PACKET_COUNTERS; + + // calculate checksum from register value + uint8_t calculated_checksum = backup_reg_calculate_checksum(reg_value); + + uint8_t checksum_from_reg = backup_reg_get_checksum(reg_value); + + // check if checksum is ok + if (calculated_checksum == checksum_from_reg) { + out = (uint8_t)(reg_value & 0xFFu); + } + else { + ; // return zero if checksum is wrong + } + +#endif + + return out; +} + +/** + * + */ +void backup_reg_set_telemetry(uint8_t in) { + backup_reg_unclock(); + +#ifdef PARAMETEO + + // get current value + uint32_t reg_value = REGISTER_PACKET_COUNTERS; + + // clear current telemetry counter using the bitmask + reg_value &= (0xFFFFFFFFu ^ 0xFFu); + + // store updated value + reg_value |= in; + + // recalculate checksum + const uint8_t new_checksum = backup_reg_calculate_checksum(reg_value); + + // store new checksum + backup_reg_set_checksum(®_value, new_checksum); + + REGISTER_PACKET_COUNTERS = reg_value; +#endif + + backup_reg_lock(); + +} + +void backup_reg_get_packet_counters(uint8_t * beacon_counter, uint8_t * meteo_counter, uint8_t * meteo_gsm_counter) { +#ifdef PARAMETEO + uint32_t reg_value = REGISTER_PACKET_COUNTERS; + + // calculate checksum from register value + uint8_t calculated_checksum = backup_reg_calculate_checksum(reg_value); + + uint8_t checksum_from_reg = backup_reg_get_checksum(reg_value); + + // check if checksum is ok + if (calculated_checksum == checksum_from_reg) { + *meteo_counter = ((reg_value & 0x00000F00u) >> 8); + *meteo_gsm_counter = ((reg_value & 0x0000F000u) >> 12); + *beacon_counter = ((reg_value & 0x00FF0000u) >> 16); + } + else { + // if it is not ok revert to default values + *beacon_counter = 0u; + *meteo_counter = 2u; + *meteo_gsm_counter = 0u; + + // and save it back into backup register + backup_reg_set_packet_counters(*beacon_counter, *meteo_counter, *meteo_gsm_counter); + } +#endif +} + +void backup_reg_set_packet_counters(uint8_t beacon_counter, uint8_t meteo_counter, uint8_t meteo_gsm_counter) { +#ifdef PARAMETEO + volatile uint32_t reg_value = REGISTER_PACKET_COUNTERS; + + // clear existing content + reg_value &= (0xFFFFFFFFu ^ 0x00FFFF00u); + + // check if meteo_counter doesn't overflow + if (meteo_counter > 15) { + meteo_counter = 15; + } + + if (meteo_gsm_counter > 15) { + meteo_gsm_counter = 15; + } + + // put new values + reg_value |= ((beacon_counter << 16) | (meteo_gsm_counter << 12) | (meteo_counter << 8)); + + // calculate new checksum + const uint8_t new_checksum = backup_reg_calculate_checksum(reg_value); + + // put new checksum value + backup_reg_set_checksum(®_value, new_checksum); + + backup_reg_unclock(); + + REGISTER_PACKET_COUNTERS = reg_value; + + backup_reg_lock(); + +#endif +} diff --git a/src/main.c b/src/main.c index c6469b4..d494e95 100644 --- a/src/main.c +++ b/src/main.c @@ -408,6 +408,8 @@ int main(int argc, char* argv[]){ if (main_reset_config_to_default == 1) { main_crc_result = 0; + backup_reg_reset_counters(); + backup_reg_set_configuration(0); #if defined(PARAMETEO) @@ -428,6 +430,9 @@ int main(int argc, char* argv[]){ // set also CRC flag because if restoring is successfull the region has good CRC backup_reg_set_bits_configuration(CONFIG_FIRST_CRC_OK); + // additionally resets packet counters stored in backup registers + backup_reg_reset_counters(); + } else { // if not store the flag in the backup register to block @@ -461,6 +466,9 @@ int main(int argc, char* argv[]){ // set also CRC flag as if restoring is successfull the region has good CRC backup_reg_set_bits_configuration(CONFIG_SECOND_CRC_OK); + // additionally resets packet counters stored in backup registers + backup_reg_reset_counters(); + } else { // if not store the flag in the backup register @@ -513,7 +521,10 @@ int main(int argc, char* argv[]){ main_button_two_right = configuration_get_right_button(); // set packets intervals - packet_tx_configure(main_config_data_basic->wx_transmit_period, main_config_data_basic->beacon_transmit_period, main_config_data_mode->powersave); + packet_tx_init(main_config_data_basic->wx_transmit_period, main_config_data_basic->beacon_transmit_period, main_config_data_mode->powersave); + + // initialie telemetry frames counter + telemetry_init(); #if defined(STM32F10X_MD_VL) // disabling access to BKP registers diff --git a/src/packet_tx_handler.c b/src/packet_tx_handler.c index ddbc018..8bde47b 100644 --- a/src/packet_tx_handler.c +++ b/src/packet_tx_handler.c @@ -42,7 +42,7 @@ uint8_t packet_tx_error_status_interval = 2; uint8_t packet_tx_error_status_counter = 0; uint8_t packet_tx_meteo_interval = 0; -uint8_t packet_tx_meteo_counter = 2; +uint8_t packet_tx_meteo_counter = 0; uint8_t packet_tx_meteo_kiss_interval = 2; uint8_t packet_tx_meteo_kiss_counter = 0; @@ -82,14 +82,20 @@ void packet_tx_send_wx_frame(void) { } -void packet_tx_configure(uint8_t meteo_interval, uint8_t beacon_interval, config_data_powersave_mode_t powersave) { +void packet_tx_init(uint8_t meteo_interval, uint8_t beacon_interval, config_data_powersave_mode_t powersave) { packet_tx_meteo_interval = meteo_interval; packet_tx_beacon_interval = beacon_interval; - // if user selected aggressive powersave mode the meteo counter must be set back to zero - // to prevent quirks with waking from sleep mode - packet_tx_meteo_counter = 0; + backup_reg_get_packet_counters(&packet_tx_beacon_counter, &packet_tx_meteo_counter, &packet_tx_meteo_gsm_counter); + + if (powersave == PWSAVE_AGGRESV) { + // if user selected aggressive powersave mode the meteo counter must be set back to zero + // to prevent quirks with waking from sleep mode + packet_tx_meteo_counter = 0; + } + + } @@ -559,6 +565,9 @@ void packet_tx_handler(const config_data_basic_t * const config_basic, const con packet_tx_telemetry_descr_counter = 0; } + // store counters in backup registers + backup_reg_set_packet_counters(packet_tx_beacon_counter, packet_tx_meteo_counter, packet_tx_meteo_gsm_counter); + #ifdef STM32L471xx // if powersave mode allow to sent extensive status messages if (rte_main_curret_powersave_mode != PWSAVE_AGGRESV) { diff --git a/src/variant_parameteo.c b/src/variant_parameteo.c new file mode 100644 index 0000000..90e644b --- /dev/null +++ b/src/variant_parameteo.c @@ -0,0 +1,17 @@ +/* + * variant.c + * + * Created on: Oct 24, 2023 + * Author: mateusz + */ + +#include "variant.h" + +int variant_validate_is_within_ram(uint32_t address) { + if (address != 0x00) { + return 1; + } + else { + return 0; + } +} diff --git a/system/include/aprs/telemetry.h b/system/include/aprs/telemetry.h index 9ea8e4e..8af2695 100644 --- a/system/include/aprs/telemetry.h +++ b/system/include/aprs/telemetry.h @@ -45,6 +45,8 @@ typedef enum wind_qf { WIND_QF_DEGRADATED = 3 }wind_qf_t; +void telemetry_init(void); + #ifdef __cplusplus extern "C" { @@ -62,7 +64,7 @@ void telemetry_send_values_pv ( uint8_t rx_pkts, void telemetry_send_chns_description_pv(const config_data_basic_t * const config_basic); void telemetry_send_status_pv(ve_direct_average_struct* avg, ve_direct_error_reason* last_error, ve_direct_system_state state, uint32_t master_time, uint16_t messages_count, uint16_t corrupted_messages_count); -#ifdef STM32L471xx +#ifdef PARAMETEO void telemetry_send_values( uint8_t rx_pkts, uint8_t tx_pkts, uint8_t digi_pkts, diff --git a/system/src/aprs/telemetry.c b/system/src/aprs/telemetry.c index dcc5010..8ab936e 100644 --- a/system/src/aprs/telemetry.c +++ b/system/src/aprs/telemetry.c @@ -8,6 +8,7 @@ #include "aprs/telemetry.h" #include "main.h" #include "delay.h" +#include "backup_registers.h" #include "ve_direct_protocol/parser.h" @@ -19,6 +20,10 @@ uint16_t telemetry_counter = 0; +void telemetry_init(void) { + telemetry_counter = backup_reg_get_telemetry(); +} + void telemetry_send_chns_description_pv(const config_data_basic_t * const config_basic) { // a buffer to assembly the 'call-ssid' string at the begining of the frame @@ -205,7 +210,7 @@ void telemetry_send_chns_description(const config_data_basic_t * const config_ba // clear the output frame buffer memset(main_own_aprs_msg, 0x00, sizeof(main_own_aprs_msg)); -#ifdef STM32L471xx +#ifdef PARAMETEO if (config_mode->digi_viscous == 0) { // prepare a frame with channel names depending on SSID if (config_basic->ssid == 0) @@ -269,7 +274,7 @@ void telemetry_send_chns_description(const config_data_basic_t * const config_ba WAIT_FOR_CHANNEL_FREE(); -#ifdef STM32L471xx +#ifdef PARAMETEO if (config_basic->ssid == 0) main_own_aprs_msg_len = sprintf(main_own_aprs_msg, ":%-6s :EQNS.0,1,0,0,1,0,0,1,0,0,0.02,10,0,0.5,-50", config_basic->callsign); else if (config_basic->ssid > 0 && config_basic->ssid < 10) @@ -300,7 +305,7 @@ void telemetry_send_chns_description(const config_data_basic_t * const config_ba WAIT_FOR_CHANNEL_FREE(); -#ifdef STM32L471xx +#ifdef PARAMETEO if (config_basic->ssid == 0) main_own_aprs_msg_len = sprintf(main_own_aprs_msg, ":%-6s :UNIT.Pkt,Pkt,Pkt,V,DegC,Hi,Hi,Hi,Hi,Hi,Hi,Hi,Hi", config_basic->callsign); else if (config_basic->ssid > 0 && config_basic->ssid < 10) @@ -502,8 +507,12 @@ void telemetry_send_values( uint8_t rx_pkts, #endif // reset the frame counter if it overflowed - if (telemetry_counter > 999) + if (telemetry_counter > 255) { telemetry_counter = 0; + } + + // store telemetry conter in backup register + backup_reg_set_telemetry((uint8_t)(telemetry_counter & 0xFFu)); // put a null terminator at the end of frame (but it should be placed there anyway) main_own_aprs_msg[main_own_aprs_msg_len] = 0;