uart.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. #include "seader_i.h"
  2. #define TAG "SeaderUART"
  3. static void seader_uart_on_irq_rx_dma_cb(
  4. FuriHalSerialHandle* handle,
  5. FuriHalSerialRxEvent ev,
  6. size_t size,
  7. void* context) {
  8. SeaderUartBridge* seader_uart = (SeaderUartBridge*)context;
  9. if(ev & (FuriHalSerialRxEventData | FuriHalSerialRxEventIdle)) {
  10. uint8_t data[FURI_HAL_SERIAL_DMA_BUFFER_SIZE] = {0};
  11. while(size) {
  12. size_t ret = furi_hal_serial_dma_rx(
  13. handle,
  14. data,
  15. (size > FURI_HAL_SERIAL_DMA_BUFFER_SIZE) ? FURI_HAL_SERIAL_DMA_BUFFER_SIZE : size);
  16. furi_stream_buffer_send(seader_uart->rx_stream, data, ret, 0);
  17. size -= ret;
  18. };
  19. furi_thread_flags_set(furi_thread_get_id(seader_uart->thread), WorkerEvtRxDone);
  20. }
  21. }
  22. void seader_uart_disable(SeaderUartBridge* seader_uart) {
  23. furi_assert(seader_uart);
  24. furi_thread_flags_set(furi_thread_get_id(seader_uart->thread), WorkerEvtStop);
  25. furi_thread_join(seader_uart->thread);
  26. furi_thread_free(seader_uart->thread);
  27. free(seader_uart);
  28. }
  29. void seader_uart_serial_init(SeaderUartBridge* seader_uart, uint8_t uart_ch) {
  30. furi_assert(!seader_uart->serial_handle);
  31. seader_uart->serial_handle = furi_hal_serial_control_acquire(uart_ch);
  32. furi_assert(seader_uart->serial_handle);
  33. furi_hal_serial_init(seader_uart->serial_handle, 115200);
  34. furi_hal_serial_dma_rx_start(
  35. seader_uart->serial_handle, seader_uart_on_irq_rx_dma_cb, seader_uart, false);
  36. }
  37. void seader_uart_serial_deinit(SeaderUartBridge* seader_uart) {
  38. furi_assert(seader_uart->serial_handle);
  39. furi_hal_serial_deinit(seader_uart->serial_handle);
  40. furi_hal_serial_control_release(seader_uart->serial_handle);
  41. seader_uart->serial_handle = NULL;
  42. }
  43. void seader_uart_set_baudrate(SeaderUartBridge* seader_uart, uint32_t baudrate) {
  44. if(baudrate != 0) {
  45. furi_hal_serial_set_br(seader_uart->serial_handle, baudrate);
  46. } else {
  47. FURI_LOG_I(TAG, "No baudrate specified");
  48. }
  49. }
  50. size_t seader_uart_process_buffer(Seader* seader, uint8_t* cmd, size_t cmd_len) {
  51. SeaderUartBridge* seader_uart = seader->uart;
  52. if(cmd_len < 2) {
  53. return cmd_len;
  54. }
  55. size_t consumed = 0;
  56. do {
  57. consumed = seader_ccid_process(seader, cmd, cmd_len);
  58. if(consumed > 0) {
  59. memset(cmd, 0, consumed);
  60. cmd_len -= consumed;
  61. if(cmd_len > 0) {
  62. memmove(cmd, cmd + consumed, cmd_len);
  63. }
  64. seader_uart->st.rx_cnt += consumed;
  65. /*
  66. memset(display, 0, SEADER_UART_RX_BUF_SIZE);
  67. for (uint8_t i = 0; i < cmd_len; i++) {
  68. snprintf(display+(i*2), sizeof(display), "%02x", cmd[i]);
  69. }
  70. FURI_LOG_I(TAG, "cmd is now %d bytes: %s", cmd_len, display);
  71. */
  72. }
  73. } while(consumed > 0 && cmd_len > 0);
  74. return cmd_len;
  75. }
  76. int32_t seader_uart_worker(void* context) {
  77. Seader* seader = (Seader*)context;
  78. SeaderUartBridge* seader_uart = seader->uart;
  79. furi_thread_set_current_priority(FuriThreadPriorityHighest);
  80. memcpy(&seader_uart->cfg, &seader_uart->cfg_new, sizeof(SeaderUartConfig));
  81. seader_uart->rx_stream = furi_stream_buffer_alloc(SEADER_UART_RX_BUF_SIZE, 1);
  82. seader_uart->tx_sem = furi_semaphore_alloc(1, 1);
  83. seader_uart->tx_thread =
  84. furi_thread_alloc_ex("SeaderUartTxWorker", 2 * 1024, seader_uart_tx_thread, seader);
  85. seader_uart_serial_init(seader_uart, seader_uart->cfg.uart_ch);
  86. seader_uart_set_baudrate(seader_uart, seader_uart->cfg.baudrate);
  87. furi_thread_flags_set(furi_thread_get_id(seader_uart->tx_thread), WorkerEvtSamRx);
  88. furi_thread_start(seader_uart->tx_thread);
  89. uint8_t cmd[SEADER_UART_RX_BUF_SIZE];
  90. size_t cmd_len = 0;
  91. while(1) {
  92. uint32_t events =
  93. furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
  94. furi_check(!(events & FuriFlagError));
  95. if(events & WorkerEvtStop) {
  96. memset(cmd, 0, cmd_len);
  97. cmd_len = 0;
  98. break;
  99. }
  100. if(events & (WorkerEvtRxDone | WorkerEvtSamTxComplete)) {
  101. size_t len = furi_stream_buffer_receive(
  102. seader_uart->rx_stream, seader_uart->rx_buf, SEADER_UART_RX_BUF_SIZE, 0);
  103. if(len > 0) {
  104. furi_delay_ms(5); //WTF
  105. /*
  106. char display[SEADER_UART_RX_BUF_SIZE * 2 + 1] = {0};
  107. for (uint8_t i = 0; i < len; i++) {
  108. snprintf(display+(i*2), sizeof(display), "%02x", seader_uart->rx_buf[i]);
  109. }
  110. FURI_LOG_I(TAG, "RECV %d bytes: %s", len, display);
  111. */
  112. if(cmd_len + len > SEADER_UART_RX_BUF_SIZE) {
  113. FURI_LOG_I(TAG, "OVERFLOW: %d + %d", cmd_len, len);
  114. memset(cmd, 0, cmd_len);
  115. cmd_len = 0;
  116. }
  117. memcpy(cmd + cmd_len, seader_uart->rx_buf, len);
  118. cmd_len += len;
  119. cmd_len = seader_uart_process_buffer(seader, cmd, cmd_len);
  120. }
  121. }
  122. }
  123. seader_uart_serial_deinit(seader_uart);
  124. furi_thread_flags_set(furi_thread_get_id(seader_uart->tx_thread), WorkerEvtTxStop);
  125. furi_thread_join(seader_uart->tx_thread);
  126. furi_thread_free(seader_uart->tx_thread);
  127. furi_stream_buffer_free(seader_uart->rx_stream);
  128. furi_semaphore_free(seader_uart->tx_sem);
  129. return 0;
  130. }
  131. SeaderUartBridge* seader_uart_enable(SeaderUartConfig* cfg, Seader* seader) {
  132. SeaderUartBridge* seader_uart = malloc(sizeof(SeaderUartBridge));
  133. seader_uart->T = 0;
  134. seader_uart->T = (seader->is_debug_enabled ? 1 : 0);
  135. memcpy(&(seader_uart->cfg_new), cfg, sizeof(SeaderUartConfig));
  136. seader_uart->thread =
  137. furi_thread_alloc_ex("SeaderUartWorker", 5 * 1024, seader_uart_worker, seader);
  138. furi_thread_start(seader_uart->thread);
  139. return seader_uart;
  140. }
  141. int32_t seader_uart_tx_thread(void* context) {
  142. Seader* seader = (Seader*)context;
  143. SeaderUartBridge* seader_uart = seader->uart;
  144. furi_thread_set_current_priority(FuriThreadPriorityHighest);
  145. while(1) {
  146. uint32_t events =
  147. furi_thread_flags_wait(WORKER_ALL_TX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
  148. furi_check(!(events & FuriFlagError));
  149. if(events & WorkerEvtTxStop) break;
  150. if(events & WorkerEvtSamRx) {
  151. if(seader_uart->tx_len > 0) {
  152. char display[SEADER_UART_RX_BUF_SIZE * 2 + 1] = {0};
  153. for(uint8_t i = 0; i < seader_uart->tx_len; i++) {
  154. snprintf(display + (i * 2), sizeof(display), "%02x", seader_uart->tx_buf[i]);
  155. }
  156. // FURI_LOG_I(TAG, "SEND %d bytes: %s", seader_uart->tx_len, display);
  157. seader_uart->st.tx_cnt += seader_uart->tx_len;
  158. furi_hal_serial_tx(
  159. seader_uart->serial_handle, seader_uart->tx_buf, seader_uart->tx_len);
  160. }
  161. }
  162. }
  163. return 0;
  164. }
  165. void seader_uart_get_config(SeaderUartBridge* seader_uart, SeaderUartConfig* cfg) {
  166. furi_assert(seader_uart);
  167. furi_assert(cfg);
  168. memcpy(cfg, &(seader_uart->cfg_new), sizeof(SeaderUartConfig));
  169. }
  170. void seader_uart_get_state(SeaderUartBridge* seader_uart, SeaderUartState* st) {
  171. furi_assert(seader_uart);
  172. furi_assert(st);
  173. memcpy(st, &(seader_uart->st), sizeof(SeaderUartState));
  174. }
  175. SeaderUartBridge* seader_uart_alloc(Seader* seader) {
  176. SeaderUartConfig cfg = {.uart_ch = FuriHalSerialIdLpuart, .baudrate = 115200};
  177. SeaderUartState uart_state;
  178. SeaderUartBridge* seader_uart;
  179. FURI_LOG_I(TAG, "Enable UART");
  180. seader_uart = seader_uart_enable(&cfg, seader);
  181. seader_uart_get_config(seader_uart, &cfg);
  182. seader_uart_get_state(seader_uart, &uart_state);
  183. return seader_uart;
  184. }
  185. void seader_uart_free(SeaderUartBridge* seader_uart) {
  186. seader_uart_disable(seader_uart);
  187. }