ソースを参照

[FL-1818] System setting and debug options. RTC HAL refactoring. (#902)

* FuriHal: RTC API refactoring. System Setting application. FuriCore: adjustable log levels. Minor code cleanup.
* Storage: change logging levels for internal storage.
* FuriCore: fix broken trace logging level
あく 4 年 前
コミット
6579368053
45 ファイル変更543 行追加2652 行削除
  1. 5 0
      applications/applications.c
  2. 0 6
      applications/applications.mk
  3. 33 43
      applications/cli/cli_commands.c
  4. 9 10
      applications/dolphin/helpers/dolphin_state.c
  5. 0 1
      applications/dolphin/helpers/dolphin_state.h
  6. 1 0
      applications/nfc/nfc_i.h
  7. 6 7
      applications/nfc/scenes/nfc_scene_start.c
  8. 2 3
      applications/rpc/rpc_system.c
  9. 1 1
      applications/snake-game/snake-game.c
  10. 1 1
      applications/storage/storage-cli.c
  11. 5 6
      applications/storage/storages/storage-int.c
  12. 1 1
      applications/storage_settings/scenes/storage_settings_scene_factory_reset.c
  13. 4 8
      applications/subghz/scenes/subghz_scene_start.c
  14. 121 0
      applications/system/system_settings.c
  15. 18 0
      applications/system/system_settings.h
  16. 6 4
      core/furi/log.c
  17. 18 20
      core/furi/log.h
  18. 0 52
      firmware/targets/f6/Inc/rtc.h
  19. 1 1
      firmware/targets/f6/Inc/stm32wbxx_hal_conf.h
  20. 0 123
      firmware/targets/f6/Src/rtc.c
  21. 0 5
      firmware/targets/f6/Src/stm32wbxx_it.c
  22. 0 159
      firmware/targets/f6/ble-glue/hw_if.h
  23. 0 893
      firmware/targets/f6/ble-glue/hw_timerserver.c
  24. 0 8
      firmware/targets/f6/furi-hal/furi-hal-bootloader.c
  25. 0 9
      firmware/targets/f6/furi-hal/furi-hal-clock.c
  26. 0 3
      firmware/targets/f6/furi-hal/furi-hal-interrupt.c
  27. 122 0
      firmware/targets/f6/furi-hal/furi-hal-rtc.c
  28. 4 6
      firmware/targets/f6/furi-hal/furi-hal.c
  29. 2 2
      firmware/targets/f6/target.mk
  30. 0 52
      firmware/targets/f7/Inc/rtc.h
  31. 1 1
      firmware/targets/f7/Inc/stm32wbxx_hal_conf.h
  32. 0 123
      firmware/targets/f7/Src/rtc.c
  33. 0 5
      firmware/targets/f7/Src/stm32wbxx_it.c
  34. 0 159
      firmware/targets/f7/ble-glue/hw_if.h
  35. 0 893
      firmware/targets/f7/ble-glue/hw_timerserver.c
  36. 0 8
      firmware/targets/f7/furi-hal/furi-hal-bootloader.c
  37. 0 9
      firmware/targets/f7/furi-hal/furi-hal-clock.c
  38. 0 3
      firmware/targets/f7/furi-hal/furi-hal-interrupt.c
  39. 122 0
      firmware/targets/f7/furi-hal/furi-hal-rtc.c
  40. 4 6
      firmware/targets/f7/furi-hal/furi-hal.c
  41. 1 1
      firmware/targets/f7/target.mk
  42. 0 18
      firmware/targets/furi-hal-include/furi-hal-bootloader.h
  43. 52 0
      firmware/targets/furi-hal-include/furi-hal-rtc.h
  44. 1 0
      firmware/targets/furi-hal-include/furi-hal.h
  45. 2 2
      lib/lfs_config.h

+ 5 - 0
applications/applications.c

@@ -65,6 +65,7 @@ extern int32_t bt_settings_app(void* p);
 extern int32_t desktop_settings_app(void* p);
 extern int32_t desktop_settings_app(void* p);
 extern int32_t about_settings_app(void* p);
 extern int32_t about_settings_app(void* p);
 extern int32_t power_settings_app(void* p);
 extern int32_t power_settings_app(void* p);
+extern int32_t system_settings_app(void* p);
 
 
 const FlipperApplication FLIPPER_SERVICES[] = {
 const FlipperApplication FLIPPER_SERVICES[] = {
 /* Services */
 /* Services */
@@ -312,6 +313,10 @@ const FlipperApplication FLIPPER_SETTINGS_APPS[] = {
     {.app = passport_app, .name = "Passport", .stack_size = 1024, .icon = NULL},
     {.app = passport_app, .name = "Passport", .stack_size = 1024, .icon = NULL},
 #endif
 #endif
 
 
+#ifdef SRV_GUI
+    {.app = system_settings_app, .name = "System", .stack_size = 1024, .icon = NULL},
+#endif
+
 #ifdef APP_ABOUT
 #ifdef APP_ABOUT
     {.app = about_settings_app, .name = "About", .stack_size = 1024, .icon = NULL},
     {.app = about_settings_app, .name = "About", .stack_size = 1024, .icon = NULL},
 #endif
 #endif

+ 0 - 6
applications/applications.mk

@@ -316,9 +316,3 @@ SRV_STORAGE ?= 0
 ifeq ($(SRV_STORAGE), 1)
 ifeq ($(SRV_STORAGE), 1)
 CFLAGS		+= -DSRV_STORAGE
 CFLAGS		+= -DSRV_STORAGE
 endif
 endif
-
-
-LAB_TESTS ?= 0
-ifeq ($(LAB_TESTS), 1)
-CFLAGS += -DLAB_TESTS
-endif

+ 33 - 43
applications/cli/cli_commands.c

@@ -2,7 +2,6 @@
 #include <furi-hal.h>
 #include <furi-hal.h>
 #include <furi-hal-gpio.h>
 #include <furi-hal-gpio.h>
 #include <furi-hal-info.h>
 #include <furi-hal-info.h>
-#include <rtc.h>
 #include <task-control-block.h>
 #include <task-control-block.h>
 #include <time.h>
 #include <time.h>
 #include <notification/notification-messages.h>
 #include <notification/notification-messages.h>
@@ -58,46 +57,40 @@ void cli_command_help(Cli* cli, string_t args, void* context) {
 }
 }
 
 
 void cli_command_date(Cli* cli, string_t args, void* context) {
 void cli_command_date(Cli* cli, string_t args, void* context) {
-    RTC_TimeTypeDef time;
-    RTC_DateTypeDef date;
+    FuriHalRtcDateTime datetime = {0};
 
 
     if(string_size(args) > 0) {
     if(string_size(args) > 0) {
-        uint16_t Hours, Minutes, Seconds, Month, Date, Year, WeekDay;
+        uint16_t hours, minutes, seconds, month, day, year, weekday;
         int ret = sscanf(
         int ret = sscanf(
             string_get_cstr(args),
             string_get_cstr(args),
             "%hu:%hu:%hu %hu-%hu-%hu %hu",
             "%hu:%hu:%hu %hu-%hu-%hu %hu",
-            &Hours,
-            &Minutes,
-            &Seconds,
-            &Month,
-            &Date,
-            &Year,
-            &WeekDay);
+            &hours,
+            &minutes,
+            &seconds,
+            &month,
+            &day,
+            &year,
+            &weekday);
         if(ret == 7) {
         if(ret == 7) {
-            time.Hours = Hours;
-            time.Minutes = Minutes;
-            time.Seconds = Seconds;
-            time.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
-            time.StoreOperation = RTC_STOREOPERATION_RESET;
-            date.WeekDay = WeekDay;
-            date.Month = Month;
-            date.Date = Date;
-            date.Year = Year - 2000;
-            HAL_RTC_SetTime(&hrtc, &time, RTC_FORMAT_BIN);
-            HAL_RTC_SetDate(&hrtc, &date, RTC_FORMAT_BIN);
-
+            datetime.hour = hours;
+            datetime.minute = minutes;
+            datetime.second = seconds;
+            datetime.weekday = weekday;
+            datetime.month = month;
+            datetime.day = day;
+            datetime.year = year;
+            furi_hal_rtc_set_datetime(&datetime);
             // Verification
             // Verification
-            HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
-            HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);
+            furi_hal_rtc_get_datetime(&datetime);
             printf(
             printf(
                 "New time is: %.2d:%.2d:%.2d %.2d-%.2d-%.2d %d",
                 "New time is: %.2d:%.2d:%.2d %.2d-%.2d-%.2d %d",
-                time.Hours,
-                time.Minutes,
-                time.Seconds,
-                date.Month,
-                date.Date,
-                2000 + date.Year,
-                date.WeekDay);
+                datetime.hour,
+                datetime.minute,
+                datetime.second,
+                datetime.month,
+                datetime.day,
+                datetime.year,
+                datetime.weekday);
         } else {
         } else {
             printf(
             printf(
                 "Invalid time format, use `hh:mm:ss MM-DD-YYYY WD`. sscanf %d %s",
                 "Invalid time format, use `hh:mm:ss MM-DD-YYYY WD`. sscanf %d %s",
@@ -106,19 +99,16 @@ void cli_command_date(Cli* cli, string_t args, void* context) {
             return;
             return;
         }
         }
     } else {
     } else {
-        // TODO add get_datetime to core, not use HAL here
-        // READ ORDER MATTERS! Time then date.
-        HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
-        HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);
+        furi_hal_rtc_get_datetime(&datetime);
         printf(
         printf(
             "%.2d:%.2d:%.2d %.2d-%.2d-%.2d %d",
             "%.2d:%.2d:%.2d %.2d-%.2d-%.2d %d",
-            time.Hours,
-            time.Minutes,
-            time.Seconds,
-            date.Month,
-            date.Date,
-            2000 + date.Year,
-            date.WeekDay);
+            datetime.hour,
+            datetime.minute,
+            datetime.second,
+            datetime.month,
+            datetime.day,
+            datetime.year,
+            datetime.weekday);
     }
     }
 }
 }
 
 

+ 9 - 10
applications/dolphin/helpers/dolphin_state.c

@@ -2,6 +2,7 @@
 #include <stdint.h>
 #include <stdint.h>
 #include <storage/storage.h>
 #include <storage/storage.h>
 #include <furi.h>
 #include <furi.h>
+#include <furi-hal.h>
 #include <math.h>
 #include <math.h>
 #include <toolbox/saved_struct.h>
 #include <toolbox/saved_struct.h>
 
 
@@ -70,20 +71,18 @@ bool dolphin_state_load(DolphinState* dolphin_state) {
 }
 }
 
 
 uint64_t dolphin_state_timestamp() {
 uint64_t dolphin_state_timestamp() {
-    RTC_TimeTypeDef time;
-    RTC_DateTypeDef date;
+    FuriHalRtcDateTime datetime;
     struct tm current;
     struct tm current;
 
 
-    HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
-    HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);
+    furi_hal_rtc_get_datetime(&datetime);
 
 
-    current.tm_year = date.Year + 100;
-    current.tm_mday = date.Date;
-    current.tm_mon = date.Month - 1;
+    current.tm_year = datetime.year - 1900;
+    current.tm_mday = datetime.day;
+    current.tm_mon = datetime.month - 1;
 
 
-    current.tm_hour = time.Hours;
-    current.tm_min = time.Minutes;
-    current.tm_sec = time.Seconds;
+    current.tm_hour = datetime.hour;
+    current.tm_min = datetime.minute;
+    current.tm_sec = datetime.second;
 
 
     return mktime(&current);
     return mktime(&current);
 }
 }

+ 0 - 1
applications/dolphin/helpers/dolphin_state.h

@@ -3,7 +3,6 @@
 #include "dolphin_deed.h"
 #include "dolphin_deed.h"
 #include <stdbool.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdint.h>
-#include <rtc.h>
 #include <time.h>
 #include <time.h>
 
 
 typedef struct DolphinState DolphinState;
 typedef struct DolphinState DolphinState;

+ 1 - 0
applications/nfc/nfc_i.h

@@ -6,6 +6,7 @@
 #include "nfc_device.h"
 #include "nfc_device.h"
 
 
 #include <furi.h>
 #include <furi.h>
+#include <furi-hal.h>
 
 
 #include <gui/gui.h>
 #include <gui/gui.h>
 #include <gui/view.h>
 #include <gui/view.h>

+ 6 - 7
applications/nfc/scenes/nfc_scene_start.c

@@ -5,9 +5,7 @@ enum SubmenuIndex {
     SubmenuIndexRunScript,
     SubmenuIndexRunScript,
     SubmenuIndexSaved,
     SubmenuIndexSaved,
     SubmenuIndexAddManualy,
     SubmenuIndexAddManualy,
-#ifdef LAB_TESTS
     SubmenuIndexDebug,
     SubmenuIndexDebug,
-#endif
 };
 };
 
 
 void nfc_scene_start_submenu_callback(void* context, uint32_t index) {
 void nfc_scene_start_submenu_callback(void* context, uint32_t index) {
@@ -32,9 +30,12 @@ void nfc_scene_start_on_enter(void* context) {
         submenu, "Saved cards", SubmenuIndexSaved, nfc_scene_start_submenu_callback, nfc);
         submenu, "Saved cards", SubmenuIndexSaved, nfc_scene_start_submenu_callback, nfc);
     submenu_add_item(
     submenu_add_item(
         submenu, "Add manually", SubmenuIndexAddManualy, nfc_scene_start_submenu_callback, nfc);
         submenu, "Add manually", SubmenuIndexAddManualy, nfc_scene_start_submenu_callback, nfc);
-#ifdef LAB_TESTS
-    submenu_add_item(submenu, "Debug", SubmenuIndexDebug, nfc_scene_start_submenu_callback, nfc);
-#endif
+
+    if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
+        submenu_add_item(
+            submenu, "Debug", SubmenuIndexDebug, nfc_scene_start_submenu_callback, nfc);
+    }
+
     submenu_set_selected_item(
     submenu_set_selected_item(
         submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneStart));
         submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneStart));
 
 
@@ -65,12 +66,10 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) {
                 nfc->scene_manager, NfcSceneStart, SubmenuIndexAddManualy);
                 nfc->scene_manager, NfcSceneStart, SubmenuIndexAddManualy);
             scene_manager_next_scene(nfc->scene_manager, NfcSceneSetType);
             scene_manager_next_scene(nfc->scene_manager, NfcSceneSetType);
             consumed = true;
             consumed = true;
-#ifdef LAB_TESTS
         } else if(event.event == SubmenuIndexDebug) {
         } else if(event.event == SubmenuIndexDebug) {
             scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexDebug);
             scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexDebug);
             scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateApduSequence);
             scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateApduSequence);
             consumed = true;
             consumed = true;
-#endif
         }
         }
     }
     }
     return consumed;
     return consumed;

+ 2 - 3
applications/rpc/rpc_system.c

@@ -2,8 +2,7 @@
 #include "rpc_i.h"
 #include "rpc_i.h"
 #include "status.pb.h"
 #include "status.pb.h"
 
 
-#include <furi-hal-info.h>
-#include <furi-hal-bootloader.h>
+#include <furi-hal.h>
 #include <power/power_service/power.h>
 #include <power/power_service/power.h>
 
 
 void rpc_system_system_ping_process(const PB_Main* msg_request, void* context) {
 void rpc_system_system_ping_process(const PB_Main* msg_request, void* context) {
@@ -104,7 +103,7 @@ void rpc_system_system_factory_reset_process(const PB_Main* request, void* conte
     furi_assert(request->which_content == PB_Main_system_factory_reset_request_tag);
     furi_assert(request->which_content == PB_Main_system_factory_reset_request_tag);
     furi_assert(context);
     furi_assert(context);
 
 
-    furi_hal_bootloader_set_flags(FuriHalBootloaderFlagFactoryReset);
+    furi_hal_rtc_set_flag(FuriHalRtcFlagFactoryReset);
     power_reboot(PowerBootModeNormal);
     power_reboot(PowerBootModeNormal);
 }
 }
 
 

+ 1 - 1
applications/snake-game/snake-game.c

@@ -322,7 +322,7 @@ int32_t snake_game_app(void* p) {
 
 
     ValueMutex state_mutex;
     ValueMutex state_mutex;
     if(!init_mutex(&state_mutex, snake_state, sizeof(SnakeState))) {
     if(!init_mutex(&state_mutex, snake_state, sizeof(SnakeState))) {
-        furi_log_print(FURI_LOG_ERROR, "cannot create mutex\r\n");
+        FURI_LOG_E("SnakeGame", "cannot create mutex\r\n");
         free(snake_state);
         free(snake_state);
         return 255;
         return 255;
     }
     }

+ 1 - 1
applications/storage/storage-cli.c

@@ -526,7 +526,7 @@ static void storage_cli_factory_reset(Cli* cli, string_t args, void* context) {
     char c = cli_getc(cli);
     char c = cli_getc(cli);
     if(c == 'y' || c == 'Y') {
     if(c == 'y' || c == 'Y') {
         printf("Data will be wiped after reboot.\r\n");
         printf("Data will be wiped after reboot.\r\n");
-        furi_hal_bootloader_set_flags(FuriHalBootloaderFlagFactoryReset);
+        furi_hal_rtc_set_flag(FuriHalRtcFlagFactoryReset);
         power_reboot(PowerBootModeNormal);
         power_reboot(PowerBootModeNormal);
     } else {
     } else {
         printf("Safe choice.\r\n");
         printf("Safe choice.\r\n");

+ 5 - 6
applications/storage/storages/storage-int.c

@@ -69,7 +69,7 @@ static int storage_int_device_read(
     LFSData* lfs_data = c->context;
     LFSData* lfs_data = c->context;
     size_t address = lfs_data->start_address + block * c->block_size + off;
     size_t address = lfs_data->start_address + block * c->block_size + off;
 
 
-    FURI_LOG_D(
+    FURI_LOG_T(
         TAG,
         TAG,
         "Device read: block %d, off %d, buffer: %p, size %d, translated address: %p",
         "Device read: block %d, off %d, buffer: %p, size %d, translated address: %p",
         block,
         block,
@@ -92,7 +92,7 @@ static int storage_int_device_prog(
     LFSData* lfs_data = c->context;
     LFSData* lfs_data = c->context;
     size_t address = lfs_data->start_address + block * c->block_size + off;
     size_t address = lfs_data->start_address + block * c->block_size + off;
 
 
-    FURI_LOG_D(
+    FURI_LOG_T(
         TAG,
         TAG,
         "Device prog: block %d, off %d, buffer: %p, size %d, translated address: %p",
         "Device prog: block %d, off %d, buffer: %p, size %d, translated address: %p",
         block,
         block,
@@ -163,15 +163,14 @@ static LFSData* storage_int_lfs_data_alloc() {
 
 
 static void storage_int_lfs_mount(LFSData* lfs_data, StorageData* storage) {
 static void storage_int_lfs_mount(LFSData* lfs_data, StorageData* storage) {
     int err;
     int err;
-    FuriHalBootloaderFlag bootloader_flags = furi_hal_bootloader_get_flags();
     lfs_t* lfs = &lfs_data->lfs;
     lfs_t* lfs = &lfs_data->lfs;
 
 
-    if(bootloader_flags & FuriHalBootloaderFlagFactoryReset) {
+    if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagFactoryReset)) {
         // Factory reset
         // Factory reset
         err = lfs_format(lfs, &lfs_data->config);
         err = lfs_format(lfs, &lfs_data->config);
         if(err == 0) {
         if(err == 0) {
             FURI_LOG_I(TAG, "Factory reset: Format successful, trying to mount");
             FURI_LOG_I(TAG, "Factory reset: Format successful, trying to mount");
-            furi_hal_bootloader_set_flags(bootloader_flags & ~FuriHalBootloaderFlagFactoryReset);
+            furi_hal_rtc_reset_flag(FuriHalRtcFlagFactoryReset);
             err = lfs_mount(lfs, &lfs_data->config);
             err = lfs_mount(lfs, &lfs_data->config);
             if(err == 0) {
             if(err == 0) {
                 FURI_LOG_I(TAG, "Factory reset: Mounted");
                 FURI_LOG_I(TAG, "Factory reset: Mounted");
@@ -687,4 +686,4 @@ void storage_int_init(StorageData* storage) {
     storage->fs_api.common.rename = storage_int_common_rename;
     storage->fs_api.common.rename = storage_int_common_rename;
     storage->fs_api.common.remove = storage_int_common_remove;
     storage->fs_api.common.remove = storage_int_common_remove;
     storage->fs_api.common.fs_info = storage_int_common_fs_info;
     storage->fs_api.common.fs_info = storage_int_common_fs_info;
-}
+}

+ 1 - 1
applications/storage_settings/scenes/storage_settings_scene_factory_reset.c

@@ -63,7 +63,7 @@ bool storage_settings_scene_factory_reset_on_event(void* context, SceneManagerEv
                 scene_manager_set_scene_state(
                 scene_manager_set_scene_state(
                     app->scene_manager, StorageSettingsFactoryReset, counter);
                     app->scene_manager, StorageSettingsFactoryReset, counter);
             } else {
             } else {
-                furi_hal_bootloader_set_flags(FuriHalBootloaderFlagFactoryReset);
+                furi_hal_rtc_set_flag(FuriHalRtcFlagFactoryReset);
                 power_reboot(PowerBootModeNormal);
                 power_reboot(PowerBootModeNormal);
             }
             }
 
 

+ 4 - 8
applications/subghz/scenes/subghz_scene_start.c

@@ -3,9 +3,7 @@
 enum SubmenuIndex {
 enum SubmenuIndex {
     SubmenuIndexRead = 10,
     SubmenuIndexRead = 10,
     SubmenuIndexSaved,
     SubmenuIndexSaved,
-#ifdef LAB_TESTS
     SubmenuIndexTest,
     SubmenuIndexTest,
-#endif
     SubmenuIndexAddManualy,
     SubmenuIndexAddManualy,
     SubmenuIndexFrequencyAnalyzer,
     SubmenuIndexFrequencyAnalyzer,
     SubmenuIndexReadRAW,
     SubmenuIndexReadRAW,
@@ -43,10 +41,10 @@ void subghz_scene_start_on_enter(void* context) {
         SubmenuIndexFrequencyAnalyzer,
         SubmenuIndexFrequencyAnalyzer,
         subghz_scene_start_submenu_callback,
         subghz_scene_start_submenu_callback,
         subghz);
         subghz);
-#ifdef LAB_TESTS
-    submenu_add_item(
-        subghz->submenu, "Test", SubmenuIndexTest, subghz_scene_start_submenu_callback, subghz);
-#endif
+    if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
+        submenu_add_item(
+            subghz->submenu, "Test", SubmenuIndexTest, subghz_scene_start_submenu_callback, subghz);
+    }
     submenu_set_selected_item(
     submenu_set_selected_item(
         subghz->submenu, scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneStart));
         subghz->submenu, scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneStart));
 
 
@@ -83,13 +81,11 @@ bool subghz_scene_start_on_event(void* context, SceneManagerEvent event) {
                 subghz->scene_manager, SubGhzSceneStart, SubmenuIndexFrequencyAnalyzer);
                 subghz->scene_manager, SubGhzSceneStart, SubmenuIndexFrequencyAnalyzer);
             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneFrequencyAnalyzer);
             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneFrequencyAnalyzer);
             return true;
             return true;
-#ifdef LAB_TESTS
         } else if(event.event == SubmenuIndexTest) {
         } else if(event.event == SubmenuIndexTest) {
             scene_manager_set_scene_state(
             scene_manager_set_scene_state(
                 subghz->scene_manager, SubGhzSceneStart, SubmenuIndexTest);
                 subghz->scene_manager, SubGhzSceneStart, SubmenuIndexTest);
             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTest);
             scene_manager_next_scene(subghz->scene_manager, SubGhzSceneTest);
             return true;
             return true;
-#endif
         }
         }
     }
     }
     return false;
     return false;

+ 121 - 0
applications/system/system_settings.c

@@ -0,0 +1,121 @@
+#include "system_settings.h"
+
+static uint8_t
+    uint32_value_index(const uint32_t value, const uint32_t values[], uint8_t values_count) {
+    int64_t last_value = INT64_MIN;
+    uint8_t index = 0;
+    for(uint8_t i = 0; i < values_count; i++) {
+        if((value >= last_value) && (value <= values[i])) {
+            index = i;
+            break;
+        }
+        last_value = values[i];
+    }
+    return index;
+}
+
+const char* const log_level_text[] = {
+    "Default",
+    "None",
+    "Error",
+    "Warning",
+    "Info",
+    "Debug",
+    "Trace",
+};
+
+const uint32_t log_level_value[] = {
+    FuriLogLevelDefault,
+    FuriLogLevelNone,
+    FuriLogLevelError,
+    FuriLogLevelWarn,
+    FuriLogLevelInfo,
+    FuriLogLevelDebug,
+    FuriLogLevelTrace,
+};
+
+static void log_level_changed(VariableItem* item) {
+    // SystemSettings* app = variable_item_get_context(item);
+    uint8_t index = variable_item_get_current_value_index(item);
+    variable_item_set_current_value_text(item, log_level_text[index]);
+    furi_hal_rtc_set_log_level(log_level_value[index]);
+}
+
+const char* const debug_text[] = {
+    "Disable",
+    "Enable",
+};
+
+static void debug_changed(VariableItem* item) {
+    uint8_t index = variable_item_get_current_value_index(item);
+    variable_item_set_current_value_text(item, debug_text[index]);
+    if(index) {
+        furi_hal_rtc_set_flag(FuriHalRtcFlagDebug);
+    } else {
+        furi_hal_rtc_reset_flag(FuriHalRtcFlagDebug);
+    }
+}
+
+static uint32_t system_settings_exit(void* context) {
+    return VIEW_NONE;
+}
+
+SystemSettings* system_settings_alloc() {
+    SystemSettings* app = furi_alloc(sizeof(SystemSettings));
+
+    // Load settings
+    app->gui = furi_record_open("gui");
+
+    app->view_dispatcher = view_dispatcher_alloc();
+    view_dispatcher_enable_queue(app->view_dispatcher);
+    view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
+
+    view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
+
+    VariableItem* item;
+    uint8_t value_index;
+    app->var_item_list = variable_item_list_alloc();
+
+    item = variable_item_list_add(
+        app->var_item_list, "Log Level", COUNT_OF(log_level_text), log_level_changed, app);
+    value_index = uint32_value_index(
+        furi_hal_rtc_get_log_level(), log_level_value, COUNT_OF(log_level_text));
+    variable_item_set_current_value_index(item, value_index);
+    variable_item_set_current_value_text(item, log_level_text[value_index]);
+
+    item = variable_item_list_add(
+        app->var_item_list, "Debug", COUNT_OF(debug_text), debug_changed, app);
+    value_index = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug) ? 1 : 0;
+    variable_item_set_current_value_index(item, value_index);
+    variable_item_set_current_value_text(item, debug_text[value_index]);
+
+    view_set_previous_callback(
+        variable_item_list_get_view(app->var_item_list), system_settings_exit);
+    view_dispatcher_add_view(
+        app->view_dispatcher,
+        SystemSettingsViewVarItemList,
+        variable_item_list_get_view(app->var_item_list));
+
+    view_dispatcher_switch_to_view(app->view_dispatcher, SystemSettingsViewVarItemList);
+
+    return app;
+}
+
+void system_settings_free(SystemSettings* app) {
+    furi_assert(app);
+    // Variable item list
+    view_dispatcher_remove_view(app->view_dispatcher, SystemSettingsViewVarItemList);
+    variable_item_list_free(app->var_item_list);
+    // View dispatcher
+    view_dispatcher_free(app->view_dispatcher);
+    // Records
+    furi_record_close("gui");
+    free(app);
+}
+
+int32_t system_settings_app(void* p) {
+    SystemSettings* app = system_settings_alloc();
+    view_dispatcher_run(app->view_dispatcher);
+    system_settings_free(app);
+    return 0;
+}

+ 18 - 0
applications/system/system_settings.h

@@ -0,0 +1,18 @@
+#pragma once
+
+#include <furi.h>
+#include <furi-hal.h>
+
+#include <gui/gui.h>
+#include <gui/view_dispatcher.h>
+#include <gui/modules/variable-item-list.h>
+
+typedef struct {
+    Gui* gui;
+    ViewDispatcher* view_dispatcher;
+    VariableItemList* var_item_list;
+} SystemSettings;
+
+typedef enum {
+    SystemSettingsViewVarItemList,
+} SystemSettingsView;

+ 6 - 4
core/furi/log.c

@@ -3,6 +3,8 @@
 #include <cmsis_os2.h>
 #include <cmsis_os2.h>
 #include <furi-hal.h>
 #include <furi-hal.h>
 
 
+#define FURI_LOG_LEVEL_DEFAULT FuriLogLevelInfo
+
 typedef struct {
 typedef struct {
     FuriLogLevel log_level;
     FuriLogLevel log_level;
     FuriLogPuts puts;
     FuriLogPuts puts;
@@ -14,15 +16,13 @@ static FuriLogParams furi_log;
 
 
 void furi_log_init() {
 void furi_log_init() {
     // Set default logging parameters
     // Set default logging parameters
-    furi_log.log_level = FURI_LOG_LEVEL;
+    furi_log.log_level = FURI_LOG_LEVEL_DEFAULT;
     furi_log.puts = furi_hal_console_puts;
     furi_log.puts = furi_hal_console_puts;
     furi_log.timetamp = HAL_GetTick;
     furi_log.timetamp = HAL_GetTick;
     furi_log.mutex = osMutexNew(NULL);
     furi_log.mutex = osMutexNew(NULL);
 }
 }
 
 
 void furi_log_print(FuriLogLevel level, const char* format, ...) {
 void furi_log_print(FuriLogLevel level, const char* format, ...) {
-    va_list args;
-    va_start(args, format);
     if(level <= furi_log.log_level && osMutexAcquire(furi_log.mutex, osWaitForever) == osOK) {
     if(level <= furi_log.log_level && osMutexAcquire(furi_log.mutex, osWaitForever) == osOK) {
         string_t string;
         string_t string;
 
 
@@ -41,10 +41,12 @@ void furi_log_print(FuriLogLevel level, const char* format, ...) {
 
 
         osMutexRelease(furi_log.mutex);
         osMutexRelease(furi_log.mutex);
     }
     }
-    va_end(args);
 }
 }
 
 
 void furi_log_set_level(FuriLogLevel level) {
 void furi_log_set_level(FuriLogLevel level) {
+    if(level == FuriLogLevelDefault) {
+        level = FURI_LOG_LEVEL_DEFAULT;
+    }
     furi_log.log_level = level;
     furi_log.log_level = level;
 }
 }
 
 

+ 18 - 20
core/furi/log.h

@@ -8,11 +8,15 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
-#define FURI_LOG_LEVEL_DEFAULT 3
-
-#ifndef FURI_LOG_LEVEL
-#define FURI_LOG_LEVEL FURI_LOG_LEVEL_DEFAULT
-#endif
+typedef enum {
+    FuriLogLevelDefault = 0,
+    FuriLogLevelNone = 1,
+    FuriLogLevelError = 2,
+    FuriLogLevelWarn = 3,
+    FuriLogLevelInfo = 4,
+    FuriLogLevelDebug = 5,
+    FuriLogLevelTrace = 6,
+} FuriLogLevel;
 
 
 #define FURI_LOG_CLR(clr) "\033[0;" clr "m"
 #define FURI_LOG_CLR(clr) "\033[0;" clr "m"
 #define FURI_LOG_CLR_RESET "\033[0m"
 #define FURI_LOG_CLR_RESET "\033[0m"
@@ -28,20 +32,11 @@ extern "C" {
 #define FURI_LOG_CLR_W FURI_LOG_CLR(FURI_LOG_CLR_BROWN)
 #define FURI_LOG_CLR_W FURI_LOG_CLR(FURI_LOG_CLR_BROWN)
 #define FURI_LOG_CLR_I FURI_LOG_CLR(FURI_LOG_CLR_GREEN)
 #define FURI_LOG_CLR_I FURI_LOG_CLR(FURI_LOG_CLR_GREEN)
 #define FURI_LOG_CLR_D FURI_LOG_CLR(FURI_LOG_CLR_BLUE)
 #define FURI_LOG_CLR_D FURI_LOG_CLR(FURI_LOG_CLR_BLUE)
-#define FURI_LOG_CLR_V
+#define FURI_LOG_CLR_T FURI_LOG_CLR(FURI_LOG_CLR_PURPLE)
 
 
 typedef void (*FuriLogPuts)(const char* data);
 typedef void (*FuriLogPuts)(const char* data);
 typedef uint32_t (*FuriLogTimestamp)(void);
 typedef uint32_t (*FuriLogTimestamp)(void);
 
 
-typedef enum {
-    FURI_LOG_NONE = 0,
-    FURI_LOG_ERROR = 1,
-    FURI_LOG_WARN = 2,
-    FURI_LOG_INFO = 3,
-    FURI_LOG_DEBUG = 4,
-    FURI_LOG_VERBOSE = 5,
-} FuriLogLevel;
-
 void furi_log_init();
 void furi_log_init();
 void furi_log_print(FuriLogLevel level, const char* format, ...);
 void furi_log_print(FuriLogLevel level, const char* format, ...);
 void furi_log_set_level(FuriLogLevel level);
 void furi_log_set_level(FuriLogLevel level);
@@ -54,11 +49,14 @@ void furi_log_set_timestamp(FuriLogTimestamp timestamp);
 #define FURI_LOG_SHOW(tag, format, log_level, log_letter, ...) \
 #define FURI_LOG_SHOW(tag, format, log_level, log_letter, ...) \
     furi_log_print(log_level, FURI_LOG_FORMAT(log_letter, tag, format), ##__VA_ARGS__)
     furi_log_print(log_level, FURI_LOG_FORMAT(log_letter, tag, format), ##__VA_ARGS__)
 
 
-#define FURI_LOG_E(tag, format, ...) FURI_LOG_SHOW(tag, format, FURI_LOG_ERROR, E, ##__VA_ARGS__)
-#define FURI_LOG_W(tag, format, ...) FURI_LOG_SHOW(tag, format, FURI_LOG_WARN, W, ##__VA_ARGS__)
-#define FURI_LOG_I(tag, format, ...) FURI_LOG_SHOW(tag, format, FURI_LOG_INFO, I, ##__VA_ARGS__)
-#define FURI_LOG_D(tag, format, ...) FURI_LOG_SHOW(tag, format, FURI_LOG_DEBUG, D, ##__VA_ARGS__)
-#define FURI_LOG_V(tag, format, ...) FURI_LOG_SHOW(tag, format, FURI_LOG_VERBOSE, V, ##__VA_ARGS__)
+#define FURI_LOG_E(tag, format, ...) \
+    FURI_LOG_SHOW(tag, format, FuriLogLevelError, E, ##__VA_ARGS__)
+#define FURI_LOG_W(tag, format, ...) FURI_LOG_SHOW(tag, format, FuriLogLevelWarn, W, ##__VA_ARGS__)
+#define FURI_LOG_I(tag, format, ...) FURI_LOG_SHOW(tag, format, FuriLogLevelInfo, I, ##__VA_ARGS__)
+#define FURI_LOG_D(tag, format, ...) \
+    FURI_LOG_SHOW(tag, format, FuriLogLevelDebug, D, ##__VA_ARGS__)
+#define FURI_LOG_T(tag, format, ...) \
+    FURI_LOG_SHOW(tag, format, FuriLogLevelTrace, T, ##__VA_ARGS__)
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }

+ 0 - 52
firmware/targets/f6/Inc/rtc.h

@@ -1,52 +0,0 @@
-/**
-  ******************************************************************************
-  * @file    rtc.h
-  * @brief   This file contains all the function prototypes for
-  *          the rtc.c file
-  ******************************************************************************
-  * @attention
-  *
-  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
-  * All rights reserved.</center></h2>
-  *
-  * This software component is licensed by ST under Ultimate Liberty license
-  * SLA0044, the "License"; You may not use this file except in compliance with
-  * the License. You may obtain a copy of the License at:
-  *                             www.st.com/SLA0044
-  *
-  ******************************************************************************
-  */
-/* Define to prevent recursive inclusion -------------------------------------*/
-#ifndef __RTC_H__
-#define __RTC_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Includes ------------------------------------------------------------------*/
-#include "main.h"
-
-/* USER CODE BEGIN Includes */
-
-/* USER CODE END Includes */
-
-extern RTC_HandleTypeDef hrtc;
-
-/* USER CODE BEGIN Private defines */
-
-/* USER CODE END Private defines */
-
-void MX_RTC_Init(void);
-
-/* USER CODE BEGIN Prototypes */
-
-/* USER CODE END Prototypes */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __RTC_H__ */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 1 - 1
firmware/targets/f6/Inc/stm32wbxx_hal_conf.h

@@ -48,7 +48,7 @@
 #define HAL_PKA_MODULE_ENABLED
 #define HAL_PKA_MODULE_ENABLED
 /*#define HAL_QSPI_MODULE_ENABLED   */
 /*#define HAL_QSPI_MODULE_ENABLED   */
 #define HAL_RNG_MODULE_ENABLED
 #define HAL_RNG_MODULE_ENABLED
-#define HAL_RTC_MODULE_ENABLED
+/*#define HAL_RTC_MODULE_ENABLED    */
 /*#define HAL_SAI_MODULE_ENABLED    */
 /*#define HAL_SAI_MODULE_ENABLED    */
 /*#define HAL_SMBUS_MODULE_ENABLED  */
 /*#define HAL_SMBUS_MODULE_ENABLED  */
 /*#define HAL_SMARTCARD_MODULE_ENABLED   */
 /*#define HAL_SMARTCARD_MODULE_ENABLED   */

+ 0 - 123
firmware/targets/f6/Src/rtc.c

@@ -1,123 +0,0 @@
-/**
-  ******************************************************************************
-  * @file    rtc.c
-  * @brief   This file provides code for the configuration
-  *          of the RTC instances.
-  ******************************************************************************
-  * @attention
-  *
-  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
-  * All rights reserved.</center></h2>
-  *
-  * This software component is licensed by ST under Ultimate Liberty license
-  * SLA0044, the "License"; You may not use this file except in compliance with
-  * the License. You may obtain a copy of the License at:
-  *                             www.st.com/SLA0044
-  *
-  ******************************************************************************
-  */
-
-/* Includes ------------------------------------------------------------------*/
-#include "rtc.h"
-
-/* USER CODE BEGIN 0 */
-
-/* USER CODE END 0 */
-
-RTC_HandleTypeDef hrtc;
-
-/* RTC init function */
-void MX_RTC_Init(void)
-{
-  RTC_TimeTypeDef sTime = {0};
-  RTC_DateTypeDef sDate = {0};
-
-  /** Initialize RTC Only
-  */
-  hrtc.Instance = RTC;
-  hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
-  hrtc.Init.AsynchPrediv = 127;
-  hrtc.Init.SynchPrediv = 255;
-  hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
-  hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
-  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
-  hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
-  if (HAL_RTC_Init(&hrtc) != HAL_OK)
-  {
-    Error_Handler();
-  }
-
-  /* USER CODE BEGIN Check_RTC_BKUP */
-  return;
-  /* USER CODE END Check_RTC_BKUP */
-
-  /** Initialize RTC and set the Time and Date
-  */
-  sTime.Hours = 0x0;
-  sTime.Minutes = 0x0;
-  sTime.Seconds = 0x0;
-  sTime.SubSeconds = 0x0;
-  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
-  sTime.StoreOperation = RTC_STOREOPERATION_RESET;
-  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
-  {
-    Error_Handler();
-  }
-  sDate.WeekDay = RTC_WEEKDAY_MONDAY;
-  sDate.Month = RTC_MONTH_JANUARY;
-  sDate.Date = 0x1;
-  sDate.Year = 0x0;
-
-  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
-  {
-    Error_Handler();
-  }
-
-}
-
-void HAL_RTC_MspInit(RTC_HandleTypeDef* rtcHandle)
-{
-
-  if(rtcHandle->Instance==RTC)
-  {
-  /* USER CODE BEGIN RTC_MspInit 0 */
-
-  /* USER CODE END RTC_MspInit 0 */
-    /* RTC clock enable */
-    __HAL_RCC_RTC_ENABLE();
-    __HAL_RCC_RTCAPB_CLK_ENABLE();
-
-    /* RTC interrupt Init */
-    HAL_NVIC_SetPriority(TAMP_STAMP_LSECSS_IRQn, 5, 0);
-    HAL_NVIC_EnableIRQ(TAMP_STAMP_LSECSS_IRQn);
-  /* USER CODE BEGIN RTC_MspInit 1 */
-
-  /* USER CODE END RTC_MspInit 1 */
-  }
-}
-
-void HAL_RTC_MspDeInit(RTC_HandleTypeDef* rtcHandle)
-{
-
-  if(rtcHandle->Instance==RTC)
-  {
-  /* USER CODE BEGIN RTC_MspDeInit 0 */
-
-  /* USER CODE END RTC_MspDeInit 0 */
-    /* Peripheral clock disable */
-    __HAL_RCC_RTC_DISABLE();
-    __HAL_RCC_RTCAPB_CLK_DISABLE();
-
-    /* RTC interrupt Deinit */
-    HAL_NVIC_DisableIRQ(TAMP_STAMP_LSECSS_IRQn);
-  /* USER CODE BEGIN RTC_MspDeInit 1 */
-
-  /* USER CODE END RTC_MspDeInit 1 */
-  }
-}
-
-/* USER CODE BEGIN 1 */
-
-/* USER CODE END 1 */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 0 - 5
firmware/targets/f6/Src/stm32wbxx_it.c

@@ -6,7 +6,6 @@
 
 
 extern usbd_device udev;
 extern usbd_device udev;
 extern COMP_HandleTypeDef hcomp1;
 extern COMP_HandleTypeDef hcomp1;
-extern RTC_HandleTypeDef hrtc;
 extern TIM_HandleTypeDef htim1;
 extern TIM_HandleTypeDef htim1;
 extern TIM_HandleTypeDef htim2;
 extern TIM_HandleTypeDef htim2;
 extern TIM_HandleTypeDef htim16;
 extern TIM_HandleTypeDef htim16;
@@ -40,10 +39,6 @@ void HSEM_IRQHandler(void) {
     HAL_HSEM_IRQHandler();
     HAL_HSEM_IRQHandler();
 }
 }
 
 
-void RTC_WKUP_IRQHandler(void){
-    HW_TS_RTC_Wakeup_Handler();
-}
-
 void IPCC_C1_TX_IRQHandler(void){
 void IPCC_C1_TX_IRQHandler(void){
     HW_IPCC_Tx_Handler();
     HW_IPCC_Tx_Handler();
 }
 }

+ 0 - 159
firmware/targets/f6/ble-glue/hw_if.h

@@ -82,165 +82,6 @@ extern "C" {
   void HW_UART_Interrupt_Handler(hw_uart_id_t hw_uart_id);
   void HW_UART_Interrupt_Handler(hw_uart_id_t hw_uart_id);
   void HW_UART_DMA_Interrupt_Handler(hw_uart_id_t hw_uart_id);
   void HW_UART_DMA_Interrupt_Handler(hw_uart_id_t hw_uart_id);
 
 
-  /******************************************************************************
-   * HW TimerServer
-   ******************************************************************************/
-  /* Exported types ------------------------------------------------------------*/
-  /**
-   * This setting is used when standby mode is supported.
-   * hw_ts_InitMode_Limited should be used when the device restarts from Standby Mode. In that case, the Timer Server does
-   * not re-initialized its context. Only the Hardware register which content has been lost is reconfigured
-   * Otherwise, hw_ts_InitMode_Full should be requested (Start from Power ON) and everything is re-initialized.
-   */
-  typedef enum
-  {
-    hw_ts_InitMode_Full,
-    hw_ts_InitMode_Limited,
-  } HW_TS_InitMode_t;
-
-  /**
-   * When a Timer is created as a SingleShot timer, it is not automatically restarted when the timeout occurs. However,
-   * the timer is kept reserved in the list and could be restarted at anytime with HW_TS_Start()
-   *
-   * When a Timer is created as a Repeated timer, it is automatically restarted when the timeout occurs.
-   */
-  typedef enum
-  {
-    hw_ts_SingleShot,
-    hw_ts_Repeated
-  } HW_TS_Mode_t;
-
-  /**
-   * hw_ts_Successful is returned when a Timer has been successfully created with HW_TS_Create(). Otherwise, hw_ts_Failed
-   * is returned. When hw_ts_Failed is returned, that means there are not enough free slots in the list to create a
-   * Timer. In that case, CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER should be increased
-   */
-  typedef enum
-  {
-    hw_ts_Successful,
-    hw_ts_Failed,
-  }HW_TS_ReturnStatus_t;
-
-  typedef void (*HW_TS_pTimerCb_t)(void);
-
-  /**
-   * @brief  Initialize the timer server
-   *         This API shall be called by the application before any timer is requested to the timer server. It
-   *         configures the RTC module to be connected to the LSI input clock.
-   *
-   * @param  TimerInitMode: When the device restarts from Standby, it should request hw_ts_InitMode_Limited so that the
-   *         Timer context is not re-initialized. Otherwise, hw_ts_InitMode_Full should be requested
-   * @param  hrtc: RTC Handle
-   * @retval None
-   */
-  void HW_TS_Init(HW_TS_InitMode_t TimerInitMode, RTC_HandleTypeDef *hrtc);
-
-  /**
-   * @brief  Interface to create a virtual timer
-   *         The user shall call this API to create a timer. Once created, the timer is reserved to the module until it
-   *         has been deleted. When creating a timer, the user shall specify the mode (single shot or repeated), the
-   *         callback to be notified when the timer expires and a module ID to identify in the timer interrupt handler
-   *         which module is concerned. In return, the user gets a timer ID to handle it.
-   *
-   * @param  TimerProcessID:  This is an identifier provided by the user and returned in the callback to allow
-   *                          identification of the requester
-   * @param  pTimerId: Timer Id returned to the user to request operation (start, stop, delete)
-   * @param  TimerMode: Mode of the virtual timer (Single shot or repeated)
-   * @param  pTimerCallBack: Callback when the virtual timer expires
-   * @retval HW_TS_ReturnStatus_t: Return whether the creation is sucessfull or not
-   */
-  HW_TS_ReturnStatus_t HW_TS_Create(uint32_t TimerProcessID, uint8_t *pTimerId, HW_TS_Mode_t TimerMode, HW_TS_pTimerCb_t pTimerCallBack);
-
-  /**
-   * @brief  Stop a virtual timer
-   *         This API may be used to stop a running timer. A timer which is stopped is move to the pending state.
-   *         A pending timer may be restarted at any time with a different timeout value but the mode cannot be changed.
-   *         Nothing is done when it is called to stop a timer which has been already stopped
-   *
-   * @param  TimerID:  Id of the timer to stop
-   * @retval None
-   */
-  void HW_TS_Stop(uint8_t TimerID);
-
-  /**
-   * @brief  Start a virtual timer
-   *         This API shall be used to start a timer. The timeout value is specified and may be different each time.
-   *         When the timer is in the single shot mode, it will move to the pending state when it expires. The user may
-   *         restart it at any time with a different timeout value. When the timer is in the repeated mode, it always
-   *         stay in the running state. When the timer expires, it will be restarted with the same timeout value.
-   *         This API shall not be called on a running timer.
-   *
-   * @param  TimerID:  The ID Id of the timer to start
-   * @param  timeout_ticks: Number of ticks of the virtual timer (Maximum value is (0xFFFFFFFF-0xFFFF = 0xFFFF0000)
-   * @retval None
-   */
-  void HW_TS_Start(uint8_t TimerID, uint32_t timeout_ticks);
-
-  /**
-   * @brief  Delete a virtual timer from the list
-   *         This API should be used when a timer is not needed anymore by the user. A deleted timer is removed from
-   *         the timer list managed by the timer server. It cannot be restarted again. The user has to go with the
-   *         creation of a new timer if required and may get a different timer id
-   *
-   * @param  TimerID:  The ID of the timer to remove from the list
-   * @retval None
-   */
-  void HW_TS_Delete(uint8_t TimerID);
-
-  /**
-   * @brief  Schedule the timer list on the timer interrupt handler
-   *         This interrupt handler shall be called by the application in the RTC interrupt handler. This handler takes
-   *         care of clearing all status flag required in the RTC and EXTI peripherals
-   *
-   * @param  None
-   * @retval None
-   */
-  void HW_TS_RTC_Wakeup_Handler(void);
-
-  /**
-   * @brief  Return the number of ticks to count before the interrupt
-   *         This API returns the number of ticks left to be counted before an interrupt is generated by the
-   *         Timer Server. This API may be used by the application for power management optimization. When the system
-   *         enters low power mode, the mode selection is a tradeoff between the wakeup time where the CPU is running
-   *         and the time while the CPU will be kept in low power mode before next wakeup. The deeper is the
-   *         low power mode used, the longer is the wakeup time. The low power mode management considering wakeup time
-   *         versus time in low power mode is implementation specific
-   *         When the timer is disabled (No timer in the list), it returns 0xFFFF
-   *
-   * @param  None
-   * @retval The number of ticks left to count
-   */
-  uint16_t HW_TS_RTC_ReadLeftTicksToCount(void);
-
-  /**
-   * @brief  Notify the application that a registered timer has expired
-   *         This API shall be implemented by the user application.
-   *         This API notifies the application that a timer expires. This API is running in the RTC Wakeup interrupt
-   *         context. The application may implement an Operating System to change the context priority where the timer
-   *         callback may be handled. This API provides the module ID to identify which module is concerned and to allow
-   *         sending the information to the correct task
-   *
-   * @param  TimerProcessID: The TimerProcessId associated with the timer when it has been created
-   * @param  TimerID: The TimerID of the expired timer
-   * @param  pTimerCallBack: The Callback associated with the timer when it has been created
-   * @retval None
-   */
-  void HW_TS_RTC_Int_AppNot(uint32_t TimerProcessID, uint8_t TimerID, HW_TS_pTimerCb_t pTimerCallBack);
-
-  /**
-   * @brief  Notify the application that the wakeupcounter has been updated
-   *         This API should be implemented by the user application
-   *         This API notifies the application that the counter has been updated. This is expected to be used along
-   *         with the HW_TS_RTC_ReadLeftTicksToCount () API. It could be that the counter has been updated since the
-   *         last call of HW_TS_RTC_ReadLeftTicksToCount () and before entering low power mode. This notification
-   *         provides a way to the application to solve that race condition to reevaluate the counter value before
-   *         entering low power mode
-   *
-   * @param  None
-   * @retval None
-   */
-  void HW_TS_RTC_CountUpdated_AppNot(void);
-
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 0 - 893
firmware/targets/f6/ble-glue/hw_timerserver.c

@@ -1,893 +0,0 @@
-/**
- ******************************************************************************
-  * File Name          : hw_timerserver.c
-  * Description        : Hardware timerserver source file for STM32WPAN Middleware.
-  *
- ******************************************************************************
-  * @attention
-  *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
-  * All rights reserved.</center></h2>
-  *
-  * This software component is licensed by ST under Ultimate Liberty license
-  * SLA0044, the "License"; You may not use this file except in compliance with
-  * the License. You may obtain a copy of the License at:
-  *                             www.st.com/SLA0044
-  *
-  ******************************************************************************
-  */
-
-/* Includes ------------------------------------------------------------------*/
-#include "app_common.h"
-#include "hw_conf.h"
-
-/* Private typedef -----------------------------------------------------------*/
-typedef enum
-{
-  TimerID_Free,
-  TimerID_Created,
-  TimerID_Running
-}TimerIDStatus_t;
-
-typedef enum
-{
-  SSR_Read_Requested,
-  SSR_Read_Not_Requested
-}RequestReadSSR_t;
-
-typedef enum
-{
-  WakeupTimerValue_Overpassed,
-  WakeupTimerValue_LargeEnough
-}WakeupTimerLimitation_Status_t;
-
-typedef struct
-{
-  HW_TS_pTimerCb_t  pTimerCallBack;
-  uint32_t        CounterInit;
-  uint32_t        CountLeft;
-  TimerIDStatus_t     TimerIDStatus;
-  HW_TS_Mode_t   TimerMode;
-  uint32_t        TimerProcessID;
-  uint8_t         PreviousID;
-  uint8_t         NextID;
-}TimerContext_t;
-
-/* Private defines -----------------------------------------------------------*/
-#define SSR_FORBIDDEN_VALUE   0xFFFFFFFF
-#define TIMER_LIST_EMPTY      0xFFFF
-
-/* Private macros ------------------------------------------------------------*/
-/* Private variables ---------------------------------------------------------*/
-
-/**
- * START of Section TIMERSERVER_CONTEXT
- */
-
-PLACE_IN_SECTION("TIMERSERVER_CONTEXT") static volatile TimerContext_t aTimerContext[CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER];
-PLACE_IN_SECTION("TIMERSERVER_CONTEXT") static volatile uint8_t CurrentRunningTimerID;
-PLACE_IN_SECTION("TIMERSERVER_CONTEXT") static volatile uint8_t PreviousRunningTimerID;
-PLACE_IN_SECTION("TIMERSERVER_CONTEXT") static volatile uint32_t SSRValueOnLastSetup;
-PLACE_IN_SECTION("TIMERSERVER_CONTEXT") static volatile WakeupTimerLimitation_Status_t  WakeupTimerLimitation;
-
-/**
- * END of Section TIMERSERVER_CONTEXT
- */
-
-static RTC_HandleTypeDef *phrtc;  /**< RTC handle */
-static uint8_t  WakeupTimerDivider;
-static uint8_t  AsynchPrescalerUserConfig;
-static uint16_t SynchPrescalerUserConfig;
-static volatile uint16_t MaxWakeupTimerSetup;
-
-/* Global variables ----------------------------------------------------------*/
-/* Private function prototypes -----------------------------------------------*/
-static void RestartWakeupCounter(uint16_t Value);
-static uint16_t ReturnTimeElapsed(void);
-static void RescheduleTimerList(void);
-static void UnlinkTimer(uint8_t TimerID, RequestReadSSR_t RequestReadSSR);
-static void LinkTimerBefore(uint8_t TimerID, uint8_t RefTimerID);
-static void LinkTimerAfter(uint8_t TimerID, uint8_t RefTimerID);
-static uint16_t linkTimer(uint8_t TimerID);
-static uint32_t ReadRtcSsrValue(void);
-
-__weak void HW_TS_RTC_CountUpdated_AppNot(void);
-
-/* Functions Definition ------------------------------------------------------*/
-
-/**
- * @brief  Read the RTC_SSR value
- *         As described in the reference manual, the RTC_SSR shall be read twice to ensure
- *         reliability of the value
- * @param  None
- * @retval SSR value read
- */
-static uint32_t ReadRtcSsrValue(void)
-{
-  uint32_t first_read;
-  uint32_t second_read;
-
-  first_read = (uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS));
-
-  second_read = (uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS));
-
-  while(first_read != second_read)
-  {
-    first_read = second_read;
-
-    second_read = (uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS));
-  }
-
-  return second_read;
-}
-
-/**
- * @brief  Insert a Timer in the list after the Timer ID specified
- * @param  TimerID:   The ID of the Timer
- * @param  RefTimerID: The ID of the Timer to be linked after
- * @retval None
- */
-static void LinkTimerAfter(uint8_t TimerID, uint8_t RefTimerID)
-{
-  uint8_t next_id;
-
-  next_id = aTimerContext[RefTimerID].NextID;
-
-  if(next_id != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
-  {
-    aTimerContext[next_id].PreviousID = TimerID;
-  }
-  aTimerContext[TimerID].NextID = next_id;
-  aTimerContext[TimerID].PreviousID = RefTimerID ;
-  aTimerContext[RefTimerID].NextID = TimerID;
-
-  return;
-}
-
-/**
- * @brief  Insert a Timer in the list before the ID specified
- * @param  TimerID:   The ID of the Timer
- * @param  RefTimerID: The ID of the Timer to be linked before
- * @retval None
- */
-static void LinkTimerBefore(uint8_t TimerID, uint8_t RefTimerID)
-{
-  uint8_t previous_id;
-
-  if(RefTimerID != CurrentRunningTimerID)
-  {
-    previous_id = aTimerContext[RefTimerID].PreviousID;
-
-    aTimerContext[previous_id].NextID = TimerID;
-    aTimerContext[TimerID].NextID = RefTimerID;
-    aTimerContext[TimerID].PreviousID = previous_id ;
-    aTimerContext[RefTimerID].PreviousID = TimerID;
-  }
-  else
-  {
-    aTimerContext[TimerID].NextID = RefTimerID;
-    aTimerContext[RefTimerID].PreviousID = TimerID;
-  }
-
-  return;
-}
-
-/**
- * @brief  Insert a Timer in the list
- * @param  TimerID:   The ID of the Timer
- * @retval None
- */
-static uint16_t linkTimer(uint8_t TimerID)
-{
-  uint32_t time_left;
-  uint16_t time_elapsed;
-  uint8_t timer_id_lookup;
-  uint8_t next_id;
-
-  if(CurrentRunningTimerID == CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
-  {
-    /**
-     * No timer in the list
-     */
-    PreviousRunningTimerID = CurrentRunningTimerID;
-    CurrentRunningTimerID = TimerID;
-    aTimerContext[TimerID].NextID = CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER;
-
-    SSRValueOnLastSetup = SSR_FORBIDDEN_VALUE;
-    time_elapsed = 0;
-  }
-  else
-  {
-    time_elapsed = ReturnTimeElapsed();
-
-    /**
-     * update count of the timer to be linked
-     */
-    aTimerContext[TimerID].CountLeft += time_elapsed;
-    time_left = aTimerContext[TimerID].CountLeft;
-
-    /**
-     * Search for index where the new timer shall be linked
-     */
-    if(aTimerContext[CurrentRunningTimerID].CountLeft <= time_left)
-    {
-      /**
-       * Search for the ID after the first one
-       */
-      timer_id_lookup = CurrentRunningTimerID;
-      next_id = aTimerContext[timer_id_lookup].NextID;
-      while((next_id != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER) && (aTimerContext[next_id].CountLeft <= time_left))
-      {
-        timer_id_lookup = aTimerContext[timer_id_lookup].NextID;
-        next_id = aTimerContext[timer_id_lookup].NextID;
-      }
-
-      /**
-       * Link after the ID
-       */
-      LinkTimerAfter(TimerID, timer_id_lookup);
-    }
-    else
-    {
-      /**
-       * Link before the first ID
-       */
-      LinkTimerBefore(TimerID, CurrentRunningTimerID);
-      PreviousRunningTimerID = CurrentRunningTimerID;
-      CurrentRunningTimerID = TimerID;
-    }
-  }
-
-  return time_elapsed;
-}
-
-/**
- * @brief  Remove a Timer from the list
- * @param  TimerID:   The ID of the Timer
- * @param  RequestReadSSR: Request to read the SSR register or not
- * @retval None
- */
-static void UnlinkTimer(uint8_t TimerID, RequestReadSSR_t RequestReadSSR)
-{
-  uint8_t previous_id;
-  uint8_t next_id;
-
-  if(TimerID == CurrentRunningTimerID)
-  {
-    PreviousRunningTimerID = CurrentRunningTimerID;
-    CurrentRunningTimerID = aTimerContext[TimerID].NextID;
-  }
-  else
-  {
-    previous_id = aTimerContext[TimerID].PreviousID;
-    next_id = aTimerContext[TimerID].NextID;
-
-    aTimerContext[previous_id].NextID = aTimerContext[TimerID].NextID;
-    if(next_id != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
-    {
-      aTimerContext[next_id].PreviousID = aTimerContext[TimerID].PreviousID;
-    }
-  }
-
-  /**
-   * Timer is out of the list
-   */
-  aTimerContext[TimerID].TimerIDStatus = TimerID_Created;
-
-  if((CurrentRunningTimerID == CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER) && (RequestReadSSR == SSR_Read_Requested))
-  {
-    SSRValueOnLastSetup = SSR_FORBIDDEN_VALUE;
-  }
-
-  return;
-}
-
-/**
- * @brief  Return the number of ticks counted by the wakeuptimer since it has been started
- * @note  The API is reading the SSR register to get how many ticks have been counted
- *        since the time the timer has been started
- * @param  None
- * @retval Time expired in Ticks
- */
-static uint16_t ReturnTimeElapsed(void)
-{
-  uint32_t  return_value;
-  uint32_t  wrap_counter;
-
-  if(SSRValueOnLastSetup != SSR_FORBIDDEN_VALUE)
-  {
-    return_value = ReadRtcSsrValue(); /**< Read SSR register first */
-
-    if (SSRValueOnLastSetup >= return_value)
-    {
-      return_value = SSRValueOnLastSetup - return_value;
-    }
-    else
-    {
-      wrap_counter = SynchPrescalerUserConfig - return_value;
-      return_value = SSRValueOnLastSetup + wrap_counter;
-    }
-
-    /**
-     * At this stage, ReturnValue holds the number of ticks counted by SSR
-     * Need to translate in number of ticks counted by the Wakeuptimer
-     */
-    return_value = return_value*AsynchPrescalerUserConfig;
-    return_value = return_value >> WakeupTimerDivider;
-  }
-  else
-  {
-    return_value = 0;
-  }
-
-  return (uint16_t)return_value;
-}
-
-/**
- * @brief  Set the wakeup counter
- * @note  The API is writing the counter value so that the value is decreased by one to cope with the fact
- *    the interrupt is generated with 1 extra clock cycle (See RefManuel)
- *    It assumes all condition are met to be allowed to write the wakeup counter
- * @param  Value: Value to be written in the counter
- * @retval None
- */
-static void RestartWakeupCounter(uint16_t Value)
-{
-  /**
-   * The wakeuptimer has been disabled in the calling function to reduce the time to poll the WUTWF
-   * FLAG when the new value will have to be written
-   *  __HAL_RTC_WAKEUPTIMER_DISABLE(phrtc);
-   */
-
-  if(Value == 0)
-  {
-    SSRValueOnLastSetup = ReadRtcSsrValue();
-
-    /**
-     * Simulate that the Timer expired
-     */
-    HAL_NVIC_SetPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);
-  }
-  else
-  {
-    if((Value > 1) ||(WakeupTimerDivider != 1))
-    {
-      Value -= 1;
-    }
-
-    while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTWF) == RESET);
-
-    /**
-     * make sure to clear the flags after checking the WUTWF.
-     * It takes 2 RTCCLK between the time the WUTE bit is disabled and the
-     * time the timer is disabled. The WUTWF bit somehow guarantee the system is stable
-     * Otherwise, when the timer is periodic with 1 Tick, it may generate an extra interrupt in between
-     * due to the autoreload feature
-     */
-    __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(phrtc, RTC_FLAG_WUTF);   /**<  Clear flag in RTC module */
-    __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**<  Clear flag in EXTI module */
-    HAL_NVIC_ClearPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);   /**<  Clear pending bit in NVIC */
-
-    MODIFY_REG(RTC->WUTR, RTC_WUTR_WUT, Value);
-
-    /**
-     * Update the value here after the WUTWF polling that may take some time
-     */
-    SSRValueOnLastSetup = ReadRtcSsrValue();
-
-    __HAL_RTC_WAKEUPTIMER_ENABLE(phrtc);    /**<  Enable the Wakeup Timer */
-
-    HW_TS_RTC_CountUpdated_AppNot();
-  }
-
-  return ;
-}
-
-/**
- * @brief  Reschedule the list of timer
- * @note  1) Update the count left for each timer in the list
- *    2) Setup the wakeuptimer
- * @param  None
- * @retval None
- */
-static void RescheduleTimerList(void)
-{
-  uint8_t   localTimerID;
-  uint32_t  timecountleft;
-  uint16_t  wakeup_timer_value;
-  uint16_t  time_elapsed;
-
-  /**
-   * The wakeuptimer is disabled now to reduce the time to poll the WUTWF
-   * FLAG when the new value will have to be written
-   */
-  if((READ_BIT(RTC->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) == SET)
-  {
-    /**
-     * Wait for the flag to be back to 0 when the wakeup timer is enabled
-     */
-    while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTWF) == SET);
-  }
-  __HAL_RTC_WAKEUPTIMER_DISABLE(phrtc);   /**<  Disable the Wakeup Timer */
-
-  localTimerID = CurrentRunningTimerID;
-
-  /**
-   * Calculate what will be the value to write in the wakeuptimer
-   */
-  timecountleft = aTimerContext[localTimerID].CountLeft;
-
-  /**
-   * Read how much has been counted
-   */
-  time_elapsed = ReturnTimeElapsed();
-
-  if(timecountleft < time_elapsed )
-  {
-    /**
-     * There is no tick left to count
-     */
-    wakeup_timer_value = 0;
-    WakeupTimerLimitation = WakeupTimerValue_LargeEnough;
-  }
-  else
-  {
-    if(timecountleft > (time_elapsed + MaxWakeupTimerSetup))
-    {
-      /**
-       * The number of tick left is greater than the Wakeuptimer maximum value
-       */
-      wakeup_timer_value = MaxWakeupTimerSetup;
-
-      WakeupTimerLimitation = WakeupTimerValue_Overpassed;
-    }
-    else
-    {
-      wakeup_timer_value = timecountleft - time_elapsed;
-      WakeupTimerLimitation = WakeupTimerValue_LargeEnough;
-    }
-
-  }
-
-  /**
-   * update ticks left to be counted for each timer
-   */
-  while(localTimerID != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
-  {
-    if (aTimerContext[localTimerID].CountLeft < time_elapsed)
-    {
-      aTimerContext[localTimerID].CountLeft = 0;
-    }
-    else
-    {
-      aTimerContext[localTimerID].CountLeft -= time_elapsed;
-    }
-    localTimerID = aTimerContext[localTimerID].NextID;
-  }
-
-  /**
-   * Write next count
-   */
-  RestartWakeupCounter(wakeup_timer_value);
-
-  return ;
-}
-
-/* Public functions ----------------------------------------------------------*/
-
-/**
- * For all public interface except that may need write access to the RTC, the RTC
- * shall be unlock at the beginning and locked at the output
- * In order to ease maintainability, the unlock is done at the top and the lock at then end
- * in case some new implementation is coming in the future
- */
-
-void HW_TS_RTC_Wakeup_Handler(void)
-{
-  HW_TS_pTimerCb_t ptimer_callback;
-  uint32_t timer_process_id;
-  uint8_t local_current_running_timer_id;
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  uint32_t primask_bit;
-#endif
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  primask_bit = __get_PRIMASK();  /**< backup PRIMASK bit */
-  __disable_irq();          /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
-#endif
-
-/* Disable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
-
-  /**
-   * Disable the Wakeup Timer
-   * This may speed up a bit the processing to wait the timer to be disabled
-   * The timer is still counting 2 RTCCLK
-   */
-  __HAL_RTC_WAKEUPTIMER_DISABLE(phrtc);
-
-  local_current_running_timer_id = CurrentRunningTimerID;
-
-  if(aTimerContext[local_current_running_timer_id].TimerIDStatus == TimerID_Running)
-  {
-    ptimer_callback = aTimerContext[local_current_running_timer_id].pTimerCallBack;
-    timer_process_id = aTimerContext[local_current_running_timer_id].TimerProcessID;
-
-    /**
-     * It should be good to check whether the TimeElapsed is greater or not than the tick left to be counted
-     * However, due to the inaccuracy of the reading of the time elapsed, it may return there is 1 tick
-     * to be left whereas the count is over
-     * A more secure implementation has been done with a flag to state whereas the full count has been written
-     * in the wakeuptimer or not
-     */
-    if(WakeupTimerLimitation != WakeupTimerValue_Overpassed)
-    {
-      if(aTimerContext[local_current_running_timer_id].TimerMode == hw_ts_Repeated)
-      {
-        UnlinkTimer(local_current_running_timer_id, SSR_Read_Not_Requested);
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-        __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-        HW_TS_Start(local_current_running_timer_id, aTimerContext[local_current_running_timer_id].CounterInit);
-
-        /* Disable the write protection for RTC registers */
-        __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
-        }
-      else
-      {
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-        __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-        HW_TS_Stop(local_current_running_timer_id);
-
-        /* Disable the write protection for RTC registers */
-        __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
-        }
-
-      HW_TS_RTC_Int_AppNot(timer_process_id, local_current_running_timer_id, ptimer_callback);
-    }
-    else
-    {
-      RescheduleTimerList();
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-      __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-    }
-  }
-  else
-  {
-    /**
-     * We should never end up in this case
-     * However, if due to any bug in the timer server this is the case, the mistake may not impact the user.
-     * We could just clean the interrupt flag and get out from this unexpected interrupt
-     */
-    while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTWF) == RESET);
-
-    /**
-     * make sure to clear the flags after checking the WUTWF.
-     * It takes 2 RTCCLK between the time the WUTE bit is disabled and the
-     * time the timer is disabled. The WUTWF bit somehow guarantee the system is stable
-     * Otherwise, when the timer is periodic with 1 Tick, it may generate an extra interrupt in between
-     * due to the autoreload feature
-     */
-    __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(phrtc, RTC_FLAG_WUTF);   /**<  Clear flag in RTC module */
-    __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**<  Clear flag in EXTI module */
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-    __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-  }
-
-  /* Enable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_ENABLE( phrtc );
-
-  return;
-}
-
-void HW_TS_Init(HW_TS_InitMode_t TimerInitMode, RTC_HandleTypeDef *hrtc)
-{
-  uint8_t loop;
-  uint32_t localmaxwakeuptimersetup;
-
-  /**
-   * Get RTC handler
-   */
-  phrtc = hrtc;
-
- /* Disable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
-
-  SET_BIT(RTC->CR, RTC_CR_BYPSHAD);
-
-  /**
-   * Readout the user config
-   */
-  WakeupTimerDivider = (4 - ((uint32_t)(READ_BIT(RTC->CR, RTC_CR_WUCKSEL))));
-
-  AsynchPrescalerUserConfig = (uint8_t)(READ_BIT(RTC->PRER, RTC_PRER_PREDIV_A) >> (uint32_t)POSITION_VAL(RTC_PRER_PREDIV_A)) + 1;
-
-  SynchPrescalerUserConfig = (uint16_t)(READ_BIT(RTC->PRER, RTC_PRER_PREDIV_S)) + 1;
-
-  /**
-   *  Margin is taken to avoid wrong calculation when the wrap around is there and some
-   *  application interrupts may have delayed the reading
-   */
-  localmaxwakeuptimersetup = ((((SynchPrescalerUserConfig - 1)*AsynchPrescalerUserConfig) - CFG_HW_TS_RTC_HANDLER_MAX_DELAY) >> WakeupTimerDivider);
-
-  if(localmaxwakeuptimersetup >= 0xFFFF)
-  {
-    MaxWakeupTimerSetup = 0xFFFF;
-  }
-  else
-  {
-    MaxWakeupTimerSetup = (uint16_t)localmaxwakeuptimersetup;
-  }
-
-  /**
-   * Configure EXTI module
-   */
-  LL_EXTI_EnableRisingTrig_0_31(RTC_EXTI_LINE_WAKEUPTIMER_EVENT);
-  LL_EXTI_EnableIT_0_31(RTC_EXTI_LINE_WAKEUPTIMER_EVENT);
-
-  if(TimerInitMode == hw_ts_InitMode_Full)
-  {
-    WakeupTimerLimitation = WakeupTimerValue_LargeEnough;
-    SSRValueOnLastSetup = SSR_FORBIDDEN_VALUE;
-
-    /**
-     * Initialize the timer server
-     */
-    for(loop = 0; loop < CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER; loop++)
-    {
-      aTimerContext[loop].TimerIDStatus = TimerID_Free;
-    }
-
-    CurrentRunningTimerID = CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER;   /**<  Set ID to non valid value */
-
-    __HAL_RTC_WAKEUPTIMER_DISABLE(phrtc);                       /**<  Disable the Wakeup Timer */
-    __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(phrtc, RTC_FLAG_WUTF);     /**<  Clear flag in RTC module */
-    __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**<  Clear flag in EXTI module  */
-    HAL_NVIC_ClearPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);       /**<  Clear pending bit in NVIC  */
-    __HAL_RTC_WAKEUPTIMER_ENABLE_IT(phrtc, RTC_IT_WUT);         /**<  Enable interrupt in RTC module  */
-  }
-  else
-  {
-    if(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTF) != RESET)
-    {
-      /**
-       * Simulate that the Timer expired
-       */
-      HAL_NVIC_SetPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);
-    }
-  }
-
-  /* Enable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_ENABLE( phrtc );
-
-  HAL_NVIC_SetPriority(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID, CFG_HW_TS_NVIC_RTC_WAKEUP_IT_PREEMPTPRIO, CFG_HW_TS_NVIC_RTC_WAKEUP_IT_SUBPRIO);   /**<  Set NVIC priority */
-  HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**<  Enable NVIC */
-
-  return;
-}
-
-HW_TS_ReturnStatus_t HW_TS_Create(uint32_t TimerProcessID, uint8_t *pTimerId, HW_TS_Mode_t TimerMode, HW_TS_pTimerCb_t pftimeout_handler)
-{
-  HW_TS_ReturnStatus_t localreturnstatus;
-  uint8_t loop = 0;
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  uint32_t primask_bit;
-#endif
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  primask_bit = __get_PRIMASK();  /**< backup PRIMASK bit */
-  __disable_irq();          /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
-#endif
-
-  while((loop < CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER) && (aTimerContext[loop].TimerIDStatus != TimerID_Free))
-  {
-    loop++;
-  }
-
-  if(loop != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
-  {
-    aTimerContext[loop].TimerIDStatus = TimerID_Created;
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-    __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-
-    aTimerContext[loop].TimerProcessID = TimerProcessID;
-    aTimerContext[loop].TimerMode = TimerMode;
-    aTimerContext[loop].pTimerCallBack = pftimeout_handler;
-    *pTimerId = loop;
-
-    localreturnstatus = hw_ts_Successful;
-  }
-  else
-  {
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-    __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-
-    localreturnstatus = hw_ts_Failed;
-  }
-
-  return(localreturnstatus);
-}
-
-void HW_TS_Delete(uint8_t timer_id)
-{
-  HW_TS_Stop(timer_id);
-
-  aTimerContext[timer_id].TimerIDStatus = TimerID_Free; /**<  release ID */
-
-  return;
-}
-
-void HW_TS_Stop(uint8_t timer_id)
-{
-  uint8_t localcurrentrunningtimerid;
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  uint32_t primask_bit;
-#endif
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  primask_bit = __get_PRIMASK();  /**< backup PRIMASK bit */
-  __disable_irq();          /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
-#endif
-
-  HAL_NVIC_DisableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);    /**<  Disable NVIC */
-
-  /* Disable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
-
-  if(aTimerContext[timer_id].TimerIDStatus == TimerID_Running)
-  {
-    UnlinkTimer(timer_id, SSR_Read_Requested);
-    localcurrentrunningtimerid = CurrentRunningTimerID;
-
-    if(localcurrentrunningtimerid == CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
-    {
-      /**
-       * List is empty
-       */
-
-      /**
-       * Disable the timer
-       */
-      if((READ_BIT(RTC->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) == SET)
-      {
-        /**
-         * Wait for the flag to be back to 0 when the wakeup timer is enabled
-         */
-        while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTWF) == SET);
-      }
-      __HAL_RTC_WAKEUPTIMER_DISABLE(phrtc);   /**<  Disable the Wakeup Timer */
-
-      while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTWF) == RESET);
-
-      /**
-       * make sure to clear the flags after checking the WUTWF.
-       * It takes 2 RTCCLK between the time the WUTE bit is disabled and the
-       * time the timer is disabled. The WUTWF bit somehow guarantee the system is stable
-       * Otherwise, when the timer is periodic with 1 Tick, it may generate an extra interrupt in between
-       * due to the autoreload feature
-       */
-      __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(phrtc, RTC_FLAG_WUTF);   /**<  Clear flag in RTC module */
-      __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**<  Clear flag in EXTI module */
-      HAL_NVIC_ClearPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);   /**<  Clear pending bit in NVIC */
-    }
-    else if(PreviousRunningTimerID != localcurrentrunningtimerid)
-    {
-      RescheduleTimerList();
-    }
-  }
-
-  /* Enable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_ENABLE( phrtc );
-
-  HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**<  Enable NVIC */
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-
-  return;
-}
-
-void HW_TS_Start(uint8_t timer_id, uint32_t timeout_ticks)
-{
-  uint16_t time_elapsed;
-  uint8_t localcurrentrunningtimerid;
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  uint32_t primask_bit;
-#endif
-
-  if(aTimerContext[timer_id].TimerIDStatus == TimerID_Running)
-  {
-    HW_TS_Stop( timer_id );
-  }
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  primask_bit = __get_PRIMASK();  /**< backup PRIMASK bit */
-  __disable_irq();          /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
-#endif
-
-  HAL_NVIC_DisableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);    /**<  Disable NVIC */
-
-  /* Disable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
-
-  aTimerContext[timer_id].TimerIDStatus = TimerID_Running;
-
-  aTimerContext[timer_id].CountLeft = timeout_ticks;
-  aTimerContext[timer_id].CounterInit = timeout_ticks;
-
-  time_elapsed =  linkTimer(timer_id);
-
-  localcurrentrunningtimerid = CurrentRunningTimerID;
-
-  if(PreviousRunningTimerID != localcurrentrunningtimerid)
-  {
-    RescheduleTimerList();
-  }
-  else
-  {
-    aTimerContext[timer_id].CountLeft -= time_elapsed;
-  }
-
-  /* Enable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_ENABLE( phrtc );
-
-  HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**<  Enable NVIC */
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-
-  return;
-}
-
-uint16_t HW_TS_RTC_ReadLeftTicksToCount(void)
-{
-  uint32_t primask_bit;
-  uint16_t return_value, auro_reload_value, elapsed_time_value;
-
-  primask_bit = __get_PRIMASK();  /**< backup PRIMASK bit */
-  __disable_irq();                /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
-
-  if((READ_BIT(RTC->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) == SET)
-  {
-    auro_reload_value = (uint32_t)(READ_BIT(RTC->WUTR, RTC_WUTR_WUT));
-
-    elapsed_time_value = ReturnTimeElapsed();
-
-    if(auro_reload_value > elapsed_time_value)
-    {
-      return_value = auro_reload_value - elapsed_time_value;
-    }
-    else
-    {
-      return_value = 0;
-    }
-  }
-  else
-  {
-    return_value = TIMER_LIST_EMPTY;
-  }
-
-  __set_PRIMASK(primask_bit);     /**< Restore PRIMASK bit*/
-
-  return (return_value);
-}
-
-__weak void HW_TS_RTC_Int_AppNot(uint32_t TimerProcessID, uint8_t TimerID, HW_TS_pTimerCb_t pTimerCallBack)
-{
-  pTimerCallBack();
-
-  return;
-}
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 0 - 8
firmware/targets/f6/furi-hal/furi-hal-bootloader.c

@@ -23,11 +23,3 @@ void furi_hal_bootloader_set_mode(FuriHalBootloaderMode mode) {
         LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_DFU);
         LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_DFU);
     }
     }
 }
 }
-
-void furi_hal_bootloader_set_flags(FuriHalBootloaderFlag flags) {
-    LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR2, flags);
-}
-
-FuriHalBootloaderFlag furi_hal_bootloader_get_flags() {
-    return LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR2);
-}

+ 0 - 9
firmware/targets/f6/furi-hal/furi-hal-clock.c

@@ -77,14 +77,6 @@ void furi_hal_clock_init() {
         Error_Handler();
         Error_Handler();
     }
     }
 
 
-    if(LL_RCC_GetRTCClockSource() != LL_RCC_RTC_CLKSOURCE_LSE) {
-        LL_RCC_ForceBackupDomainReset();
-        LL_RCC_ReleaseBackupDomainReset();
-        LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
-    }
-
-    LL_RCC_EnableRTC();
-
     LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
     LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
     LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1);
     LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1);
     LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLLSAI1);
     LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLLSAI1);
@@ -118,7 +110,6 @@ void furi_hal_clock_init() {
     LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_AES2);
     LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_AES2);
 
 
     // APB1
     // APB1
-    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
     LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
     LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
     LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1);
     LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1);
 
 

+ 0 - 3
firmware/targets/f6/furi-hal/furi-hal-interrupt.c

@@ -158,7 +158,6 @@ void DMA2_Channel8_IRQHandler(void) {
     if (furi_hal_dma_channel_isr[1][7]) furi_hal_dma_channel_isr[1][7]();
     if (furi_hal_dma_channel_isr[1][7]) furi_hal_dma_channel_isr[1][7]();
 }
 }
 
 
-
 void TAMP_STAMP_LSECSS_IRQHandler(void) {
 void TAMP_STAMP_LSECSS_IRQHandler(void) {
     if (LL_RCC_IsActiveFlag_LSECSS()) {
     if (LL_RCC_IsActiveFlag_LSECSS()) {
         LL_RCC_ClearFlag_LSECSS();
         LL_RCC_ClearFlag_LSECSS();
@@ -174,7 +173,6 @@ void TAMP_STAMP_LSECSS_IRQHandler(void) {
 void RCC_IRQHandler(void) {
 void RCC_IRQHandler(void) {
 }
 }
 
 
-
 void NMI_Handler(void) {
 void NMI_Handler(void) {
     if (LL_RCC_IsActiveFlag_HSECSS()) {
     if (LL_RCC_IsActiveFlag_HSECSS()) {
         LL_RCC_ClearFlag_HSECSS();
         LL_RCC_ClearFlag_HSECSS();
@@ -206,5 +204,4 @@ void UsageFault_Handler(void) {
 }
 }
 
 
 void DebugMon_Handler(void) {
 void DebugMon_Handler(void) {
-
 }
 }

+ 122 - 0
firmware/targets/f6/furi-hal/furi-hal-rtc.c

@@ -0,0 +1,122 @@
+#include <furi-hal-rtc.h>
+#include <stm32wbxx_ll_rcc.h>
+#include <stm32wbxx_ll_rtc.h>
+
+#include <furi.h>
+
+#define TAG "FuriHalRtc"
+
+#define FURI_HAL_RTC_BOOT_FLAGS_REG LL_RTC_BKP_DR0
+#define FURI_HAL_RTC_BOOT_VERSION_REG LL_RTC_BKP_DR1
+#define FURI_HAL_RTC_SYSTEM_REG LL_RTC_BKP_DR2
+
+typedef struct {
+    uint8_t log_level:4;
+    uint8_t log_reserved:4;
+    uint8_t flags;
+    uint16_t reserved;
+} DeveloperReg;
+
+void furi_hal_rtc_init() {
+    if(LL_RCC_GetRTCClockSource() != LL_RCC_RTC_CLKSOURCE_LSE) {
+        LL_RCC_ForceBackupDomainReset();
+        LL_RCC_ReleaseBackupDomainReset();
+        LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
+    }
+
+    LL_RCC_EnableRTC();
+    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
+
+    LL_RTC_InitTypeDef RTC_InitStruct = {0};
+    RTC_InitStruct.HourFormat = LL_RTC_HOURFORMAT_24HOUR;
+    RTC_InitStruct.AsynchPrescaler = 127;
+    RTC_InitStruct.SynchPrescaler = 255;
+    LL_RTC_Init(RTC, &RTC_InitStruct);
+
+    furi_log_set_level(furi_hal_rtc_get_log_level());
+
+    FURI_LOG_I(TAG, "Init OK");
+}
+
+void furi_hal_rtc_set_log_level(uint8_t level) {
+    uint32_t data = LL_RTC_BAK_GetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG);
+    ((DeveloperReg*)&data)->log_level = level;
+    LL_RTC_BAK_SetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG, data);
+    furi_log_set_level(level);
+}
+
+uint8_t furi_hal_rtc_get_log_level() {
+    uint32_t data = LL_RTC_BAK_GetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG);
+    return ((DeveloperReg*)&data)->log_level;
+}
+
+void furi_hal_rtc_set_flag(FuriHalRtcFlag flag) {
+    uint32_t data = LL_RTC_BAK_GetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG);
+    ((DeveloperReg*)&data)->flags |= flag;
+    LL_RTC_BAK_SetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG, data);
+}
+
+void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag) {
+    uint32_t data = LL_RTC_BAK_GetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG);
+    ((DeveloperReg*)&data)->flags &= ~flag;
+    LL_RTC_BAK_SetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG, data);
+}
+
+bool furi_hal_rtc_is_flag_set(FuriHalRtcFlag flag) {
+    uint32_t data = LL_RTC_BAK_GetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG);
+    return ((DeveloperReg*)&data)->flags & flag;
+}
+
+void furi_hal_rtc_set_datetime(FuriHalRtcDateTime* datetime) {
+    furi_assert(datetime);
+
+    /* Disable write protection */
+    LL_RTC_DisableWriteProtection(RTC);
+
+    /* Enter Initialization mode and wait for INIT flag to be set */
+    LL_RTC_EnableInitMode(RTC);
+    while(!LL_RTC_IsActiveFlag_INIT(RTC)) {}
+
+    /* Set time */
+    LL_RTC_TIME_Config(RTC,
+        LL_RTC_TIME_FORMAT_AM_OR_24,
+        __LL_RTC_CONVERT_BIN2BCD(datetime->hour),
+        __LL_RTC_CONVERT_BIN2BCD(datetime->minute),
+        __LL_RTC_CONVERT_BIN2BCD(datetime->second)
+    );
+
+    /* Set date */
+    LL_RTC_DATE_Config(RTC,
+        datetime->weekday,
+        __LL_RTC_CONVERT_BIN2BCD(datetime->day),
+        __LL_RTC_CONVERT_BIN2BCD(datetime->month),
+        __LL_RTC_CONVERT_BIN2BCD(datetime->year - 2000)
+    );
+
+    /* Exit Initialization mode */
+    LL_RTC_DisableInitMode(RTC);
+
+    /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+    if (!LL_RTC_IsShadowRegBypassEnabled(RTC)) {
+        LL_RTC_ClearFlag_RS(RTC);
+        while(!LL_RTC_IsActiveFlag_RS(RTC)) {};
+    }
+
+    /* Enable write protection */
+    LL_RTC_EnableWriteProtection(RTC);
+}
+
+void furi_hal_rtc_get_datetime(FuriHalRtcDateTime* datetime) {
+    furi_assert(datetime);
+
+    uint32_t time = LL_RTC_TIME_Get(RTC); // 0x00HHMMSS
+    uint32_t date = LL_RTC_DATE_Get(RTC); // 0xWWDDMMYY
+
+    datetime->second = __LL_RTC_CONVERT_BCD2BIN((time>>0) & 0xFF);
+    datetime->minute = __LL_RTC_CONVERT_BCD2BIN((time>>8) & 0xFF);
+    datetime->hour = __LL_RTC_CONVERT_BCD2BIN((time>>16) & 0xFF);
+    datetime->year = __LL_RTC_CONVERT_BCD2BIN((date >> 0) & 0xFF) + 2000;
+    datetime->month = __LL_RTC_CONVERT_BCD2BIN((date >> 8) & 0xFF);
+    datetime->day = __LL_RTC_CONVERT_BCD2BIN((date >> 16) & 0xFF);
+    datetime->weekday = __LL_RTC_CONVERT_BCD2BIN((date >> 24) & 0xFF);
+}

+ 4 - 6
firmware/targets/f6/furi-hal/furi-hal.c

@@ -1,7 +1,6 @@
 #include <furi-hal.h>
 #include <furi-hal.h>
 
 
 #include <comp.h>
 #include <comp.h>
-#include <rtc.h>
 #include <tim.h>
 #include <tim.h>
 #include <gpio.h>
 #include <gpio.h>
 
 
@@ -13,18 +12,14 @@
 
 
 void furi_hal_init() {
 void furi_hal_init() {
     furi_hal_clock_init();
     furi_hal_clock_init();
+    furi_hal_rtc_init();
     furi_hal_console_init();
     furi_hal_console_init();
     furi_hal_interrupt_init();
     furi_hal_interrupt_init();
     furi_hal_delay_init();
     furi_hal_delay_init();
 
 
-    // FreeRTOS glue
-    furi_hal_os_init();
-
     MX_GPIO_Init();
     MX_GPIO_Init();
     FURI_LOG_I(TAG, "GPIO OK");
     FURI_LOG_I(TAG, "GPIO OK");
 
 
-    MX_RTC_Init();
-    FURI_LOG_I(TAG, "RTC OK");
     furi_hal_bootloader_init();
     furi_hal_bootloader_init();
     furi_hal_version_init();
     furi_hal_version_init();
 
 
@@ -59,6 +54,9 @@ void furi_hal_init() {
     furi_hal_bt_init();
     furi_hal_bt_init();
     furi_hal_compress_icon_init();
     furi_hal_compress_icon_init();
 
 
+    // FreeRTOS glue
+    furi_hal_os_init();
+
     // FatFS driver initialization
     // FatFS driver initialization
     MX_FATFS_Init();
     MX_FATFS_Init();
     FURI_LOG_I(TAG, "FATFS OK");
     FURI_LOG_I(TAG, "FATFS OK");

+ 2 - 2
firmware/targets/f6/target.mk

@@ -24,7 +24,7 @@ LDFLAGS			+= $(MCU_FLAGS) -specs=nosys.specs -specs=nano.specs -u _printf_float
 CPPFLAGS		+= -fno-rtti -fno-use-cxa-atexit -fno-exceptions
 CPPFLAGS		+= -fno-rtti -fno-use-cxa-atexit -fno-exceptions
 LDFLAGS			+= -Wl,--start-group -lstdc++ -lsupc++ -Wl,--end-group
 LDFLAGS			+= -Wl,--start-group -lstdc++ -lsupc++ -Wl,--end-group
 
 
-HARDWARE_TARGET = 6
+HARDWARE_TARGET = 7
 
 
 MXPROJECT_DIR = $(TARGET_DIR)
 MXPROJECT_DIR = $(TARGET_DIR)
 
 
@@ -57,7 +57,6 @@ C_SOURCES += \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr_ex.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr_ex.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rcc.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rcc.c \
-	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rtc.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rtc_ex.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rtc_ex.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_tim.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_tim.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_tim_ex.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_tim_ex.c \
@@ -67,6 +66,7 @@ C_SOURCES += \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_i2c.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_i2c.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_lptim.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_lptim.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_rcc.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_rcc.c \
+	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_rtc.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_spi.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_spi.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_tim.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_tim.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_usart.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_usart.c \

+ 0 - 52
firmware/targets/f7/Inc/rtc.h

@@ -1,52 +0,0 @@
-/**
-  ******************************************************************************
-  * @file    rtc.h
-  * @brief   This file contains all the function prototypes for
-  *          the rtc.c file
-  ******************************************************************************
-  * @attention
-  *
-  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
-  * All rights reserved.</center></h2>
-  *
-  * This software component is licensed by ST under Ultimate Liberty license
-  * SLA0044, the "License"; You may not use this file except in compliance with
-  * the License. You may obtain a copy of the License at:
-  *                             www.st.com/SLA0044
-  *
-  ******************************************************************************
-  */
-/* Define to prevent recursive inclusion -------------------------------------*/
-#ifndef __RTC_H__
-#define __RTC_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Includes ------------------------------------------------------------------*/
-#include "main.h"
-
-/* USER CODE BEGIN Includes */
-
-/* USER CODE END Includes */
-
-extern RTC_HandleTypeDef hrtc;
-
-/* USER CODE BEGIN Private defines */
-
-/* USER CODE END Private defines */
-
-void MX_RTC_Init(void);
-
-/* USER CODE BEGIN Prototypes */
-
-/* USER CODE END Prototypes */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __RTC_H__ */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 1 - 1
firmware/targets/f7/Inc/stm32wbxx_hal_conf.h

@@ -48,7 +48,7 @@
 #define HAL_PKA_MODULE_ENABLED
 #define HAL_PKA_MODULE_ENABLED
 /*#define HAL_QSPI_MODULE_ENABLED   */
 /*#define HAL_QSPI_MODULE_ENABLED   */
 #define HAL_RNG_MODULE_ENABLED
 #define HAL_RNG_MODULE_ENABLED
-#define HAL_RTC_MODULE_ENABLED
+/*#define HAL_RTC_MODULE_ENABLED    */
 /*#define HAL_SAI_MODULE_ENABLED    */
 /*#define HAL_SAI_MODULE_ENABLED    */
 /*#define HAL_SMBUS_MODULE_ENABLED  */
 /*#define HAL_SMBUS_MODULE_ENABLED  */
 /*#define HAL_SMARTCARD_MODULE_ENABLED   */
 /*#define HAL_SMARTCARD_MODULE_ENABLED   */

+ 0 - 123
firmware/targets/f7/Src/rtc.c

@@ -1,123 +0,0 @@
-/**
-  ******************************************************************************
-  * @file    rtc.c
-  * @brief   This file provides code for the configuration
-  *          of the RTC instances.
-  ******************************************************************************
-  * @attention
-  *
-  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
-  * All rights reserved.</center></h2>
-  *
-  * This software component is licensed by ST under Ultimate Liberty license
-  * SLA0044, the "License"; You may not use this file except in compliance with
-  * the License. You may obtain a copy of the License at:
-  *                             www.st.com/SLA0044
-  *
-  ******************************************************************************
-  */
-
-/* Includes ------------------------------------------------------------------*/
-#include "rtc.h"
-
-/* USER CODE BEGIN 0 */
-
-/* USER CODE END 0 */
-
-RTC_HandleTypeDef hrtc;
-
-/* RTC init function */
-void MX_RTC_Init(void)
-{
-  RTC_TimeTypeDef sTime = {0};
-  RTC_DateTypeDef sDate = {0};
-
-  /** Initialize RTC Only
-  */
-  hrtc.Instance = RTC;
-  hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
-  hrtc.Init.AsynchPrediv = 127;
-  hrtc.Init.SynchPrediv = 255;
-  hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
-  hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
-  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
-  hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
-  if (HAL_RTC_Init(&hrtc) != HAL_OK)
-  {
-    Error_Handler();
-  }
-
-  /* USER CODE BEGIN Check_RTC_BKUP */
-  return;
-  /* USER CODE END Check_RTC_BKUP */
-
-  /** Initialize RTC and set the Time and Date
-  */
-  sTime.Hours = 0x0;
-  sTime.Minutes = 0x0;
-  sTime.Seconds = 0x0;
-  sTime.SubSeconds = 0x0;
-  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
-  sTime.StoreOperation = RTC_STOREOPERATION_RESET;
-  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
-  {
-    Error_Handler();
-  }
-  sDate.WeekDay = RTC_WEEKDAY_MONDAY;
-  sDate.Month = RTC_MONTH_JANUARY;
-  sDate.Date = 0x1;
-  sDate.Year = 0x0;
-
-  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
-  {
-    Error_Handler();
-  }
-
-}
-
-void HAL_RTC_MspInit(RTC_HandleTypeDef* rtcHandle)
-{
-
-  if(rtcHandle->Instance==RTC)
-  {
-  /* USER CODE BEGIN RTC_MspInit 0 */
-
-  /* USER CODE END RTC_MspInit 0 */
-    /* RTC clock enable */
-    __HAL_RCC_RTC_ENABLE();
-    __HAL_RCC_RTCAPB_CLK_ENABLE();
-
-    /* RTC interrupt Init */
-    HAL_NVIC_SetPriority(TAMP_STAMP_LSECSS_IRQn, 5, 0);
-    HAL_NVIC_EnableIRQ(TAMP_STAMP_LSECSS_IRQn);
-  /* USER CODE BEGIN RTC_MspInit 1 */
-
-  /* USER CODE END RTC_MspInit 1 */
-  }
-}
-
-void HAL_RTC_MspDeInit(RTC_HandleTypeDef* rtcHandle)
-{
-
-  if(rtcHandle->Instance==RTC)
-  {
-  /* USER CODE BEGIN RTC_MspDeInit 0 */
-
-  /* USER CODE END RTC_MspDeInit 0 */
-    /* Peripheral clock disable */
-    __HAL_RCC_RTC_DISABLE();
-    __HAL_RCC_RTCAPB_CLK_DISABLE();
-
-    /* RTC interrupt Deinit */
-    HAL_NVIC_DisableIRQ(TAMP_STAMP_LSECSS_IRQn);
-  /* USER CODE BEGIN RTC_MspDeInit 1 */
-
-  /* USER CODE END RTC_MspDeInit 1 */
-  }
-}
-
-/* USER CODE BEGIN 1 */
-
-/* USER CODE END 1 */
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 0 - 5
firmware/targets/f7/Src/stm32wbxx_it.c

@@ -6,7 +6,6 @@
 
 
 extern usbd_device udev;
 extern usbd_device udev;
 extern COMP_HandleTypeDef hcomp1;
 extern COMP_HandleTypeDef hcomp1;
-extern RTC_HandleTypeDef hrtc;
 extern TIM_HandleTypeDef htim1;
 extern TIM_HandleTypeDef htim1;
 extern TIM_HandleTypeDef htim2;
 extern TIM_HandleTypeDef htim2;
 extern TIM_HandleTypeDef htim16;
 extern TIM_HandleTypeDef htim16;
@@ -40,10 +39,6 @@ void HSEM_IRQHandler(void) {
     HAL_HSEM_IRQHandler();
     HAL_HSEM_IRQHandler();
 }
 }
 
 
-void RTC_WKUP_IRQHandler(void){
-    HW_TS_RTC_Wakeup_Handler();
-}
-
 void IPCC_C1_TX_IRQHandler(void){
 void IPCC_C1_TX_IRQHandler(void){
     HW_IPCC_Tx_Handler();
     HW_IPCC_Tx_Handler();
 }
 }

+ 0 - 159
firmware/targets/f7/ble-glue/hw_if.h

@@ -82,165 +82,6 @@ extern "C" {
   void HW_UART_Interrupt_Handler(hw_uart_id_t hw_uart_id);
   void HW_UART_Interrupt_Handler(hw_uart_id_t hw_uart_id);
   void HW_UART_DMA_Interrupt_Handler(hw_uart_id_t hw_uart_id);
   void HW_UART_DMA_Interrupt_Handler(hw_uart_id_t hw_uart_id);
 
 
-  /******************************************************************************
-   * HW TimerServer
-   ******************************************************************************/
-  /* Exported types ------------------------------------------------------------*/
-  /**
-   * This setting is used when standby mode is supported.
-   * hw_ts_InitMode_Limited should be used when the device restarts from Standby Mode. In that case, the Timer Server does
-   * not re-initialized its context. Only the Hardware register which content has been lost is reconfigured
-   * Otherwise, hw_ts_InitMode_Full should be requested (Start from Power ON) and everything is re-initialized.
-   */
-  typedef enum
-  {
-    hw_ts_InitMode_Full,
-    hw_ts_InitMode_Limited,
-  } HW_TS_InitMode_t;
-
-  /**
-   * When a Timer is created as a SingleShot timer, it is not automatically restarted when the timeout occurs. However,
-   * the timer is kept reserved in the list and could be restarted at anytime with HW_TS_Start()
-   *
-   * When a Timer is created as a Repeated timer, it is automatically restarted when the timeout occurs.
-   */
-  typedef enum
-  {
-    hw_ts_SingleShot,
-    hw_ts_Repeated
-  } HW_TS_Mode_t;
-
-  /**
-   * hw_ts_Successful is returned when a Timer has been successfully created with HW_TS_Create(). Otherwise, hw_ts_Failed
-   * is returned. When hw_ts_Failed is returned, that means there are not enough free slots in the list to create a
-   * Timer. In that case, CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER should be increased
-   */
-  typedef enum
-  {
-    hw_ts_Successful,
-    hw_ts_Failed,
-  }HW_TS_ReturnStatus_t;
-
-  typedef void (*HW_TS_pTimerCb_t)(void);
-
-  /**
-   * @brief  Initialize the timer server
-   *         This API shall be called by the application before any timer is requested to the timer server. It
-   *         configures the RTC module to be connected to the LSI input clock.
-   *
-   * @param  TimerInitMode: When the device restarts from Standby, it should request hw_ts_InitMode_Limited so that the
-   *         Timer context is not re-initialized. Otherwise, hw_ts_InitMode_Full should be requested
-   * @param  hrtc: RTC Handle
-   * @retval None
-   */
-  void HW_TS_Init(HW_TS_InitMode_t TimerInitMode, RTC_HandleTypeDef *hrtc);
-
-  /**
-   * @brief  Interface to create a virtual timer
-   *         The user shall call this API to create a timer. Once created, the timer is reserved to the module until it
-   *         has been deleted. When creating a timer, the user shall specify the mode (single shot or repeated), the
-   *         callback to be notified when the timer expires and a module ID to identify in the timer interrupt handler
-   *         which module is concerned. In return, the user gets a timer ID to handle it.
-   *
-   * @param  TimerProcessID:  This is an identifier provided by the user and returned in the callback to allow
-   *                          identification of the requester
-   * @param  pTimerId: Timer Id returned to the user to request operation (start, stop, delete)
-   * @param  TimerMode: Mode of the virtual timer (Single shot or repeated)
-   * @param  pTimerCallBack: Callback when the virtual timer expires
-   * @retval HW_TS_ReturnStatus_t: Return whether the creation is sucessfull or not
-   */
-  HW_TS_ReturnStatus_t HW_TS_Create(uint32_t TimerProcessID, uint8_t *pTimerId, HW_TS_Mode_t TimerMode, HW_TS_pTimerCb_t pTimerCallBack);
-
-  /**
-   * @brief  Stop a virtual timer
-   *         This API may be used to stop a running timer. A timer which is stopped is move to the pending state.
-   *         A pending timer may be restarted at any time with a different timeout value but the mode cannot be changed.
-   *         Nothing is done when it is called to stop a timer which has been already stopped
-   *
-   * @param  TimerID:  Id of the timer to stop
-   * @retval None
-   */
-  void HW_TS_Stop(uint8_t TimerID);
-
-  /**
-   * @brief  Start a virtual timer
-   *         This API shall be used to start a timer. The timeout value is specified and may be different each time.
-   *         When the timer is in the single shot mode, it will move to the pending state when it expires. The user may
-   *         restart it at any time with a different timeout value. When the timer is in the repeated mode, it always
-   *         stay in the running state. When the timer expires, it will be restarted with the same timeout value.
-   *         This API shall not be called on a running timer.
-   *
-   * @param  TimerID:  The ID Id of the timer to start
-   * @param  timeout_ticks: Number of ticks of the virtual timer (Maximum value is (0xFFFFFFFF-0xFFFF = 0xFFFF0000)
-   * @retval None
-   */
-  void HW_TS_Start(uint8_t TimerID, uint32_t timeout_ticks);
-
-  /**
-   * @brief  Delete a virtual timer from the list
-   *         This API should be used when a timer is not needed anymore by the user. A deleted timer is removed from
-   *         the timer list managed by the timer server. It cannot be restarted again. The user has to go with the
-   *         creation of a new timer if required and may get a different timer id
-   *
-   * @param  TimerID:  The ID of the timer to remove from the list
-   * @retval None
-   */
-  void HW_TS_Delete(uint8_t TimerID);
-
-  /**
-   * @brief  Schedule the timer list on the timer interrupt handler
-   *         This interrupt handler shall be called by the application in the RTC interrupt handler. This handler takes
-   *         care of clearing all status flag required in the RTC and EXTI peripherals
-   *
-   * @param  None
-   * @retval None
-   */
-  void HW_TS_RTC_Wakeup_Handler(void);
-
-  /**
-   * @brief  Return the number of ticks to count before the interrupt
-   *         This API returns the number of ticks left to be counted before an interrupt is generated by the
-   *         Timer Server. This API may be used by the application for power management optimization. When the system
-   *         enters low power mode, the mode selection is a tradeoff between the wakeup time where the CPU is running
-   *         and the time while the CPU will be kept in low power mode before next wakeup. The deeper is the
-   *         low power mode used, the longer is the wakeup time. The low power mode management considering wakeup time
-   *         versus time in low power mode is implementation specific
-   *         When the timer is disabled (No timer in the list), it returns 0xFFFF
-   *
-   * @param  None
-   * @retval The number of ticks left to count
-   */
-  uint16_t HW_TS_RTC_ReadLeftTicksToCount(void);
-
-  /**
-   * @brief  Notify the application that a registered timer has expired
-   *         This API shall be implemented by the user application.
-   *         This API notifies the application that a timer expires. This API is running in the RTC Wakeup interrupt
-   *         context. The application may implement an Operating System to change the context priority where the timer
-   *         callback may be handled. This API provides the module ID to identify which module is concerned and to allow
-   *         sending the information to the correct task
-   *
-   * @param  TimerProcessID: The TimerProcessId associated with the timer when it has been created
-   * @param  TimerID: The TimerID of the expired timer
-   * @param  pTimerCallBack: The Callback associated with the timer when it has been created
-   * @retval None
-   */
-  void HW_TS_RTC_Int_AppNot(uint32_t TimerProcessID, uint8_t TimerID, HW_TS_pTimerCb_t pTimerCallBack);
-
-  /**
-   * @brief  Notify the application that the wakeupcounter has been updated
-   *         This API should be implemented by the user application
-   *         This API notifies the application that the counter has been updated. This is expected to be used along
-   *         with the HW_TS_RTC_ReadLeftTicksToCount () API. It could be that the counter has been updated since the
-   *         last call of HW_TS_RTC_ReadLeftTicksToCount () and before entering low power mode. This notification
-   *         provides a way to the application to solve that race condition to reevaluate the counter value before
-   *         entering low power mode
-   *
-   * @param  None
-   * @retval None
-   */
-  void HW_TS_RTC_CountUpdated_AppNot(void);
-
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 0 - 893
firmware/targets/f7/ble-glue/hw_timerserver.c

@@ -1,893 +0,0 @@
-/**
- ******************************************************************************
-  * File Name          : hw_timerserver.c
-  * Description        : Hardware timerserver source file for STM32WPAN Middleware.
-  *
- ******************************************************************************
-  * @attention
-  *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
-  * All rights reserved.</center></h2>
-  *
-  * This software component is licensed by ST under Ultimate Liberty license
-  * SLA0044, the "License"; You may not use this file except in compliance with
-  * the License. You may obtain a copy of the License at:
-  *                             www.st.com/SLA0044
-  *
-  ******************************************************************************
-  */
-
-/* Includes ------------------------------------------------------------------*/
-#include "app_common.h"
-#include "hw_conf.h"
-
-/* Private typedef -----------------------------------------------------------*/
-typedef enum
-{
-  TimerID_Free,
-  TimerID_Created,
-  TimerID_Running
-}TimerIDStatus_t;
-
-typedef enum
-{
-  SSR_Read_Requested,
-  SSR_Read_Not_Requested
-}RequestReadSSR_t;
-
-typedef enum
-{
-  WakeupTimerValue_Overpassed,
-  WakeupTimerValue_LargeEnough
-}WakeupTimerLimitation_Status_t;
-
-typedef struct
-{
-  HW_TS_pTimerCb_t  pTimerCallBack;
-  uint32_t        CounterInit;
-  uint32_t        CountLeft;
-  TimerIDStatus_t     TimerIDStatus;
-  HW_TS_Mode_t   TimerMode;
-  uint32_t        TimerProcessID;
-  uint8_t         PreviousID;
-  uint8_t         NextID;
-}TimerContext_t;
-
-/* Private defines -----------------------------------------------------------*/
-#define SSR_FORBIDDEN_VALUE   0xFFFFFFFF
-#define TIMER_LIST_EMPTY      0xFFFF
-
-/* Private macros ------------------------------------------------------------*/
-/* Private variables ---------------------------------------------------------*/
-
-/**
- * START of Section TIMERSERVER_CONTEXT
- */
-
-PLACE_IN_SECTION("TIMERSERVER_CONTEXT") static volatile TimerContext_t aTimerContext[CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER];
-PLACE_IN_SECTION("TIMERSERVER_CONTEXT") static volatile uint8_t CurrentRunningTimerID;
-PLACE_IN_SECTION("TIMERSERVER_CONTEXT") static volatile uint8_t PreviousRunningTimerID;
-PLACE_IN_SECTION("TIMERSERVER_CONTEXT") static volatile uint32_t SSRValueOnLastSetup;
-PLACE_IN_SECTION("TIMERSERVER_CONTEXT") static volatile WakeupTimerLimitation_Status_t  WakeupTimerLimitation;
-
-/**
- * END of Section TIMERSERVER_CONTEXT
- */
-
-static RTC_HandleTypeDef *phrtc;  /**< RTC handle */
-static uint8_t  WakeupTimerDivider;
-static uint8_t  AsynchPrescalerUserConfig;
-static uint16_t SynchPrescalerUserConfig;
-static volatile uint16_t MaxWakeupTimerSetup;
-
-/* Global variables ----------------------------------------------------------*/
-/* Private function prototypes -----------------------------------------------*/
-static void RestartWakeupCounter(uint16_t Value);
-static uint16_t ReturnTimeElapsed(void);
-static void RescheduleTimerList(void);
-static void UnlinkTimer(uint8_t TimerID, RequestReadSSR_t RequestReadSSR);
-static void LinkTimerBefore(uint8_t TimerID, uint8_t RefTimerID);
-static void LinkTimerAfter(uint8_t TimerID, uint8_t RefTimerID);
-static uint16_t linkTimer(uint8_t TimerID);
-static uint32_t ReadRtcSsrValue(void);
-
-__weak void HW_TS_RTC_CountUpdated_AppNot(void);
-
-/* Functions Definition ------------------------------------------------------*/
-
-/**
- * @brief  Read the RTC_SSR value
- *         As described in the reference manual, the RTC_SSR shall be read twice to ensure
- *         reliability of the value
- * @param  None
- * @retval SSR value read
- */
-static uint32_t ReadRtcSsrValue(void)
-{
-  uint32_t first_read;
-  uint32_t second_read;
-
-  first_read = (uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS));
-
-  second_read = (uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS));
-
-  while(first_read != second_read)
-  {
-    first_read = second_read;
-
-    second_read = (uint32_t)(READ_BIT(RTC->SSR, RTC_SSR_SS));
-  }
-
-  return second_read;
-}
-
-/**
- * @brief  Insert a Timer in the list after the Timer ID specified
- * @param  TimerID:   The ID of the Timer
- * @param  RefTimerID: The ID of the Timer to be linked after
- * @retval None
- */
-static void LinkTimerAfter(uint8_t TimerID, uint8_t RefTimerID)
-{
-  uint8_t next_id;
-
-  next_id = aTimerContext[RefTimerID].NextID;
-
-  if(next_id != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
-  {
-    aTimerContext[next_id].PreviousID = TimerID;
-  }
-  aTimerContext[TimerID].NextID = next_id;
-  aTimerContext[TimerID].PreviousID = RefTimerID ;
-  aTimerContext[RefTimerID].NextID = TimerID;
-
-  return;
-}
-
-/**
- * @brief  Insert a Timer in the list before the ID specified
- * @param  TimerID:   The ID of the Timer
- * @param  RefTimerID: The ID of the Timer to be linked before
- * @retval None
- */
-static void LinkTimerBefore(uint8_t TimerID, uint8_t RefTimerID)
-{
-  uint8_t previous_id;
-
-  if(RefTimerID != CurrentRunningTimerID)
-  {
-    previous_id = aTimerContext[RefTimerID].PreviousID;
-
-    aTimerContext[previous_id].NextID = TimerID;
-    aTimerContext[TimerID].NextID = RefTimerID;
-    aTimerContext[TimerID].PreviousID = previous_id ;
-    aTimerContext[RefTimerID].PreviousID = TimerID;
-  }
-  else
-  {
-    aTimerContext[TimerID].NextID = RefTimerID;
-    aTimerContext[RefTimerID].PreviousID = TimerID;
-  }
-
-  return;
-}
-
-/**
- * @brief  Insert a Timer in the list
- * @param  TimerID:   The ID of the Timer
- * @retval None
- */
-static uint16_t linkTimer(uint8_t TimerID)
-{
-  uint32_t time_left;
-  uint16_t time_elapsed;
-  uint8_t timer_id_lookup;
-  uint8_t next_id;
-
-  if(CurrentRunningTimerID == CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
-  {
-    /**
-     * No timer in the list
-     */
-    PreviousRunningTimerID = CurrentRunningTimerID;
-    CurrentRunningTimerID = TimerID;
-    aTimerContext[TimerID].NextID = CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER;
-
-    SSRValueOnLastSetup = SSR_FORBIDDEN_VALUE;
-    time_elapsed = 0;
-  }
-  else
-  {
-    time_elapsed = ReturnTimeElapsed();
-
-    /**
-     * update count of the timer to be linked
-     */
-    aTimerContext[TimerID].CountLeft += time_elapsed;
-    time_left = aTimerContext[TimerID].CountLeft;
-
-    /**
-     * Search for index where the new timer shall be linked
-     */
-    if(aTimerContext[CurrentRunningTimerID].CountLeft <= time_left)
-    {
-      /**
-       * Search for the ID after the first one
-       */
-      timer_id_lookup = CurrentRunningTimerID;
-      next_id = aTimerContext[timer_id_lookup].NextID;
-      while((next_id != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER) && (aTimerContext[next_id].CountLeft <= time_left))
-      {
-        timer_id_lookup = aTimerContext[timer_id_lookup].NextID;
-        next_id = aTimerContext[timer_id_lookup].NextID;
-      }
-
-      /**
-       * Link after the ID
-       */
-      LinkTimerAfter(TimerID, timer_id_lookup);
-    }
-    else
-    {
-      /**
-       * Link before the first ID
-       */
-      LinkTimerBefore(TimerID, CurrentRunningTimerID);
-      PreviousRunningTimerID = CurrentRunningTimerID;
-      CurrentRunningTimerID = TimerID;
-    }
-  }
-
-  return time_elapsed;
-}
-
-/**
- * @brief  Remove a Timer from the list
- * @param  TimerID:   The ID of the Timer
- * @param  RequestReadSSR: Request to read the SSR register or not
- * @retval None
- */
-static void UnlinkTimer(uint8_t TimerID, RequestReadSSR_t RequestReadSSR)
-{
-  uint8_t previous_id;
-  uint8_t next_id;
-
-  if(TimerID == CurrentRunningTimerID)
-  {
-    PreviousRunningTimerID = CurrentRunningTimerID;
-    CurrentRunningTimerID = aTimerContext[TimerID].NextID;
-  }
-  else
-  {
-    previous_id = aTimerContext[TimerID].PreviousID;
-    next_id = aTimerContext[TimerID].NextID;
-
-    aTimerContext[previous_id].NextID = aTimerContext[TimerID].NextID;
-    if(next_id != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
-    {
-      aTimerContext[next_id].PreviousID = aTimerContext[TimerID].PreviousID;
-    }
-  }
-
-  /**
-   * Timer is out of the list
-   */
-  aTimerContext[TimerID].TimerIDStatus = TimerID_Created;
-
-  if((CurrentRunningTimerID == CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER) && (RequestReadSSR == SSR_Read_Requested))
-  {
-    SSRValueOnLastSetup = SSR_FORBIDDEN_VALUE;
-  }
-
-  return;
-}
-
-/**
- * @brief  Return the number of ticks counted by the wakeuptimer since it has been started
- * @note  The API is reading the SSR register to get how many ticks have been counted
- *        since the time the timer has been started
- * @param  None
- * @retval Time expired in Ticks
- */
-static uint16_t ReturnTimeElapsed(void)
-{
-  uint32_t  return_value;
-  uint32_t  wrap_counter;
-
-  if(SSRValueOnLastSetup != SSR_FORBIDDEN_VALUE)
-  {
-    return_value = ReadRtcSsrValue(); /**< Read SSR register first */
-
-    if (SSRValueOnLastSetup >= return_value)
-    {
-      return_value = SSRValueOnLastSetup - return_value;
-    }
-    else
-    {
-      wrap_counter = SynchPrescalerUserConfig - return_value;
-      return_value = SSRValueOnLastSetup + wrap_counter;
-    }
-
-    /**
-     * At this stage, ReturnValue holds the number of ticks counted by SSR
-     * Need to translate in number of ticks counted by the Wakeuptimer
-     */
-    return_value = return_value*AsynchPrescalerUserConfig;
-    return_value = return_value >> WakeupTimerDivider;
-  }
-  else
-  {
-    return_value = 0;
-  }
-
-  return (uint16_t)return_value;
-}
-
-/**
- * @brief  Set the wakeup counter
- * @note  The API is writing the counter value so that the value is decreased by one to cope with the fact
- *    the interrupt is generated with 1 extra clock cycle (See RefManuel)
- *    It assumes all condition are met to be allowed to write the wakeup counter
- * @param  Value: Value to be written in the counter
- * @retval None
- */
-static void RestartWakeupCounter(uint16_t Value)
-{
-  /**
-   * The wakeuptimer has been disabled in the calling function to reduce the time to poll the WUTWF
-   * FLAG when the new value will have to be written
-   *  __HAL_RTC_WAKEUPTIMER_DISABLE(phrtc);
-   */
-
-  if(Value == 0)
-  {
-    SSRValueOnLastSetup = ReadRtcSsrValue();
-
-    /**
-     * Simulate that the Timer expired
-     */
-    HAL_NVIC_SetPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);
-  }
-  else
-  {
-    if((Value > 1) ||(WakeupTimerDivider != 1))
-    {
-      Value -= 1;
-    }
-
-    while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTWF) == RESET);
-
-    /**
-     * make sure to clear the flags after checking the WUTWF.
-     * It takes 2 RTCCLK between the time the WUTE bit is disabled and the
-     * time the timer is disabled. The WUTWF bit somehow guarantee the system is stable
-     * Otherwise, when the timer is periodic with 1 Tick, it may generate an extra interrupt in between
-     * due to the autoreload feature
-     */
-    __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(phrtc, RTC_FLAG_WUTF);   /**<  Clear flag in RTC module */
-    __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**<  Clear flag in EXTI module */
-    HAL_NVIC_ClearPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);   /**<  Clear pending bit in NVIC */
-
-    MODIFY_REG(RTC->WUTR, RTC_WUTR_WUT, Value);
-
-    /**
-     * Update the value here after the WUTWF polling that may take some time
-     */
-    SSRValueOnLastSetup = ReadRtcSsrValue();
-
-    __HAL_RTC_WAKEUPTIMER_ENABLE(phrtc);    /**<  Enable the Wakeup Timer */
-
-    HW_TS_RTC_CountUpdated_AppNot();
-  }
-
-  return ;
-}
-
-/**
- * @brief  Reschedule the list of timer
- * @note  1) Update the count left for each timer in the list
- *    2) Setup the wakeuptimer
- * @param  None
- * @retval None
- */
-static void RescheduleTimerList(void)
-{
-  uint8_t   localTimerID;
-  uint32_t  timecountleft;
-  uint16_t  wakeup_timer_value;
-  uint16_t  time_elapsed;
-
-  /**
-   * The wakeuptimer is disabled now to reduce the time to poll the WUTWF
-   * FLAG when the new value will have to be written
-   */
-  if((READ_BIT(RTC->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) == SET)
-  {
-    /**
-     * Wait for the flag to be back to 0 when the wakeup timer is enabled
-     */
-    while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTWF) == SET);
-  }
-  __HAL_RTC_WAKEUPTIMER_DISABLE(phrtc);   /**<  Disable the Wakeup Timer */
-
-  localTimerID = CurrentRunningTimerID;
-
-  /**
-   * Calculate what will be the value to write in the wakeuptimer
-   */
-  timecountleft = aTimerContext[localTimerID].CountLeft;
-
-  /**
-   * Read how much has been counted
-   */
-  time_elapsed = ReturnTimeElapsed();
-
-  if(timecountleft < time_elapsed )
-  {
-    /**
-     * There is no tick left to count
-     */
-    wakeup_timer_value = 0;
-    WakeupTimerLimitation = WakeupTimerValue_LargeEnough;
-  }
-  else
-  {
-    if(timecountleft > (time_elapsed + MaxWakeupTimerSetup))
-    {
-      /**
-       * The number of tick left is greater than the Wakeuptimer maximum value
-       */
-      wakeup_timer_value = MaxWakeupTimerSetup;
-
-      WakeupTimerLimitation = WakeupTimerValue_Overpassed;
-    }
-    else
-    {
-      wakeup_timer_value = timecountleft - time_elapsed;
-      WakeupTimerLimitation = WakeupTimerValue_LargeEnough;
-    }
-
-  }
-
-  /**
-   * update ticks left to be counted for each timer
-   */
-  while(localTimerID != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
-  {
-    if (aTimerContext[localTimerID].CountLeft < time_elapsed)
-    {
-      aTimerContext[localTimerID].CountLeft = 0;
-    }
-    else
-    {
-      aTimerContext[localTimerID].CountLeft -= time_elapsed;
-    }
-    localTimerID = aTimerContext[localTimerID].NextID;
-  }
-
-  /**
-   * Write next count
-   */
-  RestartWakeupCounter(wakeup_timer_value);
-
-  return ;
-}
-
-/* Public functions ----------------------------------------------------------*/
-
-/**
- * For all public interface except that may need write access to the RTC, the RTC
- * shall be unlock at the beginning and locked at the output
- * In order to ease maintainability, the unlock is done at the top and the lock at then end
- * in case some new implementation is coming in the future
- */
-
-void HW_TS_RTC_Wakeup_Handler(void)
-{
-  HW_TS_pTimerCb_t ptimer_callback;
-  uint32_t timer_process_id;
-  uint8_t local_current_running_timer_id;
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  uint32_t primask_bit;
-#endif
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  primask_bit = __get_PRIMASK();  /**< backup PRIMASK bit */
-  __disable_irq();          /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
-#endif
-
-/* Disable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
-
-  /**
-   * Disable the Wakeup Timer
-   * This may speed up a bit the processing to wait the timer to be disabled
-   * The timer is still counting 2 RTCCLK
-   */
-  __HAL_RTC_WAKEUPTIMER_DISABLE(phrtc);
-
-  local_current_running_timer_id = CurrentRunningTimerID;
-
-  if(aTimerContext[local_current_running_timer_id].TimerIDStatus == TimerID_Running)
-  {
-    ptimer_callback = aTimerContext[local_current_running_timer_id].pTimerCallBack;
-    timer_process_id = aTimerContext[local_current_running_timer_id].TimerProcessID;
-
-    /**
-     * It should be good to check whether the TimeElapsed is greater or not than the tick left to be counted
-     * However, due to the inaccuracy of the reading of the time elapsed, it may return there is 1 tick
-     * to be left whereas the count is over
-     * A more secure implementation has been done with a flag to state whereas the full count has been written
-     * in the wakeuptimer or not
-     */
-    if(WakeupTimerLimitation != WakeupTimerValue_Overpassed)
-    {
-      if(aTimerContext[local_current_running_timer_id].TimerMode == hw_ts_Repeated)
-      {
-        UnlinkTimer(local_current_running_timer_id, SSR_Read_Not_Requested);
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-        __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-        HW_TS_Start(local_current_running_timer_id, aTimerContext[local_current_running_timer_id].CounterInit);
-
-        /* Disable the write protection for RTC registers */
-        __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
-        }
-      else
-      {
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-        __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-        HW_TS_Stop(local_current_running_timer_id);
-
-        /* Disable the write protection for RTC registers */
-        __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
-        }
-
-      HW_TS_RTC_Int_AppNot(timer_process_id, local_current_running_timer_id, ptimer_callback);
-    }
-    else
-    {
-      RescheduleTimerList();
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-      __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-    }
-  }
-  else
-  {
-    /**
-     * We should never end up in this case
-     * However, if due to any bug in the timer server this is the case, the mistake may not impact the user.
-     * We could just clean the interrupt flag and get out from this unexpected interrupt
-     */
-    while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTWF) == RESET);
-
-    /**
-     * make sure to clear the flags after checking the WUTWF.
-     * It takes 2 RTCCLK between the time the WUTE bit is disabled and the
-     * time the timer is disabled. The WUTWF bit somehow guarantee the system is stable
-     * Otherwise, when the timer is periodic with 1 Tick, it may generate an extra interrupt in between
-     * due to the autoreload feature
-     */
-    __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(phrtc, RTC_FLAG_WUTF);   /**<  Clear flag in RTC module */
-    __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**<  Clear flag in EXTI module */
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-    __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-  }
-
-  /* Enable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_ENABLE( phrtc );
-
-  return;
-}
-
-void HW_TS_Init(HW_TS_InitMode_t TimerInitMode, RTC_HandleTypeDef *hrtc)
-{
-  uint8_t loop;
-  uint32_t localmaxwakeuptimersetup;
-
-  /**
-   * Get RTC handler
-   */
-  phrtc = hrtc;
-
- /* Disable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
-
-  SET_BIT(RTC->CR, RTC_CR_BYPSHAD);
-
-  /**
-   * Readout the user config
-   */
-  WakeupTimerDivider = (4 - ((uint32_t)(READ_BIT(RTC->CR, RTC_CR_WUCKSEL))));
-
-  AsynchPrescalerUserConfig = (uint8_t)(READ_BIT(RTC->PRER, RTC_PRER_PREDIV_A) >> (uint32_t)POSITION_VAL(RTC_PRER_PREDIV_A)) + 1;
-
-  SynchPrescalerUserConfig = (uint16_t)(READ_BIT(RTC->PRER, RTC_PRER_PREDIV_S)) + 1;
-
-  /**
-   *  Margin is taken to avoid wrong calculation when the wrap around is there and some
-   *  application interrupts may have delayed the reading
-   */
-  localmaxwakeuptimersetup = ((((SynchPrescalerUserConfig - 1)*AsynchPrescalerUserConfig) - CFG_HW_TS_RTC_HANDLER_MAX_DELAY) >> WakeupTimerDivider);
-
-  if(localmaxwakeuptimersetup >= 0xFFFF)
-  {
-    MaxWakeupTimerSetup = 0xFFFF;
-  }
-  else
-  {
-    MaxWakeupTimerSetup = (uint16_t)localmaxwakeuptimersetup;
-  }
-
-  /**
-   * Configure EXTI module
-   */
-  LL_EXTI_EnableRisingTrig_0_31(RTC_EXTI_LINE_WAKEUPTIMER_EVENT);
-  LL_EXTI_EnableIT_0_31(RTC_EXTI_LINE_WAKEUPTIMER_EVENT);
-
-  if(TimerInitMode == hw_ts_InitMode_Full)
-  {
-    WakeupTimerLimitation = WakeupTimerValue_LargeEnough;
-    SSRValueOnLastSetup = SSR_FORBIDDEN_VALUE;
-
-    /**
-     * Initialize the timer server
-     */
-    for(loop = 0; loop < CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER; loop++)
-    {
-      aTimerContext[loop].TimerIDStatus = TimerID_Free;
-    }
-
-    CurrentRunningTimerID = CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER;   /**<  Set ID to non valid value */
-
-    __HAL_RTC_WAKEUPTIMER_DISABLE(phrtc);                       /**<  Disable the Wakeup Timer */
-    __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(phrtc, RTC_FLAG_WUTF);     /**<  Clear flag in RTC module */
-    __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**<  Clear flag in EXTI module  */
-    HAL_NVIC_ClearPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);       /**<  Clear pending bit in NVIC  */
-    __HAL_RTC_WAKEUPTIMER_ENABLE_IT(phrtc, RTC_IT_WUT);         /**<  Enable interrupt in RTC module  */
-  }
-  else
-  {
-    if(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTF) != RESET)
-    {
-      /**
-       * Simulate that the Timer expired
-       */
-      HAL_NVIC_SetPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);
-    }
-  }
-
-  /* Enable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_ENABLE( phrtc );
-
-  HAL_NVIC_SetPriority(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID, CFG_HW_TS_NVIC_RTC_WAKEUP_IT_PREEMPTPRIO, CFG_HW_TS_NVIC_RTC_WAKEUP_IT_SUBPRIO);   /**<  Set NVIC priority */
-  HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**<  Enable NVIC */
-
-  return;
-}
-
-HW_TS_ReturnStatus_t HW_TS_Create(uint32_t TimerProcessID, uint8_t *pTimerId, HW_TS_Mode_t TimerMode, HW_TS_pTimerCb_t pftimeout_handler)
-{
-  HW_TS_ReturnStatus_t localreturnstatus;
-  uint8_t loop = 0;
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  uint32_t primask_bit;
-#endif
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  primask_bit = __get_PRIMASK();  /**< backup PRIMASK bit */
-  __disable_irq();          /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
-#endif
-
-  while((loop < CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER) && (aTimerContext[loop].TimerIDStatus != TimerID_Free))
-  {
-    loop++;
-  }
-
-  if(loop != CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
-  {
-    aTimerContext[loop].TimerIDStatus = TimerID_Created;
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-    __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-
-    aTimerContext[loop].TimerProcessID = TimerProcessID;
-    aTimerContext[loop].TimerMode = TimerMode;
-    aTimerContext[loop].pTimerCallBack = pftimeout_handler;
-    *pTimerId = loop;
-
-    localreturnstatus = hw_ts_Successful;
-  }
-  else
-  {
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-    __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-
-    localreturnstatus = hw_ts_Failed;
-  }
-
-  return(localreturnstatus);
-}
-
-void HW_TS_Delete(uint8_t timer_id)
-{
-  HW_TS_Stop(timer_id);
-
-  aTimerContext[timer_id].TimerIDStatus = TimerID_Free; /**<  release ID */
-
-  return;
-}
-
-void HW_TS_Stop(uint8_t timer_id)
-{
-  uint8_t localcurrentrunningtimerid;
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  uint32_t primask_bit;
-#endif
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  primask_bit = __get_PRIMASK();  /**< backup PRIMASK bit */
-  __disable_irq();          /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
-#endif
-
-  HAL_NVIC_DisableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);    /**<  Disable NVIC */
-
-  /* Disable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
-
-  if(aTimerContext[timer_id].TimerIDStatus == TimerID_Running)
-  {
-    UnlinkTimer(timer_id, SSR_Read_Requested);
-    localcurrentrunningtimerid = CurrentRunningTimerID;
-
-    if(localcurrentrunningtimerid == CFG_HW_TS_MAX_NBR_CONCURRENT_TIMER)
-    {
-      /**
-       * List is empty
-       */
-
-      /**
-       * Disable the timer
-       */
-      if((READ_BIT(RTC->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) == SET)
-      {
-        /**
-         * Wait for the flag to be back to 0 when the wakeup timer is enabled
-         */
-        while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTWF) == SET);
-      }
-      __HAL_RTC_WAKEUPTIMER_DISABLE(phrtc);   /**<  Disable the Wakeup Timer */
-
-      while(__HAL_RTC_WAKEUPTIMER_GET_FLAG(phrtc, RTC_FLAG_WUTWF) == RESET);
-
-      /**
-       * make sure to clear the flags after checking the WUTWF.
-       * It takes 2 RTCCLK between the time the WUTE bit is disabled and the
-       * time the timer is disabled. The WUTWF bit somehow guarantee the system is stable
-       * Otherwise, when the timer is periodic with 1 Tick, it may generate an extra interrupt in between
-       * due to the autoreload feature
-       */
-      __HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(phrtc, RTC_FLAG_WUTF);   /**<  Clear flag in RTC module */
-      __HAL_RTC_WAKEUPTIMER_EXTI_CLEAR_FLAG(); /**<  Clear flag in EXTI module */
-      HAL_NVIC_ClearPendingIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);   /**<  Clear pending bit in NVIC */
-    }
-    else if(PreviousRunningTimerID != localcurrentrunningtimerid)
-    {
-      RescheduleTimerList();
-    }
-  }
-
-  /* Enable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_ENABLE( phrtc );
-
-  HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**<  Enable NVIC */
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-
-  return;
-}
-
-void HW_TS_Start(uint8_t timer_id, uint32_t timeout_ticks)
-{
-  uint16_t time_elapsed;
-  uint8_t localcurrentrunningtimerid;
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  uint32_t primask_bit;
-#endif
-
-  if(aTimerContext[timer_id].TimerIDStatus == TimerID_Running)
-  {
-    HW_TS_Stop( timer_id );
-  }
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  primask_bit = __get_PRIMASK();  /**< backup PRIMASK bit */
-  __disable_irq();          /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
-#endif
-
-  HAL_NVIC_DisableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID);    /**<  Disable NVIC */
-
-  /* Disable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_DISABLE( phrtc );
-
-  aTimerContext[timer_id].TimerIDStatus = TimerID_Running;
-
-  aTimerContext[timer_id].CountLeft = timeout_ticks;
-  aTimerContext[timer_id].CounterInit = timeout_ticks;
-
-  time_elapsed =  linkTimer(timer_id);
-
-  localcurrentrunningtimerid = CurrentRunningTimerID;
-
-  if(PreviousRunningTimerID != localcurrentrunningtimerid)
-  {
-    RescheduleTimerList();
-  }
-  else
-  {
-    aTimerContext[timer_id].CountLeft -= time_elapsed;
-  }
-
-  /* Enable the write protection for RTC registers */
-  __HAL_RTC_WRITEPROTECTION_ENABLE( phrtc );
-
-  HAL_NVIC_EnableIRQ(CFG_HW_TS_RTC_WAKEUP_HANDLER_ID); /**<  Enable NVIC */
-
-#if (CFG_HW_TS_USE_PRIMASK_AS_CRITICAL_SECTION == 1)
-  __set_PRIMASK(primask_bit); /**< Restore PRIMASK bit*/
-#endif
-
-  return;
-}
-
-uint16_t HW_TS_RTC_ReadLeftTicksToCount(void)
-{
-  uint32_t primask_bit;
-  uint16_t return_value, auro_reload_value, elapsed_time_value;
-
-  primask_bit = __get_PRIMASK();  /**< backup PRIMASK bit */
-  __disable_irq();                /**< Disable all interrupts by setting PRIMASK bit on Cortex*/
-
-  if((READ_BIT(RTC->CR, RTC_CR_WUTE) == (RTC_CR_WUTE)) == SET)
-  {
-    auro_reload_value = (uint32_t)(READ_BIT(RTC->WUTR, RTC_WUTR_WUT));
-
-    elapsed_time_value = ReturnTimeElapsed();
-
-    if(auro_reload_value > elapsed_time_value)
-    {
-      return_value = auro_reload_value - elapsed_time_value;
-    }
-    else
-    {
-      return_value = 0;
-    }
-  }
-  else
-  {
-    return_value = TIMER_LIST_EMPTY;
-  }
-
-  __set_PRIMASK(primask_bit);     /**< Restore PRIMASK bit*/
-
-  return (return_value);
-}
-
-__weak void HW_TS_RTC_Int_AppNot(uint32_t TimerProcessID, uint8_t TimerID, HW_TS_pTimerCb_t pTimerCallBack)
-{
-  pTimerCallBack();
-
-  return;
-}
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 0 - 8
firmware/targets/f7/furi-hal/furi-hal-bootloader.c

@@ -23,11 +23,3 @@ void furi_hal_bootloader_set_mode(FuriHalBootloaderMode mode) {
         LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_DFU);
         LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_DFU);
     }
     }
 }
 }
-
-void furi_hal_bootloader_set_flags(FuriHalBootloaderFlag flags) {
-    LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR2, flags);
-}
-
-FuriHalBootloaderFlag furi_hal_bootloader_get_flags() {
-    return LL_RTC_BAK_GetRegister(RTC, LL_RTC_BKP_DR2);
-}

+ 0 - 9
firmware/targets/f7/furi-hal/furi-hal-clock.c

@@ -77,14 +77,6 @@ void furi_hal_clock_init() {
         Error_Handler();
         Error_Handler();
     }
     }
 
 
-    if(LL_RCC_GetRTCClockSource() != LL_RCC_RTC_CLKSOURCE_LSE) {
-        LL_RCC_ForceBackupDomainReset();
-        LL_RCC_ReleaseBackupDomainReset();
-        LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
-    }
-
-    LL_RCC_EnableRTC();
-
     LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
     LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
     LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1);
     LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1);
     LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLLSAI1);
     LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_PLLSAI1);
@@ -118,7 +110,6 @@ void furi_hal_clock_init() {
     LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_AES2);
     LL_AHB3_GRP1_EnableClock(LL_AHB3_GRP1_PERIPH_AES2);
 
 
     // APB1
     // APB1
-    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
     LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
     LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2);
     LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1);
     LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1);
 
 

+ 0 - 3
firmware/targets/f7/furi-hal/furi-hal-interrupt.c

@@ -158,7 +158,6 @@ void DMA2_Channel8_IRQHandler(void) {
     if (furi_hal_dma_channel_isr[1][7]) furi_hal_dma_channel_isr[1][7]();
     if (furi_hal_dma_channel_isr[1][7]) furi_hal_dma_channel_isr[1][7]();
 }
 }
 
 
-
 void TAMP_STAMP_LSECSS_IRQHandler(void) {
 void TAMP_STAMP_LSECSS_IRQHandler(void) {
     if (LL_RCC_IsActiveFlag_LSECSS()) {
     if (LL_RCC_IsActiveFlag_LSECSS()) {
         LL_RCC_ClearFlag_LSECSS();
         LL_RCC_ClearFlag_LSECSS();
@@ -174,7 +173,6 @@ void TAMP_STAMP_LSECSS_IRQHandler(void) {
 void RCC_IRQHandler(void) {
 void RCC_IRQHandler(void) {
 }
 }
 
 
-
 void NMI_Handler(void) {
 void NMI_Handler(void) {
     if (LL_RCC_IsActiveFlag_HSECSS()) {
     if (LL_RCC_IsActiveFlag_HSECSS()) {
         LL_RCC_ClearFlag_HSECSS();
         LL_RCC_ClearFlag_HSECSS();
@@ -206,5 +204,4 @@ void UsageFault_Handler(void) {
 }
 }
 
 
 void DebugMon_Handler(void) {
 void DebugMon_Handler(void) {
-
 }
 }

+ 122 - 0
firmware/targets/f7/furi-hal/furi-hal-rtc.c

@@ -0,0 +1,122 @@
+#include <furi-hal-rtc.h>
+#include <stm32wbxx_ll_rcc.h>
+#include <stm32wbxx_ll_rtc.h>
+
+#include <furi.h>
+
+#define TAG "FuriHalRtc"
+
+#define FURI_HAL_RTC_BOOT_FLAGS_REG LL_RTC_BKP_DR0
+#define FURI_HAL_RTC_BOOT_VERSION_REG LL_RTC_BKP_DR1
+#define FURI_HAL_RTC_SYSTEM_REG LL_RTC_BKP_DR2
+
+typedef struct {
+    uint8_t log_level:4;
+    uint8_t log_reserved:4;
+    uint8_t flags;
+    uint16_t reserved;
+} DeveloperReg;
+
+void furi_hal_rtc_init() {
+    if(LL_RCC_GetRTCClockSource() != LL_RCC_RTC_CLKSOURCE_LSE) {
+        LL_RCC_ForceBackupDomainReset();
+        LL_RCC_ReleaseBackupDomainReset();
+        LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
+    }
+
+    LL_RCC_EnableRTC();
+    LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_RTCAPB);
+
+    LL_RTC_InitTypeDef RTC_InitStruct = {0};
+    RTC_InitStruct.HourFormat = LL_RTC_HOURFORMAT_24HOUR;
+    RTC_InitStruct.AsynchPrescaler = 127;
+    RTC_InitStruct.SynchPrescaler = 255;
+    LL_RTC_Init(RTC, &RTC_InitStruct);
+
+    furi_log_set_level(furi_hal_rtc_get_log_level());
+
+    FURI_LOG_I(TAG, "Init OK");
+}
+
+void furi_hal_rtc_set_log_level(uint8_t level) {
+    uint32_t data = LL_RTC_BAK_GetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG);
+    ((DeveloperReg*)&data)->log_level = level;
+    LL_RTC_BAK_SetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG, data);
+    furi_log_set_level(level);
+}
+
+uint8_t furi_hal_rtc_get_log_level() {
+    uint32_t data = LL_RTC_BAK_GetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG);
+    return ((DeveloperReg*)&data)->log_level;
+}
+
+void furi_hal_rtc_set_flag(FuriHalRtcFlag flag) {
+    uint32_t data = LL_RTC_BAK_GetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG);
+    ((DeveloperReg*)&data)->flags |= flag;
+    LL_RTC_BAK_SetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG, data);
+}
+
+void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag) {
+    uint32_t data = LL_RTC_BAK_GetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG);
+    ((DeveloperReg*)&data)->flags &= ~flag;
+    LL_RTC_BAK_SetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG, data);
+}
+
+bool furi_hal_rtc_is_flag_set(FuriHalRtcFlag flag) {
+    uint32_t data = LL_RTC_BAK_GetRegister(RTC, FURI_HAL_RTC_SYSTEM_REG);
+    return ((DeveloperReg*)&data)->flags & flag;
+}
+
+void furi_hal_rtc_set_datetime(FuriHalRtcDateTime* datetime) {
+    furi_assert(datetime);
+
+    /* Disable write protection */
+    LL_RTC_DisableWriteProtection(RTC);
+
+    /* Enter Initialization mode and wait for INIT flag to be set */
+    LL_RTC_EnableInitMode(RTC);
+    while(!LL_RTC_IsActiveFlag_INIT(RTC)) {}
+
+    /* Set time */
+    LL_RTC_TIME_Config(RTC,
+        LL_RTC_TIME_FORMAT_AM_OR_24,
+        __LL_RTC_CONVERT_BIN2BCD(datetime->hour),
+        __LL_RTC_CONVERT_BIN2BCD(datetime->minute),
+        __LL_RTC_CONVERT_BIN2BCD(datetime->second)
+    );
+
+    /* Set date */
+    LL_RTC_DATE_Config(RTC,
+        datetime->weekday,
+        __LL_RTC_CONVERT_BIN2BCD(datetime->day),
+        __LL_RTC_CONVERT_BIN2BCD(datetime->month),
+        __LL_RTC_CONVERT_BIN2BCD(datetime->year - 2000)
+    );
+
+    /* Exit Initialization mode */
+    LL_RTC_DisableInitMode(RTC);
+
+    /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */
+    if (!LL_RTC_IsShadowRegBypassEnabled(RTC)) {
+        LL_RTC_ClearFlag_RS(RTC);
+        while(!LL_RTC_IsActiveFlag_RS(RTC)) {};
+    }
+
+    /* Enable write protection */
+    LL_RTC_EnableWriteProtection(RTC);
+}
+
+void furi_hal_rtc_get_datetime(FuriHalRtcDateTime* datetime) {
+    furi_assert(datetime);
+
+    uint32_t time = LL_RTC_TIME_Get(RTC); // 0x00HHMMSS
+    uint32_t date = LL_RTC_DATE_Get(RTC); // 0xWWDDMMYY
+
+    datetime->second = __LL_RTC_CONVERT_BCD2BIN((time>>0) & 0xFF);
+    datetime->minute = __LL_RTC_CONVERT_BCD2BIN((time>>8) & 0xFF);
+    datetime->hour = __LL_RTC_CONVERT_BCD2BIN((time>>16) & 0xFF);
+    datetime->year = __LL_RTC_CONVERT_BCD2BIN((date >> 0) & 0xFF) + 2000;
+    datetime->month = __LL_RTC_CONVERT_BCD2BIN((date >> 8) & 0xFF);
+    datetime->day = __LL_RTC_CONVERT_BCD2BIN((date >> 16) & 0xFF);
+    datetime->weekday = __LL_RTC_CONVERT_BCD2BIN((date >> 24) & 0xFF);
+}

+ 4 - 6
firmware/targets/f7/furi-hal/furi-hal.c

@@ -1,7 +1,6 @@
 #include <furi-hal.h>
 #include <furi-hal.h>
 
 
 #include <comp.h>
 #include <comp.h>
-#include <rtc.h>
 #include <tim.h>
 #include <tim.h>
 #include <gpio.h>
 #include <gpio.h>
 
 
@@ -13,18 +12,14 @@
 
 
 void furi_hal_init() {
 void furi_hal_init() {
     furi_hal_clock_init();
     furi_hal_clock_init();
+    furi_hal_rtc_init();
     furi_hal_console_init();
     furi_hal_console_init();
     furi_hal_interrupt_init();
     furi_hal_interrupt_init();
     furi_hal_delay_init();
     furi_hal_delay_init();
 
 
-    // FreeRTOS glue
-    furi_hal_os_init();
-
     MX_GPIO_Init();
     MX_GPIO_Init();
     FURI_LOG_I(TAG, "GPIO OK");
     FURI_LOG_I(TAG, "GPIO OK");
 
 
-    MX_RTC_Init();
-    FURI_LOG_I(TAG, "RTC OK");
     furi_hal_bootloader_init();
     furi_hal_bootloader_init();
     furi_hal_version_init();
     furi_hal_version_init();
 
 
@@ -59,6 +54,9 @@ void furi_hal_init() {
     furi_hal_bt_init();
     furi_hal_bt_init();
     furi_hal_compress_icon_init();
     furi_hal_compress_icon_init();
 
 
+    // FreeRTOS glue
+    furi_hal_os_init();
+
     // FatFS driver initialization
     // FatFS driver initialization
     MX_FATFS_Init();
     MX_FATFS_Init();
     FURI_LOG_I(TAG, "FATFS OK");
     FURI_LOG_I(TAG, "FATFS OK");

+ 1 - 1
firmware/targets/f7/target.mk

@@ -57,7 +57,6 @@ C_SOURCES += \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr_ex.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr_ex.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rcc.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rcc.c \
-	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rtc.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rtc_ex.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rtc_ex.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_tim.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_tim.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_tim_ex.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_tim_ex.c \
@@ -67,6 +66,7 @@ C_SOURCES += \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_i2c.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_i2c.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_lptim.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_lptim.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_rcc.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_rcc.c \
+	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_rtc.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_spi.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_spi.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_tim.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_tim.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_usart.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_usart.c \

+ 0 - 18
firmware/targets/furi-hal-include/furi-hal-bootloader.h

@@ -17,12 +17,6 @@ typedef enum {
     FuriHalBootloaderModeDFU
     FuriHalBootloaderModeDFU
 } FuriHalBootloaderMode;
 } FuriHalBootloaderMode;
 
 
-/** Boot flags */
-typedef enum {
-    FuriHalBootloaderFlagDefault=0,
-    FuriHalBootloaderFlagFactoryReset=1,
-} FuriHalBootloaderFlag;
-
 /** Initialize boot subsystem
 /** Initialize boot subsystem
  */
  */
 void furi_hal_bootloader_init();
 void furi_hal_bootloader_init();
@@ -33,18 +27,6 @@ void furi_hal_bootloader_init();
  */
  */
 void furi_hal_bootloader_set_mode(FuriHalBootloaderMode mode);
 void furi_hal_bootloader_set_mode(FuriHalBootloaderMode mode);
 
 
-/** Set bootloader flags
- *
- * @param[in]  flags  FuriHalBootloaderFlag
- */
-void furi_hal_bootloader_set_flags(FuriHalBootloaderFlag flags);
-
-/** Get boot flag
- *
- * @return     FuriHalBootloaderFlag
- */
-FuriHalBootloaderFlag furi_hal_bootloader_get_flags();
-
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 52 - 0
firmware/targets/furi-hal-include/furi-hal-rtc.h

@@ -0,0 +1,52 @@
+/**
+ * @file furi-hal-rtc.h
+ * Furi Hal RTC API
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <main.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    // Time
+    uint8_t hour;   /**< Hour in 24H format: 0-23 */
+    uint8_t minute; /**< Minute: 0-59 */
+    uint8_t second; /**< Second: 0-59 */
+    // Date
+    uint8_t day;    /**< Current day: 1-31 */
+    uint8_t month;  /**< Current month: 1-12 */
+    uint16_t year;  /**< Current year: 2000-2099 */
+    uint8_t weekday;/**< Current weekday: 1-7 */
+} FuriHalRtcDateTime;
+
+typedef enum {
+    FuriHalRtcFlagDebug = (1<<0),
+    FuriHalRtcFlagFactoryReset = (1<<1),
+} FuriHalRtcFlag;
+
+/** Initialize RTC subsystem */
+void furi_hal_rtc_init();
+
+void furi_hal_rtc_set_log_level(uint8_t level);
+
+uint8_t furi_hal_rtc_get_log_level();
+
+void furi_hal_rtc_set_flag(FuriHalRtcFlag flag);
+
+void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag);
+
+bool furi_hal_rtc_is_flag_set(FuriHalRtcFlag flag);
+
+void furi_hal_rtc_set_datetime(FuriHalRtcDateTime* datetime);
+
+void furi_hal_rtc_get_datetime(FuriHalRtcDateTime* datetime);
+
+#ifdef __cplusplus
+}
+#endif

+ 1 - 0
firmware/targets/furi-hal-include/furi-hal.h

@@ -17,6 +17,7 @@ template <unsigned int N> struct STOP_EXTERNING_ME {};
 #include "furi-hal-sd.h"
 #include "furi-hal-sd.h"
 #include "furi-hal-i2c.h"
 #include "furi-hal-i2c.h"
 #include "furi-hal-resources.h"
 #include "furi-hal-resources.h"
+#include "furi-hal-rtc.h"
 #include "furi-hal-gpio.h"
 #include "furi-hal-gpio.h"
 #include "furi-hal-light.h"
 #include "furi-hal-light.h"
 #include "furi-hal-delay.h"
 #include "furi-hal-delay.h"

+ 2 - 2
lib/lfs_config.h

@@ -8,9 +8,9 @@
 
 
 #define LFS_TAG "Lfs"
 #define LFS_TAG "Lfs"
 
 
-#define LFS_TRACE(...) FURI_LOG_D(LFS_TAG, __VA_ARGS__);
+#define LFS_TRACE(...) FURI_LOG_T(LFS_TAG, __VA_ARGS__);
 
 
-#define LFS_DEBUG(...) FURI_LOG_I(LFS_TAG, __VA_ARGS__);
+#define LFS_DEBUG(...) FURI_LOG_D(LFS_TAG, __VA_ARGS__);
 
 
 #define LFS_WARN(...) FURI_LOG_W(LFS_TAG, __VA_ARGS__);
 #define LFS_WARN(...) FURI_LOG_W(LFS_TAG, __VA_ARGS__);