uart.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // SPDX-License-Identifier: BSD-3-Clause
  2. // Copyright (c) 2022, Alex Taradov <alex@taradov.com>. All rights reserved.
  3. /*- Includes ----------------------------------------------------------------*/
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <stdint.h>
  7. #include <stdbool.h>
  8. #include <string.h>
  9. #include "M480.h"
  10. #include "hal_config.h"
  11. #include "uart.h"
  12. #include "usb_cdc.h"
  13. #ifdef HAL_CONFIG_ENABLE_VCP
  14. /*- Definitions -------------------------------------------------------------*/
  15. #define UART_BUF_SIZE 256
  16. /*- Types ------------------------------------------------------------------*/
  17. typedef struct
  18. {
  19. int wr;
  20. int rd;
  21. uint16_t data[UART_BUF_SIZE];
  22. } fifo_buffer_t;
  23. /*- Variables --------------------------------------------------------------*/
  24. static volatile fifo_buffer_t uart_rx_fifo;
  25. static volatile fifo_buffer_t uart_tx_fifo;
  26. static volatile bool uart_fifo_overflow = false;
  27. /*- Implementations ---------------------------------------------------------*/
  28. //-----------------------------------------------------------------------------
  29. void uart_init(usb_cdc_line_coding_t *line_coding)
  30. {
  31. int wls, parity, nsb;
  32. CLK->UART_CLKSEL_REG = (CLK->UART_CLKSEL_REG & ~UART_CLKSEL_MSK) | (1/*PLL*/ << UART_CLKSEL_POS);
  33. CLK->APBCLK0 |= UART_APBCLK_EN;
  34. HAL_GPIO_UART_RX_pullup();
  35. HAL_GPIO_UART_RX_mfp(UART_RX_MPF);
  36. HAL_GPIO_UART_TX_pullup();
  37. HAL_GPIO_UART_TX_mfp(UART_TX_MPF);
  38. uart_tx_fifo.wr = 0;
  39. uart_tx_fifo.rd = 0;
  40. uart_rx_fifo.wr = 0;
  41. uart_rx_fifo.rd = 0;
  42. uart_fifo_overflow = false;
  43. if (USB_CDC_5_DATA_BITS == line_coding->bDataBits)
  44. wls = 0;
  45. else if (USB_CDC_6_DATA_BITS == line_coding->bDataBits)
  46. wls = 1;
  47. else if (USB_CDC_7_DATA_BITS == line_coding->bDataBits)
  48. wls = 2;
  49. else if (USB_CDC_8_DATA_BITS == line_coding->bDataBits)
  50. wls = 3;
  51. else
  52. wls = 3;
  53. if (USB_CDC_NO_PARITY == line_coding->bParityType)
  54. parity = 0;
  55. else if (USB_CDC_ODD_PARITY == line_coding->bParityType)
  56. parity = UART_LINE_PBE_Msk;
  57. else if (USB_CDC_EVEN_PARITY == line_coding->bParityType)
  58. parity = UART_LINE_PBE_Msk | UART_LINE_EPE_Msk;
  59. else if (USB_CDC_MARK_PARITY == line_coding->bParityType)
  60. parity = UART_LINE_PBE_Msk | UART_LINE_SPE_Msk;
  61. else if (USB_CDC_SPACE_PARITY == line_coding->bParityType)
  62. parity = UART_LINE_PBE_Msk | UART_LINE_SPE_Msk | UART_LINE_EPE_Msk;
  63. else
  64. parity = 0;
  65. if (USB_CDC_1_STOP_BIT == line_coding->bCharFormat)
  66. nsb = 0;
  67. else
  68. nsb = UART_LINE_NSB_Msk;;
  69. UART_PER->LINE = (wls << UART_LINE_WLS_Pos) | parity | nsb;
  70. UART_PER->BAUD = UART_BAUD_BAUDM0_Msk | UART_BAUD_BAUDM1_Msk | (UART_CLOCK / line_coding->dwDTERate - 2);
  71. UART_PER->INTEN = UART_INTEN_RDAIEN_Msk;
  72. NVIC_EnableIRQ(UART_IRQ_INDEX);
  73. }
  74. //-----------------------------------------------------------------------------
  75. void uart_close(void)
  76. {
  77. NVIC_DisableIRQ(UART_IRQ_INDEX);
  78. UART_PER->INTEN = 0;
  79. HAL_GPIO_UART_RX_mfp(0);
  80. HAL_GPIO_UART_TX_mfp(0);
  81. }
  82. //-----------------------------------------------------------------------------
  83. bool uart_write_byte(int byte)
  84. {
  85. int wr = (uart_tx_fifo.wr + 1) % UART_BUF_SIZE;
  86. bool res = false;
  87. NVIC_DisableIRQ(UART_IRQ_INDEX);
  88. if (wr != uart_tx_fifo.rd)
  89. {
  90. uart_tx_fifo.data[uart_tx_fifo.wr] = byte;
  91. uart_tx_fifo.wr = wr;
  92. res = true;
  93. UART_PER->INTEN |= UART_INTEN_THREIEN_Msk;
  94. }
  95. NVIC_EnableIRQ(UART_IRQ_INDEX);
  96. return res;
  97. }
  98. //-----------------------------------------------------------------------------
  99. bool uart_read_byte(int *byte)
  100. {
  101. bool res = false;
  102. NVIC_DisableIRQ(UART_IRQ_INDEX);
  103. if (uart_fifo_overflow)
  104. {
  105. *byte = (USB_CDC_SERIAL_STATE_OVERRUN << 8);
  106. uart_fifo_overflow = false;
  107. res = true;
  108. }
  109. else if (uart_rx_fifo.rd != uart_rx_fifo.wr)
  110. {
  111. *byte = uart_rx_fifo.data[uart_rx_fifo.rd];
  112. uart_rx_fifo.rd = (uart_rx_fifo.rd + 1) % UART_BUF_SIZE;
  113. res = true;
  114. }
  115. NVIC_EnableIRQ(UART_IRQ_INDEX);
  116. return res;
  117. }
  118. //-----------------------------------------------------------------------------
  119. void uart_set_break(bool brk)
  120. {
  121. if (brk)
  122. UART_PER->LINE |= UART_LINE_BCB_Msk;
  123. else
  124. UART_PER->LINE &= ~UART_LINE_BCB_Msk;
  125. }
  126. //-----------------------------------------------------------------------------
  127. void UART_IRQ_HANDLER(void)
  128. {
  129. uint32_t flags = UART_PER->INTSTS;
  130. if (flags & UART_INTSTS_RDAIF_Msk)
  131. {
  132. int status = UART_PER->FIFOSTS;
  133. int byte = UART_PER->DAT & UART_DAT_DAT_Msk;
  134. int wr = (uart_rx_fifo.wr + 1) % UART_BUF_SIZE;
  135. int state = 0;
  136. UART_PER->FIFOSTS = status;
  137. if (status & UART_FIFOSTS_RXOVIF_Msk)
  138. state |= USB_CDC_SERIAL_STATE_OVERRUN;
  139. if (status & UART_FIFOSTS_FEF_Msk)
  140. state |= USB_CDC_SERIAL_STATE_FRAMING;
  141. if (status & UART_FIFOSTS_PEF_Msk)
  142. state |= USB_CDC_SERIAL_STATE_PARITY;
  143. if (status & UART_FIFOSTS_BIF_Msk)
  144. state |= USB_CDC_SERIAL_STATE_BREAK;
  145. byte |= (state << 8);
  146. if (wr == uart_rx_fifo.rd)
  147. {
  148. uart_fifo_overflow = true;
  149. }
  150. else
  151. {
  152. uart_rx_fifo.data[uart_rx_fifo.wr] = byte;
  153. uart_rx_fifo.wr = wr;
  154. }
  155. }
  156. if (flags & UART_INTSTS_THREINT_Msk)
  157. {
  158. if (uart_tx_fifo.rd == uart_tx_fifo.wr)
  159. {
  160. UART_PER->INTEN &= ~UART_INTEN_THREIEN_Msk;
  161. }
  162. else
  163. {
  164. UART_PER->DAT = uart_tx_fifo.data[uart_tx_fifo.rd];
  165. uart_tx_fifo.rd = (uart_tx_fifo.rd + 1) % UART_BUF_SIZE;
  166. }
  167. }
  168. }
  169. #endif // HAL_CONFIG_ENABLE_VCP