Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FL-1816] Fix ble radio stack is alive check. Fix random crashes on storage use. #707

Merged
merged 7 commits into from
Sep 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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()()