| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- #include "seos_i.h"
- #include "uart.h"
- #define TAG "SeosUART"
- #define SEOS_UART_BAUD 460800
- static void seos_uart_on_irq_rx_dma_cb(
- FuriHalSerialHandle* handle,
- FuriHalSerialRxEvent ev,
- size_t size,
- void* context) {
- SeosUart* seos_uart = (SeosUart*)context;
- 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(seos_uart->rx_stream, data, ret, 0);
- size -= ret;
- };
- furi_thread_flags_set(furi_thread_get_id(seos_uart->thread), WorkerEvtRxDone);
- }
- }
- void seos_uart_disable(SeosUart* seos_uart) {
- furi_assert(seos_uart);
- furi_thread_flags_set(furi_thread_get_id(seos_uart->thread), WorkerEvtStop);
- furi_thread_join(seos_uart->thread);
- furi_thread_free(seos_uart->thread);
- free(seos_uart);
- }
- void seos_uart_serial_init(SeosUart* seos_uart, uint8_t uart_ch) {
- furi_assert(!seos_uart->serial_handle);
- SeosUartConfig cfg = seos_uart->cfg;
- seos_uart->serial_handle = furi_hal_serial_control_acquire(uart_ch);
- furi_assert(seos_uart->serial_handle);
- furi_hal_serial_init(seos_uart->serial_handle, cfg.baudrate);
- furi_hal_serial_dma_rx_start(
- seos_uart->serial_handle, seos_uart_on_irq_rx_dma_cb, seos_uart, false);
- }
- void seos_uart_serial_deinit(SeosUart* seos_uart) {
- furi_assert(seos_uart->serial_handle);
- furi_hal_serial_deinit(seos_uart->serial_handle);
- furi_hal_serial_control_release(seos_uart->serial_handle);
- seos_uart->serial_handle = NULL;
- }
- void seos_uart_set_baudrate(SeosUart* seos_uart, uint32_t baudrate) {
- if(baudrate != 0) {
- furi_hal_serial_set_br(seos_uart->serial_handle, baudrate);
- } else {
- FURI_LOG_I(TAG, "No baudrate specified");
- }
- }
- size_t seos_uart_process_buffer(SeosUart* seos_uart, uint8_t* cmd, size_t cmd_len) {
- if(cmd_len < 2) {
- return cmd_len;
- }
- size_t consumed = 0;
- do {
- if(seos_uart->receive_callback) {
- consumed =
- seos_uart->receive_callback(seos_uart->receive_callback_context, cmd, cmd_len);
- }
- if(consumed > 0) {
- memset(cmd, 0, consumed);
- cmd_len -= consumed;
- if(cmd_len > 0) {
- memmove(cmd, cmd + consumed, cmd_len);
- }
- /*
- memset(display, 0, SEOS_UART_RX_BUF_SIZE);
- for(uint8_t i = 0; i < cmd_len; i++) {
- snprintf(display + (i * 2), sizeof(display), "%02x", cmd[i]);
- }
- FURI_LOG_I(TAG, "cmd is now %d bytes: %s", cmd_len, display);
- */
- }
- } while(consumed > 0 && cmd_len > 0);
- return cmd_len;
- }
- int32_t seos_uart_worker(void* context) {
- SeosUart* seos_uart = (SeosUart*)context;
- furi_thread_set_current_priority(FuriThreadPriorityHighest);
- memcpy(&seos_uart->cfg, &seos_uart->cfg_new, sizeof(SeosUartConfig));
- seos_uart->rx_stream = furi_stream_buffer_alloc(SEOS_UART_RX_BUF_SIZE, 1);
- seos_uart->tx_sem = furi_semaphore_alloc(1, 1);
- seos_uart->tx_thread =
- furi_thread_alloc_ex("SeosUartTxWorker", 1.5 * 1024, seos_uart_tx_thread, seos_uart);
- seos_uart_serial_init(seos_uart, seos_uart->cfg.uart_ch);
- seos_uart_set_baudrate(seos_uart, seos_uart->cfg.baudrate);
- furi_thread_flags_set(furi_thread_get_id(seos_uart->tx_thread), WorkerEvtDevRx);
- furi_thread_start(seos_uart->tx_thread);
- uint8_t cmd[SEOS_UART_RX_BUF_SIZE];
- size_t cmd_len = 0;
- while(1) {
- uint32_t events =
- furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
- furi_check(!(events & FuriFlagError));
- if(events & WorkerEvtStop) {
- memset(cmd, 0, cmd_len);
- cmd_len = 0;
- break;
- }
- if(events & (WorkerEvtRxDone | WorkerEvtDevTxComplete)) {
- size_t len = furi_stream_buffer_receive(
- seos_uart->rx_stream, seos_uart->rx_buf, SEOS_UART_RX_BUF_SIZE, 0);
- if(len > 0) {
- furi_delay_ms(5); //WTF
- /*
- char display[SEOS_UART_RX_BUF_SIZE * 2 + 1] = {0};
- for(uint8_t i = 0; i < len; i++) {
- snprintf(display + (i * 2), sizeof(display), "%02x", seos_uart->rx_buf[i]);
- }
- FURI_LOG_D(TAG, "RECV %d bytes: %s", len, display);
- */
- if(cmd_len + len > SEOS_UART_RX_BUF_SIZE) {
- FURI_LOG_I(TAG, "OVERFLOW: %d + %d", cmd_len, len);
- memset(cmd, 0, cmd_len);
- cmd_len = 0;
- }
- memcpy(cmd + cmd_len, seos_uart->rx_buf, len);
- cmd_len += len;
- cmd_len = seos_uart_process_buffer(seos_uart, cmd, cmd_len);
- }
- }
- }
- seos_uart_serial_deinit(seos_uart);
- furi_thread_flags_set(furi_thread_get_id(seos_uart->tx_thread), WorkerEvtTxStop);
- furi_thread_join(seos_uart->tx_thread);
- furi_thread_free(seos_uart->tx_thread);
- furi_stream_buffer_free(seos_uart->rx_stream);
- furi_semaphore_free(seos_uart->tx_sem);
- return 0;
- }
- SeosUart* seos_uart_enable(SeosUartConfig* cfg) {
- SeosUart* seos_uart = malloc(sizeof(SeosUart));
- memcpy(&(seos_uart->cfg_new), cfg, sizeof(SeosUartConfig));
- seos_uart->thread =
- furi_thread_alloc_ex("SeosUartWorker", 5 * 1024, seos_uart_worker, seos_uart);
- furi_thread_start(seos_uart->thread);
- return seos_uart;
- }
- int32_t seos_uart_tx_thread(void* context) {
- SeosUart* seos_uart = (SeosUart*)context;
- furi_thread_set_current_priority(FuriThreadPriorityHighest);
- while(1) {
- uint32_t events =
- furi_thread_flags_wait(WORKER_ALL_TX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
- furi_check(!(events & FuriFlagError));
- if(events & WorkerEvtTxStop) break;
- if(events & WorkerEvtDevRx) {
- if(seos_uart->tx_len > 0) {
- /*
- char display[SEOS_UART_RX_BUF_SIZE * 2 + 1] = {0};
- for(uint8_t i = 0; i < seos_uart->tx_len; i++) {
- snprintf(display + (i * 2), sizeof(display), "%02x", seos_uart->tx_buf[i]);
- }
- FURI_LOG_D(TAG, "SEND %d bytes: %s", seos_uart->tx_len, display);
- */
- furi_hal_serial_tx(seos_uart->serial_handle, seos_uart->tx_buf, seos_uart->tx_len);
- }
- }
- }
- return 0;
- }
- void seos_uart_get_config(SeosUart* seos_uart, SeosUartConfig* cfg) {
- furi_assert(seos_uart);
- furi_assert(cfg);
- memcpy(cfg, &(seos_uart->cfg_new), sizeof(SeosUartConfig));
- }
- SeosUart* seos_uart_alloc() {
- SeosUartConfig cfg = {.uart_ch = FuriHalSerialIdLpuart, .baudrate = SEOS_UART_BAUD};
- SeosUart* seos_uart;
- FURI_LOG_I(TAG, "Enable UART");
- seos_uart = seos_uart_enable(&cfg);
- seos_uart_get_config(seos_uart, &cfg);
- return seos_uart;
- }
- void seos_uart_free(SeosUart* seos_uart) {
- seos_uart_disable(seos_uart);
- }
- void seos_uart_send(SeosUart* seos_uart, uint8_t* buffer, size_t len) {
- memset(seos_uart->tx_buf, 0, sizeof(seos_uart->tx_buf));
- memcpy(seos_uart->tx_buf, buffer, len);
- seos_uart->tx_len = len;
- furi_thread_flags_set(furi_thread_get_id(seos_uart->tx_thread), WorkerEvtDevRx);
- }
- void seos_uart_set_receive_callback(
- SeosUart* seos_uart,
- SeosUartReceiveCallback callback,
- void* context) {
- seos_uart->receive_callback = callback;
- seos_uart->receive_callback_context = context;
- }
|