serial.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  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. * 2006-03-13 Bernard first version
  9. * 2011-05-15 lgnq modified according bernard's implementaion.
  10. */
  11. #include <rtthread.h>
  12. #include "serial.h"
  13. /**
  14. * @addtogroup FM4 MB9BF568R
  15. */
  16. /*@{*/
  17. /* RT-Thread Device Interface */
  18. /**
  19. * This function initializes serial
  20. */
  21. static rt_err_t rt_serial_init (rt_device_t dev)
  22. {
  23. struct serial_device* uart = (struct serial_device*) dev->user_data;
  24. if (!(dev->flag & RT_DEVICE_FLAG_ACTIVATED))
  25. {
  26. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  27. {
  28. rt_memset(uart->int_rx->rx_buffer, 0,
  29. sizeof(uart->int_rx->rx_buffer));
  30. uart->int_rx->read_index = uart->int_rx->save_index = 0;
  31. }
  32. if (dev->flag & RT_DEVICE_FLAG_INT_TX)
  33. {
  34. rt_memset(uart->int_tx->tx_buffer, 0,
  35. sizeof(uart->int_tx->tx_buffer));
  36. uart->int_tx->write_index = uart->int_tx->save_index = 0;
  37. }
  38. dev->flag |= RT_DEVICE_FLAG_ACTIVATED;
  39. }
  40. return RT_EOK;
  41. }
  42. /* save a char to serial buffer */
  43. static void rt_serial_savechar(struct serial_device* uart, char ch)
  44. {
  45. rt_base_t level;
  46. /* disable interrupt */
  47. level = rt_hw_interrupt_disable();
  48. uart->int_rx->rx_buffer[uart->int_rx->save_index] = ch;
  49. uart->int_rx->save_index ++;
  50. if (uart->int_rx->save_index >= UART_RX_BUFFER_SIZE)
  51. uart->int_rx->save_index = 0;
  52. /* if the next position is read index, discard this 'read char' */
  53. if (uart->int_rx->save_index == uart->int_rx->read_index)
  54. {
  55. uart->int_rx->read_index ++;
  56. if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE)
  57. uart->int_rx->read_index = 0;
  58. }
  59. /* enable interrupt */
  60. rt_hw_interrupt_enable(level);
  61. }
  62. static rt_err_t rt_serial_open(rt_device_t dev, rt_uint16_t oflag)
  63. {
  64. struct serial_device* uart;
  65. RT_ASSERT(dev != RT_NULL);
  66. uart = (struct serial_device*) dev->user_data;
  67. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  68. {
  69. /* enable interrupt */
  70. UART_ENABLE_IRQ(uart->rx_irq);
  71. }
  72. return RT_EOK;
  73. }
  74. static rt_err_t rt_serial_close(rt_device_t dev)
  75. {
  76. struct serial_device* uart;
  77. RT_ASSERT(dev != RT_NULL);
  78. uart = (struct serial_device*) dev->user_data;
  79. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  80. {
  81. /* disable interrupt */
  82. UART_DISABLE_IRQ(uart->rx_irq);
  83. }
  84. return RT_EOK;
  85. }
  86. static rt_size_t rt_serial_read (rt_device_t dev, rt_off_t pos, void* buffer,
  87. rt_size_t size)
  88. {
  89. rt_uint8_t* ptr;
  90. rt_err_t err_code;
  91. struct serial_device* uart;
  92. ptr = buffer;
  93. err_code = RT_EOK;
  94. uart = (struct serial_device*)dev->user_data;
  95. if (dev->flag & RT_DEVICE_FLAG_INT_RX)
  96. {
  97. rt_base_t level;
  98. /* interrupt mode Rx */
  99. while (size)
  100. {
  101. if (uart->int_rx->read_index != uart->int_rx->save_index)
  102. {
  103. *ptr++ = uart->int_rx->rx_buffer[uart->int_rx->read_index];
  104. size --;
  105. /* disable interrupt */
  106. level = rt_hw_interrupt_disable();
  107. uart->int_rx->read_index ++;
  108. if (uart->int_rx->read_index >= UART_RX_BUFFER_SIZE)
  109. uart->int_rx->read_index = 0;
  110. /* enable interrupt */
  111. rt_hw_interrupt_enable(level);
  112. }
  113. else
  114. {
  115. /* set error code */
  116. err_code = -RT_EEMPTY;
  117. break;
  118. }
  119. }
  120. }
  121. else
  122. {
  123. /* polling mode */
  124. while ((rt_uint32_t)ptr - (rt_uint32_t)buffer < size)
  125. {
  126. while (uart->uart_device->SSR & SSR_RDRF)
  127. {
  128. *ptr = uart->uart_device->RDR & 0xff;
  129. ptr ++;
  130. }
  131. }
  132. }
  133. /* set error code */
  134. rt_set_errno(err_code);
  135. return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
  136. }
  137. static rt_size_t rt_serial_write (rt_device_t dev, rt_off_t pos,
  138. const void* buffer, rt_size_t size)
  139. {
  140. rt_uint8_t* ptr;
  141. rt_err_t err_code;
  142. struct serial_device* uart;
  143. err_code = RT_EOK;
  144. ptr = (rt_uint8_t*)buffer;
  145. uart = (struct serial_device*)dev->user_data;
  146. if (dev->flag & RT_DEVICE_FLAG_INT_TX)
  147. {
  148. /* interrupt mode Tx */
  149. while (uart->int_tx->save_index != uart->int_tx->write_index)
  150. {
  151. /* save on tx buffer */
  152. uart->int_tx->tx_buffer[uart->int_tx->save_index] = *ptr++;
  153. -- size;
  154. /* move to next position */
  155. uart->int_tx->save_index ++;
  156. /* wrap save index */
  157. if (uart->int_tx->save_index >= UART_TX_BUFFER_SIZE)
  158. uart->int_tx->save_index = 0;
  159. }
  160. /* set error code */
  161. if (size > 0)
  162. err_code = -RT_EFULL;
  163. }
  164. else
  165. {
  166. /* polling mode */
  167. while (size)
  168. {
  169. /*
  170. * to be polite with serial console add a line feed
  171. * to the carriage return character
  172. */
  173. if (*ptr == '\n' && (dev->flag & RT_DEVICE_FLAG_STREAM))
  174. {
  175. while (!(uart->uart_device->SSR & SSR_TDRE));
  176. uart->uart_device->TDR = '\r';
  177. }
  178. while (!(uart->uart_device->SSR & SSR_TDRE));
  179. uart->uart_device->TDR = (*ptr & 0x1FF);
  180. ++ptr;
  181. --size;
  182. }
  183. }
  184. /* set error code */
  185. rt_set_errno(err_code);
  186. return (rt_uint32_t)ptr - (rt_uint32_t)buffer;
  187. }
  188. static rt_err_t rt_serial_control (rt_device_t dev, int cmd, void *args)
  189. {
  190. RT_ASSERT(dev != RT_NULL);
  191. switch (cmd)
  192. {
  193. case RT_DEVICE_CTRL_SUSPEND:
  194. /* suspend device */
  195. dev->flag |= RT_DEVICE_FLAG_SUSPENDED;
  196. break;
  197. case RT_DEVICE_CTRL_RESUME:
  198. /* resume device */
  199. dev->flag &= ~RT_DEVICE_FLAG_SUSPENDED;
  200. break;
  201. }
  202. return RT_EOK;
  203. }
  204. /*
  205. * serial register
  206. */
  207. rt_err_t rt_hw_serial_register(rt_device_t device, const char* name,
  208. rt_uint32_t flag, struct serial_device *serial)
  209. {
  210. RT_ASSERT(device != RT_NULL);
  211. device->type = RT_Device_Class_Char;
  212. device->rx_indicate = RT_NULL;
  213. device->tx_complete = RT_NULL;
  214. device->init = rt_serial_init;
  215. device->open = rt_serial_open;
  216. device->close = rt_serial_close;
  217. device->read = rt_serial_read;
  218. device->write = rt_serial_write;
  219. device->control = rt_serial_control;
  220. device->user_data = serial;
  221. /* register a character device */
  222. return rt_device_register(device, name, RT_DEVICE_FLAG_RDWR | flag);
  223. }
  224. /* ISR for serial interrupt */
  225. void rt_hw_serial_isr(rt_device_t device)
  226. {
  227. struct serial_device* uart = (struct serial_device*) device->user_data;
  228. /* interrupt mode receive */
  229. RT_ASSERT(device->flag & RT_DEVICE_FLAG_INT_RX);
  230. /* save on rx buffer */
  231. while (uart->uart_device->SSR & SSR_RDRF)
  232. {
  233. rt_serial_savechar(uart, uart->uart_device->RDR & 0xff);
  234. }
  235. /* invoke callback */
  236. if (device->rx_indicate != RT_NULL)
  237. {
  238. rt_size_t rx_length;
  239. /* get rx length */
  240. rx_length = uart->int_rx->read_index > uart->int_rx->save_index ?
  241. UART_RX_BUFFER_SIZE - uart->int_rx->read_index + uart->int_rx->save_index :
  242. uart->int_rx->save_index - uart->int_rx->read_index;
  243. device->rx_indicate(device, rx_length);
  244. }
  245. }
  246. #ifdef RT_USING_UART0
  247. /* UART0 device driver structure */
  248. #define UART0 FM4_MFS0
  249. struct serial_int_rx uart0_int_rx;
  250. struct serial_device uart0 =
  251. {
  252. UART0,
  253. MFS0_RX_IRQn,
  254. MFS0_TX_IRQn,
  255. &uart0_int_rx,
  256. RT_NULL
  257. };
  258. struct rt_device uart0_device;
  259. void MFS0_RX_IRQHandler(void)
  260. {
  261. /* enter interrupt */
  262. rt_interrupt_enter();
  263. rt_hw_serial_isr(&uart0_device);
  264. /* leave interrupt */
  265. rt_interrupt_leave();
  266. }
  267. #endif /**< #ifdef RT_USING_UART0 */
  268. void rt_hw_serial_init(void)
  269. {
  270. uint32_t APB2_clock = (SystemCoreClock >> (APBC2_PSR_Val & 0x03));
  271. #ifdef RT_USING_UART0
  272. // Initialize ports for MFS0
  273. FM4_GPIO->PFR2 = 0x06u; // P21>SIN0_0, P22>SOT0_0
  274. FM4_GPIO->EPFR07 &= 0xFFFFFF0Ful;
  275. FM4_GPIO->EPFR07 |= 0x00000040ul;
  276. // Initialize MFS to UART asynchronous mode
  277. uart0.uart_device->SMR = SMR_MD_UART | SMR_SOE;;
  278. uart0.uart_device->BGR = (APB2_clock + (BPS/2))/BPS - 1; /* round */
  279. uart0.uart_device->ESCR = ESCR_DATABITS_8;
  280. uart0.uart_device->SCR = SCR_RXE | SCR_TXE | SCR_RIE;
  281. /* register UART0 device */
  282. rt_hw_serial_register(&uart0_device,
  283. "uart0",
  284. RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,
  285. &uart0);
  286. #endif /**< #ifdef RT_USING_UART0 */
  287. }
  288. /*@}*/