/* * Driver file for ESP8266 UART, works with the SDK. */ #include "uart_driver.h" #include #include "ets_sys.h" #include "osapi.h" #include "mem.h" #include "os_type.h" #include "ets_sys_extra.h" #include "uart_register.h" //======================================================== void FLASH_FN UART_SetWordLength(UARTn uart_no, UartBitsNum4Char len) { SET_PERI_REG_BITS(UART_CONF0(uart_no), UART_BIT_NUM, len, UART_BIT_NUM_S); } void FLASH_FN UART_SetStopBits(UARTn uart_no, UartStopBitsNum bit_num) { SET_PERI_REG_BITS(UART_CONF0(uart_no), UART_STOP_BIT_NUM, bit_num, UART_STOP_BIT_NUM_S); } void FLASH_FN UART_SetLineInverse(UARTn uart_no, UART_LineLevelInverse inverse_mask) { CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_LINE_INV_MASK); SET_PERI_REG_MASK(UART_CONF0(uart_no), inverse_mask); } void FLASH_FN UART_SetParity(UARTn uart_no, UartParityMode Parity_mode) { CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_PARITY | UART_PARITY_EN); if (Parity_mode == PARITY_NONE) { } else { SET_PERI_REG_MASK(UART_CONF0(uart_no), Parity_mode | UART_PARITY_EN); } } void FLASH_FN UART_SetBaudrate(UARTn uart_no, uint32 baud_rate) { uart_div_modify(uart_no, UART_CLK_FREQ / baud_rate); } void FLASH_FN UART_SetFlowCtrl(UARTn uart_no, UART_HwFlowCtrl flow_ctrl, uint8 rx_thresh) { if (flow_ctrl & USART_HWFlow_RTS) { PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_U0RTS); SET_PERI_REG_BITS(UART_CONF1(uart_no), UART_RX_FLOW_THRHD, rx_thresh, UART_RX_FLOW_THRHD_S); SET_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN); } else { CLEAR_PERI_REG_MASK(UART_CONF1(uart_no), UART_RX_FLOW_EN); } if (flow_ctrl & USART_HWFlow_CTS) { PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS); SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN); } else { CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_TX_FLOW_EN); } } void FLASH_FN UART_WaitTxFifoEmpty(UARTn uart_no , uint32 time_out_us) //do not use if tx flow control enabled { uint32 t_s = system_get_time(); while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S)) { if ((system_get_time() - t_s) > time_out_us) { break; } system_soft_wdt_feed(); } } bool FLASH_FN UART_CheckOutputFinished(UARTn uart_no, uint32 time_out_us) { uint32 t_start = system_get_time(); uint8 tx_fifo_len; while (1) { tx_fifo_len = UART_TxQueLen(uart_no); // TODO If using output circbuf, check if empty if (tx_fifo_len == 0) { return TRUE; } if (system_get_time() - t_start > time_out_us) { return FALSE; } system_soft_wdt_feed(); } } void FLASH_FN UART_ResetFifo(UARTn uart_no) { SET_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_RXFIFO_RST | UART_TXFIFO_RST); } void FLASH_FN UART_ClearIntrStatus(UARTn uart_no, uint32 clr_mask) { WRITE_PERI_REG(UART_INT_CLR(uart_no), clr_mask); } void FLASH_FN UART_SetIntrEna(UARTn uart_no, uint32 ena_mask) { SET_PERI_REG_MASK(UART_INT_ENA(uart_no), ena_mask); } LOCAL void u0_putc_crlf(char c) { UART_WriteCharCRLF(UART0, (u8)c, UART_TIMEOUT_US); } LOCAL void u1_putc_crlf(char c) { UART_WriteCharCRLF(UART1, (u8)c, UART_TIMEOUT_US); } void FLASH_FN UART_SetPrintPort(UARTn uart_no) { if (uart_no == UART0) { os_install_putc1((void *)u0_putc_crlf); } else { os_install_putc1((void *)u1_putc_crlf); } } // -------------- Custom UART functions ------------------------- // !!! write handlers are not ICACHE_FLASH_ATTR -> can be used in IRQ !!! /** * @brief Write a char to UART. * @param uart_no * @param c * @param timeout_us - how long to max wait for space in FIFO. * @return write success */ STATUS UART_WriteChar(UARTn uart_no, uint8 c, uint32 timeout_us) { if (timeout_us == 0) { timeout_us = UART_TIMEOUT_US; } uint32 t_s = system_get_time(); while ((system_get_time() - t_s) < timeout_us) { uint8 fifo_cnt = UART_TxQueLen(uart_no); if (fifo_cnt < UART_TX_FULL_THRESH_VAL) { WRITE_PERI_REG(UART_FIFO(uart_no), c); return OK; } system_soft_wdt_feed(); } return FAIL; } /** * @brief Write a char to UART, translating LF to CRLF and discarding CR. * @param uart_no * @param c * @param timeout_us - how long to max wait for space in FIFO. * @return write success */ STATUS UART_WriteCharCRLF(UARTn uart_no, uint8 c, uint32 timeout_us) { STATUS st; if (c == '\r') { return OK; } else if (c == '\n') { st = UART_WriteChar(uart_no, '\r', timeout_us); if (st != OK) return st; st = UART_WriteChar(uart_no, '\n', timeout_us); return st; } else { return UART_WriteChar(uart_no, c, timeout_us); } } /** * @brief Send a string to UART. * @param uart_no * @param str * @param timeout_us - how long to max wait for space in FIFO. * @return write success */ STATUS UART_WriteString(UARTn uart_no, const char *str, uint32 timeout_us) { while (*str) { STATUS suc = UART_WriteChar(uart_no, (u8) * str++, timeout_us); if (suc != OK) return suc; } return OK; } /** * @brief Send a buffer * @param uart_no * @param buffer - buffer to send * @param len - buffer size * @param timeout_us - how long to max wait for space in FIFO. * @return write success */ STATUS UART_WriteBuffer(UARTn uart_no, const uint8 *buffer, size_t len, uint32 timeout_us) { for (size_t i = 0; i < len; i++) { STATUS suc = UART_WriteChar(uart_no, (u8) * buffer++, timeout_us); if (suc != OK) return suc; } return OK; }