mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-10 06:54:19 +00: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:
parent
d73d007797
commit
fc043da9c6
37 changed files with 1966 additions and 759 deletions
|
@ -1,13 +1,14 @@
|
|||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <notification/notification.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <gui/elements.h>
|
||||
#include <furi_hal_uart.h>
|
||||
#include <furi_hal_console.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/modules/dialog_ex.h>
|
||||
|
||||
#include <notification/notification.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#define LINES_ON_SCREEN 6
|
||||
#define COLUMNS_ON_SCREEN 21
|
||||
#define TAG "UartEcho"
|
||||
|
@ -22,6 +23,7 @@ typedef struct {
|
|||
View* view;
|
||||
FuriThread* worker_thread;
|
||||
FuriStreamBuffer* rx_stream;
|
||||
FuriHalSerialHandle* serial_handle;
|
||||
} UartEchoApp;
|
||||
|
||||
typedef struct {
|
||||
|
@ -39,10 +41,16 @@ struct UartDumpModel {
|
|||
typedef enum {
|
||||
WorkerEventReserved = (1 << 0), // Reserved for StreamBuffer internal event
|
||||
WorkerEventStop = (1 << 1),
|
||||
WorkerEventRx = (1 << 2),
|
||||
WorkerEventRxData = (1 << 2),
|
||||
WorkerEventRxIdle = (1 << 3),
|
||||
WorkerEventRxOverrunError = (1 << 4),
|
||||
WorkerEventRxFramingError = (1 << 5),
|
||||
WorkerEventRxNoiseError = (1 << 6),
|
||||
} WorkerEventFlags;
|
||||
|
||||
#define WORKER_EVENTS_MASK (WorkerEventStop | WorkerEventRx)
|
||||
#define WORKER_EVENTS_MASK \
|
||||
(WorkerEventStop | WorkerEventRxData | WorkerEventRxIdle | WorkerEventRxOverrunError | \
|
||||
WorkerEventRxFramingError | WorkerEventRxNoiseError)
|
||||
|
||||
const NotificationSequence sequence_notification = {
|
||||
&message_display_backlight_on,
|
||||
|
@ -91,14 +99,39 @@ static uint32_t uart_echo_exit(void* context) {
|
|||
return VIEW_NONE;
|
||||
}
|
||||
|
||||
static void uart_echo_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
||||
static void
|
||||
uart_echo_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
|
||||
furi_assert(context);
|
||||
UNUSED(handle);
|
||||
UartEchoApp* app = context;
|
||||
volatile FuriHalSerialRxEvent event_copy = event;
|
||||
UNUSED(event_copy);
|
||||
|
||||
if(ev == UartIrqEventRXNE) {
|
||||
WorkerEventFlags flag = 0;
|
||||
|
||||
if(event & FuriHalSerialRxEventData) {
|
||||
uint8_t data = furi_hal_serial_async_rx(handle);
|
||||
furi_stream_buffer_send(app->rx_stream, &data, 1, 0);
|
||||
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx);
|
||||
flag |= WorkerEventRxData;
|
||||
}
|
||||
|
||||
if(event & FuriHalSerialRxEventIdle) {
|
||||
//idle line detected, packet transmission may have ended
|
||||
flag |= WorkerEventRxIdle;
|
||||
}
|
||||
|
||||
//error detected
|
||||
if(event & FuriHalSerialRxEventFrameError) {
|
||||
flag |= WorkerEventRxFramingError;
|
||||
}
|
||||
if(event & FuriHalSerialRxEventNoiseError) {
|
||||
flag |= WorkerEventRxNoiseError;
|
||||
}
|
||||
if(event & FuriHalSerialRxEventOverrunError) {
|
||||
flag |= WorkerEventRxOverrunError;
|
||||
}
|
||||
|
||||
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), flag);
|
||||
}
|
||||
|
||||
static void uart_echo_push_to_list(UartDumpModel* model, const char data) {
|
||||
|
@ -153,13 +186,13 @@ static int32_t uart_echo_worker(void* context) {
|
|||
furi_check((events & FuriFlagError) == 0);
|
||||
|
||||
if(events & WorkerEventStop) break;
|
||||
if(events & WorkerEventRx) {
|
||||
if(events & WorkerEventRxData) {
|
||||
size_t length = 0;
|
||||
do {
|
||||
uint8_t data[64];
|
||||
length = furi_stream_buffer_receive(app->rx_stream, data, 64, 0);
|
||||
if(length > 0) {
|
||||
furi_hal_uart_tx(FuriHalUartIdUSART1, data, length);
|
||||
furi_hal_serial_tx(app->serial_handle, data, length);
|
||||
with_view_model(
|
||||
app->view,
|
||||
UartDumpModel * model,
|
||||
|
@ -176,6 +209,23 @@ static int32_t uart_echo_worker(void* context) {
|
|||
with_view_model(
|
||||
app->view, UartDumpModel * model, { UNUSED(model); }, true);
|
||||
}
|
||||
|
||||
if(events & WorkerEventRxIdle) {
|
||||
furi_hal_serial_tx(app->serial_handle, (uint8_t*)"\r\nDetect IDLE\r\n", 15);
|
||||
}
|
||||
|
||||
if(events &
|
||||
(WorkerEventRxOverrunError | WorkerEventRxFramingError | WorkerEventRxNoiseError)) {
|
||||
if(events & WorkerEventRxOverrunError) {
|
||||
furi_hal_serial_tx(app->serial_handle, (uint8_t*)"\r\nDetect ORE\r\n", 14);
|
||||
}
|
||||
if(events & WorkerEventRxFramingError) {
|
||||
furi_hal_serial_tx(app->serial_handle, (uint8_t*)"\r\nDetect FE\r\n", 13);
|
||||
}
|
||||
if(events & WorkerEventRxNoiseError) {
|
||||
furi_hal_serial_tx(app->serial_handle, (uint8_t*)"\r\nDetect NE\r\n", 13);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -221,9 +271,11 @@ static UartEchoApp* uart_echo_app_alloc(uint32_t baudrate) {
|
|||
furi_thread_start(app->worker_thread);
|
||||
|
||||
// Enable uart listener
|
||||
furi_hal_console_disable();
|
||||
furi_hal_uart_set_br(FuriHalUartIdUSART1, baudrate);
|
||||
furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, uart_echo_on_irq_cb, app);
|
||||
app->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
|
||||
furi_check(app->serial_handle);
|
||||
furi_hal_serial_init(app->serial_handle, baudrate);
|
||||
|
||||
furi_hal_serial_async_rx_start(app->serial_handle, uart_echo_on_irq_cb, app, true);
|
||||
|
||||
return app;
|
||||
}
|
||||
|
@ -231,12 +283,13 @@ static UartEchoApp* uart_echo_app_alloc(uint32_t baudrate) {
|
|||
static void uart_echo_app_free(UartEchoApp* app) {
|
||||
furi_assert(app);
|
||||
|
||||
furi_hal_console_enable(); // this will also clear IRQ callback so thread is no longer referenced
|
||||
|
||||
furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventStop);
|
||||
furi_thread_join(app->worker_thread);
|
||||
furi_thread_free(app->worker_thread);
|
||||
|
||||
furi_hal_serial_deinit(app->serial_handle);
|
||||
furi_hal_serial_control_release(app->serial_handle);
|
||||
|
||||
// Free views
|
||||
view_dispatcher_remove_view(app->view_dispatcher, 0);
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ App(
|
|||
name="GPIO",
|
||||
apptype=FlipperAppType.MENUEXTERNAL,
|
||||
entry_point="gpio_app",
|
||||
stack_size=1 * 1024,
|
||||
stack_size=2 * 1024,
|
||||
icon="A_GPIO_14",
|
||||
order=50,
|
||||
fap_libs=["assets"],
|
||||
|
|
|
@ -46,7 +46,7 @@ void line_ensure_flow_invariant(GpioApp* app) {
|
|||
// selected. This function enforces that invariant by resetting flow_pins
|
||||
// to None if it is configured to 16,15 when LPUART is selected.
|
||||
|
||||
uint8_t available_flow_pins = app->usb_uart_cfg->uart_ch == FuriHalUartIdLPUART1 ? 3 : 4;
|
||||
uint8_t available_flow_pins = app->usb_uart_cfg->uart_ch == FuriHalSerialIdLpuart ? 3 : 4;
|
||||
VariableItem* item = app->var_item_flow;
|
||||
variable_item_set_values_count(item, available_flow_pins);
|
||||
|
||||
|
@ -77,9 +77,9 @@ static void line_port_cb(VariableItem* item) {
|
|||
variable_item_set_current_value_text(item, uart_ch[index]);
|
||||
|
||||
if(index == 0)
|
||||
app->usb_uart_cfg->uart_ch = FuriHalUartIdUSART1;
|
||||
app->usb_uart_cfg->uart_ch = FuriHalSerialIdUsart;
|
||||
else if(index == 1)
|
||||
app->usb_uart_cfg->uart_ch = FuriHalUartIdLPUART1;
|
||||
app->usb_uart_cfg->uart_ch = FuriHalSerialIdLpuart;
|
||||
|
||||
line_ensure_flow_invariant(app);
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, GpioUsbUartEventConfigSet);
|
||||
|
|
|
@ -29,17 +29,18 @@ typedef enum {
|
|||
|
||||
WorkerEvtTxStop = (1 << 2),
|
||||
WorkerEvtCdcRx = (1 << 3),
|
||||
WorkerEvtCdcTxComplete = (1 << 4),
|
||||
|
||||
WorkerEvtCfgChange = (1 << 4),
|
||||
WorkerEvtCfgChange = (1 << 5),
|
||||
|
||||
WorkerEvtLineCfgSet = (1 << 5),
|
||||
WorkerEvtCtrlLineSet = (1 << 6),
|
||||
WorkerEvtLineCfgSet = (1 << 6),
|
||||
WorkerEvtCtrlLineSet = (1 << 7),
|
||||
|
||||
} WorkerEvtFlags;
|
||||
|
||||
#define WORKER_ALL_RX_EVENTS \
|
||||
(WorkerEvtStop | WorkerEvtRxDone | WorkerEvtCfgChange | WorkerEvtLineCfgSet | \
|
||||
WorkerEvtCtrlLineSet)
|
||||
WorkerEvtCtrlLineSet | WorkerEvtCdcTxComplete)
|
||||
#define WORKER_ALL_TX_EVENTS (WorkerEvtTxStop | WorkerEvtCdcRx)
|
||||
|
||||
struct UsbUartBridge {
|
||||
|
@ -50,6 +51,7 @@ struct UsbUartBridge {
|
|||
FuriThread* tx_thread;
|
||||
|
||||
FuriStreamBuffer* rx_stream;
|
||||
FuriHalSerialHandle* serial_handle;
|
||||
|
||||
FuriMutex* usb_mutex;
|
||||
|
||||
|
@ -80,11 +82,23 @@ static const CdcCallbacks cdc_cb = {
|
|||
|
||||
static int32_t usb_uart_tx_thread(void* context);
|
||||
|
||||
static void usb_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
||||
static void usb_uart_on_irq_rx_dma_cb(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialRxEvent ev,
|
||||
size_t size,
|
||||
void* context) {
|
||||
UsbUartBridge* usb_uart = (UsbUartBridge*)context;
|
||||
|
||||
if(ev == UartIrqEventRXNE) {
|
||||
furi_stream_buffer_send(usb_uart->rx_stream, &data, 1, 0);
|
||||
if(ev & (FuriHalSerialRxEventData | FuriHalSerialRxEventIdle)) {
|
||||
uint8_t data[FURI_HAL_SERIAL_DMA_BUFFER_SIZE] = {0};
|
||||
while(size) {
|
||||
size_t ret = furi_hal_serial_dma_rx(
|
||||
handle,
|
||||
data,
|
||||
(size > FURI_HAL_SERIAL_DMA_BUFFER_SIZE) ? FURI_HAL_SERIAL_DMA_BUFFER_SIZE : size);
|
||||
furi_stream_buffer_send(usb_uart->rx_stream, data, ret, 0);
|
||||
size -= ret;
|
||||
};
|
||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtRxDone);
|
||||
}
|
||||
}
|
||||
|
@ -116,32 +130,33 @@ static void usb_uart_vcp_deinit(UsbUartBridge* usb_uart, uint8_t vcp_ch) {
|
|||
}
|
||||
|
||||
static void usb_uart_serial_init(UsbUartBridge* usb_uart, uint8_t uart_ch) {
|
||||
if(uart_ch == FuriHalUartIdUSART1) {
|
||||
furi_hal_console_disable();
|
||||
} else if(uart_ch == FuriHalUartIdLPUART1) {
|
||||
furi_hal_uart_init(uart_ch, 115200);
|
||||
}
|
||||
furi_hal_uart_set_irq_cb(uart_ch, usb_uart_on_irq_cb, usb_uart);
|
||||
furi_assert(!usb_uart->serial_handle);
|
||||
|
||||
usb_uart->serial_handle = furi_hal_serial_control_acquire(uart_ch);
|
||||
furi_assert(usb_uart->serial_handle);
|
||||
|
||||
furi_hal_serial_init(usb_uart->serial_handle, 115200);
|
||||
furi_hal_serial_dma_rx_start(
|
||||
usb_uart->serial_handle, usb_uart_on_irq_rx_dma_cb, usb_uart, false);
|
||||
}
|
||||
|
||||
static void usb_uart_serial_deinit(UsbUartBridge* usb_uart, uint8_t uart_ch) {
|
||||
UNUSED(usb_uart);
|
||||
furi_hal_uart_set_irq_cb(uart_ch, NULL, NULL);
|
||||
if(uart_ch == FuriHalUartIdUSART1)
|
||||
furi_hal_console_enable();
|
||||
else if(uart_ch == FuriHalUartIdLPUART1)
|
||||
furi_hal_uart_deinit(uart_ch);
|
||||
static void usb_uart_serial_deinit(UsbUartBridge* usb_uart) {
|
||||
furi_assert(usb_uart->serial_handle);
|
||||
|
||||
furi_hal_serial_deinit(usb_uart->serial_handle);
|
||||
furi_hal_serial_control_release(usb_uart->serial_handle);
|
||||
usb_uart->serial_handle = NULL;
|
||||
}
|
||||
|
||||
static void usb_uart_set_baudrate(UsbUartBridge* usb_uart, uint32_t baudrate) {
|
||||
if(baudrate != 0) {
|
||||
furi_hal_uart_set_br(usb_uart->cfg.uart_ch, baudrate);
|
||||
furi_hal_serial_set_br(usb_uart->serial_handle, baudrate);
|
||||
usb_uart->st.baudrate_cur = baudrate;
|
||||
} else {
|
||||
struct usb_cdc_line_coding* line_cfg =
|
||||
furi_hal_cdc_get_port_settings(usb_uart->cfg.vcp_ch);
|
||||
if(line_cfg->dwDTERate > 0) {
|
||||
furi_hal_uart_set_br(usb_uart->cfg.uart_ch, line_cfg->dwDTERate);
|
||||
furi_hal_serial_set_br(usb_uart->serial_handle, line_cfg->dwDTERate);
|
||||
usb_uart->st.baudrate_cur = line_cfg->dwDTERate;
|
||||
}
|
||||
}
|
||||
|
@ -191,7 +206,7 @@ static int32_t usb_uart_worker(void* context) {
|
|||
furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
|
||||
furi_check(!(events & FuriFlagError));
|
||||
if(events & WorkerEvtStop) break;
|
||||
if(events & WorkerEvtRxDone) {
|
||||
if(events & (WorkerEvtRxDone | WorkerEvtCdcTxComplete)) {
|
||||
size_t len = furi_stream_buffer_receive(
|
||||
usb_uart->rx_stream, usb_uart->rx_buf, USB_CDC_PKT_LEN, 0);
|
||||
if(len > 0) {
|
||||
|
@ -223,7 +238,7 @@ static int32_t usb_uart_worker(void* context) {
|
|||
furi_thread_flags_set(furi_thread_get_id(usb_uart->tx_thread), WorkerEvtTxStop);
|
||||
furi_thread_join(usb_uart->tx_thread);
|
||||
|
||||
usb_uart_serial_deinit(usb_uart, usb_uart->cfg.uart_ch);
|
||||
usb_uart_serial_deinit(usb_uart);
|
||||
usb_uart_serial_init(usb_uart, usb_uart->cfg_new.uart_ch);
|
||||
|
||||
usb_uart->cfg.uart_ch = usb_uart->cfg_new.uart_ch;
|
||||
|
@ -274,7 +289,7 @@ static int32_t usb_uart_worker(void* context) {
|
|||
}
|
||||
}
|
||||
usb_uart_vcp_deinit(usb_uart, usb_uart->cfg.vcp_ch);
|
||||
usb_uart_serial_deinit(usb_uart, usb_uart->cfg.uart_ch);
|
||||
usb_uart_serial_deinit(usb_uart);
|
||||
|
||||
furi_hal_gpio_init(USB_USART_DE_RE_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
|
@ -320,18 +335,10 @@ static int32_t usb_uart_tx_thread(void* context) {
|
|||
if(usb_uart->cfg.software_de_re != 0)
|
||||
furi_hal_gpio_write(USB_USART_DE_RE_PIN, false);
|
||||
|
||||
furi_hal_uart_tx(usb_uart->cfg.uart_ch, data, len);
|
||||
furi_hal_serial_tx(usb_uart->serial_handle, data, len);
|
||||
|
||||
if(usb_uart->cfg.software_de_re != 0) {
|
||||
//TODO: FL-3276 port to new USART API
|
||||
if(usb_uart->cfg.uart_ch == FuriHalUartIdUSART1) {
|
||||
while(!LL_USART_IsActiveFlag_TC(USART1))
|
||||
;
|
||||
} else if(usb_uart->cfg.uart_ch == FuriHalUartIdLPUART1) {
|
||||
while(!LL_LPUART_IsActiveFlag_TC(LPUART1))
|
||||
;
|
||||
}
|
||||
|
||||
furi_hal_serial_tx_wait_complete(usb_uart->serial_handle);
|
||||
furi_hal_gpio_write(USB_USART_DE_RE_PIN, true);
|
||||
}
|
||||
}
|
||||
|
@ -345,6 +352,7 @@ static int32_t usb_uart_tx_thread(void* context) {
|
|||
static void vcp_on_cdc_tx_complete(void* context) {
|
||||
UsbUartBridge* usb_uart = (UsbUartBridge*)context;
|
||||
furi_semaphore_release(usb_uart->tx_sem);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtCdcTxComplete);
|
||||
}
|
||||
|
||||
static void vcp_on_cdc_rx(void* context) {
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
#include <furi_hal_usb_hid_u2f.h>
|
||||
#include <storage/storage.h>
|
||||
|
||||
#include <furi_hal_console.h>
|
||||
|
||||
#define TAG "U2fHid"
|
||||
#define WORKER_TAG TAG "Worker"
|
||||
|
||||
|
|
|
@ -211,7 +211,12 @@ void cli_command_log(Cli* cli, FuriString* args, void* context) {
|
|||
furi_log_level_to_string(furi_log_get_level(), ¤t_level);
|
||||
printf("Current log level: %s\r\n", current_level);
|
||||
|
||||
furi_hal_console_set_tx_callback(cli_command_log_tx_callback, ring);
|
||||
FuriLogHandler log_handler = {
|
||||
.callback = cli_command_log_tx_callback,
|
||||
.context = ring,
|
||||
};
|
||||
|
||||
furi_log_add_handler(log_handler);
|
||||
|
||||
printf("Use <log ?> to list available log levels\r\n");
|
||||
printf("Press CTRL+C to stop...\r\n");
|
||||
|
@ -220,7 +225,7 @@ void cli_command_log(Cli* cli, FuriString* args, void* context) {
|
|||
cli_write(cli, buffer, ret);
|
||||
}
|
||||
|
||||
furi_hal_console_set_tx_callback(NULL, NULL);
|
||||
furi_log_remove_handler(log_handler);
|
||||
|
||||
if(restore_log_level) {
|
||||
// There will be strange behaviour if log level is set from settings while log command is running
|
||||
|
|
|
@ -24,12 +24,56 @@ const uint32_t log_level_value[] = {
|
|||
};
|
||||
|
||||
static void log_level_changed(VariableItem* item) {
|
||||
// SystemSettings* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
variable_item_set_current_value_text(item, log_level_text[index]);
|
||||
furi_hal_rtc_set_log_level(log_level_value[index]);
|
||||
}
|
||||
|
||||
const char* const log_device_text[] = {
|
||||
"USART",
|
||||
"LPUART",
|
||||
"None",
|
||||
};
|
||||
|
||||
const uint32_t log_device_value[] = {
|
||||
FuriHalRtcLogDeviceUsart,
|
||||
FuriHalRtcLogDeviceLpuart,
|
||||
FuriHalRtcLogDeviceNone};
|
||||
|
||||
static void log_device_changed(VariableItem* item) {
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
variable_item_set_current_value_text(item, log_device_text[index]);
|
||||
furi_hal_rtc_set_log_device(log_device_value[index]);
|
||||
}
|
||||
|
||||
const char* const log_baud_rate_text[] = {
|
||||
"9600",
|
||||
"38400",
|
||||
"57600",
|
||||
"115200",
|
||||
"230400",
|
||||
"460800",
|
||||
"921600",
|
||||
"1843200",
|
||||
};
|
||||
|
||||
const uint32_t log_baud_rate_value[] = {
|
||||
FuriHalRtcLogBaudRate9600,
|
||||
FuriHalRtcLogBaudRate38400,
|
||||
FuriHalRtcLogBaudRate57600,
|
||||
FuriHalRtcLogBaudRate115200,
|
||||
FuriHalRtcLogBaudRate230400,
|
||||
FuriHalRtcLogBaudRate460800,
|
||||
FuriHalRtcLogBaudRate921600,
|
||||
FuriHalRtcLogBaudRate1843200,
|
||||
};
|
||||
|
||||
static void log_baud_rate_changed(VariableItem* item) {
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
variable_item_set_current_value_text(item, log_baud_rate_text[index]);
|
||||
furi_hal_rtc_set_log_baud_rate(log_baud_rate_value[index]);
|
||||
}
|
||||
|
||||
const char* const debug_text[] = {
|
||||
"OFF",
|
||||
"ON",
|
||||
|
@ -64,7 +108,6 @@ const uint32_t heap_trace_mode_value[] = {
|
|||
};
|
||||
|
||||
static void heap_trace_mode_changed(VariableItem* item) {
|
||||
// SystemSettings* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
variable_item_set_current_value_text(item, heap_trace_mode_text[index]);
|
||||
furi_hal_rtc_set_heap_track_mode(heap_trace_mode_value[index]);
|
||||
|
@ -81,7 +124,6 @@ const uint32_t mesurement_units_value[] = {
|
|||
};
|
||||
|
||||
static void mesurement_units_changed(VariableItem* item) {
|
||||
// SystemSettings* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
variable_item_set_current_value_text(item, mesurement_units_text[index]);
|
||||
locale_set_measurement_unit(mesurement_units_value[index]);
|
||||
|
@ -98,7 +140,6 @@ const uint32_t time_format_value[] = {
|
|||
};
|
||||
|
||||
static void time_format_changed(VariableItem* item) {
|
||||
// SystemSettings* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
variable_item_set_current_value_text(item, time_format_text[index]);
|
||||
locale_set_time_format(time_format_value[index]);
|
||||
|
@ -117,7 +158,6 @@ const uint32_t date_format_value[] = {
|
|||
};
|
||||
|
||||
static void date_format_changed(VariableItem* item) {
|
||||
// SystemSettings* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
variable_item_set_current_value_text(item, date_format_text[index]);
|
||||
locale_set_date_format(date_format_value[index]);
|
||||
|
@ -227,6 +267,24 @@ SystemSettings* system_settings_alloc() {
|
|||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(item, log_level_text[value_index]);
|
||||
|
||||
item = variable_item_list_add(
|
||||
app->var_item_list, "Log Device", COUNT_OF(log_device_text), log_device_changed, app);
|
||||
value_index = value_index_uint32(
|
||||
furi_hal_rtc_get_log_device(), log_device_value, COUNT_OF(log_device_text));
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(item, log_device_text[value_index]);
|
||||
|
||||
item = variable_item_list_add(
|
||||
app->var_item_list,
|
||||
"Log Baud Rate",
|
||||
COUNT_OF(log_baud_rate_text),
|
||||
log_baud_rate_changed,
|
||||
app);
|
||||
value_index = value_index_uint32(
|
||||
furi_hal_rtc_get_log_baud_rate(), log_baud_rate_value, COUNT_OF(log_baud_rate_text));
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(item, log_baud_rate_text[value_index]);
|
||||
|
||||
item = variable_item_list_add(
|
||||
app->var_item_list, "Debug", COUNT_OF(debug_text), debug_changed, app);
|
||||
value_index = furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug) ? 1 : 0;
|
||||
|
|
|
@ -58,7 +58,7 @@ When not using the API, these peripherals MUST be enabled by the user code and t
|
|||
| SPI2 | -- |
|
||||
| I2C1 | `furi_hal_i2c.h` |
|
||||
| I2C3 | -- |
|
||||
| USART1 | `furi_hal_uart.h` |
|
||||
| USART1 | `furi_hal_serial.h` |
|
||||
| LPUART1 | -- |
|
||||
| USB | `furi_hal_usb.h` |
|
||||
|
||||
|
@ -102,8 +102,8 @@ Below is the list of DMA channels and their usage by the system.
|
|||
| -- | 3 | | |
|
||||
| -- | 4 | yes | pulse reader |
|
||||
| -- | 5 | | |
|
||||
| -- | 6 | | |
|
||||
| -- | 7 | | |
|
||||
| -- | 6 | yes | USART_Rx |
|
||||
| -- | 7 | yes | LPUART_Rx |
|
||||
| DMA2 | 1 | yes | infrared, lfrfid, subghz, |
|
||||
| -- | 2 | yes | -- |
|
||||
| -- | 3 | yes | cc1101_ext |
|
||||
|
|
|
@ -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
|
||||
|
|
107
furi/core/log.c
107
furi/core/log.c
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -1,52 +1,55 @@
|
|||
#include "value_index.h"
|
||||
#include <math.h>
|
||||
|
||||
uint8_t value_index_int32(const int32_t value, const int32_t values[], uint8_t values_count) {
|
||||
int64_t last_value = INT64_MIN;
|
||||
uint8_t index = 0;
|
||||
for(uint8_t i = 0; i < values_count; i++) {
|
||||
if((value >= last_value) && (value <= values[i])) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
last_value = values[i];
|
||||
}
|
||||
return index;
|
||||
}
|
||||
size_t value_index_int32(const int32_t value, const int32_t values[], size_t values_count) {
|
||||
size_t index = 0;
|
||||
|
||||
uint8_t value_index_uint32(const uint32_t value, const uint32_t values[], uint8_t values_count) {
|
||||
int64_t last_value = INT64_MIN;
|
||||
uint8_t index = 0;
|
||||
for(uint8_t i = 0; i < values_count; i++) {
|
||||
if((value >= last_value) && (value <= values[i])) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
last_value = values[i];
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
uint8_t value_index_float(const float value, const float values[], uint8_t values_count) {
|
||||
const float epsilon = 0.01f;
|
||||
float last_value = values[0];
|
||||
uint8_t index = 0;
|
||||
for(uint8_t i = 0; i < values_count; i++) {
|
||||
if((value >= last_value - epsilon) && (value <= values[i] + epsilon)) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
last_value = values[i];
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
uint8_t value_index_bool(const bool value, const bool values[], uint8_t values_count) {
|
||||
uint8_t index = 0;
|
||||
for(uint8_t i = 0; i < values_count; i++) {
|
||||
for(size_t i = 0; i < values_count; i++) {
|
||||
if(value == values[i]) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
size_t value_index_uint32(const uint32_t value, const uint32_t values[], size_t values_count) {
|
||||
size_t index = 0;
|
||||
|
||||
for(size_t i = 0; i < values_count; i++) {
|
||||
if(value == values[i]) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
size_t value_index_float(const float value, const float values[], size_t values_count) {
|
||||
size_t index = 0;
|
||||
|
||||
for(size_t i = 0; i < values_count; i++) {
|
||||
const float epsilon = fabsf(values[i] * 0.01f);
|
||||
if(fabsf(values[i] - value) <= epsilon) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
size_t value_index_bool(const bool value, const bool values[], size_t values_count) {
|
||||
size_t index = 0;
|
||||
|
||||
for(size_t i = 0; i < values_count; i++) {
|
||||
if(value == values[i]) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -18,7 +19,7 @@ extern "C" {
|
|||
*
|
||||
* @return value's index.
|
||||
*/
|
||||
uint8_t value_index_int32(const int32_t value, const int32_t values[], uint8_t values_count);
|
||||
size_t value_index_int32(const int32_t value, const int32_t values[], size_t values_count);
|
||||
|
||||
/** Get the index of a uint32_t array element which is closest to the given value.
|
||||
*
|
||||
|
@ -31,7 +32,7 @@ uint8_t value_index_int32(const int32_t value, const int32_t values[], uint8_t v
|
|||
*
|
||||
* @return value's index.
|
||||
*/
|
||||
uint8_t value_index_uint32(const uint32_t value, const uint32_t values[], uint8_t values_count);
|
||||
size_t value_index_uint32(const uint32_t value, const uint32_t values[], size_t values_count);
|
||||
|
||||
/** Get the index of a float array element which is closest to the given value.
|
||||
*
|
||||
|
@ -44,7 +45,7 @@ uint8_t value_index_uint32(const uint32_t value, const uint32_t values[], uint8_
|
|||
*
|
||||
* @return value's index.
|
||||
*/
|
||||
uint8_t value_index_float(const float value, const float values[], uint8_t values_count);
|
||||
size_t value_index_float(const float value, const float values[], size_t values_count);
|
||||
|
||||
/** Get the index of a bool array element which is equal to the given value.
|
||||
*
|
||||
|
@ -57,7 +58,7 @@ uint8_t value_index_float(const float value, const float values[], uint8_t value
|
|||
*
|
||||
* @return value's index.
|
||||
*/
|
||||
uint8_t value_index_bool(const bool value, const bool values[], uint8_t values_count);
|
||||
size_t value_index_bool(const bool value, const bool values[], size_t values_count);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
entry,status,name,type,params
|
||||
Version,+,50.1,,
|
||||
Version,+,51.0,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
Header,+,applications/services/cli/cli_vcp.h,,
|
||||
|
@ -160,7 +160,6 @@ Header,+,targets/f18/furi_hal/furi_hal_spi_config.h,,
|
|||
Header,+,targets/f18/furi_hal/furi_hal_target_hw.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_bus.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_clock.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_console.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_dma.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_flash.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_gpio.h,,
|
||||
|
@ -170,8 +169,11 @@ Header,+,targets/f7/furi_hal/furi_hal_idle_timer.h,,
|
|||
Header,+,targets/f7/furi_hal/furi_hal_interrupt.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_os.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_pwm.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_rtc.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_serial.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_serial_control.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_serial_types.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_spi_types.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_uart.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_usb_cdc.h,,
|
||||
Header,+,targets/f7/platform_specific/intrinsic_export.h,,
|
||||
Header,+,targets/f7/platform_specific/math_wrapper.h,,
|
||||
|
@ -190,7 +192,6 @@ Header,+,targets/furi_hal_include/furi_hal_mpu.h,,
|
|||
Header,+,targets/furi_hal_include/furi_hal_power.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_random.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_region.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_rtc.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_sd.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_speaker.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_spi.h,,
|
||||
|
@ -1057,14 +1058,6 @@ Function,-,furi_hal_clock_switch_hse2hsi,void,
|
|||
Function,-,furi_hal_clock_switch_hse2pll,_Bool,
|
||||
Function,-,furi_hal_clock_switch_hsi2hse,void,
|
||||
Function,-,furi_hal_clock_switch_pll2hse,_Bool,
|
||||
Function,+,furi_hal_console_disable,void,
|
||||
Function,+,furi_hal_console_enable,void,
|
||||
Function,+,furi_hal_console_init,void,
|
||||
Function,+,furi_hal_console_printf,void,"const char[], ..."
|
||||
Function,+,furi_hal_console_puts,void,const char*
|
||||
Function,+,furi_hal_console_set_tx_callback,void,"FuriHalConsoleTxCallback, void*"
|
||||
Function,+,furi_hal_console_tx,void,"const uint8_t*, size_t"
|
||||
Function,+,furi_hal_console_tx_with_new_line,void,"const uint8_t*, size_t"
|
||||
Function,+,furi_hal_cortex_comp_enable,void,"FuriHalCortexComp, FuriHalCortexCompFunction, uint32_t, uint32_t, FuriHalCortexCompSize"
|
||||
Function,+,furi_hal_cortex_comp_reset,void,FuriHalCortexComp
|
||||
Function,+,furi_hal_cortex_delay_us,void,uint32_t
|
||||
|
@ -1239,6 +1232,8 @@ Function,+,furi_hal_rtc_get_heap_track_mode,FuriHalRtcHeapTrackMode,
|
|||
Function,+,furi_hal_rtc_get_locale_dateformat,FuriHalRtcLocaleDateFormat,
|
||||
Function,+,furi_hal_rtc_get_locale_timeformat,FuriHalRtcLocaleTimeFormat,
|
||||
Function,+,furi_hal_rtc_get_locale_units,FuriHalRtcLocaleUnits,
|
||||
Function,+,furi_hal_rtc_get_log_baud_rate,FuriHalRtcLogBaudRate,
|
||||
Function,+,furi_hal_rtc_get_log_device,FuriHalRtcLogDevice,
|
||||
Function,+,furi_hal_rtc_get_log_level,uint8_t,
|
||||
Function,+,furi_hal_rtc_get_pin_fails,uint32_t,
|
||||
Function,+,furi_hal_rtc_get_register,uint32_t,FuriHalRtcRegister
|
||||
|
@ -1257,6 +1252,8 @@ Function,+,furi_hal_rtc_set_heap_track_mode,void,FuriHalRtcHeapTrackMode
|
|||
Function,+,furi_hal_rtc_set_locale_dateformat,void,FuriHalRtcLocaleDateFormat
|
||||
Function,+,furi_hal_rtc_set_locale_timeformat,void,FuriHalRtcLocaleTimeFormat
|
||||
Function,+,furi_hal_rtc_set_locale_units,void,FuriHalRtcLocaleUnits
|
||||
Function,+,furi_hal_rtc_set_log_baud_rate,void,FuriHalRtcLogBaudRate
|
||||
Function,+,furi_hal_rtc_set_log_device,void,FuriHalRtcLogDevice
|
||||
Function,+,furi_hal_rtc_set_log_level,void,uint8_t
|
||||
Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t
|
||||
Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t"
|
||||
|
@ -1271,6 +1268,26 @@ Function,+,furi_hal_sd_max_mount_retry_count,uint8_t,
|
|||
Function,+,furi_hal_sd_presence_init,void,
|
||||
Function,+,furi_hal_sd_read_blocks,FuriStatus,"uint32_t*, uint32_t, uint32_t"
|
||||
Function,+,furi_hal_sd_write_blocks,FuriStatus,"const uint32_t*, uint32_t, uint32_t"
|
||||
Function,+,furi_hal_serial_control_acquire,FuriHalSerialHandle*,FuriHalSerialId
|
||||
Function,+,furi_hal_serial_control_deinit,void,
|
||||
Function,+,furi_hal_serial_control_init,void,
|
||||
Function,+,furi_hal_serial_control_release,void,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_serial_control_resume,void,
|
||||
Function,+,furi_hal_serial_control_set_logging_config,void,"FuriHalSerialId, uint32_t"
|
||||
Function,+,furi_hal_serial_control_suspend,void,
|
||||
Function,+,furi_hal_serial_deinit,void,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_serial_dma_rx,size_t,"FuriHalSerialHandle*, uint8_t*, size_t"
|
||||
Function,+,furi_hal_serial_dma_rx_start,void,"FuriHalSerialHandle*, FuriHalSerialDmaRxCallback, void*, _Bool"
|
||||
Function,+,furi_hal_serial_dma_rx_stop,void,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_serial_init,void,"FuriHalSerialHandle*, uint32_t"
|
||||
Function,+,furi_hal_serial_resume,void,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_serial_async_rx,uint8_t,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_serial_async_rx_start,void,"FuriHalSerialHandle*, FuriHalSerialAsyncRxCallback, void*, _Bool"
|
||||
Function,+,furi_hal_serial_async_rx_stop,void,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_serial_set_br,void,"FuriHalSerialHandle*, uint32_t"
|
||||
Function,+,furi_hal_serial_suspend,void,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_serial_tx,void,"FuriHalSerialHandle*, const uint8_t*, size_t"
|
||||
Function,+,furi_hal_serial_tx_wait_complete,void,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_speaker_acquire,_Bool,uint32_t
|
||||
Function,-,furi_hal_speaker_deinit,void,
|
||||
Function,-,furi_hal_speaker_init,void,
|
||||
|
@ -1294,13 +1311,6 @@ Function,-,furi_hal_spi_config_init_early,void,
|
|||
Function,-,furi_hal_spi_dma_init,void,
|
||||
Function,+,furi_hal_spi_release,void,FuriHalSpiBusHandle*
|
||||
Function,+,furi_hal_switch,void,void*
|
||||
Function,+,furi_hal_uart_deinit,void,FuriHalUartId
|
||||
Function,+,furi_hal_uart_init,void,"FuriHalUartId, uint32_t"
|
||||
Function,+,furi_hal_uart_resume,void,FuriHalUartId
|
||||
Function,+,furi_hal_uart_set_br,void,"FuriHalUartId, uint32_t"
|
||||
Function,+,furi_hal_uart_set_irq_cb,void,"FuriHalUartId, void (*)(UartIrqEvent, uint8_t, void*), void*"
|
||||
Function,+,furi_hal_uart_suspend,void,FuriHalUartId
|
||||
Function,+,furi_hal_uart_tx,void,"FuriHalUartId, uint8_t*, size_t"
|
||||
Function,+,furi_hal_usb_disable,void,
|
||||
Function,+,furi_hal_usb_enable,void,
|
||||
Function,+,furi_hal_usb_get_config,FuriHalUsbInterface*,
|
||||
|
@ -1346,15 +1356,17 @@ Function,+,furi_kernel_is_running,_Bool,
|
|||
Function,+,furi_kernel_lock,int32_t,
|
||||
Function,+,furi_kernel_restore_lock,int32_t,int32_t
|
||||
Function,+,furi_kernel_unlock,int32_t,
|
||||
Function,+,furi_log_add_handler,_Bool,FuriLogHandler
|
||||
Function,+,furi_log_get_level,FuriLogLevel,
|
||||
Function,-,furi_log_init,void,
|
||||
Function,+,furi_log_level_from_string,_Bool,"const char*, FuriLogLevel*"
|
||||
Function,+,furi_log_level_to_string,_Bool,"FuriLogLevel, const char**"
|
||||
Function,+,furi_log_print_format,void,"FuriLogLevel, const char*, const char*, ..."
|
||||
Function,+,furi_log_print_raw_format,void,"FuriLogLevel, const char*, ..."
|
||||
Function,+,furi_log_puts,void,const char*
|
||||
Function,+,furi_log_remove_handler,_Bool,FuriLogHandler
|
||||
Function,+,furi_log_set_level,void,FuriLogLevel
|
||||
Function,-,furi_log_set_puts,void,FuriLogPuts
|
||||
Function,-,furi_log_set_timestamp,void,FuriLogTimestamp
|
||||
Function,+,furi_log_tx,void,"const uint8_t*, size_t"
|
||||
Function,+,furi_message_queue_alloc,FuriMessageQueue*,"uint32_t, uint32_t"
|
||||
Function,+,furi_message_queue_free,void,FuriMessageQueue*
|
||||
Function,+,furi_message_queue_get,FuriStatus,"FuriMessageQueue*, void*, uint32_t"
|
||||
|
@ -2418,10 +2430,10 @@ Function,-,utoa,char*,"unsigned, char*, int"
|
|||
Function,+,validator_is_file_alloc_init,ValidatorIsFile*,"const char*, const char*, const char*"
|
||||
Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*"
|
||||
Function,+,validator_is_file_free,void,ValidatorIsFile*
|
||||
Function,+,value_index_bool,uint8_t,"const _Bool, const _Bool[], uint8_t"
|
||||
Function,+,value_index_float,uint8_t,"const float, const float[], uint8_t"
|
||||
Function,+,value_index_int32,uint8_t,"const int32_t, const int32_t[], uint8_t"
|
||||
Function,+,value_index_uint32,uint8_t,"const uint32_t, const uint32_t[], uint8_t"
|
||||
Function,+,value_index_bool,size_t,"const _Bool, const _Bool[], size_t"
|
||||
Function,+,value_index_float,size_t,"const float, const float[], size_t"
|
||||
Function,+,value_index_int32,size_t,"const int32_t, const int32_t[], size_t"
|
||||
Function,+,value_index_uint32,size_t,"const uint32_t, const uint32_t[], size_t"
|
||||
Function,+,variable_item_get_context,void*,VariableItem*
|
||||
Function,+,variable_item_get_current_value_index,uint8_t,VariableItem*
|
||||
Function,+,variable_item_list_add,VariableItem*,"VariableItemList*, const char*, uint8_t, VariableItemChangeCallback, void*"
|
||||
|
|
|
|
@ -33,7 +33,7 @@ void furi_hal_init() {
|
|||
furi_hal_mpu_init();
|
||||
furi_hal_clock_init();
|
||||
furi_hal_random_init();
|
||||
furi_hal_console_init();
|
||||
furi_hal_serial_control_init();
|
||||
furi_hal_rtc_init();
|
||||
furi_hal_interrupt_init();
|
||||
furi_hal_flash_init();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
entry,status,name,type,params
|
||||
Version,+,50.1,,
|
||||
Version,+,51.0,,
|
||||
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
|
@ -221,7 +221,6 @@ Header,+,lib/toolbox/value_index.h,,
|
|||
Header,+,lib/toolbox/version.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_bus.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_clock.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_console.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_dma.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_flash.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_gpio.h,,
|
||||
|
@ -234,11 +233,14 @@ Header,+,targets/f7/furi_hal/furi_hal_os.h,,
|
|||
Header,+,targets/f7/furi_hal/furi_hal_pwm.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_resources.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_rfid.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_rtc.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_serial.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_serial_control.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_serial_types.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_spi_config.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_spi_types.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_subghz.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_target_hw.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_uart.h,,
|
||||
Header,+,targets/f7/furi_hal/furi_hal_usb_cdc.h,,
|
||||
Header,+,targets/f7/platform_specific/intrinsic_export.h,,
|
||||
Header,+,targets/f7/platform_specific/math_wrapper.h,,
|
||||
|
@ -259,7 +261,6 @@ Header,+,targets/furi_hal_include/furi_hal_nfc.h,,
|
|||
Header,+,targets/furi_hal_include/furi_hal_power.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_random.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_region.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_rtc.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_sd.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_speaker.h,,
|
||||
Header,+,targets/furi_hal_include/furi_hal_spi.h,,
|
||||
|
@ -1146,14 +1147,6 @@ Function,-,furi_hal_clock_switch_hse2hsi,void,
|
|||
Function,-,furi_hal_clock_switch_hse2pll,_Bool,
|
||||
Function,-,furi_hal_clock_switch_hsi2hse,void,
|
||||
Function,-,furi_hal_clock_switch_pll2hse,_Bool,
|
||||
Function,+,furi_hal_console_disable,void,
|
||||
Function,+,furi_hal_console_enable,void,
|
||||
Function,+,furi_hal_console_init,void,
|
||||
Function,+,furi_hal_console_printf,void,"const char[], ..."
|
||||
Function,+,furi_hal_console_puts,void,const char*
|
||||
Function,+,furi_hal_console_set_tx_callback,void,"FuriHalConsoleTxCallback, void*"
|
||||
Function,+,furi_hal_console_tx,void,"const uint8_t*, size_t"
|
||||
Function,+,furi_hal_console_tx_with_new_line,void,"const uint8_t*, size_t"
|
||||
Function,+,furi_hal_cortex_comp_enable,void,"FuriHalCortexComp, FuriHalCortexCompFunction, uint32_t, uint32_t, FuriHalCortexCompSize"
|
||||
Function,+,furi_hal_cortex_comp_reset,void,FuriHalCortexComp
|
||||
Function,+,furi_hal_cortex_delay_us,void,uint32_t
|
||||
|
@ -1405,6 +1398,8 @@ Function,+,furi_hal_rtc_get_heap_track_mode,FuriHalRtcHeapTrackMode,
|
|||
Function,+,furi_hal_rtc_get_locale_dateformat,FuriHalRtcLocaleDateFormat,
|
||||
Function,+,furi_hal_rtc_get_locale_timeformat,FuriHalRtcLocaleTimeFormat,
|
||||
Function,+,furi_hal_rtc_get_locale_units,FuriHalRtcLocaleUnits,
|
||||
Function,+,furi_hal_rtc_get_log_baud_rate,FuriHalRtcLogBaudRate,
|
||||
Function,+,furi_hal_rtc_get_log_device,FuriHalRtcLogDevice,
|
||||
Function,+,furi_hal_rtc_get_log_level,uint8_t,
|
||||
Function,+,furi_hal_rtc_get_pin_fails,uint32_t,
|
||||
Function,+,furi_hal_rtc_get_register,uint32_t,FuriHalRtcRegister
|
||||
|
@ -1423,6 +1418,8 @@ Function,+,furi_hal_rtc_set_heap_track_mode,void,FuriHalRtcHeapTrackMode
|
|||
Function,+,furi_hal_rtc_set_locale_dateformat,void,FuriHalRtcLocaleDateFormat
|
||||
Function,+,furi_hal_rtc_set_locale_timeformat,void,FuriHalRtcLocaleTimeFormat
|
||||
Function,+,furi_hal_rtc_set_locale_units,void,FuriHalRtcLocaleUnits
|
||||
Function,+,furi_hal_rtc_set_log_baud_rate,void,FuriHalRtcLogBaudRate
|
||||
Function,+,furi_hal_rtc_set_log_device,void,FuriHalRtcLogDevice
|
||||
Function,+,furi_hal_rtc_set_log_level,void,uint8_t
|
||||
Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t
|
||||
Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t"
|
||||
|
@ -1437,6 +1434,26 @@ Function,+,furi_hal_sd_max_mount_retry_count,uint8_t,
|
|||
Function,+,furi_hal_sd_presence_init,void,
|
||||
Function,+,furi_hal_sd_read_blocks,FuriStatus,"uint32_t*, uint32_t, uint32_t"
|
||||
Function,+,furi_hal_sd_write_blocks,FuriStatus,"const uint32_t*, uint32_t, uint32_t"
|
||||
Function,+,furi_hal_serial_control_acquire,FuriHalSerialHandle*,FuriHalSerialId
|
||||
Function,+,furi_hal_serial_control_deinit,void,
|
||||
Function,+,furi_hal_serial_control_init,void,
|
||||
Function,+,furi_hal_serial_control_release,void,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_serial_control_resume,void,
|
||||
Function,+,furi_hal_serial_control_set_logging_config,void,"FuriHalSerialId, uint32_t"
|
||||
Function,+,furi_hal_serial_control_suspend,void,
|
||||
Function,+,furi_hal_serial_deinit,void,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_serial_dma_rx,size_t,"FuriHalSerialHandle*, uint8_t*, size_t"
|
||||
Function,+,furi_hal_serial_dma_rx_start,void,"FuriHalSerialHandle*, FuriHalSerialDmaRxCallback, void*, _Bool"
|
||||
Function,+,furi_hal_serial_dma_rx_stop,void,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_serial_init,void,"FuriHalSerialHandle*, uint32_t"
|
||||
Function,+,furi_hal_serial_resume,void,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_serial_async_rx,uint8_t,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_serial_async_rx_start,void,"FuriHalSerialHandle*, FuriHalSerialAsyncRxCallback, void*, _Bool"
|
||||
Function,+,furi_hal_serial_async_rx_stop,void,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_serial_set_br,void,"FuriHalSerialHandle*, uint32_t"
|
||||
Function,+,furi_hal_serial_suspend,void,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_serial_tx,void,"FuriHalSerialHandle*, const uint8_t*, size_t"
|
||||
Function,+,furi_hal_serial_tx_wait_complete,void,FuriHalSerialHandle*
|
||||
Function,+,furi_hal_speaker_acquire,_Bool,uint32_t
|
||||
Function,-,furi_hal_speaker_deinit,void,
|
||||
Function,-,furi_hal_speaker_init,void,
|
||||
|
@ -1490,13 +1507,6 @@ Function,+,furi_hal_subghz_stop_async_tx,void,
|
|||
Function,+,furi_hal_subghz_tx,_Bool,
|
||||
Function,+,furi_hal_subghz_write_packet,void,"const uint8_t*, uint8_t"
|
||||
Function,+,furi_hal_switch,void,void*
|
||||
Function,+,furi_hal_uart_deinit,void,FuriHalUartId
|
||||
Function,+,furi_hal_uart_init,void,"FuriHalUartId, uint32_t"
|
||||
Function,+,furi_hal_uart_resume,void,FuriHalUartId
|
||||
Function,+,furi_hal_uart_set_br,void,"FuriHalUartId, uint32_t"
|
||||
Function,+,furi_hal_uart_set_irq_cb,void,"FuriHalUartId, void (*)(UartIrqEvent, uint8_t, void*), void*"
|
||||
Function,+,furi_hal_uart_suspend,void,FuriHalUartId
|
||||
Function,+,furi_hal_uart_tx,void,"FuriHalUartId, uint8_t*, size_t"
|
||||
Function,+,furi_hal_usb_disable,void,
|
||||
Function,+,furi_hal_usb_enable,void,
|
||||
Function,+,furi_hal_usb_get_config,FuriHalUsbInterface*,
|
||||
|
@ -1542,15 +1552,17 @@ Function,+,furi_kernel_is_running,_Bool,
|
|||
Function,+,furi_kernel_lock,int32_t,
|
||||
Function,+,furi_kernel_restore_lock,int32_t,int32_t
|
||||
Function,+,furi_kernel_unlock,int32_t,
|
||||
Function,+,furi_log_add_handler,_Bool,FuriLogHandler
|
||||
Function,+,furi_log_get_level,FuriLogLevel,
|
||||
Function,-,furi_log_init,void,
|
||||
Function,+,furi_log_level_from_string,_Bool,"const char*, FuriLogLevel*"
|
||||
Function,+,furi_log_level_to_string,_Bool,"FuriLogLevel, const char**"
|
||||
Function,+,furi_log_print_format,void,"FuriLogLevel, const char*, const char*, ..."
|
||||
Function,+,furi_log_print_raw_format,void,"FuriLogLevel, const char*, ..."
|
||||
Function,+,furi_log_puts,void,const char*
|
||||
Function,+,furi_log_remove_handler,_Bool,FuriLogHandler
|
||||
Function,+,furi_log_set_level,void,FuriLogLevel
|
||||
Function,-,furi_log_set_puts,void,FuriLogPuts
|
||||
Function,-,furi_log_set_timestamp,void,FuriLogTimestamp
|
||||
Function,+,furi_log_tx,void,"const uint8_t*, size_t"
|
||||
Function,+,furi_message_queue_alloc,FuriMessageQueue*,"uint32_t, uint32_t"
|
||||
Function,+,furi_message_queue_free,void,FuriMessageQueue*
|
||||
Function,+,furi_message_queue_get,FuriStatus,"FuriMessageQueue*, void*, uint32_t"
|
||||
|
@ -3202,10 +3214,10 @@ Function,-,utoa,char*,"unsigned, char*, int"
|
|||
Function,+,validator_is_file_alloc_init,ValidatorIsFile*,"const char*, const char*, const char*"
|
||||
Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*"
|
||||
Function,+,validator_is_file_free,void,ValidatorIsFile*
|
||||
Function,+,value_index_bool,uint8_t,"const _Bool, const _Bool[], uint8_t"
|
||||
Function,+,value_index_float,uint8_t,"const float, const float[], uint8_t"
|
||||
Function,+,value_index_int32,uint8_t,"const int32_t, const int32_t[], uint8_t"
|
||||
Function,+,value_index_uint32,uint8_t,"const uint32_t, const uint32_t[], uint8_t"
|
||||
Function,+,value_index_bool,size_t,"const _Bool, const _Bool[], size_t"
|
||||
Function,+,value_index_float,size_t,"const float, const float[], size_t"
|
||||
Function,+,value_index_int32,size_t,"const int32_t, const int32_t[], size_t"
|
||||
Function,+,value_index_uint32,size_t,"const uint32_t, const uint32_t[], size_t"
|
||||
Function,+,variable_item_get_context,void*,VariableItem*
|
||||
Function,+,variable_item_get_current_value_index,uint8_t,VariableItem*
|
||||
Function,+,variable_item_list_add,VariableItem*,"VariableItemList*, const char*, uint8_t, VariableItemChangeCallback, void*"
|
||||
|
|
|
|
@ -33,7 +33,7 @@ void furi_hal_init() {
|
|||
furi_hal_mpu_init();
|
||||
furi_hal_clock_init();
|
||||
furi_hal_random_init();
|
||||
furi_hal_console_init();
|
||||
furi_hal_serial_control_init();
|
||||
furi_hal_rtc_init();
|
||||
furi_hal_interrupt_init();
|
||||
furi_hal_flash_init();
|
||||
|
|
|
@ -1,99 +0,0 @@
|
|||
#include <furi_hal_console.h>
|
||||
#include <furi_hal_uart.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stm32wbxx_ll_gpio.h>
|
||||
#include <stm32wbxx_ll_usart.h>
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define TAG "FuriHalConsole"
|
||||
|
||||
#ifdef HEAP_PRINT_DEBUG
|
||||
#define CONSOLE_BAUDRATE 1843200
|
||||
#else
|
||||
#define CONSOLE_BAUDRATE 230400
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
bool alive;
|
||||
FuriHalConsoleTxCallback tx_callback;
|
||||
void* tx_callback_context;
|
||||
} FuriHalConsole;
|
||||
|
||||
FuriHalConsole furi_hal_console = {
|
||||
.alive = false,
|
||||
.tx_callback = NULL,
|
||||
.tx_callback_context = NULL,
|
||||
};
|
||||
|
||||
void furi_hal_console_init() {
|
||||
furi_hal_uart_init(FuriHalUartIdUSART1, CONSOLE_BAUDRATE);
|
||||
furi_hal_console.alive = true;
|
||||
}
|
||||
|
||||
void furi_hal_console_enable() {
|
||||
furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, NULL, NULL);
|
||||
while(!LL_USART_IsActiveFlag_TC(USART1))
|
||||
;
|
||||
furi_hal_uart_set_br(FuriHalUartIdUSART1, CONSOLE_BAUDRATE);
|
||||
furi_hal_console.alive = true;
|
||||
}
|
||||
|
||||
void furi_hal_console_disable() {
|
||||
while(!LL_USART_IsActiveFlag_TC(USART1))
|
||||
;
|
||||
furi_hal_console.alive = false;
|
||||
}
|
||||
|
||||
void furi_hal_console_set_tx_callback(FuriHalConsoleTxCallback callback, void* context) {
|
||||
FURI_CRITICAL_ENTER();
|
||||
furi_hal_console.tx_callback = callback;
|
||||
furi_hal_console.tx_callback_context = context;
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void furi_hal_console_tx(const uint8_t* buffer, size_t buffer_size) {
|
||||
if(!furi_hal_console.alive) return;
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
// Transmit data
|
||||
|
||||
if(furi_hal_console.tx_callback) {
|
||||
furi_hal_console.tx_callback(buffer, buffer_size, furi_hal_console.tx_callback_context);
|
||||
}
|
||||
|
||||
furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)buffer, buffer_size);
|
||||
// Wait for TC flag to be raised for last char
|
||||
while(!LL_USART_IsActiveFlag_TC(USART1))
|
||||
;
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void furi_hal_console_tx_with_new_line(const uint8_t* buffer, size_t buffer_size) {
|
||||
if(!furi_hal_console.alive) return;
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
// Transmit data
|
||||
furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)buffer, buffer_size);
|
||||
// Transmit new line symbols
|
||||
furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)"\r\n", 2);
|
||||
// Wait for TC flag to be raised for last char
|
||||
while(!LL_USART_IsActiveFlag_TC(USART1))
|
||||
;
|
||||
FURI_CRITICAL_EXIT();
|
||||
}
|
||||
|
||||
void furi_hal_console_printf(const char format[], ...) {
|
||||
FuriString* string;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
string = furi_string_alloc_vprintf(format, args);
|
||||
va_end(args);
|
||||
furi_hal_console_tx((const uint8_t*)furi_string_get_cstr(string), furi_string_size(string));
|
||||
furi_string_free(string);
|
||||
}
|
||||
|
||||
void furi_hal_console_puts(const char* data) {
|
||||
furi_hal_console_tx((const uint8_t*)data, strlen(data));
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*FuriHalConsoleTxCallback)(const uint8_t* buffer, size_t size, void* context);
|
||||
|
||||
void furi_hal_console_init();
|
||||
|
||||
void furi_hal_console_enable();
|
||||
|
||||
void furi_hal_console_disable();
|
||||
|
||||
void furi_hal_console_set_tx_callback(FuriHalConsoleTxCallback callback, void* context);
|
||||
|
||||
void furi_hal_console_tx(const uint8_t* buffer, size_t buffer_size);
|
||||
|
||||
void furi_hal_console_tx_with_new_line(const uint8_t* buffer, size_t buffer_size);
|
||||
|
||||
/**
|
||||
* Printf-like plain uart interface
|
||||
* @warning Will not work in ISR context
|
||||
* @param format
|
||||
* @param ...
|
||||
*/
|
||||
void furi_hal_console_printf(const char format[], ...) _ATTRIBUTE((__format__(__printf__, 1, 2)));
|
||||
|
||||
void furi_hal_console_puts(const char* data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -59,6 +59,12 @@ const IRQn_Type furi_hal_interrupt_irqn[FuriHalInterruptIdMax] = {
|
|||
// LPTIMx
|
||||
[FuriHalInterruptIdLpTim1] = LPTIM1_IRQn,
|
||||
[FuriHalInterruptIdLpTim2] = LPTIM2_IRQn,
|
||||
|
||||
// UARTx
|
||||
[FuriHalInterruptIdUart1] = USART1_IRQn,
|
||||
|
||||
// LPUARTx
|
||||
[FuriHalInterruptIdLpUart1] = LPUART1_IRQn,
|
||||
};
|
||||
|
||||
__attribute__((always_inline)) static inline void
|
||||
|
@ -329,3 +335,11 @@ void LPTIM1_IRQHandler() {
|
|||
void LPTIM2_IRQHandler() {
|
||||
furi_hal_interrupt_call(FuriHalInterruptIdLpTim2);
|
||||
}
|
||||
|
||||
void USART1_IRQHandler(void) {
|
||||
furi_hal_interrupt_call(FuriHalInterruptIdUart1);
|
||||
}
|
||||
|
||||
void LPUART1_IRQHandler(void) {
|
||||
furi_hal_interrupt_call(FuriHalInterruptIdLpUart1);
|
||||
}
|
|
@ -49,6 +49,12 @@ typedef enum {
|
|||
FuriHalInterruptIdLpTim1,
|
||||
FuriHalInterruptIdLpTim2,
|
||||
|
||||
//UARTx
|
||||
FuriHalInterruptIdUart1,
|
||||
|
||||
//LPUARTx
|
||||
FuriHalInterruptIdLpUart1,
|
||||
|
||||
// Service value
|
||||
FuriHalInterruptIdMax,
|
||||
} FuriHalInterruptId;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
#include <furi_hal_os.h>
|
||||
#include <furi_hal_clock.h>
|
||||
#include <furi_hal_console.h>
|
||||
#include <furi_hal_power.h>
|
||||
#include <furi_hal_gpio.h>
|
||||
#include <furi_hal_resources.h>
|
||||
|
@ -208,8 +207,8 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) {
|
|||
|
||||
void vApplicationStackOverflowHook(TaskHandle_t xTask, char* pcTaskName) {
|
||||
UNUSED(xTask);
|
||||
furi_hal_console_puts("\r\n\r\n stack overflow in ");
|
||||
furi_hal_console_puts(pcTaskName);
|
||||
furi_hal_console_puts("\r\n\r\n");
|
||||
furi_log_puts("\r\n\r\n stack overflow in ");
|
||||
furi_log_puts(pcTaskName);
|
||||
furi_log_puts("\r\n\r\n");
|
||||
furi_crash("StackOverflow");
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <furi_hal_bt.h>
|
||||
#include <furi_hal_vibro.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_uart.h>
|
||||
#include <furi_hal_serial_control.h>
|
||||
#include <furi_hal_rtc.h>
|
||||
#include <furi_hal_debug.h>
|
||||
|
||||
|
@ -178,14 +178,12 @@ static inline void furi_hal_power_light_sleep() {
|
|||
|
||||
static inline void furi_hal_power_suspend_aux_periphs() {
|
||||
// Disable USART
|
||||
furi_hal_uart_suspend(FuriHalUartIdUSART1);
|
||||
furi_hal_uart_suspend(FuriHalUartIdLPUART1);
|
||||
furi_hal_serial_control_suspend();
|
||||
}
|
||||
|
||||
static inline void furi_hal_power_resume_aux_periphs() {
|
||||
// Re-enable USART
|
||||
furi_hal_uart_resume(FuriHalUartIdUSART1);
|
||||
furi_hal_uart_resume(FuriHalUartIdLPUART1);
|
||||
furi_hal_serial_control_resume();
|
||||
}
|
||||
|
||||
static inline void furi_hal_power_deep_sleep() {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <furi_hal_rtc.h>
|
||||
#include <furi_hal_light.h>
|
||||
#include <furi_hal_debug.h>
|
||||
#include <furi_hal_serial_control.h>
|
||||
|
||||
#include <stm32wbxx_ll_pwr.h>
|
||||
#include <stm32wbxx_ll_bus.h>
|
||||
|
@ -34,7 +35,9 @@ typedef struct {
|
|||
FuriHalRtcLocaleUnits locale_units : 1;
|
||||
FuriHalRtcLocaleTimeFormat locale_timeformat : 1;
|
||||
FuriHalRtcLocaleDateFormat locale_dateformat : 2;
|
||||
uint8_t reserved : 6;
|
||||
FuriHalRtcLogDevice log_device : 2;
|
||||
FuriHalRtcLogBaudRate log_baud_rate : 3;
|
||||
uint8_t reserved : 1;
|
||||
} SystemReg;
|
||||
|
||||
_Static_assert(sizeof(SystemReg) == 4, "SystemReg size mismatch");
|
||||
|
@ -51,6 +54,24 @@ static const uint8_t furi_hal_rtc_days_per_month[2][FURI_HAL_RTC_MONTHS_COUNT] =
|
|||
|
||||
static const uint16_t furi_hal_rtc_days_per_year[] = {365, 366};
|
||||
|
||||
static const FuriHalSerialId furi_hal_rtc_log_devices[] = {
|
||||
[FuriHalRtcLogDeviceUsart] = FuriHalSerialIdUsart,
|
||||
[FuriHalRtcLogDeviceLpuart] = FuriHalSerialIdLpuart,
|
||||
[FuriHalRtcLogDeviceReserved] = FuriHalSerialIdMax,
|
||||
[FuriHalRtcLogDeviceNone] = FuriHalSerialIdMax,
|
||||
};
|
||||
|
||||
static const uint32_t furi_hal_rtc_log_baud_rates[] = {
|
||||
[FuriHalRtcLogBaudRate230400] = 230400,
|
||||
[FuriHalRtcLogBaudRate9600] = 9600,
|
||||
[FuriHalRtcLogBaudRate38400] = 38400,
|
||||
[FuriHalRtcLogBaudRate57600] = 57600,
|
||||
[FuriHalRtcLogBaudRate115200] = 115200,
|
||||
[FuriHalRtcLogBaudRate460800] = 460800,
|
||||
[FuriHalRtcLogBaudRate921600] = 921600,
|
||||
[FuriHalRtcLogBaudRate1843200] = 1843200,
|
||||
};
|
||||
|
||||
static void furi_hal_rtc_reset() {
|
||||
LL_RCC_ForceBackupDomainReset();
|
||||
LL_RCC_ReleaseBackupDomainReset();
|
||||
|
@ -153,6 +174,9 @@ void furi_hal_rtc_init() {
|
|||
LL_RTC_Init(RTC, &RTC_InitStruct);
|
||||
|
||||
furi_log_set_level(furi_hal_rtc_get_log_level());
|
||||
furi_hal_serial_control_set_logging_config(
|
||||
furi_hal_rtc_log_devices[furi_hal_rtc_get_log_device()],
|
||||
furi_hal_rtc_log_baud_rates[furi_hal_rtc_get_log_baud_rate()]);
|
||||
|
||||
FURI_LOG_I(TAG, "Init OK");
|
||||
}
|
||||
|
@ -199,6 +223,40 @@ uint8_t furi_hal_rtc_get_log_level() {
|
|||
return data->log_level;
|
||||
}
|
||||
|
||||
void furi_hal_rtc_set_log_device(FuriHalRtcLogDevice device) {
|
||||
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
|
||||
SystemReg* data = (SystemReg*)&data_reg;
|
||||
data->log_device = device;
|
||||
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
|
||||
|
||||
furi_hal_serial_control_set_logging_config(
|
||||
furi_hal_rtc_log_devices[furi_hal_rtc_get_log_device()],
|
||||
furi_hal_rtc_log_baud_rates[furi_hal_rtc_get_log_baud_rate()]);
|
||||
}
|
||||
|
||||
FuriHalRtcLogDevice furi_hal_rtc_get_log_device() {
|
||||
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
|
||||
SystemReg* data = (SystemReg*)&data_reg;
|
||||
return data->log_device;
|
||||
}
|
||||
|
||||
void furi_hal_rtc_set_log_baud_rate(FuriHalRtcLogBaudRate baud_rate) {
|
||||
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
|
||||
SystemReg* data = (SystemReg*)&data_reg;
|
||||
data->log_baud_rate = baud_rate;
|
||||
furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg);
|
||||
|
||||
furi_hal_serial_control_set_logging_config(
|
||||
furi_hal_rtc_log_devices[furi_hal_rtc_get_log_device()],
|
||||
furi_hal_rtc_log_baud_rates[furi_hal_rtc_get_log_baud_rate()]);
|
||||
}
|
||||
|
||||
FuriHalRtcLogBaudRate furi_hal_rtc_get_log_baud_rate() {
|
||||
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
|
||||
SystemReg* data = (SystemReg*)&data_reg;
|
||||
return data->log_baud_rate;
|
||||
}
|
||||
|
||||
void furi_hal_rtc_set_flag(FuriHalRtcFlag flag) {
|
||||
uint32_t data_reg = furi_hal_rtc_get_register(FuriHalRtcRegisterSystem);
|
||||
SystemReg* data = (SystemReg*)&data_reg;
|
||||
|
|
|
@ -64,32 +64,50 @@ typedef enum {
|
|||
} FuriHalRtcRegister;
|
||||
|
||||
typedef enum {
|
||||
FuriHalRtcLocaleUnitsMetric = 0, /**< Metric measurement units */
|
||||
FuriHalRtcLocaleUnitsImperial = 1, /**< Imperial measurement units */
|
||||
FuriHalRtcLocaleUnitsMetric = 0x0, /**< Metric measurement units */
|
||||
FuriHalRtcLocaleUnitsImperial = 0x1, /**< Imperial measurement units */
|
||||
} FuriHalRtcLocaleUnits;
|
||||
|
||||
typedef enum {
|
||||
FuriHalRtcLocaleTimeFormat24h = 0, /**< 24-hour format */
|
||||
FuriHalRtcLocaleTimeFormat12h = 1, /**< 12-hour format */
|
||||
FuriHalRtcLocaleTimeFormat24h = 0x0, /**< 24-hour format */
|
||||
FuriHalRtcLocaleTimeFormat12h = 0x1, /**< 12-hour format */
|
||||
} FuriHalRtcLocaleTimeFormat;
|
||||
|
||||
typedef enum {
|
||||
FuriHalRtcLocaleDateFormatDMY = 0, /**< Day/Month/Year */
|
||||
FuriHalRtcLocaleDateFormatMDY = 1, /**< Month/Day/Year */
|
||||
FuriHalRtcLocaleDateFormatYMD = 2, /**< Year/Month/Day */
|
||||
FuriHalRtcLocaleDateFormatDMY = 0x0, /**< Day/Month/Year */
|
||||
FuriHalRtcLocaleDateFormatMDY = 0x1, /**< Month/Day/Year */
|
||||
FuriHalRtcLocaleDateFormatYMD = 0x2, /**< Year/Month/Day */
|
||||
} FuriHalRtcLocaleDateFormat;
|
||||
|
||||
typedef enum {
|
||||
FuriHalRtcLogDeviceUsart = 0x0, /**< Default: USART */
|
||||
FuriHalRtcLogDeviceLpuart = 0x1, /**< Default: LPUART */
|
||||
FuriHalRtcLogDeviceReserved = 0x2, /**< Reserved for future use */
|
||||
FuriHalRtcLogDeviceNone = 0x3, /**< None, disable serial logging */
|
||||
} FuriHalRtcLogDevice;
|
||||
|
||||
typedef enum {
|
||||
FuriHalRtcLogBaudRate230400 = 0x0, /**< 230400 baud */
|
||||
FuriHalRtcLogBaudRate9600 = 0x1, /**< 9600 baud */
|
||||
FuriHalRtcLogBaudRate38400 = 0x2, /**< 38400 baud */
|
||||
FuriHalRtcLogBaudRate57600 = 0x3, /**< 57600 baud */
|
||||
FuriHalRtcLogBaudRate115200 = 0x4, /**< 115200 baud */
|
||||
FuriHalRtcLogBaudRate460800 = 0x5, /**< 460800 baud */
|
||||
FuriHalRtcLogBaudRate921600 = 0x6, /**< 921600 baud */
|
||||
FuriHalRtcLogBaudRate1843200 = 0x7, /**< 1843200 baud */
|
||||
} FuriHalRtcLogBaudRate;
|
||||
|
||||
/** Early initialization */
|
||||
void furi_hal_rtc_init_early();
|
||||
void furi_hal_rtc_init_early(void);
|
||||
|
||||
/** Early de-initialization */
|
||||
void furi_hal_rtc_deinit_early();
|
||||
void furi_hal_rtc_deinit_early(void);
|
||||
|
||||
/** Initialize RTC subsystem */
|
||||
void furi_hal_rtc_init();
|
||||
void furi_hal_rtc_init(void);
|
||||
|
||||
/** Force sync shadow registers */
|
||||
void furi_hal_rtc_sync_shadow();
|
||||
void furi_hal_rtc_sync_shadow(void);
|
||||
|
||||
/** Reset ALL RTC registers content */
|
||||
void furi_hal_rtc_reset_registers();
|
||||
|
@ -119,7 +137,31 @@ void furi_hal_rtc_set_log_level(uint8_t level);
|
|||
*
|
||||
* @return The Log Level value
|
||||
*/
|
||||
uint8_t furi_hal_rtc_get_log_level();
|
||||
uint8_t furi_hal_rtc_get_log_level(void);
|
||||
|
||||
/** Set logging device
|
||||
*
|
||||
* @param[in] device The device
|
||||
*/
|
||||
void furi_hal_rtc_set_log_device(FuriHalRtcLogDevice device);
|
||||
|
||||
/** Get logging device
|
||||
*
|
||||
* @return The furi hal rtc log device.
|
||||
*/
|
||||
FuriHalRtcLogDevice furi_hal_rtc_get_log_device(void);
|
||||
|
||||
/** Set logging baud rate
|
||||
*
|
||||
* @param[in] baud_rate The baud rate
|
||||
*/
|
||||
void furi_hal_rtc_set_log_baud_rate(FuriHalRtcLogBaudRate baud_rate);
|
||||
|
||||
/** Get logging baud rate
|
||||
*
|
||||
* @return The furi hal rtc log baud rate.
|
||||
*/
|
||||
FuriHalRtcLogBaudRate furi_hal_rtc_get_log_baud_rate(void);
|
||||
|
||||
/** Set RTC Flag
|
||||
*
|
||||
|
@ -151,7 +193,7 @@ void furi_hal_rtc_set_boot_mode(FuriHalRtcBootMode mode);
|
|||
*
|
||||
* @return The RTC boot mode.
|
||||
*/
|
||||
FuriHalRtcBootMode furi_hal_rtc_get_boot_mode();
|
||||
FuriHalRtcBootMode furi_hal_rtc_get_boot_mode(void);
|
||||
|
||||
/** Set Heap Track mode
|
||||
*
|
||||
|
@ -163,7 +205,7 @@ void furi_hal_rtc_set_heap_track_mode(FuriHalRtcHeapTrackMode mode);
|
|||
*
|
||||
* @return The RTC heap track mode.
|
||||
*/
|
||||
FuriHalRtcHeapTrackMode furi_hal_rtc_get_heap_track_mode();
|
||||
FuriHalRtcHeapTrackMode furi_hal_rtc_get_heap_track_mode(void);
|
||||
|
||||
/** Set locale units
|
||||
*
|
||||
|
@ -175,7 +217,7 @@ void furi_hal_rtc_set_locale_units(FuriHalRtcLocaleUnits value);
|
|||
*
|
||||
* @return The RTC Locale Units.
|
||||
*/
|
||||
FuriHalRtcLocaleUnits furi_hal_rtc_get_locale_units();
|
||||
FuriHalRtcLocaleUnits furi_hal_rtc_get_locale_units(void);
|
||||
|
||||
/** Set RTC Locale Time Format
|
||||
*
|
||||
|
@ -187,7 +229,7 @@ void furi_hal_rtc_set_locale_timeformat(FuriHalRtcLocaleTimeFormat value);
|
|||
*
|
||||
* @return The RTC Locale Time Format.
|
||||
*/
|
||||
FuriHalRtcLocaleTimeFormat furi_hal_rtc_get_locale_timeformat();
|
||||
FuriHalRtcLocaleTimeFormat furi_hal_rtc_get_locale_timeformat(void);
|
||||
|
||||
/** Set RTC Locale Date Format
|
||||
*
|
||||
|
@ -199,7 +241,7 @@ void furi_hal_rtc_set_locale_dateformat(FuriHalRtcLocaleDateFormat value);
|
|||
*
|
||||
* @return The RTC Locale Date Format
|
||||
*/
|
||||
FuriHalRtcLocaleDateFormat furi_hal_rtc_get_locale_dateformat();
|
||||
FuriHalRtcLocaleDateFormat furi_hal_rtc_get_locale_dateformat(void);
|
||||
|
||||
/** Set RTC Date Time
|
||||
*
|
||||
|
@ -231,7 +273,7 @@ void furi_hal_rtc_set_fault_data(uint32_t value);
|
|||
*
|
||||
* @return RTC Fault Data value
|
||||
*/
|
||||
uint32_t furi_hal_rtc_get_fault_data();
|
||||
uint32_t furi_hal_rtc_get_fault_data(void);
|
||||
|
||||
/** Set Pin Fails count
|
||||
*
|
||||
|
@ -243,13 +285,13 @@ void furi_hal_rtc_set_pin_fails(uint32_t value);
|
|||
*
|
||||
* @return Pin Fails Count
|
||||
*/
|
||||
uint32_t furi_hal_rtc_get_pin_fails();
|
||||
uint32_t furi_hal_rtc_get_pin_fails(void);
|
||||
|
||||
/** Get UNIX Timestamp
|
||||
*
|
||||
* @return Unix Timestamp in seconds from UNIX epoch start
|
||||
*/
|
||||
uint32_t furi_hal_rtc_get_timestamp();
|
||||
uint32_t furi_hal_rtc_get_timestamp(void);
|
||||
|
||||
/** Convert DateTime to UNIX timestamp
|
||||
*
|
838
targets/f7/furi_hal/furi_hal_serial.c
Normal file
838
targets/f7/furi_hal/furi_hal_serial.c
Normal file
|
@ -0,0 +1,838 @@
|
|||
#include <furi_hal_serial.h>
|
||||
#include "furi_hal_serial_types_i.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stm32wbxx_ll_lpuart.h>
|
||||
#include <stm32wbxx_ll_usart.h>
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <stm32wbxx_ll_dma.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_interrupt.h>
|
||||
#include <furi_hal_bus.h>
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
#define FURI_HAL_SERIAL_USART_OVERSAMPLING LL_USART_OVERSAMPLING_16
|
||||
|
||||
#define FURI_HAL_SERIAL_USART_DMA_INSTANCE (DMA1)
|
||||
#define FURI_HAL_SERIAL_USART_DMA_CHANNEL (LL_DMA_CHANNEL_6)
|
||||
|
||||
#define FURI_HAL_SERIAL_LPUART_DMA_INSTANCE (DMA1)
|
||||
#define FURI_HAL_SERIAL_LPUART_DMA_CHANNEL (LL_DMA_CHANNEL_7)
|
||||
|
||||
typedef struct {
|
||||
uint8_t* buffer_rx_ptr;
|
||||
size_t buffer_rx_index_write;
|
||||
size_t buffer_rx_index_read;
|
||||
bool enabled;
|
||||
FuriHalSerialHandle* handle;
|
||||
FuriHalSerialAsyncRxCallback rx_byte_callback;
|
||||
FuriHalSerialDmaRxCallback rx_dma_callback;
|
||||
void* context;
|
||||
} FuriHalSerial;
|
||||
|
||||
static FuriHalSerial furi_hal_serial[FuriHalSerialIdMax] = {0};
|
||||
|
||||
static size_t furi_hal_serial_dma_bytes_available(FuriHalSerialId ch);
|
||||
|
||||
static void furi_hal_serial_async_rx_configure(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialAsyncRxCallback callback,
|
||||
void* context);
|
||||
|
||||
static void furi_hal_serial_usart_irq_callback(void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
FuriHalSerialRxEvent event = 0;
|
||||
// Notification flags
|
||||
if(USART1->ISR & USART_ISR_RXNE_RXFNE) {
|
||||
event |= FuriHalSerialRxEventData;
|
||||
}
|
||||
if(USART1->ISR & USART_ISR_IDLE) {
|
||||
USART1->ICR = USART_ICR_IDLECF;
|
||||
event |= FuriHalSerialRxEventIdle;
|
||||
}
|
||||
// Error flags
|
||||
if(USART1->ISR & USART_ISR_ORE) {
|
||||
USART1->ICR = USART_ICR_ORECF;
|
||||
event |= FuriHalSerialRxEventOverrunError;
|
||||
}
|
||||
if(USART1->ISR & USART_ISR_NE) {
|
||||
USART1->ICR = USART_ICR_NECF;
|
||||
event |= FuriHalSerialRxEventNoiseError;
|
||||
}
|
||||
if(USART1->ISR & USART_ISR_FE) {
|
||||
USART1->ICR = USART_ICR_FECF;
|
||||
event |= FuriHalSerialRxEventFrameError;
|
||||
}
|
||||
if(USART1->ISR & USART_ISR_PE) {
|
||||
USART1->ICR = USART_ICR_PECF;
|
||||
event |= FuriHalSerialRxEventFrameError;
|
||||
}
|
||||
|
||||
if(furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_ptr == NULL) {
|
||||
if(furi_hal_serial[FuriHalSerialIdUsart].rx_byte_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdUsart].rx_byte_callback(
|
||||
furi_hal_serial[FuriHalSerialIdUsart].handle,
|
||||
event,
|
||||
furi_hal_serial[FuriHalSerialIdUsart].context);
|
||||
}
|
||||
} else {
|
||||
if(furi_hal_serial[FuriHalSerialIdUsart].rx_dma_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdUsart].rx_dma_callback(
|
||||
furi_hal_serial[FuriHalSerialIdUsart].handle,
|
||||
event,
|
||||
furi_hal_serial_dma_bytes_available(FuriHalSerialIdUsart),
|
||||
furi_hal_serial[FuriHalSerialIdUsart].context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_serial_usart_dma_rx_isr(void* context) {
|
||||
UNUSED(context);
|
||||
#if FURI_HAL_SERIAL_USART_DMA_CHANNEL == LL_DMA_CHANNEL_6
|
||||
if(LL_DMA_IsActiveFlag_HT6(FURI_HAL_SERIAL_USART_DMA_INSTANCE)) {
|
||||
LL_DMA_ClearFlag_HT6(FURI_HAL_SERIAL_USART_DMA_INSTANCE);
|
||||
furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_index_write =
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE -
|
||||
LL_DMA_GetDataLength(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
if((furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_index_read >
|
||||
furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_index_write) ||
|
||||
(furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_index_read <
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE / 4)) {
|
||||
if(furi_hal_serial[FuriHalSerialIdUsart].rx_dma_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdUsart].rx_dma_callback(
|
||||
furi_hal_serial[FuriHalSerialIdUsart].handle,
|
||||
FuriHalSerialRxEventData,
|
||||
furi_hal_serial_dma_bytes_available(FuriHalSerialIdUsart),
|
||||
furi_hal_serial[FuriHalSerialIdUsart].context);
|
||||
}
|
||||
}
|
||||
|
||||
} else if(LL_DMA_IsActiveFlag_TC6(FURI_HAL_SERIAL_USART_DMA_INSTANCE)) {
|
||||
LL_DMA_ClearFlag_TC6(FURI_HAL_SERIAL_USART_DMA_INSTANCE);
|
||||
|
||||
if(furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_index_read <
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE * 3 / 4) {
|
||||
if(furi_hal_serial[FuriHalSerialIdUsart].rx_dma_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdUsart].rx_dma_callback(
|
||||
furi_hal_serial[FuriHalSerialIdUsart].handle,
|
||||
FuriHalSerialRxEventData,
|
||||
furi_hal_serial_dma_bytes_available(FuriHalSerialIdUsart),
|
||||
furi_hal_serial[FuriHalSerialIdUsart].context);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
}
|
||||
|
||||
static void furi_hal_serial_usart_init_dma_rx(void) {
|
||||
/* USART1_RX_DMA Init */
|
||||
furi_check(furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_ptr == NULL);
|
||||
furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_index_write = 0;
|
||||
furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_index_read = 0;
|
||||
furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_ptr = malloc(FURI_HAL_SERIAL_DMA_BUFFER_SIZE);
|
||||
LL_DMA_SetMemoryAddress(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_USART_DMA_CHANNEL,
|
||||
(uint32_t)furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_ptr);
|
||||
LL_DMA_SetPeriphAddress(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_USART_DMA_CHANNEL,
|
||||
(uint32_t) & (USART1->RDR));
|
||||
|
||||
LL_DMA_ConfigTransfer(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_USART_DMA_CHANNEL,
|
||||
LL_DMA_DIRECTION_PERIPH_TO_MEMORY | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT |
|
||||
LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE |
|
||||
LL_DMA_PRIORITY_HIGH);
|
||||
LL_DMA_SetDataLength(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_USART_DMA_CHANNEL,
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE);
|
||||
LL_DMA_SetPeriphRequest(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_USART_DMA_CHANNEL,
|
||||
LL_DMAMUX_REQ_USART1_RX);
|
||||
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch6, furi_hal_serial_usart_dma_rx_isr, NULL);
|
||||
|
||||
#if FURI_HAL_SERIAL_USART_DMA_CHANNEL == LL_DMA_CHANNEL_6
|
||||
if(LL_DMA_IsActiveFlag_HT6(FURI_HAL_SERIAL_USART_DMA_INSTANCE))
|
||||
LL_DMA_ClearFlag_HT6(FURI_HAL_SERIAL_USART_DMA_INSTANCE);
|
||||
if(LL_DMA_IsActiveFlag_TC6(FURI_HAL_SERIAL_USART_DMA_INSTANCE))
|
||||
LL_DMA_ClearFlag_TC6(FURI_HAL_SERIAL_USART_DMA_INSTANCE);
|
||||
if(LL_DMA_IsActiveFlag_TE6(FURI_HAL_SERIAL_USART_DMA_INSTANCE))
|
||||
LL_DMA_ClearFlag_TE6(FURI_HAL_SERIAL_USART_DMA_INSTANCE);
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
|
||||
LL_DMA_EnableIT_TC(FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
LL_DMA_EnableIT_HT(FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
|
||||
LL_DMA_EnableChannel(FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
LL_USART_EnableDMAReq_RX(USART1);
|
||||
|
||||
LL_USART_EnableIT_IDLE(USART1);
|
||||
}
|
||||
|
||||
static void furi_hal_serial_usart_deinit_dma_rx(void) {
|
||||
if(furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_ptr != NULL) {
|
||||
LL_DMA_DisableChannel(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
LL_USART_DisableDMAReq_RX(USART1);
|
||||
|
||||
LL_USART_DisableIT_IDLE(USART1);
|
||||
LL_DMA_DisableIT_TC(FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
LL_DMA_DisableIT_HT(FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
|
||||
LL_DMA_ClearFlag_TC6(FURI_HAL_SERIAL_USART_DMA_INSTANCE);
|
||||
LL_DMA_ClearFlag_HT6(FURI_HAL_SERIAL_USART_DMA_INSTANCE);
|
||||
|
||||
LL_DMA_DeInit(FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch6, NULL, NULL);
|
||||
free(furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_ptr);
|
||||
furi_hal_serial[FuriHalSerialIdUsart].buffer_rx_ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_serial_usart_init(FuriHalSerialHandle* handle, uint32_t baud) {
|
||||
furi_hal_bus_enable(FuriHalBusUSART1);
|
||||
LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_usart_tx,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn7USART1);
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_usart_rx,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn7USART1);
|
||||
|
||||
LL_USART_InitTypeDef USART_InitStruct;
|
||||
USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1;
|
||||
USART_InitStruct.BaudRate = baud;
|
||||
USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
|
||||
USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
|
||||
USART_InitStruct.Parity = LL_USART_PARITY_NONE;
|
||||
USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
|
||||
USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
|
||||
USART_InitStruct.OverSampling = FURI_HAL_SERIAL_USART_OVERSAMPLING;
|
||||
LL_USART_Init(USART1, &USART_InitStruct);
|
||||
LL_USART_EnableFIFO(USART1);
|
||||
LL_USART_ConfigAsyncMode(USART1);
|
||||
|
||||
LL_USART_Enable(USART1);
|
||||
|
||||
while(!LL_USART_IsActiveFlag_TEACK(USART1) || !LL_USART_IsActiveFlag_REACK(USART1))
|
||||
;
|
||||
|
||||
furi_hal_serial_set_br(handle, baud);
|
||||
LL_USART_DisableIT_ERROR(USART1);
|
||||
furi_hal_serial[handle->id].enabled = true;
|
||||
}
|
||||
|
||||
static void furi_hal_serial_lpuart_irq_callback(void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
FuriHalSerialRxEvent event = 0;
|
||||
// Notification flags
|
||||
if(LPUART1->ISR & USART_ISR_RXNE_RXFNE) {
|
||||
event |= FuriHalSerialRxEventData;
|
||||
}
|
||||
if(LPUART1->ISR & USART_ISR_IDLE) {
|
||||
LPUART1->ICR = USART_ICR_IDLECF;
|
||||
event |= FuriHalSerialRxEventIdle;
|
||||
}
|
||||
// Error flags
|
||||
if(LPUART1->ISR & USART_ISR_ORE) {
|
||||
LPUART1->ICR = USART_ICR_ORECF;
|
||||
event |= FuriHalSerialRxEventOverrunError;
|
||||
}
|
||||
if(LPUART1->ISR & USART_ISR_NE) {
|
||||
LPUART1->ICR = USART_ICR_NECF;
|
||||
event |= FuriHalSerialRxEventNoiseError;
|
||||
}
|
||||
if(LPUART1->ISR & USART_ISR_FE) {
|
||||
LPUART1->ICR = USART_ICR_FECF;
|
||||
event |= FuriHalSerialRxEventFrameError;
|
||||
}
|
||||
if(LPUART1->ISR & USART_ISR_PE) {
|
||||
LPUART1->ICR = USART_ICR_PECF;
|
||||
event |= FuriHalSerialRxEventFrameError;
|
||||
}
|
||||
|
||||
if(furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_ptr == NULL) {
|
||||
if(furi_hal_serial[FuriHalSerialIdLpuart].rx_byte_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].rx_byte_callback(
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].handle,
|
||||
event,
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].context);
|
||||
}
|
||||
} else {
|
||||
if(furi_hal_serial[FuriHalSerialIdLpuart].rx_dma_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].rx_dma_callback(
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].handle,
|
||||
event,
|
||||
furi_hal_serial_dma_bytes_available(FuriHalSerialIdLpuart),
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_serial_lpuart_dma_rx_isr(void* context) {
|
||||
UNUSED(context);
|
||||
#if FURI_HAL_SERIAL_LPUART_DMA_CHANNEL == LL_DMA_CHANNEL_7
|
||||
if(LL_DMA_IsActiveFlag_HT7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE)) {
|
||||
LL_DMA_ClearFlag_HT7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE);
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_index_write =
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE -
|
||||
LL_DMA_GetDataLength(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
if((furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_index_read >
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_index_write) ||
|
||||
(furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_index_read <
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE / 4)) {
|
||||
if(furi_hal_serial[FuriHalSerialIdLpuart].rx_dma_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].rx_dma_callback(
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].handle,
|
||||
FuriHalSerialRxEventData,
|
||||
furi_hal_serial_dma_bytes_available(FuriHalSerialIdLpuart),
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].context);
|
||||
}
|
||||
}
|
||||
|
||||
} else if(LL_DMA_IsActiveFlag_TC7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE)) {
|
||||
LL_DMA_ClearFlag_TC7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE);
|
||||
|
||||
if(furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_index_read <
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE * 3 / 4) {
|
||||
if(furi_hal_serial[FuriHalSerialIdLpuart].rx_dma_callback) {
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].rx_dma_callback(
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].handle,
|
||||
FuriHalSerialRxEventData,
|
||||
furi_hal_serial_dma_bytes_available(FuriHalSerialIdLpuart),
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].context);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
}
|
||||
|
||||
static void furi_hal_serial_lpuart_init_dma_rx(void) {
|
||||
/* LPUART1_RX_DMA Init */
|
||||
furi_check(furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_ptr == NULL);
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_index_write = 0;
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_index_read = 0;
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_ptr = malloc(FURI_HAL_SERIAL_DMA_BUFFER_SIZE);
|
||||
LL_DMA_SetMemoryAddress(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_LPUART_DMA_CHANNEL,
|
||||
(uint32_t)furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_ptr);
|
||||
LL_DMA_SetPeriphAddress(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_LPUART_DMA_CHANNEL,
|
||||
(uint32_t) & (LPUART1->RDR));
|
||||
|
||||
LL_DMA_ConfigTransfer(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_LPUART_DMA_CHANNEL,
|
||||
LL_DMA_DIRECTION_PERIPH_TO_MEMORY | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT |
|
||||
LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_BYTE | LL_DMA_MDATAALIGN_BYTE |
|
||||
LL_DMA_PRIORITY_HIGH);
|
||||
LL_DMA_SetDataLength(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_LPUART_DMA_CHANNEL,
|
||||
FURI_HAL_SERIAL_DMA_BUFFER_SIZE);
|
||||
LL_DMA_SetPeriphRequest(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE,
|
||||
FURI_HAL_SERIAL_LPUART_DMA_CHANNEL,
|
||||
LL_DMAMUX_REQ_LPUART1_RX);
|
||||
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch7, furi_hal_serial_lpuart_dma_rx_isr, NULL);
|
||||
|
||||
#if FURI_HAL_SERIAL_LPUART_DMA_CHANNEL == LL_DMA_CHANNEL_7
|
||||
if(LL_DMA_IsActiveFlag_HT7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE))
|
||||
LL_DMA_ClearFlag_HT7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE);
|
||||
if(LL_DMA_IsActiveFlag_TC7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE))
|
||||
LL_DMA_ClearFlag_TC7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE);
|
||||
if(LL_DMA_IsActiveFlag_TE7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE))
|
||||
LL_DMA_ClearFlag_TE7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE);
|
||||
#else
|
||||
#error Update this code. Would you kindly?
|
||||
#endif
|
||||
|
||||
LL_DMA_EnableIT_TC(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
LL_DMA_EnableIT_HT(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
|
||||
LL_DMA_EnableChannel(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
LL_USART_EnableDMAReq_RX(LPUART1);
|
||||
|
||||
LL_USART_EnableIT_IDLE(LPUART1);
|
||||
}
|
||||
|
||||
static void furi_hal_serial_lpuart_deinit_dma_rx(void) {
|
||||
if(furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_ptr != NULL) {
|
||||
LL_DMA_DisableChannel(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
LL_USART_DisableDMAReq_RX(LPUART1);
|
||||
|
||||
LL_USART_DisableIT_IDLE(LPUART1);
|
||||
LL_DMA_DisableIT_TC(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
LL_DMA_DisableIT_HT(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
|
||||
LL_DMA_ClearFlag_TC7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE);
|
||||
LL_DMA_ClearFlag_HT7(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE);
|
||||
|
||||
LL_DMA_DeInit(FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch7, NULL, NULL);
|
||||
free(furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_ptr);
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].buffer_rx_ptr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_serial_lpuart_init(FuriHalSerialHandle* handle, uint32_t baud) {
|
||||
furi_hal_bus_enable(FuriHalBusLPUART1);
|
||||
LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1);
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_ext_pc0,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn8LPUART1);
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_ext_pc1,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn8LPUART1);
|
||||
|
||||
LL_LPUART_InitTypeDef LPUART_InitStruct;
|
||||
LPUART_InitStruct.PrescalerValue = LL_LPUART_PRESCALER_DIV1;
|
||||
LPUART_InitStruct.BaudRate = baud;
|
||||
LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B;
|
||||
LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1;
|
||||
LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE;
|
||||
LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;
|
||||
LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
|
||||
LL_LPUART_Init(LPUART1, &LPUART_InitStruct);
|
||||
LL_LPUART_EnableFIFO(LPUART1);
|
||||
|
||||
LL_LPUART_Enable(LPUART1);
|
||||
|
||||
while(!LL_LPUART_IsActiveFlag_TEACK(LPUART1) || !LL_LPUART_IsActiveFlag_REACK(LPUART1))
|
||||
;
|
||||
|
||||
furi_hal_serial_set_br(handle, baud);
|
||||
LL_LPUART_DisableIT_ERROR(LPUART1);
|
||||
furi_hal_serial[handle->id].enabled = true;
|
||||
}
|
||||
|
||||
void furi_hal_serial_init(FuriHalSerialHandle* handle, uint32_t baud) {
|
||||
furi_check(handle);
|
||||
if(handle->id == FuriHalSerialIdLpuart) {
|
||||
furi_hal_serial_lpuart_init(handle, baud);
|
||||
} else if(handle->id == FuriHalSerialIdUsart) {
|
||||
furi_hal_serial_usart_init(handle, baud);
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t furi_hal_serial_get_prescaler(FuriHalSerialHandle* handle, uint32_t baud) {
|
||||
uint32_t uartclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART1_CLKSOURCE);
|
||||
uint32_t divisor = (uartclk / baud);
|
||||
uint32_t prescaler = 0;
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
if(FURI_HAL_SERIAL_USART_OVERSAMPLING == LL_USART_OVERSAMPLING_16) {
|
||||
divisor = (divisor / 16) >> 12;
|
||||
} else {
|
||||
divisor = (divisor / 8) >> 12;
|
||||
}
|
||||
if(divisor < 1) {
|
||||
prescaler = LL_USART_PRESCALER_DIV1;
|
||||
} else if(divisor < 2) {
|
||||
prescaler = LL_USART_PRESCALER_DIV2;
|
||||
} else if(divisor < 4) {
|
||||
prescaler = LL_USART_PRESCALER_DIV4;
|
||||
} else if(divisor < 6) {
|
||||
prescaler = LL_USART_PRESCALER_DIV6;
|
||||
} else if(divisor < 8) {
|
||||
prescaler = LL_USART_PRESCALER_DIV8;
|
||||
} else if(divisor < 10) {
|
||||
prescaler = LL_USART_PRESCALER_DIV10;
|
||||
} else if(divisor < 12) {
|
||||
prescaler = LL_USART_PRESCALER_DIV12;
|
||||
} else if(divisor < 16) {
|
||||
prescaler = LL_USART_PRESCALER_DIV16;
|
||||
} else if(divisor < 32) {
|
||||
prescaler = LL_USART_PRESCALER_DIV32;
|
||||
} else if(divisor < 64) {
|
||||
prescaler = LL_USART_PRESCALER_DIV64;
|
||||
} else if(divisor < 128) {
|
||||
prescaler = LL_USART_PRESCALER_DIV128;
|
||||
} else {
|
||||
prescaler = LL_USART_PRESCALER_DIV256;
|
||||
}
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
divisor >>= 12;
|
||||
if(divisor < 1) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV1;
|
||||
} else if(divisor < 2) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV2;
|
||||
} else if(divisor < 4) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV4;
|
||||
} else if(divisor < 6) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV6;
|
||||
} else if(divisor < 8) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV8;
|
||||
} else if(divisor < 10) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV10;
|
||||
} else if(divisor < 12) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV12;
|
||||
} else if(divisor < 16) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV16;
|
||||
} else if(divisor < 32) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV32;
|
||||
} else if(divisor < 64) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV64;
|
||||
} else if(divisor < 128) {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV128;
|
||||
} else {
|
||||
prescaler = LL_LPUART_PRESCALER_DIV256;
|
||||
}
|
||||
}
|
||||
|
||||
return prescaler;
|
||||
}
|
||||
|
||||
void furi_hal_serial_set_br(FuriHalSerialHandle* handle, uint32_t baud) {
|
||||
furi_check(handle);
|
||||
uint32_t prescaler = furi_hal_serial_get_prescaler(handle, baud);
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
if(LL_USART_IsEnabled(USART1)) {
|
||||
// Wait for transfer complete flag
|
||||
while(!LL_USART_IsActiveFlag_TC(USART1))
|
||||
;
|
||||
LL_USART_Disable(USART1);
|
||||
uint32_t uartclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART1_CLKSOURCE);
|
||||
LL_USART_SetPrescaler(USART1, prescaler);
|
||||
LL_USART_SetBaudRate(
|
||||
USART1, uartclk, prescaler, FURI_HAL_SERIAL_USART_OVERSAMPLING, baud);
|
||||
LL_USART_Enable(USART1);
|
||||
}
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
if(LL_LPUART_IsEnabled(LPUART1)) {
|
||||
// Wait for transfer complete flag
|
||||
while(!LL_LPUART_IsActiveFlag_TC(LPUART1))
|
||||
;
|
||||
LL_LPUART_Disable(LPUART1);
|
||||
uint32_t uartclk = LL_RCC_GetLPUARTClockFreq(LL_RCC_LPUART1_CLKSOURCE);
|
||||
LL_LPUART_SetPrescaler(LPUART1, prescaler);
|
||||
LL_LPUART_SetBaudRate(LPUART1, uartclk, prescaler, baud);
|
||||
LL_LPUART_Enable(LPUART1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_serial_deinit(FuriHalSerialHandle* handle) {
|
||||
furi_check(handle);
|
||||
furi_hal_serial_async_rx_configure(handle, NULL, NULL);
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
if(furi_hal_bus_is_enabled(FuriHalBusUSART1)) {
|
||||
furi_hal_bus_disable(FuriHalBusUSART1);
|
||||
}
|
||||
if(LL_USART_IsEnabled(USART1)) {
|
||||
LL_USART_Disable(USART1);
|
||||
}
|
||||
furi_hal_serial_usart_deinit_dma_rx();
|
||||
furi_hal_gpio_init(&gpio_usart_tx, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_usart_rx, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
if(furi_hal_bus_is_enabled(FuriHalBusLPUART1)) {
|
||||
furi_hal_bus_disable(FuriHalBusLPUART1);
|
||||
}
|
||||
if(LL_LPUART_IsEnabled(LPUART1)) {
|
||||
LL_LPUART_Disable(LPUART1);
|
||||
}
|
||||
furi_hal_serial_lpuart_deinit_dma_rx();
|
||||
furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
} else {
|
||||
furi_crash();
|
||||
}
|
||||
furi_hal_serial[handle->id].enabled = false;
|
||||
}
|
||||
|
||||
void furi_hal_serial_suspend(FuriHalSerialHandle* handle) {
|
||||
furi_check(handle);
|
||||
if(handle->id == FuriHalSerialIdLpuart && LL_LPUART_IsEnabled(LPUART1)) {
|
||||
LL_LPUART_Disable(LPUART1);
|
||||
} else if(handle->id == FuriHalSerialIdUsart && LL_USART_IsEnabled(USART1)) {
|
||||
LL_USART_Disable(USART1);
|
||||
}
|
||||
furi_hal_serial[handle->id].enabled = false;
|
||||
}
|
||||
|
||||
void furi_hal_serial_resume(FuriHalSerialHandle* handle) {
|
||||
furi_check(handle);
|
||||
if(!furi_hal_serial[handle->id].enabled) {
|
||||
if(handle->id == FuriHalSerialIdLpuart) {
|
||||
LL_LPUART_Enable(LPUART1);
|
||||
} else if(handle->id == FuriHalSerialIdUsart) {
|
||||
LL_USART_Enable(USART1);
|
||||
}
|
||||
furi_hal_serial[handle->id].enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_serial_tx(FuriHalSerialHandle* handle, const uint8_t* buffer, size_t buffer_size) {
|
||||
furi_check(handle);
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
if(LL_USART_IsEnabled(USART1) == 0) return;
|
||||
|
||||
while(buffer_size > 0) {
|
||||
while(!LL_USART_IsActiveFlag_TXE(USART1))
|
||||
;
|
||||
|
||||
LL_USART_TransmitData8(USART1, *buffer);
|
||||
buffer++;
|
||||
buffer_size--;
|
||||
}
|
||||
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
if(LL_LPUART_IsEnabled(LPUART1) == 0) return;
|
||||
|
||||
while(buffer_size > 0) {
|
||||
while(!LL_LPUART_IsActiveFlag_TXE(LPUART1))
|
||||
;
|
||||
|
||||
LL_LPUART_TransmitData8(LPUART1, *buffer);
|
||||
|
||||
buffer++;
|
||||
buffer_size--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_serial_tx_wait_complete(FuriHalSerialHandle* handle) {
|
||||
furi_check(handle);
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
if(LL_USART_IsEnabled(USART1) == 0) return;
|
||||
|
||||
while(!LL_USART_IsActiveFlag_TC(USART1))
|
||||
;
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
if(LL_LPUART_IsEnabled(LPUART1) == 0) return;
|
||||
|
||||
while(!LL_LPUART_IsActiveFlag_TC(LPUART1))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_serial_event_init(FuriHalSerialHandle* handle, bool report_errors) {
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
LL_USART_EnableIT_IDLE(USART1);
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
LL_LPUART_EnableIT_IDLE(LPUART1);
|
||||
}
|
||||
|
||||
if(report_errors) {
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
LL_USART_EnableIT_ERROR(USART1);
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
LL_LPUART_EnableIT_ERROR(LPUART1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_serial_event_deinit(FuriHalSerialHandle* handle) {
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
if(LL_USART_IsEnabledIT_IDLE(USART1)) LL_USART_DisableIT_IDLE(USART1);
|
||||
if(LL_USART_IsEnabledIT_ERROR(USART1)) LL_USART_DisableIT_ERROR(USART1);
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
if(LL_LPUART_IsEnabledIT_IDLE(LPUART1)) LL_LPUART_DisableIT_IDLE(LPUART1);
|
||||
if(LL_LPUART_IsEnabledIT_ERROR(LPUART1)) LL_LPUART_DisableIT_ERROR(LPUART1);
|
||||
}
|
||||
}
|
||||
|
||||
static void furi_hal_serial_async_rx_configure(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialAsyncRxCallback callback,
|
||||
void* context) {
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
if(callback) {
|
||||
furi_hal_serial_usart_deinit_dma_rx();
|
||||
furi_hal_interrupt_set_isr(
|
||||
FuriHalInterruptIdUart1, furi_hal_serial_usart_irq_callback, NULL);
|
||||
LL_USART_EnableIT_RXNE_RXFNE(USART1);
|
||||
} else {
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdUart1, NULL, NULL);
|
||||
furi_hal_serial_usart_deinit_dma_rx();
|
||||
LL_USART_DisableIT_RXNE_RXFNE(USART1);
|
||||
}
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
if(callback) {
|
||||
furi_hal_serial_lpuart_deinit_dma_rx();
|
||||
furi_hal_interrupt_set_isr(
|
||||
FuriHalInterruptIdLpUart1, furi_hal_serial_lpuart_irq_callback, NULL);
|
||||
LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);
|
||||
} else {
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdLpUart1, NULL, NULL);
|
||||
furi_hal_serial_lpuart_deinit_dma_rx();
|
||||
LL_LPUART_DisableIT_RXNE_RXFNE(LPUART1);
|
||||
}
|
||||
}
|
||||
furi_hal_serial[handle->id].rx_byte_callback = callback;
|
||||
furi_hal_serial[handle->id].handle = handle;
|
||||
furi_hal_serial[handle->id].rx_dma_callback = NULL;
|
||||
furi_hal_serial[handle->id].context = context;
|
||||
}
|
||||
|
||||
void furi_hal_serial_async_rx_start(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialAsyncRxCallback callback,
|
||||
void* context,
|
||||
bool report_errors) {
|
||||
furi_check(handle);
|
||||
furi_check(callback);
|
||||
|
||||
furi_hal_serial_event_init(handle, report_errors);
|
||||
furi_hal_serial_async_rx_configure(handle, callback, context);
|
||||
|
||||
// Assign different functions to different UARTs
|
||||
furi_check(
|
||||
furi_hal_serial[FuriHalSerialIdUsart].rx_byte_callback !=
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].rx_byte_callback);
|
||||
}
|
||||
|
||||
void furi_hal_serial_async_rx_stop(FuriHalSerialHandle* handle) {
|
||||
furi_check(handle);
|
||||
furi_hal_serial_event_deinit(handle);
|
||||
furi_hal_serial_async_rx_configure(handle, NULL, NULL);
|
||||
}
|
||||
|
||||
uint8_t furi_hal_serial_async_rx(FuriHalSerialHandle* handle) {
|
||||
furi_check(FURI_IS_IRQ_MODE());
|
||||
furi_assert(handle->id < FuriHalSerialIdMax);
|
||||
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
return LL_USART_ReceiveData8(USART1);
|
||||
}
|
||||
return LL_LPUART_ReceiveData8(LPUART1);
|
||||
}
|
||||
|
||||
static size_t furi_hal_serial_dma_bytes_available(FuriHalSerialId ch) {
|
||||
size_t dma_remain = 0;
|
||||
if(ch == FuriHalSerialIdUsart) {
|
||||
dma_remain = LL_DMA_GetDataLength(
|
||||
FURI_HAL_SERIAL_USART_DMA_INSTANCE, FURI_HAL_SERIAL_USART_DMA_CHANNEL);
|
||||
} else if(ch == FuriHalSerialIdLpuart) {
|
||||
dma_remain = LL_DMA_GetDataLength(
|
||||
FURI_HAL_SERIAL_LPUART_DMA_INSTANCE, FURI_HAL_SERIAL_LPUART_DMA_CHANNEL);
|
||||
} else {
|
||||
furi_crash();
|
||||
}
|
||||
|
||||
furi_hal_serial[ch].buffer_rx_index_write = FURI_HAL_SERIAL_DMA_BUFFER_SIZE - dma_remain;
|
||||
if(furi_hal_serial[ch].buffer_rx_index_write >= furi_hal_serial[ch].buffer_rx_index_read) {
|
||||
return furi_hal_serial[ch].buffer_rx_index_write -
|
||||
furi_hal_serial[ch].buffer_rx_index_read;
|
||||
} else {
|
||||
return FURI_HAL_SERIAL_DMA_BUFFER_SIZE - furi_hal_serial[ch].buffer_rx_index_read +
|
||||
furi_hal_serial[ch].buffer_rx_index_write;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t furi_hal_serial_dma_rx_read_byte(FuriHalSerialHandle* handle) {
|
||||
uint8_t data = 0;
|
||||
data =
|
||||
furi_hal_serial[handle->id].buffer_rx_ptr[furi_hal_serial[handle->id].buffer_rx_index_read];
|
||||
furi_hal_serial[handle->id].buffer_rx_index_read++;
|
||||
if(furi_hal_serial[handle->id].buffer_rx_index_read >= FURI_HAL_SERIAL_DMA_BUFFER_SIZE) {
|
||||
furi_hal_serial[handle->id].buffer_rx_index_read = 0;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
size_t furi_hal_serial_dma_rx(FuriHalSerialHandle* handle, uint8_t* data, size_t len) {
|
||||
furi_check(FURI_IS_IRQ_MODE());
|
||||
furi_assert(furi_hal_serial[handle->id].buffer_rx_ptr != NULL);
|
||||
size_t i = 0;
|
||||
size_t available = furi_hal_serial_dma_bytes_available(handle->id);
|
||||
if(available < len) {
|
||||
len = available;
|
||||
}
|
||||
for(i = 0; i < len; i++) {
|
||||
data[i] = furi_hal_serial_dma_rx_read_byte(handle);
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static void furi_hal_serial_dma_configure(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialDmaRxCallback callback,
|
||||
void* context) {
|
||||
furi_check(handle);
|
||||
|
||||
if(handle->id == FuriHalSerialIdUsart) {
|
||||
if(callback) {
|
||||
furi_hal_serial_usart_init_dma_rx();
|
||||
furi_hal_interrupt_set_isr(
|
||||
FuriHalInterruptIdUart1, furi_hal_serial_usart_irq_callback, NULL);
|
||||
} else {
|
||||
LL_USART_DisableIT_RXNE_RXFNE(USART1);
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdUart1, NULL, NULL);
|
||||
furi_hal_serial_usart_deinit_dma_rx();
|
||||
}
|
||||
} else if(handle->id == FuriHalSerialIdLpuart) {
|
||||
if(callback) {
|
||||
furi_hal_serial_lpuart_init_dma_rx();
|
||||
furi_hal_interrupt_set_isr(
|
||||
FuriHalInterruptIdLpUart1, furi_hal_serial_lpuart_irq_callback, NULL);
|
||||
} else {
|
||||
LL_LPUART_DisableIT_RXNE_RXFNE(LPUART1);
|
||||
furi_hal_interrupt_set_isr(FuriHalInterruptIdLpUart1, NULL, NULL);
|
||||
furi_hal_serial_lpuart_deinit_dma_rx();
|
||||
}
|
||||
}
|
||||
furi_hal_serial[handle->id].rx_byte_callback = NULL;
|
||||
furi_hal_serial[handle->id].handle = handle;
|
||||
furi_hal_serial[handle->id].rx_dma_callback = callback;
|
||||
furi_hal_serial[handle->id].context = context;
|
||||
}
|
||||
|
||||
void furi_hal_serial_dma_rx_start(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialDmaRxCallback callback,
|
||||
void* context,
|
||||
bool report_errors) {
|
||||
furi_check(handle);
|
||||
furi_check(callback);
|
||||
|
||||
furi_hal_serial_event_init(handle, report_errors);
|
||||
furi_hal_serial_dma_configure(handle, callback, context);
|
||||
|
||||
// Assign different functions to different UARTs
|
||||
furi_check(
|
||||
furi_hal_serial[FuriHalSerialIdUsart].rx_dma_callback !=
|
||||
furi_hal_serial[FuriHalSerialIdLpuart].rx_dma_callback);
|
||||
}
|
||||
|
||||
void furi_hal_serial_dma_rx_stop(FuriHalSerialHandle* handle) {
|
||||
furi_check(handle);
|
||||
furi_hal_serial_event_deinit(handle);
|
||||
furi_hal_serial_dma_configure(handle, NULL, NULL);
|
||||
}
|
189
targets/f7/furi_hal/furi_hal_serial.h
Normal file
189
targets/f7/furi_hal/furi_hal_serial.h
Normal file
|
@ -0,0 +1,189 @@
|
|||
/**
|
||||
* @file furi_hal_serial.h
|
||||
*
|
||||
* Serial HAL API
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "furi_hal_serial_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Initialize Serial
|
||||
*
|
||||
* Configures GPIO, configures and enables transceiver.
|
||||
*
|
||||
* @param handle Serial handle
|
||||
* @param baud baud rate
|
||||
*/
|
||||
void furi_hal_serial_init(FuriHalSerialHandle* handle, uint32_t baud);
|
||||
|
||||
/** De-initialize Serial
|
||||
*
|
||||
* Configures GPIO to analog, clears callback and callback context, disables
|
||||
* hardware
|
||||
*
|
||||
* @param handle Serial handle
|
||||
*/
|
||||
void furi_hal_serial_deinit(FuriHalSerialHandle* handle);
|
||||
|
||||
/** Suspend operation
|
||||
*
|
||||
* Suspend hardware, settings and callbacks are preserved
|
||||
*
|
||||
* @param handle Serial handle
|
||||
*/
|
||||
void furi_hal_serial_suspend(FuriHalSerialHandle* handle);
|
||||
|
||||
/** Resume operation
|
||||
*
|
||||
* Resumes hardware from suspended state
|
||||
*
|
||||
* @param handle Serial handle
|
||||
*/
|
||||
void furi_hal_serial_resume(FuriHalSerialHandle* handle);
|
||||
|
||||
/** Changes baud rate
|
||||
*
|
||||
* @param handle Serial handle
|
||||
* @param baud baud rate
|
||||
*/
|
||||
void furi_hal_serial_set_br(FuriHalSerialHandle* handle, uint32_t baud);
|
||||
|
||||
/** Transmits data in semi-blocking mode
|
||||
*
|
||||
* Fills transmission pipe with data, returns as soon as all bytes from buffer
|
||||
* are in the pipe.
|
||||
*
|
||||
* Real transmission will be completed later. Use
|
||||
* `furi_hal_serial_tx_wait_complete` to wait for completion if you need it.
|
||||
*
|
||||
* @param handle Serial handle
|
||||
* @param buffer data
|
||||
* @param buffer_size data size (in bytes)
|
||||
*/
|
||||
void furi_hal_serial_tx(FuriHalSerialHandle* handle, const uint8_t* buffer, size_t buffer_size);
|
||||
|
||||
/** Wait until transmission is completed
|
||||
*
|
||||
* Ensures that all data has been sent.
|
||||
*
|
||||
* @param handle Serial handle
|
||||
*/
|
||||
void furi_hal_serial_tx_wait_complete(FuriHalSerialHandle* handle);
|
||||
|
||||
/** Serial RX events */
|
||||
typedef enum {
|
||||
FuriHalSerialRxEventData = (1 << 0), /**< Data: new data available */
|
||||
FuriHalSerialRxEventIdle = (1 << 1), /**< Idle: bus idle detected */
|
||||
FuriHalSerialRxEventFrameError = (1 << 2), /**< Framing Error: incorrect frame detected */
|
||||
FuriHalSerialRxEventNoiseError = (1 << 3), /**< Noise Error: noise on the line detected */
|
||||
FuriHalSerialRxEventOverrunError = (1 << 4), /**< Overrun Error: no space for received data */
|
||||
} FuriHalSerialRxEvent;
|
||||
|
||||
/** Receive callback
|
||||
*
|
||||
* @warning Callback will be called in interrupt context, ensure thread
|
||||
* safety on your side.
|
||||
* @param handle Serial handle
|
||||
* @param event FuriHalSerialRxEvent
|
||||
* @param context Callback context provided earlier
|
||||
*/
|
||||
typedef void (*FuriHalSerialAsyncRxCallback)(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialRxEvent event,
|
||||
void* context);
|
||||
|
||||
/** Start and sets Serial Receive callback
|
||||
*
|
||||
* @warning Callback will be called in interrupt context, ensure thread
|
||||
* safety on your side
|
||||
*
|
||||
* @param handle Serial handle
|
||||
* @param callback callback pointer
|
||||
* @param context callback context
|
||||
* @param[in] report_errors report RX error
|
||||
*/
|
||||
void furi_hal_serial_async_rx_start(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialAsyncRxCallback callback,
|
||||
void* context,
|
||||
bool report_errors);
|
||||
|
||||
/** Stop Serial Receive
|
||||
*
|
||||
* @param handle Serial handle
|
||||
*/
|
||||
void furi_hal_serial_async_rx_stop(FuriHalSerialHandle* handle);
|
||||
|
||||
/** Get data Serial receive
|
||||
*
|
||||
* @warning This function must be called only from the callback
|
||||
* FuriHalSerialAsyncRxCallback
|
||||
*
|
||||
* @param handle Serial handle
|
||||
*
|
||||
* @return data
|
||||
*/
|
||||
uint8_t furi_hal_serial_async_rx(FuriHalSerialHandle* handle);
|
||||
|
||||
/* DMA based Serial API */
|
||||
|
||||
#define FURI_HAL_SERIAL_DMA_BUFFER_SIZE (256u)
|
||||
|
||||
/** Receive DMA callback
|
||||
*
|
||||
* @warning DMA Callback will be called in interrupt context, ensure thread
|
||||
* safety on your side.
|
||||
*
|
||||
* @param handle Serial handle
|
||||
* @param event FuriHalSerialDmaRxEvent
|
||||
* @param data_len Received data
|
||||
* @param context Callback context provided earlier
|
||||
*/
|
||||
typedef void (*FuriHalSerialDmaRxCallback)(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialRxEvent event,
|
||||
size_t data_len,
|
||||
void* context);
|
||||
|
||||
/** Start and sets Serial event callback receive DMA
|
||||
*
|
||||
* @param handle Serial handle
|
||||
* @param callback callback pointer
|
||||
* @param context callback context
|
||||
* @param[in] report_errors report RX error
|
||||
*/
|
||||
void furi_hal_serial_dma_rx_start(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialDmaRxCallback callback,
|
||||
void* context,
|
||||
bool report_errors);
|
||||
|
||||
/** Stop Serial receive DMA
|
||||
*
|
||||
* @param handle Serial handle
|
||||
*/
|
||||
void furi_hal_serial_dma_rx_stop(FuriHalSerialHandle* handle);
|
||||
|
||||
/** Get data Serial receive DMA
|
||||
*
|
||||
* @warning This function must be called only from the callback
|
||||
* FuriHalSerialDmaRxCallback
|
||||
*
|
||||
* @param handle Serial handle
|
||||
* @param data pointer to data buffer
|
||||
* @param len get data size (in bytes)
|
||||
*
|
||||
* @return size actual data receive (in bytes)
|
||||
*/
|
||||
size_t furi_hal_serial_dma_rx(FuriHalSerialHandle* handle, uint8_t* data, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
233
targets/f7/furi_hal/furi_hal_serial_control.c
Normal file
233
targets/f7/furi_hal/furi_hal_serial_control.c
Normal file
|
@ -0,0 +1,233 @@
|
|||
#include "furi_hal_serial_control.h"
|
||||
#include "furi_hal_serial_types_i.h"
|
||||
#include "furi_hal_serial.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <toolbox/api_lock.h>
|
||||
|
||||
#define TAG "FuriHalSerialControl"
|
||||
|
||||
typedef enum {
|
||||
FuriHalSerialControlMessageTypeStop,
|
||||
FuriHalSerialControlMessageTypeSuspend,
|
||||
FuriHalSerialControlMessageTypeResume,
|
||||
FuriHalSerialControlMessageTypeAcquire,
|
||||
FuriHalSerialControlMessageTypeRelease,
|
||||
FuriHalSerialControlMessageTypeLogging,
|
||||
} FuriHalSerialControlMessageType;
|
||||
|
||||
typedef struct {
|
||||
FuriHalSerialControlMessageType type;
|
||||
FuriApiLock api_lock;
|
||||
void* input;
|
||||
void* output;
|
||||
} FuriHalSerialControlMessage;
|
||||
|
||||
typedef struct {
|
||||
const FuriHalSerialId id;
|
||||
const uint32_t baud_rate;
|
||||
} FuriHalSerialControlMessageInputLogging;
|
||||
|
||||
typedef struct {
|
||||
FuriHalSerialHandle handles[FuriHalSerialIdMax];
|
||||
FuriMessageQueue* queue;
|
||||
FuriThread* thread;
|
||||
|
||||
// Logging
|
||||
FuriHalSerialId log_config_serial_id;
|
||||
uint32_t log_config_serial_baud_rate;
|
||||
FuriLogHandler log_handler;
|
||||
FuriHalSerialHandle* log_serial;
|
||||
} FuriHalSerialControl;
|
||||
|
||||
FuriHalSerialControl* furi_hal_serial_control = NULL;
|
||||
|
||||
static void furi_hal_serial_control_log_callback(const uint8_t* data, size_t size, void* context) {
|
||||
FuriHalSerialHandle* handle = context;
|
||||
furi_hal_serial_tx(handle, data, size);
|
||||
}
|
||||
|
||||
static void furi_hal_serial_control_log_set_handle(FuriHalSerialHandle* handle) {
|
||||
if(furi_hal_serial_control->log_serial) {
|
||||
furi_log_remove_handler(furi_hal_serial_control->log_handler);
|
||||
furi_hal_serial_deinit(furi_hal_serial_control->log_serial);
|
||||
furi_hal_serial_control->log_serial = NULL;
|
||||
}
|
||||
|
||||
if(handle) {
|
||||
furi_hal_serial_control->log_serial = handle;
|
||||
furi_hal_serial_init(
|
||||
furi_hal_serial_control->log_serial,
|
||||
furi_hal_serial_control->log_config_serial_baud_rate);
|
||||
furi_hal_serial_control->log_handler.callback = furi_hal_serial_control_log_callback;
|
||||
furi_hal_serial_control->log_handler.context = furi_hal_serial_control->log_serial;
|
||||
furi_log_add_handler(furi_hal_serial_control->log_handler);
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t furi_hal_serial_control_thread(void* args) {
|
||||
UNUSED(args);
|
||||
|
||||
bool should_continue = true;
|
||||
while(should_continue || furi_message_queue_get_count(furi_hal_serial_control->queue) > 0) {
|
||||
FuriHalSerialControlMessage message = {0};
|
||||
FuriStatus status =
|
||||
furi_message_queue_get(furi_hal_serial_control->queue, &message, FuriWaitForever);
|
||||
furi_check(status == FuriStatusOk);
|
||||
|
||||
if(message.type == FuriHalSerialControlMessageTypeStop) {
|
||||
should_continue = false;
|
||||
} else if(message.type == FuriHalSerialControlMessageTypeSuspend) {
|
||||
for(size_t i = 0; i < FuriHalSerialIdMax; i++) {
|
||||
furi_hal_serial_tx_wait_complete(&furi_hal_serial_control->handles[i]);
|
||||
furi_hal_serial_suspend(&furi_hal_serial_control->handles[i]);
|
||||
}
|
||||
api_lock_unlock(message.api_lock);
|
||||
} else if(message.type == FuriHalSerialControlMessageTypeResume) {
|
||||
for(size_t i = 0; i < FuriHalSerialIdMax; i++) {
|
||||
furi_hal_serial_resume(&furi_hal_serial_control->handles[i]);
|
||||
}
|
||||
api_lock_unlock(message.api_lock);
|
||||
} else if(message.type == FuriHalSerialControlMessageTypeAcquire) {
|
||||
FuriHalSerialId serial_id = *(FuriHalSerialId*)message.input;
|
||||
if(furi_hal_serial_control->handles[serial_id].in_use) {
|
||||
*(FuriHalSerialHandle**)message.output = NULL;
|
||||
} else {
|
||||
// Logging
|
||||
if(furi_hal_serial_control->log_config_serial_id == serial_id) {
|
||||
furi_hal_serial_control_log_set_handle(NULL);
|
||||
}
|
||||
// Return handle
|
||||
furi_hal_serial_control->handles[serial_id].in_use = true;
|
||||
*(FuriHalSerialHandle**)message.output =
|
||||
&furi_hal_serial_control->handles[serial_id];
|
||||
}
|
||||
api_lock_unlock(message.api_lock);
|
||||
} else if(message.type == FuriHalSerialControlMessageTypeRelease) {
|
||||
FuriHalSerialHandle* handle = *(FuriHalSerialHandle**)message.input;
|
||||
furi_assert(handle->in_use);
|
||||
furi_hal_serial_deinit(handle);
|
||||
handle->in_use = false;
|
||||
|
||||
// Return back logging
|
||||
if(furi_hal_serial_control->log_config_serial_id == handle->id) {
|
||||
furi_hal_serial_control_log_set_handle(handle);
|
||||
}
|
||||
api_lock_unlock(message.api_lock);
|
||||
} else if(message.type == FuriHalSerialControlMessageTypeLogging) {
|
||||
// Set new configuration
|
||||
FuriHalSerialControlMessageInputLogging* message_input = message.input;
|
||||
furi_hal_serial_control->log_config_serial_id = message_input->id;
|
||||
furi_hal_serial_control->log_config_serial_baud_rate = message_input->baud_rate;
|
||||
// Apply new configuration
|
||||
FuriHalSerialHandle* handle = NULL;
|
||||
if(furi_hal_serial_control->log_config_serial_id < FuriHalSerialIdMax) {
|
||||
handle = &furi_hal_serial_control
|
||||
->handles[furi_hal_serial_control->log_config_serial_id];
|
||||
}
|
||||
furi_hal_serial_control_log_set_handle(handle);
|
||||
api_lock_unlock(message.api_lock);
|
||||
} else {
|
||||
furi_crash("Invalid parameter");
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void furi_hal_serial_control_init(void) {
|
||||
furi_check(furi_hal_serial_control == NULL);
|
||||
// Allocate resources
|
||||
furi_hal_serial_control = malloc(sizeof(FuriHalSerialControl));
|
||||
furi_hal_serial_control->handles[FuriHalSerialIdUsart].id = FuriHalSerialIdUsart;
|
||||
furi_hal_serial_control->handles[FuriHalSerialIdLpuart].id = FuriHalSerialIdLpuart;
|
||||
furi_hal_serial_control->queue =
|
||||
furi_message_queue_alloc(8, sizeof(FuriHalSerialControlMessage));
|
||||
furi_hal_serial_control->thread =
|
||||
furi_thread_alloc_ex("SerialControlDriver", 512, furi_hal_serial_control_thread, NULL);
|
||||
furi_thread_mark_as_service(furi_hal_serial_control->thread);
|
||||
furi_thread_set_priority(furi_hal_serial_control->thread, FuriThreadPriorityHighest);
|
||||
furi_hal_serial_control->log_config_serial_id = FuriHalSerialIdMax;
|
||||
// Start control plane thread
|
||||
furi_thread_start(furi_hal_serial_control->thread);
|
||||
}
|
||||
|
||||
void furi_hal_serial_control_deinit(void) {
|
||||
furi_check(furi_hal_serial_control);
|
||||
// Stop control plane thread
|
||||
FuriHalSerialControlMessage message;
|
||||
message.type = FuriHalSerialControlMessageTypeStop;
|
||||
furi_message_queue_put(furi_hal_serial_control->queue, &message, FuriWaitForever);
|
||||
furi_thread_join(furi_hal_serial_control->thread);
|
||||
// Release resources
|
||||
furi_thread_free(furi_hal_serial_control->thread);
|
||||
furi_message_queue_free(furi_hal_serial_control->queue);
|
||||
free(furi_hal_serial_control);
|
||||
}
|
||||
|
||||
void furi_hal_serial_control_suspend(void) {
|
||||
furi_check(furi_hal_serial_control);
|
||||
|
||||
FuriHalSerialControlMessage message;
|
||||
message.type = FuriHalSerialControlMessageTypeSuspend;
|
||||
message.api_lock = api_lock_alloc_locked();
|
||||
furi_message_queue_put(furi_hal_serial_control->queue, &message, FuriWaitForever);
|
||||
api_lock_wait_unlock_and_free(message.api_lock);
|
||||
}
|
||||
|
||||
void furi_hal_serial_control_resume(void) {
|
||||
furi_check(furi_hal_serial_control);
|
||||
|
||||
FuriHalSerialControlMessage message;
|
||||
message.type = FuriHalSerialControlMessageTypeResume;
|
||||
message.api_lock = api_lock_alloc_locked();
|
||||
furi_message_queue_put(furi_hal_serial_control->queue, &message, FuriWaitForever);
|
||||
api_lock_wait_unlock_and_free(message.api_lock);
|
||||
}
|
||||
|
||||
FuriHalSerialHandle* furi_hal_serial_control_acquire(FuriHalSerialId serial_id) {
|
||||
furi_check(furi_hal_serial_control);
|
||||
|
||||
FuriHalSerialHandle* output = NULL;
|
||||
|
||||
FuriHalSerialControlMessage message;
|
||||
message.type = FuriHalSerialControlMessageTypeAcquire;
|
||||
message.api_lock = api_lock_alloc_locked();
|
||||
message.input = &serial_id;
|
||||
message.output = &output;
|
||||
furi_message_queue_put(furi_hal_serial_control->queue, &message, FuriWaitForever);
|
||||
api_lock_wait_unlock_and_free(message.api_lock);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void furi_hal_serial_control_release(FuriHalSerialHandle* handle) {
|
||||
furi_check(furi_hal_serial_control);
|
||||
furi_check(handle);
|
||||
|
||||
FuriHalSerialControlMessage message;
|
||||
message.type = FuriHalSerialControlMessageTypeRelease;
|
||||
message.api_lock = api_lock_alloc_locked();
|
||||
message.input = &handle;
|
||||
furi_message_queue_put(furi_hal_serial_control->queue, &message, FuriWaitForever);
|
||||
api_lock_wait_unlock_and_free(message.api_lock);
|
||||
}
|
||||
|
||||
void furi_hal_serial_control_set_logging_config(FuriHalSerialId serial_id, uint32_t baud_rate) {
|
||||
furi_check(serial_id <= FuriHalSerialIdMax);
|
||||
furi_check(baud_rate >= 9600 && baud_rate <= 4000000);
|
||||
|
||||
// Very special case of updater, where RTC initialized before kernel start
|
||||
if(!furi_hal_serial_control) return;
|
||||
|
||||
FuriHalSerialControlMessageInputLogging message_input = {
|
||||
.id = serial_id,
|
||||
.baud_rate = baud_rate,
|
||||
};
|
||||
FuriHalSerialControlMessage message;
|
||||
message.type = FuriHalSerialControlMessageTypeLogging;
|
||||
message.api_lock = api_lock_alloc_locked();
|
||||
message.input = &message_input;
|
||||
furi_message_queue_put(furi_hal_serial_control->queue, &message, FuriWaitForever);
|
||||
api_lock_wait_unlock_and_free(message.api_lock);
|
||||
}
|
46
targets/f7/furi_hal/furi_hal_serial_control.h
Normal file
46
targets/f7/furi_hal/furi_hal_serial_control.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
#pragma once
|
||||
|
||||
#include "furi_hal_serial_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Initialize Serial Control */
|
||||
void furi_hal_serial_control_init(void);
|
||||
|
||||
/** De-Initialize Serial Control */
|
||||
void furi_hal_serial_control_deinit(void);
|
||||
|
||||
/** Suspend All Serial Interfaces */
|
||||
void furi_hal_serial_control_suspend(void);
|
||||
|
||||
/** Resume All Serial Interfaces */
|
||||
void furi_hal_serial_control_resume(void);
|
||||
|
||||
/** Acquire Serial Interface Handler
|
||||
*
|
||||
* @param[in] serial_id The serial transceiver identifier
|
||||
*
|
||||
* @return The Serial Interface Handle or null if interfaces is in use
|
||||
*/
|
||||
FuriHalSerialHandle* furi_hal_serial_control_acquire(FuriHalSerialId serial_id);
|
||||
|
||||
/** Release Serial Interface Handler
|
||||
*
|
||||
* @param handle The handle
|
||||
*/
|
||||
void furi_hal_serial_control_release(FuriHalSerialHandle* handle);
|
||||
|
||||
/** Acquire Serial Interface Handler
|
||||
*
|
||||
* @param[in] serial_id The serial transceiver identifier. Use FuriHalSerialIdMax to disable logging.
|
||||
* @param[in] baud_rate The baud rate
|
||||
*
|
||||
* @return The Serial Interface Handle or null if interfaces is in use
|
||||
*/
|
||||
void furi_hal_serial_control_set_logging_config(FuriHalSerialId serial_id, uint32_t baud_rate);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
15
targets/f7/furi_hal/furi_hal_serial_types.h
Normal file
15
targets/f7/furi_hal/furi_hal_serial_types.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
/**
|
||||
* UART channels
|
||||
*/
|
||||
typedef enum {
|
||||
FuriHalSerialIdUsart,
|
||||
FuriHalSerialIdLpuart,
|
||||
|
||||
FuriHalSerialIdMax,
|
||||
} FuriHalSerialId;
|
||||
|
||||
typedef struct FuriHalSerialHandle FuriHalSerialHandle;
|
8
targets/f7/furi_hal/furi_hal_serial_types_i.h
Normal file
8
targets/f7/furi_hal/furi_hal_serial_types_i.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <furi_hal_serial_types.h>
|
||||
|
||||
struct FuriHalSerialHandle {
|
||||
FuriHalSerialId id;
|
||||
bool in_use;
|
||||
};
|
|
@ -1,244 +0,0 @@
|
|||
#include <furi_hal_uart.h>
|
||||
#include <stdbool.h>
|
||||
#include <stm32wbxx_ll_lpuart.h>
|
||||
#include <stm32wbxx_ll_usart.h>
|
||||
#include <stm32wbxx_ll_rcc.h>
|
||||
#include <furi_hal_resources.h>
|
||||
#include <furi_hal_bus.h>
|
||||
|
||||
#include <furi.h>
|
||||
|
||||
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];
|
||||
|
||||
static void furi_hal_usart_init(uint32_t baud) {
|
||||
furi_hal_bus_enable(FuriHalBusUSART1);
|
||||
LL_RCC_SetUSARTClockSource(LL_RCC_USART1_CLKSOURCE_PCLK2);
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_usart_tx,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn7USART1);
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_usart_rx,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn7USART1);
|
||||
|
||||
LL_USART_InitTypeDef USART_InitStruct;
|
||||
USART_InitStruct.PrescalerValue = LL_USART_PRESCALER_DIV1;
|
||||
USART_InitStruct.BaudRate = baud;
|
||||
USART_InitStruct.DataWidth = LL_USART_DATAWIDTH_8B;
|
||||
USART_InitStruct.StopBits = LL_USART_STOPBITS_1;
|
||||
USART_InitStruct.Parity = LL_USART_PARITY_NONE;
|
||||
USART_InitStruct.TransferDirection = LL_USART_DIRECTION_TX_RX;
|
||||
USART_InitStruct.HardwareFlowControl = LL_USART_HWCONTROL_NONE;
|
||||
USART_InitStruct.OverSampling = LL_USART_OVERSAMPLING_16;
|
||||
LL_USART_Init(USART1, &USART_InitStruct);
|
||||
LL_USART_EnableFIFO(USART1);
|
||||
LL_USART_ConfigAsyncMode(USART1);
|
||||
|
||||
LL_USART_Enable(USART1);
|
||||
|
||||
while(!LL_USART_IsActiveFlag_TEACK(USART1) || !LL_USART_IsActiveFlag_REACK(USART1))
|
||||
;
|
||||
|
||||
LL_USART_DisableIT_ERROR(USART1);
|
||||
|
||||
NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
}
|
||||
|
||||
static void furi_hal_lpuart_init(uint32_t baud) {
|
||||
furi_hal_bus_enable(FuriHalBusLPUART1);
|
||||
LL_RCC_SetLPUARTClockSource(LL_RCC_LPUART1_CLKSOURCE_PCLK1);
|
||||
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_ext_pc0,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn8LPUART1);
|
||||
furi_hal_gpio_init_ex(
|
||||
&gpio_ext_pc1,
|
||||
GpioModeAltFunctionPushPull,
|
||||
GpioPullUp,
|
||||
GpioSpeedVeryHigh,
|
||||
GpioAltFn8LPUART1);
|
||||
|
||||
LL_LPUART_InitTypeDef LPUART_InitStruct;
|
||||
LPUART_InitStruct.PrescalerValue = LL_LPUART_PRESCALER_DIV1;
|
||||
LPUART_InitStruct.BaudRate = 115200;
|
||||
LPUART_InitStruct.DataWidth = LL_LPUART_DATAWIDTH_8B;
|
||||
LPUART_InitStruct.StopBits = LL_LPUART_STOPBITS_1;
|
||||
LPUART_InitStruct.Parity = LL_LPUART_PARITY_NONE;
|
||||
LPUART_InitStruct.TransferDirection = LL_LPUART_DIRECTION_TX_RX;
|
||||
LPUART_InitStruct.HardwareFlowControl = LL_LPUART_HWCONTROL_NONE;
|
||||
LL_LPUART_Init(LPUART1, &LPUART_InitStruct);
|
||||
LL_LPUART_EnableFIFO(LPUART1);
|
||||
|
||||
LL_LPUART_Enable(LPUART1);
|
||||
|
||||
while(!LL_LPUART_IsActiveFlag_TEACK(LPUART1) || !LL_LPUART_IsActiveFlag_REACK(LPUART1))
|
||||
;
|
||||
|
||||
furi_hal_uart_set_br(FuriHalUartIdLPUART1, baud);
|
||||
LL_LPUART_DisableIT_ERROR(LPUART1);
|
||||
|
||||
NVIC_SetPriority(LPUART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0));
|
||||
}
|
||||
|
||||
void furi_hal_uart_init(FuriHalUartId ch, uint32_t baud) {
|
||||
if(ch == FuriHalUartIdLPUART1) {
|
||||
furi_hal_lpuart_init(baud);
|
||||
} else if(ch == FuriHalUartIdUSART1) {
|
||||
furi_hal_usart_init(baud);
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_uart_set_br(FuriHalUartId ch, uint32_t baud) {
|
||||
if(ch == FuriHalUartIdUSART1) {
|
||||
if(LL_USART_IsEnabled(USART1)) {
|
||||
// Wait for transfer complete flag
|
||||
while(!LL_USART_IsActiveFlag_TC(USART1))
|
||||
;
|
||||
LL_USART_Disable(USART1);
|
||||
uint32_t uartclk = LL_RCC_GetUSARTClockFreq(LL_RCC_USART1_CLKSOURCE);
|
||||
LL_USART_SetBaudRate(
|
||||
USART1, uartclk, LL_USART_PRESCALER_DIV1, LL_USART_OVERSAMPLING_16, baud);
|
||||
LL_USART_Enable(USART1);
|
||||
}
|
||||
} else if(ch == FuriHalUartIdLPUART1) {
|
||||
if(LL_LPUART_IsEnabled(LPUART1)) {
|
||||
// Wait for transfer complete flag
|
||||
while(!LL_LPUART_IsActiveFlag_TC(LPUART1))
|
||||
;
|
||||
LL_LPUART_Disable(LPUART1);
|
||||
uint32_t uartclk = LL_RCC_GetLPUARTClockFreq(LL_RCC_LPUART1_CLKSOURCE);
|
||||
if(uartclk / baud > 4095) {
|
||||
LL_LPUART_SetPrescaler(LPUART1, LL_LPUART_PRESCALER_DIV32);
|
||||
LL_LPUART_SetBaudRate(LPUART1, uartclk, LL_LPUART_PRESCALER_DIV32, baud);
|
||||
} else {
|
||||
LL_LPUART_SetPrescaler(LPUART1, LL_LPUART_PRESCALER_DIV1);
|
||||
LL_LPUART_SetBaudRate(LPUART1, uartclk, LL_LPUART_PRESCALER_DIV1, baud);
|
||||
}
|
||||
LL_LPUART_Enable(LPUART1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_uart_deinit(FuriHalUartId ch) {
|
||||
furi_hal_uart_set_irq_cb(ch, NULL, NULL);
|
||||
if(ch == FuriHalUartIdUSART1) {
|
||||
if(furi_hal_bus_is_enabled(FuriHalBusUSART1)) {
|
||||
furi_hal_bus_disable(FuriHalBusUSART1);
|
||||
}
|
||||
furi_hal_gpio_init(&gpio_usart_tx, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_usart_rx, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
} else if(ch == FuriHalUartIdLPUART1) {
|
||||
if(furi_hal_bus_is_enabled(FuriHalBusLPUART1)) {
|
||||
furi_hal_bus_disable(FuriHalBusLPUART1);
|
||||
}
|
||||
furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_hal_gpio_init(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
while(buffer_size > 0) {
|
||||
while(!LL_USART_IsActiveFlag_TXE(USART1))
|
||||
;
|
||||
|
||||
LL_USART_TransmitData8(USART1, *buffer);
|
||||
buffer++;
|
||||
buffer_size--;
|
||||
}
|
||||
|
||||
} else if(ch == FuriHalUartIdLPUART1) {
|
||||
if(LL_LPUART_IsEnabled(LPUART1) == 0) return;
|
||||
|
||||
while(buffer_size > 0) {
|
||||
while(!LL_LPUART_IsActiveFlag_TXE(LPUART1))
|
||||
;
|
||||
|
||||
LL_LPUART_TransmitData8(LPUART1, *buffer);
|
||||
|
||||
buffer++;
|
||||
buffer_size--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void furi_hal_uart_set_irq_cb(
|
||||
FuriHalUartId ch,
|
||||
void (*cb)(UartIrqEvent ev, uint8_t data, void* ctx),
|
||||
void* ctx) {
|
||||
if(cb == NULL) {
|
||||
if(ch == FuriHalUartIdUSART1) {
|
||||
NVIC_DisableIRQ(USART1_IRQn);
|
||||
LL_USART_DisableIT_RXNE_RXFNE(USART1);
|
||||
} else if(ch == FuriHalUartIdLPUART1) {
|
||||
NVIC_DisableIRQ(LPUART1_IRQn);
|
||||
LL_LPUART_DisableIT_RXNE_RXFNE(LPUART1);
|
||||
}
|
||||
irq_cb[ch] = cb;
|
||||
irq_ctx[ch] = ctx;
|
||||
} else {
|
||||
irq_ctx[ch] = ctx;
|
||||
irq_cb[ch] = cb;
|
||||
if(ch == FuriHalUartIdUSART1) {
|
||||
NVIC_EnableIRQ(USART1_IRQn);
|
||||
LL_USART_EnableIT_RXNE_RXFNE(USART1);
|
||||
} else if(ch == FuriHalUartIdLPUART1) {
|
||||
NVIC_EnableIRQ(LPUART1_IRQn);
|
||||
LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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_ORE(LPUART1)) {
|
||||
LL_LPUART_ClearFlag_ORE(LPUART1);
|
||||
}
|
||||
}
|
||||
|
||||
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_ORE(USART1)) {
|
||||
LL_USART_ClearFlag_ORE(USART1);
|
||||
}
|
||||
}
|
|
@ -1,89 +0,0 @@
|
|||
/**
|
||||
* @file furi_hal_uart.h
|
||||
* @version 1.0
|
||||
* @date 2021-11-19
|
||||
*
|
||||
* UART HAL api interface
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* UART channels
|
||||
*/
|
||||
typedef enum {
|
||||
FuriHalUartIdUSART1,
|
||||
FuriHalUartIdLPUART1,
|
||||
} FuriHalUartId;
|
||||
|
||||
/**
|
||||
* UART events
|
||||
*/
|
||||
typedef enum {
|
||||
UartIrqEventRXNE,
|
||||
} UartIrqEvent;
|
||||
|
||||
/**
|
||||
* Init UART
|
||||
* Configures GPIO to UART function, сonfigures UART hardware, enables UART hardware
|
||||
* @param channel UART channel
|
||||
* @param baud baudrate
|
||||
*/
|
||||
void furi_hal_uart_init(FuriHalUartId channel, uint32_t baud);
|
||||
|
||||
/**
|
||||
* Deinit UART
|
||||
* Configures GPIO to analog, clears callback and callback context, disables UART hardware
|
||||
* @param channel UART channel
|
||||
*/
|
||||
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
|
||||
* @param baud baudrate
|
||||
*/
|
||||
void furi_hal_uart_set_br(FuriHalUartId channel, uint32_t baud);
|
||||
|
||||
/**
|
||||
* Transmits data
|
||||
* @param channel UART channel
|
||||
* @param buffer data
|
||||
* @param buffer_size data size (in bytes)
|
||||
*/
|
||||
void furi_hal_uart_tx(FuriHalUartId channel, uint8_t* buffer, size_t buffer_size);
|
||||
|
||||
/**
|
||||
* Sets UART event callback
|
||||
* @param channel UART channel
|
||||
* @param callback callback pointer
|
||||
* @param context callback context
|
||||
*/
|
||||
void furi_hal_uart_set_irq_cb(
|
||||
FuriHalUartId channel,
|
||||
void (*callback)(UartIrqEvent event, uint8_t data, void* context),
|
||||
void* context);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -14,7 +14,6 @@ struct STOP_EXTERNING_ME {};
|
|||
#include <furi_hal_clock.h>
|
||||
#include <furi_hal_bus.h>
|
||||
#include <furi_hal_crypto.h>
|
||||
#include <furi_hal_console.h>
|
||||
#include <furi_hal_debug.h>
|
||||
#include <furi_hal_dma.h>
|
||||
#include <furi_hal_os.h>
|
||||
|
@ -36,7 +35,8 @@ struct STOP_EXTERNING_ME {};
|
|||
#include <furi_hal_usb.h>
|
||||
#include <furi_hal_usb_hid.h>
|
||||
#include <furi_hal_usb_ccid.h>
|
||||
#include <furi_hal_uart.h>
|
||||
#include <furi_hal_serial_control.h>
|
||||
#include <furi_hal_serial.h>
|
||||
#include <furi_hal_info.h>
|
||||
#include <furi_hal_random.h>
|
||||
#include <furi_hal_target_hw.h>
|
||||
|
|
Loading…
Reference in a new issue