1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

rewrite HardwareSerial code for UART0 + UART1 support in ESP8266

This commit is contained in:
Markus Sattler 2015-04-01 22:47:13 +02:00
parent 88698ea1c6
commit 1ee7ecdaa2
2 changed files with 655 additions and 401 deletions

View File

@ -17,8 +17,10 @@
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
Modified 31 March 2015 by Markus Sattler (rewrite the code for UART0 + UART1 support in ESP8266)
*/
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -37,219 +39,428 @@ extern "C" {
#include "HardwareSerial.h" #include "HardwareSerial.h"
HardwareSerial Serial;
uart_t* uart0_init(int baud_rate);
void uart0_set_baudrate(uart_t* uart, int baud_rate);
int uart0_get_baudrate(uart_t* uart);
void uart0_uninit(uart_t* uart);
void uart0_transmit(uart_t* uart, const char* buf, size_t size); // may block on TX fifo
void uart0_wait_for_transmit(uart_t* uart);
void uart0_transmit_char(uart_t* uart, char c); // does not block, but character will be lost if FIFO is full
void uart_set_debug(bool enabled);
bool uart_get_debug();
struct uart_
{
int baud_rate;
};
#define UART_TX_FIFO_SIZE 0x80 #define UART_TX_FIFO_SIZE 0x80
void ICACHE_FLASH_ATTR uart0_interrupt_handler(uart_t* uart) /**
{ * UART GPIOs
uint32_t status = READ_PERI_REG(UART_INT_ST(0)); *
if (status & UART_RXFIFO_FULL_INT_ST) * UART0 TX: 1 or 2
{ * UART0 RX: 3
while(true) *
{ * UART0 SWAP TX: 15
int rx_count = (READ_PERI_REG(UART_STATUS(0)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT; * UART0 SWAP RX: 13
if (!rx_count) *
break; *
* UART1 TX: 7 (NC) or 2
* UART1 RX: 8 (NC)
*
* UART1 SWAP TX: 11 (NC)
* UART1 SWAP RX: 6 (NC)
*
* NC = Not Connected to Module Pads --> No Access
*
*/
while(rx_count--)
{ // ####################################################################################################
// ####################################################################################################
// ####################################################################################################
HardwareSerial Serial(UART0);
HardwareSerial Serial1(UART1);
// ####################################################################################################
// ####################################################################################################
// ####################################################################################################
void uart_interrupt_handler(uart_t* uart);
void uart_wait_for_tx_fifo(uart_t* uart, size_t size_needed);
size_t uart_get_tx_fifo_room(uart_t* uart);
void uart_wait_for_transmit(uart_t* uart);
void uart_transmit_char(uart_t* uart, char c);
void uart_transmit(uart_t* uart, const char* buf, size_t size);
void uart_flush(uart_t* uart);
void uart_interrupt_enable(uart_t* uart);
void uart_interrupt_disable(uart_t* uart);
void uart_arm_tx_interrupt(uart_t* uart);
void uart_disarm_tx_interrupt(uart_t* uart);
void uart_set_baudrate(uart_t* uart, int baud_rate);
int uart_get_baudrate(uart_t* uart);
uart_t* uart_init(UARTnr_t uart_nr, int baudrate);
void uart_uninit(uart_t* uart);
void uart_swap(uart_t* uart);
void uart_ignore_char(char c);
void uart0_write_char(char c);
void uart1_write_char(char c);
void uart_set_debug(UARTnr_t uart_nr);
UARTnr_t uart_get_debug();
// ####################################################################################################
// ####################################################################################################
// ####################################################################################################
void ICACHE_FLASH_ATTR uart_interrupt_handler(uart_t* uart) {
// -------------- UART 0 --------------
uint32_t status = READ_PERI_REG(UART_INT_ST(0));
if(Serial.isRxEnabled()) {
if(status & UART_RXFIFO_FULL_INT_ST) {
while(true) {
int rx_count = (READ_PERI_REG(UART_STATUS(0)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT;
if(!rx_count) break;
while(rx_count--) {
char c = READ_PERI_REG(UART_FIFO(0)) & 0xFF; char c = READ_PERI_REG(UART_FIFO(0)) & 0xFF;
Serial._rx_complete_irq(c); Serial._rx_complete_irq(c);
} }
} }
WRITE_PERI_REG(UART_INT_CLR(0), UART_RXFIFO_FULL_INT_CLR); WRITE_PERI_REG(UART_INT_CLR(0), UART_RXFIFO_FULL_INT_CLR);
} }
if (status & UART_TXFIFO_EMPTY_INT_ST) }
{ if(Serial.isTxEnabled()) {
if(status & UART_TXFIFO_EMPTY_INT_ST) {
WRITE_PERI_REG(UART_INT_CLR(0), UART_TXFIFO_EMPTY_INT_CLR); WRITE_PERI_REG(UART_INT_CLR(0), UART_TXFIFO_EMPTY_INT_CLR);
Serial._tx_empty_irq(); Serial._tx_empty_irq();
} }
} }
void ICACHE_FLASH_ATTR uart0_wait_for_tx_fifo(size_t size_needed) // -------------- UART 1 --------------
{
while (true) status = READ_PERI_REG(UART_INT_ST(1));
{ if(Serial1.isRxEnabled()) {
size_t tx_count = (READ_PERI_REG(UART_STATUS(0)) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT; if(status & UART_RXFIFO_FULL_INT_ST) {
if (tx_count <= (UART_TX_FIFO_SIZE - size_needed)) while(true) {
break; int rx_count = (READ_PERI_REG(UART_STATUS(1)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT;
if(!rx_count) break;
while(rx_count--) {
char c = READ_PERI_REG(UART_FIFO(1)) & 0xFF;
Serial1._rx_complete_irq(c);
}
}
WRITE_PERI_REG(UART_INT_CLR(1), UART_RXFIFO_FULL_INT_CLR);
}
}
if(Serial1.isTxEnabled()) {
status = READ_PERI_REG(UART_INT_ST(1));
if(status & UART_TXFIFO_EMPTY_INT_ST) {
WRITE_PERI_REG(UART_INT_CLR(1), UART_TXFIFO_EMPTY_INT_CLR);
Serial1._tx_empty_irq();
}
} }
} }
size_t ICACHE_FLASH_ATTR uart0_get_tx_fifo_room() // ####################################################################################################
{
return UART_TX_FIFO_SIZE - ((READ_PERI_REG(UART_STATUS(0)) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT); void ICACHE_FLASH_ATTR uart_wait_for_tx_fifo(uart_t* uart, size_t size_needed) {
if(uart->txEnabled) {
while(true) {
size_t tx_count = (READ_PERI_REG(UART_STATUS(uart->uart_nr)) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT;
if(tx_count <= (UART_TX_FIFO_SIZE - size_needed)) break;
}
}
} }
void ICACHE_FLASH_ATTR uart0_wait_for_transmit(uart_t* uart) size_t ICACHE_FLASH_ATTR uart_get_tx_fifo_room(uart_t* uart) {
{ if(uart->txEnabled) {
uart0_wait_for_tx_fifo(UART_TX_FIFO_SIZE); return UART_TX_FIFO_SIZE - ((READ_PERI_REG(UART_STATUS(uart->uart_nr)) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT);
}
return 0;
} }
void ICACHE_FLASH_ATTR uart0_transmit_char(uart_t* uart, char c) void ICACHE_FLASH_ATTR uart_wait_for_transmit(uart_t* uart) {
{ if(uart->txEnabled) {
WRITE_PERI_REG(UART_FIFO(0), c); uart_wait_for_tx_fifo(uart, UART_TX_FIFO_SIZE);
}
} }
void ICACHE_FLASH_ATTR uart0_transmit(uart_t* uart, const char* buf, size_t size) void ICACHE_FLASH_ATTR uart_transmit_char(uart_t* uart, char c) {
{ if(uart->txEnabled) {
while (size) WRITE_PERI_REG(UART_FIFO(uart->uart_nr), c);
{ }
}
void ICACHE_FLASH_ATTR uart_transmit(uart_t* uart, const char* buf, size_t size) {
if(uart->txEnabled) {
while(size) {
size_t part_size = (size > UART_TX_FIFO_SIZE) ? UART_TX_FIFO_SIZE : size; size_t part_size = (size > UART_TX_FIFO_SIZE) ? UART_TX_FIFO_SIZE : size;
size -= part_size; size -= part_size;
uart0_wait_for_tx_fifo(part_size); uart_wait_for_tx_fifo(uart, part_size);
for(; part_size; --part_size, ++buf) for(; part_size; --part_size, ++buf)
WRITE_PERI_REG(UART_FIFO(0), *buf); WRITE_PERI_REG(UART_FIFO(uart->uart_nr), *buf);
}
} }
} }
void ICACHE_FLASH_ATTR uart0_flush(uart_t* uart) void ICACHE_FLASH_ATTR uart_flush(uart_t* uart) {
{ uint32_t tmp = 0x00000000;
SET_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST | UART_TXFIFO_RST);
CLEAR_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST | UART_TXFIFO_RST); if(uart->rxEnabled) {
tmp |= UART_RXFIFO_RST;
} }
void ICACHE_FLASH_ATTR uart0_interrupt_enable(uart_t* uart) if(uart->txEnabled) {
{ tmp |= UART_TXFIFO_RST;
WRITE_PERI_REG(UART_INT_CLR(0), 0x1ff); }
ETS_UART_INTR_ATTACH(&uart0_interrupt_handler, uart);
SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA); SET_PERI_REG_MASK(UART_CONF0(uart->uart_nr), tmp);
CLEAR_PERI_REG_MASK(UART_CONF0(uart->uart_nr), tmp);
}
void ICACHE_FLASH_ATTR uart_interrupt_enable(uart_t* uart) {
WRITE_PERI_REG(UART_INT_CLR(uart->uart_nr), 0x1ff);
ETS_UART_INTR_ATTACH(&uart_interrupt_handler, uart); // uart parameter is not osed in irq function!
if(uart->rxEnabled) {
SET_PERI_REG_MASK(UART_INT_ENA(uart->uart_nr), UART_RXFIFO_FULL_INT_ENA);
}
ETS_UART_INTR_ENABLE(); ETS_UART_INTR_ENABLE();
} }
void ICACHE_FLASH_ATTR uart0_interrupt_disable(uart_t* uart) void ICACHE_FLASH_ATTR uart_interrupt_disable(uart_t* uart) {
{ if(uart->rxEnabled) {
CLEAR_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA); CLEAR_PERI_REG_MASK(UART_INT_ENA(uart->uart_nr), UART_RXFIFO_FULL_INT_ENA);
ETS_UART_INTR_DISABLE(); }
if(uart->txEnabled) {
CLEAR_PERI_REG_MASK(UART_INT_ENA(uart->uart_nr), UART_TXFIFO_EMPTY_INT_ENA);
}
//ETS_UART_INTR_DISABLE(); // never disable irq complete may its needed by the other Serial Interface!
} }
void ICACHE_FLASH_ATTR uart0_arm_tx_interrupt() void ICACHE_FLASH_ATTR uart_arm_tx_interrupt(uart_t* uart) {
{ if(uart->txEnabled) {
SET_PERI_REG_MASK(UART_INT_ENA(0), UART_TXFIFO_EMPTY_INT_ENA); SET_PERI_REG_MASK(UART_INT_ENA(uart->uart_nr), UART_TXFIFO_EMPTY_INT_ENA);
}
} }
void ICACHE_FLASH_ATTR uart0_disarm_tx_interrupt() void ICACHE_FLASH_ATTR uart_disarm_tx_interrupt(uart_t* uart) {
{ if(uart->txEnabled) {
CLEAR_PERI_REG_MASK(UART_INT_ENA(0), UART_TXFIFO_EMPTY_INT_ENA); CLEAR_PERI_REG_MASK(UART_INT_ENA(uart->uart_nr), UART_TXFIFO_EMPTY_INT_ENA);
}
} }
void ICACHE_FLASH_ATTR uart0_set_baudrate(uart_t* uart, int baud_rate) void ICACHE_FLASH_ATTR uart_set_baudrate(uart_t* uart, int baud_rate) {
{
uart->baud_rate = baud_rate; uart->baud_rate = baud_rate;
uart_div_modify(0, UART_CLK_FREQ / (uart->baud_rate)); uart_div_modify(uart->uart_nr, UART_CLK_FREQ / (uart->baud_rate));
} }
int ICACHE_FLASH_ATTR uart0_get_baudrate(uart_t* uart) int ICACHE_FLASH_ATTR uart_get_baudrate(uart_t* uart) {
{
return uart->baud_rate; return uart->baud_rate;
} }
uart_t* ICACHE_FLASH_ATTR uart0_init(int baudrate) uart_t* ICACHE_FLASH_ATTR uart_init(UARTnr_t uart_nr, int baudrate) {
{
uart_t* uart = (uart_t*) os_malloc(sizeof(uart_t));
uint32_t conf1 = 0x00000000;
uart_t* uart = (uart_t*) os_malloc(sizeof(uart_t));
uart->uart_nr = uart_nr;
switch(uart->uart_nr) {
case UART0:
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
PIN_PULLUP_EN(PERIPHS_IO_MUX_U0RXD_U); PIN_PULLUP_EN(PERIPHS_IO_MUX_U0RXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD);
uart->rxEnabled = true;
uart->txEnabled = true;
uart->rxPin = 3;
uart->txPin = 1;
break;
case UART1:
PIN_PULLUP_DIS(PERIPHS_IO_MUX_GPIO2_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
uart->rxEnabled = false;
uart->txEnabled = true;
uart->rxPin = 255;
uart->txPin = 2;
break;
case UART_NO:
default:
// big fail!
break;
}
uart_set_baudrate(uart, baudrate);
WRITE_PERI_REG(UART_CONF0(uart->uart_nr), 0x3 << UART_BIT_NUM_S); // 8n1
uart0_set_baudrate(uart, baudrate); uart_flush(uart);
WRITE_PERI_REG(UART_CONF0(0), 0x3 << UART_BIT_NUM_S); // 8n1 uart_interrupt_enable(uart);
uart0_flush(uart); if(uart->rxEnabled) {
uart0_interrupt_enable(uart); conf1 |= ((0x01 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S);
}
WRITE_PERI_REG(UART_CONF1(0), ((0x01 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) | if(uart->txEnabled) {
((0x20 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S)); conf1 |= ((0x20 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S);
}
WRITE_PERI_REG(UART_CONF1(uart->uart_nr), conf1);
return uart; return uart;
} }
void ICACHE_FLASH_ATTR uart0_uninit(uart_t* uart) void ICACHE_FLASH_ATTR uart_uninit(uart_t* uart) {
{ uart_interrupt_disable(uart);
uart0_interrupt_disable(uart);
// TODO: revert pin functions switch(uart->rxPin) {
case 3:
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0RXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_GPIO3);
break;
case 13:
PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTCK_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13);
break;
}
switch(uart->rxPin) {
case 1:
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_GPIO1);
break;
case 2:
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);
break;
case 15:
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO2);
break;
}
pinMode(uart->rxPin , INPUT);
pinMode(uart->txPin , INPUT);
os_free(uart); os_free(uart);
} }
void ICACHE_FLASH_ATTR uart0_swap(uart_t* uart) void ICACHE_FLASH_ATTR uart_swap(uart_t* uart) {
{ switch(uart->uart_nr) {
case UART0:
if(uart->txPin == 1 && uart->rxPin == 3) {
PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTCK_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS); PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS);
PIN_PULLUP_EN(PERIPHS_IO_MUX_MTDO_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_UART0_RTS); PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_UART0_RTS);
//SWAP PIN : U0TXD<==>U0RTS(MTDO, GPIO15) , U0RXD<==>U0CTS(MTCK, GPIO13) //SWAP PIN : U0TXD<==>U0RTS(MTDO, GPIO15) , U0RXD<==>U0CTS(MTCK, GPIO13)
SET_PERI_REG_MASK(0x3ff00028, BIT2); SET_PERI_REG_MASK(0x3ff00028, BIT2);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_GPIO1);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_GPIO3); PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_GPIO3);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_GPIO1);
pinMode(uart->rxPin, INPUT);
pinMode(uart->txPin, INPUT);
uart->rxPin = 13;
uart->txPin = 15;
} else {
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD);
PIN_PULLUP_EN(PERIPHS_IO_MUX_U0RXD_U);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD);
CLEAR_PERI_REG_MASK(0x3ff00028, BIT2);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15);
pinMode(uart->rxPin, INPUT);
pinMode(uart->txPin, INPUT);
uart->rxPin = 3;
uart->txPin = 1;
} }
void ICACHE_FLASH_ATTR break;
uart_ignore_char(char c) case UART1:
{ // current no swap possible! see GPIO pins used by UART
break;
default:
break;
}
} }
void ICACHE_FLASH_ATTR // ####################################################################################################
uart_write_char(char c) // ####################################################################################################
{ // ####################################################################################################
if (c == '\n')
void ICACHE_FLASH_ATTR uart_ignore_char(char c) {
}
void ICACHE_FLASH_ATTR uart0_write_char(char c) {
if(c == '\n') {
WRITE_PERI_REG(UART_FIFO(0), '\r'); WRITE_PERI_REG(UART_FIFO(0), '\r');
}
WRITE_PERI_REG(UART_FIFO(0), c); WRITE_PERI_REG(UART_FIFO(0), c);
} }
bool s_uart_debug_enabled = true; void ICACHE_FLASH_ATTR uart1_write_char(char c) {
void ICACHE_FLASH_ATTR uart_set_debug(bool enabled) if(c == '\n') {
{ WRITE_PERI_REG(UART_FIFO(1), '\r');
s_uart_debug_enabled = enabled; }
if (enabled) WRITE_PERI_REG(UART_FIFO(1), c);
{ }
static UARTnr_t s_uart_debug_nr = UART_NO;
void ICACHE_FLASH_ATTR uart_set_debug(UARTnr_t uart_nr) {
s_uart_debug_nr = uart_nr;
switch(s_uart_debug_nr) {
case UART0:
system_set_os_print(1); system_set_os_print(1);
ets_install_putc1((void *)&uart_write_char); ets_install_putc1((void *) &uart0_write_char);
} break;
else case UART1:
system_set_os_print(1);
ets_install_putc1((void *) &uart1_write_char);
break;
case UART_NO:
default:
system_set_os_print(0);
ets_install_putc1((void *) &uart_ignore_char); ets_install_putc1((void *) &uart_ignore_char);
break;
}
} }
bool ICACHE_FLASH_ATTR uart_get_debug() UARTnr_t ICACHE_FLASH_ATTR uart_get_debug() {
{ return s_uart_debug_nr;
return s_uart_debug_enabled;
} }
ICACHE_FLASH_ATTR HardwareSerial::HardwareSerial() : // ####################################################################################################
_uart(0), _rx_buffer(0), _tx_buffer(0) // ####################################################################################################
{ // ####################################################################################################
ICACHE_FLASH_ATTR HardwareSerial::HardwareSerial(UARTnr_t uart_nr) :
_uart(0), _tx_buffer(0), _rx_buffer(0), _written(false) {
_uart_nr = uart_nr;
} }
void ICACHE_FLASH_ATTR HardwareSerial::begin(unsigned long baud, byte config) void ICACHE_FLASH_ATTR HardwareSerial::begin(unsigned long baud, byte config) {
{
// disable debug for this interface
if(uart_get_debug() == _uart_nr) {
uart_set_debug(UART_NO);
}
_uart = uart_init(_uart_nr, baud);
if(_uart->rxEnabled) {
_rx_buffer = new cbuf(SERIAL_RX_BUFFER_SIZE); _rx_buffer = new cbuf(SERIAL_RX_BUFFER_SIZE);
}
if(_uart->txEnabled) {
_tx_buffer = new cbuf(SERIAL_TX_BUFFER_SIZE); _tx_buffer = new cbuf(SERIAL_TX_BUFFER_SIZE);
uart_set_debug(false); }
_uart = uart0_init(baud);
_written = false; _written = false;
delay(1); delay(1);
} }
void ICACHE_FLASH_ATTR HardwareSerial::end() void ICACHE_FLASH_ATTR HardwareSerial::end() {
{ uart_uninit(_uart);
uart0_uninit(_uart);
delete _rx_buffer; delete _rx_buffer;
delete _tx_buffer; delete _tx_buffer;
_uart = 0; _uart = 0;
@ -257,65 +468,86 @@ void ICACHE_FLASH_ATTR HardwareSerial::end()
_tx_buffer = 0; _tx_buffer = 0;
} }
void ICACHE_FLASH_ATTR HardwareSerial::swap() void ICACHE_FLASH_ATTR HardwareSerial::swap() {
{ uart_swap(_uart);
uart0_swap(_uart);
pinMode(1, INPUT);
pinMode(3, INPUT);
} }
void ICACHE_FLASH_ATTR HardwareSerial::setDebugOutput(bool en) void ICACHE_FLASH_ATTR HardwareSerial::setDebugOutput(bool en) {
{ if(en) {
uart_set_debug(en); uart_set_debug(_uart->uart_nr);
} else {
// disable debug for this interface
if(uart_get_debug() == _uart_nr) {
uart_set_debug(UART_NO);
}
}
} }
int ICACHE_FLASH_ATTR HardwareSerial::available(void) bool ICACHE_FLASH_ATTR HardwareSerial::isTxEnabled(void) {
{ if(_uart == 0) return false;
return _uart->txEnabled;
}
bool ICACHE_FLASH_ATTR HardwareSerial::isRxEnabled(void) {
if(_uart == 0) return false;
return _uart->rxEnabled;
}
int ICACHE_FLASH_ATTR HardwareSerial::available(void) {
if(_uart->rxEnabled) {
return static_cast<int>(_rx_buffer->getSize()); return static_cast<int>(_rx_buffer->getSize());
} else {
return 0;
}
} }
int ICACHE_FLASH_ATTR HardwareSerial::peek(void) int ICACHE_FLASH_ATTR HardwareSerial::peek(void) {
{ if(_uart->rxEnabled) {
return _rx_buffer->peek(); return _rx_buffer->peek();
} else {
return -1;
}
} }
int ICACHE_FLASH_ATTR HardwareSerial::read(void) int ICACHE_FLASH_ATTR HardwareSerial::read(void) {
{ if(_uart->rxEnabled) {
return _rx_buffer->read(); return _rx_buffer->read();
} else {
return -1;
}
} }
int ICACHE_FLASH_ATTR HardwareSerial::availableForWrite(void) int ICACHE_FLASH_ATTR HardwareSerial::availableForWrite(void) {
{ if(_uart->txEnabled) {
return static_cast<int>(_tx_buffer->room()); return static_cast<int>(_tx_buffer->room());
} else {
return 0;
}
} }
void ICACHE_FLASH_ATTR HardwareSerial::flush() void ICACHE_FLASH_ATTR HardwareSerial::flush() {
{ if(!_uart->txEnabled) return;
if (!_written) if(!_written) return;
return;
while (_tx_buffer->getSize() || uart0_get_tx_fifo_room() < UART_TX_FIFO_SIZE) while(_tx_buffer->getSize() || uart_get_tx_fifo_room(_uart) < UART_TX_FIFO_SIZE)
yield(); yield();
_written = false; _written = false;
} }
size_t ICACHE_FLASH_ATTR HardwareSerial::write(uint8_t c) size_t ICACHE_FLASH_ATTR HardwareSerial::write(uint8_t c) {
{ if(!_uart->txEnabled) return 0;
_written = true; _written = true;
size_t room = uart0_get_tx_fifo_room(); size_t room = uart_get_tx_fifo_room(_uart);
if (room > 0 && _tx_buffer->empty()) if(room > 0 && _tx_buffer->empty()) {
{ uart_transmit_char(_uart, c);
uart0_transmit_char(_uart, c); if(room < 10) {
if (room < 10) uart_arm_tx_interrupt(_uart);
{
uart0_arm_tx_interrupt();
} }
return 1; return 1;
} }
while (_tx_buffer->room() == 0) while(_tx_buffer->room() == 0) {
{
yield(); yield();
} }
@ -323,30 +555,24 @@ size_t ICACHE_FLASH_ATTR HardwareSerial::write(uint8_t c)
return 1; return 1;
} }
ICACHE_FLASH_ATTR HardwareSerial::operator bool() const ICACHE_FLASH_ATTR HardwareSerial::operator bool() const {
{
return _uart != 0; return _uart != 0;
} }
void ICACHE_FLASH_ATTR HardwareSerial::_rx_complete_irq(char c) void ICACHE_FLASH_ATTR HardwareSerial::_rx_complete_irq(char c) {
{
_rx_buffer->write(c); _rx_buffer->write(c);
} }
void ICACHE_FLASH_ATTR HardwareSerial::_tx_empty_irq(void) void ICACHE_FLASH_ATTR HardwareSerial::_tx_empty_irq(void) {
{
size_t queued = _tx_buffer->getSize(); size_t queued = _tx_buffer->getSize();
if (!queued) if(!queued) {
{ uart_disarm_tx_interrupt(_uart);
uart0_disarm_tx_interrupt();
return; return;
} }
size_t room = uart0_get_tx_fifo_room(); size_t room = uart_get_tx_fifo_room(_uart);
int n = static_cast<int>((queued < room) ? queued : room); int n = static_cast<int>((queued < room) ? queued : room);
while (n--) while(n--) {
{ uart_transmit_char(_uart, _tx_buffer->read());
uart0_transmit_char(_uart, _tx_buffer->read());
} }
} }

View File

@ -20,6 +20,7 @@
Modified 14 August 2012 by Alarus Modified 14 August 2012 by Alarus
Modified 3 December 2013 by Matthijs Kooijman Modified 3 December 2013 by Matthijs Kooijman
Modified 18 December 2014 by Ivan Grokhotkov (esp8266 platform support) Modified 18 December 2014 by Ivan Grokhotkov (esp8266 platform support)
Modified 31 March 2015 by Markus Sattler (rewrite the code for UART0 + UART1 support in ESP8266)
*/ */
#ifndef HardwareSerial_h #ifndef HardwareSerial_h
@ -59,14 +60,29 @@
// #define SERIAL_8O2 0x3E // #define SERIAL_8O2 0x3E
class cbuf; class cbuf;
typedef struct uart_ uart_t;
class HardwareSerial : public Stream typedef enum {
{ UART0 = 0,
UART1 = 1,
UART_NO = 0xFF
} UARTnr_t;
typedef struct {
UARTnr_t uart_nr;
int baud_rate;
bool rxEnabled;
bool txEnabled;
uint8_t rxPin;
uint8_t txPin;
} uart_t;
class HardwareSerial: public Stream {
public: public:
HardwareSerial(); HardwareSerial(UARTnr_t uart_nr);
void begin(unsigned long baud) { begin(baud, 0); } void begin(unsigned long baud) {
begin(baud, 0);
}
void begin(unsigned long, uint8_t); void begin(unsigned long, uint8_t);
void end(); void end();
void swap(); //use GPIO13 and GPIO15 as RX and TX void swap(); //use GPIO13 and GPIO15 as RX and TX
@ -76,21 +92,32 @@ public:
int availableForWrite(void); int availableForWrite(void);
void flush(void) override; void flush(void) override;
size_t write(uint8_t) override; size_t write(uint8_t) override;
inline size_t write(unsigned long n) { return write((uint8_t)n); } inline size_t write(unsigned long n) {
inline size_t write(long n) { return write((uint8_t)n); } return write((uint8_t) n);
inline size_t write(unsigned int n) { return write((uint8_t)n); } }
inline size_t write(int n) { return write((uint8_t)n); } inline size_t write(long n) {
return write((uint8_t) n);
}
inline size_t write(unsigned int n) {
return write((uint8_t) n);
}
inline size_t write(int n) {
return write((uint8_t) n);
}
using Print::write; // pull in write(str) and write(buf, size) from Print using Print::write; // pull in write(str) and write(buf, size) from Print
operator bool() const; operator bool() const;
void setDebugOutput(bool); void setDebugOutput(bool);
bool isTxEnabled(void);
bool isRxEnabled(void);
protected: protected:
friend void uart0_interrupt_handler(uart_t* uart); friend void uart_interrupt_handler(uart_t* uart);
void _rx_complete_irq(char c); void _rx_complete_irq(char c);
void _tx_empty_irq(void); void _tx_empty_irq(void);
protected: protected:
UARTnr_t _uart_nr;
uart_t* _uart; uart_t* _uart;
cbuf* _tx_buffer; cbuf* _tx_buffer;
cbuf* _rx_buffer; cbuf* _rx_buffer;
@ -98,5 +125,6 @@ protected:
}; };
extern HardwareSerial Serial; extern HardwareSerial Serial;
extern HardwareSerial Serial1;
#endif #endif