uart.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /******************************************************************************
  2. * Copyright 2013-2014 Espressif Systems (Wuxi)
  3. *
  4. * FileName: uart.c
  5. *
  6. * Description: Two UART mode configration and interrupt handler.
  7. * Check your hardware connection while use this mode.
  8. *
  9. * Modification history:
  10. * 2014/3/12, v1.0 create this file.
  11. *******************************************************************************/
  12. #include "ets_sys.h"
  13. #include "osapi.h"
  14. #include "driver/uart.h"
  15. #include "task/task.h"
  16. #include "user_config.h"
  17. #include "user_interface.h"
  18. #include "osapi.h"
  19. #define UART0 0
  20. #define UART1 1
  21. #ifndef FUNC_U0RXD
  22. #define FUNC_U0RXD 0
  23. #endif
  24. #ifndef FUNC_U0CTS
  25. #define FUNC_U0CTS 4
  26. #endif
  27. // For event signalling
  28. static task_handle_t sig = 0;
  29. // UartDev is defined and initialized in rom code.
  30. extern UartDevice UartDev;
  31. static os_timer_t autobaud_timer;
  32. LOCAL void ICACHE_RAM_ATTR
  33. uart0_rx_intr_handler(void *para);
  34. /******************************************************************************
  35. * FunctionName : uart_config
  36. * Description : Internal used function
  37. * UART0 used for data TX/RX, RX buffer size is 0x100, interrupt enabled
  38. * UART1 just used for debug output
  39. * Parameters : uart_no, use UART0 or UART1 defined ahead
  40. * Returns : NONE
  41. *******************************************************************************/
  42. LOCAL void ICACHE_FLASH_ATTR
  43. uart_config(uint8 uart_no)
  44. {
  45. if (uart_no == UART1) {
  46. PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
  47. } else {
  48. /* rcv_buff size if 0x100 */
  49. ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff));
  50. PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
  51. PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
  52. PIN_PULLUP_EN(PERIPHS_IO_MUX_U0RXD_U);
  53. PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD);
  54. }
  55. uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate));
  56. WRITE_PERI_REG(UART_CONF0(uart_no), ((UartDev.exist_parity & UART_PARITY_EN_M) << UART_PARITY_EN_S) //SET BIT AND PARITY MODE
  57. | ((UartDev.parity & UART_PARITY_M) <<UART_PARITY_S )
  58. | ((UartDev.stop_bits & UART_STOP_BIT_NUM) << UART_STOP_BIT_NUM_S)
  59. | ((UartDev.data_bits & UART_BIT_NUM) << UART_BIT_NUM_S));
  60. //clear rx and tx fifo,not ready
  61. SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
  62. CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST);
  63. //set rx fifo trigger
  64. WRITE_PERI_REG(UART_CONF1(uart_no), (UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S);
  65. //clear all interrupt
  66. WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff);
  67. //enable rx_interrupt
  68. SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA);
  69. }
  70. /******************************************************************************
  71. * FunctionName : uart0_alt
  72. * Description : Internal used function
  73. * UART0 pins changed to 13,15 if 'on' is set, else set to normal pins
  74. * Parameters : on - 1 = use alternate pins, 0 = use normal pins
  75. * Returns : NONE
  76. *******************************************************************************/
  77. void ICACHE_FLASH_ATTR
  78. uart0_alt(uint8 on)
  79. {
  80. if (on)
  81. {
  82. PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTDO_U);
  83. PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS);
  84. PIN_PULLUP_EN(PERIPHS_IO_MUX_MTCK_U);
  85. PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_U0CTS);
  86. // now make RTS/CTS behave as TX/RX
  87. IOSWAP |= (1 << IOSWAPU0);
  88. }
  89. else
  90. {
  91. PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
  92. PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
  93. PIN_PULLUP_EN(PERIPHS_IO_MUX_U0RXD_U);
  94. PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD);
  95. // now make RX/TX behave as TX/RX
  96. IOSWAP &= ~(1 << IOSWAPU0);
  97. }
  98. }
  99. /******************************************************************************
  100. * FunctionName : uart_tx_one_char
  101. * Description : Internal used function
  102. * Use uart interface to transfer one char
  103. * Parameters : uint8 TxChar - character to tx
  104. * Returns : OK
  105. *******************************************************************************/
  106. STATUS ICACHE_FLASH_ATTR
  107. uart_tx_one_char(uint8 uart, uint8 TxChar)
  108. {
  109. while (true)
  110. {
  111. uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT<<UART_TXFIFO_CNT_S);
  112. if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) {
  113. break;
  114. }
  115. }
  116. WRITE_PERI_REG(UART_FIFO(uart) , TxChar);
  117. return OK;
  118. }
  119. /******************************************************************************
  120. * FunctionName : uart1_write_char
  121. * Description : Internal used function
  122. * Do some special deal while tx char is '\r' or '\n'
  123. * Parameters : char c - character to tx
  124. * Returns : NONE
  125. *******************************************************************************/
  126. LOCAL void ICACHE_FLASH_ATTR
  127. uart1_write_char(char c)
  128. {
  129. if (c == '\n')
  130. {
  131. uart_tx_one_char(UART1, '\r');
  132. uart_tx_one_char(UART1, '\n');
  133. }
  134. else if (c == '\r')
  135. {
  136. }
  137. else
  138. {
  139. uart_tx_one_char(UART1, c);
  140. }
  141. }
  142. /******************************************************************************
  143. * FunctionName : uart0_tx_buffer
  144. * Description : use uart0 to transfer buffer
  145. * Parameters : uint8 *buf - point to send buffer
  146. * uint16 len - buffer len
  147. * Returns :
  148. *******************************************************************************/
  149. void ICACHE_FLASH_ATTR
  150. uart0_tx_buffer(uint8 *buf, uint16 len)
  151. {
  152. uint16 i;
  153. for (i = 0; i < len; i++)
  154. {
  155. uart_tx_one_char(UART0, buf[i]);
  156. }
  157. }
  158. /******************************************************************************
  159. * FunctionName : uart0_sendStr
  160. * Description : use uart0 to transfer buffer
  161. * Parameters : uint8 *buf - point to send buffer
  162. * uint16 len - buffer len
  163. * Returns :
  164. *******************************************************************************/
  165. void ICACHE_FLASH_ATTR uart0_sendStr(const char *str)
  166. {
  167. while(*str)
  168. {
  169. // uart_tx_one_char(UART0, *str++);
  170. uart0_putc(*str++);
  171. }
  172. }
  173. /******************************************************************************
  174. * FunctionName : uart0_putc
  175. * Description : use uart0 to transfer char
  176. * Parameters : uint8 c - send char
  177. * Returns :
  178. *******************************************************************************/
  179. void ICACHE_FLASH_ATTR uart0_putc(const char c)
  180. {
  181. if (c == '\n')
  182. {
  183. uart_tx_one_char(UART0, '\r');
  184. uart_tx_one_char(UART0, '\n');
  185. }
  186. else if (c == '\r')
  187. {
  188. }
  189. else
  190. {
  191. uart_tx_one_char(UART0, c);
  192. }
  193. }
  194. /******************************************************************************
  195. * FunctionName : uart0_rx_intr_handler
  196. * Description : Internal used function
  197. * UART0 interrupt handler, add self handle code inside
  198. * Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg
  199. * Returns : NONE
  200. *******************************************************************************/
  201. LOCAL void
  202. uart0_rx_intr_handler(void *para)
  203. {
  204. /* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents
  205. * uart1 and uart0 respectively
  206. */
  207. RcvMsgBuff *pRxBuff = (RcvMsgBuff *)para;
  208. uint8 RcvChar;
  209. bool got_input = false;
  210. if (UART_RXFIFO_FULL_INT_ST != (READ_PERI_REG(UART_INT_ST(UART0)) & UART_RXFIFO_FULL_INT_ST)) {
  211. return;
  212. }
  213. WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR);
  214. while (READ_PERI_REG(UART_STATUS(UART0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
  215. RcvChar = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
  216. /* you can add your handle code below.*/
  217. *(pRxBuff->pWritePos) = RcvChar;
  218. // insert here for get one command line from uart
  219. if (RcvChar == '\r' || RcvChar == '\n' ) {
  220. pRxBuff->BuffState = WRITE_OVER;
  221. }
  222. if (pRxBuff->pWritePos == (pRxBuff->pRcvMsgBuff + RX_BUFF_SIZE)) {
  223. // overflow ...we may need more error handle here.
  224. pRxBuff->pWritePos = pRxBuff->pRcvMsgBuff ;
  225. } else {
  226. pRxBuff->pWritePos++;
  227. }
  228. if (pRxBuff->pWritePos == pRxBuff->pReadPos){ // overflow one byte, need push pReadPos one byte ahead
  229. if (pRxBuff->pReadPos == (pRxBuff->pRcvMsgBuff + RX_BUFF_SIZE)) {
  230. pRxBuff->pReadPos = pRxBuff->pRcvMsgBuff ;
  231. } else {
  232. pRxBuff->pReadPos++;
  233. }
  234. }
  235. got_input = true;
  236. }
  237. if (got_input && sig)
  238. task_post_low (sig, false);
  239. }
  240. static void
  241. uart_autobaud_timeout(void *timer_arg)
  242. {
  243. uint32_t uart_no = (uint32_t) timer_arg;
  244. uint32_t divisor = uart_baudrate_detect(uart_no, 1);
  245. static int called_count = 0;
  246. // Shut off after two minutes to stop wasting CPU cycles if insufficient input received
  247. if (called_count++ > 10 * 60 * 2 || divisor) {
  248. os_timer_disarm(&autobaud_timer);
  249. }
  250. if (divisor) {
  251. uart_div_modify(uart_no, divisor);
  252. }
  253. }
  254. static void
  255. uart_init_autobaud(uint32_t uart_no)
  256. {
  257. os_timer_setfn(&autobaud_timer, uart_autobaud_timeout, (void *) uart_no);
  258. os_timer_arm(&autobaud_timer, 100, TRUE);
  259. }
  260. static void
  261. uart_stop_autobaud()
  262. {
  263. os_timer_disarm(&autobaud_timer);
  264. }
  265. /******************************************************************************
  266. * FunctionName : uart_init
  267. * Description : user interface for init uart
  268. * Parameters : UartBautRate uart0_br - uart0 bautrate
  269. * UartBautRate uart1_br - uart1 bautrate
  270. * uint8 task_prio - task priority to signal on input
  271. * os_signal_t sig_input - signal to post
  272. * Returns : NONE
  273. *******************************************************************************/
  274. void ICACHE_FLASH_ATTR
  275. uart_init(UartBautRate uart0_br, UartBautRate uart1_br, os_signal_t sig_input)
  276. {
  277. sig = sig_input;
  278. // rom use 74880 baut_rate, here reinitialize
  279. UartDev.baut_rate = uart0_br;
  280. uart_config(UART0);
  281. UartDev.baut_rate = uart1_br;
  282. uart_config(UART1);
  283. ETS_UART_INTR_ENABLE();
  284. #ifdef BIT_RATE_AUTOBAUD
  285. uart_init_autobaud(0);
  286. #endif
  287. }
  288. void ICACHE_FLASH_ATTR
  289. uart_setup(uint8 uart_no)
  290. {
  291. #ifdef BIT_RATE_AUTOBAUD
  292. uart_stop_autobaud();
  293. #endif
  294. ETS_UART_INTR_DISABLE();
  295. uart_config(uart_no);
  296. ETS_UART_INTR_ENABLE();
  297. }