Просмотр исходного кода

[FL-2818] FuriHal: add FuriHalCortexTimer, use it for i2c bus timeouts (#1900)

* FuriHal: add FuriHalCortexTimer, use it for i2c bus timeouts
* Furi: cleanup FuriHalCortexTimer sources and headers
あく 3 лет назад
Родитель
Сommit
33892ebfb7

+ 4 - 1
firmware/targets/f7/api_symbols.csv

@@ -1,5 +1,5 @@
 entry,status,name,type,params
-Version,+,3.4,,
+Version,+,3.5,,
 Header,+,applications/services/bt/bt_service/bt.h,,
 Header,+,applications/services/cli/cli.h,,
 Header,+,applications/services/cli/cli_vcp.h,,
@@ -985,6 +985,9 @@ Function,+,furi_hal_console_tx_with_new_line,void,"const uint8_t*, size_t"
 Function,+,furi_hal_cortex_delay_us,void,uint32_t
 Function,-,furi_hal_cortex_init_early,void,
 Function,+,furi_hal_cortex_instructions_per_microsecond,uint32_t,
+Function,+,furi_hal_cortex_timer_get,FuriHalCortexTimer,uint32_t
+Function,+,furi_hal_cortex_timer_is_expired,_Bool,FuriHalCortexTimer
+Function,+,furi_hal_cortex_timer_wait,void,FuriHalCortexTimer
 Function,+,furi_hal_crypto_decrypt,_Bool,"const uint8_t*, uint8_t*, size_t"
 Function,+,furi_hal_crypto_encrypt,_Bool,"const uint8_t*, uint8_t*, size_t"
 Function,-,furi_hal_crypto_init,void,

+ 19 - 2
firmware/targets/f7/furi_hal/furi_hal_cortex.c

@@ -2,6 +2,8 @@
 
 #include <stm32wbxx.h>
 
+#define FURI_HAL_CORTEX_INSTRUCTIONS_PER_MICROSECOND (SystemCoreClock / 1000000)
+
 void furi_hal_cortex_init_early() {
     CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
     DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
@@ -13,11 +15,26 @@ void furi_hal_cortex_init_early() {
 
 void furi_hal_cortex_delay_us(uint32_t microseconds) {
     uint32_t start = DWT->CYCCNT;
-    uint32_t time_ticks = SystemCoreClock / 1000000 * microseconds;
+    uint32_t time_ticks = FURI_HAL_CORTEX_INSTRUCTIONS_PER_MICROSECOND * microseconds;
     while((DWT->CYCCNT - start) < time_ticks) {
     };
 }
 
 uint32_t furi_hal_cortex_instructions_per_microsecond() {
-    return SystemCoreClock / 1000000;
+    return FURI_HAL_CORTEX_INSTRUCTIONS_PER_MICROSECOND;
+}
+
+FuriHalCortexTimer furi_hal_cortex_timer_get(uint32_t timeout_us) {
+    FuriHalCortexTimer cortex_timer = {0};
+    cortex_timer.start = DWT->CYCCNT;
+    cortex_timer.value = FURI_HAL_CORTEX_INSTRUCTIONS_PER_MICROSECOND * timeout_us;
+    return cortex_timer;
 }
+
+bool furi_hal_cortex_timer_is_expired(FuriHalCortexTimer cortex_timer) {
+    return !((DWT->CYCCNT - cortex_timer.start) < cortex_timer.value);
+}
+
+void furi_hal_cortex_timer_wait(FuriHalCortexTimer cortex_timer) {
+    while(!furi_hal_cortex_timer_is_expired(cortex_timer));
+}

+ 15 - 14
firmware/targets/f7/furi_hal/furi_hal_i2c.c

@@ -1,6 +1,7 @@
 #include <furi_hal_i2c.h>
 #include <furi_hal_version.h>
 #include <furi_hal_power.h>
+#include <furi_hal_cortex.h>
 
 #include <stm32wbxx_ll_i2c.h>
 #include <stm32wbxx_ll_gpio.h>
@@ -60,11 +61,11 @@ bool furi_hal_i2c_tx(
     furi_assert(timeout > 0);
 
     bool ret = true;
-    uint32_t timeout_tick = furi_get_tick() + timeout;
+    FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout * 1000);
 
     do {
         while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) {
-            if(furi_get_tick() >= timeout_tick) {
+            if(furi_hal_cortex_timer_is_expired(timer)) {
                 ret = false;
                 break;
             }
@@ -89,7 +90,7 @@ bool furi_hal_i2c_tx(
                 size--;
             }
 
-            if(furi_get_tick() >= timeout_tick) {
+            if(furi_hal_cortex_timer_is_expired(timer)) {
                 ret = false;
                 break;
             }
@@ -111,11 +112,11 @@ bool furi_hal_i2c_rx(
     furi_assert(timeout > 0);
 
     bool ret = true;
-    uint32_t timeout_tick = furi_get_tick() + timeout;
+    FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout * 1000);
 
     do {
         while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) {
-            if(furi_get_tick() >= timeout_tick) {
+            if(furi_hal_cortex_timer_is_expired(timer)) {
                 ret = false;
                 break;
             }
@@ -140,7 +141,7 @@ bool furi_hal_i2c_rx(
                 size--;
             }
 
-            if(furi_get_tick() >= timeout_tick) {
+            if(furi_hal_cortex_timer_is_expired(timer)) {
                 ret = false;
                 break;
             }
@@ -175,11 +176,11 @@ bool furi_hal_i2c_is_device_ready(FuriHalI2cBusHandle* handle, uint8_t i2c_addr,
     furi_assert(timeout > 0);
 
     bool ret = true;
-    uint32_t timeout_tick = furi_get_tick() + timeout;
+    FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout * 1000);
 
     do {
         while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) {
-            if(furi_get_tick() >= timeout_tick) {
+            if(furi_hal_cortex_timer_is_expired(timer)) {
                 return false;
             }
         }
@@ -190,14 +191,14 @@ bool furi_hal_i2c_is_device_ready(FuriHalI2cBusHandle* handle, uint8_t i2c_addr,
 
         while((!LL_I2C_IsActiveFlag_NACK(handle->bus->i2c)) &&
               (!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c))) {
-            if(furi_get_tick() >= timeout_tick) {
+            if(furi_hal_cortex_timer_is_expired(timer)) {
                 return false;
             }
         }
 
         if(LL_I2C_IsActiveFlag_NACK(handle->bus->i2c)) {
             while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c)) {
-                if(furi_get_tick() >= timeout_tick) {
+                if(furi_hal_cortex_timer_is_expired(timer)) {
                     return false;
                 }
             }
@@ -214,7 +215,7 @@ bool furi_hal_i2c_is_device_ready(FuriHalI2cBusHandle* handle, uint8_t i2c_addr,
         }
 
         while(!LL_I2C_IsActiveFlag_STOP(handle->bus->i2c)) {
-            if(furi_get_tick() >= timeout_tick) {
+            if(furi_hal_cortex_timer_is_expired(timer)) {
                 return false;
             }
         }
@@ -308,11 +309,11 @@ bool furi_hal_i2c_write_mem(
 
     bool ret = true;
     uint8_t size = len + 1;
-    uint32_t timeout_tick = furi_get_tick() + timeout;
+    FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout * 1000);
 
     do {
         while(LL_I2C_IsActiveFlag_BUSY(handle->bus->i2c)) {
-            if(furi_get_tick() >= timeout_tick) {
+            if(furi_hal_cortex_timer_is_expired(timer)) {
                 ret = false;
                 break;
             }
@@ -341,7 +342,7 @@ bool furi_hal_i2c_write_mem(
                 size--;
             }
 
-            if(furi_get_tick() >= timeout_tick) {
+            if(furi_hal_cortex_timer_is_expired(timer)) {
                 ret = false;
                 break;
             }

+ 29 - 0
firmware/targets/furi_hal_include/furi_hal_cortex.h

@@ -6,11 +6,18 @@
 #pragma once
 
 #include <stdint.h>
+#include <stdbool.h>
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+/** Cortex timer provides high precision low level expiring timer */
+typedef struct {
+    uint32_t start;
+    uint32_t value;
+} FuriHalCortexTimer;
+
 /** Early init stage for cortex
  */
 void furi_hal_cortex_init_early();
@@ -27,6 +34,28 @@ void furi_hal_cortex_delay_us(uint32_t microseconds);
  */
 uint32_t furi_hal_cortex_instructions_per_microsecond();
 
+/** Get Timer
+ *
+ * @param[in]  timeout_us  The expire timeout in us
+ *
+ * @return     The FuriHalCortexTimer
+ */
+FuriHalCortexTimer furi_hal_cortex_timer_get(uint32_t timeout_us);
+
+/** Check if timer expired
+ *
+ * @param[in]  cortex_timer  The FuriHalCortexTimer
+ *
+ * @return     true if expired
+ */
+bool furi_hal_cortex_timer_is_expired(FuriHalCortexTimer cortex_timer);
+
+/** Wait for timer expire
+ *
+ * @param[in]  cortex_timer  The FuriHalCortexTimer
+ */
+void furi_hal_cortex_timer_wait(FuriHalCortexTimer cortex_timer);
+
 #ifdef __cplusplus
 }
 #endif