1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-12 04:34:43 +04:00

FuriHal: UART refactoring (#3211)

* FuriHal: UART refactoring
* ApiSymbols: add furi_record_destroy
* FuriHal: cleanup serial API, add logging configuration in RTC
* FuriHal: hide private part in _i header. Toolbox: cleanup value index. SystemSettings: logging device and baudrate.
* FuriHal: RTC logging method documentation
* Synchronize API Symbols
* Furi: mark HEAP_PRINT_DEBUG as broken
* FuriHal: furi_hal_serial, add custom IRQ func
* Fix PR review issues
* FuriHal: UART add reception DMA (#3220)
* FuriHal: add DMA serial rx mode
* usb_uart_bridge: switch to working with DMA
* Sync api symbol versions
* FuriHal: update serial docs and api
* FuriHal: Selial added similar API for simple reception mode as with DMA
* FuriHal: Update API target H18
* API: ver API H7
* FuriHal: Serial error processing
* FuriHal: fix furi_hal_serial set baudrate
* Sync api symbols
* FuriHal: cleanup serial isr and various flag handling procedures
* FuriHal: cleanup and simplify serial API
* Debug: update UART Echo serial related flags
* FuriHal: update serial API symbols naming
* FuriHalSerial: various improvements and PR review fixes
* FuriHal: proper ISR function signatures

---------

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
Co-authored-by: hedger <hedger@users.noreply.github.com>
Co-authored-by: SkorP <skorpionm@yandex.ru>
Co-authored-by: Skorpionm <85568270+Skorpionm@users.noreply.github.com>
This commit is contained in:
あく
2024-01-16 08:09:37 +09:00
committed by GitHub
parent d73d007797
commit fc043da9c6
37 changed files with 1966 additions and 759 deletions

View File

@@ -2,7 +2,6 @@
#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>
@@ -59,69 +58,69 @@ extern size_t xPortGetTotalHeapSize(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);
furi_log_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);
furi_log_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_log_puts("\r\n\tr");
__furi_put_uint32_as_text(i);
furi_hal_console_puts(" : ");
furi_log_puts(" : ");
__furi_put_uint32_as_hex(__furi_check_registers[i]);
}
furi_hal_console_puts("\r\n\tlr : ");
furi_log_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_log_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");
furi_log_puts("\r\n\tcore2: not faulted");
} else {
furi_hal_console_puts("\r\n\tcore2: hardfaulted.\r\n\tPC: ");
furi_log_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_log_puts("\r\n\tLR: ");
__furi_put_uint32_as_hex(fault_info->source_lr);
furi_hal_console_puts("\r\n\tSP: ");
furi_log_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_log_puts("\r\n\t heap total: ");
__furi_put_uint32_as_text(xPortGetTotalHeapSize());
furi_hal_console_puts("\r\n\t heap free: ");
furi_log_puts("\r\n\t heap free: ");
__furi_put_uint32_as_text(xPortGetFreeHeapSize());
furi_hal_console_puts("\r\n\t heap watermark: ");
furi_log_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_log_puts("[ISR ");
__furi_put_uint32_as_text(__get_IPSR());
furi_hal_console_puts("] ");
furi_log_puts("] ");
} else {
const char* name = pcTaskGetName(NULL);
if(name == NULL) {
furi_hal_console_puts("[main] ");
furi_log_puts("[main] ");
} else {
furi_hal_console_puts("[");
furi_hal_console_puts(name);
furi_hal_console_puts("] ");
furi_log_puts("[");
furi_log_puts(name);
furi_log_puts("] ");
}
}
}
@@ -140,9 +139,9 @@ FURI_NORETURN void __furi_crash_implementation() {
__furi_check_message = "furi_check failed";
}
furi_hal_console_puts("\r\n\033[0;31m[CRASH]");
furi_log_puts("\r\n\033[0;31m[CRASH]");
__furi_print_name(isr);
furi_hal_console_puts(__furi_check_message);
furi_log_puts(__furi_check_message);
__furi_print_register_info();
if(!isr) {
@@ -157,8 +156,8 @@ FURI_NORETURN void __furi_crash_implementation() {
#ifdef FURI_NDEBUG
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_log_puts("\r\nSystem halted. Connect debugger for more info\r\n");
furi_log_puts("\033[0m\r\n");
furi_hal_debug_enable();
RESTORE_REGISTERS_AND_HALT_MCU(debug);
@@ -169,8 +168,8 @@ FURI_NORETURN void __furi_crash_implementation() {
ptr = (uint32_t) "Check serial logs";
}
furi_hal_rtc_set_fault_data(ptr);
furi_hal_console_puts("\r\nRebooting system.\r\n");
furi_hal_console_puts("\033[0m\r\n");
furi_log_puts("\r\nRebooting system.\r\n");
furi_log_puts("\033[0m\r\n");
furi_hal_power_reset();
}
#endif
@@ -187,11 +186,11 @@ FURI_NORETURN void __furi_halt_implementation() {
__furi_check_message = "System halt requested.";
}
furi_hal_console_puts("\r\n\033[0;31m[HALT]");
furi_log_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");
furi_log_puts(__furi_check_message);
furi_log_puts("\r\nSystem halted. Bye-bye!\r\n");
furi_log_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

View File

@@ -2,17 +2,19 @@
#include "check.h"
#include "mutex.h"
#include <furi_hal.h>
#include <m-list.h>
LIST_DEF(FuriLogHandlersList, FuriLogHandler, M_POD_OPLIST)
#define FURI_LOG_LEVEL_DEFAULT FuriLogLevelInfo
typedef struct {
FuriLogLevel log_level;
FuriLogPuts puts;
FuriLogTimestamp timestamp;
FuriMutex* mutex;
FuriLogHandlersList_t tx_handlers;
} FuriLogParams;
static FuriLogParams furi_log;
static FuriLogParams furi_log = {0};
typedef struct {
const char* str;
@@ -32,9 +34,77 @@ static const FuriLogLevelDescription FURI_LOG_LEVEL_DESCRIPTIONS[] = {
void furi_log_init() {
// Set default logging parameters
furi_log.log_level = FURI_LOG_LEVEL_DEFAULT;
furi_log.puts = furi_hal_console_puts;
furi_log.timestamp = furi_get_tick;
furi_log.mutex = furi_mutex_alloc(FuriMutexTypeNormal);
furi_log.mutex = furi_mutex_alloc(FuriMutexTypeRecursive);
FuriLogHandlersList_init(furi_log.tx_handlers);
}
bool furi_log_add_handler(FuriLogHandler handler) {
furi_check(handler.callback);
bool ret = true;
furi_check(furi_mutex_acquire(furi_log.mutex, FuriWaitForever) == FuriStatusOk);
FuriLogHandlersList_it_t it;
FuriLogHandlersList_it(it, furi_log.tx_handlers);
while(!FuriLogHandlersList_end_p(it)) {
if(memcmp(FuriLogHandlersList_ref(it), &handler, sizeof(FuriLogHandler)) == 0) {
ret = false;
} else {
FuriLogHandlersList_next(it);
}
}
if(ret) {
FuriLogHandlersList_push_back(furi_log.tx_handlers, handler);
}
furi_mutex_release(furi_log.mutex);
return ret;
}
bool furi_log_remove_handler(FuriLogHandler handler) {
bool ret = false;
furi_check(furi_mutex_acquire(furi_log.mutex, FuriWaitForever) == FuriStatusOk);
FuriLogHandlersList_it_t it;
FuriLogHandlersList_it(it, furi_log.tx_handlers);
while(!FuriLogHandlersList_end_p(it)) {
if(memcmp(FuriLogHandlersList_ref(it), &handler, sizeof(FuriLogHandler)) == 0) {
FuriLogHandlersList_remove(furi_log.tx_handlers, it);
ret = true;
} else {
FuriLogHandlersList_next(it);
}
}
furi_mutex_release(furi_log.mutex);
return ret;
}
void furi_log_tx(const uint8_t* data, size_t size) {
if(!FURI_IS_ISR()) {
furi_check(furi_mutex_acquire(furi_log.mutex, FuriWaitForever) == FuriStatusOk);
} else {
if(furi_mutex_get_owner(furi_log.mutex)) return;
}
FuriLogHandlersList_it_t it;
FuriLogHandlersList_it(it, furi_log.tx_handlers);
while(!FuriLogHandlersList_end_p(it)) {
FuriLogHandlersList_ref(it)->callback(data, size, FuriLogHandlersList_ref(it)->context);
FuriLogHandlersList_next(it);
}
if(!FURI_IS_ISR()) furi_mutex_release(furi_log.mutex);
}
void furi_log_puts(const char* data) {
furi_check(data);
furi_log_tx((const uint8_t*)data, strlen(data));
}
void furi_log_print_format(FuriLogLevel level, const char* tag, const char* format, ...) {
@@ -72,13 +142,8 @@ void furi_log_print_format(FuriLogLevel level, const char* tag, const char* form
// Timestamp
furi_string_printf(
string,
"%lu %s[%s][%s] " _FURI_LOG_CLR_RESET,
furi_log.timestamp(),
color,
log_letter,
tag);
furi_log.puts(furi_string_get_cstr(string));
string, "%lu %s[%s][%s] " _FURI_LOG_CLR_RESET, furi_get_tick(), color, log_letter, tag);
furi_log_puts(furi_string_get_cstr(string));
furi_string_reset(string);
va_list args;
@@ -86,10 +151,10 @@ void furi_log_print_format(FuriLogLevel level, const char* tag, const char* form
furi_string_vprintf(string, format, args);
va_end(args);
furi_log.puts(furi_string_get_cstr(string));
furi_log_puts(furi_string_get_cstr(string));
furi_string_free(string);
furi_log.puts("\r\n");
furi_log_puts("\r\n");
furi_mutex_release(furi_log.mutex);
}
@@ -105,7 +170,7 @@ void furi_log_print_raw_format(FuriLogLevel level, const char* format, ...) {
furi_string_vprintf(string, format, args);
va_end(args);
furi_log.puts(furi_string_get_cstr(string));
furi_log_puts(furi_string_get_cstr(string));
furi_string_free(string);
furi_mutex_release(furi_log.mutex);
@@ -123,16 +188,6 @@ FuriLogLevel furi_log_get_level(void) {
return furi_log.log_level;
}
void furi_log_set_puts(FuriLogPuts puts) {
furi_assert(puts);
furi_log.puts = puts;
}
void furi_log_set_timestamp(FuriLogTimestamp timestamp) {
furi_assert(timestamp);
furi_log.timestamp = timestamp;
}
bool furi_log_level_to_string(FuriLogLevel level, const char** str) {
for(size_t i = 0; i < COUNT_OF(FURI_LOG_LEVEL_DESCRIPTIONS); i++) {
if(level == FURI_LOG_LEVEL_DESCRIPTIONS[i].level) {

View File

@@ -39,11 +39,44 @@ typedef enum {
#define _FURI_LOG_CLR_D _FURI_LOG_CLR(_FURI_LOG_CLR_BLUE)
#define _FURI_LOG_CLR_T _FURI_LOG_CLR(_FURI_LOG_CLR_PURPLE)
typedef void (*FuriLogPuts)(const char* data);
typedef uint32_t (*FuriLogTimestamp)(void);
typedef void (*FuriLogHandlerCallback)(const uint8_t* data, size_t size, void* context);
typedef struct {
FuriLogHandlerCallback callback;
void* context;
} FuriLogHandler;
/** Initialize logging */
void furi_log_init();
void furi_log_init(void);
/** Add log TX callback
*
* @param[in] callback The callback
*
* @return true on success, false otherwise
*/
bool furi_log_add_handler(FuriLogHandler handler);
/** Remove log TX callback
*
* @param[in] callback The callback
*
* @return true on success, false otherwise
*/
bool furi_log_remove_handler(FuriLogHandler handler);
/** Transmit data through log IO callbacks
*
* @param[in] data The data
* @param[in] size The size
*/
void furi_log_tx(const uint8_t* data, size_t size);
/** Transmit data through log IO callbacks
*
* @param[in] data The data, null-terminated C-string
*/
void furi_log_puts(const char* data);
/** Print log record
*
@@ -74,19 +107,7 @@ void furi_log_set_level(FuriLogLevel level);
*
* @return The furi log level.
*/
FuriLogLevel furi_log_get_level();
/** Set log output callback
*
* @param[in] puts The puts callback
*/
void furi_log_set_puts(FuriLogPuts puts);
/** Set timestamp callback
*
* @param[in] timestamp The timestamp callback
*/
void furi_log_set_timestamp(FuriLogTimestamp timestamp);
FuriLogLevel furi_log_get_level(void);
/** Log level to string
*

View File

@@ -39,7 +39,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <stm32wbxx.h>
#include <furi_hal_console.h>
#include <core/log.h>
#include <core/common_defines.h>
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
@@ -52,6 +52,10 @@ task.h is included from an application file. */
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#ifdef HEAP_PRINT_DEBUG
#error This feature is broken, logging transport must be replaced with RTT
#endif
#if(configSUPPORT_DYNAMIC_ALLOCATION == 0)
#error This file must not be used if configSUPPORT_DYNAMIC_ALLOCATION is 0
#endif
@@ -286,13 +290,13 @@ static void print_heap_init() {
// {PHStart|heap_start|heap_end}
FURI_CRITICAL_ENTER();
furi_hal_console_puts("{PHStart|");
furi_log_puts("{PHStart|");
ultoa(heap_start, tmp_str, 16);
furi_hal_console_puts(tmp_str);
furi_hal_console_puts("|");
furi_log_puts(tmp_str);
furi_log_puts("|");
ultoa(heap_end, tmp_str, 16);
furi_hal_console_puts(tmp_str);
furi_hal_console_puts("}\r\n");
furi_log_puts(tmp_str);
furi_log_puts("}\r\n");
FURI_CRITICAL_EXIT();
}
@@ -305,15 +309,15 @@ static void print_heap_malloc(void* ptr, size_t size) {
// {thread name|m|address|size}
FURI_CRITICAL_ENTER();
furi_hal_console_puts("{");
furi_hal_console_puts(name);
furi_hal_console_puts("|m|0x");
furi_log_puts("{");
furi_log_puts(name);
furi_log_puts("|m|0x");
ultoa((unsigned long)ptr, tmp_str, 16);
furi_hal_console_puts(tmp_str);
furi_hal_console_puts("|");
furi_log_puts(tmp_str);
furi_log_puts("|");
utoa(size, tmp_str, 10);
furi_hal_console_puts(tmp_str);
furi_hal_console_puts("}\r\n");
furi_log_puts(tmp_str);
furi_log_puts("}\r\n");
FURI_CRITICAL_EXIT();
}
@@ -326,12 +330,12 @@ static void print_heap_free(void* ptr) {
// {thread name|f|address}
FURI_CRITICAL_ENTER();
furi_hal_console_puts("{");
furi_hal_console_puts(name);
furi_hal_console_puts("|f|0x");
furi_log_puts("{");
furi_log_puts(name);
furi_log_puts("|f|0x");
ultoa((unsigned long)ptr, tmp_str, 16);
furi_hal_console_puts(tmp_str);
furi_hal_console_puts("}\r\n");
furi_log_puts(tmp_str);
furi_log_puts("}\r\n");
FURI_CRITICAL_EXIT();
}
#endif

View File

@@ -114,8 +114,10 @@ FuriThreadId furi_mutex_get_owner(FuriMutex* instance) {
hMutex = (SemaphoreHandle_t)((uint32_t)instance & ~1U);
if((FURI_IS_IRQ_MODE()) || (hMutex == NULL)) {
if((hMutex == NULL)) {
owner = 0;
} else if(FURI_IS_IRQ_MODE()) {
owner = (FuriThreadId)xSemaphoreGetMutexHolderFromISR(hMutex);
} else {
owner = (FuriThreadId)xSemaphoreGetMutexHolder(hMutex);
}

View File

@@ -9,7 +9,6 @@
#include "log.h"
#include <furi_hal_rtc.h>
#include <furi_hal_console.h>
#include <FreeRTOS.h>
#include <task.h>
@@ -570,7 +569,7 @@ static size_t __furi_thread_stdout_write(FuriThread* thread, const char* data, s
if(thread->output.write_callback != NULL) {
thread->output.write_callback(data, size);
} else {
furi_hal_console_tx((const uint8_t*)data, size);
furi_log_tx((const uint8_t*)data, size);
}
return size;
}