Skip to content

Commit

Permalink
[FL-1816] Fix ble radio stack is alive check (flipperdevices#707)
Browse files Browse the repository at this point in the history
* bt: fix bt_is_alive return, add bt_is_active
* bt: fix bt_is_alive return
* Cli: show heap usage in ps.
* FuriHal: strict sequence for flash operations
* Scripts: add stress test
* Core: proper heap calculation.

Co-authored-by: あく <[email protected]>
  • Loading branch information
gornekich and skotopes authored Sep 16, 2021
1 parent b4ffc1f commit f05153e
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 44 deletions.
6 changes: 3 additions & 3 deletions applications/bt/bt_service/bt.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,17 @@ int32_t bt_srv() {
}
}
// Update statusbar
view_port_enabled_set(bt->statusbar_view_port, furi_hal_bt_is_alive());
view_port_enabled_set(bt->statusbar_view_port, furi_hal_bt_is_active());

BtMessage message;
while(1) {
furi_check(osMessageQueueGet(bt->message_queue, &message, NULL, osWaitForever) == osOK);
if(message.type == BtMessageTypeUpdateStatusbar) {
// Update statusbar
view_port_enabled_set(bt->statusbar_view_port, furi_hal_bt_is_alive());
view_port_enabled_set(bt->statusbar_view_port, furi_hal_bt_is_active());
} else if(message.type == BtMessageTypeUpdateBatteryLevel) {
// Update battery level
if(furi_hal_bt_is_alive()) {
if(furi_hal_bt_is_active()) {
battery_svc_update_level(message.data.battery_level);
}
} else if(message.type == BtMessageTypePinCodeShow) {
Expand Down
12 changes: 7 additions & 5 deletions applications/cli/cli_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -385,17 +385,19 @@ void cli_command_ps(Cli* cli, string_t args, void* context) {
const uint8_t threads_num_max = 32;
osThreadId_t threads_id[threads_num_max];
uint8_t thread_num = osThreadEnumerate(threads_id, threads_num_max);
printf("%d threads in total:\r\n", thread_num);
printf("%-20s %-14s %-14s %s\r\n", "Name", "Stack start", "Stack alloc", "Stack watermark");
printf(
"%-20s %-14s %-8s %-8s %s\r\n", "Name", "Stack start", "Heap", "Stack", "Stack min free");
for(uint8_t i = 0; i < thread_num; i++) {
TaskControlBlock* tcb = (TaskControlBlock*)threads_id[i];
printf(
"%-20s 0x%-12lx %-14ld %ld\r\n",
"%-20s 0x%-12lx %-8d %-8ld %-8ld\r\n",
osThreadGetName(threads_id[i]),
(uint32_t)tcb->pxStack,
(uint32_t)(tcb->pxEndOfStack - tcb->pxStack + 1) * sizeof(uint32_t),
osThreadGetStackSpace(threads_id[i]) * sizeof(uint32_t));
memmgr_heap_get_thread_memory(threads_id[i]),
(uint32_t)(tcb->pxEndOfStack - tcb->pxStack + 1) * sizeof(StackType_t),
osThreadGetStackSpace(threads_id[i]));
}
printf("\r\nTotal: %d", thread_num);
}

void cli_command_free(Cli* cli, string_t args, void* context) {
Expand Down
18 changes: 10 additions & 8 deletions core/furi/memmgr_heap.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,19 +155,21 @@ void memmgr_heap_disable_thread_trace(osThreadId_t thread_id) {
}

size_t memmgr_heap_get_thread_memory(osThreadId_t thread_id) {
size_t leftovers = 0;
size_t leftovers = MEMMGR_HEAP_UNKNOWN;
vTaskSuspendAll();
{
memmgr_heap_thread_trace_depth++;
MemmgrHeapAllocDict_t* alloc_dict =
MemmgrHeapThreadDict_get(memmgr_heap_thread_dict, (uint32_t)thread_id);
furi_check(alloc_dict);
MemmgrHeapAllocDict_it_t alloc_dict_it;
for(MemmgrHeapAllocDict_it(alloc_dict_it, *alloc_dict);
!MemmgrHeapAllocDict_end_p(alloc_dict_it);
MemmgrHeapAllocDict_next(alloc_dict_it)) {
MemmgrHeapAllocDict_itref_t* data = MemmgrHeapAllocDict_ref(alloc_dict_it);
leftovers += data->value;
if(alloc_dict) {
leftovers = 0;
MemmgrHeapAllocDict_it_t alloc_dict_it;
for(MemmgrHeapAllocDict_it(alloc_dict_it, *alloc_dict);
!MemmgrHeapAllocDict_end_p(alloc_dict_it);
MemmgrHeapAllocDict_next(alloc_dict_it)) {
MemmgrHeapAllocDict_itref_t* data = MemmgrHeapAllocDict_ref(alloc_dict_it);
leftovers += data->value;
}
}
memmgr_heap_thread_trace_depth--;
}
Expand Down
2 changes: 2 additions & 0 deletions core/furi/memmgr_heap.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
extern "C" {
#endif

#define MEMMGR_HEAP_UNKNOWN 0xFFFFFFFF

/** Memmgr heap enable thread allocation tracking
* @param thread_id - thread id to track
*/
Expand Down
26 changes: 19 additions & 7 deletions firmware/targets/f6/furi-hal/furi-hal-bt.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ void furi_hal_bt_start_advertising() {
}

void furi_hal_bt_stop_advertising() {
if(furi_hal_bt_is_alive()) {
if(furi_hal_bt_is_active()) {
gap_stop_advertising();
}
}
Expand Down Expand Up @@ -52,6 +52,11 @@ void furi_hal_bt_dump_state(string_t buffer) {
}

bool furi_hal_bt_is_alive() {
BleGlueStatus status = APPE_Status();
return (status == BleGlueStatusBroken) || (status == BleGlueStatusStarted);
}

bool furi_hal_bt_is_active() {
return gap_get_state() > GapStateIdle;
}

Expand All @@ -67,26 +72,33 @@ bool furi_hal_bt_wait_startup() {
return true;
}

bool furi_hal_bt_lock_flash() {
bool furi_hal_bt_lock_flash(bool erase_flag) {
if (!furi_hal_bt_wait_startup()) {
return false;
}

while (HAL_HSEM_FastTake(CFG_HW_FLASH_SEMID) != HAL_OK) {
osDelay(1);
}

SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON);

HAL_FLASH_Unlock();

while(LL_FLASH_IsOperationSuspended()) {};
if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON);

while(LL_FLASH_IsActiveFlag_OperationSuspended()) {};

__disable_irq();

return true;
}

void furi_hal_bt_unlock_flash() {
SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_OFF);
void furi_hal_bt_unlock_flash(bool erase_flag) {
__enable_irq();

if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_OFF);

HAL_FLASH_Lock();

HAL_HSEM_Release(CFG_HW_FLASH_SEMID, HSEM_CPU1_COREID);
}

Expand Down
12 changes: 6 additions & 6 deletions firmware/targets/f6/furi-hal/furi-hal-flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ size_t furi_hal_flash_get_free_page_count() {
}

bool furi_hal_flash_erase(uint8_t page, uint8_t count) {
if (!furi_hal_bt_lock_flash()) {
if (!furi_hal_bt_lock_flash(true)) {
return false;
}
FLASH_EraseInitTypeDef erase;
Expand All @@ -66,24 +66,24 @@ bool furi_hal_flash_erase(uint8_t page, uint8_t count) {
erase.NbPages = count;
uint32_t error;
HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&erase, &error);
furi_hal_bt_unlock_flash();
furi_hal_bt_unlock_flash(true);
return status == HAL_OK;
}

bool furi_hal_flash_write_dword(size_t address, uint64_t data) {
if (!furi_hal_bt_lock_flash()) {
if (!furi_hal_bt_lock_flash(false)) {
return false;
}
HAL_StatusTypeDef status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data);
furi_hal_bt_unlock_flash();
furi_hal_bt_unlock_flash(false);
return status == HAL_OK;
}

bool furi_hal_flash_write_dword_from(size_t address, size_t source_address) {
if (!furi_hal_bt_lock_flash()) {
if (!furi_hal_bt_lock_flash(false)) {
return false;
}
HAL_StatusTypeDef status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST, address, source_address);
furi_hal_bt_unlock_flash();
furi_hal_bt_unlock_flash(false);
return status == HAL_OK;
}
26 changes: 19 additions & 7 deletions firmware/targets/f7/furi-hal/furi-hal-bt.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ void furi_hal_bt_start_advertising() {
}

void furi_hal_bt_stop_advertising() {
if(furi_hal_bt_is_alive()) {
if(furi_hal_bt_is_active()) {
gap_stop_advertising();
}
}
Expand Down Expand Up @@ -52,6 +52,11 @@ void furi_hal_bt_dump_state(string_t buffer) {
}

bool furi_hal_bt_is_alive() {
BleGlueStatus status = APPE_Status();
return (status == BleGlueStatusBroken) || (status == BleGlueStatusStarted);
}

bool furi_hal_bt_is_active() {
return gap_get_state() > GapStateIdle;
}

Expand All @@ -67,26 +72,33 @@ bool furi_hal_bt_wait_startup() {
return true;
}

bool furi_hal_bt_lock_flash() {
bool furi_hal_bt_lock_flash(bool erase_flag) {
if (!furi_hal_bt_wait_startup()) {
return false;
}

while (HAL_HSEM_FastTake(CFG_HW_FLASH_SEMID) != HAL_OK) {
osDelay(1);
}

SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON);

HAL_FLASH_Unlock();

while(LL_FLASH_IsOperationSuspended()) {};
if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_ON);

while(LL_FLASH_IsActiveFlag_OperationSuspended()) {};

__disable_irq();

return true;
}

void furi_hal_bt_unlock_flash() {
SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_OFF);
void furi_hal_bt_unlock_flash(bool erase_flag) {
__enable_irq();

if(erase_flag) SHCI_C2_FLASH_EraseActivity(ERASE_ACTIVITY_OFF);

HAL_FLASH_Lock();

HAL_HSEM_Release(CFG_HW_FLASH_SEMID, HSEM_CPU1_COREID);
}

Expand Down
12 changes: 6 additions & 6 deletions firmware/targets/f7/furi-hal/furi-hal-flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ size_t furi_hal_flash_get_free_page_count() {
}

bool furi_hal_flash_erase(uint8_t page, uint8_t count) {
if (!furi_hal_bt_lock_flash()) {
if (!furi_hal_bt_lock_flash(true)) {
return false;
}
FLASH_EraseInitTypeDef erase;
Expand All @@ -66,24 +66,24 @@ bool furi_hal_flash_erase(uint8_t page, uint8_t count) {
erase.NbPages = count;
uint32_t error;
HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&erase, &error);
furi_hal_bt_unlock_flash();
furi_hal_bt_unlock_flash(true);
return status == HAL_OK;
}

bool furi_hal_flash_write_dword(size_t address, uint64_t data) {
if (!furi_hal_bt_lock_flash()) {
if (!furi_hal_bt_lock_flash(false)) {
return false;
}
HAL_StatusTypeDef status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, address, data);
furi_hal_bt_unlock_flash();
furi_hal_bt_unlock_flash(false);
return status == HAL_OK;
}

bool furi_hal_flash_write_dword_from(size_t address, size_t source_address) {
if (!furi_hal_bt_lock_flash()) {
if (!furi_hal_bt_lock_flash(false)) {
return false;
}
HAL_StatusTypeDef status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST, address, source_address);
furi_hal_bt_unlock_flash();
furi_hal_bt_unlock_flash(false);
return status == HAL_OK;
}
7 changes: 5 additions & 2 deletions firmware/targets/furi-hal-include/furi-hal-bt.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ void furi_hal_bt_start_advertising();
/** Stop advertising */
void furi_hal_bt_stop_advertising();

/** Returns true if BLE is advertising */
bool furi_hal_bt_is_active();

/** Get BT/BLE system component state */
void furi_hal_bt_dump_state(string_t buffer);

Expand All @@ -32,10 +35,10 @@ bool furi_hal_bt_wait_startup();
* Lock shared access to flash controller
* @return true if lock was successful, false if not
*/
bool furi_hal_bt_lock_flash();
bool furi_hal_bt_lock_flash(bool erase_flag);

/** Unlock shared access to flash controller */
void furi_hal_bt_unlock_flash();
void furi_hal_bt_unlock_flash(bool erase_flag);

/** Start ble tone tx at given channel and power */
void furi_hal_bt_start_tone_tx(uint8_t channel, uint8_t power);
Expand Down
48 changes: 48 additions & 0 deletions scripts/storage.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
#!/usr/bin/env python3

from flipper.storage import FlipperStorage

import logging
import argparse
import os
import sys
import binascii
import posixpath
import filecmp
import tempfile


class Main:
Expand Down Expand Up @@ -56,6 +59,16 @@ def __init__(self):
self.parser_list.add_argument("flipper_path", help="Flipper path", default="/")
self.parser_list.set_defaults(func=self.list)

self.parser_stress = self.subparsers.add_parser("stress", help="Stress test")
self.parser.add_argument(
"-c", "--count", type=int, default=10, help="Iteration count"
)
self.parser_stress.add_argument("flipper_path", help="Flipper path")
self.parser_stress.add_argument(
"file_size", type=int, help="Test file size in bytes"
)
self.parser_stress.set_defaults(func=self.stress)

# logging
self.logger = logging.getLogger()

Expand Down Expand Up @@ -262,6 +275,41 @@ def list(self):
storage.list_tree(self.args.flipper_path)
storage.stop()

def stress(self):
self.logger.error("This test is wearing out flash memory.")
self.logger.error("Never use it with internal storage(/int)")

if self.args.flipper_path.startswith(
"/int"
) or self.args.flipper_path.startswith("/any"):
self.logger.error("Stop at this point or device warranty will be void")
say = input("Anything to say? ").strip().lower()
if say != "void":
return
say = input("Why, Mr. Anderson? ").strip().lower()
if say != "because":
return

with tempfile.TemporaryDirectory() as tmpdirname:
send_file_name = os.path.join(tmpdirname, "send")
receive_file_name = os.path.join(tmpdirname, "receive")
open(send_file_name, "w").write("A" * self.args.file_size)
storage = FlipperStorage(self.args.port)
storage.start()
if storage.exist_file(self.args.flipper_path):
self.logger.error("File exists, remove it first")
return
while self.args.count > 0:
storage.send_file(send_file_name, self.args.flipper_path)
storage.receive_file(self.args.flipper_path, receive_file_name)
if not filecmp.cmp(receive_file_name, send_file_name):
self.logger.error("Files mismatch")
break
storage.remove(self.args.flipper_path)
os.unlink(receive_file_name)
self.args.count -= 1
storage.stop()


if __name__ == "__main__":
Main()()

0 comments on commit f05153e

Please sign in to comment.