فهرست منبع

[FL-667] Power saving: deep sleep in tickless state (#300)

* SYSTEM: tickless mode with deep sleep.
* Move FreeRTOS ticks to lptim2.
* API: move all sumbodules init routines to one place.
* Timebase: working lptim2 at tick source.
* API Timebase: lp-timer routines, timer access safe zones prediction and synchronization. 
* FreeRTOS: adjust configuration for tickless mode.
* NFC: support for tickless mode.
* API Timebase: improve tick error handling in IRQ. 
* Apploader: use insomnia mode to run applications.
* BLE: prevent sleep while core2 starting.
* HAL: nap while in insomnia mode.

Co-authored-by: coreglitch <mail@s3f.ru>
あく 5 سال پیش
والد
کامیت
c8aca9ef48
44فایلهای تغییر یافته به همراه395 افزوده شده و 200 حذف شده
  1. 3 0
      applications/app-loader/app-loader.c
  2. 1 1
      applications/gui/gui_event.c
  3. 4 0
      applications/nfc/nfc_worker.c
  4. 3 0
      firmware/targets/api-hal-include/api-hal.h
  5. 7 3
      firmware/targets/f4/Inc/FreeRTOSConfig.h
  6. 1 1
      firmware/targets/f4/Inc/adc.h
  7. 1 1
      firmware/targets/f4/Inc/aes.h
  8. 1 1
      firmware/targets/f4/Inc/comp.h
  9. 1 1
      firmware/targets/f4/Inc/crc.h
  10. 1 1
      firmware/targets/f4/Inc/gpio.h
  11. 1 1
      firmware/targets/f4/Inc/i2c.h
  12. 1 1
      firmware/targets/f4/Inc/pka.h
  13. 1 1
      firmware/targets/f4/Inc/rf.h
  14. 1 1
      firmware/targets/f4/Inc/rng.h
  15. 1 1
      firmware/targets/f4/Inc/rtc.h
  16. 1 1
      firmware/targets/f4/Inc/spi.h
  17. 1 0
      firmware/targets/f4/Inc/stm32wbxx_it.h
  18. 1 1
      firmware/targets/f4/Inc/tim.h
  19. 1 1
      firmware/targets/f4/Inc/usart.h
  20. 1 1
      firmware/targets/f4/Src/adc.c
  21. 1 1
      firmware/targets/f4/Src/aes.c
  22. 13 22
      firmware/targets/f4/Src/app_freertos.c
  23. 1 1
      firmware/targets/f4/Src/comp.c
  24. 1 1
      firmware/targets/f4/Src/crc.c
  25. 1 1
      firmware/targets/f4/Src/gpio.c
  26. 1 1
      firmware/targets/f4/Src/i2c.c
  27. 1 23
      firmware/targets/f4/Src/main.c
  28. 1 1
      firmware/targets/f4/Src/pka.c
  29. 1 1
      firmware/targets/f4/Src/rf.c
  30. 1 1
      firmware/targets/f4/Src/rng.c
  31. 1 1
      firmware/targets/f4/Src/rtc.c
  32. 1 1
      firmware/targets/f4/Src/spi.c
  33. 0 111
      firmware/targets/f4/Src/stm32wbxx_hal_timebase_tim.c
  34. 15 3
      firmware/targets/f4/Src/stm32wbxx_it.c
  35. 1 1
      firmware/targets/f4/Src/tim.c
  36. 1 1
      firmware/targets/f4/Src/usart.c
  37. 95 0
      firmware/targets/f4/api-hal/api-hal-timebase-timer.h
  38. 174 0
      firmware/targets/f4/api-hal/api-hal-timebase.c
  39. 27 0
      firmware/targets/f4/api-hal/api-hal-timebase.h
  40. 7 0
      firmware/targets/f4/api-hal/api-hal.c
  41. 3 0
      firmware/targets/f4/ble-glue/app_entry.c
  42. 13 10
      firmware/targets/f4/f4.ioc
  43. 1 1
      firmware/targets/f4/stm32wb55xx_flash_cm4.ld
  44. 1 0
      firmware/targets/f4/target.mk

+ 3 - 0
applications/app-loader/app-loader.c

@@ -5,6 +5,7 @@
 #include "menu/menu_item.h"
 #include "applications.h"
 #include <assets_icons.h>
+#include <api-hal.h>
 
 typedef struct {
     FuriApp* handler;
@@ -37,6 +38,7 @@ static void input_callback(InputEvent* input_event, void* _ctx) {
     if(input_event->state && input_event->input == InputBack) {
         furiac_kill(ctx->handler);
         widget_enabled_set(ctx->widget, false);
+        api_hal_timebase_insomnia_exit();
     }
 }
 
@@ -49,6 +51,7 @@ static void handle_menu(void* _ctx) {
 
     // TODO how to call this?
     // furiac_wait_libs(&FLIPPER_STARTUP[i].libs);
+    api_hal_timebase_insomnia_enter();
 
     ctx->state->current_app = ctx->app;
     ctx->state->handler = furiac_start(ctx->app->app, ctx->app->name, NULL);

+ 1 - 1
applications/gui/gui_event.c

@@ -42,7 +42,7 @@ GuiEvent* gui_event_alloc() {
 
     gui_event->timer = osTimerNew(gui_event_timer_callback, osTimerPeriodic, gui_event, NULL);
     assert(gui_event->timer);
-    osTimerStart(gui_event->timer, 1000 / 10);
+    // osTimerStart(gui_event->timer, 1024 / 4);
 
     // Input
     gui_event->input_event_record = furi_open("input_events");

+ 4 - 0
applications/nfc/nfc_worker.c

@@ -1,4 +1,5 @@
 #include "nfc_worker_i.h"
+#include <api-hal.h>
 
 NfcWorker* nfc_worker_alloc(osMessageQueueId_t message_queue) {
     NfcWorker* nfc_worker = furi_alloc(sizeof(NfcWorker));
@@ -54,6 +55,8 @@ void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state) {
 void nfc_worker_task(void* context) {
     NfcWorker* nfc_worker = context;
 
+    api_hal_timebase_insomnia_enter();
+
     rfalLowPowerModeStop();
     if(nfc_worker->state == NfcWorkerStatePoll) {
         nfc_worker_poll(nfc_worker);
@@ -66,6 +69,7 @@ void nfc_worker_task(void* context) {
 
     nfc_worker_change_state(nfc_worker, NfcWorkerStateReady);
 
+    api_hal_timebase_insomnia_exit();
     osThreadExit();
 }
 

+ 3 - 0
firmware/targets/api-hal-include/api-hal.h

@@ -4,6 +4,7 @@
 template <unsigned int N> struct STOP_EXTERNING_ME {};
 #endif
 
+#include "api-hal-timebase.h"
 #include "api-hal-boot.h"
 #include "api-hal-gpio.h"
 #include "api-hal-delay.h"
@@ -16,3 +17,5 @@ template <unsigned int N> struct STOP_EXTERNING_ME {};
 #include "api-hal-bt.h"
 #include "api-hal-spi.h"
 #include "api-hal-flash.h"
+
+void api_hal_init();

+ 7 - 3
firmware/targets/f4/Inc/FreeRTOSConfig.h

@@ -51,6 +51,7 @@
 #if defined(__ICCARM__) || defined(__CC_ARM) || defined(__GNUC__)
   #include <stdint.h>
   extern uint32_t SystemCoreClock;
+  void xPortSysTickHandler(void);
 /* USER CODE BEGIN 0 */
   extern void configureTimerForRunTimeStats(void);
   extern unsigned long getRunTimeCounterValue(void);
@@ -65,7 +66,7 @@
 #define configUSE_IDLE_HOOK                      1
 #define configUSE_TICK_HOOK                      0
 #define configCPU_CLOCK_HZ                       ( SystemCoreClock )
-#define configTICK_RATE_HZ                       ((TickType_t)1000)
+#define configTICK_RATE_HZ                       ((TickType_t)1024)
 #define configMAX_PRIORITIES                     ( 56 )
 #define configMINIMAL_STACK_SIZE                 ((uint16_t)128)
 #define configTOTAL_HEAP_SIZE                    ((size_t)40960)
@@ -78,13 +79,16 @@
 #define configCHECK_FOR_STACK_OVERFLOW           1
 #define configUSE_RECURSIVE_MUTEXES              1
 #define configUSE_COUNTING_SEMAPHORES            1
+#define configENABLE_BACKWARD_COMPATIBILITY      0
 #define configUSE_PORT_OPTIMISED_TASK_SELECTION  0
+#define configUSE_TICKLESS_IDLE                  2
 #define configRECORD_STACK_HIGH_ADDRESS          1
 /* USER CODE BEGIN MESSAGE_BUFFER_LENGTH_TYPE */
 /* Defaults to size_t for backward compatibility, but can be changed
    if lengths will always be less than the number of bytes in a size_t. */
 #define configMESSAGE_BUFFER_LENGTH_TYPE         size_t
 #define configNUM_THREAD_LOCAL_STORAGE_POINTERS 1
+#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP   8
 /* USER CODE END MESSAGE_BUFFER_LENGTH_TYPE */
 
 /* Co-routine definitions. */
@@ -102,7 +106,7 @@ to exclude the API function. */
 #define INCLUDE_vTaskPrioritySet             1
 #define INCLUDE_uxTaskPriorityGet            1
 #define INCLUDE_vTaskDelete                  1
-#define INCLUDE_vTaskCleanUpResources        0
+#define INCLUDE_vTaskCleanUpResources        1
 #define INCLUDE_vTaskSuspend                 1
 #define INCLUDE_vTaskDelayUntil              1
 #define INCLUDE_vTaskDelay                   1
@@ -157,7 +161,7 @@ standard names. */
 /* IMPORTANT: This define is commented when used with STM32Cube firmware, when the timebase source is SysTick,
               to prevent overwriting SysTick_Handler defined within STM32Cube HAL */
 
-#define xPortSysTickHandler SysTick_Handler
+/* #define xPortSysTickHandler SysTick_Handler */
 
 /* USER CODE BEGIN 2 */
 /* Definitions needed when configGENERATE_RUN_TIME_STATS is on */

+ 1 - 1
firmware/targets/f4/Inc/adc.h

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Inc/aes.h

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Inc/comp.h

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Inc/crc.h

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Inc/gpio.h

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Inc/i2c.h

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Inc/pka.h

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Inc/rf.h

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Inc/rng.h

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Inc/rtc.h

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Inc/spi.h

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 0
firmware/targets/f4/Inc/stm32wbxx_it.h

@@ -53,6 +53,7 @@ void MemManage_Handler(void);
 void BusFault_Handler(void);
 void UsageFault_Handler(void);
 void DebugMon_Handler(void);
+void SysTick_Handler(void);
 void TAMP_STAMP_LSECSS_IRQHandler(void);
 void RCC_IRQHandler(void);
 void EXTI1_IRQHandler(void);

+ 1 - 1
firmware/targets/f4/Inc/tim.h

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Inc/usart.h

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Src/adc.c

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Src/aes.c

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 13 - 22
firmware/targets/f4/Src/app_freertos.c

@@ -26,7 +26,6 @@
 
 /* Private includes ----------------------------------------------------------*/
 /* USER CODE BEGIN Includes */
-
 /* USER CODE END Includes */
 
 /* Private typedef -----------------------------------------------------------*/
@@ -48,18 +47,11 @@
 /* USER CODE BEGIN Variables */
 
 /* USER CODE END Variables */
-/* Definitions for defaultTask */
-osThreadId_t defaultTaskHandle;
-const osThreadAttr_t defaultTask_attributes = {
-  .name = "defaultTask",
-  .priority = (osPriority_t) osPriorityNormal,
-  .stack_size = 1024 * 4
-};
 /* Definitions for app_main */
 osThreadId_t app_mainHandle;
 const osThreadAttr_t app_main_attributes = {
   .name = "app_main",
-  .priority = (osPriority_t) osPriorityLow,
+  .priority = (osPriority_t) osPriorityNormal,
   .stack_size = 1024 * 4
 };
 
@@ -68,8 +60,7 @@ const osThreadAttr_t app_main_attributes = {
 
 /* USER CODE END FunctionPrototypes */
 
-void StartDefaultTask(void *argument);
-extern void app(void *argument);
+void app(void *argument);
 
 void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
 
@@ -77,7 +68,7 @@ void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */
 void configureTimerForRunTimeStats(void);
 unsigned long getRunTimeCounterValue(void);
 void vApplicationIdleHook(void);
-void vApplicationStackOverflowHook(xTaskHandle xTask, signed char *pcTaskName);
+void vApplicationStackOverflowHook(TaskHandle_t xTask, signed char *pcTaskName);
 
 /* USER CODE BEGIN 1 */
 /* Functions needed when configGENERATE_RUN_TIME_STATS is on */
@@ -108,7 +99,7 @@ __weak void vApplicationIdleHook( void )
 /* USER CODE END 2 */
 
 /* USER CODE BEGIN 4 */
-__weak void vApplicationStackOverflowHook(xTaskHandle xTask, signed char *pcTaskName)
+__weak void vApplicationStackOverflowHook(TaskHandle_t xTask, signed char *pcTaskName)
 {
    /* Run time stack overflow checking is performed if
    configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook function is
@@ -116,6 +107,9 @@ __weak void vApplicationStackOverflowHook(xTaskHandle xTask, signed char *pcTask
 }
 /* USER CODE END 4 */
 
+/* USER CODE BEGIN VPORT_SUPPORT_TICKS_AND_SLEEP */
+/* USER CODE END VPORT_SUPPORT_TICKS_AND_SLEEP */
+
 /**
   * @brief  FreeRTOS initialization
   * @param  None
@@ -143,9 +137,6 @@ void MX_FREERTOS_Init(void) {
   /* USER CODE END RTOS_QUEUES */
 
   /* Create the thread(s) */
-  /* creation of defaultTask */
-  defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);
-
   /* creation of app_main */
   app_mainHandle = osThreadNew(app, NULL, &app_main_attributes);
 
@@ -159,22 +150,22 @@ void MX_FREERTOS_Init(void) {
 
 }
 
-/* USER CODE BEGIN Header_StartDefaultTask */
+/* USER CODE BEGIN Header_app */
 /**
-  * @brief  Function implementing the defaultTask thread.
+  * @brief  Function implementing the app_main thread.
   * @param  argument: Not used
   * @retval None
   */
-/* USER CODE END Header_StartDefaultTask */
-void StartDefaultTask(void *argument)
+/* USER CODE END Header_app */
+__weak void app(void *argument)
 {
-  /* USER CODE BEGIN StartDefaultTask */
+  /* USER CODE BEGIN app */
   /* Infinite loop */
   for(;;)
   {
     osDelay(1);
   }
-  /* USER CODE END StartDefaultTask */
+  /* USER CODE END app */
 }
 
 /* Private application code --------------------------------------------------*/

+ 1 - 1
firmware/targets/f4/Src/comp.c

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Src/crc.c

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Src/gpio.c

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Src/i2c.c

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 23
firmware/targets/f4/Src/main.c

@@ -118,10 +118,9 @@ int main(void)
   MX_AES2_Init();
   MX_CRC_Init();
   /* USER CODE BEGIN 2 */
+  api_hal_init();
   MX_FATFS_Init();
   delay_us_init_DWT();
-  api_hal_vcp_init();
-  api_hal_spi_init();
   // Errata 2.2.9, Flash OPTVERR flag is always set after system reset
   __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
   /* USER CODE END 2 */
@@ -236,27 +235,6 @@ void SystemClock_Config(void)
 
 /* USER CODE END 4 */
 
- /**
-  * @brief  Period elapsed callback in non blocking mode
-  * @note   This function is called  when TIM17 interrupt took place, inside
-  * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
-  * a global variable "uwTick" used as application time base.
-  * @param  htim : TIM handle
-  * @retval None
-  */
-void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
-{
-  /* USER CODE BEGIN Callback 0 */
-
-  /* USER CODE END Callback 0 */
-  if (htim->Instance == TIM17) {
-    HAL_IncTick();
-  }
-  /* USER CODE BEGIN Callback 1 */
-
-  /* USER CODE END Callback 1 */
-}
-
 /**
   * @brief  This function is executed in case of error occurrence.
   * @retval None

+ 1 - 1
firmware/targets/f4/Src/pka.c

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Src/rf.c

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Src/rng.c

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Src/rtc.c

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Src/spi.c

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 0 - 111
firmware/targets/f4/Src/stm32wbxx_hal_timebase_tim.c

@@ -1,111 +0,0 @@
-/* USER CODE BEGIN Header */
-/**
-  ******************************************************************************
-  * @file    stm32wbxx_hal_timebase_TIM.c
-  * @brief   HAL time base based on the hardware TIM.
-  ******************************************************************************
-  * @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
-  *
-  ******************************************************************************
-  */
-/* USER CODE END Header */
-
-/* Includes ------------------------------------------------------------------*/
-#include "stm32wbxx_hal.h"
-#include "stm32wbxx_hal_tim.h"
-
-/* Private typedef -----------------------------------------------------------*/
-/* Private define ------------------------------------------------------------*/
-/* Private macro -------------------------------------------------------------*/
-/* Private variables ---------------------------------------------------------*/
-TIM_HandleTypeDef        htim17;
-/* Private function prototypes -----------------------------------------------*/
-/* Private functions ---------------------------------------------------------*/
-
-/**
-  * @brief  This function configures the TIM17 as a time base source.
-  *         The time source is configured  to have 1ms time base with a dedicated
-  *         Tick interrupt priority.
-  * @note   This function is called  automatically at the beginning of program after
-  *         reset by HAL_Init() or at any time when clock is configured, by HAL_RCC_ClockConfig().
-  * @param  TickPriority: Tick interrupt priority.
-  * @retval HAL status
-  */
-HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
-{
-  RCC_ClkInitTypeDef    clkconfig;
-  uint32_t              uwTimclock = 0;
-  uint32_t              uwPrescalerValue = 0;
-  uint32_t              pFLatency;
-  /*Configure the TIM17 IRQ priority */
-  HAL_NVIC_SetPriority(TIM1_TRG_COM_TIM17_IRQn, TickPriority ,0);
-
-  /* Enable the TIM17 global Interrupt */
-  HAL_NVIC_EnableIRQ(TIM1_TRG_COM_TIM17_IRQn);
-  /* Enable TIM17 clock */
-  __HAL_RCC_TIM17_CLK_ENABLE();
-
-  /* Get clock configuration */
-  HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
-
-  /* Compute TIM17 clock */
-  uwTimclock = HAL_RCC_GetPCLK2Freq();
-  /* Compute the prescaler value to have TIM17 counter clock equal to 1MHz */
-  uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000U) - 1U);
-
-  /* Initialize TIM17 */
-  htim17.Instance = TIM17;
-
-  /* Initialize TIMx peripheral as follow:
-  + Period = [(TIM17CLK/1000) - 1]. to have a (1/1000) s time base.
-  + Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
-  + ClockDivision = 0
-  + Counter direction = Up
-  */
-  htim17.Init.Period = (1000000U / 1000U) - 1U;
-  htim17.Init.Prescaler = uwPrescalerValue;
-  htim17.Init.ClockDivision = 0;
-  htim17.Init.CounterMode = TIM_COUNTERMODE_UP;
-  if(HAL_TIM_Base_Init(&htim17) == HAL_OK)
-  {
-    /* Start the TIM time Base generation in interrupt mode */
-    return HAL_TIM_Base_Start_IT(&htim17);
-  }
-
-  /* Return function status */
-  return HAL_ERROR;
-}
-
-/**
-  * @brief  Suspend Tick increment.
-  * @note   Disable the tick increment by disabling TIM17 update interrupt.
-  * @param  None
-  * @retval None
-  */
-void HAL_SuspendTick(void)
-{
-  /* Disable TIM17 update Interrupt */
-  __HAL_TIM_DISABLE_IT(&htim17, TIM_IT_UPDATE);
-}
-
-/**
-  * @brief  Resume Tick increment.
-  * @note   Enable the tick increment by Enabling TIM17 update interrupt.
-  * @param  None
-  * @retval None
-  */
-void HAL_ResumeTick(void)
-{
-  /* Enable TIM17 Update interrupt */
-  __HAL_TIM_ENABLE_IT(&htim17, TIM_IT_UPDATE);
-}
-
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

+ 15 - 3
firmware/targets/f4/Src/stm32wbxx_it.c

@@ -21,6 +21,8 @@
 /* Includes ------------------------------------------------------------------*/
 #include "main.h"
 #include "stm32wbxx_it.h"
+#include "FreeRTOS.h"
+#include "task.h"
 /* Private includes ----------------------------------------------------------*/
 /* USER CODE BEGIN Includes */
 /* USER CODE END Includes */
@@ -62,8 +64,6 @@ extern COMP_HandleTypeDef hcomp1;
 extern RTC_HandleTypeDef hrtc;
 extern TIM_HandleTypeDef htim1;
 extern TIM_HandleTypeDef htim2;
-extern TIM_HandleTypeDef htim17;
-
 /* USER CODE BEGIN EV */
 
 /* USER CODE END EV */
@@ -160,6 +160,19 @@ void DebugMon_Handler(void)
   /* USER CODE END DebugMonitor_IRQn 1 */
 }
 
+/**
+  * @brief This function handles System tick timer.
+  */
+void SysTick_Handler(void)
+{
+  /* USER CODE BEGIN SysTick_IRQn 0 */
+
+  /* USER CODE END SysTick_IRQn 0 */
+  /* USER CODE BEGIN SysTick_IRQn 1 */
+  HAL_IncTick();
+  /* USER CODE END SysTick_IRQn 1 */
+}
+
 /******************************************************************************/
 /* STM32WBxx Peripheral Interrupt Handlers                                    */
 /* Add here the Interrupt Handlers for the used peripherals.                  */
@@ -288,7 +301,6 @@ void TIM1_TRG_COM_TIM17_IRQHandler(void)
 
   /* USER CODE END TIM1_TRG_COM_TIM17_IRQn 0 */
   HAL_TIM_IRQHandler(&htim1);
-  HAL_TIM_IRQHandler(&htim17);
   /* USER CODE BEGIN TIM1_TRG_COM_TIM17_IRQn 1 */
 
   /* USER CODE END TIM1_TRG_COM_TIM17_IRQn 1 */

+ 1 - 1
firmware/targets/f4/Src/tim.c

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 1 - 1
firmware/targets/f4/Src/usart.c

@@ -6,7 +6,7 @@
   ******************************************************************************
   * @attention
   *
-  * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
+  * <h2><center>&copy; Copyright (c) 2021 STMicroelectronics.
   * All rights reserved.</center></h2>
   *
   * This software component is licensed by ST under Ultimate Liberty license

+ 95 - 0
firmware/targets/f4/api-hal/api-hal-timebase-timer.h

@@ -0,0 +1,95 @@
+#pragma once
+
+#include <stm32wbxx_ll_lptim.h>
+#include <stdbool.h>
+
+static inline void assert(bool value) {
+    if (!value) asm("bkpt 1");
+}
+
+// Timer used for system ticks
+#define API_HAL_TIMEBASE_TIMER_MAX  0xFFFF
+#define API_HAL_TIMEBASE_TIMER_REG_LOAD_DLY 0x1
+#define API_HAL_TIMEBASE_TIMER       LPTIM2
+#define API_HAL_TIMEBASE_TIMER_IRQ   LPTIM2_IRQn
+#define API_HAL_TIMEBASE_TIMER_CLOCK_INIT() \
+{ \
+    LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_LSE); \
+    LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPTIM2); \
+} \
+
+static inline void api_hal_timebase_timer_init() {
+    API_HAL_TIMEBASE_TIMER_CLOCK_INIT();
+
+    LL_LPTIM_Enable(API_HAL_TIMEBASE_TIMER);
+    while(!LL_LPTIM_IsEnabled(API_HAL_TIMEBASE_TIMER)) {}
+
+    LL_LPTIM_SetClockSource(API_HAL_TIMEBASE_TIMER, LL_LPTIM_CLK_SOURCE_INTERNAL);
+    LL_LPTIM_SetPrescaler(API_HAL_TIMEBASE_TIMER, LL_LPTIM_PRESCALER_DIV1);
+    LL_LPTIM_SetPolarity(API_HAL_TIMEBASE_TIMER, LL_LPTIM_OUTPUT_POLARITY_REGULAR);
+    LL_LPTIM_SetUpdateMode(API_HAL_TIMEBASE_TIMER, LL_LPTIM_UPDATE_MODE_IMMEDIATE);
+    LL_LPTIM_SetCounterMode(API_HAL_TIMEBASE_TIMER, LL_LPTIM_COUNTER_MODE_INTERNAL);
+    LL_LPTIM_TrigSw(API_HAL_TIMEBASE_TIMER);
+    LL_LPTIM_SetInput1Src(API_HAL_TIMEBASE_TIMER, LL_LPTIM_INPUT1_SRC_GPIO);
+    LL_LPTIM_SetInput2Src(API_HAL_TIMEBASE_TIMER, LL_LPTIM_INPUT2_SRC_GPIO);
+
+    NVIC_SetPriority(API_HAL_TIMEBASE_TIMER_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
+    NVIC_EnableIRQ(API_HAL_TIMEBASE_TIMER_IRQ);
+}
+
+static inline uint32_t api_hal_timebase_timer_get_cnt() {
+    uint32_t counter = LL_LPTIM_GetCounter(API_HAL_TIMEBASE_TIMER);
+    uint32_t counter_shadow = LL_LPTIM_GetCounter(API_HAL_TIMEBASE_TIMER);
+    while(counter != counter_shadow) {
+        counter = counter_shadow;
+        counter_shadow = LL_LPTIM_GetCounter(API_HAL_TIMEBASE_TIMER);
+    }
+    return counter;
+}
+
+static inline bool api_hal_timebase_timer_arr_is_ok() {
+    return LL_LPTIM_IsActiveFlag_ARROK(API_HAL_TIMEBASE_TIMER);
+}
+
+static inline uint32_t api_hal_timebase_timer_get_arr() {
+    return LL_LPTIM_GetAutoReload(API_HAL_TIMEBASE_TIMER);;
+}
+
+static inline void api_hal_timebase_timer_set_arr(uint32_t value) {
+    value &= API_HAL_TIMEBASE_TIMER_MAX;
+    if (value != api_hal_timebase_timer_get_arr()) {
+        assert(api_hal_timebase_timer_arr_is_ok());
+        LL_LPTIM_ClearFlag_ARROK(API_HAL_TIMEBASE_TIMER);
+        LL_LPTIM_SetAutoReload(API_HAL_TIMEBASE_TIMER, value);
+    }
+}
+
+static inline bool api_hal_timebase_timer_cmp_is_ok() {
+    return LL_LPTIM_IsActiveFlag_CMPOK(API_HAL_TIMEBASE_TIMER);
+}
+
+static inline uint32_t api_hal_timebase_timer_get_cmp() {
+    return LL_LPTIM_GetCompare(API_HAL_TIMEBASE_TIMER);;
+}
+
+static inline void api_hal_timebase_timer_set_cmp(uint32_t value) {
+    value &= API_HAL_TIMEBASE_TIMER_MAX;
+    if (value != api_hal_timebase_timer_get_cmp()) {
+        assert(api_hal_timebase_timer_cmp_is_ok());
+        LL_LPTIM_ClearFlag_CMPOK(API_HAL_TIMEBASE_TIMER);
+        LL_LPTIM_SetCompare(API_HAL_TIMEBASE_TIMER, value);
+    }
+}
+
+static inline bool api_hal_timebase_timer_is_safe() {
+    uint16_t cmp = api_hal_timebase_timer_get_cmp();
+    uint16_t cnt = api_hal_timebase_timer_get_cnt();
+    uint16_t margin = (cmp > cnt) ? cmp - cnt : cnt - cmp;
+    if (margin < 8) {
+        return false;
+    }
+    if (!api_hal_timebase_timer_cmp_is_ok()) {
+        return false;
+    }
+    return true;
+}

+ 174 - 0
firmware/targets/f4/api-hal/api-hal-timebase.c

@@ -0,0 +1,174 @@
+#include <api-hal-timebase.h>
+#include <api-hal-timebase-timer.h>
+
+#include <stm32wbxx_hal.h>
+#include <stm32wbxx_ll_gpio.h>
+#include <FreeRTOS.h>
+#include <cmsis_os.h>
+
+#define API_HAL_TIMEBASE_CLK_FREQUENCY 32768
+#define API_HAL_TIMEBASE_TICK_PER_SECOND 1024
+#define API_HAL_TIMEBASE_CLK_PER_TICK (API_HAL_TIMEBASE_CLK_FREQUENCY / API_HAL_TIMEBASE_TICK_PER_SECOND)
+#define API_HAL_TIMEBASE_TICK_PER_EPOCH (API_HAL_TIMEBASE_TIMER_MAX / API_HAL_TIMEBASE_CLK_PER_TICK)
+#define API_HAL_TIMEBASE_MAX_SLEEP (API_HAL_TIMEBASE_TICK_PER_EPOCH - 1)
+
+typedef struct {
+    // Sleep control
+    volatile uint16_t insomnia;
+    // Tick counters
+    volatile uint32_t in_sleep;
+    volatile uint32_t in_awake;
+    // Error counters
+    volatile uint32_t sleep_error;
+    volatile uint32_t awake_error;
+} ApiHalTimbase;
+
+ApiHalTimbase api_hal_timebase = {
+    .insomnia = 0,
+    .in_sleep = 0,
+    .in_awake = 0,
+    .sleep_error = 0,
+    .awake_error = 0,
+};
+
+void api_hal_timebase_init() {
+    api_hal_timebase_timer_init();
+    LL_DBGMCU_APB1_GRP2_FreezePeriph(LL_DBGMCU_APB1_GRP2_LPTIM2_STOP);
+
+    LL_LPTIM_EnableIT_CMPM(API_HAL_TIMEBASE_TIMER);
+    LL_LPTIM_EnableIT_ARRM(API_HAL_TIMEBASE_TIMER);
+
+    LL_LPTIM_SetAutoReload(API_HAL_TIMEBASE_TIMER, API_HAL_TIMEBASE_TIMER_MAX);
+    LL_LPTIM_SetCompare(API_HAL_TIMEBASE_TIMER, API_HAL_TIMEBASE_CLK_PER_TICK);
+
+    LL_LPTIM_StartCounter(API_HAL_TIMEBASE_TIMER, LL_LPTIM_OPERATING_MODE_CONTINUOUS);
+}
+
+uint16_t api_hal_timebase_insomnia_level() {
+    return api_hal_timebase.insomnia;
+}
+
+void api_hal_timebase_insomnia_enter() {
+    api_hal_timebase.insomnia++;
+}
+
+void api_hal_timebase_insomnia_exit() {
+    api_hal_timebase.insomnia--;
+}
+
+void LPTIM2_IRQHandler(void) {
+    // Autoreload
+    const bool arrm_flag = LL_LPTIM_IsActiveFlag_ARRM(API_HAL_TIMEBASE_TIMER);
+    if(arrm_flag) {
+        LL_LPTIM_ClearFLAG_ARRM(API_HAL_TIMEBASE_TIMER);
+    }
+    if(LL_LPTIM_IsActiveFlag_CMPM(API_HAL_TIMEBASE_TIMER)) {
+        LL_LPTIM_ClearFLAG_CMPM(API_HAL_TIMEBASE_TIMER);
+
+        // Store important value
+        uint16_t cnt = api_hal_timebase_timer_get_cnt();
+        uint16_t cmp = api_hal_timebase_timer_get_cmp();
+        uint16_t current_tick = cnt / API_HAL_TIMEBASE_CLK_PER_TICK;
+        uint16_t compare_tick = cmp / API_HAL_TIMEBASE_CLK_PER_TICK;
+
+        // Calculate error
+        // happens when HAL or other high priority IRQ takes our time
+        int32_t error = (int32_t)compare_tick - current_tick;
+        api_hal_timebase.awake_error += ((error>0) ? error : -error);
+
+        // Calculate and set next tick 
+        uint16_t next_tick = current_tick + 1;
+        api_hal_timebase_timer_set_cmp(next_tick * API_HAL_TIMEBASE_CLK_PER_TICK);
+
+        // Notify OS
+        api_hal_timebase.in_awake ++;
+        if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
+            xPortSysTickHandler();
+        }
+    }
+}
+
+static inline uint32_t api_hal_timebase_nap(TickType_t expected_idle_ticks) {
+    __WFI();
+    return 0;
+}
+
+static inline uint32_t api_hal_timebase_sleep(TickType_t expected_idle_ticks) {
+    // Store important value before going to sleep
+    const uint16_t before_cnt = api_hal_timebase_timer_get_cnt();
+    const uint16_t before_tick = before_cnt / API_HAL_TIMEBASE_CLK_PER_TICK;
+
+    // Calculate and set next wakeup compare value
+    const uint16_t expected_cnt = (before_tick + expected_idle_ticks - 2) * API_HAL_TIMEBASE_CLK_PER_TICK;
+    api_hal_timebase_timer_set_cmp(expected_cnt);
+
+    // Go to stop2 mode
+    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
+
+    // Spin till we are in timer safe zone
+    while(!api_hal_timebase_timer_is_safe()) {}
+
+    // Store current counter value, calculate current tick
+    const uint16_t after_cnt = api_hal_timebase_timer_get_cnt();
+    const uint16_t after_tick = after_cnt / API_HAL_TIMEBASE_CLK_PER_TICK;
+
+    // Store and clear interrupt flags
+    // we don't want handler to be called after renabling IRQ
+    bool cmpm_flag = LL_LPTIM_IsActiveFlag_CMPM(API_HAL_TIMEBASE_TIMER);
+    if (cmpm_flag) LL_LPTIM_ClearFLAG_CMPM(API_HAL_TIMEBASE_TIMER);
+    bool arrm_flag = LL_LPTIM_IsActiveFlag_ARRM(API_HAL_TIMEBASE_TIMER);
+    if (arrm_flag) LL_LPTIM_ClearFLAG_ARRM(API_HAL_TIMEBASE_TIMER);
+
+    // Calculate and set next wakeup compare value
+    const uint16_t next_cmp = (after_tick + 1) * API_HAL_TIMEBASE_CLK_PER_TICK;
+    api_hal_timebase_timer_set_cmp(next_cmp);
+
+    // Calculate ticks count spent in sleep and perform sanity checks
+    int32_t completed_ticks = arrm_flag ? (int32_t)before_tick - after_tick : (int32_t)after_tick - before_tick;
+
+    return completed_ticks;
+}
+
+void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) {
+    // Limit mount of ticks to maximum that timer can count
+    if (expected_idle_ticks > API_HAL_TIMEBASE_MAX_SLEEP) {
+        expected_idle_ticks = API_HAL_TIMEBASE_MAX_SLEEP;
+    }
+    
+    // Stop IRQ handling, no one should disturb us till we finish 
+    __disable_irq();
+
+    // Confirm OS that sleep is still possible
+    // And check if timer is in safe zone
+    // (8 clocks till any IRQ event or ongoing synchronization)
+    if (eTaskConfirmSleepModeStatus() == eAbortSleep
+        || !api_hal_timebase_timer_is_safe()) {
+        __enable_irq();
+        return;
+    }
+
+    uint32_t completed_ticks;
+    if (api_hal_timebase.insomnia) {
+        completed_ticks = api_hal_timebase_nap(expected_idle_ticks);
+    } else {
+        completed_ticks = api_hal_timebase_sleep(expected_idle_ticks);
+    }
+    assert(completed_ticks >= 0);
+
+    // Reenable IRQ
+    __enable_irq();
+
+    // Notify system about time spent in sleep
+    if (completed_ticks > 0) {
+        api_hal_timebase.in_sleep += completed_ticks;
+        if (completed_ticks > expected_idle_ticks) {
+            // We are late, count error
+            api_hal_timebase.sleep_error += (completed_ticks - expected_idle_ticks);
+            // Freertos is not happy when we overleep
+            // But we are not going to tell her
+            vTaskStepTick(expected_idle_ticks);
+        } else {
+            vTaskStepTick(completed_ticks);
+        }
+    }
+}

+ 27 - 0
firmware/targets/f4/api-hal/api-hal-timebase.h

@@ -0,0 +1,27 @@
+#pragma once
+
+#include <stdint.h>
+
+/* Initialize timebase
+ * Configure and start tick timer
+ */
+void api_hal_timebase_init();
+
+/* Get current insomnia level
+ * @return insomnia level: 0 - no insomnia, >0 - insomnia, bearer count.
+ */
+uint16_t api_hal_timebase_insomnia_level();
+
+/* Enter insomnia mode
+ * Prevents device from going to sleep
+ * @warning Internally increases insomnia level
+ * Must be paired with api_hal_timebase_insomnia_exit
+ */
+void api_hal_timebase_insomnia_enter();
+
+/* Exit insomnia mode
+ * Allow device to go to sleep
+ * @warning Internally decreases insomnia level.
+ * Must be paired with api_hal_timebase_insomnia_enter
+ */
+void api_hal_timebase_insomnia_exit();

+ 7 - 0
firmware/targets/f4/api-hal/api-hal.c

@@ -0,0 +1,7 @@
+#include <api-hal.h>
+
+void api_hal_init() {
+    api_hal_timebase_init();
+    api_hal_vcp_init();
+    api_hal_spi_init();
+}

+ 3 - 0
firmware/targets/f4/ble-glue/app_entry.c

@@ -8,6 +8,7 @@
 #include "shci_tl.h"
 #include "stm32_lpm.h"
 #include "app_debug.h"
+#include <api-hal.h>
 
 extern RTC_HandleTypeDef hrtc;
 
@@ -51,6 +52,7 @@ void APPE_Init() {
   HW_TS_Init(hw_ts_InitMode_Full, &hrtc); /**< Initialize the TimerServer */
 
   // APPD_Init();
+  api_hal_timebase_insomnia_enter();
 
   appe_Tl_Init();	/* Initialize all transport layers */
 
@@ -142,6 +144,7 @@ static void APPE_SysUserEvtRx( void * pPayload ) {
   } else {
     ble_glue_status = BleGlueStatusBroken;
   }
+  api_hal_timebase_insomnia_exit();
 }
 
 /*************************************************************

+ 13 - 10
firmware/targets/f4/f4.ioc

@@ -30,7 +30,7 @@ PinOutPanel.RotationAngle=0
 RCC.MCO1PinFreq_Value=64000000
 RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
 SH.GPXTI13.0=GPIO_EXTI13
-RCC.LPTIM1Freq_Value=64000000
+RCC.LPTIM1Freq_Value=32768
 NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false
 FREERTOS.configENABLE_FPU=1
 NVIC.EXTI1_IRQn=true\:5\:0\:true\:false\:true\:false\:true\:true
@@ -69,7 +69,6 @@ MxDb.Version=DB.6.0.10
 PB0.GPIOParameters=GPIO_Label
 PA1.GPIOParameters=GPIO_Speed,PinState,GPIO_Label,GPIO_ModeDefaultOutputPP
 ProjectManager.BackupPrevious=false
-VP_SYS_VS_tim17.Signal=SYS_VS_tim17
 PC4.GPIO_Label=CC1101_G0
 FREERTOS.HEAP_NUMBER=4
 RCC.LSE_Drive_Capability=RCC_LSEDRIVE_MEDIUMLOW
@@ -95,15 +94,14 @@ Mcu.Package=VFQFPN68
 TIM2.Prescaler=64-1
 PB1.Signal=GPXTI1
 PA5.Locked=true
-NVIC.TimeBase=TIM1_TRG_COM_TIM17_IRQn
 SPI2.Mode=SPI_MODE_MASTER
 PA2.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD
 SH.GPXTI11.0=GPIO_EXTI11
 SH.GPXTI8.0=GPIO_EXTI8
 VP_PKA_VS_PKA.Mode=PKA_Activate
 PA14.Locked=true
+VP_SYS_VS_Systick.Signal=SYS_VS_Systick
 SH.GPXTI8.ConfNb=1
-NVIC.TimeBaseIP=TIM17
 RCC.LSCOPinFreq_Value=32000
 PA10.Signal=I2C1_SDA
 VP_RTC_VS_RTC_Calendar.Mode=RTC_Calendar
@@ -138,12 +136,11 @@ RCC.PLLQoutputFreq_Value=64000000
 ProjectManager.ProjectFileName=f4.ioc
 RCC.SMPSFreq_Value=4000000
 PA3.GPIO_ModeDefaultOutputPP=GPIO_MODE_OUTPUT_OD
-FREERTOS.Tasks01=defaultTask,24,1024,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL;app_main,8,1024,app,As external,NULL,Dynamic,NULL,NULL
+FREERTOS.Tasks01=app_main,24,1024,app,As weak,NULL,Dynamic,NULL,NULL
 ADC1.Rank-0\#ChannelRegularConversion=1
 PA15.GPIOParameters=GPIO_PuPd,GPIO_Label
 Mcu.PinsNb=69
 PC11.Locked=true
-VP_SYS_VS_tim17.Mode=TIM17
 ADC1.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,OffsetNumber-0\#ChannelRegularConversion,NbrOfConversionFlag,master,EnableAnalogWatchDog1,ContinuousConvMode
 PC13.Locked=true
 ADC1.OffsetNumber-0\#ChannelRegularConversion=ADC_OFFSET_NONE
@@ -170,7 +167,7 @@ Mcu.Pin60=VP_PKA_VS_PKA
 Mcu.Pin61=VP_RNG_VS_RNG
 Mcu.Pin66=VP_TIM2_VS_ClockSourceINT
 Mcu.Pin67=VP_TIM16_VS_ClockSourceINT
-Mcu.Pin64=VP_SYS_VS_tim17
+Mcu.Pin64=VP_SYS_VS_Systick
 Mcu.Pin65=VP_TIM1_VS_ClockSourceINT
 PD0.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
 PC3.GPIOParameters=GPIO_Label
@@ -332,6 +329,7 @@ PD0.GPIO_Label=CC1101_CS
 PC0.GPIO_Label=PC0
 PA11.Mode=Device
 PB0.GPIO_Label=DISPLAY_RST
+FREERTOS.configTICK_RATE_HZ=1000
 VP_RTC_VS_RTC_Calendar.Signal=RTC_VS_RTC_Calendar
 PB11.GPIO_PuPd=GPIO_PULLUP
 PC13.GPIO_Label=BUTTON_BACK
@@ -374,7 +372,7 @@ Mcu.Pin7=PC1
 Mcu.Pin8=PC2
 Mcu.Pin9=PC3
 OSC_OUT.Mode=HSE-External-Oscillator
-FREERTOS.IPParameters=Tasks01,configTOTAL_HEAP_SIZE,HEAP_NUMBER,configUSE_TIMERS,configUSE_IDLE_HOOK,FootprintOK,configCHECK_FOR_STACK_OVERFLOW,configRECORD_STACK_HIGH_ADDRESS,configGENERATE_RUN_TIME_STATS,configENABLE_FPU
+FREERTOS.IPParameters=Tasks01,configTOTAL_HEAP_SIZE,HEAP_NUMBER,configUSE_TIMERS,configUSE_IDLE_HOOK,FootprintOK,configCHECK_FOR_STACK_OVERFLOW,configRECORD_STACK_HIGH_ADDRESS,configGENERATE_RUN_TIME_STATS,configENABLE_FPU,configUSE_TICKLESS_IDLE,configENABLE_BACKWARD_COMPATIBILITY,INCLUDE_vTaskCleanUpResources,configTICK_RATE_HZ
 OSC_OUT.Signal=RCC_OSC_OUT
 RCC.AHBFreq_Value=64000000
 SPI2.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_16
@@ -392,9 +390,10 @@ FREERTOS.configUSE_TIMERS=1
 NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
 PH3-BOOT0.GPIOParameters=GPIO_Label,GPIO_ModeDefaultEXTI
 Mcu.IP10=RCC
-NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:true
+NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:true\:true\:false\:false
 Mcu.IP12=RNG
 Mcu.IP11=RF
+FREERTOS.configENABLE_BACKWARD_COMPATIBILITY=0
 Mcu.IP18=TIM2
 Mcu.IP17=TIM1
 NVIC.TIM1_TRG_COM_TIM17_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:true
@@ -422,6 +421,7 @@ PB7.Signal=USART1_RX
 Mcu.IP21=USB
 PB8.Locked=true
 Mcu.IP20=USART1
+FREERTOS.INCLUDE_vTaskCleanUpResources=1
 Mcu.IP22=USB_DEVICE
 PE4.Signal=GPIO_Output
 PB0.Locked=true
@@ -474,6 +474,7 @@ USB_DEVICE.VirtualModeFS=Cdc_FS
 PC4.GPIO_PuPd=GPIO_PULLDOWN
 NVIC.SavedSvcallIrqHandlerGenerated=false
 PC11.Signal=GPIO_Output
+FREERTOS.configUSE_TICKLESS_IDLE=2
 PC4.Signal=GPXTI4
 ProjectManager.DefaultFWLocation=true
 PC2.Mode=Full_Duplex_Master
@@ -504,6 +505,7 @@ RCC.HCLKRFFreq_Value=16000000
 PC5.GPIOParameters=GPIO_Label
 PB9.Mode=PWM Generation3 CH3N
 PB2.GPIOParameters=GPIO_Label
+RCC.LPTIM1CLockSelection=RCC_LPTIM1CLKSOURCE_LSE
 SH.GPXTI12.ConfNb=1
 PE4.Locked=true
 SPI2.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,BaudRatePrescaler,CLKPhase
@@ -535,13 +537,14 @@ RCC.PLLSAI1QoutputFreq_Value=48000000
 RCC.ADCFreq_Value=48000000
 PC1.GPIO_Label=PC1
 PA10.GPIOParameters=GPIO_Speed,GPIO_Label
+VP_SYS_VS_Systick.Mode=SysTick
 VP_ADC1_Vref_Input.Signal=ADC1_Vref_Input
 SH.SharedAnalog_PC5.1=ADC1_IN14,IN14-Single-Ended
 OSC_OUT.Locked=true
 PA4.GPIOParameters=GPIO_Label
 PH3-BOOT0.GPIO_ModeDefaultEXTI=GPIO_MODE_IT_RISING_FALLING
 PB15.GPIOParameters=GPIO_Label
-RCC.IPParameters=ADCFreq_Value,AHB2CLKDivider,AHBFreq_Value,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,APB3Freq_Value,Cortex2Freq_Value,CortexFreq_Value,EnableCSSLSE,EnbaleCSS,FCLK2Freq_Value,FCLKCortexFreq_Value,FamilyName,HCLK2Freq_Value,HCLK3Freq_Value,HCLKFreq_Value,HCLKRFFreq_Value,HSE_VALUE,HSI48_VALUE,HSI_VALUE,I2C1Freq_Value,I2C3Freq_Value,LCDFreq_Value,LPTIM1Freq_Value,LPTIM2Freq_Value,LPUART1Freq_Value,LSCOPinFreq_Value,LSE_Drive_Capability,LSE_Timout,LSI_VALUE,MCO1PinFreq_Value,MSIOscState,PLLM,PLLPoutputFreq_Value,PLLQoutputFreq_Value,PLLRCLKFreq_Value,PLLSAI1N,PLLSAI1PoutputFreq_Value,PLLSAI1QoutputFreq_Value,PLLSAI1RoutputFreq_Value,PLLSourceVirtual,PREFETCH_ENABLE,PWRFreq_Value,RFWKPClockSelection,RFWKPFreq_Value,RNGCLockSelection,RNGFreq_Value,RTCClockSelection,RTCFreq_Value,SAI1Freq_Value,SMPS1Freq_Value,SMPSCLockSelectionVirtual,SMPSDivider,SMPSFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,USART1Freq_Value,USBFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAI1OutputFreq_Value
+RCC.IPParameters=ADCFreq_Value,AHB2CLKDivider,AHBFreq_Value,APB1Freq_Value,APB1TimFreq_Value,APB2Freq_Value,APB2TimFreq_Value,APB3Freq_Value,Cortex2Freq_Value,CortexFreq_Value,EnableCSSLSE,EnbaleCSS,FCLK2Freq_Value,FCLKCortexFreq_Value,FamilyName,HCLK2Freq_Value,HCLK3Freq_Value,HCLKFreq_Value,HCLKRFFreq_Value,HSE_VALUE,HSI48_VALUE,HSI_VALUE,I2C1Freq_Value,I2C3Freq_Value,LCDFreq_Value,LPTIM1CLockSelection,LPTIM1Freq_Value,LPTIM2Freq_Value,LPUART1Freq_Value,LSCOPinFreq_Value,LSE_Drive_Capability,LSE_Timout,LSI_VALUE,MCO1PinFreq_Value,MSIOscState,PLLM,PLLPoutputFreq_Value,PLLQoutputFreq_Value,PLLRCLKFreq_Value,PLLSAI1N,PLLSAI1PoutputFreq_Value,PLLSAI1QoutputFreq_Value,PLLSAI1RoutputFreq_Value,PLLSourceVirtual,PREFETCH_ENABLE,PWRFreq_Value,RFWKPClockSelection,RFWKPFreq_Value,RNGCLockSelection,RNGFreq_Value,RTCClockSelection,RTCFreq_Value,SAI1Freq_Value,SMPS1Freq_Value,SMPSCLockSelectionVirtual,SMPSDivider,SMPSFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,USART1Freq_Value,USBFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAI1OutputFreq_Value
 ProjectManager.AskForMigrate=true
 Mcu.Name=STM32WB55RGVx
 NVIC.SavedPendsvIrqHandlerGenerated=false

+ 1 - 1
firmware/targets/f4/stm32wb55xx_flash_cm4.ld

@@ -55,7 +55,7 @@ _Min_Stack_Size = 0x1000; /* required amount of stack */
 /* Specify the memory areas */
 MEMORY
 {
-FLASH (rx)                 : ORIGIN = 0x08008000, LENGTH = 480K
+FLASH (rx)                 : ORIGIN = 0x08000000, LENGTH = 512K
 RAM1 (xrw)                 : ORIGIN = 0x20000004, LENGTH = 0x2FFFC
 RAM_SHARED (xrw)           : ORIGIN = 0x20030000, LENGTH = 10K
 }

+ 1 - 0
firmware/targets/f4/target.mk

@@ -64,6 +64,7 @@ C_SOURCES		+= \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_tim_ex.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_uart.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_uart_ex.c \
+	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_lptim.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_adc.c \
 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_usb.c \
 	$(CUBE_DIR)/Middlewares/Third_Party/FreeRTOS/Source/croutine.c \