unleashed-firmware/furi/core/check.c

201 lines
7 KiB
C
Raw Normal View History

#include "check.h"
#include "common_defines.h"
#include <stm32wbxx.h>
#include <furi_hal_console.h>
#include <furi_hal_power.h>
#include <furi_hal_rtc.h>
#include <furi_hal_debug.h>
#include <furi_hal_bt.h>
[FL-140] Core api dynamic records (#296) * SYSTEM: tickless mode with deep sleep. * Move FreeRTOS ticks to lptim2 * API: move all sumbodules init routines to one place. Timebase: working lptim2 at tick source. * API Timebase: lp-timer routines, timer access safe zones prediction and synchronization. FreeRTOS: adjust configuration for tickless mode. * NFC: support for tickless mode. * API Timebase: improve tick error handling in IRQ. Apploader: use insomnia mode to run applications. * BLE: prevent sleep while core2 starting * HAL: nap while in insomnia mode * init records work * try to implement record delete * tests and flapp * flapp subsystem * new core functions to get app stat, simplify core code * fix thread termination * add strdup to core * fix tests * Refactoring: remove all unusued parts, update API usage, aggreagate API sources and headers, new record storage * Refactoring: update furi record api usage, cleanup code * Fix broken merge for freertos apps * Core, Target: fix compilation warnings * Drop firmware target local * HAL Timebase, Power, Clock: semaphore guarded access to clock and power modes, better sleep mode. * SD-Filesystem: wait for all deps to arrive before adding widget. Core, BLE: disable debug dump to serial. * delete old app example-ipc * delete old app fatfs list * fix strobe app, add input header * delete old display driver * comment old app qr-code * fix sd-card test, add forced widget update * remove unused new core test * increase heap to 128k * comment and assert old core tests * fix syntax Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
2021-01-20 16:09:26 +00:00
#include <stdio.h>
#include <FreeRTOS.h>
#include <task.h>
#include <stdio.h>
#include <stdlib.h>
PLACE_IN_SECTION("MB_MEM2") const char* __furi_check_message = NULL;
PLACE_IN_SECTION("MB_MEM2") uint32_t __furi_check_registers[13] = {0};
/** Load r12 value to __furi_check_message and store registers to __furi_check_registers */
#define GET_MESSAGE_AND_STORE_REGISTERS() \
asm volatile("ldr r11, =__furi_check_message \n" \
"str r12, [r11] \n" \
"ldr r12, =__furi_check_registers \n" \
"stm r12, {r0-r11} \n" \
"str lr, [r12, #48] \n" \
: \
: \
: "memory");
/** Restore registers and halt MCU
*
* - Always use it with GET_MESSAGE_AND_STORE_REGISTERS
* - If debugger is(was) connected this routine will raise bkpt
* - If debugger is not connected then endless loop
*
*/
#define RESTORE_REGISTERS_AND_HALT_MCU(debug) \
register const bool r0 asm("r0") = debug; \
asm volatile("cbnz r0, with_debugger%= \n" \
"ldr r12, =__furi_check_registers\n" \
"ldm r12, {r0-r11} \n" \
"loop%=: \n" \
"wfi \n" \
"b loop%= \n" \
"with_debugger%=: \n" \
"ldr r12, =__furi_check_registers\n" \
"ldm r12, {r0-r11} \n" \
"debug_loop%=: \n" \
"bkpt 0x00 \n" \
"wfi \n" \
"b debug_loop%= \n" \
: \
: "r"(r0) \
: "memory");
extern size_t xPortGetTotalHeapSize(void);
extern size_t xPortGetFreeHeapSize(void);
extern size_t xPortGetMinimumEverFreeHeapSize(void);
static void __furi_put_uint32_as_text(uint32_t data) {
char tmp_str[] = "-2147483648";
itoa(data, tmp_str, 10);
furi_hal_console_puts(tmp_str);
}
static void __furi_put_uint32_as_hex(uint32_t data) {
char tmp_str[] = "0xFFFFFFFF";
itoa(data, tmp_str, 16);
furi_hal_console_puts(tmp_str);
}
static void __furi_print_register_info() {
// Print registers
for(uint8_t i = 0; i < 12; i++) {
furi_hal_console_puts("\r\n\tr");
__furi_put_uint32_as_text(i);
furi_hal_console_puts(" : ");
__furi_put_uint32_as_hex(__furi_check_registers[i]);
}
furi_hal_console_puts("\r\n\tlr : ");
__furi_put_uint32_as_hex(__furi_check_registers[12]);
}
static void __furi_print_stack_info() {
furi_hal_console_puts("\r\n\tstack watermark: ");
__furi_put_uint32_as_text(uxTaskGetStackHighWaterMark(NULL) * 4);
}
static void __furi_print_bt_stack_info() {
const FuriHalBtHardfaultInfo* fault_info = furi_hal_bt_get_hardfault_info();
if(fault_info == NULL) {
furi_hal_console_puts("\r\n\tcore2: not faulted");
} else {
furi_hal_console_puts("\r\n\tcore2: hardfaulted.\r\n\tPC: ");
__furi_put_uint32_as_hex(fault_info->source_pc);
furi_hal_console_puts("\r\n\tLR: ");
__furi_put_uint32_as_hex(fault_info->source_lr);
furi_hal_console_puts("\r\n\tSP: ");
__furi_put_uint32_as_hex(fault_info->source_sp);
}
}
static void __furi_print_heap_info() {
furi_hal_console_puts("\r\n\t heap total: ");
__furi_put_uint32_as_text(xPortGetTotalHeapSize());
furi_hal_console_puts("\r\n\t heap free: ");
__furi_put_uint32_as_text(xPortGetFreeHeapSize());
furi_hal_console_puts("\r\n\t heap watermark: ");
__furi_put_uint32_as_text(xPortGetMinimumEverFreeHeapSize());
}
static void __furi_print_name(bool isr) {
if(isr) {
furi_hal_console_puts("[ISR ");
__furi_put_uint32_as_text(__get_IPSR());
furi_hal_console_puts("] ");
} else {
const char* name = pcTaskGetName(NULL);
if(name == NULL) {
furi_hal_console_puts("[main] ");
} else {
furi_hal_console_puts("[");
furi_hal_console_puts(name);
furi_hal_console_puts("] ");
}
}
}
FURI_NORETURN void __furi_crash() {
__disable_irq();
GET_MESSAGE_AND_STORE_REGISTERS();
bool isr = FURI_IS_IRQ_MODE();
if(__furi_check_message == NULL) {
__furi_check_message = "Fatal Error";
} else if(__furi_check_message == (void*)__FURI_ASSERT_MESSAGE_FLAG) {
__furi_check_message = "furi_assert failed";
} else if(__furi_check_message == (void*)__FURI_CHECK_MESSAGE_FLAG) {
__furi_check_message = "furi_check failed";
}
furi_hal_console_puts("\r\n\033[0;31m[CRASH]");
__furi_print_name(isr);
furi_hal_console_puts(__furi_check_message);
__furi_print_register_info();
if(!isr) {
__furi_print_stack_info();
}
__furi_print_heap_info();
__furi_print_bt_stack_info();
#ifndef FURI_DEBUG
// Check if debug enabled by DAP
// https://developer.arm.com/documentation/ddi0403/d/Debug-Architecture/ARMv7-M-Debug/Debug-register-support-in-the-SCS/Debug-Halting-Control-and-Status-Register--DHCSR?lang=en
bool debug = CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk;
if(debug) {
#endif
furi_hal_console_puts("\r\nSystem halted. Connect debugger for more info\r\n");
furi_hal_console_puts("\033[0m\r\n");
furi_hal_debug_enable();
RESTORE_REGISTERS_AND_HALT_MCU(true);
#ifndef FURI_DEBUG
} else {
furi_hal_rtc_set_fault_data((uint32_t)__furi_check_message);
furi_hal_console_puts("\r\nRebooting system.\r\n");
furi_hal_console_puts("\033[0m\r\n");
furi_hal_power_reset();
}
#endif
[FL-2263] Flasher service & RAM exec (#1006) * WIP on stripping fw * Compact FW build - use RAM_EXEC=1 COMPACT=1 DEBUG=0 * Fixed uninitialized storage struct; small fixes to compact fw * Flasher srv w/mocked flash ops * Fixed typos & accomodated FFF changes * Alternative fw startup branch * Working load & jmp to RAM fw * +manifest processing for stage loader; + crc verification for stage payload * Fixed questionable code & potential leaks * Lowered screen update rate; added radio stack update stubs; working dfu write * Console EP with manifest & stage validation * Added microtar lib; minor ui fixes for updater * Removed microtar * Removed mtar #2 * Added a better version of microtar * TAR archive api; LFS backup & restore core * Recursive backup/restore * LFS worker thread * Added system apps to loader - not visible in UI; full update process with restarts * Typo fix * Dropped BL & f6; tooling for updater WIP * Minor py fixes * Minor fixes to make it build after merge * Ported flash workaround from BL + fixed visuals * Minor cleanup * Chmod + loader app search fix * Python linter fix * Removed usb stuff & float read support for staged loader == -10% of binary size * Added backup/restore & update pb requests * Added stub impl to RPC for backup/restore/update commands * Reworked TAR to use borrowed Storage api; slightly reduced build size by removing `static string`; hidden update-related RPC behind defines * Moved backup&restore to storage * Fixed new message types * Backup/restore/update RPC impl * Moved furi_hal_crc to LL; minor fixes * CRC HAL rework to LL * Purging STM HAL * Brought back minimal DFU boot mode (no gui); additional crc state checks * Added splash screen, BROKEN usb function * Clock init rework WIP * Stripped graphics from DFU mode * Temp fix for unused static fun * WIP update picker - broken! * Fixed UI * Bumping version * Fixed RTC setup * Backup to update folder instead of ext root * Removed unused scenes & more usb remnants from staged loader * CI updates * Fixed update bundle name * Temporary restored USB handler * Attempt to prevent .text corruption * Comments on how I spent this Saturday * Added update file icon * Documentation updates * Moved common code to lib folder * Storage: more unit tests * Storage: blocking dir open, differentiate file and dir when freed. * Major refactoring; added input processing to updater to allow retrying on failures (not very useful prob). Added API for extraction of thread return value * Removed re-init check for manifest * Changed low-level path manipulation to toolbox/path.h; makefile cleanup; tiny fix in lint.py * Increased update worker stack size * Text fixes in backup CLI * Displaying number of update stages to run; removed timeout in handling errors * Bumping version * Added thread cleanup for spawner thread * Updated build targets to exclude firmware bundle from 'ALL' * Fixed makefile for update_package; skipping VCP init for update mode (ugly) * Switched github build from ALL to update_package * Added +x for dist_update.sh * Cli: add total heap size to "free" command * Moved (RAM) suffix to build version instead of git commit no. * DFU comment * Some fixes suggested by clang-tidy * Fixed recursive PREFIX macro * Makefile: gather all new rules in updater namespace. FuriHal: rename bootloader to boot, isr safe delays * Github: correct build target name in firmware build * FuriHal: move target switch to boot * Makefile: fix firmware flash * Furi, FuriHal: move kernel start to furi, early init * Drop bootloader related stuff * Drop cube. Drop bootloader linker script. * Renamed update_hl, moved constants to #defines * Moved update-related boot mode to separate bitfield * Reworked updater cli to single entry point; fixed crash on tar cleanup * Added Python replacement for dist shell scripts * Linter fixes for dist.py +x * Fixes for environment suffix * Dropped bash scripts * Added dirty build flag to version structure & interfaces * Version string escapes * Fixed flag logic in dist.py; added support for App instances being imported and not terminating the whole program * Fixed fw address in ReadMe.md * Rpc: fix crash on double screen start * Return back original boot behavior and fix jump to system bootloader * Cleanup code, add error sequence for RTC * Update firmware readme * FuriHal: drop boot, restructure RTC registers usage and add header register check * Furi goes first * Toolchain: add ccache support * Renamed update bundle dir Co-authored-by: DrZlo13 <who.just.the.doctor@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
2022-04-13 20:50:25 +00:00
__builtin_unreachable();
}
FURI_NORETURN void __furi_halt() {
__disable_irq();
GET_MESSAGE_AND_STORE_REGISTERS();
bool isr = FURI_IS_IRQ_MODE();
if(__furi_check_message == NULL) {
__furi_check_message = "System halt requested.";
}
furi_hal_console_puts("\r\n\033[0;31m[HALT]");
__furi_print_name(isr);
furi_hal_console_puts(__furi_check_message);
furi_hal_console_puts("\r\nSystem halted. Bye-bye!\r\n");
furi_hal_console_puts("\033[0m\r\n");
// Check if debug enabled by DAP
// https://developer.arm.com/documentation/ddi0403/d/Debug-Architecture/ARMv7-M-Debug/Debug-register-support-in-the-SCS/Debug-Halting-Control-and-Status-Register--DHCSR?lang=en
bool debug = CoreDebug->DHCSR & CoreDebug_DHCSR_C_DEBUGEN_Msk;
RESTORE_REGISTERS_AND_HALT_MCU(debug);
__builtin_unreachable();
}