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

Merge branch 'esp8266' of github.com:esp8266/Arduino into esp8266

This commit is contained in:
Ivan Grokhotkov 2015-04-03 00:03:30 +03:00
commit 3df5388b8f
2 changed files with 655 additions and 401 deletions

View File

@ -1,352 +1,578 @@
/* /*
HardwareSerial.cpp - esp8266 UART support HardwareSerial.cpp - esp8266 UART support
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved. Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment. This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details. Lesser General Public License for more details.
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 <stdio.h>
#include <string.h> #include <stdlib.h>
#include <inttypes.h> #include <stdio.h>
#include "Arduino.h" #include <string.h>
#include "cbuf.h" #include <inttypes.h>
#include "Arduino.h"
extern "C" { #include "cbuf.h"
#include "osapi.h"
#include "ets_sys.h" extern "C" {
#include "mem.h" #include "osapi.h"
#include "uart_register.h" #include "ets_sys.h"
#include "user_interface.h" #include "mem.h"
} #include "uart_register.h"
#include "user_interface.h"
#include "HardwareSerial.h" }
HardwareSerial Serial; #include "HardwareSerial.h"
uart_t* uart0_init(int baud_rate); #define UART_TX_FIFO_SIZE 0x80
void uart0_set_baudrate(uart_t* uart, int baud_rate);
int uart0_get_baudrate(uart_t* uart); /**
void uart0_uninit(uart_t* uart); * UART GPIOs
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); * UART0 TX: 1 or 2
void uart0_transmit_char(uart_t* uart, char c); // does not block, but character will be lost if FIFO is full * UART0 RX: 3
*
void uart_set_debug(bool enabled); * UART0 SWAP TX: 15
bool uart_get_debug(); * UART0 SWAP RX: 13
*
struct uart_ *
{ * UART1 TX: 7 (NC) or 2
int baud_rate; * UART1 RX: 8 (NC)
}; *
* UART1 SWAP TX: 11 (NC)
#define UART_TX_FIFO_SIZE 0x80 * UART1 SWAP RX: 6 (NC)
*
void ICACHE_FLASH_ATTR uart0_interrupt_handler(uart_t* uart) * NC = Not Connected to Module Pads --> No Access
{ *
uint32_t status = READ_PERI_REG(UART_INT_ST(0)); */
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; HardwareSerial Serial(UART0);
HardwareSerial Serial1(UART1);
while(rx_count--)
{ // ####################################################################################################
char c = READ_PERI_REG(UART_FIFO(0)) & 0xFF; // ####################################################################################################
Serial._rx_complete_irq(c); // ####################################################################################################
}
} void uart_interrupt_handler(uart_t* uart);
WRITE_PERI_REG(UART_INT_CLR(0), UART_RXFIFO_FULL_INT_CLR); void uart_wait_for_tx_fifo(uart_t* uart, size_t size_needed);
}
if (status & UART_TXFIFO_EMPTY_INT_ST) size_t uart_get_tx_fifo_room(uart_t* uart);
{ void uart_wait_for_transmit(uart_t* uart);
WRITE_PERI_REG(UART_INT_CLR(0), UART_TXFIFO_EMPTY_INT_CLR); void uart_transmit_char(uart_t* uart, char c);
Serial._tx_empty_irq(); 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 ICACHE_FLASH_ATTR uart0_wait_for_tx_fifo(size_t size_needed) void uart_arm_tx_interrupt(uart_t* uart);
{ void uart_disarm_tx_interrupt(uart_t* uart);
while (true) void uart_set_baudrate(uart_t* uart, int baud_rate);
{ int uart_get_baudrate(uart_t* uart);
size_t tx_count = (READ_PERI_REG(UART_STATUS(0)) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT;
if (tx_count <= (UART_TX_FIFO_SIZE - size_needed)) uart_t* uart_init(UARTnr_t uart_nr, int baudrate);
break; void uart_uninit(uart_t* uart);
} void uart_swap(uart_t* uart);
}
void uart_ignore_char(char c);
size_t ICACHE_FLASH_ATTR uart0_get_tx_fifo_room() void uart0_write_char(char c);
{ void uart1_write_char(char c);
return UART_TX_FIFO_SIZE - ((READ_PERI_REG(UART_STATUS(0)) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT);
} void uart_set_debug(UARTnr_t uart_nr);
UARTnr_t uart_get_debug();
void ICACHE_FLASH_ATTR uart0_wait_for_transmit(uart_t* uart)
{ // ####################################################################################################
uart0_wait_for_tx_fifo(UART_TX_FIFO_SIZE); // ####################################################################################################
} // ####################################################################################################
void ICACHE_FLASH_ATTR uart0_transmit_char(uart_t* uart, char c) void ICACHE_FLASH_ATTR uart_interrupt_handler(uart_t* uart) {
{
WRITE_PERI_REG(UART_FIFO(0), c); // -------------- UART 0 --------------
} uint32_t status = READ_PERI_REG(UART_INT_ST(0));
if(Serial.isRxEnabled()) {
void ICACHE_FLASH_ATTR uart0_transmit(uart_t* uart, const char* buf, size_t size) if(status & UART_RXFIFO_FULL_INT_ST) {
{ while(true) {
while (size) int rx_count = (READ_PERI_REG(UART_STATUS(0)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT;
{ if(!rx_count) break;
size_t part_size = (size > UART_TX_FIFO_SIZE) ? UART_TX_FIFO_SIZE : size;
size -= part_size; while(rx_count--) {
char c = READ_PERI_REG(UART_FIFO(0)) & 0xFF;
uart0_wait_for_tx_fifo(part_size); Serial._rx_complete_irq(c);
for(;part_size;--part_size, ++buf) }
WRITE_PERI_REG(UART_FIFO(0), *buf); }
} WRITE_PERI_REG(UART_INT_CLR(0), UART_RXFIFO_FULL_INT_CLR);
} }
}
void ICACHE_FLASH_ATTR uart0_flush(uart_t* uart) if(Serial.isTxEnabled()) {
{ if(status & UART_TXFIFO_EMPTY_INT_ST) {
SET_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST | UART_TXFIFO_RST); WRITE_PERI_REG(UART_INT_CLR(0), UART_TXFIFO_EMPTY_INT_CLR);
CLEAR_PERI_REG_MASK(UART_CONF0(0), UART_RXFIFO_RST | UART_TXFIFO_RST); Serial._tx_empty_irq();
} }
}
void ICACHE_FLASH_ATTR uart0_interrupt_enable(uart_t* uart)
{ // -------------- UART 1 --------------
WRITE_PERI_REG(UART_INT_CLR(0), 0x1ff);
ETS_UART_INTR_ATTACH(&uart0_interrupt_handler, uart); status = READ_PERI_REG(UART_INT_ST(1));
SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA); if(Serial1.isRxEnabled()) {
ETS_UART_INTR_ENABLE(); if(status & UART_RXFIFO_FULL_INT_ST) {
} while(true) {
int rx_count = (READ_PERI_REG(UART_STATUS(1)) >> UART_RXFIFO_CNT_S) & UART_RXFIFO_CNT;
void ICACHE_FLASH_ATTR uart0_interrupt_disable(uart_t* uart) if(!rx_count) break;
{
CLEAR_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA); while(rx_count--) {
ETS_UART_INTR_DISABLE(); char c = READ_PERI_REG(UART_FIFO(1)) & 0xFF;
} Serial1._rx_complete_irq(c);
}
void ICACHE_FLASH_ATTR uart0_arm_tx_interrupt() }
{ WRITE_PERI_REG(UART_INT_CLR(1), UART_RXFIFO_FULL_INT_CLR);
SET_PERI_REG_MASK(UART_INT_ENA(0), UART_TXFIFO_EMPTY_INT_ENA); }
} }
if(Serial1.isTxEnabled()) {
void ICACHE_FLASH_ATTR uart0_disarm_tx_interrupt() status = READ_PERI_REG(UART_INT_ST(1));
{ if(status & UART_TXFIFO_EMPTY_INT_ST) {
CLEAR_PERI_REG_MASK(UART_INT_ENA(0), UART_TXFIFO_EMPTY_INT_ENA); WRITE_PERI_REG(UART_INT_CLR(1), UART_TXFIFO_EMPTY_INT_CLR);
} Serial1._tx_empty_irq();
}
void ICACHE_FLASH_ATTR uart0_set_baudrate(uart_t* uart, int baud_rate) }
{ }
uart->baud_rate = baud_rate;
uart_div_modify(0, UART_CLK_FREQ / (uart->baud_rate)); // ####################################################################################################
}
void ICACHE_FLASH_ATTR uart_wait_for_tx_fifo(uart_t* uart, size_t size_needed) {
int ICACHE_FLASH_ATTR uart0_get_baudrate(uart_t* uart) if(uart->txEnabled) {
{ while(true) {
return uart->baud_rate; 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;
}
uart_t* ICACHE_FLASH_ATTR uart0_init(int baudrate) }
{ }
uart_t* uart = (uart_t*) os_malloc(sizeof(uart_t));
size_t ICACHE_FLASH_ATTR uart_get_tx_fifo_room(uart_t* uart) {
PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); if(uart->txEnabled) {
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); return UART_TX_FIFO_SIZE - ((READ_PERI_REG(UART_STATUS(uart->uart_nr)) >> UART_TXFIFO_CNT_S) & UART_TXFIFO_CNT);
PIN_PULLUP_EN(PERIPHS_IO_MUX_U0RXD_U); }
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD); return 0;
}
uart0_set_baudrate(uart, baudrate);
WRITE_PERI_REG(UART_CONF0(0), 0x3 << UART_BIT_NUM_S); // 8n1 void ICACHE_FLASH_ATTR uart_wait_for_transmit(uart_t* uart) {
if(uart->txEnabled) {
uart0_flush(uart); uart_wait_for_tx_fifo(uart, UART_TX_FIFO_SIZE);
uart0_interrupt_enable(uart); }
}
WRITE_PERI_REG(UART_CONF1(0), ((0x01 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S) |
((0x20 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S)); void ICACHE_FLASH_ATTR uart_transmit_char(uart_t* uart, char c) {
if(uart->txEnabled) {
return uart; WRITE_PERI_REG(UART_FIFO(uart->uart_nr), c);
} }
}
void ICACHE_FLASH_ATTR uart0_uninit(uart_t* uart)
{ void ICACHE_FLASH_ATTR uart_transmit(uart_t* uart, const char* buf, size_t size) {
uart0_interrupt_disable(uart); if(uart->txEnabled) {
// TODO: revert pin functions while(size) {
os_free(uart); size_t part_size = (size > UART_TX_FIFO_SIZE) ? UART_TX_FIFO_SIZE : size;
} size -= part_size;
void ICACHE_FLASH_ATTR uart0_swap(uart_t* uart) uart_wait_for_tx_fifo(uart, part_size);
{ for(; part_size; --part_size, ++buf)
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS); WRITE_PERI_REG(UART_FIFO(uart->uart_nr), *buf);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_UART0_RTS); }
//SWAP PIN : U0TXD<==>U0RTS(MTDO, GPIO15) , U0RXD<==>U0CTS(MTCK, GPIO13) }
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); void ICACHE_FLASH_ATTR uart_flush(uart_t* uart) {
} uint32_t tmp = 0x00000000;
void ICACHE_FLASH_ATTR if(uart->rxEnabled) {
uart_ignore_char(char c) tmp |= UART_RXFIFO_RST;
{ }
}
if(uart->txEnabled) {
void ICACHE_FLASH_ATTR tmp |= UART_TXFIFO_RST;
uart_write_char(char c) }
{
if (c == '\n') SET_PERI_REG_MASK(UART_CONF0(uart->uart_nr), tmp);
WRITE_PERI_REG(UART_FIFO(0), '\r'); CLEAR_PERI_REG_MASK(UART_CONF0(uart->uart_nr), tmp);
}
WRITE_PERI_REG(UART_FIFO(0), c);
} void ICACHE_FLASH_ATTR uart_interrupt_enable(uart_t* uart) {
WRITE_PERI_REG(UART_INT_CLR(uart->uart_nr), 0x1ff);
bool s_uart_debug_enabled = true; ETS_UART_INTR_ATTACH(&uart_interrupt_handler, uart); // uart parameter is not osed in irq function!
void ICACHE_FLASH_ATTR uart_set_debug(bool enabled) if(uart->rxEnabled) {
{ SET_PERI_REG_MASK(UART_INT_ENA(uart->uart_nr), UART_RXFIFO_FULL_INT_ENA);
s_uart_debug_enabled = enabled; }
if (enabled) ETS_UART_INTR_ENABLE();
{ }
system_set_os_print(1);
ets_install_putc1((void *)&uart_write_char); void ICACHE_FLASH_ATTR uart_interrupt_disable(uart_t* uart) {
} if(uart->rxEnabled) {
else CLEAR_PERI_REG_MASK(UART_INT_ENA(uart->uart_nr), UART_RXFIFO_FULL_INT_ENA);
ets_install_putc1((void *)&uart_ignore_char); }
} if(uart->txEnabled) {
CLEAR_PERI_REG_MASK(UART_INT_ENA(uart->uart_nr), UART_TXFIFO_EMPTY_INT_ENA);
bool ICACHE_FLASH_ATTR uart_get_debug() }
{ //ETS_UART_INTR_DISABLE(); // never disable irq complete may its needed by the other Serial Interface!
return s_uart_debug_enabled; }
}
void ICACHE_FLASH_ATTR uart_arm_tx_interrupt(uart_t* uart) {
ICACHE_FLASH_ATTR HardwareSerial::HardwareSerial() : if(uart->txEnabled) {
_uart(0), _rx_buffer(0), _tx_buffer(0) SET_PERI_REG_MASK(UART_INT_ENA(uart->uart_nr), UART_TXFIFO_EMPTY_INT_ENA);
{ }
} }
void ICACHE_FLASH_ATTR HardwareSerial::begin(unsigned long baud, byte config) void ICACHE_FLASH_ATTR uart_disarm_tx_interrupt(uart_t* uart) {
{ if(uart->txEnabled) {
_rx_buffer = new cbuf(SERIAL_RX_BUFFER_SIZE); CLEAR_PERI_REG_MASK(UART_INT_ENA(uart->uart_nr), UART_TXFIFO_EMPTY_INT_ENA);
_tx_buffer = new cbuf(SERIAL_TX_BUFFER_SIZE); }
uart_set_debug(false); }
_uart = uart0_init(baud);
_written = false; void ICACHE_FLASH_ATTR uart_set_baudrate(uart_t* uart, int baud_rate) {
delay(1); uart->baud_rate = baud_rate;
} uart_div_modify(uart->uart_nr, UART_CLK_FREQ / (uart->baud_rate));
}
void ICACHE_FLASH_ATTR HardwareSerial::end()
{ int ICACHE_FLASH_ATTR uart_get_baudrate(uart_t* uart) {
uart0_uninit(_uart); return uart->baud_rate;
delete _rx_buffer; }
delete _tx_buffer;
_uart = 0; uart_t* ICACHE_FLASH_ATTR uart_init(UARTnr_t uart_nr, int baudrate) {
_rx_buffer = 0;
_tx_buffer = 0; uint32_t conf1 = 0x00000000;
} uart_t* uart = (uart_t*) os_malloc(sizeof(uart_t));
uart->uart_nr = uart_nr;
void ICACHE_FLASH_ATTR HardwareSerial::swap()
{ switch(uart->uart_nr) {
uart0_swap(_uart); case UART0:
pinMode(1, INPUT); PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U);
pinMode(3, INPUT); 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);
void ICACHE_FLASH_ATTR HardwareSerial::setDebugOutput(bool en) uart->rxEnabled = true;
{ uart->txEnabled = true;
uart_set_debug(en); uart->rxPin = 3;
} uart->txPin = 1;
break;
int ICACHE_FLASH_ATTR HardwareSerial::available(void) case UART1:
{ PIN_PULLUP_DIS(PERIPHS_IO_MUX_GPIO2_U);
return static_cast<int>(_rx_buffer->getSize()); PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_U1TXD_BK);
} uart->rxEnabled = false;
uart->txEnabled = true;
int ICACHE_FLASH_ATTR HardwareSerial::peek(void) uart->rxPin = 255;
{ uart->txPin = 2;
return _rx_buffer->peek(); break;
} case UART_NO:
default:
int ICACHE_FLASH_ATTR HardwareSerial::read(void) // big fail!
{ break;
return _rx_buffer->read(); }
} uart_set_baudrate(uart, baudrate);
WRITE_PERI_REG(UART_CONF0(uart->uart_nr), 0x3 << UART_BIT_NUM_S); // 8n1
int ICACHE_FLASH_ATTR HardwareSerial::availableForWrite(void)
{ uart_flush(uart);
return static_cast<int>(_tx_buffer->room()); uart_interrupt_enable(uart);
}
if(uart->rxEnabled) {
void ICACHE_FLASH_ATTR HardwareSerial::flush() conf1 |= ((0x01 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S);
{ }
if (!_written)
return; if(uart->txEnabled) {
conf1 |= ((0x20 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S);
while (_tx_buffer->getSize() || uart0_get_tx_fifo_room() < UART_TX_FIFO_SIZE) }
yield();
WRITE_PERI_REG(UART_CONF1(uart->uart_nr), conf1);
_written = false;
} return uart;
}
size_t ICACHE_FLASH_ATTR HardwareSerial::write(uint8_t c)
{ void ICACHE_FLASH_ATTR uart_uninit(uart_t* uart) {
_written = true; uart_interrupt_disable(uart);
size_t room = uart0_get_tx_fifo_room();
if (room > 0 && _tx_buffer->empty()) switch(uart->rxPin) {
{ case 3:
uart0_transmit_char(_uart, c); PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0RXD_U);
if (room < 10) PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_GPIO3);
{ break;
uart0_arm_tx_interrupt(); case 13:
} PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTCK_U);
return 1; PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_GPIO13);
} break;
}
while (_tx_buffer->room() == 0)
{ switch(uart->rxPin) {
yield(); case 1:
} PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_GPIO1);
break;
_tx_buffer->write(c); case 2:
return 1; PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO2_U, FUNC_GPIO2);
} break;
case 15:
ICACHE_FLASH_ATTR HardwareSerial::operator bool() const PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_GPIO15);
{ break;
return _uart != 0; }
}
void ICACHE_FLASH_ATTR HardwareSerial::_rx_complete_irq(char c) pinMode(uart->rxPin , INPUT);
{ pinMode(uart->txPin , INPUT);
_rx_buffer->write(c);
} os_free(uart);
}
void ICACHE_FLASH_ATTR HardwareSerial::_tx_empty_irq(void)
{ void ICACHE_FLASH_ATTR uart_swap(uart_t* uart) {
size_t queued = _tx_buffer->getSize(); switch(uart->uart_nr) {
if (!queued) case UART0:
{ if(uart->txPin == 1 && uart->rxPin == 3) {
uart0_disarm_tx_interrupt();
return; PIN_PULLUP_DIS(PERIPHS_IO_MUX_MTCK_U);
} PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS);
size_t room = uart0_get_tx_fifo_room(); PIN_PULLUP_EN(PERIPHS_IO_MUX_MTDO_U);
int n = static_cast<int>((queued < room) ? queued : room); PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTDO_U, FUNC_UART0_RTS);
while (n--)
{ //SWAP PIN : U0TXD<==>U0RTS(MTDO, GPIO15) , U0RXD<==>U0CTS(MTCK, GPIO13)
uart0_transmit_char(_uart, _tx_buffer->read()); SET_PERI_REG_MASK(0x3ff00028, BIT2);
}
} 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;
}
break;
case UART1:
// current no swap possible! see GPIO pins used by UART
break;
default:
break;
}
}
// ####################################################################################################
// ####################################################################################################
// ####################################################################################################
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), c);
}
void ICACHE_FLASH_ATTR uart1_write_char(char c) {
if(c == '\n') {
WRITE_PERI_REG(UART_FIFO(1), '\r');
}
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);
ets_install_putc1((void *) &uart0_write_char);
break;
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);
break;
}
}
UARTnr_t ICACHE_FLASH_ATTR uart_get_debug() {
return s_uart_debug_nr;
}
// ####################################################################################################
// ####################################################################################################
// ####################################################################################################
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) {
// 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);
}
if(_uart->txEnabled) {
_tx_buffer = new cbuf(SERIAL_TX_BUFFER_SIZE);
}
_written = false;
delay(1);
}
void ICACHE_FLASH_ATTR HardwareSerial::end() {
uart_uninit(_uart);
delete _rx_buffer;
delete _tx_buffer;
_uart = 0;
_rx_buffer = 0;
_tx_buffer = 0;
}
void ICACHE_FLASH_ATTR HardwareSerial::swap() {
uart_swap(_uart);
}
void ICACHE_FLASH_ATTR HardwareSerial::setDebugOutput(bool en) {
if(en) {
uart_set_debug(_uart->uart_nr);
} else {
// disable debug for this interface
if(uart_get_debug() == _uart_nr) {
uart_set_debug(UART_NO);
}
}
}
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());
} else {
return 0;
}
}
int ICACHE_FLASH_ATTR HardwareSerial::peek(void) {
if(_uart->rxEnabled) {
return _rx_buffer->peek();
} else {
return -1;
}
}
int ICACHE_FLASH_ATTR HardwareSerial::read(void) {
if(_uart->rxEnabled) {
return _rx_buffer->read();
} else {
return -1;
}
}
int ICACHE_FLASH_ATTR HardwareSerial::availableForWrite(void) {
if(_uart->txEnabled) {
return static_cast<int>(_tx_buffer->room());
} else {
return 0;
}
}
void ICACHE_FLASH_ATTR HardwareSerial::flush() {
if(!_uart->txEnabled) return;
if(!_written) return;
while(_tx_buffer->getSize() || uart_get_tx_fifo_room(_uart) < UART_TX_FIFO_SIZE)
yield();
_written = false;
}
size_t ICACHE_FLASH_ATTR HardwareSerial::write(uint8_t c) {
if(!_uart->txEnabled) return 0;
_written = true;
size_t room = uart_get_tx_fifo_room(_uart);
if(room > 0 && _tx_buffer->empty()) {
uart_transmit_char(_uart, c);
if(room < 10) {
uart_arm_tx_interrupt(_uart);
}
return 1;
}
while(_tx_buffer->room() == 0) {
yield();
}
_tx_buffer->write(c);
return 1;
}
ICACHE_FLASH_ATTR HardwareSerial::operator bool() const {
return _uart != 0;
}
void ICACHE_FLASH_ATTR HardwareSerial::_rx_complete_irq(char c) {
_rx_buffer->write(c);
}
void ICACHE_FLASH_ATTR HardwareSerial::_tx_empty_irq(void) {
size_t queued = _tx_buffer->getSize();
if(!queued) {
uart_disarm_tx_interrupt(_uart);
return;
}
size_t room = uart_get_tx_fifo_room(_uart);
int n = static_cast<int>((queued < room) ? queued : room);
while(n--) {
uart_transmit_char(_uart, _tx_buffer->read());
}
}

View File

@ -1,26 +1,27 @@
/* /*
HardwareSerial.h - Hardware serial library for Wiring HardwareSerial.h - Hardware serial library for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved. Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details. Lesser General Public License for more details.
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 28 September 2010 by Mark Sproul Modified 28 September 2010 by Mark Sproul
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
#define HardwareSerial_h #define HardwareSerial_h
@ -59,44 +60,71 @@
// #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,
public: UART1 = 1,
HardwareSerial(); UART_NO = 0xFF
} UARTnr_t;
void begin(unsigned long baud) { begin(baud, 0); } typedef struct {
void begin(unsigned long, uint8_t); UARTnr_t uart_nr;
void end(); int baud_rate;
void swap(); //use GPIO13 and GPIO15 as RX and TX bool rxEnabled;
int available(void) override; bool txEnabled;
int peek(void) override; uint8_t rxPin;
int read(void) override; uint8_t txPin;
int availableForWrite(void); } uart_t;
void flush(void) override;
size_t write(uint8_t) override;
inline size_t write(unsigned long 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
operator bool() const;
void setDebugOutput(bool); class HardwareSerial: public Stream {
public:
HardwareSerial(UARTnr_t uart_nr);
protected: void begin(unsigned long baud) {
friend void uart0_interrupt_handler(uart_t* uart); begin(baud, 0);
void _rx_complete_irq(char c); }
void _tx_empty_irq(void); void begin(unsigned long, uint8_t);
void end();
void swap(); //use GPIO13 and GPIO15 as RX and TX
int available(void) override;
int peek(void) override;
int read(void) override;
int availableForWrite(void);
void flush(void) override;
size_t write(uint8_t) override;
inline size_t write(unsigned long 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
operator bool() const;
protected: void setDebugOutput(bool);
uart_t* _uart; bool isTxEnabled(void);
cbuf* _tx_buffer; bool isRxEnabled(void);
cbuf* _rx_buffer;
bool _written; protected:
friend void uart_interrupt_handler(uart_t* uart);
void _rx_complete_irq(char c);
void _tx_empty_irq(void);
protected:
UARTnr_t _uart_nr;
uart_t* _uart;
cbuf* _tx_buffer;
cbuf* _rx_buffer;
bool _written;
}; };
extern HardwareSerial Serial; extern HardwareSerial Serial;
extern HardwareSerial Serial1;
#endif #endif