From 0eac917f911c717071a109f916a2aedaa40d68cf Mon Sep 17 00:00:00 2001 From: Nikolay Minaylov Date: Fri, 29 Apr 2022 15:02:17 +0300 Subject: [PATCH 1/4] [FL-2163] CLI: Separate session from CLI service (#1130) * CLI: session refactoring * Added forgotten define * Desktop lock state save * Dolphin: use proper type for value returned by dolphin_state_xp_to_levelup Co-authored-by: Aleksandr Kutuzov --- applications/cli/cli.c | 167 +++++++++++----- applications/cli/cli.h | 23 ++- applications/cli/cli_i.h | 17 +- .../cli/cli_vcp.c | 188 +++++++++--------- applications/cli/cli_vcp.h | 18 ++ .../desktop_settings/desktop_settings.h | 3 +- applications/desktop/helpers/pin_lock.c | 37 +++- applications/desktop/helpers/pin_lock.h | 4 +- .../desktop/scenes/desktop_scene_lock_menu.c | 2 +- .../desktop/scenes/desktop_scene_pin_input.c | 2 +- applications/dolphin/helpers/dolphin_state.c | 2 +- applications/gpio/usb_uart_bridge.c | 43 ++-- applications/rpc/rpc_cli.c | 4 +- applications/subghz/helpers/subghz_chat.c | 8 +- applications/subghz/helpers/subghz_chat.h | 3 +- applications/subghz/subghz_cli.c | 2 +- firmware/targets/f7/furi_hal/furi_hal_usb.c | 1 - .../targets/f7/furi_hal/furi_hal_usb_cdc.c | 3 + firmware/targets/furi_hal_include/furi_hal.h | 1 - .../targets/furi_hal_include/furi_hal_vcp.h | 63 ------ 20 files changed, 348 insertions(+), 243 deletions(-) rename firmware/targets/f7/furi_hal/furi_hal_vcp.c => applications/cli/cli_vcp.c (69%) create mode 100644 applications/cli/cli_vcp.h delete mode 100644 firmware/targets/furi_hal_include/furi_hal_vcp.h diff --git a/applications/cli/cli.c b/applications/cli/cli.c index 091d37f8b..4e200d6bd 100644 --- a/applications/cli/cli.c +++ b/applications/cli/cli.c @@ -1,9 +1,11 @@ #include "cli_i.h" #include "cli_commands.h" - +#include "cli_vcp.h" #include #include +#define TAG "CliSrv" + Cli* cli_alloc() { Cli* cli = malloc(sizeof(Cli)); @@ -12,55 +14,78 @@ Cli* cli_alloc() { string_init(cli->last_line); string_init(cli->line); + cli->session = NULL; + cli->mutex = osMutexNew(NULL); furi_check(cli->mutex); + cli->idle_sem = osSemaphoreNew(1, 0, NULL); + return cli; } -void cli_free(Cli* cli) { +void cli_putc(Cli* cli, char c) { furi_assert(cli); - - string_clear(cli->last_line); - string_clear(cli->line); - - CliCommandTree_clear(cli->commands); - - free(cli); -} - -void cli_putc(char c) { - furi_hal_vcp_tx((uint8_t*)&c, 1); + if(cli->session != NULL) { + cli->session->tx((uint8_t*)&c, 1); + } } char cli_getc(Cli* cli) { furi_assert(cli); - char c; - if(furi_hal_vcp_rx((uint8_t*)&c, 1) == 0) { + char c = 0; + if(cli->session != NULL) { + if(cli->session->rx((uint8_t*)&c, 1, osWaitForever) == 0) { + cli_reset(cli); + } + } else { cli_reset(cli); } return c; } -void cli_stdout_callback(void* _cookie, const char* data, size_t size) { - furi_hal_vcp_tx((const uint8_t*)data, size); -} - void cli_write(Cli* cli, const uint8_t* buffer, size_t size) { - return furi_hal_vcp_tx(buffer, size); + furi_assert(cli); + if(cli->session != NULL) { + cli->session->tx(buffer, size); + } } size_t cli_read(Cli* cli, uint8_t* buffer, size_t size) { - return furi_hal_vcp_rx(buffer, size); + furi_assert(cli); + if(cli->session != NULL) { + return cli->session->rx(buffer, size, osWaitForever); + } else { + return 0; + } +} + +size_t cli_read_timeout(Cli* cli, uint8_t* buffer, size_t size, uint32_t timeout) { + furi_assert(cli); + if(cli->session != NULL) { + return cli->session->rx(buffer, size, timeout); + } else { + return 0; + } } bool cli_cmd_interrupt_received(Cli* cli) { + furi_assert(cli); char c = '\0'; - if(furi_hal_vcp_rx_with_timeout((uint8_t*)&c, 1, 0) == 1) { - return c == CliSymbolAsciiETX; - } else { - return false; + if(cli->session != NULL) { + if(cli->session->rx((uint8_t*)&c, 1, 0) == 1) { + return c == CliSymbolAsciiETX; + } } + return false; +} + +bool cli_is_connected(Cli* cli) { + furi_assert(cli); + if(cli->session != NULL) { + return (cli->session->is_connected()); + } + return false; } void cli_print_usage(const char* cmd, const char* usage, const char* arg) { @@ -139,7 +164,7 @@ static void cli_handle_backspace(Cli* cli) { cli->cursor_position--; } else { - cli_putc(CliSymbolAsciiBell); + cli_putc(cli, CliSymbolAsciiBell); } } @@ -210,7 +235,7 @@ static void cli_handle_enter(Cli* cli) { printf( "`%s` command not found, use `help` or `?` to list all available commands", string_get_cstr(command)); - cli_putc(CliSymbolAsciiBell); + cli_putc(cli, CliSymbolAsciiBell); } furi_check(osMutexRelease(cli->mutex) == osOK); @@ -301,43 +326,43 @@ static void cli_handle_escape(Cli* cli, char c) { } void cli_process_input(Cli* cli) { - char c = cli_getc(cli); - size_t r; + char in_chr = cli_getc(cli); + size_t rx_len; - if(c == CliSymbolAsciiTab) { + if(in_chr == CliSymbolAsciiTab) { cli_handle_autocomplete(cli); - } else if(c == CliSymbolAsciiSOH) { + } else if(in_chr == CliSymbolAsciiSOH) { osDelay(33); // We are too fast, Minicom is not ready yet cli_motd(); cli_prompt(cli); - } else if(c == CliSymbolAsciiETX) { + } else if(in_chr == CliSymbolAsciiETX) { cli_reset(cli); cli_prompt(cli); - } else if(c == CliSymbolAsciiEOT) { + } else if(in_chr == CliSymbolAsciiEOT) { cli_reset(cli); - } else if(c == CliSymbolAsciiEsc) { - r = furi_hal_vcp_rx((uint8_t*)&c, 1); - if(r && c == '[') { - furi_hal_vcp_rx((uint8_t*)&c, 1); - cli_handle_escape(cli, c); + } else if(in_chr == CliSymbolAsciiEsc) { + rx_len = cli_read(cli, (uint8_t*)&in_chr, 1); + if((rx_len > 0) && (in_chr == '[')) { + cli_read(cli, (uint8_t*)&in_chr, 1); + cli_handle_escape(cli, in_chr); } else { - cli_putc(CliSymbolAsciiBell); + cli_putc(cli, CliSymbolAsciiBell); } - } else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) { + } else if(in_chr == CliSymbolAsciiBackspace || in_chr == CliSymbolAsciiDel) { cli_handle_backspace(cli); - } else if(c == CliSymbolAsciiCR) { + } else if(in_chr == CliSymbolAsciiCR) { cli_handle_enter(cli); - } else if(c >= 0x20 && c < 0x7F) { + } else if(in_chr >= 0x20 && in_chr < 0x7F) { if(cli->cursor_position == string_size(cli->line)) { - string_push_back(cli->line, c); - cli_putc(c); + string_push_back(cli->line, in_chr); + cli_putc(cli, in_chr); } else { // ToDo: better way? string_t temp; string_init(temp); string_reserve(temp, string_size(cli->line) + 1); string_set_strn(temp, string_get_cstr(cli->line), cli->cursor_position); - string_push_back(temp, c); + string_push_back(temp, in_chr); string_cat_str(temp, string_get_cstr(cli->line) + cli->cursor_position); // cli->line is cleared and temp's buffer moved to cli->line @@ -345,12 +370,12 @@ void cli_process_input(Cli* cli) { // NO MEMORY LEAK, STOP REPORTING IT // Print character in replace mode - printf("\e[4h%c\e[4l", c); + printf("\e[4h%c\e[4l", in_chr); fflush(stdout); } cli->cursor_position++; } else { - cli_putc(CliSymbolAsciiBell); + cli_putc(cli, CliSymbolAsciiBell); } } @@ -398,19 +423,59 @@ void cli_delete_command(Cli* cli, const char* name) { string_clear(name_str); } +void cli_session_open(Cli* cli, void* session) { + furi_assert(cli); + + furi_check(osMutexAcquire(cli->mutex, osWaitForever) == osOK); + cli->session = session; + if(cli->session != NULL) { + cli->session->init(); + furi_stdglue_set_thread_stdout_callback(cli->session->tx_stdout); + } else { + furi_stdglue_set_thread_stdout_callback(NULL); + } + osSemaphoreRelease(cli->idle_sem); + furi_check(osMutexRelease(cli->mutex) == osOK); +} + +void cli_session_close(Cli* cli) { + furi_assert(cli); + + furi_check(osMutexAcquire(cli->mutex, osWaitForever) == osOK); + if(cli->session != NULL) { + cli->session->deinit(); + } + cli->session = NULL; + furi_stdglue_set_thread_stdout_callback(NULL); + furi_check(osMutexRelease(cli->mutex) == osOK); +} + int32_t cli_srv(void* p) { Cli* cli = cli_alloc(); - furi_hal_vcp_init(); - // Init basic cli commands cli_commands_init(cli); furi_record_create("cli", cli); - furi_stdglue_set_thread_stdout_callback(cli_stdout_callback); + if(cli->session != NULL) { + furi_stdglue_set_thread_stdout_callback(cli->session->tx_stdout); + } else { + furi_stdglue_set_thread_stdout_callback(NULL); + } + + if(furi_hal_rtc_get_boot_mode() == FuriHalRtcBootModeNormal) { + cli_session_open(cli, &cli_vcp); + } else { + FURI_LOG_W(TAG, "Skipped CLI session open: device in special startup mode"); + } + while(1) { - cli_process_input(cli); + if(cli->session != NULL) { + cli_process_input(cli); + } else { + furi_check(osSemaphoreAcquire(cli->idle_sem, osWaitForever) == osOK); + } } return 0; diff --git a/applications/cli/cli.h b/applications/cli/cli.h index 1f1b61a24..29f27392c 100644 --- a/applications/cli/cli.h +++ b/applications/cli/cli.h @@ -73,17 +73,28 @@ void cli_print_usage(const char* cmd, const char* usage, const char* arg); */ void cli_delete_command(Cli* cli, const char* name); -/** Read from terminal Do it only from inside of cli call. +/** Read from terminal * * @param cli Cli instance * @param buffer pointer to buffer * @param size size of buffer in bytes * - * @return bytes written + * @return bytes read */ size_t cli_read(Cli* cli, uint8_t* buffer, size_t size); -/** Not blocking check for interrupt command received +/** Non-blocking read from terminal + * + * @param cli Cli instance + * @param buffer pointer to buffer + * @param size size of buffer in bytes + * @param timeout timeout value in ms + * + * @return bytes read + */ +size_t cli_read_timeout(Cli* cli, uint8_t* buffer, size_t size, uint32_t timeout); + +/** Non-blocking check for interrupt command received * * @param cli Cli instance * @@ -111,6 +122,12 @@ char cli_getc(Cli* cli); */ void cli_nl(); +void cli_session_open(Cli* cli, void* session); + +void cli_session_close(Cli* cli); + +bool cli_is_connected(Cli* cli); + #ifdef __cplusplus } #endif diff --git a/applications/cli/cli_i.h b/applications/cli/cli_i.h index c645f1a3b..feb3bcb72 100755 --- a/applications/cli/cli_i.h +++ b/applications/cli/cli_i.h @@ -18,6 +18,17 @@ typedef struct { uint32_t flags; } CliCommand; +typedef struct CliSession CliSession; + +struct CliSession { + void (*init)(void); + void (*deinit)(void); + size_t (*rx)(uint8_t* buffer, size_t size, uint32_t timeout); + void (*tx)(const uint8_t* buffer, size_t size); + void (*tx_stdout)(void* _cookie, const char* data, size_t size); + bool (*is_connected)(void); +}; + BPTREE_DEF2( CliCommandTree, CLI_COMMANDS_TREE_RANK, @@ -31,18 +42,18 @@ BPTREE_DEF2( struct Cli { CliCommandTree_t commands; osMutexId_t mutex; + osSemaphoreId_t idle_sem; string_t last_line; string_t line; + CliSession* session; size_t cursor_position; }; Cli* cli_alloc(); -void cli_free(Cli* cli); - void cli_reset(Cli* cli); -void cli_putc(char c); +void cli_putc(Cli* cli, char c); void cli_stdout_callback(void* _cookie, const char* data, size_t size); diff --git a/firmware/targets/f7/furi_hal/furi_hal_vcp.c b/applications/cli/cli_vcp.c similarity index 69% rename from firmware/targets/f7/furi_hal/furi_hal_vcp.c rename to applications/cli/cli_vcp.c index ac8ee7305..f570aee15 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_vcp.c +++ b/applications/cli/cli_vcp.c @@ -2,8 +2,9 @@ #include #include #include +#include "cli_i.h" -#define TAG "FuriHalVcp" +#define TAG "CliVcp" #define USB_CDC_PKT_LEN CDC_DATA_SZ #define VCP_RX_BUF_SIZE (USB_CDC_PKT_LEN * 3) @@ -12,19 +13,18 @@ #define VCP_IF_NUM 0 typedef enum { - VcpEvtEnable = (1 << 0), - VcpEvtDisable = (1 << 1), - VcpEvtConnect = (1 << 2), - VcpEvtDisconnect = (1 << 3), - VcpEvtStreamRx = (1 << 4), - VcpEvtRx = (1 << 5), - VcpEvtStreamTx = (1 << 6), - VcpEvtTx = (1 << 7), + VcpEvtStop = (1 << 0), + VcpEvtConnect = (1 << 1), + VcpEvtDisconnect = (1 << 2), + VcpEvtStreamRx = (1 << 3), + VcpEvtRx = (1 << 4), + VcpEvtStreamTx = (1 << 5), + VcpEvtTx = (1 << 6), } WorkerEvtFlags; -#define VCP_THREAD_FLAG_ALL \ - (VcpEvtEnable | VcpEvtDisable | VcpEvtConnect | VcpEvtDisconnect | VcpEvtRx | VcpEvtTx | \ - VcpEvtStreamRx | VcpEvtStreamTx) +#define VCP_THREAD_FLAG_ALL \ + (VcpEvtStop | VcpEvtConnect | VcpEvtDisconnect | VcpEvtRx | VcpEvtTx | VcpEvtStreamRx | \ + VcpEvtStreamTx) typedef struct { FuriThread* thread; @@ -33,9 +33,12 @@ typedef struct { StreamBufferHandle_t rx_stream; volatile bool connected; + volatile bool running; + + FuriHalUsbInterface* usb_if_prev; uint8_t data_buffer[USB_CDC_PKT_LEN]; -} FuriHalVcp; +} CliVcp; static int32_t vcp_worker(void* context); static void vcp_on_cdc_tx_complete(void* context); @@ -51,25 +54,23 @@ static CdcCallbacks cdc_cb = { NULL, }; -static FuriHalVcp* vcp = NULL; +static CliVcp* vcp = NULL; static const uint8_t ascii_soh = 0x01; static const uint8_t ascii_eot = 0x04; -void furi_hal_vcp_init() { - vcp = malloc(sizeof(FuriHalVcp)); +static void cli_vcp_init() { + if(vcp == NULL) { + vcp = malloc(sizeof(CliVcp)); + vcp->tx_stream = xStreamBufferCreate(VCP_TX_BUF_SIZE, 1); + vcp->rx_stream = xStreamBufferCreate(VCP_RX_BUF_SIZE, 1); + } + furi_assert(vcp->thread == NULL); + vcp->connected = false; - vcp->tx_stream = xStreamBufferCreate(VCP_TX_BUF_SIZE, 1); - vcp->rx_stream = xStreamBufferCreate(VCP_RX_BUF_SIZE, 1); - - if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) { - FURI_LOG_W(TAG, "Skipped worker init: device in special startup mode"); - return; - } - vcp->thread = furi_thread_alloc(); - furi_thread_set_name(vcp->thread, "VcpDriver"); + furi_thread_set_name(vcp->thread, "CliVcpWorker"); furi_thread_set_stack_size(vcp->thread, 1024); furi_thread_set_callback(vcp->thread, vcp_worker); furi_thread_start(vcp->thread); @@ -77,48 +78,35 @@ void furi_hal_vcp_init() { FURI_LOG_I(TAG, "Init OK"); } +static void cli_vcp_deinit() { + osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtStop); + furi_thread_join(vcp->thread); + furi_thread_free(vcp->thread); + vcp->thread = NULL; +} + static int32_t vcp_worker(void* context) { - bool enabled = true; - bool tx_idle = false; + bool tx_idle = true; size_t missed_rx = 0; uint8_t last_tx_pkt_len = 0; - furi_hal_usb_set_config(&usb_cdc_single, NULL); + // Switch USB to VCP mode (if it is not set yet) + vcp->usb_if_prev = furi_hal_usb_get_config(); + if((vcp->usb_if_prev != &usb_cdc_single) && (vcp->usb_if_prev != &usb_cdc_dual)) { + furi_hal_usb_set_config(&usb_cdc_single, NULL); + } furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb, NULL); + FURI_LOG_D(TAG, "Start"); + vcp->running = true; + while(1) { uint32_t flags = osThreadFlagsWait(VCP_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever); furi_assert((flags & osFlagsError) == 0); - // VCP enabled - if((flags & VcpEvtEnable) && !enabled) { -#ifdef FURI_HAL_USB_VCP_DEBUG - FURI_LOG_D(TAG, "Enable"); -#endif - flags |= VcpEvtTx; - furi_hal_cdc_set_callbacks(VCP_IF_NUM, &cdc_cb, NULL); - enabled = true; - furi_hal_cdc_receive(VCP_IF_NUM, vcp->data_buffer, USB_CDC_PKT_LEN); // flush Rx buffer - if(furi_hal_cdc_get_ctrl_line_state(VCP_IF_NUM) & (1 << 0)) { - vcp->connected = true; - xStreamBufferSend(vcp->rx_stream, &ascii_soh, 1, osWaitForever); - } - } - - // VCP disabled - if((flags & VcpEvtDisable) && enabled) { -#ifdef FURI_HAL_USB_VCP_DEBUG - FURI_LOG_D(TAG, "Disable"); -#endif - enabled = false; - vcp->connected = false; - xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0); - xStreamBufferSend(vcp->rx_stream, &ascii_eot, 1, osWaitForever); - } - // VCP session opened - if((flags & VcpEvtConnect) && enabled) { -#ifdef FURI_HAL_USB_VCP_DEBUG + if(flags & VcpEvtConnect) { +#ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "Connect"); #endif if(vcp->connected == false) { @@ -128,8 +116,8 @@ static int32_t vcp_worker(void* context) { } // VCP session closed - if((flags & VcpEvtDisconnect) && enabled) { -#ifdef FURI_HAL_USB_VCP_DEBUG + if(flags & VcpEvtDisconnect) { +#ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "Disconnect"); #endif if(vcp->connected == true) { @@ -140,8 +128,8 @@ static int32_t vcp_worker(void* context) { } // Rx buffer was read, maybe there is enough space for new data? - if((flags & VcpEvtStreamRx) && enabled && missed_rx > 0) { -#ifdef FURI_HAL_USB_VCP_DEBUG + if((flags & VcpEvtStreamRx) && (missed_rx > 0)) { +#ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "StreamRx"); #endif if(xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) { @@ -151,10 +139,10 @@ static int32_t vcp_worker(void* context) { } // New data received - if((flags & VcpEvtRx)) { + if(flags & VcpEvtRx) { if(xStreamBufferSpacesAvailable(vcp->rx_stream) >= USB_CDC_PKT_LEN) { int32_t len = furi_hal_cdc_receive(VCP_IF_NUM, vcp->data_buffer, USB_CDC_PKT_LEN); -#ifdef FURI_HAL_USB_VCP_DEBUG +#ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "Rx %d", len); #endif if(len > 0) { @@ -163,7 +151,7 @@ static int32_t vcp_worker(void* context) { len); } } else { -#ifdef FURI_HAL_USB_VCP_DEBUG +#ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "Rx missed"); #endif missed_rx++; @@ -171,8 +159,8 @@ static int32_t vcp_worker(void* context) { } // New data in Tx buffer - if((flags & VcpEvtStreamTx) && enabled) { -#ifdef FURI_HAL_USB_VCP_DEBUG + if(flags & VcpEvtStreamTx) { +#ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "StreamTx"); #endif if(tx_idle) { @@ -181,10 +169,10 @@ static int32_t vcp_worker(void* context) { } // CDC write transfer done - if((flags & VcpEvtTx) && enabled) { + if(flags & VcpEvtTx) { size_t len = xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0); -#ifdef FURI_HAL_USB_VCP_DEBUG +#ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "Tx %d", len); #endif if(len > 0) { // Some data left in Tx buffer. Sending it now @@ -202,23 +190,33 @@ static int32_t vcp_worker(void* context) { last_tx_pkt_len = 0; } } + + if(flags & VcpEvtStop) { + vcp->connected = false; + vcp->running = false; + furi_hal_cdc_set_callbacks(VCP_IF_NUM, NULL, NULL); + // Restore previous USB mode (if it was set during init) + if((vcp->usb_if_prev != &usb_cdc_single) && (vcp->usb_if_prev != &usb_cdc_dual)) { + furi_hal_usb_set_config(vcp->usb_if_prev, NULL); + } + xStreamBufferReceive(vcp->tx_stream, vcp->data_buffer, USB_CDC_PKT_LEN, 0); + xStreamBufferSend(vcp->rx_stream, &ascii_eot, 1, osWaitForever); + break; + } } + FURI_LOG_D(TAG, "End"); return 0; } -void furi_hal_vcp_enable() { - osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtEnable); -} - -void furi_hal_vcp_disable() { - osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisable); -} - -size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeout) { +static size_t cli_vcp_rx(uint8_t* buffer, size_t size, uint32_t timeout) { furi_assert(vcp); furi_assert(buffer); -#ifdef FURI_HAL_USB_VCP_DEBUG + if(vcp->running == false) { + return 0; + } + +#ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "rx %u start", size); #endif @@ -229,7 +227,7 @@ size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeo if(batch_size > VCP_RX_BUF_SIZE) batch_size = VCP_RX_BUF_SIZE; size_t len = xStreamBufferReceive(vcp->rx_stream, buffer, batch_size, timeout); -#ifdef FURI_HAL_USB_VCP_DEBUG +#ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "rx %u ", batch_size); #endif if(len == 0) break; @@ -239,22 +237,21 @@ size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeo rx_cnt += len; } -#ifdef FURI_HAL_USB_VCP_DEBUG +#ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "rx %u end", size); #endif return rx_cnt; } -size_t furi_hal_vcp_rx(uint8_t* buffer, size_t size) { - furi_assert(vcp); - return furi_hal_vcp_rx_with_timeout(buffer, size, osWaitForever); -} - -void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) { +static void cli_vcp_tx(const uint8_t* buffer, size_t size) { furi_assert(vcp); furi_assert(buffer); -#ifdef FURI_HAL_USB_VCP_DEBUG + if(vcp->running == false) { + return; + } + +#ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "tx %u start", size); #endif @@ -264,7 +261,7 @@ void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) { xStreamBufferSend(vcp->tx_stream, buffer, batch_size, osWaitForever); osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtStreamTx); -#ifdef FURI_HAL_USB_VCP_DEBUG +#ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "tx %u", batch_size); #endif @@ -272,11 +269,15 @@ void furi_hal_vcp_tx(const uint8_t* buffer, size_t size) { buffer += batch_size; } -#ifdef FURI_HAL_USB_VCP_DEBUG +#ifdef CLI_VCP_DEBUG FURI_LOG_D(TAG, "tx %u end", size); #endif } +static void cli_vcp_tx_stdout(void* _cookie, const char* data, size_t size) { + cli_vcp_tx((const uint8_t*)data, size); +} + static void vcp_state_callback(void* context, uint8_t state) { if(state == 0) { osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtDisconnect); @@ -303,7 +304,16 @@ static void vcp_on_cdc_tx_complete(void* context) { osThreadFlagsSet(furi_thread_get_thread_id(vcp->thread), VcpEvtTx); } -bool furi_hal_vcp_is_connected(void) { +static bool cli_vcp_is_connected(void) { furi_assert(vcp); return vcp->connected; } + +CliSession cli_vcp = { + cli_vcp_init, + cli_vcp_deinit, + cli_vcp_rx, + cli_vcp_tx, + cli_vcp_tx_stdout, + cli_vcp_is_connected, +}; diff --git a/applications/cli/cli_vcp.h b/applications/cli/cli_vcp.h new file mode 100644 index 000000000..2bd47efb2 --- /dev/null +++ b/applications/cli/cli_vcp.h @@ -0,0 +1,18 @@ +/** + * @file cli_vcp.h + * VCP HAL API + */ + +#pragma once + +#include "cli_i.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern CliSession cli_vcp; + +#ifdef __cplusplus +} +#endif diff --git a/applications/desktop/desktop_settings/desktop_settings.h b/applications/desktop/desktop_settings/desktop_settings.h index e096288df..85beb5039 100644 --- a/applications/desktop/desktop_settings/desktop_settings.h +++ b/applications/desktop/desktop_settings/desktop_settings.h @@ -5,7 +5,7 @@ #include #include -#define DESKTOP_SETTINGS_VER (2) +#define DESKTOP_SETTINGS_VER (3) #define DESKTOP_SETTINGS_PATH "/int/desktop.settings" #define DESKTOP_SETTINGS_MAGIC (0x17) #define PIN_MAX_LENGTH 12 @@ -39,5 +39,6 @@ typedef struct { typedef struct { uint16_t favorite; PinCode pin_code; + uint8_t is_locked; uint32_t auto_lock_delay_ms; } DesktopSettings; diff --git a/applications/desktop/helpers/pin_lock.c b/applications/desktop/helpers/pin_lock.c index 8da238bd8..4956c6cc3 100644 --- a/applications/desktop/helpers/pin_lock.c +++ b/applications/desktop/helpers/pin_lock.c @@ -8,6 +8,7 @@ #include "../helpers/pin_lock.h" #include "../desktop_i.h" +#include static const NotificationSequence sequence_pin_fail = { &message_display_on, @@ -61,26 +62,50 @@ uint32_t desktop_pin_lock_get_fail_timeout() { return pin_timeout; } -void desktop_pin_lock() { +void desktop_pin_lock(DesktopSettings* settings) { + furi_assert(settings); + furi_hal_rtc_set_pin_fails(0); furi_hal_rtc_set_flag(FuriHalRtcFlagLock); - furi_hal_usb_disable(); + Cli* cli = furi_record_open("cli"); + cli_session_close(cli); + furi_record_close("cli"); + settings->is_locked = 1; + SAVE_DESKTOP_SETTINGS(settings); } -void desktop_pin_unlock() { +void desktop_pin_unlock(DesktopSettings* settings) { + furi_assert(settings); + furi_hal_rtc_reset_flag(FuriHalRtcFlagLock); - furi_hal_usb_enable(); + Cli* cli = furi_record_open("cli"); + cli_session_open(cli, &cli_vcp); + furi_record_close("cli"); + settings->is_locked = 0; + SAVE_DESKTOP_SETTINGS(settings); } void desktop_pin_lock_init(DesktopSettings* settings) { + furi_assert(settings); + if(settings->pin_code.length > 0) { - furi_hal_rtc_set_flag(FuriHalRtcFlagLock); - furi_hal_usb_disable(); + if(settings->is_locked == 1) { + furi_hal_rtc_set_flag(FuriHalRtcFlagLock); + } else { + if(desktop_pin_lock_is_locked()) { + settings->is_locked = 1; + SAVE_DESKTOP_SETTINGS(settings); + } + } } else { furi_hal_rtc_set_pin_fails(0); furi_hal_rtc_reset_flag(FuriHalRtcFlagLock); furi_hal_usb_enable(); } + + if(desktop_pin_lock_is_locked()) { + furi_hal_usb_disable(); + } } bool desktop_pin_lock_verify(const PinCode* pin_set, const PinCode* pin_entered) { diff --git a/applications/desktop/helpers/pin_lock.h b/applications/desktop/helpers/pin_lock.h index e99ef9f3e..4454cda54 100644 --- a/applications/desktop/helpers/pin_lock.h +++ b/applications/desktop/helpers/pin_lock.h @@ -8,9 +8,9 @@ void desktop_pin_lock_error_notify(); uint32_t desktop_pin_lock_get_fail_timeout(); -void desktop_pin_lock(); +void desktop_pin_lock(DesktopSettings* settings); -void desktop_pin_unlock(); +void desktop_pin_unlock(DesktopSettings* settings); bool desktop_pin_lock_is_locked(); diff --git a/applications/desktop/scenes/desktop_scene_lock_menu.c b/applications/desktop/scenes/desktop_scene_lock_menu.c index b11b90a3e..11478810d 100644 --- a/applications/desktop/scenes/desktop_scene_lock_menu.c +++ b/applications/desktop/scenes/desktop_scene_lock_menu.c @@ -54,7 +54,7 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { break; case DesktopLockMenuEventPinLock: if(desktop->settings.pin_code.length > 0) { - desktop_pin_lock(); + desktop_pin_lock(&desktop->settings); desktop_lock(desktop); } else { LoaderStatus status = diff --git a/applications/desktop/scenes/desktop_scene_pin_input.c b/applications/desktop/scenes/desktop_scene_pin_input.c index 156a5eb2a..7f9d8fcfb 100644 --- a/applications/desktop/scenes/desktop_scene_pin_input.c +++ b/applications/desktop/scenes/desktop_scene_pin_input.c @@ -126,7 +126,7 @@ bool desktop_scene_pin_input_on_event(void* context, SceneManagerEvent event) { consumed = true; break; case DesktopPinInputEventUnlocked: - desktop_pin_unlock(); + desktop_pin_unlock(&desktop->settings); desktop_unlock(desktop); consumed = true; break; diff --git a/applications/dolphin/helpers/dolphin_state.c b/applications/dolphin/helpers/dolphin_state.c index bfd467b8b..86287a2a6 100644 --- a/applications/dolphin/helpers/dolphin_state.c +++ b/applications/dolphin/helpers/dolphin_state.c @@ -148,7 +148,7 @@ void dolphin_state_on_deed(DolphinState* dolphin_state, DolphinDeed deed) { dolphin_deed_get_app_limit(app) - dolphin_state->data.icounter_daily_limit[app]; uint8_t deed_weight = CLAMP(dolphin_deed_get_weight(deed), weight_limit, 0); - uint8_t xp_to_levelup = dolphin_state_xp_to_levelup(dolphin_state->data.icounter); + uint32_t xp_to_levelup = dolphin_state_xp_to_levelup(dolphin_state->data.icounter); if(xp_to_levelup) { deed_weight = MIN(xp_to_levelup, deed_weight); dolphin_state->data.icounter += deed_weight; diff --git a/applications/gpio/usb_uart_bridge.c b/applications/gpio/usb_uart_bridge.c index c33f97b11..8f27340e4 100644 --- a/applications/gpio/usb_uart_bridge.c +++ b/applications/gpio/usb_uart_bridge.c @@ -3,6 +3,8 @@ #include #include #include "usb_cdc.h" +#include "cli/cli_vcp.h" +#include "cli/cli.h" #define USB_CDC_PKT_LEN CDC_DATA_SZ #define USB_UART_RX_BUF_SIZE (USB_CDC_PKT_LEN * 5) @@ -16,17 +18,16 @@ static const GpioPin* flow_pins[][2] = { }; typedef enum { - WorkerEvtReserved = (1 << 0), // Reserved for StreamBuffer internal event - WorkerEvtStop = (1 << 1), - WorkerEvtRxDone = (1 << 2), + WorkerEvtStop = (1 << 0), + WorkerEvtRxDone = (1 << 1), - WorkerEvtTxStop = (1 << 3), - WorkerEvtCdcRx = (1 << 4), + WorkerEvtTxStop = (1 << 2), + WorkerEvtCdcRx = (1 << 3), - WorkerEvtCfgChange = (1 << 5), + WorkerEvtCfgChange = (1 << 4), - WorkerEvtLineCfgSet = (1 << 6), - WorkerEvtCtrlLineSet = (1 << 7), + WorkerEvtLineCfgSet = (1 << 5), + WorkerEvtCtrlLineSet = (1 << 6), } WorkerEvtFlags; @@ -84,18 +85,29 @@ static void usb_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { static void usb_uart_vcp_init(UsbUartBridge* usb_uart, uint8_t vcp_ch) { furi_hal_usb_unlock(); + FURI_LOG_I("", "Init %d", vcp_ch); if(vcp_ch == 0) { + Cli* cli = furi_record_open("cli"); + cli_session_close(cli); + furi_record_close("cli"); furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true); - furi_hal_vcp_disable(); } else { furi_check(furi_hal_usb_set_config(&usb_cdc_dual, NULL) == true); + Cli* cli = furi_record_open("cli"); + cli_session_open(cli, &cli_vcp); + furi_record_close("cli"); } furi_hal_cdc_set_callbacks(vcp_ch, (CdcCallbacks*)&cdc_cb, usb_uart); } static void usb_uart_vcp_deinit(UsbUartBridge* usb_uart, uint8_t vcp_ch) { furi_hal_cdc_set_callbacks(vcp_ch, NULL, NULL); - if(vcp_ch == 0) furi_hal_vcp_enable(); + FURI_LOG_I("", "Deinit %d", vcp_ch); + if(vcp_ch != 0) { + Cli* cli = furi_record_open("cli"); + cli_session_close(cli); + furi_record_close("cli"); + } } static void usb_uart_serial_init(UsbUartBridge* usb_uart, uint8_t uart_ch) { @@ -155,7 +167,6 @@ static int32_t usb_uart_worker(void* context) { furi_thread_set_context(usb_uart->tx_thread, usb_uart); furi_thread_set_callback(usb_uart->tx_thread, usb_uart_tx_thread); - FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); usb_uart_vcp_init(usb_uart, usb_uart->cfg.vcp_ch); usb_uart_serial_init(usb_uart, usb_uart->cfg.uart_ch); usb_uart_set_baudrate(usb_uart, usb_uart->cfg.baudrate); @@ -247,11 +258,9 @@ static int32_t usb_uart_worker(void* context) { usb_uart_update_ctrl_lines(usb_uart); } } - usb_uart_vcp_deinit(usb_uart, usb_uart->cfg.vcp_ch); usb_uart_serial_deinit(usb_uart, usb_uart->cfg.uart_ch); - furi_hal_usb_unlock(); - furi_hal_usb_set_config(usb_mode_prev, NULL); + if(usb_uart->cfg.flow_pins != 0) { furi_hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][0], GpioModeAnalog); furi_hal_gpio_init_simple(flow_pins[usb_uart->cfg.flow_pins - 1][1], GpioModeAnalog); @@ -265,6 +274,12 @@ static int32_t usb_uart_worker(void* context) { osMutexDelete(usb_uart->usb_mutex); osSemaphoreDelete(usb_uart->tx_sem); + furi_hal_usb_unlock(); + furi_check(furi_hal_usb_set_config(&usb_cdc_single, NULL) == true); + Cli* cli = furi_record_open("cli"); + cli_session_open(cli, &cli_vcp); + furi_record_close("cli"); + return 0; } diff --git a/applications/rpc/rpc_cli.c b/applications/rpc/rpc_cli.c index fd1f6e7fc..b93043678 100644 --- a/applications/rpc/rpc_cli.c +++ b/applications/rpc/rpc_cli.c @@ -62,8 +62,8 @@ void rpc_cli_command_start_session(Cli* cli, string_t args, void* context) { size_t size_received = 0; while(1) { - size_received = furi_hal_vcp_rx_with_timeout(buffer, CLI_READ_BUFFER_SIZE, 50); - if(!furi_hal_vcp_is_connected() || cli_rpc.session_close_request) { + size_received = cli_read_timeout(cli_rpc.cli, buffer, CLI_READ_BUFFER_SIZE, 50); + if(!cli_is_connected(cli_rpc.cli) || cli_rpc.session_close_request) { break; } diff --git a/applications/subghz/helpers/subghz_chat.c b/applications/subghz/helpers/subghz_chat.c index 30618813c..e6b7b7bc7 100644 --- a/applications/subghz/helpers/subghz_chat.c +++ b/applications/subghz/helpers/subghz_chat.c @@ -12,6 +12,8 @@ struct SubGhzChatWorker { volatile bool worker_stoping; osMessageQueueId_t event_queue; uint32_t last_time_rx_data; + + Cli* cli; }; /** Worker thread @@ -27,7 +29,7 @@ static int32_t subghz_chat_worker_thread(void* context) { event.event = SubGhzChatEventUserEntrance; osMessageQueuePut(instance->event_queue, &event, 0, 0); while(instance->worker_running) { - if(furi_hal_vcp_rx_with_timeout((uint8_t*)&c, 1, 1000) == 1) { + if(cli_read_timeout(instance->cli, (uint8_t*)&c, 1, 1000) == 1) { event.event = SubGhzChatEventInputData; event.c = c; osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever); @@ -52,9 +54,11 @@ static void subghz_chat_worker_update_rx_event_chat(void* context) { osMessageQueuePut(instance->event_queue, &event, 0, osWaitForever); } -SubGhzChatWorker* subghz_chat_worker_alloc() { +SubGhzChatWorker* subghz_chat_worker_alloc(Cli* cli) { SubGhzChatWorker* instance = malloc(sizeof(SubGhzChatWorker)); + instance->cli = cli; + instance->thread = furi_thread_alloc(); furi_thread_set_name(instance->thread, "SubGhzChat"); furi_thread_set_stack_size(instance->thread, 2048); diff --git a/applications/subghz/helpers/subghz_chat.h b/applications/subghz/helpers/subghz_chat.h index 6556d0c33..b418bbdbf 100644 --- a/applications/subghz/helpers/subghz_chat.h +++ b/applications/subghz/helpers/subghz_chat.h @@ -1,5 +1,6 @@ #pragma once #include "../subghz_i.h" +#include typedef struct SubGhzChatWorker SubGhzChatWorker; @@ -17,7 +18,7 @@ typedef struct { char c; } SubGhzChatEvent; -SubGhzChatWorker* subghz_chat_worker_alloc(); +SubGhzChatWorker* subghz_chat_worker_alloc(Cli* cli); void subghz_chat_worker_free(SubGhzChatWorker* instance); bool subghz_chat_worker_start(SubGhzChatWorker* instance, uint32_t frequency); void subghz_chat_worker_stop(SubGhzChatWorker* instance); diff --git a/applications/subghz/subghz_cli.c b/applications/subghz/subghz_cli.c index 6928c4bac..65ea0cf28 100644 --- a/applications/subghz/subghz_cli.c +++ b/applications/subghz/subghz_cli.c @@ -525,7 +525,7 @@ static void subghz_cli_command_chat(Cli* cli, string_t args) { return; } - SubGhzChatWorker* subghz_chat = subghz_chat_worker_alloc(); + SubGhzChatWorker* subghz_chat = subghz_chat_worker_alloc(cli); if(!subghz_chat_worker_start(subghz_chat, frequency)) { printf("Startup error SubGhzChatWorker\r\n"); diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb.c b/firmware/targets/f7/furi_hal/furi_hal_usb.c index f1044c36b..7032d059b 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb.c @@ -1,7 +1,6 @@ #include "furi_hal_version.h" #include "furi_hal_usb_i.h" #include "furi_hal_usb.h" -#include "furi_hal_vcp.h" #include #include #include diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c b/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c index 028e3e30c..807f16348 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb_cdc.c @@ -482,6 +482,9 @@ void furi_hal_cdc_set_callbacks(uint8_t if_num, CdcCallbacks* cb, void* context) if(callbacks[if_num]->state_callback != NULL) { if(connected == true) callbacks[if_num]->state_callback(cb_ctx[if_num], 1); } + if(callbacks[if_num]->ctrl_line_callback != NULL) { + callbacks[if_num]->ctrl_line_callback(cb_ctx[if_num], cdc_ctrl_line_state[if_num]); + } } } diff --git a/firmware/targets/furi_hal_include/furi_hal.h b/firmware/targets/furi_hal_include/furi_hal.h index a1e4a90fb..8480f8840 100644 --- a/firmware/targets/furi_hal_include/furi_hal.h +++ b/firmware/targets/furi_hal_include/furi_hal.h @@ -22,7 +22,6 @@ template struct STOP_EXTERNING_ME {}; #include "furi_hal_light.h" #include "furi_hal_delay.h" #include "furi_hal_power.h" -#include "furi_hal_vcp.h" #include "furi_hal_interrupt.h" #include "furi_hal_version.h" #include "furi_hal_bt.h" diff --git a/firmware/targets/furi_hal_include/furi_hal_vcp.h b/firmware/targets/furi_hal_include/furi_hal_vcp.h deleted file mode 100644 index ef5c18f95..000000000 --- a/firmware/targets/furi_hal_include/furi_hal_vcp.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @file furi_hal_vcp.h - * VCP HAL API - */ - -#pragma once - -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** Init VCP HAL Allocates ring buffer and initializes state - */ -void furi_hal_vcp_init(); - -/** Disable VCP to make CDC interface usable by other application - */ -void furi_hal_vcp_disable(); - -/** Enable VCP - */ -void furi_hal_vcp_enable(); - -/** Recieve data from VCP Waits till some data arrives, never returns 0 - * - * @param buffer pointer to buffer - * @param size buffer size - * - * @return items copied in buffer, 0 if channel closed - */ -size_t furi_hal_vcp_rx(uint8_t* buffer, size_t size); - -/** Recieve data from VCP with timeout Waits till some data arrives during - * timeout - * - * @param buffer pointer to buffer - * @param size buffer size - * @param timeout rx timeout in ms - * - * @return items copied in buffer, 0 if channel closed or timeout occurs - */ -size_t furi_hal_vcp_rx_with_timeout(uint8_t* buffer, size_t size, uint32_t timeout); - -/** Transmit data to VCP - * - * @param buffer pointer to buffer - * @param size buffer size - */ -void furi_hal_vcp_tx(const uint8_t* buffer, size_t size); - -/** Check whether VCP is connected - * - * @return true if connected - */ -bool furi_hal_vcp_is_connected(void); - -#ifdef __cplusplus -} -#endif From 73477cceed7c02785d477f704c355067aaa80f2b Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Fri, 29 Apr 2022 16:17:42 +0400 Subject: [PATCH 2/4] SubGhz add protocol Firefly (#1183) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * SubGhz: add protocol "Firefly" * SubGhz: refactoring "Add Manually" scene * SubGhz: refactoring Firefly protocol Co-authored-by: あく --- .../subghz/scenes/subghz_scene_set_type.c | 93 ++++- lib/subghz/protocols/firefly.c | 343 ++++++++++++++++++ lib/subghz/protocols/firefly.h | 109 ++++++ lib/subghz/protocols/registry.c | 2 +- lib/subghz/protocols/registry.h | 1 + 5 files changed, 531 insertions(+), 17 deletions(-) create mode 100644 lib/subghz/protocols/firefly.c create mode 100644 lib/subghz/protocols/firefly.h diff --git a/applications/subghz/scenes/subghz_scene_set_type.c b/applications/subghz/scenes/subghz_scene_set_type.c index 22a151434..964b85b2f 100644 --- a/applications/subghz/scenes/subghz_scene_set_type.c +++ b/applications/subghz/scenes/subghz_scene_set_type.c @@ -4,6 +4,7 @@ #include #include #include +#include #define TAG "SubGhzSetType" @@ -19,13 +20,16 @@ enum SubmenuIndex { SubmenuIndexGateTX, SubmenuIndexDoorHan_315_00, SubmenuIndexDoorHan_433_92, + SubmenuIndexFirefly_300_00, }; bool subghz_scene_set_type_submenu_gen_data_protocol( void* context, const char* protocol_name, uint64_t key, - uint32_t bit) { + uint32_t bit, + uint32_t frequency, + FuriHalSubGhzPreset preset) { furi_assert(context); SubGhz* subghz = context; @@ -44,10 +48,7 @@ bool subghz_scene_set_type_submenu_gen_data_protocol( Stream* fff_data_stream = flipper_format_get_raw_stream(subghz->txrx->fff_data); stream_clean(fff_data_stream); if(!subghz_protocol_decoder_base_serialize( - subghz->txrx->decoder_result, - subghz->txrx->fff_data, - subghz_setting_get_default_frequency(subghz->setting), - FuriHalSubGhzPresetOok650Async)) { + subghz->txrx->decoder_result, subghz->txrx->fff_data, frequency, preset)) { FURI_LOG_E(TAG, "Unable to serialize"); break; } @@ -107,6 +108,12 @@ void subghz_scene_set_type_on_enter(void* context) { SubmenuIndexCAME24bit, subghz_scene_set_type_submenu_callback, subghz); + submenu_add_item( + subghz->submenu, + "Firefly_300", + SubmenuIndexFirefly_300_00, + subghz_scene_set_type_submenu_callback, + subghz); submenu_add_item( subghz->submenu, "CAME TWEE", @@ -152,7 +159,13 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { switch(event.event) { case SubmenuIndexPricenton: key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8 - if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "Princeton", key, 24)) { + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_PRINCETON_NAME, + key, + 24, + 433920000, + FuriHalSubGhzPresetOok650Async)) { uint32_t te = 400; flipper_format_update_uint32(subghz->txrx->fff_data, "TE", (uint32_t*)&te, 1); generated_protocol = true; @@ -160,32 +173,74 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { break; case SubmenuIndexNiceFlo12bit: key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4 - if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "Nice FLO", key, 12)) { + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_NICE_FLO_NAME, + key, + 12, + 433920000, + FuriHalSubGhzPresetOok650Async)) { generated_protocol = true; } break; case SubmenuIndexNiceFlo24bit: key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8 - if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "Nice FLO", key, 24)) { + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_NICE_FLO_NAME, + key, + 24, + 433920000, + FuriHalSubGhzPresetOok650Async)) { generated_protocol = true; } break; case SubmenuIndexCAME12bit: key = (key & 0x0000FFF0) | 0x1; //btn 0x1, 0x2, 0x4 - if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "CAME", key, 12)) { + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_CAME_NAME, + key, + 12, + 433920000, + FuriHalSubGhzPresetOok650Async)) { generated_protocol = true; } break; case SubmenuIndexCAME24bit: key = (key & 0x00FFFFF0) | 0x4; //btn 0x1, 0x2, 0x4, 0x8 - if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "CAME", key, 24)) { + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_CAME_NAME, + key, + 24, + 433920000, + FuriHalSubGhzPresetOok650Async)) { + generated_protocol = true; + } + break; + case SubmenuIndexFirefly_300_00: + key = (key & 0x3FF); + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_FIREFLY_NAME, + key, + 10, + 300000000, + FuriHalSubGhzPresetOok650Async)) { generated_protocol = true; } break; case SubmenuIndexCAMETwee: key = (key & 0x0FFFFFF0); key = 0x003FFF7200000000 | (key ^ 0xE0E0E0EE); - if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "CAME TWEE", key, 54)) { + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_CAME_TWEE_NAME, + key, + 54, + 433920000, + FuriHalSubGhzPresetOok650Async)) { generated_protocol = true; } break; @@ -198,13 +253,19 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { case SubmenuIndexGateTX: key = (key & 0x00F0FF00) | 0xF << 16 | 0x40; //btn 0xF, 0xC, 0xA, 0x6 (?) uint64_t rev_key = subghz_protocol_blocks_reverse_key(key, 24); - if(subghz_scene_set_type_submenu_gen_data_protocol(subghz, "GateTX", rev_key, 24)) { + if(subghz_scene_set_type_submenu_gen_data_protocol( + subghz, + SUBGHZ_PROTOCOL_GATE_TX_NAME, + rev_key, + 24, + 433920000, + FuriHalSubGhzPresetOok650Async)) { generated_protocol = true; } break; case SubmenuIndexDoorHan_433_92: - subghz->txrx->transmitter = - subghz_transmitter_alloc_init(subghz->txrx->environment, "KeeLoq"); + subghz->txrx->transmitter = subghz_transmitter_alloc_init( + subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME); if(subghz->txrx->transmitter) { subghz_protocol_keeloq_create_data( subghz->txrx->transmitter->protocol_instance, @@ -227,8 +288,8 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { } break; case SubmenuIndexDoorHan_315_00: - subghz->txrx->transmitter = - subghz_transmitter_alloc_init(subghz->txrx->environment, "KeeLoq"); + subghz->txrx->transmitter = subghz_transmitter_alloc_init( + subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME); if(subghz->txrx->transmitter) { subghz_protocol_keeloq_create_data( subghz->txrx->transmitter->protocol_instance, diff --git a/lib/subghz/protocols/firefly.c b/lib/subghz/protocols/firefly.c new file mode 100644 index 000000000..e872d5580 --- /dev/null +++ b/lib/subghz/protocols/firefly.c @@ -0,0 +1,343 @@ +#include "firefly.h" + +#include "../blocks/const.h" +#include "../blocks/decoder.h" +#include "../blocks/encoder.h" +#include "../blocks/generic.h" +#include "../blocks/math.h" + +/* + * Help + * https://phreakerclub.com/447 + * + */ + +#define TAG "SubGhzProtocolFirefly" + +#define DIP_PATTERN "%c%c%c%c%c%c%c%c%c%c" +#define DATA_TO_DIP(dip) \ + (dip & 0x0200 ? '1' : '0'), (dip & 0x0100 ? '1' : '0'), (dip & 0x0080 ? '1' : '0'), \ + (dip & 0x0040 ? '1' : '0'), (dip & 0x0020 ? '1' : '0'), (dip & 0x0010 ? '1' : '0'), \ + (dip & 0x0008 ? '1' : '0'), (dip & 0x0004 ? '1' : '0'), (dip & 0x0002 ? '1' : '0'), \ + (dip & 0x0001 ? '1' : '0') + +static const SubGhzBlockConst subghz_protocol_firefly_const = { + .te_short = 500, + .te_long = 1500, + .te_delta = 150, + .min_count_bit_for_found = 10, +}; + +struct SubGhzProtocolDecoderFirefly { + SubGhzProtocolDecoderBase base; + + SubGhzBlockDecoder decoder; + SubGhzBlockGeneric generic; +}; + +struct SubGhzProtocolEncoderFirefly { + SubGhzProtocolEncoderBase base; + + SubGhzProtocolBlockEncoder encoder; + SubGhzBlockGeneric generic; +}; + +typedef enum { + FireflyDecoderStepReset = 0, + FireflyDecoderStepSaveDuration, + FireflyDecoderStepCheckDuration, +} FireflyDecoderStep; + +const SubGhzProtocolDecoder subghz_protocol_firefly_decoder = { + .alloc = subghz_protocol_decoder_firefly_alloc, + .free = subghz_protocol_decoder_firefly_free, + + .feed = subghz_protocol_decoder_firefly_feed, + .reset = subghz_protocol_decoder_firefly_reset, + + .get_hash_data = subghz_protocol_decoder_firefly_get_hash_data, + .serialize = subghz_protocol_decoder_firefly_serialize, + .deserialize = subghz_protocol_decoder_firefly_deserialize, + .get_string = subghz_protocol_decoder_firefly_get_string, +}; + +const SubGhzProtocolEncoder subghz_protocol_firefly_encoder = { + .alloc = subghz_protocol_encoder_firefly_alloc, + .free = subghz_protocol_encoder_firefly_free, + + .deserialize = subghz_protocol_encoder_firefly_deserialize, + .stop = subghz_protocol_encoder_firefly_stop, + .yield = subghz_protocol_encoder_firefly_yield, +}; + +const SubGhzProtocol subghz_protocol_firefly = { + .name = SUBGHZ_PROTOCOL_FIREFLY_NAME, + .type = SubGhzProtocolTypeStatic, + .flag = SubGhzProtocolFlag_315 | SubGhzProtocolFlag_AM | SubGhzProtocolFlag_Decodable | + SubGhzProtocolFlag_Load | SubGhzProtocolFlag_Save | SubGhzProtocolFlag_Send, + + .decoder = &subghz_protocol_firefly_decoder, + .encoder = &subghz_protocol_firefly_encoder, +}; + +void* subghz_protocol_encoder_firefly_alloc(SubGhzEnvironment* environment) { + SubGhzProtocolEncoderFirefly* instance = malloc(sizeof(SubGhzProtocolEncoderFirefly)); + + instance->base.protocol = &subghz_protocol_firefly; + instance->generic.protocol_name = instance->base.protocol->name; + + instance->encoder.repeat = 10; + instance->encoder.size_upload = 28; //max 10bit*2 + 2 (start, stop) + instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); + instance->encoder.is_runing = false; + return instance; +} + +void subghz_protocol_encoder_firefly_free(void* context) { + furi_assert(context); + SubGhzProtocolEncoderFirefly* instance = context; + free(instance->encoder.upload); + free(instance); +} + +/** + * Generating an upload from data. + * @param instance Pointer to a SubGhzProtocolEncoderFirefly instance + * @return true On success + */ +static bool subghz_protocol_encoder_firefly_get_upload(SubGhzProtocolEncoderFirefly* instance) { + furi_assert(instance); + size_t index = 0; + size_t size_upload = (instance->generic.data_count_bit * 2); + if(size_upload > instance->encoder.size_upload) { + FURI_LOG_E(TAG, "Size upload exceeds allocated encoder buffer."); + return false; + } else { + instance->encoder.size_upload = size_upload; + } + + //Send key data + for(uint8_t i = instance->generic.data_count_bit; i > 1; i--) { + if(bit_read(instance->generic.data, i - 1)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short * 3); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short); + } else { + //send bit 0 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short * 3); + } + } + //Send end bit + if(bit_read(instance->generic.data, 0)) { + //send bit 1 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short * 3); + //Send PT_GUARD + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short * 42); + } else { + //send bit 0 + instance->encoder.upload[index++] = + level_duration_make(true, (uint32_t)subghz_protocol_firefly_const.te_short); + //Send PT_GUARD + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_firefly_const.te_short * 44); + } + + return true; +} + +bool subghz_protocol_encoder_firefly_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolEncoderFirefly* instance = context; + bool res = false; + do { + if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + FURI_LOG_E(TAG, "Deserialize error"); + break; + } + + //optional parameter parameter + flipper_format_read_uint32( + flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); + + subghz_protocol_encoder_firefly_get_upload(instance); + instance->encoder.is_runing = true; + + res = true; + } while(false); + + return res; +} + +void subghz_protocol_encoder_firefly_stop(void* context) { + SubGhzProtocolEncoderFirefly* instance = context; + instance->encoder.is_runing = false; +} + +LevelDuration subghz_protocol_encoder_firefly_yield(void* context) { + SubGhzProtocolEncoderFirefly* instance = context; + + if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { + instance->encoder.is_runing = false; + return level_duration_reset(); + } + + LevelDuration ret = instance->encoder.upload[instance->encoder.front]; + + if(++instance->encoder.front == instance->encoder.size_upload) { + instance->encoder.repeat--; + instance->encoder.front = 0; + } + + return ret; +} + +void* subghz_protocol_decoder_firefly_alloc(SubGhzEnvironment* environment) { + SubGhzProtocolDecoderFirefly* instance = malloc(sizeof(SubGhzProtocolDecoderFirefly)); + instance->base.protocol = &subghz_protocol_firefly; + instance->generic.protocol_name = instance->base.protocol->name; + return instance; +} + +void subghz_protocol_decoder_firefly_free(void* context) { + furi_assert(context); + SubGhzProtocolDecoderFirefly* instance = context; + free(instance); +} + +void subghz_protocol_decoder_firefly_reset(void* context) { + furi_assert(context); + SubGhzProtocolDecoderFirefly* instance = context; + instance->decoder.parser_step = FireflyDecoderStepReset; +} + +void subghz_protocol_decoder_firefly_feed(void* context, bool level, uint32_t duration) { + furi_assert(context); + SubGhzProtocolDecoderFirefly* instance = context; + switch(instance->decoder.parser_step) { + case FireflyDecoderStepReset: + if((!level) && (DURATION_DIFF(duration, subghz_protocol_firefly_const.te_short * 42) < + subghz_protocol_firefly_const.te_delta * 20)) { + //Found header Firefly + instance->decoder.decode_data = 0; + instance->decoder.decode_count_bit = 0; + instance->decoder.parser_step = FireflyDecoderStepSaveDuration; + } + break; + case FireflyDecoderStepSaveDuration: + if(level) { + instance->decoder.te_last = duration; + instance->decoder.parser_step = FireflyDecoderStepCheckDuration; + } else { + instance->decoder.parser_step = FireflyDecoderStepReset; + } + break; + case FireflyDecoderStepCheckDuration: + if(!level) { //save interval + if(duration >= (subghz_protocol_firefly_const.te_short * 5)) { + instance->decoder.parser_step = FireflyDecoderStepReset; + //checking that the duration matches the guardtime + if((DURATION_DIFF(duration, subghz_protocol_firefly_const.te_short * 42) > + subghz_protocol_firefly_const.te_delta * 20)) { + break; + } + if(DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_firefly_const.te_short) < + subghz_protocol_firefly_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + } else if( + DURATION_DIFF( + instance->decoder.te_last, subghz_protocol_firefly_const.te_long) < + subghz_protocol_firefly_const.te_delta) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + } + if(instance->decoder.decode_count_bit == + subghz_protocol_firefly_const.min_count_bit_for_found) { + instance->generic.serial = 0x0; + instance->generic.btn = 0x0; + + instance->generic.data = instance->decoder.decode_data; + instance->generic.data_count_bit = instance->decoder.decode_count_bit; + + if(instance->base.callback) + instance->base.callback(&instance->base, instance->base.context); + } + break; + } + + if((DURATION_DIFF(instance->decoder.te_last, subghz_protocol_firefly_const.te_short) < + subghz_protocol_firefly_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_firefly_const.te_long) < + subghz_protocol_firefly_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 0); + instance->decoder.parser_step = FireflyDecoderStepSaveDuration; + } else if( + (DURATION_DIFF(instance->decoder.te_last, subghz_protocol_firefly_const.te_long) < + subghz_protocol_firefly_const.te_delta) && + (DURATION_DIFF(duration, subghz_protocol_firefly_const.te_short) < + subghz_protocol_firefly_const.te_delta)) { + subghz_protocol_blocks_add_bit(&instance->decoder, 1); + instance->decoder.parser_step = FireflyDecoderStepSaveDuration; + } else { + instance->decoder.parser_step = FireflyDecoderStepReset; + } + + } else { + instance->decoder.parser_step = FireflyDecoderStepReset; + } + break; + } +} + +uint8_t subghz_protocol_decoder_firefly_get_hash_data(void* context) { + furi_assert(context); + SubGhzProtocolDecoderFirefly* instance = context; + return subghz_protocol_blocks_get_hash_data( + &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); +} + +bool subghz_protocol_decoder_firefly_serialize( + void* context, + FlipperFormat* flipper_format, + uint32_t frequency, + FuriHalSubGhzPreset preset) { + furi_assert(context); + SubGhzProtocolDecoderFirefly* instance = context; + return subghz_block_generic_serialize(&instance->generic, flipper_format, frequency, preset); +} + +bool subghz_protocol_decoder_firefly_deserialize(void* context, FlipperFormat* flipper_format) { + furi_assert(context); + SubGhzProtocolDecoderFirefly* instance = context; + return subghz_block_generic_deserialize(&instance->generic, flipper_format); +} + +void subghz_protocol_decoder_firefly_get_string(void* context, string_t output) { + furi_assert(context); + SubGhzProtocolDecoderFirefly* instance = context; + + uint32_t code_found_lo = instance->generic.data & 0x00000000ffffffff; + + uint64_t code_found_reverse = subghz_protocol_blocks_reverse_key( + instance->generic.data, instance->generic.data_count_bit); + + uint32_t code_found_reverse_lo = code_found_reverse & 0x00000000ffffffff; + + string_cat_printf( + output, + "%s %dbit\r\n" + "Key:0x%08lX\r\n" + "Yek:0x%08lX\r\n" + "DIP:" DIP_PATTERN "\r\n", + instance->generic.protocol_name, + instance->generic.data_count_bit, + code_found_lo, + code_found_reverse_lo, + DATA_TO_DIP(code_found_lo)); +} diff --git a/lib/subghz/protocols/firefly.h b/lib/subghz/protocols/firefly.h new file mode 100644 index 000000000..abb4537c8 --- /dev/null +++ b/lib/subghz/protocols/firefly.h @@ -0,0 +1,109 @@ +#pragma once + +#include "base.h" + +#define SUBGHZ_PROTOCOL_FIREFLY_NAME "Firefly" + +typedef struct SubGhzProtocolDecoderFirefly SubGhzProtocolDecoderFirefly; +typedef struct SubGhzProtocolEncoderFirefly SubGhzProtocolEncoderFirefly; + +extern const SubGhzProtocolDecoder subghz_protocol_firefly_decoder; +extern const SubGhzProtocolEncoder subghz_protocol_firefly_encoder; +extern const SubGhzProtocol subghz_protocol_firefly; + +/** + * Allocate SubGhzProtocolEncoderFirefly. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolEncoderFirefly* pointer to a SubGhzProtocolEncoderFirefly instance + */ +void* subghz_protocol_encoder_firefly_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolEncoderFirefly. + * @param context Pointer to a SubGhzProtocolEncoderFirefly instance + */ +void subghz_protocol_encoder_firefly_free(void* context); + +/** + * Deserialize and generating an upload to send. + * @param context Pointer to a SubGhzProtocolEncoderFirefly instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_encoder_firefly_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Forced transmission stop. + * @param context Pointer to a SubGhzProtocolEncoderFirefly instance + */ +void subghz_protocol_encoder_firefly_stop(void* context); + +/** + * Getting the level and duration of the upload to be loaded into DMA. + * @param context Pointer to a SubGhzProtocolEncoderFirefly instance + * @return LevelDuration + */ +LevelDuration subghz_protocol_encoder_firefly_yield(void* context); + +/** + * Allocate SubGhzProtocolDecoderFirefly. + * @param environment Pointer to a SubGhzEnvironment instance + * @return SubGhzProtocolDecoderFirefly* pointer to a SubGhzProtocolDecoderFirefly instance + */ +void* subghz_protocol_decoder_firefly_alloc(SubGhzEnvironment* environment); + +/** + * Free SubGhzProtocolDecoderFirefly. + * @param context Pointer to a SubGhzProtocolDecoderFirefly instance + */ +void subghz_protocol_decoder_firefly_free(void* context); + +/** + * Reset decoder SubGhzProtocolDecoderFirefly. + * @param context Pointer to a SubGhzProtocolDecoderFirefly instance + */ +void subghz_protocol_decoder_firefly_reset(void* context); + +/** + * Parse a raw sequence of levels and durations received from the air. + * @param context Pointer to a SubGhzProtocolDecoderFirefly instance + * @param level Signal level true-high false-low + * @param duration Duration of this level in, us + */ +void subghz_protocol_decoder_firefly_feed(void* context, bool level, uint32_t duration); + +/** + * Getting the hash sum of the last randomly received parcel. + * @param context Pointer to a SubGhzProtocolDecoderFirefly instance + * @return hash Hash sum + */ +uint8_t subghz_protocol_decoder_firefly_get_hash_data(void* context); + +/** + * Serialize data SubGhzProtocolDecoderFirefly. + * @param context Pointer to a SubGhzProtocolDecoderFirefly instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param frequency The frequency at which the signal was received, Hz + * @param preset The modulation on which the signal was received, FuriHalSubGhzPreset + * @return true On success + */ +bool subghz_protocol_decoder_firefly_serialize( + void* context, + FlipperFormat* flipper_format, + uint32_t frequency, + FuriHalSubGhzPreset preset); + +/** + * Deserialize data SubGhzProtocolDecoderFirefly. + * @param context Pointer to a SubGhzProtocolDecoderFirefly instance + * @param flipper_format Pointer to a FlipperFormat instance + * @return true On success + */ +bool subghz_protocol_decoder_firefly_deserialize(void* context, FlipperFormat* flipper_format); + +/** + * Getting a textual representation of the received data. + * @param context Pointer to a SubGhzProtocolDecoderFirefly instance + * @param output Resulting text + */ +void subghz_protocol_decoder_firefly_get_string(void* context, string_t output); diff --git a/lib/subghz/protocols/registry.c b/lib/subghz/protocols/registry.c index 6d15af560..c384eda11 100644 --- a/lib/subghz/protocols/registry.c +++ b/lib/subghz/protocols/registry.c @@ -7,7 +7,7 @@ const SubGhzProtocol* subghz_protocol_registry[] = { &subghz_protocol_nero_sketch, &subghz_protocol_ido, &subghz_protocol_kia, &subghz_protocol_hormann, &subghz_protocol_nero_radio, &subghz_protocol_somfy_telis, &subghz_protocol_somfy_keytis, &subghz_protocol_scher_khan, &subghz_protocol_gate_tx, - &subghz_protocol_raw, + &subghz_protocol_raw, &subghz_protocol_firefly, }; diff --git a/lib/subghz/protocols/registry.h b/lib/subghz/protocols/registry.h index cce48e024..531caee2a 100644 --- a/lib/subghz/protocols/registry.h +++ b/lib/subghz/protocols/registry.h @@ -21,6 +21,7 @@ #include "scher_khan.h" #include "gate_tx.h" #include "raw.h" +#include "firefly.h" /** * Registration by name SubGhzProtocol. From 01434265f6375b2d6330e7d6425bf8cd9dcb9c0f Mon Sep 17 00:00:00 2001 From: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Date: Fri, 29 Apr 2022 16:29:51 +0300 Subject: [PATCH 3/4] [FL-2399, FL-2261] Tickless sleep shenanigans (#1168) * Disable USART in sleep * Restore UART state on suspend/resume * FuriHal: Enable stop mode and add insomnia to I2C and SPI * Remove IDLE interrupt * FuriHal: add FPU isr and disable all FPU interrupt, add core2 stop mode configuration on deep sleep * FuriHal: tie stop mode debug with debug rtc flag * FuriHal: adjust flash latency on clock switch, tie mcu debug with RTC debug flag * FuriHal: move resource init to early stage * Add EXTI pending check, enable debug traps with compile-time flag * Wrap sleep debug functions in conditional compilation * Remove erroneous changed * Do not use CSS, remove it from everywhere * Enable/disable USB on VBUS connect (prototype) * FuriHal: add LPMS and DEEPSLEEP magic, workaround state inconsistency between cores * FuriHal: honor c1 LMPS * USB mode switch fix * Applications: add flags and insomnia bypass system * Correct spelling * FuriHal: cleanup insomnia usage, reset sleep flags on wakeup, add shutdown api * FuriHal: extra check on reinit request * FuriHal: rename gpio_display_rst pin to gpio_display_rst_n * FuriHal: add debug HAL * FuriHal: add some magic to core2 reload procedure, fix issue with crash on ble keyboard exit * FuriHal: cleanup ble glue, add BLE_GLUE_DEBUG flag * FuriHal: ble reinit API, move os timer to LPTIM1 for deep sleep capability, shutdown that works * FuriHal: take insomnia while shutdown * Remove USB switch on/off on VBUS change * Better tick skew handling * Improve tick consistency under load * Add USB_HP dummy IRQ handler * Move interrupt check closer to sleep * Clean up includes * Re-enable Insomnia globally * FuriHal: enable CSS * FuriHal: remove questionable core2 clock shenanigans * FuriHal: use core1 RCC registers in idle timer config * FuriHal: return back CSS handlers, add lptim isr dispatching Co-authored-by: Aleksandr Kutuzov Co-authored-by: nminaylov --- applications/accessor/accessor_app.cpp | 4 +- applications/applications.c | 293 +++++++++++++++--- applications/applications.h | 6 + applications/gui/canvas.c | 4 - applications/ibutton/ibutton_app.cpp | 5 +- applications/lfrfid/lfrfid_app.cpp | 4 +- applications/loader/loader.c | 9 +- applications/nfc/nfc_worker.c | 2 - applications/storage/storage_glue.c | 2 - firmware/targets/f7/ble_glue/app_conf.h | 2 +- firmware/targets/f7/ble_glue/app_debug.c | 111 +------ firmware/targets/f7/ble_glue/ble_glue.c | 17 +- firmware/targets/f7/ble_glue/gap.c | 27 +- firmware/targets/f7/furi_hal/furi_hal.c | 4 +- firmware/targets/f7/furi_hal/furi_hal_bt.c | 46 +-- firmware/targets/f7/furi_hal/furi_hal_clock.c | 4 + firmware/targets/f7/furi_hal/furi_hal_debug.c | 20 ++ firmware/targets/f7/furi_hal/furi_hal_i2c.c | 3 + .../targets/f7/furi_hal/furi_hal_idle_timer.h | 8 +- .../targets/f7/furi_hal/furi_hal_interrupt.c | 89 ++++-- .../targets/f7/furi_hal/furi_hal_interrupt.h | 4 + firmware/targets/f7/furi_hal/furi_hal_os.c | 89 ++++-- firmware/targets/f7/furi_hal/furi_hal_power.c | 99 +++++- .../targets/f7/furi_hal/furi_hal_resources.c | 39 ++- .../targets/f7/furi_hal/furi_hal_resources.h | 2 +- firmware/targets/f7/furi_hal/furi_hal_rtc.c | 18 +- firmware/targets/f7/furi_hal/furi_hal_spi.c | 5 + firmware/targets/f7/furi_hal/furi_hal_uart.c | 33 +- firmware/targets/f7/furi_hal/furi_hal_uart.h | 18 +- firmware/targets/f7/furi_hal/furi_hal_usb.c | 2 + firmware/targets/f7/target.mk | 8 + firmware/targets/furi_hal_include/furi_hal.h | 1 + .../targets/furi_hal_include/furi_hal_bt.h | 6 + .../targets/furi_hal_include/furi_hal_debug.h | 23 ++ .../targets/furi_hal_include/furi_hal_power.h | 3 + lib/u8g2/u8g2_glue.c | 2 +- 36 files changed, 710 insertions(+), 302 deletions(-) create mode 100644 firmware/targets/f7/furi_hal/furi_hal_debug.c create mode 100644 firmware/targets/furi_hal_include/furi_hal_debug.h diff --git a/applications/accessor/accessor_app.cpp b/applications/accessor/accessor_app.cpp index 21b2e2587..f021a816e 100644 --- a/applications/accessor/accessor_app.cpp +++ b/applications/accessor/accessor_app.cpp @@ -32,7 +32,6 @@ void AccessorApp::run(void) { } AccessorApp::AccessorApp() { - furi_hal_power_insomnia_enter(); notification = static_cast(furi_record_open("notification")); onewire_host = onewire_host_alloc(); furi_hal_power_enable_otg(); @@ -42,7 +41,6 @@ AccessorApp::~AccessorApp() { furi_hal_power_disable_otg(); furi_record_close("notification"); onewire_host_free(onewire_host); - furi_hal_power_insomnia_exit(); } AccessorAppViewManager* AccessorApp::get_view_manager() { @@ -139,4 +137,4 @@ WIEGAND* AccessorApp::get_wiegand() { OneWireHost* AccessorApp::get_one_wire() { return onewire_host; -} \ No newline at end of file +} diff --git a/applications/applications.c b/applications/applications.c index 6b4c63211..b9e8bbd47 100644 --- a/applications/applications.c +++ b/applications/applications.c @@ -74,61 +74,113 @@ extern int32_t system_settings_app(void* p); const FlipperApplication FLIPPER_SERVICES[] = { /* Services */ #ifdef SRV_RPC - {.app = rpc_srv, .name = "RpcSrv", .stack_size = 1024 * 4, .icon = NULL}, + {.app = rpc_srv, + .name = "RpcSrv", + .stack_size = 1024 * 4, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_BT - {.app = bt_srv, .name = "BtSrv", .stack_size = 1024, .icon = NULL}, + {.app = bt_srv, + .name = "BtSrv", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_CLI - {.app = cli_srv, .name = "CliSrv", .stack_size = 4096, .icon = NULL}, + {.app = cli_srv, + .name = "CliSrv", + .stack_size = 4096, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_DIALOGS - {.app = dialogs_srv, .name = "DialogsSrv", .stack_size = 1024, .icon = NULL}, + {.app = dialogs_srv, + .name = "DialogsSrv", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_DOLPHIN - {.app = dolphin_srv, .name = "DolphinSrv", .stack_size = 1024, .icon = NULL}, + {.app = dolphin_srv, + .name = "DolphinSrv", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_DESKTOP #ifdef SRV_UPDATER #error SRV_UPDATER and SRV_DESKTOP are mutually exclusive! #endif - {.app = desktop_srv, .name = "DesktopSrv", .stack_size = 2048, .icon = NULL}, + {.app = desktop_srv, + .name = "DesktopSrv", + .stack_size = 2048, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_GUI - {.app = gui_srv, .name = "GuiSrv", .stack_size = 2048, .icon = NULL}, + {.app = gui_srv, + .name = "GuiSrv", + .stack_size = 2048, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_INPUT - {.app = input_srv, .name = "InputSrv", .stack_size = 1024, .icon = NULL}, + {.app = input_srv, + .name = "InputSrv", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_LOADER - {.app = loader_srv, .name = "LoaderSrv", .stack_size = 1024, .icon = NULL}, + {.app = loader_srv, + .name = "LoaderSrv", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_NOTIFICATION - {.app = notification_srv, .name = "NotificationSrv", .stack_size = 1536, .icon = NULL}, + {.app = notification_srv, + .name = "NotificationSrv", + .stack_size = 1536, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_POWER - {.app = power_srv, .name = "PowerSrv", .stack_size = 1024, .icon = NULL}, + {.app = power_srv, + .name = "PowerSrv", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_STORAGE - {.app = storage_srv, .name = "StorageSrv", .stack_size = 3072, .icon = NULL}, + {.app = storage_srv, + .name = "StorageSrv", + .stack_size = 3072, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_UPDATER #ifdef SRV_DESKTOP #error SRV_UPDATER and SRV_DESKTOP are mutually exclusive! #endif - {.app = updater_srv, .name = "UpdaterSrv", .stack_size = 2048, .icon = NULL}, + {.app = updater_srv, + .name = "UpdaterSrv", + .stack_size = 2048, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif }; @@ -139,7 +191,11 @@ const FlipperApplication FLIPPER_SYSTEM_APPS[] = { #ifdef SRV_UPDATER #error APP_UPDATER and SRV_UPDATER are mutually exclusive! #endif - {.app = updater_srv, .name = "UpdaterApp", .stack_size = 2048, .icon = NULL}, + {.app = updater_srv, + .name = "UpdaterApp", + .stack_size = 2048, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif }; @@ -149,35 +205,67 @@ const size_t FLIPPER_SYSTEM_APPS_COUNT = COUNT_OF(FLIPPER_SYSTEM_APPS); const FlipperApplication FLIPPER_APPS[] = { #ifdef APP_SUBGHZ - {.app = subghz_app, .name = "Sub-GHz", .stack_size = 2048, .icon = &A_Sub1ghz_14}, + {.app = subghz_app, + .name = "Sub-GHz", + .stack_size = 2048, + .icon = &A_Sub1ghz_14, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_LF_RFID - {.app = lfrfid_app, .name = "125 kHz RFID", .stack_size = 2048, .icon = &A_125khz_14}, + {.app = lfrfid_app, + .name = "125 kHz RFID", + .stack_size = 2048, + .icon = &A_125khz_14, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_NFC - {.app = nfc_app, .name = "NFC", .stack_size = 4096, .icon = &A_NFC_14}, + {.app = nfc_app, + .name = "NFC", + .stack_size = 4096, + .icon = &A_NFC_14, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_INFRARED - {.app = infrared_app, .name = "Infrared", .stack_size = 1024 * 3, .icon = &A_Infrared_14}, + {.app = infrared_app, + .name = "Infrared", + .stack_size = 1024 * 3, + .icon = &A_Infrared_14, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_GPIO - {.app = gpio_app, .name = "GPIO", .stack_size = 1024, .icon = &A_GPIO_14}, + {.app = gpio_app, + .name = "GPIO", + .stack_size = 1024, + .icon = &A_GPIO_14, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_IBUTTON - {.app = ibutton_app, .name = "iButton", .stack_size = 2048, .icon = &A_iButton_14}, + {.app = ibutton_app, + .name = "iButton", + .stack_size = 2048, + .icon = &A_iButton_14, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_BAD_USB - {.app = bad_usb_app, .name = "Bad USB", .stack_size = 2048, .icon = &A_BadUsb_14}, + {.app = bad_usb_app, + .name = "Bad USB", + .stack_size = 2048, + .icon = &A_BadUsb_14, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_U2F - {.app = u2f_app, .name = "U2F", .stack_size = 2048, .icon = &A_U2F_14}, + {.app = u2f_app, + .name = "U2F", + .stack_size = 2048, + .icon = &A_U2F_14, + .flags = FlipperApplicationFlagDefault}, #endif }; @@ -234,15 +322,27 @@ const size_t FLIPPER_ON_SYSTEM_START_COUNT = COUNT_OF(FLIPPER_ON_SYSTEM_START); // Plugin menu const FlipperApplication FLIPPER_PLUGINS[] = { #ifdef APP_BLE_HID - {.app = bt_hid_app, .name = "Bluetooth Remote", .stack_size = 1024, .icon = NULL}, + {.app = bt_hid_app, + .name = "Bluetooth Remote", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_MUSIC_PLAYER - {.app = music_player_app, .name = "Music Player", .stack_size = 1024, .icon = &A_Plugins_14}, + {.app = music_player_app, + .name = "Music Player", + .stack_size = 1024, + .icon = &A_Plugins_14, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_SNAKE_GAME - {.app = snake_game_app, .name = "Snake Game", .stack_size = 1024, .icon = &A_Plugins_14}, + {.app = snake_game_app, + .name = "Snake Game", + .stack_size = 1024, + .icon = &A_Plugins_14, + .flags = FlipperApplicationFlagDefault}, #endif }; @@ -251,108 +351,201 @@ const size_t FLIPPER_PLUGINS_COUNT = COUNT_OF(FLIPPER_PLUGINS); // Plugin menu const FlipperApplication FLIPPER_DEBUG_APPS[] = { #ifdef APP_BLINK - {.app = blink_test_app, .name = "Blink Test", .stack_size = 1024, .icon = NULL}, + {.app = blink_test_app, + .name = "Blink Test", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_VIBRO_TEST - {.app = vibro_test_app, .name = "Vibro Test", .stack_size = 1024, .icon = NULL}, + {.app = vibro_test_app, + .name = "Vibro Test", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_KEYPAD_TEST - {.app = keypad_test_app, .name = "Keypad Test", .stack_size = 1024, .icon = NULL}, + {.app = keypad_test_app, + .name = "Keypad Test", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_ACCESSOR - {.app = accessor_app, .name = "Accessor", .stack_size = 4096, .icon = NULL}, + {.app = accessor_app, + .name = "Accessor", + .stack_size = 4096, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_USB_TEST - {.app = usb_test_app, .name = "USB Test", .stack_size = 1024, .icon = NULL}, + {.app = usb_test_app, + .name = "USB Test", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_USB_MOUSE - {.app = usb_mouse_app, .name = "USB Mouse Demo", .stack_size = 1024, .icon = NULL}, + {.app = usb_mouse_app, + .name = "USB Mouse Demo", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_UART_ECHO - {.app = uart_echo_app, .name = "Uart Echo", .stack_size = 2048, .icon = NULL}, + {.app = uart_echo_app, + .name = "Uart Echo", + .stack_size = 2048, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_INFRARED_MONITOR - {.app = infrared_monitor_app, .name = "Infrared Monitor", .stack_size = 1024, .icon = NULL}, + {.app = infrared_monitor_app, + .name = "Infrared Monitor", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_SCENED - {.app = scened_app, .name = "Templated Scene", .stack_size = 1024, .icon = NULL}, + {.app = scened_app, + .name = "Templated Scene", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_LF_RFID - {.app = lfrfid_debug_app, .name = "LF-RFID Debug", .stack_size = 1024, .icon = NULL}, + {.app = lfrfid_debug_app, + .name = "LF-RFID Debug", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_BT - {.app = bt_debug_app, .name = "Bluetooth Debug", .stack_size = 1024, .icon = NULL}, + {.app = bt_debug_app, + .name = "Bluetooth Debug", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_UNIT_TESTS - {.app = delay_test_app, .name = "Delay Test", .stack_size = 1024, .icon = NULL}, + {.app = delay_test_app, + .name = "Delay Test", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_DISPLAY_TEST - {.app = display_test_app, .name = "Display Test", .stack_size = 1024, .icon = NULL}, + {.app = display_test_app, + .name = "Display Test", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_BATTERY_TEST - {.app = battery_test_app, .name = "Battery Test", .stack_size = 1024, .icon = NULL}, + {.app = battery_test_app, + .name = "Battery Test", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_TEXT_BOX_TEST - {.app = text_box_test_app, .name = "Text Box Test", .stack_size = 1024, .icon = NULL}, + {.app = text_box_test_app, + .name = "Text Box Test", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif }; const size_t FLIPPER_DEBUG_APPS_COUNT = COUNT_OF(FLIPPER_DEBUG_APPS); #ifdef APP_ARCHIVE -const FlipperApplication FLIPPER_ARCHIVE = - {.app = archive_app, .name = "Archive", .stack_size = 4096, .icon = &A_FileManager_14}; +const FlipperApplication FLIPPER_ARCHIVE = { + .app = archive_app, + .name = "Archive", + .stack_size = 4096, + .icon = &A_FileManager_14, + .flags = FlipperApplicationFlagDefault}; #endif // Settings menu const FlipperApplication FLIPPER_SETTINGS_APPS[] = { #ifdef SRV_BT - {.app = bt_settings_app, .name = "Bluetooth", .stack_size = 1024, .icon = NULL}, + {.app = bt_settings_app, + .name = "Bluetooth", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_NOTIFICATION {.app = notification_settings_app, .name = "LCD and Notifications", .stack_size = 1024, - .icon = NULL}, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_STORAGE - {.app = storage_settings_app, .name = "Storage", .stack_size = 2048, .icon = NULL}, + {.app = storage_settings_app, + .name = "Storage", + .stack_size = 2048, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_POWER - {.app = power_settings_app, .name = "Power", .stack_size = 1024, .icon = NULL}, + {.app = power_settings_app, + .name = "Power", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagInsomniaSafe}, #endif #ifdef SRV_DESKTOP - {.app = desktop_settings_app, .name = "Desktop", .stack_size = 1024, .icon = NULL}, + {.app = desktop_settings_app, + .name = "Desktop", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_PASSPORT - {.app = passport_app, .name = "Passport", .stack_size = 1024, .icon = NULL}, + {.app = passport_app, + .name = "Passport", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef SRV_GUI - {.app = system_settings_app, .name = "System", .stack_size = 1024, .icon = NULL}, + {.app = system_settings_app, + .name = "System", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif #ifdef APP_ABOUT - {.app = about_settings_app, .name = "About", .stack_size = 1024, .icon = NULL}, + {.app = about_settings_app, + .name = "About", + .stack_size = 1024, + .icon = NULL, + .flags = FlipperApplicationFlagDefault}, #endif }; diff --git a/applications/applications.h b/applications/applications.h index 705dba28d..bebe438ab 100644 --- a/applications/applications.h +++ b/applications/applications.h @@ -3,11 +3,17 @@ #include #include +typedef enum { + FlipperApplicationFlagDefault = 0, + FlipperApplicationFlagInsomniaSafe = (1 << 0), +} FlipperApplicationFlag; + typedef struct { const FuriThreadCallback app; const char* name; const size_t stack_size; const Icon* icon; + const FlipperApplicationFlag flags; } FlipperApplication; typedef void (*FlipperOnStartHook)(void); diff --git a/applications/gui/canvas.c b/applications/gui/canvas.c index fe07bd5e3..1e275aafb 100644 --- a/applications/gui/canvas.c +++ b/applications/gui/canvas.c @@ -17,8 +17,6 @@ const CanvasFontParameters canvas_font_params[FontTotalNumber] = { Canvas* canvas_init() { Canvas* canvas = malloc(sizeof(Canvas)); - furi_hal_power_insomnia_enter(); - // Setup u8g2 u8g2_Setup_st756x_flipper(&canvas->fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32); canvas->orientation = CanvasOrientationHorizontal; @@ -31,8 +29,6 @@ Canvas* canvas_init() { canvas_clear(canvas); canvas_commit(canvas); - furi_hal_power_insomnia_exit(); - return canvas; } diff --git a/applications/ibutton/ibutton_app.cpp b/applications/ibutton/ibutton_app.cpp index 73f59a908..43eb36924 100644 --- a/applications/ibutton/ibutton_app.cpp +++ b/applications/ibutton/ibutton_app.cpp @@ -41,7 +41,6 @@ iButtonApp::iButtonApp() : notification{"notification"} , storage{"storage"} , dialogs{"dialogs"} { - furi_hal_power_insomnia_enter(); key = ibutton_key_alloc(); key_worker = ibutton_worker_alloc(); ibutton_worker_start_thread(key_worker); @@ -56,8 +55,6 @@ iButtonApp::~iButtonApp() { ibutton_worker_stop_thread(key_worker); ibutton_worker_free(key_worker); ibutton_key_free(key); - - furi_hal_power_insomnia_exit(); } iButtonAppViewManager* iButtonApp::get_view_manager() { @@ -342,4 +339,4 @@ void iButtonApp::make_app_folder() { if(!storage_simply_mkdir(storage, app_folder)) { dialog_message_show_storage_error(dialogs, "Cannot create\napp folder"); } -} \ No newline at end of file +} diff --git a/applications/lfrfid/lfrfid_app.cpp b/applications/lfrfid/lfrfid_app.cpp index 4653eb2d5..c2274234b 100644 --- a/applications/lfrfid/lfrfid_app.cpp +++ b/applications/lfrfid/lfrfid_app.cpp @@ -31,11 +31,9 @@ LfRfidApp::LfRfidApp() , storage{"storage"} , dialogs{"dialogs"} , text_store(40) { - furi_hal_power_insomnia_enter(); } LfRfidApp::~LfRfidApp() { - furi_hal_power_insomnia_exit(); } void LfRfidApp::run(void* _args) { @@ -201,4 +199,4 @@ void LfRfidApp::make_app_folder() { if(!storage_simply_mkdir(storage, app_folder)) { dialog_message_show_storage_error(dialogs, "Cannot create\napp folder"); } -} \ No newline at end of file +} diff --git a/applications/loader/loader.c b/applications/loader/loader.c index 3882647ef..43e275ab9 100644 --- a/applications/loader/loader.c +++ b/applications/loader/loader.c @@ -238,7 +238,10 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con if(thread_state == FuriThreadStateRunning) { event.type = LoaderEventTypeApplicationStarted; furi_pubsub_publish(loader_instance->pubsub, &event); - furi_hal_power_insomnia_enter(); + + if(!loader_instance->application->flags & FlipperApplicationFlagInsomniaSafe) { + furi_hal_power_insomnia_enter(); + } } else if(thread_state == FuriThreadStateStopped) { FURI_LOG_I( TAG, @@ -251,7 +254,9 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con loader_instance->application_arguments = NULL; } - furi_hal_power_insomnia_exit(); + if(!loader_instance->application->flags & FlipperApplicationFlagInsomniaSafe) { + furi_hal_power_insomnia_exit(); + } loader_unlock(instance); event.type = LoaderEventTypeApplicationStopped; diff --git a/applications/nfc/nfc_worker.c b/applications/nfc/nfc_worker.c index f44335bba..6b3c8f092 100644 --- a/applications/nfc/nfc_worker.c +++ b/applications/nfc/nfc_worker.c @@ -86,7 +86,6 @@ void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state) { int32_t nfc_worker_task(void* context) { NfcWorker* nfc_worker = context; - furi_hal_power_insomnia_enter(); furi_hal_nfc_exit_sleep(); if(nfc_worker->state == NfcWorkerStateDetect) { @@ -110,7 +109,6 @@ int32_t nfc_worker_task(void* context) { } furi_hal_nfc_sleep(); nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); - furi_hal_power_insomnia_exit(); return 0; } diff --git a/applications/storage/storage_glue.c b/applications/storage/storage_glue.c index 7ce8ec2c2..09656ae34 100644 --- a/applications/storage/storage_glue.c +++ b/applications/storage/storage_glue.c @@ -39,12 +39,10 @@ void storage_data_init(StorageData* storage) { } bool storage_data_lock(StorageData* storage) { - furi_hal_power_insomnia_enter(); return (osMutexAcquire(storage->mutex, osWaitForever) == osOK); } bool storage_data_unlock(StorageData* storage) { - furi_hal_power_insomnia_exit(); return (osMutexRelease(storage->mutex) == osOK); } diff --git a/firmware/targets/f7/ble_glue/app_conf.h b/firmware/targets/f7/ble_glue/app_conf.h index 96a0c25b6..1406f9649 100644 --- a/firmware/targets/f7/ble_glue/app_conf.h +++ b/firmware/targets/f7/ble_glue/app_conf.h @@ -396,7 +396,7 @@ typedef enum { * keep debugger enabled while in any low power mode when set to 1 * should be set to 0 in production */ -#define CFG_DEBUGGER_SUPPORTED 0 +#define CFG_DEBUGGER_SUPPORTED 1 /** * When set to 1, the traces are enabled in the BLE services diff --git a/firmware/targets/f7/ble_glue/app_debug.c b/firmware/targets/f7/ble_glue/app_debug.c index 41d667048..e480ea364 100644 --- a/firmware/targets/f7/ble_glue/app_debug.c +++ b/firmware/targets/f7/ble_glue/app_debug.c @@ -1,25 +1,3 @@ -/* USER CODE BEGIN Header */ -/** - ****************************************************************************** - * File Name : app_debug.c - * Description : Debug capabilities source file for STM32WPAN Middleware - ****************************************************************************** - * @attention - * - *

© Copyright (c) 2020 STMicroelectronics. - * All rights reserved.

- * - * 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 ------------------------------------------------------------------*/ -/* USER CODE BEGIN Includes */ #include "utilities_common.h" #include "app_common.h" @@ -28,10 +6,7 @@ #include "tl.h" #include "dbg_trace.h" #include -/* USER CODE END Includes */ -/* Private typedef -----------------------------------------------------------*/ -/* USER CODE BEGIN PTD */ typedef PACKED_STRUCT { GPIO_TypeDef* port; uint16_t pin; @@ -39,10 +14,7 @@ typedef PACKED_STRUCT { uint8_t reserved; } APPD_GpioConfig_t; -/* USER CODE END PTD */ -/* Private defines -----------------------------------------------------------*/ -/* USER CODE BEGIN PD */ #define GPIO_NBR_OF_RF_SIGNALS 9 #define GPIO_CFG_NBR_OF_FEATURES 34 #define NBR_OF_TRACES_CONFIG_PARAMETERS 4 @@ -51,12 +23,11 @@ APPD_GpioConfig_t; /** * THIS SHALL BE SET TO A VALUE DIFFERENT FROM 0 ONLY ON REQUEST FROM ST SUPPORT */ -#define BLE_DTB_CFG 7 +#define BLE_DTB_CFG 0 +// #define BLE_DTB_CFG 7 #define SYS_DBG_CFG1 (SHCI_C2_DEBUG_OPTIONS_IPCORE_LP | SHCI_C2_DEBUG_OPTIONS_CPU2_STOP_EN) -/* USER CODE END PD */ /* Private variables ---------------------------------------------------------*/ -/* USER CODE BEGIN PV */ PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static SHCI_C2_DEBUG_TracesConfig_t APPD_TracesConfig = {0, 0, 0, 0}; PLACE_IN_SECTION("MB_MEM2") @@ -91,7 +62,7 @@ static const APPD_GpioConfig_t aGpioConfigList[GPIO_CFG_NBR_OF_FEATURES] = { {GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_TRACES_TX - Set on Entry / Reset on Exit */ {GPIOA, LL_GPIO_PIN_6, 1, 0}, /* HARD_FAULT - Set on Entry / Reset on Exit */ /* From v1.1.1 */ - {GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IP_CORE_LP_STATUS - Set on Entry / Reset on Exit */ + {GPIOC, LL_GPIO_PIN_1, 1, 0}, /* IP_CORE_LP_STATUS - Set on Entry / Reset on Exit */ /* From v1.2.0 */ {GPIOA, LL_GPIO_PIN_0, 0, 0}, /* END_OF_CONNECTION_EVENT - Set on Entry / Reset on Exit */ {GPIOA, LL_GPIO_PIN_0, 0, 0}, /* TIMER_SERVER_CALLBACK - Toggle on Entry */ @@ -130,65 +101,20 @@ static const APPD_GpioConfig_t aRfConfigList[GPIO_NBR_OF_RF_SIGNALS] = { {GPIOB, LL_GPIO_PIN_10, 0, 0}, /* DTB18 - FSM4 */ }; #endif -/* USER CODE END PV */ -/* Global variables ----------------------------------------------------------*/ -/* USER CODE BEGIN GV */ -/* USER CODE END GV */ - -/* Private function prototypes -----------------------------------------------*/ -/* USER CODE BEGIN PFP */ static void APPD_SetCPU2GpioConfig(void); static void APPD_BleDtbCfg(void); -/* USER CODE END PFP */ - -/* Functions Definition ------------------------------------------------------*/ -void APPD_Init(void) { -/* USER CODE BEGIN APPD_Init */ -#if(CFG_DEBUGGER_SUPPORTED == 1) - /** - * Keep debugger enabled while in any low power mode - */ - LL_DBGMCU_EnableDBGSleepMode(); - LL_DBGMCU_EnableDBGStopMode(); - - /***************** ENABLE DEBUGGER *************************************/ - LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_48); - -#else - LL_GPIO_InitTypeDef gpio_config = {0}; - LL_PWR_EnableVddUSB(); - - gpio_config.Mode = LL_GPIO_MODE_ANALOG; - gpio_config.Speed = LL_GPIO_SPEED_FREQ_LOW; - // gpio_config.OutputType = LL_GPIO_OUTPUT_PUSHPULL; - // gpio_config.Pull = LL_GPIO_PULL_NO; - // gpio_config.Alternate = LL_GPIO_AF_10; - gpio_config.Pin = LL_GPIO_PIN_15 | LL_GPIO_PIN_14 | LL_GPIO_PIN_13; - LL_GPIO_Init(GPIOA, &gpio_config); - - gpio_config.Pin = LL_GPIO_PIN_4 | LL_GPIO_PIN_3; - LL_GPIO_Init(GPIOB, &gpio_config); - - LL_DBGMCU_DisableDBGSleepMode(); - LL_DBGMCU_DisableDBGStopMode(); - LL_DBGMCU_DisableDBGStandbyMode(); - -#endif /* (CFG_DEBUGGER_SUPPORTED == 1) */ +void APPD_Init() { #if(CFG_DEBUG_TRACE != 0) DbgTraceInit(); #endif APPD_SetCPU2GpioConfig(); APPD_BleDtbCfg(); - - /* USER CODE END APPD_Init */ - return; } void APPD_EnableCPU2(void) { - /* USER CODE BEGIN APPD_EnableCPU2 */ SHCI_C2_DEBUG_Init_Cmd_Packet_t DebugCmdPacket = { {{0, 0, 0}}, /**< Does not need to be initialized */ {(uint8_t*)aGpioConfigList, @@ -204,6 +130,7 @@ void APPD_EnableCPU2(void) { /** GPIO DEBUG Initialization */ SHCI_C2_DEBUG_Init(&DebugCmdPacket); + // We don't need External Power Amplifier // LL_GPIO_InitTypeDef gpio_config; // gpio_config.Pull = GPIO_NOPULL; // gpio_config.Mode = GPIO_MODE_OUTPUT_PP; @@ -212,17 +139,10 @@ void APPD_EnableCPU2(void) { // HAL_GPIO_Init(GPIOC, &gpio_config); // SHCI_C2_ExtpaConfig((uint32_t)GPIOC, LL_GPIO_PIN_3, EXT_PA_ENABLED_LOW, EXT_PA_ENABLED); - /* USER CODE END APPD_EnableCPU2 */ return; } -/************************************************************* - * - * LOCAL FUNCTIONS - * - *************************************************************/ static void APPD_SetCPU2GpioConfig(void) { - /* USER CODE BEGIN APPD_SetCPU2GpioConfig */ LL_GPIO_InitTypeDef gpio_config = {0}; uint8_t local_loop; uint16_t gpioa_pin_list; @@ -259,8 +179,9 @@ static void APPD_SetCPU2GpioConfig(void) { gpio_config.OutputType = LL_GPIO_OUTPUT_PUSHPULL; gpio_config.Pull = LL_GPIO_PULL_NO; - gpio_config.Pin = LL_GPIO_PIN_15 | LL_GPIO_PIN_14 | LL_GPIO_PIN_13; - LL_GPIO_Init(GPIOA, &gpio_config); + // Never disable SWD, why would you? + // gpio_config.Pin = LL_GPIO_PIN_15 | LL_GPIO_PIN_14 | LL_GPIO_PIN_13; + // LL_GPIO_Init(GPIOA, &gpio_config); if(gpioa_pin_list != 0) { gpio_config.Pin = gpioa_pin_list; @@ -282,13 +203,9 @@ static void APPD_SetCPU2GpioConfig(void) { LL_GPIO_Init(GPIOC, &gpio_config); LL_GPIO_ResetOutputPin(GPIOC, gpioa_pin_list); } - - /* USER CODE END APPD_SetCPU2GpioConfig */ - return; } static void APPD_BleDtbCfg(void) { -/* USER CODE BEGIN APPD_BleDtbCfg */ #if(BLE_DTB_CFG != 0) LL_GPIO_InitTypeDef gpio_config = {0}; uint8_t local_loop; @@ -304,11 +221,9 @@ static void APPD_BleDtbCfg(void) { case(uint32_t)GPIOA: gpioa_pin_list |= aRfConfigList[local_loop].pin; break; - case(uint32_t)GPIOB: gpiob_pin_list |= aRfConfigList[local_loop].pin; break; - default: break; } @@ -334,16 +249,8 @@ static void APPD_BleDtbCfg(void) { LL_GPIO_Init(GPIOB, &gpio_config); } #endif - - /* USER CODE END APPD_BleDtbCfg */ - return; } -/************************************************************* - * - * WRAP FUNCTIONS - * -*************************************************************/ #if(CFG_DEBUG_TRACE != 0) void DbgOutputInit(void) { } @@ -353,5 +260,3 @@ void DbgOutputTraces(uint8_t* p_data, uint16_t size, void (*cb)(void)) { cb(); } #endif - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/firmware/targets/f7/ble_glue/ble_glue.c b/firmware/targets/f7/ble_glue/ble_glue.c index 64643dea9..ec4a617b8 100644 --- a/firmware/targets/f7/ble_glue/ble_glue.c +++ b/firmware/targets/f7/ble_glue/ble_glue.c @@ -63,9 +63,10 @@ void ble_glue_init() { LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI); /* Initialize the CPU2 reset value before starting CPU2 with C2BOOT */ LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); - furi_hal_power_insomnia_enter(); - // APPD_Init(); +#ifdef BLE_GLUE_DEBUG + APPD_Init(); +#endif // Initialize all transport layers TL_MM_Config_t tl_mm_config; @@ -198,7 +199,6 @@ bool ble_glue_start() { } bool ret = false; - furi_hal_power_insomnia_enter(); if(ble_app_init()) { FURI_LOG_I(TAG, "Radio stack started"); ble_glue->status = BleGlueStatusRadioStackRunning; @@ -213,7 +213,6 @@ bool ble_glue_start() { ble_glue->status = BleGlueStatusRadioStackMissing; ble_app_thread_stop(); } - furi_hal_power_insomnia_exit(); return ret; } @@ -293,8 +292,10 @@ static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status) { */ static void ble_glue_sys_user_event_callback(void* pPayload) { UNUSED(pPayload); - /* Traces channel initialization */ - // APPD_EnableCPU2( ); + +#ifdef BLE_GLUE_DEBUG + APPD_EnableCPU2(); +#endif TL_AsynchEvt_t* p_sys_event = (TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload); @@ -309,10 +310,8 @@ static void ble_glue_sys_user_event_callback(void* pPayload) { } ble_glue->status = BleGlueStatusC2Started; - furi_hal_power_insomnia_exit(); } else if(p_sys_event->subevtcode == SHCI_SUB_EVT_ERROR_NOTIF) { FURI_LOG_E(TAG, "Error during initialization"); - furi_hal_power_insomnia_exit(); } else if(p_sys_event->subevtcode == SHCI_SUB_EVT_BLE_NVM_RAM_UPDATE) { SHCI_C2_BleNvmRamUpdate_Evt_t* p_sys_ble_nvm_ram_update_event = (SHCI_C2_BleNvmRamUpdate_Evt_t*)p_sys_event->payload; @@ -444,4 +443,4 @@ BleGlueCommandResult ble_glue_fus_wait_operation() { } while(wip); return BleGlueCommandResultOK; -} \ No newline at end of file +} diff --git a/firmware/targets/f7/ble_glue/gap.c b/firmware/targets/f7/ble_glue/gap.c index b21095ed7..45191a5a5 100644 --- a/firmware/targets/f7/ble_glue/gap.c +++ b/firmware/targets/f7/ble_glue/gap.c @@ -115,7 +115,6 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { if(gap->enable_adv) { // Restart advertising gap_advertise_start(GapStateAdvFast); - furi_hal_power_insomnia_exit(); } GapEvent event = {.type = GapEventTypeDisconnected}; gap->on_event_cb(event, gap->context); @@ -151,8 +150,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { } break; - case EVT_LE_CONN_COMPLETE: - furi_hal_power_insomnia_enter(); + case EVT_LE_CONN_COMPLETE: { hci_le_connection_complete_event_rp0* event = (hci_le_connection_complete_event_rp0*)meta_evt->data; gap->connection_params.conn_interval = event->Conn_Interval; @@ -169,7 +167,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { gap_verify_connection_parameters(gap); // Start pairing by sending security request aci_gap_slave_security_req(event->Connection_Handle); - break; + } break; case EVT_LE_ADVERTISING_REPORT: { if(gap_scan) { @@ -414,7 +412,9 @@ static void gap_advertise_start(GapState new_state) { // Stop advertising status = aci_gap_set_non_discoverable(); if(status) { - FURI_LOG_E(TAG, "Stop Advertising Failed, result: %d", status); + FURI_LOG_E(TAG, "set_non_discoverable failed %d", status); + } else { + FURI_LOG_D(TAG, "set_non_discoverable success"); } } // Configure advertising @@ -431,7 +431,7 @@ static void gap_advertise_start(GapState new_state) { 0, 0); if(status) { - FURI_LOG_E(TAG, "Set discoverable err: %d", status); + FURI_LOG_E(TAG, "set_discoverable failed %d", status); } gap->state = new_state; GapEvent event = {.type = GapEventTypeStartAdvertising}; @@ -440,14 +440,25 @@ static void gap_advertise_start(GapState new_state) { } static void gap_advertise_stop() { + tBleStatus ret; if(gap->state > GapStateIdle) { if(gap->state == GapStateConnected) { // Terminate connection - aci_gap_terminate(gap->service.connection_handle, 0x13); + ret = aci_gap_terminate(gap->service.connection_handle, 0x13); + if(ret != BLE_STATUS_SUCCESS) { + FURI_LOG_E(TAG, "terminate failed %d", ret); + } else { + FURI_LOG_D(TAG, "terminate success"); + } } // Stop advertising osTimerStop(gap->advertise_timer); - aci_gap_set_non_discoverable(); + ret = aci_gap_set_non_discoverable(); + if(ret != BLE_STATUS_SUCCESS) { + FURI_LOG_E(TAG, "set_non_discoverable failed %d", ret); + } else { + FURI_LOG_D(TAG, "set_non_discoverable success"); + } gap->state = GapStateIdle; } GapEvent event = {.type = GapEventTypeStopAdvertising}; diff --git a/firmware/targets/f7/furi_hal/furi_hal.c b/firmware/targets/f7/furi_hal/furi_hal.c index 03031a930..e97c0e8c1 100644 --- a/firmware/targets/f7/furi_hal/furi_hal.c +++ b/firmware/targets/f7/furi_hal/furi_hal.c @@ -10,10 +10,10 @@ 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_os_init(); + furi_hal_spi_init_early(); furi_hal_i2c_init_early(); diff --git a/firmware/targets/f7/furi_hal/furi_hal_bt.c b/firmware/targets/f7/furi_hal/furi_hal_bt.c index 83d25ec9c..48d69844d 100755 --- a/firmware/targets/f7/furi_hal/furi_hal_bt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_bt.c @@ -134,7 +134,6 @@ bool furi_hal_bt_start_radio_stack() { // Wait until C2 is started or timeout if(!ble_glue_wait_for_c2_start(FURI_HAL_BT_C2_START_TIMEOUT)) { FURI_LOG_E(TAG, "Core2 start failed"); - LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); ble_glue_thread_stop(); break; } @@ -154,7 +153,6 @@ bool furi_hal_bt_start_radio_stack() { // Starting radio stack if(!ble_glue_start()) { FURI_LOG_E(TAG, "Failed to start radio stack"); - LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); ble_glue_thread_stop(); ble_app_thread_stop(); break; @@ -221,27 +219,39 @@ bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb, return ret; } +void furi_hal_bt_reinit() { + FURI_LOG_I(TAG, "Disconnect and stop advertising"); + furi_hal_bt_stop_advertising(); + + FURI_LOG_I(TAG, "Stop current profile services"); + current_profile->stop(); + + // Magic happens here + hci_reset(); + + FURI_LOG_I(TAG, "Stop BLE related RTOS threads"); + ble_app_thread_stop(); + gap_thread_stop(); + + FURI_LOG_I(TAG, "Reset SHCI"); + furi_check(ble_glue_reinit_c2()); + + osDelay(100); + ble_glue_thread_stop(); + + FURI_LOG_I(TAG, "Start BT initialization"); + furi_hal_bt_init(); + + furi_hal_bt_start_radio_stack(); +} + bool furi_hal_bt_change_app(FuriHalBtProfile profile, GapEventCallback event_cb, void* context) { furi_assert(event_cb); furi_assert(profile < FuriHalBtProfileNumber); bool ret = true; - FURI_LOG_I(TAG, "Stop current profile services"); - current_profile->stop(); - FURI_LOG_I(TAG, "Disconnect and stop advertising"); - furi_hal_bt_stop_advertising(); - FURI_LOG_I(TAG, "Shutdow 2nd core"); - LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); - FURI_LOG_I(TAG, "Stop BLE related RTOS threads"); - ble_app_thread_stop(); - gap_thread_stop(); - FURI_LOG_I(TAG, "Reset SHCI"); - ble_glue_reinit_c2(); - osDelay(100); - ble_glue_thread_stop(); - FURI_LOG_I(TAG, "Start BT initialization"); - furi_hal_bt_init(); - furi_hal_bt_start_radio_stack(); + furi_hal_bt_reinit(); + ret = furi_hal_bt_start_app(profile, event_cb, context); if(ret) { current_profile = &profile_config[profile]; diff --git a/firmware/targets/f7/furi_hal/furi_hal_clock.c b/firmware/targets/f7/furi_hal/furi_hal_clock.c index 022644220..09efe76dd 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_clock.c +++ b/firmware/targets/f7/furi_hal/furi_hal_clock.c @@ -204,6 +204,8 @@ void furi_hal_clock_switch_to_hsi() { while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) ; + + LL_FLASH_SetLatency(LL_FLASH_LATENCY_1); } void furi_hal_clock_switch_to_pll() { @@ -215,6 +217,8 @@ void furi_hal_clock_switch_to_pll() { while(!LL_RCC_PLL_IsReady()) ; + LL_FLASH_SetLatency(LL_FLASH_LATENCY_3); + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSE); diff --git a/firmware/targets/f7/furi_hal/furi_hal_debug.c b/firmware/targets/f7/furi_hal/furi_hal_debug.c new file mode 100644 index 000000000..3b5dfe622 --- /dev/null +++ b/firmware/targets/f7/furi_hal/furi_hal_debug.c @@ -0,0 +1,20 @@ +#include + +#include +#include + +void furi_hal_debug_enable() { + // Low power mode debug + LL_DBGMCU_EnableDBGSleepMode(); + LL_DBGMCU_EnableDBGStopMode(); + LL_DBGMCU_EnableDBGStandbyMode(); + LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_48); +} + +void furi_hal_debug_disable() { + // Low power mode debug + LL_DBGMCU_DisableDBGSleepMode(); + LL_DBGMCU_DisableDBGStopMode(); + LL_DBGMCU_DisableDBGStandbyMode(); + LL_EXTI_DisableIT_32_63(LL_EXTI_LINE_48); +} diff --git a/firmware/targets/f7/furi_hal/furi_hal_i2c.c b/firmware/targets/f7/furi_hal/furi_hal_i2c.c index 7e0bee58b..fdef11270 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_i2c.c +++ b/firmware/targets/f7/furi_hal/furi_hal_i2c.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include @@ -23,6 +24,7 @@ void furi_hal_i2c_init() { } void furi_hal_i2c_acquire(FuriHalI2cBusHandle* handle) { + furi_hal_power_insomnia_enter(); // Lock bus access handle->bus->callback(handle->bus, FuriHalI2cBusEventLock); // Ensuree that no active handle set @@ -46,6 +48,7 @@ void furi_hal_i2c_release(FuriHalI2cBusHandle* handle) { handle->bus->current_handle = NULL; // Unlock bus handle->bus->callback(handle->bus, FuriHalI2cBusEventUnlock); + furi_hal_power_insomnia_exit(); } bool furi_hal_i2c_tx( diff --git a/firmware/targets/f7/furi_hal/furi_hal_idle_timer.h b/firmware/targets/f7/furi_hal/furi_hal_idle_timer.h index 61afd631c..36b45755a 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_idle_timer.h +++ b/firmware/targets/f7/furi_hal/furi_hal_idle_timer.h @@ -7,12 +7,14 @@ // 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 +#define FURI_HAL_IDLE_TIMER LPTIM1 +#define FURI_HAL_IDLE_TIMER_IRQ LPTIM1_IRQn static inline void furi_hal_idle_timer_init() { // Configure clock source - LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_LSE); + LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_LSE); + // There is a theoretical possibility that we need it + LL_APB1_GRP1_EnableClockSleep(LL_APB1_GRP1_PERIPH_LPTIM1); // Set interrupt priority and enable them NVIC_SetPriority( FURI_HAL_IDLE_TIMER_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0)); diff --git a/firmware/targets/f7/furi_hal/furi_hal_interrupt.c b/firmware/targets/f7/furi_hal/furi_hal_interrupt.c index d122fbc73..526c9f3da 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_interrupt.c +++ b/firmware/targets/f7/furi_hal/furi_hal_interrupt.c @@ -54,6 +54,10 @@ const IRQn_Type furi_hal_interrupt_irqn[FuriHalInterruptIdMax] = { // HSEM [FuriHalInterruptIdHsem] = HSEM_IRQn, + + // LPTIMx + [FuriHalInterruptIdLpTim1] = LPTIM1_IRQn, + [FuriHalInterruptIdLpTim2] = LPTIM2_IRQn, }; __attribute__((always_inline)) static inline void @@ -82,6 +86,16 @@ void furi_hal_interrupt_init() { NVIC_SetPriority(PendSV_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0)); + NVIC_SetPriority(FPU_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0)); + NVIC_EnableIRQ(FPU_IRQn); + + LL_SYSCFG_DisableIT_FPU_IOC(); + LL_SYSCFG_DisableIT_FPU_DZC(); + LL_SYSCFG_DisableIT_FPU_UFC(); + LL_SYSCFG_DisableIT_FPU_OFC(); + LL_SYSCFG_DisableIT_FPU_IDC(); + LL_SYSCFG_DisableIT_FPU_IXC(); + FURI_LOG_I(TAG, "Init OK"); } @@ -120,82 +134,82 @@ void furi_hal_interrupt_set_isr_ex( } /* Timer 2 */ -void TIM2_IRQHandler(void) { +void TIM2_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdTIM2); } /* Timer 1 Update */ -void TIM1_UP_TIM16_IRQHandler(void) { +void TIM1_UP_TIM16_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdTim1UpTim16); } -void TIM1_TRG_COM_TIM17_IRQHandler(void) { +void TIM1_TRG_COM_TIM17_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdTim1TrgComTim17); } -void TIM1_CC_IRQHandler(void) { +void TIM1_CC_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdTim1Cc); } /* DMA 1 */ -void DMA1_Channel1_IRQHandler(void) { +void DMA1_Channel1_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch1); } -void DMA1_Channel2_IRQHandler(void) { +void DMA1_Channel2_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch2); } -void DMA1_Channel3_IRQHandler(void) { +void DMA1_Channel3_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch3); } -void DMA1_Channel4_IRQHandler(void) { +void DMA1_Channel4_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch4); } -void DMA1_Channel5_IRQHandler(void) { +void DMA1_Channel5_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch5); } -void DMA1_Channel6_IRQHandler(void) { +void DMA1_Channel6_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch6); } -void DMA1_Channel7_IRQHandler(void) { +void DMA1_Channel7_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch7); } /* DMA 2 */ -void DMA2_Channel1_IRQHandler(void) { +void DMA2_Channel1_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch1); } -void DMA2_Channel2_IRQHandler(void) { +void DMA2_Channel2_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch2); } -void DMA2_Channel3_IRQHandler(void) { +void DMA2_Channel3_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch3); } -void DMA2_Channel4_IRQHandler(void) { +void DMA2_Channel4_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch4); } -void DMA2_Channel5_IRQHandler(void) { +void DMA2_Channel5_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch5); } -void DMA2_Channel6_IRQHandler(void) { +void DMA2_Channel6_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch6); } -void DMA2_Channel7_IRQHandler(void) { +void DMA2_Channel7_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch7); } -void HSEM_IRQHandler(void) { +void HSEM_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdHsem); } @@ -211,11 +225,11 @@ void TAMP_STAMP_LSECSS_IRQHandler(void) { } } -void RCC_IRQHandler(void) { +void RCC_IRQHandler() { furi_hal_interrupt_call(FuriHalInterruptIdRcc); } -void NMI_Handler(void) { +void NMI_Handler() { if(LL_RCC_IsActiveFlag_HSECSS()) { LL_RCC_ClearFlag_HSECSS(); FURI_LOG_E(TAG, "HSE CSS fired: resetting system"); @@ -223,23 +237,23 @@ void NMI_Handler(void) { } } -void HardFault_Handler(void) { +void HardFault_Handler() { furi_crash("HardFault"); } -void MemManage_Handler(void) { +void MemManage_Handler() { furi_crash("MemManage"); } -void BusFault_Handler(void) { +void BusFault_Handler() { furi_crash("BusFault"); } -void UsageFault_Handler(void) { +void UsageFault_Handler() { furi_crash("UsageFault"); } -void DebugMon_Handler(void) { +void DebugMon_Handler() { } #include "usbd_core.h" @@ -249,20 +263,35 @@ extern usbd_device udev; extern void HW_IPCC_Tx_Handler(); extern void HW_IPCC_Rx_Handler(); -void SysTick_Handler(void) { +void SysTick_Handler() { furi_hal_os_tick(); } -void USB_LP_IRQHandler(void) { +void USB_LP_IRQHandler() { #ifndef FURI_RAM_EXEC usbd_poll(&udev); #endif } -void IPCC_C1_TX_IRQHandler(void) { +void USB_HP_IRQHandler() { +} + +void IPCC_C1_TX_IRQHandler() { HW_IPCC_Tx_Handler(); } -void IPCC_C1_RX_IRQHandler(void) { +void IPCC_C1_RX_IRQHandler() { HW_IPCC_Rx_Handler(); } + +void FPU_IRQHandler() { + furi_crash("FpuFault"); +} + +void LPTIM1_IRQHandler() { + furi_hal_interrupt_call(FuriHalInterruptIdLpTim1); +} + +void LPTIM2_IRQHandler() { + furi_hal_interrupt_call(FuriHalInterruptIdLpTim2); +} diff --git a/firmware/targets/f7/furi_hal/furi_hal_interrupt.h b/firmware/targets/f7/furi_hal/furi_hal_interrupt.h index 725e779e0..8a280ff8d 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_interrupt.h +++ b/firmware/targets/f7/furi_hal/furi_hal_interrupt.h @@ -45,6 +45,10 @@ typedef enum { // HSEM FuriHalInterruptIdHsem, + // LPTIMx + FuriHalInterruptIdLpTim1, + FuriHalInterruptIdLpTim2, + // Service value FuriHalInterruptIdMax, } FuriHalInterruptId; diff --git a/firmware/targets/f7/furi_hal/furi_hal_os.c b/firmware/targets/f7/furi_hal/furi_hal_os.c index e282645bc..8beb0d084 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_os.c +++ b/firmware/targets/f7/furi_hal/furi_hal_os.c @@ -1,8 +1,10 @@ #include #include #include -#include +#include +#include #include + #include #include @@ -18,32 +20,32 @@ #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) +#define FURI_HAL_OS_NVIC_IS_PENDING() (NVIC->ISPR[0] || NVIC->ISPR[1]) +#define FURI_HAL_OS_EXTI_LINE_0_31 0 +#define FURI_HAL_OS_EXTI_LINE_32_63 1 + +// Arbitrary (but small) number for better tick consistency +#define FURI_HAL_OS_EXTRA_CNT 3 + #ifdef FURI_HAL_OS_DEBUG #include -#define LED_SLEEP_PORT GPIOA -#define LED_SLEEP_PIN LL_GPIO_PIN_7 -#define LED_TICK_PORT GPIOA -#define LED_TICK_PIN LL_GPIO_PIN_6 -#define LED_SECOND_PORT GPIOA -#define LED_SECOND_PIN LL_GPIO_PIN_4 - void furi_hal_os_timer_callback() { - LL_GPIO_TogglePin(LED_SECOND_PORT, LED_SECOND_PIN); + furi_hal_gpio_write(&gpio_ext_pa4, !furi_hal_gpio_read(&gpio_ext_pa4)); } #endif extern void xPortSysTickHandler(); -static volatile uint32_t furi_hal_os_skew = 0; +static volatile uint32_t furi_hal_os_skew; void furi_hal_os_init() { 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); + furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull); + furi_hal_gpio_init_simple(&gpio_ext_pa6, GpioModeOutputPushPull); + furi_hal_gpio_init_simple(&gpio_ext_pa4, GpioModeOutputPushPull); osTimerId_t second_timer = osTimerNew(furi_hal_os_timer_callback, osTimerPeriodic, NULL, NULL); osTimerStart(second_timer, FURI_HAL_OS_TICK_HZ); #endif @@ -54,12 +56,61 @@ void furi_hal_os_init() { void furi_hal_os_tick() { if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { #ifdef FURI_HAL_OS_DEBUG - LL_GPIO_TogglePin(LED_TICK_PORT, LED_TICK_PIN); + furi_hal_gpio_write(&gpio_ext_pa6, !furi_hal_gpio_read(&gpio_ext_pa6)); #endif xPortSysTickHandler(); } } +#ifdef FURI_HAL_OS_DEBUG +// Find out the IRQ number while debugging +static void furi_hal_os_nvic_dbg_trap() { + for(int32_t i = WWDG_IRQn; i <= DMAMUX1_OVR_IRQn; i++) { + if(NVIC_GetPendingIRQ(i)) { + (void)i; + // Break here + __NOP(); + } + } +} + +// Find out the EXTI line number while debugging +static void furi_hal_os_exti_dbg_trap(uint32_t exti, uint32_t val) { + for(uint32_t i = 0; val; val >>= 1U, ++i) { + if(val & 1U) { + (void)exti; + (void)i; + // Break here + __NOP(); + } + } +} +#endif + +static inline bool furi_hal_os_is_pending_irq() { + if(FURI_HAL_OS_NVIC_IS_PENDING()) { +#ifdef FURI_HAL_OS_DEBUG + furi_hal_os_nvic_dbg_trap(); +#endif + return true; + } + + uint32_t exti_lines_active; + if((exti_lines_active = LL_EXTI_ReadFlag_0_31(LL_EXTI_LINE_ALL_0_31))) { +#ifdef FURI_HAL_OS_DEBUG + furi_hal_os_exti_dbg_trap(FURI_HAL_OS_EXTI_LINE_0_31, exti_lines_active); +#endif + return true; + } else if((exti_lines_active = LL_EXTI_ReadFlag_32_63(LL_EXTI_LINE_ALL_32_63))) { +#ifdef FURI_HAL_OS_DEBUG + furi_hal_os_exti_dbg_trap(FURI_HAL_OS_EXTI_LINE_32_63, exti_lines_active); +#endif + return true; + } + + return false; +} + static inline uint32_t furi_hal_os_sleep(TickType_t expected_idle_ticks) { // Stop ticks furi_hal_clock_suspend_tick(); @@ -68,20 +119,20 @@ static inline uint32_t furi_hal_os_sleep(TickType_t expected_idle_ticks) { 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); + furi_hal_gpio_write(&gpio_ext_pa7, 0); #endif // Go to sleep mode furi_hal_power_sleep(); #ifdef FURI_HAL_OS_DEBUG - LL_GPIO_SetOutputPin(LED_SLEEP_PORT, LED_SLEEP_PIN); + furi_hal_gpio_write(&gpio_ext_pa7, 1); #endif // Calculate how much time we spent in the sleep - uint32_t after_cnt = furi_hal_idle_timer_get_cnt() + furi_hal_os_skew; + uint32_t after_cnt = furi_hal_idle_timer_get_cnt() + furi_hal_os_skew + FURI_HAL_OS_EXTRA_CNT; uint32_t after_tick = FURI_HAL_OS_IDLE_CNT_TO_TICKS(after_cnt); - furi_hal_os_skew = after_cnt - (after_cnt / after_tick); + furi_hal_os_skew = after_cnt - FURI_HAL_OS_TICKS_TO_IDLE_CNT(after_tick); bool cmpm = LL_LPTIM_IsActiveFlag_CMPM(FURI_HAL_IDLE_TIMER); bool arrm = LL_LPTIM_IsActiveFlag_ARRM(FURI_HAL_IDLE_TIMER); @@ -110,7 +161,7 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) { __disable_irq(); // Confirm OS that sleep is still possible - if(eTaskConfirmSleepModeStatus() == eAbortSleep) { + if(eTaskConfirmSleepModeStatus() == eAbortSleep || furi_hal_os_is_pending_irq()) { __enable_irq(); return; } diff --git a/firmware/targets/f7/furi_hal/furi_hal_power.c b/firmware/targets/f7/furi_hal/furi_hal_power.c index 2b78c7f0b..52bb7bcfe 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_power.c +++ b/firmware/targets/f7/furi_hal/furi_hal_power.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,12 @@ #define TAG "FuriHalPower" +#ifdef FURI_HAL_POWER_DEEP_SLEEP_ENABLED +#define FURI_HAL_POWER_DEEP_INSOMNIA 0 +#else +#define FURI_HAL_POWER_DEEP_INSOMNIA 1 +#endif + typedef struct { volatile uint8_t insomnia; volatile uint8_t deep_insomnia; @@ -28,7 +35,7 @@ typedef struct { static volatile FuriHalPower furi_hal_power = { .insomnia = 0, - .deep_insomnia = 1, + .deep_insomnia = FURI_HAL_POWER_DEEP_INSOMNIA, .suppress_charge = 0, }; @@ -70,11 +77,6 @@ const ParamCEDV cedv = { .DOD100 = 3299, }; -void HAL_RCC_CSSCallback(void) { - // TODO: notify user about issue with HSE - furi_hal_power_reset(); -} - void furi_hal_power_init() { LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); LL_PWR_SMPS_SetMode(LL_PWR_SMPS_STEP_DOWN); @@ -84,6 +86,11 @@ void furi_hal_power_init() { bq25896_init(&furi_hal_i2c_handle_power); furi_hal_i2c_release(&furi_hal_i2c_handle_power); +#ifdef FURI_HAL_OS_DEBUG + furi_hal_gpio_init_simple(&gpio_ext_pb2, GpioModeOutputPushPull); + furi_hal_gpio_init_simple(&gpio_ext_pc3, GpioModeOutputPushPull); +#endif + FURI_LOG_I(TAG, "Init OK"); } @@ -140,12 +147,28 @@ void furi_hal_power_light_sleep() { __WFI(); } +static inline void furi_hal_power_suspend_aux_periphs() { + // Disable USART + furi_hal_uart_suspend(FuriHalUartIdUSART1); + furi_hal_uart_suspend(FuriHalUartIdLPUART1); + // TODO: Disable USB +} + +static inline void furi_hal_power_resume_aux_periphs() { + // Re-enable USART + furi_hal_uart_resume(FuriHalUartIdUSART1); + furi_hal_uart_resume(FuriHalUartIdLPUART1); + // TODO: Re-enable USB +} + void furi_hal_power_deep_sleep() { + furi_hal_power_suspend_aux_periphs(); + while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)) ; if(!LL_HSEM_1StepLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID)) { - if(LL_PWR_IsActiveFlag_C2DS()) { + if(LL_PWR_IsActiveFlag_C2DS() || LL_PWR_IsActiveFlag_C2SB()) { // Release ENTRY_STOP_MODE semaphore LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0); @@ -163,7 +186,8 @@ void furi_hal_power_deep_sleep() { LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0); // Prepare deep sleep - LL_PWR_SetPowerMode(LL_PWR_MODE_STOP1); + LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2); + LL_C2_PWR_SetPowerMode(LL_PWR_MODE_STOP2); LL_LPM_EnableDeepSleep(); #if defined(__CC_ARM) @@ -173,6 +197,15 @@ void furi_hal_power_deep_sleep() { __WFI(); + LL_LPM_EnableSleep(); + + // Make sure that values differ to prevent disaster on wfi + LL_PWR_SetPowerMode(LL_PWR_MODE_STOP0); + LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); + + LL_PWR_ClearFlag_C1STOP_C1STB(); + LL_PWR_ClearFlag_C2STOP_C2STB(); + /* Release ENTRY_STOP_MODE semaphore */ LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0); @@ -184,13 +217,31 @@ void furi_hal_power_deep_sleep() { } LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0); + + furi_hal_power_resume_aux_periphs(); } void furi_hal_power_sleep() { if(furi_hal_power_deep_sleep_available()) { +#ifdef FURI_HAL_OS_DEBUG + furi_hal_gpio_write(&gpio_ext_pc3, 1); +#endif + furi_hal_power_deep_sleep(); + +#ifdef FURI_HAL_OS_DEBUG + furi_hal_gpio_write(&gpio_ext_pc3, 0); +#endif } else { +#ifdef FURI_HAL_OS_DEBUG + furi_hal_gpio_write(&gpio_ext_pb2, 1); +#endif + furi_hal_power_light_sleep(); + +#ifdef FURI_HAL_OS_DEBUG + furi_hal_gpio_write(&gpio_ext_pb2, 0); +#endif } } @@ -215,6 +266,38 @@ bool furi_hal_power_is_charging() { return ret; } +void furi_hal_power_shutdown() { + furi_hal_power_insomnia_enter(); + + furi_hal_bt_reinit(); + + while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)) + ; + + if(!LL_HSEM_1StepLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID)) { + if(LL_PWR_IsActiveFlag_C2DS() || LL_PWR_IsActiveFlag_C2SB()) { + // Release ENTRY_STOP_MODE semaphore + LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0); + } + } + + // Prepare Wakeup pin + LL_PWR_SetWakeUpPinPolarityLow(LL_PWR_WAKEUP_PIN2); + LL_PWR_EnableWakeUpPin(LL_PWR_WAKEUP_PIN2); + LL_C2_PWR_EnableWakeUpPin(LL_PWR_WAKEUP_PIN2); + + /* Release RCC semaphore */ + LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0); + + LL_PWR_DisableBootC2(); + LL_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); + LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); + LL_LPM_EnableDeepSleep(); + + __WFI(); + furi_crash("Insomniac core2"); +} + void furi_hal_power_off() { furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); bq25896_poweroff(&furi_hal_i2c_handle_power); diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.c b/firmware/targets/f7/furi_hal/furi_hal_resources.c index 901955856..e548ffaf3 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.c +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.c @@ -1,6 +1,9 @@ #include #include +#include +#include + const GpioPin vibro_gpio = {.port = VIBRO_GPIO_Port, .pin = VIBRO_Pin}; const GpioPin ibutton_gpio = {.port = iBTN_GPIO_Port, .pin = iBTN_Pin}; @@ -9,7 +12,7 @@ const GpioPin gpio_rf_sw_0 = {.port = RF_SW_0_GPIO_Port, .pin = RF_SW_0_Pin}; const GpioPin gpio_subghz_cs = {.port = CC1101_CS_GPIO_Port, .pin = CC1101_CS_Pin}; const GpioPin gpio_display_cs = {.port = DISPLAY_CS_GPIO_Port, .pin = DISPLAY_CS_Pin}; -const GpioPin gpio_display_rst = {.port = DISPLAY_RST_GPIO_Port, .pin = DISPLAY_RST_Pin}; +const GpioPin gpio_display_rst_n = {.port = DISPLAY_RST_GPIO_Port, .pin = DISPLAY_RST_Pin}; const GpioPin gpio_display_di = {.port = DISPLAY_DI_GPIO_Port, .pin = DISPLAY_DI_Pin}; const GpioPin gpio_sdcard_cs = {.port = SD_CS_GPIO_Port, .pin = SD_CS_Pin}; const GpioPin gpio_sdcard_cd = {.port = SD_CD_GPIO_Port, .pin = SD_CD_Pin}; @@ -72,14 +75,32 @@ const size_t input_pins_count = sizeof(input_pins) / sizeof(InputPin); void furi_hal_resources_init_early() { furi_hal_gpio_init(&gpio_button_left, GpioModeInput, GpioPullUp, GpioSpeedLow); - furi_hal_gpio_init_simple(&gpio_display_rst, GpioModeOutputPushPull); + + // Display pins + furi_hal_gpio_write(&gpio_display_rst_n, 1); + furi_hal_gpio_init_simple(&gpio_display_rst_n, GpioModeOutputPushPull); furi_hal_gpio_init_simple(&gpio_display_di, GpioModeOutputPushPull); + // Alternative pull configuration for shutdown + SET_BIT(PWR->PUCRB, DISPLAY_RST_Pin); + CLEAR_BIT(PWR->PDCRB, DISPLAY_RST_Pin); + SET_BIT(PWR->CR3, PWR_CR3_APC); + // Hard reset USB furi_hal_gpio_init_simple(&gpio_usb_dm, GpioModeOutputOpenDrain); furi_hal_gpio_init_simple(&gpio_usb_dp, GpioModeOutputOpenDrain); furi_hal_gpio_write(&gpio_usb_dm, 0); furi_hal_gpio_write(&gpio_usb_dp, 0); + + // External header pins + furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_ext_pc3, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_ext_pb2, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_ext_pb3, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_ext_pa4, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_ext_pa6, GpioModeAnalog, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_init(&gpio_ext_pa7, GpioModeAnalog, GpioPullNo, GpioSpeedLow); } void furi_hal_resources_deinit_early() { @@ -92,19 +113,9 @@ void furi_hal_resources_init() { input_pins[i].gpio, GpioModeInterruptRiseFall, GpioPullUp, GpioSpeedLow); } - // External header pins - furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_ext_pc3, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_ext_pb2, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_ext_pb3, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_ext_pa4, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_ext_pa6, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_init(&gpio_ext_pa7, GpioModeAnalog, GpioPullNo, GpioSpeedLow); - // Display pins - furi_hal_gpio_init(&gpio_display_rst, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); - furi_hal_gpio_write(&gpio_display_rst, 0); + furi_hal_gpio_init(&gpio_display_rst_n, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(&gpio_display_rst_n, 0); furi_hal_gpio_init(&gpio_display_di, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); furi_hal_gpio_write(&gpio_display_di, 0); diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.h b/firmware/targets/f7/furi_hal/furi_hal_resources.h index eaafd7c52..69485307b 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.h +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.h @@ -48,7 +48,7 @@ extern const GpioPin gpio_rf_sw_0; extern const GpioPin gpio_subghz_cs; extern const GpioPin gpio_display_cs; -extern const GpioPin gpio_display_rst; +extern const GpioPin gpio_display_rst_n; extern const GpioPin gpio_display_di; extern const GpioPin gpio_sdcard_cs; extern const GpioPin gpio_sdcard_cd; diff --git a/firmware/targets/f7/furi_hal/furi_hal_rtc.c b/firmware/targets/f7/furi_hal/furi_hal_rtc.c index 748d7e41c..b580a04b7 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_rtc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_rtc.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -36,7 +37,6 @@ void furi_hal_rtc_init_early() { // LSE and RTC LL_PWR_EnableBkUpAccess(); if(!RTC_CLOCK_IS_READY()) { - // Start LSI1 needed for CSS LL_RCC_LSI1_Enable(); // Try to start LSE normal way LL_RCC_LSE_SetDriveCapability(LL_RCC_LSEDRIVE_HIGH); @@ -55,8 +55,6 @@ void furi_hal_rtc_init_early() { } // Set RTC domain clock to LSE LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE); - // Enable LSE CSS - LL_RCC_LSE_EnableCSS(); } // Enable clocking LL_RCC_EnableRTC(); @@ -74,6 +72,12 @@ void furi_hal_rtc_init_early() { data->version = FURI_HAL_RTC_HEADER_VERSION; furi_hal_rtc_set_register(FuriHalRtcRegisterHeader, data_reg); } + + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { + furi_hal_debug_enable(); + } else { + furi_hal_debug_disable(); + } } void furi_hal_rtc_deinit_early() { @@ -126,6 +130,10 @@ void furi_hal_rtc_set_flag(FuriHalRtcFlag flag) { DeveloperReg* data = (DeveloperReg*)&data_reg; data->flags |= flag; furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg); + + if(flag & FuriHalRtcFlagDebug) { + furi_hal_debug_enable(); + } } void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag) { @@ -133,6 +141,10 @@ void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag) { DeveloperReg* data = (DeveloperReg*)&data_reg; data->flags &= ~flag; furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg); + + if(flag & FuriHalRtcFlagDebug) { + furi_hal_debug_disable(); + } } bool furi_hal_rtc_is_flag_set(FuriHalRtcFlag flag) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_spi.c b/firmware/targets/f7/furi_hal/furi_hal_spi.c index d74a394a7..01cb3ae68 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_spi.c +++ b/firmware/targets/f7/furi_hal/furi_hal_spi.c @@ -1,5 +1,6 @@ #include "furi_hal_spi.h" #include "furi_hal_resources.h" +#include #include #include @@ -55,6 +56,8 @@ void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) { void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) { furi_assert(handle); + furi_hal_power_insomnia_enter(); + handle->bus->callback(handle->bus, FuriHalSpiBusEventLock); handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate); @@ -75,6 +78,8 @@ void furi_hal_spi_release(FuriHalSpiBusHandle* handle) { // Bus events handle->bus->callback(handle->bus, FuriHalSpiBusEventDeactivate); handle->bus->callback(handle->bus, FuriHalSpiBusEventUnlock); + + furi_hal_power_insomnia_exit(); } static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) { diff --git a/firmware/targets/f7/furi_hal/furi_hal_uart.c b/firmware/targets/f7/furi_hal/furi_hal_uart.c index c4ad20162..74b14f4fd 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_uart.c +++ b/firmware/targets/f7/furi_hal/furi_hal_uart.c @@ -8,6 +8,8 @@ #include #include +static bool furi_hal_usart_prev_enabled[2]; + static void (*irq_cb[2])(uint8_t ev, uint8_t data, void* context); static void* irq_ctx[2]; @@ -44,7 +46,6 @@ static void furi_hal_usart_init(uint32_t baud) { ; LL_USART_EnableIT_RXNE_RXFNE(USART1); - LL_USART_EnableIT_IDLE(USART1); NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); } @@ -81,7 +82,6 @@ static void furi_hal_lpuart_init(uint32_t baud) { furi_hal_uart_set_br(FuriHalUartIdLPUART1, baud); LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1); - LL_LPUART_EnableIT_IDLE(LPUART1); NVIC_SetPriority(LPUART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); } @@ -136,6 +136,28 @@ void furi_hal_uart_deinit(FuriHalUartId ch) { } } +void furi_hal_uart_suspend(FuriHalUartId channel) { + if(channel == FuriHalUartIdLPUART1 && LL_LPUART_IsEnabled(LPUART1)) { + LL_LPUART_Disable(LPUART1); + furi_hal_usart_prev_enabled[channel] = true; + } else if(channel == FuriHalUartIdUSART1 && LL_USART_IsEnabled(USART1)) { + LL_USART_Disable(USART1); + furi_hal_usart_prev_enabled[channel] = true; + } +} + +void furi_hal_uart_resume(FuriHalUartId channel) { + if(!furi_hal_usart_prev_enabled[channel]) { + return; + } else if(channel == FuriHalUartIdLPUART1) { + LL_LPUART_Enable(LPUART1); + } else if(channel == FuriHalUartIdUSART1) { + LL_USART_Enable(USART1); + } + + furi_hal_usart_prev_enabled[channel] = false; +} + void furi_hal_uart_tx(FuriHalUartId ch, uint8_t* buffer, size_t buffer_size) { if(ch == FuriHalUartIdUSART1) { if(LL_USART_IsEnabled(USART1) == 0) return; @@ -189,22 +211,15 @@ void LPUART1_IRQHandler(void) { if(LL_LPUART_IsActiveFlag_RXNE_RXFNE(LPUART1)) { uint8_t data = LL_LPUART_ReceiveData8(LPUART1); irq_cb[FuriHalUartIdLPUART1](UartIrqEventRXNE, data, irq_ctx[FuriHalUartIdLPUART1]); - } else if(LL_LPUART_IsActiveFlag_IDLE(LPUART1)) { - irq_cb[FuriHalUartIdLPUART1](UartIrqEventIDLE, 0, irq_ctx[FuriHalUartIdLPUART1]); - LL_LPUART_ClearFlag_IDLE(LPUART1); } else if(LL_LPUART_IsActiveFlag_ORE(LPUART1)) { LL_LPUART_ClearFlag_ORE(LPUART1); } - //TODO: more events } void USART1_IRQHandler(void) { if(LL_USART_IsActiveFlag_RXNE_RXFNE(USART1)) { uint8_t data = LL_USART_ReceiveData8(USART1); irq_cb[FuriHalUartIdUSART1](UartIrqEventRXNE, data, irq_ctx[FuriHalUartIdUSART1]); - } else if(LL_USART_IsActiveFlag_IDLE(USART1)) { - irq_cb[FuriHalUartIdUSART1](UartIrqEventIDLE, 0, irq_ctx[FuriHalUartIdUSART1]); - LL_USART_ClearFlag_IDLE(USART1); } else if(LL_USART_IsActiveFlag_ORE(USART1)) { LL_USART_ClearFlag_ORE(USART1); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_uart.h b/firmware/targets/f7/furi_hal/furi_hal_uart.h index 9224a0b2c..07211db8b 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_uart.h +++ b/firmware/targets/f7/furi_hal/furi_hal_uart.h @@ -27,8 +27,6 @@ typedef enum { */ typedef enum { UartIrqEventRXNE, - UartIrqEventIDLE, - //TODO: more events } UartIrqEvent; /** @@ -46,6 +44,20 @@ void furi_hal_uart_init(FuriHalUartId channel, uint32_t baud); */ void furi_hal_uart_deinit(FuriHalUartId channel); +/** + * Suspend UART operation + * Disables UART hardware, settings and callbacks are preserved + * @param channel UART channel + */ +void furi_hal_uart_suspend(FuriHalUartId channel); + +/** + * Resume UART operation + * Resumes UART hardware from suspended state + * @param channel UART channel + */ +void furi_hal_uart_resume(FuriHalUartId channel); + /** * Changes UART baudrate * @param channel UART channel @@ -74,4 +86,4 @@ void furi_hal_uart_set_irq_cb( #ifdef __cplusplus } -#endif \ No newline at end of file +#endif diff --git a/firmware/targets/f7/furi_hal/furi_hal_usb.c b/firmware/targets/f7/furi_hal/furi_hal_usb.c index 7032d059b..d41414f87 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_usb.c +++ b/firmware/targets/f7/furi_hal/furi_hal_usb.c @@ -76,7 +76,9 @@ void furi_hal_usb_init(void) { usb.enabled = false; usb.if_cur = NULL; NVIC_SetPriority(USB_LP_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); + NVIC_SetPriority(USB_HP_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0)); NVIC_EnableIRQ(USB_LP_IRQn); + NVIC_EnableIRQ(USB_HP_IRQn); usb.thread = furi_thread_alloc(); furi_thread_set_name(usb.thread, "UsbDriver"); diff --git a/firmware/targets/f7/target.mk b/firmware/targets/f7/target.mk index 1822b6284..6410ba130 100644 --- a/firmware/targets/f7/target.mk +++ b/firmware/targets/f7/target.mk @@ -119,6 +119,10 @@ ifeq ($(FURI_HAL_USB_VCP_DEBUG), 1) CFLAGS += -DFURI_HAL_USB_VCP_DEBUG endif +ifeq ($(FURI_HAL_POWER_DEEP_SLEEP_ENABLED), 1) +CFLAGS += -DFURI_HAL_POWER_DEEP_SLEEP_ENABLED +endif + FURI_HAL_SUBGHZ_TX_GPIO ?= 0 ifneq ($(FURI_HAL_SUBGHZ_TX_GPIO), 0) CFLAGS += -DFURI_HAL_SUBGHZ_TX_GPIO=$(FURI_HAL_SUBGHZ_TX_GPIO) @@ -128,6 +132,10 @@ ifeq ($(INVERT_RFID_IN), 1) CFLAGS += -DINVERT_RFID_IN endif +ifeq ($(BLE_GLUE_DEBUG), 1) +CFLAGS += -DBLE_GLUE_DEBUG +endif + FURI_HAL_DIR = $(TARGET_DIR)/furi_hal CFLAGS += -I$(FURI_HAL_DIR) C_SOURCES += $(wildcard $(FURI_HAL_DIR)/*.c) diff --git a/firmware/targets/furi_hal_include/furi_hal.h b/firmware/targets/furi_hal_include/furi_hal.h index 8480f8840..17814b137 100644 --- a/firmware/targets/furi_hal_include/furi_hal.h +++ b/firmware/targets/furi_hal_include/furi_hal.h @@ -12,6 +12,7 @@ template struct STOP_EXTERNING_ME {}; #include "furi_hal_clock.h" #include "furi_hal_crypto.h" #include "furi_hal_console.h" +#include "furi_hal_debug.h" #include "furi_hal_os.h" #include "furi_hal_sd.h" #include "furi_hal_i2c.h" diff --git a/firmware/targets/furi_hal_include/furi_hal_bt.h b/firmware/targets/furi_hal_include/furi_hal_bt.h index 74e8d3214..73b16becb 100644 --- a/firmware/targets/furi_hal_include/furi_hal_bt.h +++ b/firmware/targets/furi_hal_include/furi_hal_bt.h @@ -68,6 +68,12 @@ FuriHalBtStack furi_hal_bt_get_radio_stack(); */ bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb, void* context); +/** Reinitialize core2 + * + * Also can be used to prepare core2 for stop modes + */ +void furi_hal_bt_reinit(); + /** Change BLE app * Restarts 2nd core * diff --git a/firmware/targets/furi_hal_include/furi_hal_debug.h b/firmware/targets/furi_hal_include/furi_hal_debug.h new file mode 100644 index 000000000..88397bbba --- /dev/null +++ b/firmware/targets/furi_hal_include/furi_hal_debug.h @@ -0,0 +1,23 @@ +/** + * @file furi_hal_debug.h + * Debug HAL API + */ + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Enable MCU debug */ +void furi_hal_debug_enable(); + +/** Disable MCU debug */ +void furi_hal_debug_disable(); + +#ifdef __cplusplus +} +#endif diff --git a/firmware/targets/furi_hal_include/furi_hal_power.h b/firmware/targets/furi_hal_include/furi_hal_power.h index 717f65706..16af959cf 100644 --- a/firmware/targets/furi_hal_include/furi_hal_power.h +++ b/firmware/targets/furi_hal_include/furi_hal_power.h @@ -85,6 +85,9 @@ uint8_t furi_hal_power_get_bat_health_pct(); */ bool furi_hal_power_is_charging(); +/** Switch MCU to SHUTDOWN */ +void furi_hal_power_shutdown(); + /** Poweroff device */ void furi_hal_power_off(); diff --git a/lib/u8g2/u8g2_glue.c b/lib/u8g2/u8g2_glue.c index 550a46104..cc186663f 100644 --- a/lib/u8g2/u8g2_glue.c +++ b/lib/u8g2/u8g2_glue.c @@ -17,7 +17,7 @@ uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, vo asm("nop"); break; case U8X8_MSG_GPIO_RESET: - furi_hal_gpio_write(&gpio_display_rst, arg_int); + furi_hal_gpio_write(&gpio_display_rst_n, arg_int); break; default: return 0; From 7017fa4f9eef3da2ae0a267da3093de7cdd16ed1 Mon Sep 17 00:00:00 2001 From: hedger Date: Fri, 29 Apr 2022 17:21:12 +0300 Subject: [PATCH 4/4] [FL-2515] Keep backlight on for updater ops (#1184) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [FL-2515] Keep backlight on for updater ops * Notification: Renamed backlight sequences to more obvious names Co-authored-by: あく --- applications/bt/bt_service/bt.c | 4 +- applications/cli/cli_commands.c | 2 +- applications/debug_tools/uart_echo.c | 2 +- applications/desktop/desktop.c | 2 +- applications/desktop/helpers/pin_lock.c | 2 +- .../desktop/scenes/desktop_scene_locked.c | 2 +- .../desktop/scenes/desktop_scene_pin_input.c | 2 +- .../gpio/scenes/gpio_scene_usb_uart.c | 4 +- applications/notification/notification.h | 6 +- applications/notification/notification_app.c | 14 ++--- .../notification/notification_messages.c | 61 ++++++++++--------- .../notification/notification_messages.h | 28 ++++----- .../notification/notification_settings_app.c | 4 +- .../power/battery_test_app/battery_test_app.c | 2 +- applications/u2f/scenes/u2f_scene_main.c | 2 +- .../updater/scenes/updater_scene_main.c | 4 +- applications/updater/updater.c | 2 + applications/updater/updater_i.h | 2 + lib/infrared/worker/infrared_worker.c | 2 +- 19 files changed, 77 insertions(+), 70 deletions(-) diff --git a/applications/bt/bt_service/bt.c b/applications/bt/bt_service/bt.c index 5636ceceb..111ebcb24 100755 --- a/applications/bt/bt_service/bt.c +++ b/applications/bt/bt_service/bt.c @@ -60,7 +60,7 @@ static ViewPort* bt_pin_code_view_port_alloc(Bt* bt) { static void bt_pin_code_show(Bt* bt, uint32_t pin_code) { bt->pin_code = pin_code; - notification_message(bt->notification, &sequence_display_on); + notification_message(bt->notification, &sequence_display_backlight_on); gui_view_port_send_to_front(bt->gui, bt->pin_code_view_port); view_port_enabled_set(bt->pin_code_view_port, true); } @@ -74,7 +74,7 @@ static void bt_pin_code_hide(Bt* bt) { static bool bt_pin_code_verify_event_handler(Bt* bt, uint32_t pin) { furi_assert(bt); - notification_message(bt->notification, &sequence_display_on); + notification_message(bt->notification, &sequence_display_backlight_on); string_t pin_str; dialog_message_set_icon(bt->dialog_message, &I_BLE_Pairing_128x64, 0, 0); string_init_printf(pin_str, "Verify code\n%06d", pin); diff --git a/applications/cli/cli_commands.c b/applications/cli/cli_commands.c index a58ddd49a..bdec231b0 100644 --- a/applications/cli/cli_commands.c +++ b/applications/cli/cli_commands.c @@ -202,7 +202,7 @@ void cli_command_led(Cli* cli, string_t args, void* context) { } else if(!string_cmp(light_name, "b")) { notification_led_message.type = NotificationMessageTypeLedBlue; } else if(!string_cmp(light_name, "bl")) { - notification_led_message.type = NotificationMessageTypeLedDisplay; + notification_led_message.type = NotificationMessageTypeLedDisplayBacklight; } else { cli_print_usage("led", " <0-255>", string_get_cstr(args)); string_clear(light_name); diff --git a/applications/debug_tools/uart_echo.c b/applications/debug_tools/uart_echo.c index 73af1e664..0e4ee1d89 100644 --- a/applications/debug_tools/uart_echo.c +++ b/applications/debug_tools/uart_echo.c @@ -45,7 +45,7 @@ typedef enum { #define WORKER_EVENTS_MASK (WorkerEventStop | WorkerEventRx) const NotificationSequence sequence_notification = { - &message_display_on, + &message_display_backlight_on, &message_green_255, &message_delay_10, NULL, diff --git a/applications/desktop/desktop.c b/applications/desktop/desktop.c index daaffc2db..7686a1456 100644 --- a/applications/desktop/desktop.c +++ b/applications/desktop/desktop.c @@ -121,7 +121,7 @@ void desktop_lock(Desktop* desktop) { scene_manager_set_scene_state( desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER); scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); - notification_message(desktop->notification, &sequence_display_off_delay_1000); + notification_message(desktop->notification, &sequence_display_backlight_off_delay_1000); } void desktop_unlock(Desktop* desktop) { diff --git a/applications/desktop/helpers/pin_lock.c b/applications/desktop/helpers/pin_lock.c index 4956c6cc3..00ac41778 100644 --- a/applications/desktop/helpers/pin_lock.c +++ b/applications/desktop/helpers/pin_lock.c @@ -11,7 +11,7 @@ #include static const NotificationSequence sequence_pin_fail = { - &message_display_on, + &message_display_backlight_on, &message_red_255, &message_vibro_on, diff --git a/applications/desktop/scenes/desktop_scene_locked.c b/applications/desktop/scenes/desktop_scene_locked.c index 118bbce40..90df22269 100644 --- a/applications/desktop/scenes/desktop_scene_locked.c +++ b/applications/desktop/scenes/desktop_scene_locked.c @@ -89,7 +89,7 @@ bool desktop_scene_locked_on_event(void* context, SceneManagerEvent event) { break; case DesktopLockedEventUpdate: if(desktop_view_locked_is_locked_hint_visible(desktop->locked_view)) { - notification_message(desktop->notification, &sequence_display_off); + notification_message(desktop->notification, &sequence_display_backlight_off); } desktop_view_locked_update(desktop->locked_view); consumed = true; diff --git a/applications/desktop/scenes/desktop_scene_pin_input.c b/applications/desktop/scenes/desktop_scene_pin_input.c index 7f9d8fcfb..dd5c8ce38 100644 --- a/applications/desktop/scenes/desktop_scene_pin_input.c +++ b/applications/desktop/scenes/desktop_scene_pin_input.c @@ -133,7 +133,7 @@ bool desktop_scene_pin_input_on_event(void* context, SceneManagerEvent event) { case DesktopPinInputEventBack: scene_manager_search_and_switch_to_previous_scene( desktop->scene_manager, DesktopSceneLocked); - notification_message(desktop->notification, &sequence_display_off); + notification_message(desktop->notification, &sequence_display_backlight_off); consumed = true; break; } diff --git a/applications/gpio/scenes/gpio_scene_usb_uart.c b/applications/gpio/scenes/gpio_scene_usb_uart.c index f8f473eeb..aa41aaf98 100644 --- a/applications/gpio/scenes/gpio_scene_usb_uart.c +++ b/applications/gpio/scenes/gpio_scene_usb_uart.c @@ -33,7 +33,7 @@ void gpio_scene_usb_uart_on_enter(void* context) { gpio_usb_uart_set_callback(app->gpio_usb_uart, gpio_scene_usb_uart_callback, app); scene_manager_set_scene_state(app->scene_manager, GpioSceneUsbUart, 0); view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewUsbUart); - notification_message(app->notifications, &sequence_display_lock); + notification_message(app->notifications, &sequence_display_backlight_enforce_on); } bool gpio_scene_usb_uart_on_event(void* context, SceneManagerEvent event) { @@ -63,5 +63,5 @@ void gpio_scene_usb_uart_on_exit(void* context) { usb_uart_disable(app->usb_uart_bridge); free(scene_usb_uart); } - notification_message(app->notifications, &sequence_display_unlock); + notification_message(app->notifications, &sequence_display_backlight_enforce_auto); } diff --git a/applications/notification/notification.h b/applications/notification/notification.h index b73efad20..4cb9dc5e0 100644 --- a/applications/notification/notification.h +++ b/applications/notification/notification.h @@ -50,9 +50,9 @@ typedef enum { NotificationMessageTypeDelay, - NotificationMessageTypeLedDisplay, - NotificationMessageTypeLedDisplayLock, - NotificationMessageTypeLedDisplayUnlock, + NotificationMessageTypeLedDisplayBacklight, + NotificationMessageTypeLedDisplayBacklightEnforceOn, + NotificationMessageTypeLedDisplayBacklightEnforceAuto, NotificationMessageTypeDoNotReset, diff --git a/applications/notification/notification_app.c b/applications/notification/notification_app.c index 75be20b16..4db12bbf2 100644 --- a/applications/notification/notification_app.c +++ b/applications/notification/notification_app.c @@ -152,7 +152,7 @@ void notification_sound_off() { static void notification_display_timer(void* ctx) { furi_assert(ctx); NotificationApp* app = ctx; - notification_message(app, &sequence_display_off); + notification_message(app, &sequence_display_backlight_off); } // message processing @@ -174,7 +174,7 @@ void notification_process_notification_message( while(notification_message != NULL) { switch(notification_message->type) { - case NotificationMessageTypeLedDisplay: + case NotificationMessageTypeLedDisplayBacklight: // if on - switch on and start timer // if off - switch off and stop timer // on timer - switch off @@ -190,7 +190,7 @@ void notification_process_notification_message( } reset_mask |= reset_display_mask; break; - case NotificationMessageTypeLedDisplayLock: + case NotificationMessageTypeLedDisplayBacklightEnforceOn: furi_assert(app->display_led_lock < UINT8_MAX); app->display_led_lock++; if(app->display_led_lock == 1) { @@ -199,7 +199,7 @@ void notification_process_notification_message( notification_message->data.led.value * display_brightness_setting); } break; - case NotificationMessageTypeLedDisplayUnlock: + case NotificationMessageTypeLedDisplayBacklightEnforceAuto: furi_assert(app->display_led_lock > 0); app->display_led_lock--; if(app->display_led_lock == 0) { @@ -322,7 +322,7 @@ void notification_process_internal_message(NotificationApp* app, NotificationApp while(notification_message != NULL) { switch(notification_message->type) { - case NotificationMessageTypeLedDisplay: + case NotificationMessageTypeLedDisplayBacklight: notification_apply_internal_led_layer( &app->display, notification_settings_get_display_brightness( @@ -442,7 +442,7 @@ static void input_event_callback(const void* value, void* context) { furi_assert(value); furi_assert(context); NotificationApp* app = context; - notification_message(app, &sequence_display_on); + notification_message(app, &sequence_display_backlight_on); } // App alloc @@ -482,7 +482,7 @@ static NotificationApp* notification_app_alloc() { // display backlight control app->event_record = furi_record_open("input_events"); furi_pubsub_subscribe(app->event_record, input_event_callback, app); - notification_message(app, &sequence_display_on); + notification_message(app, &sequence_display_backlight_on); return app; }; diff --git a/applications/notification/notification_messages.c b/applications/notification/notification_messages.c index 168c4d0f1..5a95556e3 100644 --- a/applications/notification/notification_messages.c +++ b/applications/notification/notification_messages.c @@ -4,24 +4,27 @@ /*********************************** Messages **********************************/ -// Display -const NotificationMessage message_display_on = { - .type = NotificationMessageTypeLedDisplay, +/** Display: backlight wakeup */ +const NotificationMessage message_display_backlight_on = { + .type = NotificationMessageTypeLedDisplayBacklight, .data.led.value = 0xFF, }; -const NotificationMessage message_display_off = { - .type = NotificationMessageTypeLedDisplay, +/** Display: backlight force off */ +const NotificationMessage message_display_backlight_off = { + .type = NotificationMessageTypeLedDisplayBacklight, .data.led.value = 0x00, }; -const NotificationMessage message_display_lock = { - .type = NotificationMessageTypeLedDisplayLock, +/** Display: backlight always on */ +const NotificationMessage message_display_backlight_enforce_on = { + .type = NotificationMessageTypeLedDisplayBacklightEnforceOn, .data.led.value = 0xFF, }; -const NotificationMessage message_display_unlock = { - .type = NotificationMessageTypeLedDisplayUnlock, +/** Display: automatic backlight management, with configured timeout */ +const NotificationMessage message_display_backlight_enforce_auto = { + .type = NotificationMessageTypeLedDisplayBacklightEnforceAuto, .data.led.value = 0x00, }; @@ -166,7 +169,7 @@ const NotificationSequence sequence_reset_rgb = { }; const NotificationSequence sequence_reset_display = { - &message_display_off, + &message_display_backlight_off, NULL, }; @@ -188,29 +191,31 @@ const NotificationSequence sequence_set_vibro_on = { }; // Display -const NotificationSequence sequence_display_on = { - &message_display_on, +const NotificationSequence sequence_display_backlight_on = { + &message_display_backlight_on, NULL, }; -const NotificationSequence sequence_display_off = { - &message_display_off, +const NotificationSequence sequence_display_backlight_off = { + &message_display_backlight_off, NULL, }; -const NotificationSequence sequence_display_lock = { - &message_display_lock, +/** Display: backlight always on lock */ +const NotificationSequence sequence_display_backlight_enforce_on = { + &message_display_backlight_enforce_on, NULL, }; -const NotificationSequence sequence_display_unlock = { - &message_display_unlock, +/** Display: backlight always on unlock */ +const NotificationSequence sequence_display_backlight_enforce_auto = { + &message_display_backlight_enforce_auto, NULL, }; -const NotificationSequence sequence_display_off_delay_1000 = { +const NotificationSequence sequence_display_backlight_off_delay_1000 = { &message_delay_1000, - &message_display_off, + &message_display_backlight_off, NULL, }; @@ -383,7 +388,7 @@ const NotificationSequence sequence_double_vibro = { }; const NotificationSequence sequence_success = { - &message_display_on, + &message_display_backlight_on, &message_green_255, &message_vibro_on, &message_note_c5, @@ -400,7 +405,7 @@ const NotificationSequence sequence_success = { }; const NotificationSequence sequence_error = { - &message_display_on, + &message_display_backlight_on, &message_red_255, &message_vibro_on, &message_note_c5, @@ -422,27 +427,27 @@ const NotificationSequence sequence_audiovisual_alert = { &message_force_display_brightness_setting_1f, &message_vibro_on, - &message_display_on, + &message_display_backlight_on, &message_note_c7, &message_delay_250, - &message_display_off, + &message_display_backlight_off, &message_note_c4, &message_delay_250, - &message_display_on, + &message_display_backlight_on, &message_note_c7, &message_delay_250, - &message_display_off, + &message_display_backlight_off, &message_note_c4, &message_delay_250, - &message_display_on, + &message_display_backlight_on, &message_note_c7, &message_delay_250, - &message_display_off, + &message_display_backlight_off, &message_note_c4, &message_delay_250, diff --git a/applications/notification/notification_messages.h b/applications/notification/notification_messages.h index 610443413..c1ab34071 100644 --- a/applications/notification/notification_messages.h +++ b/applications/notification/notification_messages.h @@ -9,15 +9,10 @@ extern "C" { /*********************************** Messages **********************************/ // Display - -/** Display: backlight wakeup */ -extern const NotificationMessage message_display_on; -/** Display: backlight force off */ -extern const NotificationMessage message_display_off; -/** Display: backlight always on lock */ -extern const NotificationMessage message_display_lock; -/** Display: backlight always on unlock */ -extern const NotificationMessage message_display_unlock; +extern const NotificationMessage message_display_backlight_on; +extern const NotificationMessage message_display_backlight_off; +extern const NotificationMessage message_display_backlight_enforce_on; +extern const NotificationMessage message_display_backlight_enforce_auto; // Led ON extern const NotificationMessage message_red_255; @@ -71,15 +66,16 @@ extern const NotificationSequence sequence_set_vibro_on; // Display /** Display: backlight wakeup */ -extern const NotificationSequence sequence_display_on; +extern const NotificationSequence sequence_display_backlight_on; /** Display: backlight force off */ -extern const NotificationSequence sequence_display_off; -/** Display: backlight always on lock */ -extern const NotificationSequence sequence_display_lock; -/** Display: backlight always on unlock */ -extern const NotificationSequence sequence_display_unlock; +extern const NotificationSequence sequence_display_backlight_off; /** Display: backlight force off after a delay of 1000ms */ -extern const NotificationSequence sequence_display_off_delay_1000; +extern const NotificationSequence sequence_display_backlight_off_delay_1000; + +/** Display: backlight always on lock */ +extern const NotificationSequence sequence_display_backlight_enforce_on; +/** Display: backlight always on unlock */ +extern const NotificationSequence sequence_display_backlight_enforce_auto; // Charging extern const NotificationSequence sequence_charging; diff --git a/applications/notification/notification_settings_app.c b/applications/notification/notification_settings_app.c index e7a57aa61..eef14ebf5 100644 --- a/applications/notification/notification_settings_app.c +++ b/applications/notification/notification_settings_app.c @@ -70,7 +70,7 @@ static void backlight_changed(VariableItem* item) { variable_item_set_current_value_text(item, backlight_text[index]); app->notification->settings.display_brightness = backlight_value[index]; - notification_message(app->notification, &sequence_display_on); + notification_message(app->notification, &sequence_display_backlight_on); } static void screen_changed(VariableItem* item) { @@ -79,7 +79,7 @@ static void screen_changed(VariableItem* item) { variable_item_set_current_value_text(item, delay_text[index]); app->notification->settings.display_off_delay_ms = delay_value[index]; - notification_message(app->notification, &sequence_display_on); + notification_message(app->notification, &sequence_display_backlight_on); } const NotificationMessage apply_message = { diff --git a/applications/power/battery_test_app/battery_test_app.c b/applications/power/battery_test_app/battery_test_app.c index 4d73fee54..1588a525f 100755 --- a/applications/power/battery_test_app/battery_test_app.c +++ b/applications/power/battery_test_app/battery_test_app.c @@ -28,7 +28,7 @@ static void battery_test_battery_info_update_model(void* context) { .health = app->info.health, }; battery_info_set_data(app->batery_info, &battery_info_data); - notification_message(app->notifications, &sequence_display_on); + notification_message(app->notifications, &sequence_display_backlight_on); } BatteryTestApp* battery_test_alloc() { diff --git a/applications/u2f/scenes/u2f_scene_main.c b/applications/u2f/scenes/u2f_scene_main.c index dadecb362..d0957b591 100644 --- a/applications/u2f/scenes/u2f_scene_main.c +++ b/applications/u2f/scenes/u2f_scene_main.c @@ -59,7 +59,7 @@ bool u2f_scene_main_on_event(void* context, SceneManagerEvent event) { u2f_view_set_state(app->u2f_view, U2fMsgRegister); else if(event.event == U2fCustomEventAuth) u2f_view_set_state(app->u2f_view, U2fMsgAuth); - notification_message(app->notifications, &sequence_display_on); + notification_message(app->notifications, &sequence_display_backlight_on); notification_message(app->notifications, &sequence_single_vibro); } notification_message(app->notifications, &sequence_blink_magenta_10); diff --git a/applications/updater/scenes/updater_scene_main.c b/applications/updater/scenes/updater_scene_main.c index 165028c4c..c5fc99ffb 100644 --- a/applications/updater/scenes/updater_scene_main.c +++ b/applications/updater/scenes/updater_scene_main.c @@ -25,6 +25,7 @@ static void sd_mount_callback(const void* message, void* context) { void updater_scene_main_on_enter(void* context) { Updater* updater = (Updater*)context; + notification_message(updater->notification, &sequence_display_backlight_enforce_on); UpdaterMainView* main_view = updater->main_view; FuriPubSubSubscription* sub = @@ -92,8 +93,9 @@ bool updater_scene_main_on_event(void* context, SceneManagerEvent event) { void updater_scene_main_on_exit(void* context) { Updater* updater = (Updater*)context; + notification_message(updater->notification, &sequence_display_backlight_enforce_auto); furi_pubsub_unsubscribe( storage_get_pubsub(updater->storage), updater_main_get_storage_pubsub(updater->main_view)); scene_manager_set_scene_state(updater->scene_manager, UpdaterSceneMain, 0); -} \ No newline at end of file +} diff --git a/applications/updater/updater.c b/applications/updater/updater.c index 519ba167d..c1115ce18 100644 --- a/applications/updater/updater.c +++ b/applications/updater/updater.c @@ -47,6 +47,7 @@ Updater* updater_alloc(const char* arg) { } updater->storage = furi_record_open("storage"); + updater->notification = furi_record_open("notification"); updater->gui = furi_record_open("gui"); updater->view_dispatcher = view_dispatcher_alloc(); @@ -119,6 +120,7 @@ void updater_free(Updater* updater) { furi_record_close("gui"); furi_record_close("storage"); + furi_record_close("notification"); free(updater); } diff --git a/applications/updater/updater_i.h b/applications/updater/updater_i.h index d0e7c77c9..89201e1e0 100644 --- a/applications/updater/updater_i.h +++ b/applications/updater/updater_i.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #ifdef __cplusplus @@ -41,6 +42,7 @@ typedef struct UpdaterManifestProcessingState { typedef struct { // GUI Gui* gui; + NotificationApp* notification; SceneManager* scene_manager; ViewDispatcher* view_dispatcher; Storage* storage; diff --git a/lib/infrared/worker/infrared_worker.c b/lib/infrared/worker/infrared_worker.c index 4439a7133..5711d2c00 100644 --- a/lib/infrared/worker/infrared_worker.c +++ b/lib/infrared/worker/infrared_worker.c @@ -177,7 +177,7 @@ static int32_t infrared_worker_rx_thread(void* thread_context) { notification_message(instance->notification, &sequence_blink_blue_10); } if(instance->signal.timings_cnt == 0) - notification_message(instance->notification, &sequence_display_on); + notification_message(instance->notification, &sequence_display_backlight_on); while(sizeof(LevelDuration) == xStreamBufferReceive( instance->stream, &level_duration, sizeof(LevelDuration), 0)) {