serial.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Email Notes
  8. * 2019-07-16 Kevin.Liu kevin.liu.mchp@gmail.com First Release
  9. * 2023-09-16 luhuadong luhuadong@163.com support serial v2
  10. */
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #include <atmel_start.h>
  14. #include <board.h>
  15. /* SAM MCU serial device */
  16. static struct rt_serial_device sam_serial;
  17. static void serial_rxcallback(const struct usart_async_descriptor *const io_descr)
  18. {
  19. (void)io_descr;
  20. /* enter interrupt */
  21. rt_interrupt_enter();
  22. #ifdef RT_USING_SERIAL_V2
  23. struct rt_serial_rx_fifo *rx_fifo;
  24. uint8_t data;
  25. rx_fifo = (struct rt_serial_rx_fifo *)sam_serial.serial_rx;
  26. RT_ASSERT(rx_fifo != RT_NULL);
  27. do {
  28. ringbuffer_get((struct ringbuffer *const)&io_descr->rx, &data);
  29. rt_ringbuffer_putchar_force(&rx_fifo->rb, data);
  30. } while (0); // maybe not only one byte
  31. #endif
  32. /* Notify Serial driver to process RX data */
  33. rt_hw_serial_isr(&sam_serial, RT_SERIAL_EVENT_RX_IND); // or RT_SERIAL_EVENT_RX_DMADONE
  34. /* leave interrupt */
  35. rt_interrupt_leave();
  36. }
  37. static void serial_txcallback(const struct usart_async_descriptor *const io_descr)
  38. {
  39. (void)io_descr;
  40. /* enter interrupt */
  41. rt_interrupt_enter();
  42. /* Notify Serial driver to process TX done event */
  43. rt_hw_serial_isr(&sam_serial, RT_SERIAL_EVENT_TX_DONE);
  44. /* leave interrupt */
  45. rt_interrupt_leave();
  46. }
  47. /**
  48. * @brief Configure serial port
  49. *
  50. * This function will configure UART baudrate, parity and so on.
  51. *
  52. * @return RT_EOK.
  53. */
  54. static rt_err_t serial_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
  55. {
  56. struct usart_async_descriptor* desc;
  57. RT_ASSERT(serial != RT_NULL);
  58. desc = (struct usart_async_descriptor *)serial->parent.user_data;
  59. RT_ASSERT(desc != RT_NULL);
  60. RT_ASSERT(cfg != RT_NULL);
  61. usart_async_disable(desc);
  62. /* Set baudrate */
  63. usart_async_set_baud_rate(desc, (const uint32_t)cfg->baud_rate);
  64. /* Set stop bit */
  65. if (cfg->stop_bits == STOP_BITS_1)
  66. usart_async_set_stopbits(desc, USART_STOP_BITS_ONE);
  67. else if (cfg->stop_bits == STOP_BITS_2)
  68. usart_async_set_stopbits(desc, USART_STOP_BITS_TWO);
  69. if (cfg->bit_order == BIT_ORDER_LSB)
  70. usart_async_set_data_order(desc, USART_DATA_ORDER_LSB);
  71. else if (cfg->bit_order == BIT_ORDER_MSB)
  72. usart_async_set_data_order(desc, USART_DATA_ORDER_MSB);
  73. /* Set character size */
  74. switch (cfg->data_bits)
  75. {
  76. case DATA_BITS_5:
  77. usart_async_set_character_size(desc, USART_CHARACTER_SIZE_5BITS);
  78. break;
  79. case DATA_BITS_6:
  80. usart_async_set_character_size(desc, USART_CHARACTER_SIZE_6BITS);
  81. break;
  82. case DATA_BITS_7:
  83. usart_async_set_character_size(desc, USART_CHARACTER_SIZE_7BITS);
  84. break;
  85. case DATA_BITS_8:
  86. usart_async_set_character_size(desc, USART_CHARACTER_SIZE_8BITS);
  87. break;
  88. case DATA_BITS_9:
  89. usart_async_set_character_size(desc, USART_CHARACTER_SIZE_9BITS);
  90. break;
  91. default:
  92. break;
  93. }
  94. if (cfg->parity == PARITY_NONE)
  95. usart_async_set_parity(desc, USART_PARITY_NONE);
  96. else if (cfg->parity == PARITY_ODD)
  97. usart_async_set_parity(desc, USART_PARITY_ODD);
  98. else if (cfg->parity == PARITY_EVEN)
  99. usart_async_set_parity(desc, USART_PARITY_EVEN);
  100. usart_async_enable(desc);
  101. return RT_EOK;
  102. }
  103. /**
  104. * @brief Control serial port
  105. *
  106. * This function provide UART enable/disable control.
  107. *
  108. * @return RT_EOK.
  109. */
  110. static rt_err_t serial_control(struct rt_serial_device *serial, int cmd, void *arg)
  111. {
  112. struct usart_async_descriptor* desc;
  113. RT_ASSERT(serial != RT_NULL);
  114. desc = (struct usart_async_descriptor *)serial->parent.user_data;
  115. RT_ASSERT(desc != RT_NULL);
  116. switch (cmd)
  117. {
  118. /* disable interrupt */
  119. case RT_DEVICE_CTRL_CLR_INT:
  120. usart_async_disable(desc);
  121. break;
  122. /* enable interrupt */
  123. case RT_DEVICE_CTRL_SET_INT:
  124. usart_async_enable(desc);
  125. break;
  126. /* UART config */
  127. case RT_DEVICE_CTRL_CONFIG: // RT_SERIAL_RX_NON_BLOCKING or RT_SERIAL_RX_BLOCKING
  128. // RT_SERIAL_TX_NON_BLOCKING or RT_SERIAL_TX_BLOCKING
  129. break;
  130. #ifdef RT_USING_SERIAL_V2
  131. case RT_DEVICE_CHECK_OPTMODE:
  132. break;
  133. #endif
  134. default:
  135. break;
  136. }
  137. return RT_EOK;
  138. }
  139. /**
  140. * @brief Serial sends a char
  141. *
  142. * This function will send a char to the UART
  143. *
  144. * @return 1.
  145. */
  146. static int serial_putc(struct rt_serial_device *serial, char c)
  147. {
  148. struct usart_async_descriptor* desc;
  149. RT_ASSERT(serial != RT_NULL);
  150. desc = (struct usart_async_descriptor *)serial->parent.user_data;
  151. RT_ASSERT(desc != RT_NULL);
  152. while (usart_async_is_tx_empty(desc) == 0);
  153. _usart_async_write_byte(&TARGET_IO.device, (uint8_t)c);
  154. return 1;
  155. }
  156. /**
  157. * @brief Serial gets a char
  158. *
  159. * This function will get a char from the UART
  160. *
  161. * @return received char character or -1 if no char received.
  162. */
  163. static int serial_getc(struct rt_serial_device *serial)
  164. {
  165. char c;
  166. int ch;
  167. struct usart_async_descriptor* desc;
  168. RT_ASSERT(serial != RT_NULL);
  169. desc = (struct usart_async_descriptor *)serial->parent.user_data;
  170. RT_ASSERT(desc != RT_NULL);
  171. ch = -1;
  172. if (usart_async_is_rx_not_empty(desc))
  173. {
  174. io_read(&desc->io, (uint8_t *)&c, 1);
  175. ch = c & 0xff;
  176. }
  177. return ch;
  178. }
  179. static const struct rt_uart_ops sam_serial_ops =
  180. {
  181. serial_configure,
  182. serial_control,
  183. serial_putc,
  184. serial_getc,
  185. };
  186. /**
  187. * @brief Initialize the UART
  188. *
  189. * This function initialize the UART
  190. *
  191. * @return None.
  192. */
  193. int rt_hw_uart_init(void)
  194. {
  195. struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
  196. config.baud_rate = DEFAULT_USART_BAUD_RATE;
  197. sam_serial.ops = &sam_serial_ops;
  198. sam_serial.config = config;
  199. sam_serial.serial_rx = RT_NULL;
  200. sam_serial.serial_tx = RT_NULL;
  201. rt_hw_serial_register(&sam_serial, "uart0" /* RT_CONSOLE_DEVICE_NAME */,
  202. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX |
  203. RT_DEVICE_FLAG_INT_TX, (void *)&TARGET_IO);
  204. usart_async_register_callback(&TARGET_IO, USART_ASYNC_TXC_CB, serial_txcallback);
  205. usart_async_register_callback(&TARGET_IO, USART_ASYNC_RXC_CB, serial_rxcallback);
  206. return 0;
  207. }