usart.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2011-01-13 weety first version
  9. * 2013-07-21 weety using serial component
  10. */
  11. #include <rtthread.h>
  12. #include <rthw.h>
  13. #include <at91sam9g45.h>
  14. #include <rtdevice.h>
  15. struct at91_uart {
  16. AT91S_USART *port;
  17. int irq;
  18. };
  19. /**
  20. * This function will handle serial port interrupt
  21. */
  22. void rt_at91_usart_handler(int vector, void *param)
  23. {
  24. int status;
  25. struct at91_uart *uart;
  26. rt_device_t dev = (rt_device_t)param;
  27. uart = (struct at91_uart *)dev->user_data;
  28. status = uart->port->US_CSR;
  29. if (!(status & uart->port->US_IMR)) /* check actived and enabled interrupt */
  30. {
  31. return;
  32. }
  33. rt_interrupt_enter();
  34. rt_hw_serial_isr((struct rt_serial_device *)dev, RT_SERIAL_EVENT_RX_IND);
  35. rt_interrupt_leave();
  36. }
  37. /**
  38. * UART device in RT-Thread
  39. */
  40. static rt_err_t at91_usart_configure(struct rt_serial_device *serial,
  41. struct serial_configure *cfg)
  42. {
  43. int div;
  44. int mode = 0;
  45. struct at91_uart *uart;
  46. RT_ASSERT(serial != RT_NULL);
  47. RT_ASSERT(cfg != RT_NULL);
  48. uart = (struct at91_uart *)serial->parent.user_data;
  49. uart->port->US_CR = AT91C_US_RSTTX | AT91C_US_RSTRX |
  50. AT91C_US_RXDIS | AT91C_US_TXDIS;
  51. mode |= AT91C_US_USMODE_NORMAL | AT91C_US_CLKS_CLOCK |
  52. AT91C_US_CHMODE_NORMAL;
  53. switch (cfg->data_bits)
  54. {
  55. case DATA_BITS_8:
  56. mode |= AT91C_US_CHRL_8_BITS;
  57. break;
  58. case DATA_BITS_7:
  59. mode |= AT91C_US_CHRL_7_BITS;
  60. break;
  61. case DATA_BITS_6:
  62. mode |= AT91C_US_CHRL_6_BITS;
  63. break;
  64. case DATA_BITS_5:
  65. mode |= AT91C_US_CHRL_5_BITS;
  66. break;
  67. default:
  68. mode |= AT91C_US_CHRL_8_BITS;
  69. break;
  70. }
  71. switch (cfg->stop_bits)
  72. {
  73. case STOP_BITS_2:
  74. mode |= AT91C_US_NBSTOP_2_BIT;
  75. break;
  76. case STOP_BITS_1:
  77. default:
  78. mode |= AT91C_US_NBSTOP_1_BIT;
  79. break;
  80. }
  81. switch (cfg->parity)
  82. {
  83. case PARITY_ODD:
  84. mode |= AT91C_US_PAR_ODD;
  85. break;
  86. case PARITY_EVEN:
  87. mode |= AT91C_US_PAR_EVEN;
  88. break;
  89. case PARITY_NONE:
  90. default:
  91. mode |= AT91C_US_PAR_NONE;
  92. break;
  93. }
  94. uart->port->US_MR = mode;
  95. /* Assume OVER is cleared and fractional baudrate generator is disabled */
  96. div = (clk_get_rate(clk_get("mck")) / 16 + cfg->baud_rate/2) / cfg->baud_rate;
  97. uart->port->US_BRGR = div;
  98. uart->port->US_CR = AT91C_US_RXEN | AT91C_US_TXEN;
  99. uart->port->US_IER = AT91C_US_RXRDY;
  100. return RT_EOK;
  101. }
  102. static rt_err_t at91_usart_control(struct rt_serial_device *serial,
  103. int cmd, void *arg)
  104. {
  105. struct at91_uart* uart;
  106. RT_ASSERT(serial != RT_NULL);
  107. uart = (struct at91_uart *)serial->parent.user_data;
  108. switch (cmd)
  109. {
  110. case RT_DEVICE_CTRL_CLR_INT:
  111. /* disable rx irq */
  112. rt_hw_interrupt_mask(uart->irq);
  113. break;
  114. case RT_DEVICE_CTRL_SET_INT:
  115. /* enable rx irq */
  116. rt_hw_interrupt_umask(uart->irq);
  117. break;
  118. }
  119. return RT_EOK;
  120. }
  121. static int at91_usart_putc(struct rt_serial_device *serial, char c)
  122. {
  123. //rt_uint32_t level;
  124. struct at91_uart *uart = serial->parent.user_data;
  125. while (!(uart->port->US_CSR & AT91C_US_TXRDY));
  126. uart->port->US_THR = c;
  127. return 1;
  128. }
  129. static int at91_usart_getc(struct rt_serial_device *serial)
  130. {
  131. int result;
  132. struct at91_uart *uart = serial->parent.user_data;
  133. if (uart->port->US_CSR & AT91C_US_RXRDY)
  134. {
  135. result = uart->port->US_RHR & 0xff;
  136. }
  137. else
  138. {
  139. result = -1;
  140. }
  141. return result;
  142. }
  143. static const struct rt_uart_ops at91_usart_ops =
  144. {
  145. at91_usart_configure,
  146. at91_usart_control,
  147. at91_usart_putc,
  148. at91_usart_getc,
  149. };
  150. #if defined(RT_USING_DBGU)
  151. static struct rt_serial_device serial_dbgu;
  152. struct at91_uart dbgu = {
  153. (AT91PS_USART)AT91C_BASE_DBGU,
  154. AT91C_ID_SYS
  155. };
  156. #endif
  157. #if defined(RT_USING_UART0)
  158. static struct rt_serial_device serial0;
  159. struct at91_uart uart0 = {
  160. AT91C_BASE_US0,
  161. AT91C_ID_US0
  162. };
  163. #endif
  164. #if defined(RT_USING_UART1)
  165. static struct rt_serial_device serial1;
  166. struct at91_uart uart1 = {
  167. AT91C_BASE_US1,
  168. AT91C_ID_US1
  169. };
  170. #endif
  171. #if defined(RT_USING_UART2)
  172. static struct rt_serial_device serial2;
  173. struct at91_uart uart2 = {
  174. AT91C_BASE_US2,
  175. AT91C_ID_US2
  176. };
  177. #endif
  178. #if defined(RT_USING_UART3)
  179. static struct rt_serial_device serial3;
  180. struct at91_uart uart3 = {
  181. AT91C_BASE_US3,
  182. AT91C_ID_US3
  183. };
  184. #endif
  185. void at91_usart_gpio_init(void)
  186. {
  187. #ifdef RT_USING_DBGU
  188. #define DRXD 12 // DBGU rx as Peripheral A on PB12
  189. #define DTXD 13 // DBGU tx as Peripheral A on PB13
  190. AT91C_BASE_PIOB->PIO_IDR, (1<<DRXD)|(1<<DTXD); // Disables the Input Change Interrupt on the I/O line
  191. AT91C_BASE_PIOB->PIO_PPUDR, (1<<DRXD)|(1<<DTXD); // Disables the pull up resistor on the I/O line
  192. AT91C_BASE_PIOB->PIO_ASR, (1<<DRXD)|(1<<DTXD); // Assigns the I/O line to the Peripheral A function
  193. AT91C_BASE_PIOB->PIO_PDR, (1<<DRXD)|(1<<DTXD); // enables peripheral control of the pin
  194. AT91C_BASE_PMC->PMC_PCER, 1 << AT91C_ID_SYS;
  195. #endif
  196. #ifdef RT_USING_UART0
  197. #define RXD0 18 // UART0 rx as Peripheral A on PB18
  198. #define TXD0 19 // UART0 tx as Peripheral A on PB19
  199. AT91C_BASE_PMC->PMC_PCER, 1 << AT91C_ID_US0;
  200. AT91C_BASE_PIOB->PIO_IDR, (1<<RXD0)|(1<<TXD0);
  201. AT91C_BASE_PIOB->PIO_PPUER, (1<<RXD0);
  202. AT91C_BASE_PIOB->PIO_PPUDR, (1<<TXD0);
  203. AT91C_BASE_PIOB->PIO_ASR, (1<<RXD0)|(1<<TXD0);
  204. AT91C_BASE_PIOB->PIO_PDR, (1<<RXD0)|(1<<TXD0);
  205. #endif
  206. #ifdef RT_USING_UART1
  207. #define TXD1 4 // UART1 tx as Peripheral A on PB4
  208. #define RXD1 5 // UART1 rx as Peripheral A on PB5
  209. AT91C_BASE_PMC->PMC_PCER, 1 << AT91C_ID_US1;
  210. AT91C_BASE_PIOB->PIO_IDR, (1<<RXD1)|(1<<TXD1);
  211. AT91C_BASE_PIOB->PIO_PPUER, (1<<RXD1);
  212. AT91C_BASE_PIOB->PIO_PPUDR, (1<<TXD1);
  213. AT91C_BASE_PIOB->PIO_ASR, (1<<RXD1)|(1<<TXD1);
  214. AT91C_BASE_PIOB->PIO_PDR, (1<<RXD1)|(1<<TXD1);
  215. #endif
  216. #ifdef RT_USING_UART2
  217. #define TXD2 6 // UART2 tx as Peripheral A on PB6
  218. #define RXD2 7 // UART2 rx as Peripheral A on PB7
  219. AT91C_BASE_PMC->PMC_PCER, 1 << AT91C_ID_US2;
  220. AT91C_BASE_PIOB->PIO_IDR, (1<<RXD2)|(1<<TXD2);
  221. AT91C_BASE_PIOB->PIO_PPUER, (1<<RXD2);
  222. AT91C_BASE_PIOB->PIO_PPUDR, (1<<TXD2);
  223. AT91C_BASE_PIOB->PIO_ASR, (1<<RXD2)|(1<<TXD2);
  224. AT91C_BASE_PIOB->PIO_PDR, (1<<RXD2)|(1<<TXD2);
  225. #endif
  226. #ifdef RT_USING_UART3
  227. #define TXD3 8 // UART3 tx as Peripheral A on PB8
  228. #define RXD3 9 // UART3 rx as Peripheral A on PB9
  229. AT91C_BASE_PMC->PMC_PCER, 1<<AT91C_ID_US3;
  230. AT91C_BASE_PIOB->PIO_IDR, (1<<RXD3)|(1<<TXD3);
  231. AT91C_BASE_PIOB->PIO_PPUER, (1<<RXD3);
  232. AT91C_BASE_PIOB->PIO_PPUDR, (1<<TXD3);
  233. AT91C_BASE_PIOB->PIO_ASR, (1<<RXD3)|(1<<TXD3);
  234. AT91C_BASE_PIOB->PIO_PDR, (1<<RXD3)|(1<<TXD3);
  235. #endif
  236. }
  237. /**
  238. * This function will handle init uart
  239. */
  240. int rt_hw_uart_init(void)
  241. {
  242. at91_usart_gpio_init();
  243. #if defined(RT_USING_DBGU)
  244. serial_dbgu.ops = &at91_usart_ops;
  245. serial_dbgu.config.baud_rate = BAUD_RATE_115200;
  246. serial_dbgu.config.bit_order = BIT_ORDER_LSB;
  247. serial_dbgu.config.data_bits = DATA_BITS_8;
  248. serial_dbgu.config.parity = PARITY_NONE;
  249. serial_dbgu.config.stop_bits = STOP_BITS_1;
  250. serial_dbgu.config.invert = NRZ_NORMAL;
  251. serial_dbgu.config.bufsz = RT_SERIAL_RB_BUFSZ;
  252. /* register vcom device */
  253. rt_hw_serial_register(&serial_dbgu, "dbgu",
  254. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
  255. &dbgu);
  256. #endif
  257. #if defined(RT_USING_UART0)
  258. serial0.ops = &at91_usart_ops;
  259. serial0.config.baud_rate = BAUD_RATE_115200;
  260. serial0.config.bit_order = BIT_ORDER_LSB;
  261. serial0.config.data_bits = DATA_BITS_8;
  262. serial0.config.parity = PARITY_NONE;
  263. serial0.config.stop_bits = STOP_BITS_1;
  264. serial0.config.invert = NRZ_NORMAL;
  265. serial0.config.bufsz = RT_SERIAL_RB_BUFSZ;
  266. /* register vcom device */
  267. rt_hw_serial_register(&serial0, "uart0",
  268. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,
  269. &uart0);
  270. rt_hw_interrupt_install(uart0.irq, rt_at91_usart_handler,
  271. (void *)&(serial0.parent), "UART0");
  272. rt_hw_interrupt_umask(uart0.irq);
  273. #endif
  274. #if defined(RT_USING_UART1)
  275. serial1.ops = &at91_usart_ops;
  276. serial1.config.baud_rate = BAUD_RATE_115200;
  277. serial1.config.bit_order = BIT_ORDER_LSB;
  278. serial1.config.data_bits = DATA_BITS_8;
  279. serial1.config.parity = PARITY_NONE;
  280. serial1.config.stop_bits = STOP_BITS_1;
  281. serial1.config.invert = NRZ_NORMAL;
  282. serial1.config.bufsz = RT_SERIAL_RB_BUFSZ;
  283. /* register vcom device */
  284. rt_hw_serial_register(&serial1, "uart1",
  285. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
  286. &uart1);
  287. rt_hw_interrupt_install(uart1.irq, rt_at91_usart_handler,
  288. (void *)&(serial1.parent), "UART1");
  289. rt_hw_interrupt_umask(uart1.irq);
  290. #endif
  291. #if defined(RT_USING_UART2)
  292. serial2.ops = &at91_usart_ops;
  293. serial2.config.baud_rate = BAUD_RATE_115200;
  294. serial2.config.bit_order = BIT_ORDER_LSB;
  295. serial2.config.data_bits = DATA_BITS_8;
  296. serial2.config.parity = PARITY_NONE;
  297. serial2.config.stop_bits = STOP_BITS_1;
  298. serial2.config.invert = NRZ_NORMAL;
  299. serial2.config.bufsz = RT_SERIAL_RB_BUFSZ;
  300. /* register vcom device */
  301. rt_hw_serial_register(&serial2, "uart2",
  302. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
  303. &uart2);
  304. rt_hw_interrupt_install(uart2.irq, rt_at91_usart_handler,
  305. (void *)&(serial2.parent), "UART2");
  306. rt_hw_interrupt_umask(uart2.irq);
  307. #endif
  308. #if defined(RT_USING_UART3)
  309. serial3.ops = &at91_usart_ops;
  310. serial3.config.baud_rate = BAUD_RATE_115200;
  311. serial3.config.bit_order = BIT_ORDER_LSB;
  312. serial3.config.data_bits = DATA_BITS_8;
  313. serial3.config.parity = PARITY_NONE;
  314. serial3.config.stop_bits = STOP_BITS_1;
  315. serial3.config.invert = NRZ_NORMAL;
  316. serial3.config.bufsz = RT_SERIAL_RB_BUFSZ;
  317. /* register vcom device */
  318. rt_hw_serial_register(&serial3, "uart3",
  319. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX,
  320. &uart3);
  321. rt_hw_interrupt_install(uart3.irq, rt_at91_usart_handler,
  322. (void *)&(serial3.parent), "UART3");
  323. rt_hw_interrupt_umask(uart3.irq);
  324. #endif
  325. return 0;
  326. }
  327. INIT_BOARD_EXPORT(rt_hw_uart_init);
  328. #ifdef RT_USING_DBGU
  329. void rt_dbgu_isr(void)
  330. {
  331. rt_at91_usart_handler(dbgu.irq, &(serial_dbgu.parent));
  332. }
  333. #endif