mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-13 01:38:35 -07: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:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user