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:
MX
2024-01-19 23:20:37 +03:00
parent 16a3f4c06a
commit a1e62c3e76
37 changed files with 1967 additions and 760 deletions

View File

@@ -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) {