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

[FL-1228] FuriHal: add charge suppress API. (#743)

* FuriHal: add charge suppress API.

* FuriHal: add guards to insomnia and charge suppress routines.

* FuriHal: proper API for scheduler in power.

* FuriHal: move charging control from critical section, fix deadlock.

* Gui: use FreeRTOS native timers controls for IconAnimation, fix crash on animation start stop
あく 4 лет назад
Родитель
Сommit
832fb1b795

+ 5 - 3
applications/gui/icon_animation.c

@@ -2,6 +2,7 @@
 #include "icon_i.h"
 
 #include <furi.h>
+#include <timers.h>
 
 IconAnimation* icon_animation_alloc(const Icon* icon) {
     furi_assert(icon);
@@ -63,8 +64,9 @@ void icon_animation_start(IconAnimation* instance) {
     if(!instance->animating) {
         instance->animating = true;
         furi_check(
-            osTimerStart(instance->timer, (osKernelGetTickFreq() / instance->icon->frame_rate)) ==
-            osOK);
+            xTimerChangePeriod(
+                instance->timer, (osKernelGetTickFreq() / instance->icon->frame_rate), 0) ==
+            pdPASS);
     }
 }
 
@@ -72,7 +74,7 @@ void icon_animation_stop(IconAnimation* instance) {
     furi_assert(instance);
     if(instance->animating) {
         instance->animating = false;
-        furi_check(osTimerStop(instance->timer) == osOK);
+        furi_check(xTimerStop(instance->timer, 0) == pdPASS);
         instance->frame = 0;
     }
 }

+ 4 - 0
applications/subghz/subghz.c

@@ -260,8 +260,12 @@ int32_t subghz_app(void* p) {
         scene_manager_next_scene(subghz->scene_manager, SubGhzSceneStart);
     }
 
+    furi_hal_power_suppress_charge_enter();
+
     view_dispatcher_run(subghz->view_dispatcher);
 
+    furi_hal_power_suppress_charge_exit();
+
     subghz_free(subghz);
 
     return 0;

+ 17 - 0
applications/subghz/subghz_cli.c

@@ -48,6 +48,8 @@ void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) {
     hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
     hal_gpio_write(&gpio_cc1101_g0, true);
 
+    furi_hal_power_suppress_charge_enter();
+
     if(furi_hal_subghz_tx()) {
         printf("Transmitting at frequency %lu Hz\r\n", frequency);
         printf("Press CTRL+C to stop\r\n");
@@ -60,6 +62,8 @@ void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) {
 
     furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
     furi_hal_subghz_sleep();
+
+    furi_hal_power_suppress_charge_exit();
 }
 
 void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) {
@@ -86,6 +90,8 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) {
     printf("Receiving at frequency %lu Hz\r\n", frequency);
     printf("Press CTRL+C to stop\r\n");
 
+    furi_hal_power_suppress_charge_enter();
+
     furi_hal_subghz_rx();
 
     while(!cli_cmd_interrupt_received(cli)) {
@@ -94,6 +100,8 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) {
         fflush(stdout);
     }
 
+    furi_hal_power_suppress_charge_exit();
+
     furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
     furi_hal_subghz_sleep();
 }
@@ -143,6 +151,9 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) {
     furi_hal_subghz_reset();
     furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
     frequency = furi_hal_subghz_set_frequency_and_path(frequency);
+
+    furi_hal_power_suppress_charge_enter();
+
     furi_hal_subghz_start_async_tx(subghz_protocol_encoder_common_yield, encoder);
 
     while(!(furi_hal_subghz_is_async_tx_complete() || cli_cmd_interrupt_received(cli))) {
@@ -153,6 +164,8 @@ void subghz_cli_command_tx(Cli* cli, string_t args, void* context) {
     furi_hal_subghz_stop_async_tx();
     furi_hal_subghz_sleep();
 
+    furi_hal_power_suppress_charge_exit();
+
     subghz_decoder_princeton_free(protocol);
     subghz_protocol_encoder_common_free(encoder);
 }
@@ -218,6 +231,8 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
     frequency = furi_hal_subghz_set_frequency_and_path(frequency);
     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
 
+    furi_hal_power_suppress_charge_enter();
+
     // Prepare and start RX
     furi_hal_subghz_start_async_rx(subghz_cli_command_rx_callback, instance);
 
@@ -243,6 +258,8 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) {
     furi_hal_subghz_stop_async_rx();
     furi_hal_subghz_sleep();
 
+    furi_hal_power_suppress_charge_exit();
+
     printf("\r\nPackets recieved %u\r\n", instance->packet_count);
 
     // Cleanup

+ 30 - 2
firmware/targets/f6/furi-hal/furi-hal-power.c

@@ -16,13 +16,15 @@
 #include <furi.h>
 
 typedef struct {
-    volatile uint32_t insomnia;
-    volatile uint32_t deep_insomnia;
+    volatile uint8_t insomnia;
+    volatile uint8_t deep_insomnia;
+    volatile uint8_t suppress_charge;
 } FuriHalPower;
 
 static volatile FuriHalPower furi_hal_power = {
     .insomnia = 0,
     .deep_insomnia = 1,
+    .suppress_charge = 0,
 };
 
 const ParamCEDV cedv = {
@@ -80,11 +82,15 @@ uint16_t furi_hal_power_insomnia_level() {
 }
 
 void furi_hal_power_insomnia_enter() {
+    vTaskSuspendAll();
     furi_hal_power.insomnia++;
+    xTaskResumeAll();
 }
 
 void furi_hal_power_insomnia_exit() {
+    vTaskSuspendAll();
     furi_hal_power.insomnia--;
+    xTaskResumeAll();
 }
 
 bool furi_hal_power_sleep_available() {
@@ -282,3 +288,25 @@ void furi_hal_power_enable_external_3_3v(){
 void furi_hal_power_disable_external_3_3v(){
     LL_GPIO_ResetOutputPin(PERIPH_POWER_GPIO_Port, PERIPH_POWER_Pin);
 }
+
+void furi_hal_power_suppress_charge_enter() {
+    vTaskSuspendAll();
+    bool disable_charging = furi_hal_power.suppress_charge == 0;
+    furi_hal_power.suppress_charge++;
+    xTaskResumeAll();
+
+    if (disable_charging) {
+        bq25896_disable_charging();
+    }
+}
+
+void furi_hal_power_suppress_charge_exit() {
+    vTaskSuspendAll();
+    furi_hal_power.suppress_charge--;
+    bool enable_charging = furi_hal_power.suppress_charge == 0;
+    xTaskResumeAll();
+
+    if (enable_charging) {
+        bq25896_enable_charging();
+    }
+}

+ 39 - 21
firmware/targets/f7/furi-hal/furi-hal-flash.h

@@ -5,70 +5,88 @@
 #include <stddef.h>
 
 /** Get flash base address
- * @return pointer to flash base
+ *
+ * @return     pointer to flash base
  */
 size_t furi_hal_flash_get_base();
 
 /** Get flash read block size
- * @return size in bytes
+ *
+ * @return     size in bytes
  */
 size_t furi_hal_flash_get_read_block_size();
 
 /** Get flash write block size
- * @return size in bytes
+ *
+ * @return     size in bytes
  */
 size_t furi_hal_flash_get_write_block_size();
 
 /** Get flash page size
- * @return size in bytes
+ *
+ * @return     size in bytes
  */
 size_t furi_hal_flash_get_page_size();
 
 /** Get expected flash cycles count
- * @return count of erase-write operations 
+ *
+ * @return     count of erase-write operations
  */
 size_t furi_hal_flash_get_cycles_count();
 
 /** Get free flash start address
- * @return pointer to free region start
+ *
+ * @return     pointer to free region start
  */
 const void* furi_hal_flash_get_free_start_address();
 
 /** Get free flash end address
- * @return pointer to free region end
+ *
+ * @return     pointer to free region end
  */
 const void* furi_hal_flash_get_free_end_address();
 
 /** Get first free page start address
- * @return first free page memory address
+ *
+ * @return     first free page memory address
  */
 size_t furi_hal_flash_get_free_page_start_address();
 
 /** Get free page count
- * @return free page count
+ *
+ * @return     free page count
  */
 size_t furi_hal_flash_get_free_page_count();
 
-/*
- * Erase Flash
+/** Erase Flash
+ *
  * Locking operation, uses HSEM to manage shared access.
- * @param page, page number
- * @param count, page count to erase
+ *
+ * @param      page   page number
+ * @param      count  page count to erase
+ *
+ * @return     true on success
  */
 bool furi_hal_flash_erase(uint8_t page, uint8_t count);
 
-/*
- * Write double word (64 bits)
+/** Write double word (64 bits)
+ *
  * Locking operation, uses HSEM to manage shared access.
- * @param address - destination address, must be double word aligned.
- * @param data - data to write
+ *
+ * @param      address  destination address, must be double word aligned.
+ * @param      data     data to write
+ *
+ * @return     true on success
  */
 bool furi_hal_flash_write_dword(size_t address, uint64_t data);
 
-/*
- * Write double word (64 bits) from address
+/** Write double word (64 bits) from address
+ *
  * Locking operation, uses HSEM to manage shared access.
- * @param address - destination address, must be block aligned
- * @param source_address - source address
+ *
+ * @param      address         destination address, must be block aligned
+ * @param      source_address  source address
+ *
+ * @return     true on success
  */
 bool furi_hal_flash_write_dword_from(size_t address, size_t source_address);

+ 30 - 2
firmware/targets/f7/furi-hal/furi-hal-power.c

@@ -16,13 +16,15 @@
 #include <furi.h>
 
 typedef struct {
-    volatile uint32_t insomnia;
-    volatile uint32_t deep_insomnia;
+    volatile uint8_t insomnia;
+    volatile uint8_t deep_insomnia;
+    volatile uint8_t suppress_charge;
 } FuriHalPower;
 
 static volatile FuriHalPower furi_hal_power = {
     .insomnia = 0,
     .deep_insomnia = 1,
+    .suppress_charge = 0,
 };
 
 const ParamCEDV cedv = {
@@ -80,11 +82,15 @@ uint16_t furi_hal_power_insomnia_level() {
 }
 
 void furi_hal_power_insomnia_enter() {
+    vTaskSuspendAll();
     furi_hal_power.insomnia++;
+    xTaskResumeAll();
 }
 
 void furi_hal_power_insomnia_exit() {
+    vTaskSuspendAll();
     furi_hal_power.insomnia--;
+    xTaskResumeAll();
 }
 
 bool furi_hal_power_sleep_available() {
@@ -282,3 +288,25 @@ void furi_hal_power_enable_external_3_3v(){
 void furi_hal_power_disable_external_3_3v(){
     LL_GPIO_ResetOutputPin(PERIPH_POWER_GPIO_Port, PERIPH_POWER_Pin);
 }
+
+void furi_hal_power_suppress_charge_enter() {
+    vTaskSuspendAll();
+    bool disable_charging = furi_hal_power.suppress_charge == 0;
+    furi_hal_power.suppress_charge++;
+    xTaskResumeAll();
+
+    if (disable_charging) {
+        bq25896_disable_charging();
+    }
+}
+
+void furi_hal_power_suppress_charge_exit() {
+    vTaskSuspendAll();
+    furi_hal_power.suppress_charge--;
+    bool enable_charging = furi_hal_power.suppress_charge == 0;
+    xTaskResumeAll();
+
+    if (enable_charging) {
+        bq25896_enable_charging();
+    }
+}

+ 10 - 0
firmware/targets/furi-hal-include/furi-hal-power.h

@@ -157,6 +157,16 @@ void furi_hal_power_enable_external_3_3v();
  */
 void furi_hal_power_disable_external_3_3v();
 
+/** Enter supress charge mode.
+ *
+ * Use this function when your application need clean power supply.
+ */
+void furi_hal_power_suppress_charge_enter();
+
+/** Exit supress charge mode
+ */
+void furi_hal_power_suppress_charge_exit();
+
 #ifdef __cplusplus
 }
 #endif

+ 10 - 0
lib/drivers/bq25896.c

@@ -91,6 +91,16 @@ bool bq25896_is_charging() {
     return bq25896_regs.r0B.CHRG_STAT != ChrgStatNo;
 }
 
+void bq25896_enable_charging() {
+    bq25896_regs.r03.CHG_CONFIG = 1;
+    bq25896_write_reg(0x03, (uint8_t*)&bq25896_regs.r03);
+}
+
+void bq25896_disable_charging() {
+    bq25896_regs.r03.CHG_CONFIG = 0;
+    bq25896_write_reg(0x03, (uint8_t*)&bq25896_regs.r03);
+}
+
 void bq25896_enable_otg() {
     bq25896_regs.r03.OTG_CONFIG = 1;
     bq25896_write_reg(0x03, (uint8_t*)&bq25896_regs.r03);

+ 6 - 0
lib/drivers/bq25896.h

@@ -12,6 +12,12 @@ void bq25896_poweroff();
 /** Is currently charging */
 bool bq25896_is_charging();
 
+/** Enable charging */
+void bq25896_enable_charging();
+
+/** Disable charging */
+void bq25896_disable_charging();
+
 /** Enable otg */
 void bq25896_enable_otg();