Переглянути джерело

[FL-2480] Use SysTick as the main OS timer (#1140)

* Use SysTick as OS tick timer
* Use LPTIM2 as tickless idle timer
* Remove dummy LPTIM2 IRQ handler
* Clean up clock init code
* Rename os timer to idle timer
* Advance hal ticks along with FreeRTOS's
* Improve SysTick control during tickless idle
* Improve idle timer precision
* Correct SysTick IRQ priority
* Main, FuriHal: move system startup to separate thread
* Minor code cleanup

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Georgii Surkov 3 роки тому
батько
коміт
df66f4f6ba

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

@@ -18,7 +18,7 @@ extern uint32_t SystemCoreClock;
 #define configUSE_IDLE_HOOK 0
 #define configUSE_TICK_HOOK 0
 #define configCPU_CLOCK_HZ (SystemCoreClock)
-#define configTICK_RATE_HZ ((TickType_t)1024)
+#define configTICK_RATE_HZ ((TickType_t)1000)
 #define configMAX_PRIORITIES (56)
 #define configMINIMAL_STACK_SIZE ((uint16_t)128)
 

+ 17 - 23
firmware/targets/f7/Src/main.c

@@ -6,32 +6,31 @@
 
 #define TAG "Main"
 
-#ifdef FURI_RAM_EXEC
-int main() {
-    // Initialize FURI layer
-    furi_init();
-
-    // Flipper critical FURI HAL
-    furi_hal_init_early();
+static const osThreadAttr_t init_thread_attr = {
+    .name = "Init",
+    .stack_size = 4096,
+};
 
+void init_task() {
     // Flipper FURI HAL
     furi_hal_init();
 
     // Init flipper
     flipper_init();
 
-    furi_run();
-
-    while(1) {
-    }
+    osThreadExit();
 }
-#else
+
 int main() {
     // Initialize FURI layer
     furi_init();
 
     // Flipper critical FURI HAL
     furi_hal_init_early();
+
+#ifdef FURI_RAM_EXEC
+    osThreadNew(init_task, NULL, &init_thread_attr);
+#else
     furi_hal_light_sequence("RGB");
 
     // Delay is for button sampling
@@ -52,20 +51,15 @@ int main() {
         furi_hal_power_reset();
     } else {
         furi_hal_light_sequence("rgb G");
-
-        // Flipper FURI HAL
-        furi_hal_init();
-
-        // Init flipper
-        flipper_init();
-
-        furi_run();
+        osThreadNew(init_task, NULL, &init_thread_attr);
     }
+#endif
 
-    while(1) {
-    }
+    // Run Kernel
+    furi_run();
+
+    furi_crash("Kernel is Dead");
 }
-#endif
 
 void Error_Handler(void) {
     furi_crash("ErrorHandler");

+ 2 - 3
firmware/targets/f7/furi_hal/furi_hal.c

@@ -10,6 +10,8 @@ void furi_hal_init_early() {
     furi_hal_clock_init_early();
     furi_hal_delay_init();
 
+    furi_hal_os_init();
+
     furi_hal_resources_init_early();
 
     furi_hal_spi_init_early();
@@ -75,9 +77,6 @@ void furi_hal_init() {
     furi_hal_bt_init();
     furi_hal_compress_icon_init();
 
-    // FreeRTOS glue
-    furi_hal_os_init();
-
     // FatFS driver initialization
     MX_FATFS_Init();
     FURI_LOG_I(TAG, "FATFS OK");

+ 20 - 8
firmware/targets/f7/furi_hal/furi_hal_clock.c

@@ -9,13 +9,15 @@
 
 #define TAG "FuriHalClock"
 
-#define TICK_INT_PRIORITY 0U
+#define CPU_CLOCK_HZ_EARLY 4000000
+#define CPU_CLOCK_HZ_MAIN 64000000
+#define TICK_INT_PRIORITY 15U
 #define HS_CLOCK_IS_READY() (LL_RCC_HSE_IsReady() && LL_RCC_HSI_IsReady())
 #define LS_CLOCK_IS_READY() (LL_RCC_LSE_IsReady() && LL_RCC_LSI1_IsReady())
 
 void furi_hal_clock_init_early() {
-    LL_Init1msTick(4000000);
-    LL_SetSystemCoreClock(4000000);
+    LL_SetSystemCoreClock(CPU_CLOCK_HZ_EARLY);
+    LL_Init1msTick(SystemCoreClock);
 
     LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA);
     LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOB);
@@ -27,6 +29,8 @@ void furi_hal_clock_init_early() {
     LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
     LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
 
+    LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPTIM2);
+
     LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C1);
     LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_I2C3);
 }
@@ -47,7 +51,7 @@ void furi_hal_clock_deinit_early() {
 }
 
 void furi_hal_clock_init() {
-    /* Prepare Flash memory for 64mHz system clock */
+    /* Prepare Flash memory for 64MHz system clock */
     LL_FLASH_SetLatency(LL_FLASH_LATENCY_3);
     while(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_3)
         ;
@@ -116,12 +120,13 @@ void furi_hal_clock_init() {
         ;
 
     /* Update CMSIS variable (which can be updated also through SystemCoreClockUpdate function) */
-    LL_SetSystemCoreClock(64000000);
+    LL_SetSystemCoreClock(CPU_CLOCK_HZ_MAIN);
 
     /* Update the time base */
-    LL_InitTick(64000000, 1000);
+    LL_Init1msTick(SystemCoreClock);
     LL_SYSTICK_EnableIT();
-    NVIC_SetPriority(SysTick_IRQn, TICK_INT_PRIORITY);
+    NVIC_SetPriority(
+        SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), TICK_INT_PRIORITY, 0));
     NVIC_EnableIRQ(SysTick_IRQn);
 
     LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
@@ -175,7 +180,6 @@ void furi_hal_clock_init() {
 
     // APB1 GRP2
     LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPUART1);
-    LL_APB1_GRP2_EnableClock(LL_APB1_GRP2_PERIPH_LPTIM2);
 
     // APB2
     // LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC);
@@ -217,3 +221,11 @@ void furi_hal_clock_switch_to_pll() {
     while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL)
         ;
 }
+
+void furi_hal_clock_suspend_tick() {
+    CLEAR_BIT(SysTick->CTRL, SysTick_CTRL_ENABLE_Msk);
+}
+
+void furi_hal_clock_resume_tick() {
+    SET_BIT(SysTick->CTRL, SysTick_CTRL_ENABLE_Msk);
+}

+ 6 - 0
firmware/targets/f7/furi_hal/furi_hal_clock.h

@@ -14,3 +14,9 @@ void furi_hal_clock_switch_to_hsi();
 
 /** Switch to PLL clock */
 void furi_hal_clock_switch_to_pll();
+
+/** Stop SysTick counter without resetting */
+void furi_hal_clock_suspend_tick();
+
+/** Continue SysTick counter operation */
+void furi_hal_clock_resume_tick();

+ 1 - 7
firmware/targets/f7/furi_hal/furi_hal_delay.c

@@ -6,8 +6,6 @@
 
 #define TAG "FuriHalDelay"
 
-static volatile uint32_t tick_cnt = 0;
-
 void furi_hal_delay_init() {
     CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
     DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
@@ -18,12 +16,8 @@ uint32_t furi_hal_delay_instructions_per_microsecond() {
     return SystemCoreClock / 1000000;
 }
 
-void furi_hal_tick(void) {
-    tick_cnt++;
-}
-
 uint32_t furi_hal_get_tick(void) {
-    return tick_cnt;
+    return osKernelGetTickCount();
 }
 
 uint32_t furi_hal_ms_to_ticks(float milliseconds) {

+ 55 - 0
firmware/targets/f7/furi_hal/furi_hal_idle_timer.h

@@ -0,0 +1,55 @@
+#pragma once
+
+#include <stm32wbxx_ll_lptim.h>
+#include <stm32wbxx_ll_bus.h>
+#include <stm32wbxx_ll_rcc.h>
+#include <stdint.h>
+
+// Timer used for tickless idle
+#define FURI_HAL_IDLE_TIMER_MAX 0xFFFF
+#define FURI_HAL_IDLE_TIMER LPTIM2
+#define FURI_HAL_IDLE_TIMER_IRQ LPTIM2_IRQn
+
+static inline void furi_hal_idle_timer_init() {
+    // Configure clock source
+    LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_LSE);
+    // Set interrupt priority and enable them
+    NVIC_SetPriority(
+        FURI_HAL_IDLE_TIMER_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
+    NVIC_EnableIRQ(FURI_HAL_IDLE_TIMER_IRQ);
+}
+
+static inline void furi_hal_idle_timer_start(uint32_t count) {
+    count--;
+    // Enable timer
+    LL_LPTIM_Enable(FURI_HAL_IDLE_TIMER);
+    while(!LL_LPTIM_IsEnabled(FURI_HAL_IDLE_TIMER))
+        ;
+
+    // Enable compare match interrupt
+    LL_LPTIM_EnableIT_CMPM(FURI_HAL_IDLE_TIMER);
+
+    // Set compare, autoreload and start counter
+    // Include some marging to workaround ARRM behaviour
+    LL_LPTIM_SetCompare(FURI_HAL_IDLE_TIMER, count - 3);
+    LL_LPTIM_SetAutoReload(FURI_HAL_IDLE_TIMER, count);
+    LL_LPTIM_StartCounter(FURI_HAL_IDLE_TIMER, LL_LPTIM_OPERATING_MODE_ONESHOT);
+}
+
+static inline void furi_hal_idle_timer_reset() {
+    // Hard reset timer
+    // THE ONLY RELIABLE WAY to stop it according to errata
+    LL_LPTIM_DeInit(FURI_HAL_IDLE_TIMER);
+    // Prevent IRQ handler call
+    NVIC_ClearPendingIRQ(FURI_HAL_IDLE_TIMER_IRQ);
+}
+
+static inline uint32_t furi_hal_idle_timer_get_cnt() {
+    uint32_t counter = LL_LPTIM_GetCounter(FURI_HAL_IDLE_TIMER);
+    uint32_t counter_shadow = LL_LPTIM_GetCounter(FURI_HAL_IDLE_TIMER);
+    while(counter != counter_shadow) {
+        counter = counter_shadow;
+        counter_shadow = LL_LPTIM_GetCounter(FURI_HAL_IDLE_TIMER);
+    }
+    return counter;
+}

+ 3 - 2
firmware/targets/f7/furi_hal/furi_hal_interrupt.c

@@ -1,5 +1,6 @@
 #include "furi_hal_interrupt.h"
 #include "furi_hal_delay.h"
+#include "furi_hal_os.h"
 
 #include <furi.h>
 
@@ -249,7 +250,7 @@ extern void HW_IPCC_Tx_Handler();
 extern void HW_IPCC_Rx_Handler();
 
 void SysTick_Handler(void) {
-    furi_hal_tick();
+    furi_hal_os_tick();
 }
 
 void USB_LP_IRQHandler(void) {
@@ -264,4 +265,4 @@ void IPCC_C1_TX_IRQHandler(void) {
 
 void IPCC_C1_RX_IRQHandler(void) {
     HW_IPCC_Rx_Handler();
-}
+}

+ 29 - 42
firmware/targets/f7/furi_hal/furi_hal_os.c

@@ -1,17 +1,22 @@
 #include <furi_hal_os.h>
-#include <furi_hal_os_timer.h>
+#include <furi_hal_clock.h>
 #include <furi_hal_power.h>
+#include <furi_hal_delay.h>
+#include <furi_hal_idle_timer.h>
 #include <stm32wbxx_ll_cortex.h>
 
 #include <furi.h>
 
 #define TAG "FuriHalOs"
 
-#define FURI_HAL_OS_CLK_FREQUENCY 32768
-#define FURI_HAL_OS_TICK_PER_SECOND 1024
-#define FURI_HAL_OS_CLK_PER_TICK (FURI_HAL_OS_CLK_FREQUENCY / FURI_HAL_OS_TICK_PER_SECOND)
-#define FURI_HAL_OS_TICK_PER_EPOCH (FURI_HAL_OS_TIMER_MAX / FURI_HAL_OS_CLK_PER_TICK)
-#define FURI_HAL_OS_MAX_SLEEP (FURI_HAL_OS_TICK_PER_EPOCH - 1)
+#define FURI_HAL_IDLE_TIMER_CLK_HZ 32768
+#define FURI_HAL_OS_TICK_HZ configTICK_RATE_HZ
+
+#define FURI_HAL_OS_IDLE_CNT_TO_TICKS(x) ((x * FURI_HAL_OS_TICK_HZ) / FURI_HAL_IDLE_TIMER_CLK_HZ)
+#define FURI_HAL_OS_TICKS_TO_IDLE_CNT(x) ((x * FURI_HAL_IDLE_TIMER_CLK_HZ) / FURI_HAL_OS_TICK_HZ)
+
+#define FURI_HAL_IDLE_TIMER_TICK_PER_EPOCH (FURI_HAL_OS_IDLE_CNT_TO_TICKS(FURI_HAL_IDLE_TIMER_MAX))
+#define FURI_HAL_OS_MAX_SLEEP (FURI_HAL_IDLE_TIMER_TICK_PER_EPOCH - 1)
 
 #ifdef FURI_HAL_OS_DEBUG
 #include <stm32wbxx_ll_gpio.h>
@@ -30,48 +35,37 @@ void furi_hal_os_timer_callback() {
 
 extern void xPortSysTickHandler();
 
-volatile uint32_t furi_hal_os_skew = 0;
+static volatile uint32_t furi_hal_os_skew = 0;
 
 void furi_hal_os_init() {
-    LL_DBGMCU_APB1_GRP2_FreezePeriph(LL_DBGMCU_APB1_GRP2_LPTIM2_STOP);
-
-    furi_hal_os_timer_init();
-    furi_hal_os_timer_continuous(FURI_HAL_OS_CLK_PER_TICK);
+    furi_hal_idle_timer_init();
 
 #ifdef FURI_HAL_OS_DEBUG
     LL_GPIO_SetPinMode(LED_SLEEP_PORT, LED_SLEEP_PIN, LL_GPIO_MODE_OUTPUT);
     LL_GPIO_SetPinMode(LED_TICK_PORT, LED_TICK_PIN, LL_GPIO_MODE_OUTPUT);
     LL_GPIO_SetPinMode(LED_SECOND_PORT, LED_SECOND_PIN, LL_GPIO_MODE_OUTPUT);
     osTimerId_t second_timer = osTimerNew(furi_hal_os_timer_callback, osTimerPeriodic, NULL, NULL);
-    osTimerStart(second_timer, FURI_HAL_OS_TICK_PER_SECOND);
+    osTimerStart(second_timer, FURI_HAL_OS_TICK_HZ);
 #endif
 
     FURI_LOG_I(TAG, "Init OK");
 }
 
-void LPTIM2_IRQHandler(void) {
-    // Autoreload
-    if(LL_LPTIM_IsActiveFlag_ARRM(FURI_HAL_OS_TIMER)) {
-        LL_LPTIM_ClearFLAG_ARRM(FURI_HAL_OS_TIMER);
-        if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
+void furi_hal_os_tick() {
+    if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) {
 #ifdef FURI_HAL_OS_DEBUG
-            LL_GPIO_TogglePin(LED_TICK_PORT, LED_TICK_PIN);
+        LL_GPIO_TogglePin(LED_TICK_PORT, LED_TICK_PIN);
 #endif
-            xPortSysTickHandler();
-        }
-    }
-    if(LL_LPTIM_IsActiveFlag_CMPM(FURI_HAL_OS_TIMER)) {
-        LL_LPTIM_ClearFLAG_CMPM(FURI_HAL_OS_TIMER);
+        xPortSysTickHandler();
     }
 }
 
 static inline uint32_t furi_hal_os_sleep(TickType_t expected_idle_ticks) {
     // Stop ticks
-    furi_hal_os_timer_reset();
-    LL_SYSTICK_DisableIT();
+    furi_hal_clock_suspend_tick();
 
     // Start wakeup timer
-    furi_hal_os_timer_single(expected_idle_ticks * FURI_HAL_OS_CLK_PER_TICK);
+    furi_hal_idle_timer_start(FURI_HAL_OS_TICKS_TO_IDLE_CNT(expected_idle_ticks));
 
 #ifdef FURI_HAL_OS_DEBUG
     LL_GPIO_ResetOutputPin(LED_SLEEP_PORT, LED_SLEEP_PIN);
@@ -85,21 +79,19 @@ static inline uint32_t furi_hal_os_sleep(TickType_t expected_idle_ticks) {
 #endif
 
     // Calculate how much time we spent in the sleep
-    uint32_t after_cnt = furi_hal_os_timer_get_cnt() + furi_hal_os_skew;
-    uint32_t after_tick = after_cnt / FURI_HAL_OS_CLK_PER_TICK;
-    furi_hal_os_skew = after_cnt % FURI_HAL_OS_CLK_PER_TICK;
+    uint32_t after_cnt = furi_hal_idle_timer_get_cnt() + furi_hal_os_skew;
+    uint32_t after_tick = FURI_HAL_OS_IDLE_CNT_TO_TICKS(after_cnt);
+    furi_hal_os_skew = after_cnt - (after_cnt / after_tick);
 
-    bool cmpm = LL_LPTIM_IsActiveFlag_CMPM(FURI_HAL_OS_TIMER);
-    bool arrm = LL_LPTIM_IsActiveFlag_ARRM(FURI_HAL_OS_TIMER);
+    bool cmpm = LL_LPTIM_IsActiveFlag_CMPM(FURI_HAL_IDLE_TIMER);
+    bool arrm = LL_LPTIM_IsActiveFlag_ARRM(FURI_HAL_IDLE_TIMER);
     if(cmpm && arrm) after_tick += expected_idle_ticks;
 
     // Prepare tick timer for new round
-    furi_hal_os_timer_reset();
+    furi_hal_idle_timer_reset();
 
     // Resume ticks
-    LL_SYSTICK_EnableIT();
-    furi_hal_os_timer_continuous(FURI_HAL_OS_CLK_PER_TICK);
-
+    furi_hal_clock_resume_tick();
     return after_tick;
 }
 
@@ -109,7 +101,7 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) {
         return;
     }
 
-    // Limit mount of ticks to maximum that timer can count
+    // Limit amount of ticks to maximum that timer can count
     if(expected_idle_ticks > FURI_HAL_OS_MAX_SLEEP) {
         expected_idle_ticks = FURI_HAL_OS_MAX_SLEEP;
     }
@@ -125,14 +117,9 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) {
 
     // Sleep and track how much ticks we spent sleeping
     uint32_t completed_ticks = furi_hal_os_sleep(expected_idle_ticks);
-
     // Notify system about time spent in sleep
     if(completed_ticks > 0) {
-        if(completed_ticks > expected_idle_ticks) {
-            vTaskStepTick(expected_idle_ticks);
-        } else {
-            vTaskStepTick(completed_ticks);
-        }
+        vTaskStepTick(MIN(completed_ticks, expected_idle_ticks));
     }
 
     // Reenable IRQ

+ 5 - 1
firmware/targets/f7/furi_hal/furi_hal_os.h

@@ -11,6 +11,10 @@ extern "C" {
  */
 void furi_hal_os_init();
 
+/* Advance OS tick counter
+ */
+void furi_hal_os_tick();
+
 #ifdef __cplusplus
 }
-#endif
+#endif

+ 0 - 69
firmware/targets/f7/furi_hal/furi_hal_os_timer.h

@@ -1,69 +0,0 @@
-#pragma once
-
-#include <stm32wbxx_ll_lptim.h>
-#include <stm32wbxx_ll_bus.h>
-#include <stm32wbxx_ll_rcc.h>
-#include <stdint.h>
-
-// Timer used for system ticks
-#define FURI_HAL_OS_TIMER_MAX 0xFFFF
-#define FURI_HAL_OS_TIMER_REG_LOAD_DLY 0x1
-#define FURI_HAL_OS_TIMER LPTIM2
-#define FURI_HAL_OS_TIMER_IRQ LPTIM2_IRQn
-
-static inline void furi_hal_os_timer_init() {
-    // Configure clock source
-    LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_LSE);
-    // Set interrupt priority and enable them
-    NVIC_SetPriority(
-        FURI_HAL_OS_TIMER_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
-    NVIC_EnableIRQ(FURI_HAL_OS_TIMER_IRQ);
-}
-
-static inline void furi_hal_os_timer_continuous(uint32_t count) {
-    count--;
-    // Enable timer
-    LL_LPTIM_Enable(FURI_HAL_OS_TIMER);
-    while(!LL_LPTIM_IsEnabled(FURI_HAL_OS_TIMER))
-        ;
-
-    // Enable rutoreload match interrupt
-    LL_LPTIM_EnableIT_ARRM(FURI_HAL_OS_TIMER);
-
-    // Set autoreload and start counter
-    LL_LPTIM_SetAutoReload(FURI_HAL_OS_TIMER, count);
-    LL_LPTIM_StartCounter(FURI_HAL_OS_TIMER, LL_LPTIM_OPERATING_MODE_CONTINUOUS);
-}
-
-static inline void furi_hal_os_timer_single(uint32_t count) {
-    count--;
-    // Enable timer
-    LL_LPTIM_Enable(FURI_HAL_OS_TIMER);
-    while(!LL_LPTIM_IsEnabled(FURI_HAL_OS_TIMER))
-        ;
-
-    // Enable compare match interrupt
-    LL_LPTIM_EnableIT_CMPM(FURI_HAL_OS_TIMER);
-
-    // Set compare, autoreload and start counter
-    // Include some marging to workaround ARRM behaviour
-    LL_LPTIM_SetCompare(FURI_HAL_OS_TIMER, count - 3);
-    LL_LPTIM_SetAutoReload(FURI_HAL_OS_TIMER, count);
-    LL_LPTIM_StartCounter(FURI_HAL_OS_TIMER, LL_LPTIM_OPERATING_MODE_ONESHOT);
-}
-
-static inline void furi_hal_os_timer_reset() {
-    // Hard reset timer
-    // THE ONLY RELIABLEWAY to stop it according to errata
-    LL_LPTIM_DeInit(FURI_HAL_OS_TIMER);
-}
-
-static inline uint32_t furi_hal_os_timer_get_cnt() {
-    uint32_t counter = LL_LPTIM_GetCounter(FURI_HAL_OS_TIMER);
-    uint32_t counter_shadow = LL_LPTIM_GetCounter(FURI_HAL_OS_TIMER);
-    while(counter != counter_shadow) {
-        counter = counter_shadow;
-        counter_shadow = LL_LPTIM_GetCounter(FURI_HAL_OS_TIMER);
-    }
-    return counter;
-}

+ 0 - 5
firmware/targets/furi_hal_include/furi_hal_delay.h

@@ -18,11 +18,6 @@ void furi_hal_delay_init();
 /** Get instructions per microsecond count */
 uint32_t furi_hal_delay_instructions_per_microsecond();
 
-/** Increase tick counter.
- *  Should be called from SysTick ISR
- */
-void furi_hal_tick(void);
-
 /** Get current tick counter
  *
  * System uptime, may overflow.