esp8266-std/driver/uart.c

293 lines
8.5 KiB
C
Raw Permalink Normal View History

2018-11-23 01:43:17 +00:00
/*
* Copyright (C) 2014 -2019 Espressif System
*
*/
#include "esp_common.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "freertos/semphr.h"
#include "uart.h"
#include "cfg.h"
#include "log.h"
#include "freertos/timers.h"
static xSemaphoreHandle uart_sema = NULL;
static ne_uart_recv_t uart_recv;
LOCAL void uart0_rx_intr_handler(void *para);
LOCAL STATUS
uart_tx_one_char(uint8 uart, uint8 TxChar)
{
while (true) {
uint32 fifo_cnt = READ_PERI_REG(UART_STATUS(uart)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S);
if ((fifo_cnt >> UART_TXFIFO_CNT_S & UART_TXFIFO_CNT) < 126) {
break;
}
}
WRITE_PERI_REG(UART_FIFO(uart) , TxChar);
return OK;
}
LOCAL void
uart1_write_char(char c)
{
if (c == '\n') {
uart_tx_one_char(UART1, '\r');
uart_tx_one_char(UART1, '\n');
} else if (c == '\r') {
} else {
uart_tx_one_char(UART1, c);
}
}
LOCAL void
uart0_write_char(char c)
{
if (c == '\n') {
uart_tx_one_char(UART0, '\r');
uart_tx_one_char(UART0, '\n');
} else if (c == '\r') {
} else {
uart_tx_one_char(UART0, c);
}
}
void ICACHE_FLASH_ATTR
uart_tx_str(uint8 uart,uint8* str)
{
if(str == NULL) {
return;
}
while(*str != '\0') {
uart_tx_one_char(uart,*str);
str++;
}
}
void ICACHE_FLASH_ATTR
uart_tx_buf(uint8 uart,uint8* buf,int32 len)
{
int32 loop = 0;
if((buf == NULL) || (len <= 0)) {
return;
}
for(loop = 0;loop < len;loop++) {
uart_tx_one_char(uart,buf[loop]);
}
}
void ICACHE_FLASH_ATTR
UART_SetWordLength(UART_Port uart_no, UART_WordLength len)
{
SET_PERI_REG_BITS(UART_CONF0(uart_no), UART_BIT_NUM, len, UART_BIT_NUM_S);
}
void ICACHE_FLASH_ATTR
UART_SetStopBits(UART_Port uart_no, UART_StopBits bit_num)
{
SET_PERI_REG_BITS(UART_CONF0(uart_no), UART_STOP_BIT_NUM, bit_num, UART_STOP_BIT_NUM_S);
}
void ICACHE_FLASH_ATTR
UART_SetLineInverse(UART_Port 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 ICACHE_FLASH_ATTR
UART_SetParity(UART_Port uart_no, UART_ParityMode Parity_mode)
{
CLEAR_PERI_REG_MASK(UART_CONF0(uart_no), UART_PARITY | UART_PARITY_EN);
if (Parity_mode == USART_Parity_None) {
} else {
SET_PERI_REG_MASK(UART_CONF0(uart_no), Parity_mode | UART_PARITY_EN);
}
}
void ICACHE_FLASH_ATTR
UART_SetBaudrate(UART_Port uart_no, uint32 baud_rate)
{
uart_div_modify(uart_no, UART_CLK_FREQ / baud_rate);
}
//only when USART_HardwareFlowControl_RTS is set , will the rx_thresh value be set.
void ICACHE_FLASH_ATTR
UART_SetFlowCtrl(UART_Port uart_no, UART_HwFlowCtrl flow_ctrl, uint8 rx_thresh)
{
if (flow_ctrl & USART_HardwareFlowControl_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_HardwareFlowControl_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 ICACHE_FLASH_ATTR
UART_WaitTxFifoEmpty(UART_Port uart_no) //do not use if tx flow control enabled
{
while (READ_PERI_REG(UART_STATUS(uart_no)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S));
// <20><><EFBFBD>ü<EFBFBD><C3BC><EFBFBD>
uint32 value = READ_PERI_REG(UART_CLKDIV(uart_no));
value = UART_CLK_FREQ/value;
value = (10*1000000)/value;
os_delay_us(value);
}
void ICACHE_FLASH_ATTR
UART_ResetFifo(UART_Port 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 ICACHE_FLASH_ATTR
UART_ClearIntrStatus(UART_Port uart_no, uint32 clr_mask)
{
WRITE_PERI_REG(UART_INT_CLR(uart_no), clr_mask);
}
void ICACHE_FLASH_ATTR
UART_SetIntrEna(UART_Port uart_no, uint32 ena_mask)
{
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), ena_mask);
}
void ICACHE_FLASH_ATTR
UART_intr_handler_register(void *fn)
{
_xt_isr_attach(ETS_UART_INUM, fn,NULL);
}
void ICACHE_FLASH_ATTR
UART_SetPrintPort(UART_Port uart_no)
{
if (uart_no == 1) {
os_install_putc1(uart1_write_char);
} else {
os_install_putc1(uart0_write_char);
}
}
void ICACHE_FLASH_ATTR
UART_ParamConfig(UART_Port uart_no, UART_ConfigTypeDef *pUARTConfig)
{
if (uart_no == UART1) {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
} else {
_xt_isr_attach(ETS_UART_INUM, uart0_rx_intr_handler,NULL);
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD);
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
}
UART_SetFlowCtrl(uart_no, pUARTConfig->flow_ctrl, pUARTConfig->UART_RxFlowThresh);
UART_SetBaudrate(uart_no, pUARTConfig->baud_rate);
WRITE_PERI_REG(UART_CONF0(uart_no),
((pUARTConfig->parity == USART_Parity_None) ? 0x0 : (UART_PARITY_EN | pUARTConfig->parity))
| (pUARTConfig->stop_bits << UART_STOP_BIT_NUM_S)
| (pUARTConfig->data_bits << UART_BIT_NUM_S)
| ((pUARTConfig->flow_ctrl & USART_HardwareFlowControl_CTS) ? UART_TX_FLOW_EN : 0x0)
| pUARTConfig->UART_InverseMask);
UART_ResetFifo(uart_no);
}
void ICACHE_FLASH_ATTR
UART_IntrConfig(UART_Port uart_no, UART_IntrConfTypeDef *pUARTIntrConf)
{
uint32 reg_val = 0;
UART_ClearIntrStatus(uart_no, UART_INTR_MASK);
reg_val = READ_PERI_REG(UART_CONF1(uart_no)) & ~((UART_RX_FLOW_THRHD << UART_RX_FLOW_THRHD_S) | UART_RX_FLOW_EN) ;
reg_val |= ((pUARTIntrConf->UART_IntrEnMask & UART_RXFIFO_TOUT_INT_ENA) ?
((((pUARTIntrConf->UART_RX_TimeOutIntrThresh)&UART_RX_TOUT_THRHD) << UART_RX_TOUT_THRHD_S) | UART_RX_TOUT_EN) : 0);
reg_val |= ((pUARTIntrConf->UART_IntrEnMask & UART_RXFIFO_FULL_INT_ENA) ?
(((pUARTIntrConf->UART_RX_FifoFullIntrThresh)&UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) : 0);
reg_val |= ((pUARTIntrConf->UART_IntrEnMask & UART_TXFIFO_EMPTY_INT_ENA) ?
(((pUARTIntrConf->UART_TX_FifoEmptyIntrThresh)&UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S) : 0);
WRITE_PERI_REG(UART_CONF1(uart_no), reg_val);
CLEAR_PERI_REG_MASK(UART_INT_ENA(uart_no), UART_INTR_MASK);
SET_PERI_REG_MASK(UART_INT_ENA(uart_no), pUARTIntrConf->UART_IntrEnMask);
}
LOCAL void IRAM_ATTR
uart0_rx_intr_handler(void *para)
{
uint8 RcvChar;
uint8 uart_no = UART0;
uint8 fifo_len = 0;
uint8 buf_idx = 0;
portBASE_TYPE xHigherPriorityTaskWoken;
uint32 uart_intr_status = READ_PERI_REG(UART_INT_ST(uart_no)) ;
if (UART_FRM_ERR_INT_ST == (uart_intr_status & UART_FRM_ERR_INT_ST)) {
WRITE_PERI_REG(UART_INT_CLR(uart_no), UART_FRM_ERR_INT_CLR);
} else if ((UART_RXFIFO_TOUT_INT_ST == (uart_intr_status & UART_RXFIFO_TOUT_INT_ST))|| (UART_RXFIFO_FULL_INT_ST == (uart_intr_status & UART_RXFIFO_FULL_INT_ST))) {
fifo_len = (READ_PERI_REG(UART_STATUS(UART0)) >> UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT;
buf_idx = 0;
// start
WRITE_PERI_REG(0x60000914,0x73);
for(buf_idx = 0;(buf_idx < fifo_len) && (uart_recv.recv_len < UART_BUF_SIZE);buf_idx++) {
uart_recv.uart_buf[uart_recv.recv_len++] = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
}
for ( ;buf_idx < fifo_len; buf_idx++) {
RcvChar = READ_PERI_REG(UART_FIFO(UART0)) & 0xFF;
}
WRITE_PERI_REG(0x60000914,0x73);
WRITE_PERI_REG(UART_INT_CLR(UART0), UART_RXFIFO_FULL_INT_CLR | UART_RXFIFO_TOUT_INT_CLR);
} else {
WRITE_PERI_REG(UART_INT_CLR(uart_no), uart_intr_status | UART_CTS_CHG_INT_CLR);
}
}
ne_uart_recv_t *ne_get_uart_recv_info(void)
{
return &uart_recv;
}
void ne_adjust_recv_info(uint32 pos)
{
ETS_UART_INTR_DISABLE();
memcpy(uart_recv.uart_buf, uart_recv.uart_buf + pos, uart_recv.recv_len - pos);
uart_recv.recv_len -= pos;
ETS_UART_INTR_ENABLE();
}