uart.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /******************************************************************************
  2. * 2016 ideasX (Tyler Berezowsky)
  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. * Future Work: Modify ISR to handle UART timeout and Errors
  9. *
  10. * Modification history:
  11. * 2014/3/12, v1.0 create this file.
  12. *******************************************************************************/
  13. #include "driver/uart.h"
  14. // UartDev is defined and initialized in rom code.
  15. extern UartDevice UartDev;
  16. static void uart0_rx_intr_handler(void *para);
  17. /******************************************************************************
  18. * FunctionName : uart_config
  19. * Description : Internal used function
  20. * UART0 used for data TX/RX, RX buffer size is 0x100, interrupt enabled
  21. * UART1 just used for debug output
  22. * Parameters : uart_no, use UART0 or UART1 defined ahead
  23. * Returns : NONE
  24. *******************************************************************************/
  25. static void ICACHE_FLASH_ATTR
  26. uart_config(uint8 uart_no)
  27. {
  28. if (uart_no == UART1) {
  29. PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK); // setup gpio2 for UART1
  30. }
  31. else {
  32. ETS_UART_INTR_ATTACH(uart0_rx_intr_handler, &(UartDev.rcv_buff)); // attach uart0_rx_intr_handler ISR
  33. PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); // disable pullup on TX pin
  34. PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); // setup gpio TX pin
  35. /* setup hardware flow control */
  36. #if UART_HW_RTS
  37. PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); //SETUP HW FLOW CONTROL RTS PIN
  38. #endif
  39. #if UART_HW_CTS
  40. PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_U0CTS); //SETUP HW FLOW CONTROL CTS PIN
  41. #endif
  42. }
  43. uart_div_modify(uart_no, UART_CLK_FREQ / (UartDev.baut_rate)); // setup baudrate
  44. WRITE_PERI_REG(UART_CONF0(uart_no), ((UartDev.exist_parity & UART_PARITY_EN_M) << UART_PARITY_EN_S) // setup parity
  45. | ((UartDev.parity & UART_PARITY_M) <<UART_PARITY_S )
  46. | ((UartDev.stop_bits & UART_STOP_BIT_NUM) << UART_STOP_BIT_NUM_S) // setup stop bits
  47. | ((UartDev.data_bits & UART_BIT_NUM) << UART_BIT_NUM_S)); // setup data bits
  48. //clear rx and tx fifo,not ready
  49. SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); // set clear RX FIFO bits
  50. CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); // clear clear RX FIFO bits
  51. if (uart_no == UART0){
  52. WRITE_PERI_REG(UART_CONF1(uart_no),
  53. ((1 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) | // set UART0 full interrupt to 1 bytes
  54. #if UART_HW_RTS
  55. ((110 & UART_RX_FLOW_THRHD) << UART_RX_FLOW_THRHD_S) | // set hardware flow control threshold
  56. UART_RX_FLOW_EN | // set enable hardware flow control flag
  57. #endif
  58. (0x02 & UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S | // setup timeout interrupt
  59. UART_RX_TOUT_EN| // setup enable timeout flag
  60. ((0x10 & UART_TXFIFO_EMPTY_THRHD)<<UART_TXFIFO_EMPTY_THRHD_S)); // setup UART0 empty interrupt threshold to 16 bytes
  61. #if UART_HW_CTS
  62. SET_PERI_REG_MASK( UART_CONF0(uart_no),UART_TX_FLOW_EN); //add this sentense to add a tx flow control via MTCK( CTS )
  63. #endif
  64. //SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UARben affleck in batman suitT_RXFIFO_TOUT_INT_ENA |UART_FRM_ERR_INT_ENA); // enable interrupts for timeout and byte error
  65. }
  66. else{
  67. WRITE_PERI_REG(UART_CONF1(uart_no),((UartDev.rcv_buff.TrigLvl & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S));//TrigLvl default val == 1
  68. }
  69. WRITE_PERI_REG(UART_INT_CLR(uart_no), 0xffff); //clear all interrupts
  70. SET_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_RXFIFO_FULL_INT_ENA); // enable full RX FIFO interrupt
  71. }
  72. /******************************************************************************
  73. * FunctionName : uart1_tx_one_char
  74. * Description : Internal used function
  75. * Use uart1 interface to transfer one char
  76. * Parameters : uint8 TxChar - character to tx
  77. * Returns : OK
  78. *******************************************************************************/
  79. static STATUS ICACHE_FLASH_ATTR
  80. uart1_tx_one_char(uint8 TxChar)
  81. {
  82. while (true) // dump FIFO until empty
  83. {
  84. uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(UART1)) & (UART_TXFIFO_CNT<<UART_TXFIFO_CNT_S);
  85. if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) {
  86. break;
  87. }
  88. }
  89. WRITE_PERI_REG(UART_FIFO(UART1) , TxChar); // add character to FIFO
  90. return OK;
  91. }
  92. /******************************************************************************
  93. * FunctionName : uart1_write_char
  94. * Description : Internal used function
  95. * Do some special deal while tx char is '\r' or '\n'
  96. * Parameters : char c - character to tx
  97. * Returns : NONE
  98. *******************************************************************************/
  99. static void ICACHE_FLASH_ATTR
  100. uart1_write_char(char c)
  101. {
  102. if (c == '\n') {
  103. uart1_tx_one_char('\r');
  104. uart1_tx_one_char('\n');
  105. } else if (c == '\r') {
  106. } else {
  107. uart1_tx_one_char(c);
  108. }
  109. }
  110. /******************************************************************************
  111. * FunctionName : uart0_rx_intr_handler
  112. * Description : Internal used function
  113. * UART0 interrupt handler, add self handle code inside
  114. * Parameters : void *para - point to ETS_UART_INTR_ATTACH's arg
  115. * Returns : NONE
  116. *******************************************************************************/
  117. extern void process_command(char* str);
  118. static void uart0_rx_intr_handler(void *para)
  119. {
  120. /* uart0 and uart1 intr combine togther, when interrupt occur, see reg 0x3ff20020, bit2, bit0 represents
  121. * uart1 and uart0 respectively
  122. */
  123. RcvMsgBuff *pRxBuff = (RcvMsgBuff *)para;
  124. uint8 RcvChar;
  125. // if uart0 fifo isn't full return
  126. if (UART_RXFIFO_FULL_INT_ST == (READ_PERI_REG(UART_INT_ST(UART0)) & UART_RXFIFO_FULL_INT_ST)){
  127. WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR); // clear full FIFO flag
  128. while (READ_PERI_REG(UART_STATUS(UART0)) & (UART_RXFIFO_CNT << UART_RXFIFO_CNT_S)) {
  129. RcvChar = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
  130. /* you can add your handle code below.*/
  131. uart_tx_one_char(RcvChar); // echo recieved character
  132. // NOTE: Lets modify the \r\n sequence to something more american.
  133. // NOTE: Add hook for backspace character...I need to learn the ASCII code
  134. // NOTE: Backspace character should also remove the last two stored characters
  135. // in the buffer. This might be possible by moving the pWritePos back 2 characters?
  136. // if "\r\n" recieved dump UART buffer into str
  137. if (RcvChar == '\r') continue;
  138. if (RcvChar == '\n') {
  139. int len;
  140. char *str;
  141. len = pRxBuff->pWritePos - pRxBuff->pReadPos;
  142. if (len == 0) continue;
  143. if (len < 0) len += RX_BUFF_SIZE;
  144. str = (char*)os_zalloc(len+1);
  145. if (str) {
  146. uint8 loop;
  147. for (loop = 0; loop < len; loop++) str[loop] = uart0_rx_one_char();
  148. str[len] = '\0';
  149. process_command(str);
  150. os_free(str);
  151. }
  152. }
  153. // otherwise add character to buffer
  154. else {
  155. *(pRxBuff->pWritePos) = RcvChar;
  156. pRxBuff->pWritePos++;
  157. }
  158. // if we hit the end of the buffer, loop back to the beginning
  159. if (pRxBuff->pWritePos == (pRxBuff->pRcvMsgBuff + RX_BUFF_SIZE)) {
  160. // overflow ...we may need more error handle here.
  161. pRxBuff->pWritePos = pRxBuff->pRcvMsgBuff ;
  162. }
  163. }
  164. }
  165. }
  166. ICACHE_FLASH_ATTR int uart0_rx_one_char() {
  167. if(UartDev.rcv_buff.pReadPos == UartDev.rcv_buff.pWritePos) return -1;
  168. int ret = *UartDev.rcv_buff.pReadPos;
  169. UartDev.rcv_buff.pReadPos++;
  170. if(UartDev.rcv_buff.pReadPos == (UartDev.rcv_buff.pRcvMsgBuff + RX_BUFF_SIZE)) {
  171. UartDev.rcv_buff.pReadPos = UartDev.rcv_buff.pRcvMsgBuff;
  172. }
  173. return ret;
  174. }
  175. /******************************************************************************
  176. * FunctionName : uart0_tx_buffer
  177. * Description : use uart0 to transfer buffer
  178. * Parameters : uint8 *buf - point to send buffer
  179. * uint16 len - buffer len
  180. * Returns :
  181. *******************************************************************************/
  182. // void ICACHE_FLASH_ATTR uart0_tx_buffer(uint8 *buf, uint16 len)
  183. // {
  184. // uint16 i;
  185. //
  186. // for (i = 0; i < len; i++) {
  187. // uart_tx_one_char(buf[i]);
  188. // }
  189. // }
  190. void ICACHE_FLASH_ATTR uart0_send(const char *str) {
  191. uint8 i = 0;
  192. while (str[i]) {
  193. uart_tx_one_char(str[i]);
  194. i++;
  195. }
  196. }
  197. /******************************************************************************
  198. * FunctionName : uart_init
  199. * Description : user interface for init uart
  200. * Parameters : UartBautRate uart0_br - uart0 bautrate
  201. * UartBautRate uart1_br - uart1 bautrate
  202. * Returns : NONE
  203. *******************************************************************************/
  204. void ICACHE_FLASH_ATTR
  205. uart_init(UartBautRate uart0_br, UartBautRate uart1_br, bool enable_uart1) {
  206. // rom use 74880 baut_rate, here reinitialize
  207. UartDev.baut_rate = uart0_br;
  208. uart_config(UART0);
  209. if (enable_uart1) {
  210. UartDev.baut_rate = uart1_br;
  211. uart_config(UART1);
  212. }
  213. ETS_UART_INTR_ENABLE();
  214. }