uart.c 11 KB

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