uart.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. // From module: SERCOM Callback API
  2. #include <samd21.h>
  3. #include <sercom.h>
  4. // #include <sercom_interrupt.h>
  5. // From module: SERCOM USART - Serial Communications (Callback APIs)
  6. #include <usart.h>
  7. // #include <usart_interrupt.h>
  8. #include <rtdevice.h>
  9. typedef struct _samd2x_uart_t
  10. {
  11. struct rt_serial_device *serial;
  12. struct usart_module *instance;
  13. Sercom *com;
  14. enum usart_signal_mux_settings mux_setting;
  15. uint32_t pinmux_pad0;
  16. uint32_t pinmux_pad1;
  17. uint32_t pinmux_pad2;
  18. uint32_t pinmux_pad3;
  19. enum system_interrupt_vector vector;
  20. } SAMD2x_UART_T;
  21. static struct rt_serial_device _serial3;
  22. static struct usart_module _uart3_instance;
  23. static SAMD2x_UART_T _uart3 = {
  24. &_serial3,
  25. &_uart3_instance,
  26. SERCOM3,
  27. USART_RX_1_TX_0_XCK_1,
  28. PINMUX_PA22C_SERCOM3_PAD0,
  29. PINMUX_PA23C_SERCOM3_PAD1,
  30. PINMUX_UNUSED,
  31. PINMUX_UNUSED,
  32. SYSTEM_INTERRUPT_MODULE_SERCOM3
  33. };
  34. // static struct rt_serial_device _serial2;
  35. // static struct rt_serial_device _serial3;
  36. // static struct rt_serial_device _serial4;
  37. static rt_err_t _uart_cfg(struct rt_serial_device *serial, struct serial_configure *cfg)
  38. {
  39. SAMD2x_UART_T *uart;
  40. RT_ASSERT(serial != RT_NULL);
  41. RT_ASSERT(cfg != RT_NULL);
  42. uart = (SAMD2x_UART_T *)serial->parent.user_data;
  43. //! [setup_config]
  44. struct usart_config config_usart;
  45. //! [setup_config]
  46. //! [setup_config_defaults]
  47. usart_get_config_defaults(&config_usart);
  48. //! [setup_config_defaults]
  49. config_usart.baudrate = cfg->baud_rate;
  50. switch (cfg->data_bits )
  51. {
  52. case DATA_BITS_8:
  53. config_usart.character_size = USART_CHARACTER_SIZE_8BIT;
  54. break;
  55. case DATA_BITS_5:
  56. config_usart.character_size = USART_CHARACTER_SIZE_5BIT;
  57. break;
  58. case DATA_BITS_6:
  59. config_usart.character_size = USART_CHARACTER_SIZE_6BIT;
  60. break;
  61. case DATA_BITS_7:
  62. config_usart.character_size = USART_CHARACTER_SIZE_7BIT;
  63. break;
  64. case DATA_BITS_9:
  65. config_usart.character_size = USART_CHARACTER_SIZE_9BIT;
  66. break;
  67. default:
  68. config_usart.character_size = USART_CHARACTER_SIZE_8BIT;
  69. break;
  70. }
  71. switch (cfg->parity)
  72. {
  73. case PARITY_NONE:
  74. config_usart.parity = USART_PARITY_NONE;
  75. break;
  76. case PARITY_EVEN:
  77. config_usart.parity = USART_PARITY_EVEN;
  78. break;
  79. case PARITY_ODD:
  80. config_usart.parity = USART_PARITY_ODD;
  81. break;
  82. default:
  83. config_usart.parity = USART_PARITY_NONE;
  84. break;
  85. }
  86. config_usart.stopbits = USART_STOPBITS_1;
  87. if (cfg->stop_bits != USART_STOPBITS_1)
  88. {
  89. config_usart.stopbits = USART_STOPBITS_2;
  90. }
  91. config_usart.data_order = USART_DATAORDER_LSB;
  92. if (cfg->bit_order != BIT_ORDER_LSB)
  93. {
  94. config_usart.data_order = USART_DATAORDER_MSB;
  95. }
  96. config_usart.mux_setting = uart->mux_setting;
  97. config_usart.pinmux_pad0 = uart->pinmux_pad0;
  98. config_usart.pinmux_pad1 = uart->pinmux_pad1;
  99. config_usart.pinmux_pad2 = uart->pinmux_pad2;
  100. config_usart.pinmux_pad3 = uart->pinmux_pad3;
  101. config_usart.receiver_enable = false;
  102. config_usart.transmitter_enable = true;
  103. while (usart_init(uart->instance, uart->com, &config_usart) != STATUS_OK) {
  104. }
  105. usart_enable(uart->instance);
  106. /* Wait for the synchronization to complete */
  107. _usart_wait_for_sync(uart->instance);
  108. return RT_EOK;
  109. }
  110. static rt_err_t _uart_ctrl(struct rt_serial_device *serial, int cmd, void *arg)
  111. {
  112. SAMD2x_UART_T *uart;
  113. RT_ASSERT(serial != RT_NULL);
  114. uart = (SAMD2x_UART_T *)(serial->parent.user_data);
  115. switch (cmd)
  116. {
  117. /* disable interrupt */
  118. case RT_DEVICE_CTRL_CLR_INT:
  119. uart->com->USART.INTENCLR.reg = SERCOM_USART_INTFLAG_RXC;
  120. usart_disable_transceiver(uart->instance, USART_TRANSCEIVER_RX);
  121. system_interrupt_disable(uart->vector);
  122. /* Wait for the synchronization to complete */
  123. _usart_wait_for_sync(uart->instance);
  124. break;
  125. /* enable interrupt */
  126. case RT_DEVICE_CTRL_SET_INT:
  127. /* Enable RX interrupt. */
  128. /* Enable the RX Complete Interrupt */
  129. uart->com->USART.INTENSET.reg = SERCOM_USART_INTFLAG_RXC;
  130. usart_enable_transceiver(uart->instance, USART_TRANSCEIVER_RX);
  131. system_interrupt_enable(uart->vector);
  132. /* Wait for the synchronization to complete */
  133. _usart_wait_for_sync(uart->instance);
  134. break;
  135. default:
  136. return RT_ERROR;
  137. }
  138. return RT_EOK;
  139. }
  140. static int _uart_putc(struct rt_serial_device *serial, char c)
  141. {
  142. SAMD2x_UART_T *uart;
  143. RT_ASSERT(serial != RT_NULL);
  144. // while (!(uart->com->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_DRE)) {
  145. // }
  146. uart = (SAMD2x_UART_T *)(serial->parent.user_data);
  147. /* Write data to USART module */
  148. uart->com->USART.DATA.reg = c;
  149. while (!(uart->com->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_TXC)) {
  150. /* Wait until data is sent */
  151. }
  152. return 1;
  153. }
  154. static int _uart_getc(struct rt_serial_device *serial)
  155. {
  156. int ch;
  157. SAMD2x_UART_T *uart;
  158. RT_ASSERT(serial != RT_NULL);
  159. uart = (SAMD2x_UART_T *)(serial->parent.user_data);
  160. /* Check if USART has new data */
  161. if (!(uart->com->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_RXC)) {
  162. /* Return error code */
  163. return -1;
  164. }
  165. ch = uart->com->USART.DATA.reg & 0x1FF;
  166. return ch;
  167. }
  168. static struct rt_uart_ops _uart_ops = {
  169. _uart_cfg,
  170. _uart_ctrl,
  171. _uart_putc,
  172. _uart_getc
  173. };
  174. static void uart_int_cb(SAMD2x_UART_T *uart_handle)
  175. {
  176. /* Temporary variables */
  177. uint16_t interrupt_status;
  178. uint8_t error_code;
  179. struct usart_module *module = uart_handle->instance;
  180. /* Pointer to the hardware module instance */
  181. SercomUsart *const usart_hw = &(module->hw->USART);
  182. /* Read and mask interrupt flag register */
  183. interrupt_status = usart_hw->INTFLAG.reg;
  184. interrupt_status &= usart_hw->INTENSET.reg;
  185. /* Check if the Receive Complete interrupt has occurred, and that
  186. * there's more data to receive */
  187. if (interrupt_status & SERCOM_USART_INTFLAG_RXC) {
  188. /* Read out the status code and mask away all but the 4 LSBs*/
  189. error_code = (uint8_t)(usart_hw->STATUS.reg & SERCOM_USART_STATUS_MASK);
  190. #if !SAMD20
  191. /* CTS status should not be considered as an error */
  192. if(error_code & SERCOM_USART_STATUS_CTS) {
  193. error_code &= ~SERCOM_USART_STATUS_CTS;
  194. }
  195. #endif
  196. #ifdef FEATURE_USART_LIN_MASTER
  197. /* TXE status should not be considered as an error */
  198. if(error_code & SERCOM_USART_STATUS_TXE) {
  199. error_code &= ~SERCOM_USART_STATUS_TXE;
  200. }
  201. #endif
  202. /* Check if an error has occurred during the receiving */
  203. if (error_code) {
  204. /* Check which error occurred */
  205. if (error_code & SERCOM_USART_STATUS_FERR) {
  206. /* clear flag by writing 1 to it */
  207. usart_hw->STATUS.reg = SERCOM_USART_STATUS_FERR;
  208. } else if (error_code & SERCOM_USART_STATUS_BUFOVF) {
  209. /* clear flag by writing 1 to it */
  210. usart_hw->STATUS.reg = SERCOM_USART_STATUS_BUFOVF;
  211. } else if (error_code & SERCOM_USART_STATUS_PERR) {
  212. /* clear flag by writing 1 to it */
  213. usart_hw->STATUS.reg = SERCOM_USART_STATUS_PERR;
  214. }
  215. #ifdef FEATURE_USART_LIN_SLAVE
  216. else if (error_code & SERCOM_USART_STATUS_ISF) {
  217. /* clear flag by writing 1 to it */
  218. usart_hw->STATUS.reg = SERCOM_USART_STATUS_ISF;
  219. }
  220. #endif
  221. #ifdef FEATURE_USART_COLLISION_DECTION
  222. else if (error_code & SERCOM_USART_STATUS_COLL) {
  223. /* clear flag by writing 1 to it */
  224. usart_hw->STATUS.reg = SERCOM_USART_STATUS_COLL;
  225. }
  226. #endif
  227. } else {
  228. rt_hw_serial_isr(uart_handle->serial, RT_SERIAL_EVENT_RX_IND);
  229. }
  230. }
  231. #ifdef FEATURE_USART_HARDWARE_FLOW_CONTROL
  232. if (interrupt_status & SERCOM_USART_INTFLAG_CTSIC) {
  233. /* Disable interrupts */
  234. usart_hw->INTENCLR.reg = SERCOM_USART_INTENCLR_CTSIC;
  235. /* Clear interrupt flag */
  236. usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_CTSIC;
  237. }
  238. #endif
  239. #ifdef FEATURE_USART_LIN_SLAVE
  240. if (interrupt_status & SERCOM_USART_INTFLAG_RXBRK) {
  241. /* Disable interrupts */
  242. usart_hw->INTENCLR.reg = SERCOM_USART_INTENCLR_RXBRK;
  243. /* Clear interrupt flag */
  244. usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_RXBRK;
  245. }
  246. #endif
  247. #ifdef FEATURE_USART_START_FRAME_DECTION
  248. if (interrupt_status & SERCOM_USART_INTFLAG_RXS) {
  249. /* Disable interrupts */
  250. usart_hw->INTENCLR.reg = SERCOM_USART_INTENCLR_RXS;
  251. /* Clear interrupt flag */
  252. usart_hw->INTFLAG.reg = SERCOM_USART_INTFLAG_RXS;
  253. }
  254. #endif
  255. }
  256. void SERCOM3_Handler(void)
  257. {
  258. uart_int_cb(&_uart3);
  259. }
  260. void uart_init(void)
  261. {
  262. struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
  263. config.bufsz = 512;
  264. _serial3.config = config;
  265. _serial3.ops = &_uart_ops;
  266. rt_hw_serial_register(&_serial3, "uart3", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, &_uart3);
  267. }