uart.c 13 KB

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