[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
This commit is contained in:
あく 2021-10-04 10:01:41 +03:00 committed by GitHub
parent a7edebce69
commit 832fb1b795
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 151 additions and 28 deletions

View File

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

View File

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

View File

@ -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_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow);
hal_gpio_write(&gpio_cc1101_g0, true); hal_gpio_write(&gpio_cc1101_g0, true);
furi_hal_power_suppress_charge_enter();
if(furi_hal_subghz_tx()) { if(furi_hal_subghz_tx()) {
printf("Transmitting at frequency %lu Hz\r\n", frequency); printf("Transmitting at frequency %lu Hz\r\n", frequency);
printf("Press CTRL+C to stop\r\n"); 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_set_path(FuriHalSubGhzPathIsolate);
furi_hal_subghz_sleep(); furi_hal_subghz_sleep();
furi_hal_power_suppress_charge_exit();
} }
void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { 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("Receiving at frequency %lu Hz\r\n", frequency);
printf("Press CTRL+C to stop\r\n"); printf("Press CTRL+C to stop\r\n");
furi_hal_power_suppress_charge_enter();
furi_hal_subghz_rx(); furi_hal_subghz_rx();
while(!cli_cmd_interrupt_received(cli)) { 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); fflush(stdout);
} }
furi_hal_power_suppress_charge_exit();
furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate); furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
furi_hal_subghz_sleep(); 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_reset();
furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async); furi_hal_subghz_load_preset(FuriHalSubGhzPresetOok650Async);
frequency = furi_hal_subghz_set_frequency_and_path(frequency); 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); 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))) { 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_stop_async_tx();
furi_hal_subghz_sleep(); furi_hal_subghz_sleep();
furi_hal_power_suppress_charge_exit();
subghz_decoder_princeton_free(protocol); subghz_decoder_princeton_free(protocol);
subghz_protocol_encoder_common_free(encoder); 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); frequency = furi_hal_subghz_set_frequency_and_path(frequency);
hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
furi_hal_power_suppress_charge_enter();
// Prepare and start RX // Prepare and start RX
furi_hal_subghz_start_async_rx(subghz_cli_command_rx_callback, instance); 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_stop_async_rx();
furi_hal_subghz_sleep(); furi_hal_subghz_sleep();
furi_hal_power_suppress_charge_exit();
printf("\r\nPackets recieved %u\r\n", instance->packet_count); printf("\r\nPackets recieved %u\r\n", instance->packet_count);
// Cleanup // Cleanup

View File

@ -16,13 +16,15 @@
#include <furi.h> #include <furi.h>
typedef struct { typedef struct {
volatile uint32_t insomnia; volatile uint8_t insomnia;
volatile uint32_t deep_insomnia; volatile uint8_t deep_insomnia;
volatile uint8_t suppress_charge;
} FuriHalPower; } FuriHalPower;
static volatile FuriHalPower furi_hal_power = { static volatile FuriHalPower furi_hal_power = {
.insomnia = 0, .insomnia = 0,
.deep_insomnia = 1, .deep_insomnia = 1,
.suppress_charge = 0,
}; };
const ParamCEDV cedv = { const ParamCEDV cedv = {
@ -80,11 +82,15 @@ uint16_t furi_hal_power_insomnia_level() {
} }
void furi_hal_power_insomnia_enter() { void furi_hal_power_insomnia_enter() {
vTaskSuspendAll();
furi_hal_power.insomnia++; furi_hal_power.insomnia++;
xTaskResumeAll();
} }
void furi_hal_power_insomnia_exit() { void furi_hal_power_insomnia_exit() {
vTaskSuspendAll();
furi_hal_power.insomnia--; furi_hal_power.insomnia--;
xTaskResumeAll();
} }
bool furi_hal_power_sleep_available() { 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(){ void furi_hal_power_disable_external_3_3v(){
LL_GPIO_ResetOutputPin(PERIPH_POWER_GPIO_Port, PERIPH_POWER_Pin); 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();
}
}

View File

@ -5,70 +5,88 @@
#include <stddef.h> #include <stddef.h>
/** Get flash base address /** Get flash base address
* @return pointer to flash base *
* @return pointer to flash base
*/ */
size_t furi_hal_flash_get_base(); size_t furi_hal_flash_get_base();
/** Get flash read block size /** Get flash read block size
* @return size in bytes *
* @return size in bytes
*/ */
size_t furi_hal_flash_get_read_block_size(); size_t furi_hal_flash_get_read_block_size();
/** Get flash write block size /** Get flash write block size
* @return size in bytes *
* @return size in bytes
*/ */
size_t furi_hal_flash_get_write_block_size(); size_t furi_hal_flash_get_write_block_size();
/** Get flash page size /** Get flash page size
* @return size in bytes *
* @return size in bytes
*/ */
size_t furi_hal_flash_get_page_size(); size_t furi_hal_flash_get_page_size();
/** Get expected flash cycles count /** 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(); size_t furi_hal_flash_get_cycles_count();
/** Get free flash start address /** 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(); const void* furi_hal_flash_get_free_start_address();
/** Get free flash end 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(); const void* furi_hal_flash_get_free_end_address();
/** Get first free page start 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(); size_t furi_hal_flash_get_free_page_start_address();
/** Get free page count /** Get free page count
* @return free page count *
* @return free page count
*/ */
size_t furi_hal_flash_get_free_page_count(); size_t furi_hal_flash_get_free_page_count();
/* /** Erase Flash
* Erase Flash *
* Locking operation, uses HSEM to manage shared access. * 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); 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. * 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); 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. * 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); bool furi_hal_flash_write_dword_from(size_t address, size_t source_address);

View File

@ -16,13 +16,15 @@
#include <furi.h> #include <furi.h>
typedef struct { typedef struct {
volatile uint32_t insomnia; volatile uint8_t insomnia;
volatile uint32_t deep_insomnia; volatile uint8_t deep_insomnia;
volatile uint8_t suppress_charge;
} FuriHalPower; } FuriHalPower;
static volatile FuriHalPower furi_hal_power = { static volatile FuriHalPower furi_hal_power = {
.insomnia = 0, .insomnia = 0,
.deep_insomnia = 1, .deep_insomnia = 1,
.suppress_charge = 0,
}; };
const ParamCEDV cedv = { const ParamCEDV cedv = {
@ -80,11 +82,15 @@ uint16_t furi_hal_power_insomnia_level() {
} }
void furi_hal_power_insomnia_enter() { void furi_hal_power_insomnia_enter() {
vTaskSuspendAll();
furi_hal_power.insomnia++; furi_hal_power.insomnia++;
xTaskResumeAll();
} }
void furi_hal_power_insomnia_exit() { void furi_hal_power_insomnia_exit() {
vTaskSuspendAll();
furi_hal_power.insomnia--; furi_hal_power.insomnia--;
xTaskResumeAll();
} }
bool furi_hal_power_sleep_available() { 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(){ void furi_hal_power_disable_external_3_3v(){
LL_GPIO_ResetOutputPin(PERIPH_POWER_GPIO_Port, PERIPH_POWER_Pin); 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();
}
}

View File

@ -157,6 +157,16 @@ void furi_hal_power_enable_external_3_3v();
*/ */
void furi_hal_power_disable_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 #ifdef __cplusplus
} }
#endif #endif

View File

@ -91,6 +91,16 @@ bool bq25896_is_charging() {
return bq25896_regs.r0B.CHRG_STAT != ChrgStatNo; 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() { void bq25896_enable_otg() {
bq25896_regs.r03.OTG_CONFIG = 1; bq25896_regs.r03.OTG_CONFIG = 1;
bq25896_write_reg(0x03, (uint8_t*)&bq25896_regs.r03); bq25896_write_reg(0x03, (uint8_t*)&bq25896_regs.r03);

View File

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