uart.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. #include "uart.h"
  2. #include "bsp/shark_bsp.h"
  3. #include "bsp/gpio.h"
  4. #include "libs/shark_libs.h"
  5. #include "libs/shark_task.h"
  6. #define SHARK_UART_BAUDRATE 38400
  7. #define SHARK_UART0_com USART0
  8. #define SHARK_UART0_tx_port GPIOB
  9. #define SHARK_UART0_tx_pin GPIO_PIN_6
  10. #define SHARK_UART0_rx_port GPIOB
  11. #define SHARK_UART0_rx_pin GPIO_PIN_7
  12. #define SHARK_UART0_irq USART0_IRQn
  13. #define SHARK_UART0_clk RCU_USART0
  14. #define SHARK_UART0_tx_gpio_clk RCU_GPIOB
  15. #define SHARK_UART0_rx_gpio_clk RCU_GPIOB
  16. #define SHARK_UART0_tx_dma DMA
  17. #define SHARK_UART0_tx_dma_ch DMA_CH1
  18. #define SHARK_UART0_tx_dma_clk RCU_DMA
  19. #define SHARK_UART0_rx_dma DMA
  20. #define SHARK_UART0_rx_dma_ch DMA_CH2
  21. #define SHARK_UART0_rx_dma_clk RCU_DMA
  22. #define SHARK_UART1_com USART1
  23. #define SHARK_UART1_tx_port GPIOA
  24. #define SHARK_UART1_tx_pin GPIO_PIN_2
  25. #define SHARK_UART1_rx_port GPIOA
  26. #define SHARK_UART1_rx_pin GPIO_PIN_3
  27. #define SHARK_UART1_irq USART1_IRQn
  28. #define SHARK_UART1_clk RCU_USART1
  29. #define SHARK_UART1_tx_gpio_clk RCU_GPIOA
  30. #define SHARK_UART1_rx_gpio_clk RCU_GPIOA
  31. #define SHARK_UART1_tx_dma DMA
  32. #define SHARK_UART1_tx_dma_ch DMA_CH3
  33. #define SHARK_UART1_tx_dma_clk RCU_DMA
  34. #define SHARK_UART1_rx_dma DMA
  35. #define SHARK_UART1_rx_dma_ch DMA_CH4
  36. #define SHARK_UART1_rx_dma_clk RCU_DMA
  37. // ================================================================================
  38. static u8 shark_uart0_tx_cache[SHARK_UART_TX_MEM_SIZE];
  39. #if UART_NUM==2
  40. static u8 shark_uart1_tx_cache[SHARK_UART_TX_MEM_SIZE];
  41. #endif
  42. static u8 shark_uart_rx_cache[SHARK_UART_RX_MEM_SIZE];
  43. static shark_uart_t _shark_uart[UART_NUM];
  44. static shark_task_t _uart_task;
  45. static u64 _rx_time;
  46. ///static bool uart_no_data = false;
  47. #define update_dma_w_pos(uart) circle_update_write_position(&uart->rx_queue, SHARK_UART_RX_MEM_SIZE - DMA_CHCNT(uart->rx_dma_ch))
  48. extern void protocol_recv_frame(uart_enum_t uart_no, char *data, int len);
  49. extern void protocol_old_recv_frame(uart_enum_t uart_no, uint8_t *data, int len);
  50. extern void health_add_uart_error(uint32_t c, uint32_t l, uint32_t d);
  51. // ================================================================================
  52. static uart_enum_t _uart_index(uint32_t com){
  53. return com == SHARK_UART0_com?SHARK_UART0:SHARK_UART1;
  54. }
  55. static bool shark_uart_on_rx_frame(shark_uart_t *uart)
  56. {
  57. u16 crc0 = shark_decode_u16(uart->rx_frame + uart->rx_length);
  58. u16 crc1 = shark_crc16_check(uart->rx_frame, uart->rx_length);
  59. if (crc0 != crc1) {
  60. health_add_uart_error(1, 0, 0);
  61. return false;
  62. }
  63. #if (CONFIG_BOARD_TYPE==SHARK_BOARD_SP600)
  64. //wait 250us to give the time for PS200 485 switch to rx mode
  65. task_udelay(250);
  66. #endif
  67. protocol_recv_frame(_uart_index(uart->uart_com), (char *)uart->rx_frame, uart->rx_length);
  68. return true;
  69. }
  70. static void shark_uart_rx(shark_uart_t *uart){
  71. while(1) {
  72. u8 data;
  73. update_dma_w_pos(uart);
  74. if (circle_get_one_data(&uart->rx_queue, &data) != 1) {
  75. if (shark_get_mseconds() >= (5 + _rx_time)) {
  76. //_rx_time = 0xFFFFFFFFFFFFL;
  77. if (uart->rx_length_old_prot > 0){
  78. protocol_old_recv_frame(_uart_index(uart->uart_com), uart->rx_frame_old_prot, uart->rx_length_old_prot);
  79. uart->rx_length_old_prot = 0;
  80. }
  81. }
  82. if (shark_get_mseconds() >= (UART_TIMEOUT + _rx_time)){
  83. uart->uart_no_data = true;
  84. }else {
  85. uart->uart_no_data = false;
  86. }
  87. break;
  88. }
  89. _rx_time = shark_get_mseconds();
  90. uart->rx_frame_old_prot[uart->rx_length_old_prot ++] = data;
  91. if (uart->rx_length_old_prot == sizeof(uart->rx_frame_old_prot)){
  92. uart->rx_length_old_prot = 0;
  93. }
  94. switch(data){
  95. case CH_START:
  96. uart->rx_length = 0;
  97. uart->escape = false;
  98. uart->start = true;
  99. break;
  100. case CH_END:
  101. if (uart->rx_length > 2 && uart->rx_length != 0xFFFF){
  102. uart->rx_length -= 2; //skip crc
  103. shark_uart_on_rx_frame(uart);
  104. }else if (uart->start == true){
  105. health_add_uart_error(0, 1, 0);
  106. }
  107. uart->rx_length = 0xFFFF;
  108. uart->start = false;
  109. break;
  110. case CH_ESC:
  111. uart->escape = true;
  112. break;
  113. default:
  114. if (uart->escape) {
  115. uart->escape = false;
  116. switch (data) {
  117. case CH_ESC_START:
  118. data = CH_START;
  119. break;
  120. case CH_ESC_END:
  121. data = CH_END;
  122. break;
  123. case CH_ESC_ESC:
  124. data = CH_ESC;
  125. break;
  126. default:
  127. data = 0xFF;
  128. }
  129. }
  130. if (uart->rx_length < sizeof(uart->rx_frame)) {
  131. uart->rx_frame[uart->rx_length] = data;
  132. uart->rx_length++;
  133. } else {
  134. uart->rx_length = 0xFFFF;
  135. if (uart->start == true) {
  136. health_add_uart_error(0, 1, 0);
  137. }
  138. }
  139. }
  140. }
  141. }
  142. static void shark_uart_dma_tx(shark_uart_t *uart)
  143. {
  144. u32 value = DMA_CHCTL(uart->tx_dma_ch);
  145. if (value & DMA_CHXCTL_CHEN) {
  146. if (SET != dma_flag_get(uart->tx_dma_ch, DMA_FLAG_FTF)) {
  147. return;
  148. }
  149. byte_queue_skip(&uart->tx_queue, uart->tx_length);
  150. DMA_CHCTL(uart->tx_dma_ch) = value & (~DMA_CHXCTL_CHEN);
  151. }
  152. uart->tx_length = byte_queue_peek(&uart->tx_queue);
  153. if (uart->tx_length > 0) {
  154. DMA_CHCNT(uart->tx_dma_ch) = uart->tx_length;
  155. DMA_CHMADDR(uart->tx_dma_ch) = (u32) byte_queue_head(&uart->tx_queue);
  156. dma_flag_clear(uart->tx_dma_ch, DMA_FLAG_FTF);
  157. DMA_CHCTL(uart->tx_dma_ch) = value | DMA_CHXCTL_CHEN;
  158. }
  159. }
  160. static void shark_uart_write(shark_uart_t *uart, const u8 *buff, u16 size)
  161. {
  162. while (size > 0) {
  163. u16 length = byte_queue_write(&uart->tx_queue, buff, size);
  164. if (length == size) {
  165. shark_uart_dma_tx(uart);
  166. break;
  167. }
  168. shark_uart_dma_tx(uart);
  169. buff += length;
  170. size -= length;
  171. }
  172. }
  173. static void shark_uart_write_byte(shark_uart_t *uart, u8 value)
  174. {
  175. shark_uart_write(uart, &value, 1);
  176. }
  177. static void shark_uart_tx_dma_init(shark_uart_t *uart){
  178. dma_parameter_struct dma_init_struct;
  179. rcu_periph_clock_enable(_uart_index(uart->uart_com)== SHARK_UART0?SHARK_UART0_tx_dma_clk:SHARK_UART1_tx_dma_clk);
  180. dma_deinit(uart->tx_dma_ch);
  181. dma_init_struct.direction = DMA_MEMORY_TO_PERIPHERAL;
  182. dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
  183. dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
  184. dma_init_struct.periph_addr = (u32) &USART_TDATA(uart->uart_com);
  185. dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
  186. dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
  187. dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
  188. dma_init(uart->tx_dma_ch, &dma_init_struct);
  189. dma_circulation_disable(uart->tx_dma_ch);
  190. dma_memory_to_memory_disable(uart->tx_dma_ch);
  191. usart_dma_transmit_config(uart->uart_com, USART_DENT_ENABLE);
  192. #if 0
  193. if (uart->tx_dma_ch == DMA_CH1) {
  194. nvic_irq_enable(DMA_Channel1_2_IRQn ,4, 0);
  195. }else {
  196. nvic_irq_enable(DMA_Channel3_4_IRQn ,4, 0);
  197. }
  198. dma_interrupt_enable(uart->tx_dma_ch, DMA_INT_FTF);
  199. #endif
  200. }
  201. static void shark_uart_rx_dma_init(shark_uart_t *uart){
  202. dma_parameter_struct dma_init_struct;
  203. rcu_periph_clock_enable(_uart_index(uart->uart_com)== SHARK_UART0?SHARK_UART0_rx_dma_clk:SHARK_UART1_rx_dma_clk);
  204. dma_deinit(uart->rx_dma_ch);
  205. dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
  206. dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
  207. dma_init_struct.memory_width = DMA_MEMORY_WIDTH_8BIT;
  208. dma_init_struct.memory_addr = (u32)uart->rx_queue.buffer;
  209. dma_init_struct.number = uart->rx_queue.buffer_len;
  210. dma_init_struct.periph_addr = (u32) &USART_RDATA(uart->uart_com);
  211. dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
  212. dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_8BIT;
  213. dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
  214. dma_init(uart->rx_dma_ch, &dma_init_struct);
  215. dma_circulation_enable(uart->rx_dma_ch);
  216. dma_memory_to_memory_disable(uart->rx_dma_ch);
  217. dma_channel_enable(uart->rx_dma_ch);
  218. usart_dma_receive_config(uart->uart_com, USART_DENR_ENABLE);
  219. }
  220. static void shark_uart_pin_init(shark_uart_t *uart){
  221. if (_uart_index(uart->uart_com) == SHARK_UART0) {
  222. rcu_periph_clock_enable(SHARK_UART0_clk);
  223. rcu_periph_clock_enable(SHARK_UART0_rx_gpio_clk);
  224. rcu_periph_clock_enable(SHARK_UART0_tx_gpio_clk);
  225. gpio_af_set(SHARK_UART0_tx_port, GPIO_AF_0,SHARK_UART0_tx_pin);
  226. gpio_mode_set(SHARK_UART0_tx_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, SHARK_UART0_tx_pin);
  227. gpio_output_options_set(SHARK_UART0_tx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SHARK_UART0_tx_pin);
  228. gpio_af_set(SHARK_UART0_rx_port, GPIO_AF_0,SHARK_UART0_rx_pin);
  229. gpio_mode_set(SHARK_UART0_rx_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, SHARK_UART0_rx_pin);
  230. gpio_output_options_set(SHARK_UART0_rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,SHARK_UART0_rx_pin);
  231. }else {
  232. rcu_periph_clock_enable(SHARK_UART1_clk);
  233. rcu_periph_clock_enable(SHARK_UART1_rx_gpio_clk);
  234. rcu_periph_clock_enable(SHARK_UART1_tx_gpio_clk);
  235. gpio_af_set(SHARK_UART1_tx_port, GPIO_AF_1,SHARK_UART1_tx_pin);
  236. gpio_mode_set(SHARK_UART1_tx_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, SHARK_UART1_tx_pin);
  237. gpio_output_options_set(SHARK_UART1_tx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, SHARK_UART1_tx_pin);
  238. gpio_af_set(SHARK_UART1_rx_port, GPIO_AF_1,SHARK_UART1_rx_pin);
  239. gpio_mode_set(SHARK_UART1_rx_port, GPIO_MODE_AF, GPIO_PUPD_PULLUP, SHARK_UART1_rx_pin);
  240. gpio_output_options_set(SHARK_UART1_rx_port, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,SHARK_UART1_rx_pin);
  241. }
  242. }
  243. static void shark_uart_pin_deinit(shark_uart_t *uart){
  244. if (_uart_index(uart->uart_com) == SHARK_UART0) {
  245. gpio_mode_set(SHARK_UART0_tx_port, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SHARK_UART0_tx_pin);
  246. gpio_mode_set(SHARK_UART0_rx_port, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SHARK_UART0_rx_pin);
  247. }else {
  248. gpio_mode_set(SHARK_UART1_tx_port, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SHARK_UART1_tx_pin);
  249. gpio_mode_set(SHARK_UART1_rx_port, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SHARK_UART1_rx_pin);
  250. }
  251. }
  252. static void shark_uart_device_init(shark_uart_t *uart){
  253. usart_deinit(uart->uart_com);
  254. usart_baudrate_set(uart->uart_com, SHARK_UART_BAUDRATE);
  255. usart_word_length_set(uart->uart_com, USART_WL_8BIT);
  256. usart_stop_bit_set(uart->uart_com, USART_STB_1BIT);
  257. usart_parity_config(uart->uart_com, USART_PM_NONE);
  258. usart_hardware_flow_rts_config(uart->uart_com, USART_RTS_DISABLE);
  259. usart_hardware_flow_cts_config(uart->uart_com, USART_CTS_DISABLE);
  260. usart_receive_config(uart->uart_com, USART_RECEIVE_ENABLE);
  261. usart_transmit_config(uart->uart_com, USART_TRANSMIT_ENABLE);
  262. }
  263. static u32 shark_uart_handler(void)
  264. {
  265. shark_uart_t *uart = _shark_uart + SHARK_UART0;
  266. if (uart->uart_com != 0) {
  267. shark_uart_rx(uart);
  268. shark_uart_dma_tx(uart);
  269. }
  270. #if UART_NUM==2
  271. uart = _shark_uart + SHARK_UART1;
  272. if (uart->uart_com != 0) {
  273. shark_uart_rx(uart);
  274. shark_uart_dma_tx(uart);
  275. }
  276. #endif
  277. return 0;
  278. }
  279. void shark_uart_flush(void){
  280. shark_uart_t *uart = _shark_uart + SHARK_UART0;
  281. if (uart->uart_com != 0) {
  282. shark_uart_dma_tx(uart);
  283. }
  284. #if UART_NUM==2
  285. uart = _shark_uart + SHARK_UART1;
  286. if (uart->uart_com != 0) {
  287. shark_uart_dma_tx(uart);
  288. }
  289. #endif
  290. }
  291. #if 0
  292. void DMA_Channel1_2_IRQHandler(void){
  293. shark_uart_t *uart = _shark_uart + SHARK_UART0;
  294. if (dma_interrupt_flag_get(uart->tx_dma_ch, DMA_INT_FLAG_FTF) != RESET){
  295. shark_uart_dma_tx(uart);
  296. dma_interrupt_flag_clear(uart->tx_dma_ch, DMA_INT_FLAG_FTF);
  297. }
  298. }
  299. void DMA_Channel3_4_IRQHandler(void){
  300. shark_uart_t *uart = _shark_uart + SHARK_UART1;
  301. if (dma_interrupt_flag_get(uart->tx_dma_ch, DMA_INT_FLAG_FTF) != RESET){
  302. shark_uart_dma_tx(uart);
  303. dma_interrupt_flag_clear(uart->tx_dma_ch, DMA_INT_FLAG_FTF);
  304. }
  305. }
  306. #endif
  307. static u8 *tx_cache_addr(uart_enum_t uart_no){
  308. #if UART_NUM==2
  309. return (uart_no == SHARK_UART0)?shark_uart0_tx_cache:shark_uart1_tx_cache;
  310. #else
  311. return shark_uart0_tx_cache;
  312. #endif
  313. }
  314. void shark_uart_deinit(uart_enum_t uart_no){
  315. shark_uart_t *uart = _shark_uart + uart_no;
  316. if (uart->uart_com != 0) {
  317. usart_disable(uart->uart_com);
  318. usart_deinit(uart->uart_com);
  319. rcu_periph_clock_disable(uart_no == SHARK_UART0?SHARK_UART0_clk:SHARK_UART1_clk);
  320. dma_channel_disable(uart->rx_dma_ch);
  321. dma_channel_disable(uart->tx_dma_ch);
  322. rcu_periph_clock_disable(uart_no == SHARK_UART0?SHARK_UART0_tx_dma_clk:SHARK_UART1_tx_dma_clk);
  323. rcu_periph_clock_disable(uart_no == SHARK_UART0?SHARK_UART0_rx_dma_clk:SHARK_UART1_rx_dma_clk);
  324. shark_uart_pin_deinit(uart);
  325. }
  326. if (uart_no == SHARK_UART0) {
  327. UART0_IR_EN(0);
  328. }else {
  329. UART1_IR_EN(0);
  330. }
  331. }
  332. bool shark_uart_timeout(void){
  333. #if UART_NUM==2
  334. return (_shark_uart[0].uart_no_data && _shark_uart[1].uart_no_data)?TRUE:FALSE;
  335. #else
  336. return (_shark_uart[0].uart_no_data)?TRUE:FALSE;
  337. #endif
  338. }
  339. void shark_uart_init(uart_enum_t uart_no)
  340. {
  341. shark_uart_t *uart = _shark_uart + uart_no;
  342. uart->escape = false;
  343. uart->rx_length = 0;
  344. uart->tx_length = 0;
  345. uart->uart_com = (uart_no == SHARK_UART0)?SHARK_UART0_com:SHARK_UART1_com;
  346. circle_buffer_init(&uart->rx_queue, shark_uart_rx_cache, SHARK_UART_TX_MEM_SIZE);
  347. byte_queue_init(&uart->tx_queue,tx_cache_addr(uart_no), SHARK_UART_TX_MEM_SIZE);
  348. uart->rx_dma_ch = (uart_no == SHARK_UART0)?SHARK_UART0_rx_dma_ch:SHARK_UART1_rx_dma_ch;
  349. uart->tx_dma_ch = (uart_no == SHARK_UART0)?SHARK_UART0_tx_dma_ch:SHARK_UART1_tx_dma_ch;
  350. shark_uart_pin_init(uart);
  351. shark_uart_device_init(uart);
  352. shark_uart_rx_dma_init(uart);
  353. shark_uart_tx_dma_init(uart);
  354. usart_enable(uart->uart_com);
  355. if (_uart_task.handler == NULL) {
  356. _uart_task.handler = shark_uart_handler;
  357. shark_task_add(&_uart_task);
  358. }
  359. if (uart_no == SHARK_UART0) {
  360. UART0_IR_EN(1);
  361. }else {
  362. UART1_IR_EN(1);
  363. }
  364. _rx_time = shark_get_mseconds();
  365. uart->uart_no_data = false;
  366. }
  367. static void shark_uart_write_byte_esc(shark_uart_t *uart, u8 value)
  368. {
  369. switch (value) {
  370. case CH_START:
  371. shark_uart_write_byte(uart, CH_ESC);
  372. value = CH_ESC_START;
  373. break;
  374. case CH_END:
  375. shark_uart_write_byte(uart, CH_ESC);
  376. value = CH_ESC_END;
  377. break;
  378. case CH_ESC:
  379. shark_uart_write_byte(uart, CH_ESC);
  380. value = CH_ESC_ESC;
  381. break;
  382. }
  383. shark_uart_write_byte(uart, value);
  384. }
  385. static void shark_uart_write_esc(shark_uart_t *uart, const u8 *buff, u16 length)
  386. {
  387. const u8 *buff_end;
  388. for (buff_end = buff + length; buff < buff_end; buff++) {
  389. shark_uart_write_byte_esc(uart, *buff);
  390. }
  391. }
  392. static void shark_uart_tx_start(shark_uart_t *uart)
  393. {
  394. shark_uart_write_byte(uart, CH_START);
  395. uart->tx_crc16 = 0;
  396. }
  397. static void shark_uart_tx_continue(shark_uart_t *uart, const void *buff, u16 length)
  398. {
  399. shark_uart_write_esc(uart, (const u8 *) buff, length);
  400. uart->tx_crc16 = shark_crc16_update(uart->tx_crc16, (const u8 *) buff, length);
  401. }
  402. static void shark_uart_tx_end(shark_uart_t *uart)
  403. {
  404. shark_uart_write_esc(uart, (u8 *)&uart->tx_crc16, sizeof(uart->tx_crc16));
  405. shark_uart_write_byte(uart, CH_END);
  406. }
  407. void shark_uart_write_frame(uart_enum_t uart_no, uint8_t *bytes, int len){
  408. shark_uart_t *uart = _shark_uart + uart_no;
  409. shark_uart_tx_start(uart);
  410. shark_uart_tx_continue(uart, bytes, len);
  411. shark_uart_tx_end(uart);
  412. }
  413. void shark_uart_frame_start(uart_enum_t uart_no, uint8_t *bytes, int len){
  414. shark_uart_t *uart = _shark_uart + uart_no;
  415. shark_uart_tx_start(uart);
  416. shark_uart_tx_continue(uart, bytes, len);
  417. }
  418. void shark_uart_frame_continue(uart_enum_t uart_no, uint8_t *bytes, int len){
  419. shark_uart_t *uart = _shark_uart + uart_no;
  420. shark_uart_tx_continue(uart, bytes, len);
  421. }
  422. void shark_uart_frame_end(uart_enum_t uart_no){
  423. shark_uart_tx_end(_shark_uart + uart_no);
  424. }
  425. void shark_uart_write_bytes(uart_enum_t uart_no, u8 *buff, u16 size){
  426. shark_uart_write(_shark_uart + uart_no, buff, size);
  427. }