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,24 +1,26 @@
/*
HardwareSerial.cpp - esp8266 UART support
HardwareSerial.cpp - esp8266 UART support
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
This file is part of the esp8266 core for Arduino environment.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
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,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
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>
@ -37,316 +39,540 @@ extern "C" {
#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
void ICACHE_FLASH_ATTR uart0_interrupt_handler(uart_t* uart)
{
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;
/**
* UART GPIOs
*
* UART0 TX: 1 or 2
* UART0 RX: 3
*
* UART0 SWAP TX: 15
* UART0 SWAP RX: 13
*
*
* 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--)
{
char c = READ_PERI_REG(UART_FIFO(0)) & 0xFF;
Serial._rx_complete_irq(c);
}
}
WRITE_PERI_REG(UART_INT_CLR(0), UART_RXFIFO_FULL_INT_CLR);
}
if (status & UART_TXFIFO_EMPTY_INT_ST)
{
WRITE_PERI_REG(UART_INT_CLR(0), UART_TXFIFO_EMPTY_INT_CLR);
Serial._tx_empty_irq();
}
// ####################################################################################################
// ####################################################################################################
// ####################################################################################################
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;
Serial._rx_complete_irq(c);
}
}
WRITE_PERI_REG(UART_INT_CLR(0), UART_RXFIFO_FULL_INT_CLR);
}
}
if(Serial.isTxEnabled()) {
if(status & UART_TXFIFO_EMPTY_INT_ST) {
WRITE_PERI_REG(UART_INT_CLR(0), UART_TXFIFO_EMPTY_INT_CLR);
Serial._tx_empty_irq();
}
}
// -------------- UART 1 --------------
status = READ_PERI_REG(UART_INT_ST(1));
if(Serial1.isRxEnabled()) {
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;
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();
}
}
}
void ICACHE_FLASH_ATTR uart0_wait_for_tx_fifo(size_t size_needed)
{
while (true)
{
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))
break;
}
// ####################################################################################################
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;
}
}
}
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);
size_t ICACHE_FLASH_ATTR uart_get_tx_fifo_room(uart_t* uart) {
if(uart->txEnabled) {
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_wait_for_transmit(uart_t* uart)
{
uart0_wait_for_tx_fifo(UART_TX_FIFO_SIZE);
void ICACHE_FLASH_ATTR uart_wait_for_transmit(uart_t* uart) {
if(uart->txEnabled) {
uart_wait_for_tx_fifo(uart, UART_TX_FIFO_SIZE);
}
}
void ICACHE_FLASH_ATTR uart0_transmit_char(uart_t* uart, char c)
{
WRITE_PERI_REG(UART_FIFO(0), c);
void ICACHE_FLASH_ATTR uart_transmit_char(uart_t* uart, char c) {
if(uart->txEnabled) {
WRITE_PERI_REG(UART_FIFO(uart->uart_nr), c);
}
}
void ICACHE_FLASH_ATTR uart0_transmit(uart_t* uart, const char* buf, size_t size)
{
while (size)
{
size_t part_size = (size > UART_TX_FIFO_SIZE) ? UART_TX_FIFO_SIZE : size;
size -= part_size;
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 -= part_size;
uart0_wait_for_tx_fifo(part_size);
for(;part_size;--part_size, ++buf)
WRITE_PERI_REG(UART_FIFO(0), *buf);
}
uart_wait_for_tx_fifo(uart, part_size);
for(; part_size; --part_size, ++buf)
WRITE_PERI_REG(UART_FIFO(uart->uart_nr), *buf);
}
}
}
void ICACHE_FLASH_ATTR uart0_flush(uart_t* uart)
{
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);
void ICACHE_FLASH_ATTR uart_flush(uart_t* uart) {
uint32_t tmp = 0x00000000;
if(uart->rxEnabled) {
tmp |= UART_RXFIFO_RST;
}
if(uart->txEnabled) {
tmp |= UART_TXFIFO_RST;
}
SET_PERI_REG_MASK(UART_CONF0(uart->uart_nr), tmp);
CLEAR_PERI_REG_MASK(UART_CONF0(uart->uart_nr), tmp);
}
void ICACHE_FLASH_ATTR uart0_interrupt_enable(uart_t* uart)
{
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);
ETS_UART_INTR_ENABLE();
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();
}
void ICACHE_FLASH_ATTR uart0_interrupt_disable(uart_t* uart)
{
CLEAR_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA);
ETS_UART_INTR_DISABLE();
void ICACHE_FLASH_ATTR uart_interrupt_disable(uart_t* uart) {
if(uart->rxEnabled) {
CLEAR_PERI_REG_MASK(UART_INT_ENA(uart->uart_nr), UART_RXFIFO_FULL_INT_ENA);
}
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()
{
SET_PERI_REG_MASK(UART_INT_ENA(0), UART_TXFIFO_EMPTY_INT_ENA);
void ICACHE_FLASH_ATTR uart_arm_tx_interrupt(uart_t* uart) {
if(uart->txEnabled) {
SET_PERI_REG_MASK(UART_INT_ENA(uart->uart_nr), UART_TXFIFO_EMPTY_INT_ENA);
}
}
void ICACHE_FLASH_ATTR uart0_disarm_tx_interrupt()
{
CLEAR_PERI_REG_MASK(UART_INT_ENA(0), UART_TXFIFO_EMPTY_INT_ENA);
void ICACHE_FLASH_ATTR uart_disarm_tx_interrupt(uart_t* uart) {
if(uart->txEnabled) {
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)
{
uart->baud_rate = baud_rate;
uart_div_modify(0, UART_CLK_FREQ / (uart->baud_rate));
void ICACHE_FLASH_ATTR uart_set_baudrate(uart_t* uart, int baud_rate) {
uart->baud_rate = baud_rate;
uart_div_modify(uart->uart_nr, UART_CLK_FREQ / (uart->baud_rate));
}
int ICACHE_FLASH_ATTR uart0_get_baudrate(uart_t* uart)
{
return uart->baud_rate;
int ICACHE_FLASH_ATTR uart_get_baudrate(uart_t* uart) {
return uart->baud_rate;
}
uart_t* ICACHE_FLASH_ATTR uart0_init(int baudrate)
{
uart_t* uart = (uart_t*) os_malloc(sizeof(uart_t));
uart_t* ICACHE_FLASH_ATTR uart_init(UARTnr_t uart_nr, int baudrate) {
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);
uint32_t conf1 = 0x00000000;
uart_t* uart = (uart_t*) os_malloc(sizeof(uart_t));
uart->uart_nr = uart_nr;
uart0_set_baudrate(uart, baudrate);
WRITE_PERI_REG(UART_CONF0(0), 0x3 << UART_BIT_NUM_S); // 8n1
switch(uart->uart_nr) {
case UART0:
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);
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_flush(uart);
uart0_interrupt_enable(uart);
uart_flush(uart);
uart_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));
if(uart->rxEnabled) {
conf1 |= ((0x01 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S);
}
return uart;
if(uart->txEnabled) {
conf1 |= ((0x20 & UART_TXFIFO_EMPTY_THRHD) << UART_TXFIFO_EMPTY_THRHD_S);
}
WRITE_PERI_REG(UART_CONF1(uart->uart_nr), conf1);
return uart;
}
void ICACHE_FLASH_ATTR uart0_uninit(uart_t* uart)
{
uart0_interrupt_disable(uart);
// TODO: revert pin functions
os_free(uart);
void ICACHE_FLASH_ATTR uart_uninit(uart_t* uart) {
uart_interrupt_disable(uart);
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_GPIO15);
break;
}
pinMode(uart->rxPin , INPUT);
pinMode(uart->txPin , INPUT);
os_free(uart);
}
void ICACHE_FLASH_ATTR uart0_swap(uart_t* uart)
{
PIN_FUNC_SELECT(PERIPHS_IO_MUX_MTCK_U, FUNC_UART0_CTS);
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_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_PULLUP_EN(PERIPHS_IO_MUX_MTDO_U);
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_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 uart_ignore_char(char c) {
}
void ICACHE_FLASH_ATTR
uart_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 uart0_write_char(char c) {
if(c == '\n') {
WRITE_PERI_REG(UART_FIFO(0), '\r');
}
WRITE_PERI_REG(UART_FIFO(0), c);
}
bool s_uart_debug_enabled = true;
void ICACHE_FLASH_ATTR uart_set_debug(bool enabled)
{
s_uart_debug_enabled = enabled;
if (enabled)
{
system_set_os_print(1);
ets_install_putc1((void *)&uart_write_char);
}
else
ets_install_putc1((void *)&uart_ignore_char);
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);
}
bool ICACHE_FLASH_ATTR uart_get_debug()
{
return s_uart_debug_enabled;
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;
}
}
ICACHE_FLASH_ATTR HardwareSerial::HardwareSerial() :
_uart(0), _rx_buffer(0), _tx_buffer(0)
{
UARTnr_t ICACHE_FLASH_ATTR uart_get_debug() {
return s_uart_debug_nr;
}
void ICACHE_FLASH_ATTR HardwareSerial::begin(unsigned long baud, byte config)
{
_rx_buffer = new cbuf(SERIAL_RX_BUFFER_SIZE);
_tx_buffer = new cbuf(SERIAL_TX_BUFFER_SIZE);
uart_set_debug(false);
_uart = uart0_init(baud);
_written = false;
delay(1);
// ####################################################################################################
// ####################################################################################################
// ####################################################################################################
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::end()
{
uart0_uninit(_uart);
delete _rx_buffer;
delete _tx_buffer;
_uart = 0;
_rx_buffer = 0;
_tx_buffer = 0;
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::swap()
{
uart0_swap(_uart);
pinMode(1, INPUT);
pinMode(3, INPUT);
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::setDebugOutput(bool en)
{
uart_set_debug(en);
void ICACHE_FLASH_ATTR HardwareSerial::swap() {
uart_swap(_uart);
}
int ICACHE_FLASH_ATTR HardwareSerial::available(void)
{
return static_cast<int>(_rx_buffer->getSize());
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);
}
}
}
int ICACHE_FLASH_ATTR HardwareSerial::peek(void)
{
return _rx_buffer->peek();
bool ICACHE_FLASH_ATTR HardwareSerial::isTxEnabled(void) {
if(_uart == 0) return false;
return _uart->txEnabled;
}
int ICACHE_FLASH_ATTR HardwareSerial::read(void)
{
return _rx_buffer->read();
bool ICACHE_FLASH_ATTR HardwareSerial::isRxEnabled(void) {
if(_uart == 0) return false;
return _uart->rxEnabled;
}
int ICACHE_FLASH_ATTR HardwareSerial::availableForWrite(void)
{
return static_cast<int>(_tx_buffer->room());
int ICACHE_FLASH_ATTR HardwareSerial::available(void) {
if(_uart->rxEnabled) {
return static_cast<int>(_rx_buffer->getSize());
} else {
return 0;
}
}
void ICACHE_FLASH_ATTR HardwareSerial::flush()
{
if (!_written)
return;
while (_tx_buffer->getSize() || uart0_get_tx_fifo_room() < UART_TX_FIFO_SIZE)
yield();
_written = false;
int ICACHE_FLASH_ATTR HardwareSerial::peek(void) {
if(_uart->rxEnabled) {
return _rx_buffer->peek();
} else {
return -1;
}
}
size_t ICACHE_FLASH_ATTR HardwareSerial::write(uint8_t c)
{
_written = true;
size_t room = uart0_get_tx_fifo_room();
if (room > 0 && _tx_buffer->empty())
{
uart0_transmit_char(_uart, c);
if (room < 10)
{
uart0_arm_tx_interrupt();
}
return 1;
}
while (_tx_buffer->room() == 0)
{
yield();
}
_tx_buffer->write(c);
return 1;
int ICACHE_FLASH_ATTR HardwareSerial::read(void) {
if(_uart->rxEnabled) {
return _rx_buffer->read();
} else {
return -1;
}
}
ICACHE_FLASH_ATTR HardwareSerial::operator bool() const
{
return _uart != 0;
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::_rx_complete_irq(char c)
{
_rx_buffer->write(c);
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;
}
void ICACHE_FLASH_ATTR HardwareSerial::_tx_empty_irq(void)
{
size_t queued = _tx_buffer->getSize();
if (!queued)
{
uart0_disarm_tx_interrupt();
return;
}
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;
}
size_t room = uart0_get_tx_fifo_room();
int n = static_cast<int>((queued < room) ? queued : room);
while (n--)
{
uart0_transmit_char(_uart, _tx_buffer->read());
}
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
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
HardwareSerial.h - Hardware serial library for Wiring
Copyright (c) 2006 Nicholas Zambetti. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
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,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Modified 28 September 2010 by Mark Sproul
Modified 14 August 2012 by Alarus
Modified 3 December 2013 by Matthijs Kooijman
Modified 18 December 2014 by Ivan Grokhotkov (esp8266 platform support)
*/
Modified 28 September 2010 by Mark Sproul
Modified 14 August 2012 by Alarus
Modified 3 December 2013 by Matthijs Kooijman
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
#define HardwareSerial_h
@ -59,44 +60,71 @@
// #define SERIAL_8O2 0x3E
class cbuf;
typedef struct uart_ uart_t;
class HardwareSerial : public Stream
{
public:
HardwareSerial();
typedef enum {
UART0 = 0,
UART1 = 1,
UART_NO = 0xFF
} UARTnr_t;
void begin(unsigned long baud) { begin(baud, 0); }
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;
typedef struct {
UARTnr_t uart_nr;
int baud_rate;
bool rxEnabled;
bool txEnabled;
uint8_t rxPin;
uint8_t txPin;
} uart_t;
void setDebugOutput(bool);
class HardwareSerial: public Stream {
public:
HardwareSerial(UARTnr_t uart_nr);
protected:
friend void uart0_interrupt_handler(uart_t* uart);
void _rx_complete_irq(char c);
void _tx_empty_irq(void);
void begin(unsigned long baud) {
begin(baud, 0);
}
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:
uart_t* _uart;
cbuf* _tx_buffer;
cbuf* _rx_buffer;
bool _written;
void setDebugOutput(bool);
bool isTxEnabled(void);
bool isRxEnabled(void);
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 Serial1;
#endif