OVMS3-idf/components/esp32/include/rom/uart.h
Ivan Grokhotkov 508fb79a26 uart: fix uart_tx_wait_idle to wait for fifo empty
In some cases, when data was just written into UART FIFO, transmitter
state could be still zero while the FIFO did contain some data.
This resulted in uart_tx_wait_idle occasionally returning before all
the data was sent out.
Fix by checking both UART transmitter state and TX FIFO count.
2018-10-15 20:08:16 +08:00

420 lines
10 KiB
C

// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ROM_UART_H_
#define _ROM_UART_H_
#include "esp_types.h"
#include "esp_attr.h"
#include "ets_sys.h"
#include "soc/soc.h"
#include "soc/uart_reg.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup uart_apis, uart configuration and communication related apis
* @brief uart apis
*/
/** @addtogroup uart_apis
* @{
*/
#define RX_BUFF_SIZE 0x100
#define TX_BUFF_SIZE 100
//uart int enalbe register ctrl bits
#define UART_RCV_INTEN BIT0
#define UART_TRX_INTEN BIT1
#define UART_LINE_STATUS_INTEN BIT2
//uart int identification ctrl bits
#define UART_INT_FLAG_MASK 0x0E
//uart fifo ctrl bits
#define UART_CLR_RCV_FIFO BIT1
#define UART_CLR_TRX_FIFO BIT2
#define UART_RCVFIFO_TRG_LVL_BITS BIT6
//uart line control bits
#define UART_DIV_LATCH_ACCESS_BIT BIT7
//uart line status bits
#define UART_RCV_DATA_RDY_FLAG BIT0
#define UART_RCV_OVER_FLOW_FLAG BIT1
#define UART_RCV_PARITY_ERR_FLAG BIT2
#define UART_RCV_FRAME_ERR_FLAG BIT3
#define UART_BRK_INT_FLAG BIT4
#define UART_TRX_FIFO_EMPTY_FLAG BIT5
#define UART_TRX_ALL_EMPTY_FLAG BIT6 // include fifo and shift reg
#define UART_RCV_ERR_FLAG BIT7
//send and receive message frame head
#define FRAME_FLAG 0x7E
typedef enum {
UART_LINE_STATUS_INT_FLAG = 0x06,
UART_RCV_FIFO_INT_FLAG = 0x04,
UART_RCV_TMOUT_INT_FLAG = 0x0C,
UART_TXBUFF_EMPTY_INT_FLAG = 0x02
} UartIntType; //consider bit0 for int_flag
typedef enum {
RCV_ONE_BYTE = 0x0,
RCV_FOUR_BYTE = 0x1,
RCV_EIGHT_BYTE = 0x2,
RCV_FOURTEEN_BYTE = 0x3
} UartRcvFifoTrgLvl;
typedef enum {
FIVE_BITS = 0x0,
SIX_BITS = 0x1,
SEVEN_BITS = 0x2,
EIGHT_BITS = 0x3
} UartBitsNum4Char;
typedef enum {
ONE_STOP_BIT = 1,
ONE_HALF_STOP_BIT = 2,
TWO_STOP_BIT = 3
} UartStopBitsNum;
typedef enum {
NONE_BITS = 0,
ODD_BITS = 2,
EVEN_BITS = 3
} UartParityMode;
typedef enum {
STICK_PARITY_DIS = 0,
STICK_PARITY_EN = 2
} UartExistParity;
typedef enum {
BIT_RATE_9600 = 9600,
BIT_RATE_19200 = 19200,
BIT_RATE_38400 = 38400,
BIT_RATE_57600 = 57600,
BIT_RATE_115200 = 115200,
BIT_RATE_230400 = 230400,
BIT_RATE_460800 = 460800,
BIT_RATE_921600 = 921600
} UartBautRate;
typedef enum {
NONE_CTRL,
HARDWARE_CTRL,
XON_XOFF_CTRL
} UartFlowCtrl;
typedef enum {
EMPTY,
UNDER_WRITE,
WRITE_OVER
} RcvMsgBuffState;
typedef struct {
uint8_t *pRcvMsgBuff;
uint8_t *pWritePos;
uint8_t *pReadPos;
uint8_t TrigLvl;
RcvMsgBuffState BuffState;
} RcvMsgBuff;
typedef struct {
uint32_t TrxBuffSize;
uint8_t *pTrxBuff;
} TrxMsgBuff;
typedef enum {
BAUD_RATE_DET,
WAIT_SYNC_FRM,
SRCH_MSG_HEAD,
RCV_MSG_BODY,
RCV_ESC_CHAR,
} RcvMsgState;
typedef struct {
UartBautRate baut_rate;
UartBitsNum4Char data_bits;
UartExistParity exist_parity;
UartParityMode parity; // chip size in byte
UartStopBitsNum stop_bits;
UartFlowCtrl flow_ctrl;
uint8_t buff_uart_no; //indicate which uart use tx/rx buffer
uint8_t tx_uart_no;
RcvMsgBuff rcv_buff;
// TrxMsgBuff trx_buff;
RcvMsgState rcv_state;
int received;
} UartDevice;
/**
* @brief Init uart device struct value and reset uart0/uart1 rx.
* Please do not call this function in SDK.
*
* @param None
*
* @return None
*/
void uartAttach(void);
/**
* @brief Init uart0 or uart1 for UART download booting mode.
* Please do not call this function in SDK.
*
* @param uint8_t uart_no : 0 for UART0, else for UART1.
*
* @param uint32_t clock : clock used by uart module, to adjust baudrate.
*
* @return None
*/
void Uart_Init(uint8_t uart_no, uint32_t clock);
/**
* @brief Modify uart baudrate.
* This function will reset RX/TX fifo for uart.
*
* @param uint8_t uart_no : 0 for UART0, 1 for UART1.
*
* @param uint32_t DivLatchValue : (clock << 4)/baudrate.
*
* @return None
*/
void uart_div_modify(uint8_t uart_no, uint32_t DivLatchValue);
/**
* @brief Init uart0 or uart1 for UART download booting mode.
* Please do not call this function in SDK.
*
* @param uint8_t uart_no : 0 for UART0, 1 for UART1.
*
* @param uint8_t is_sync : 0, only one UART module, easy to detect, wait until detected;
* 1, two UART modules, hard to detect, detect and return.
*
* @return None
*/
int uart_baudrate_detect(uint8_t uart_no, uint8_t is_sync);
/**
* @brief Switch printf channel of uart_tx_one_char.
* Please do not call this function when printf.
*
* @param uint8_t uart_no : 0 for UART0, 1 for UART1.
*
* @return None
*/
void uart_tx_switch(uint8_t uart_no);
/**
* @brief Switch message exchange channel for UART download booting.
* Please do not call this function in SDK.
*
* @param uint8_t uart_no : 0 for UART0, 1 for UART1.
*
* @return None
*/
void uart_buff_switch(uint8_t uart_no);
/**
* @brief Output a char to printf channel, wait until fifo not full.
*
* @param None
*
* @return OK.
*/
STATUS uart_tx_one_char(uint8_t TxChar);
/**
* @brief Output a char to message exchange channel, wait until fifo not full.
* Please do not call this function in SDK.
*
* @param None
*
* @return OK.
*/
STATUS uart_tx_one_char2(uint8_t TxChar);
/**
* @brief Wait until uart tx full empty.
*
* @param uint8_t uart_no : 0 for UART0, 1 for UART1.
*
* @return None.
*/
void uart_tx_flush(uint8_t uart_no);
/**
* @brief Wait until uart tx full empty and the last char send ok.
*
* @param uart_no : 0 for UART0, 1 for UART1, 2 for UART2
*
* The function defined in ROM code has a bug, so we define the correct version
* here for compatibility.
*/
static inline void IRAM_ATTR uart_tx_wait_idle(uint8_t uart_no) {
uint32_t status;
do {
status = READ_PERI_REG(UART_STATUS_REG(uart_no));
/* either tx count or state is non-zero */
} while ((status & (UART_ST_UTX_OUT_M | UART_TXFIFO_CNT_M)) != 0);
}
/**
* @brief Get an input char from message channel.
* Please do not call this function in SDK.
*
* @param uint8_t *pRxChar : the pointer to store the char.
*
* @return OK for successful.
* FAIL for failed.
*/
STATUS uart_rx_one_char(uint8_t *pRxChar);
/**
* @brief Get an input char from message channel, wait until successful.
* Please do not call this function in SDK.
*
* @param None
*
* @return char : input char value.
*/
char uart_rx_one_char_block(void);
/**
* @brief Get an input string line from message channel.
* Please do not call this function in SDK.
*
* @param uint8_t *pString : the pointer to store the string.
*
* @param uint8_t MaxStrlen : the max string length, incude '\0'.
*
* @return OK.
*/
STATUS UartRxString(uint8_t *pString, uint8_t MaxStrlen);
/**
* @brief Process uart recevied information in the interrupt handler.
* Please do not call this function in SDK.
*
* @param void *para : the message receive buffer.
*
* @return None
*/
void uart_rx_intr_handler(void *para);
/**
* @brief Get an char from receive buffer.
* Please do not call this function in SDK.
*
* @param RcvMsgBuff *pRxBuff : the pointer to the struct that include receive buffer.
*
* @param uint8_t *pRxByte : the pointer to store the char.
*
* @return OK for successful.
* FAIL for failed.
*/
STATUS uart_rx_readbuff( RcvMsgBuff *pRxBuff, uint8_t *pRxByte);
/**
* @brief Get all chars from receive buffer.
* Please do not call this function in SDK.
*
* @param uint8_t *pCmdLn : the pointer to store the string.
*
* @return OK for successful.
* FAIL for failed.
*/
STATUS UartGetCmdLn(uint8_t *pCmdLn);
/**
* @brief Get uart configuration struct.
* Please do not call this function in SDK.
*
* @param None
*
* @return UartDevice * : uart configuration struct pointer.
*/
UartDevice *GetUartDevice(void);
/**
* @brief Send an packet to download tool, with SLIP escaping.
* Please do not call this function in SDK.
*
* @param uint8_t *p : the pointer to output string.
*
* @param int len : the string length.
*
* @return None.
*/
void send_packet(uint8_t *p, int len);
/**
* @brief Receive an packet from download tool, with SLIP escaping.
* Please do not call this function in SDK.
*
* @param uint8_t *p : the pointer to input string.
*
* @param int len : If string length > len, the string will be truncated.
*
* @param uint8_t is_sync : 0, only one UART module;
* 1, two UART modules.
*
* @return int : the length of the string.
*/
int recv_packet(uint8_t *p, int len, uint8_t is_sync);
/**
* @brief Send an packet to download tool, with SLIP escaping.
* Please do not call this function in SDK.
*
* @param uint8_t *pData : the pointer to input string.
*
* @param uint16_t DataLen : the string length.
*
* @return OK for successful.
* FAIL for failed.
*/
STATUS SendMsg(uint8_t *pData, uint16_t DataLen);
/**
* @brief Receive an packet from download tool, with SLIP escaping.
* Please do not call this function in SDK.
*
* @param uint8_t *pData : the pointer to input string.
*
* @param uint16_t MaxDataLen : If string length > MaxDataLen, the string will be truncated.
*
* @param uint8_t is_sync : 0, only one UART module;
* 1, two UART modules.
*
* @return OK for successful.
* FAIL for failed.
*/
STATUS RcvMsg(uint8_t *pData, uint16_t MaxDataLen, uint8_t is_sync);
extern UartDevice UartDev;
/**
* @}
*/
#ifdef __cplusplus
}
#endif
#endif /* _ROM_UART_H_ */