From 15b434f5e25581d438a84a571600ac2c9c27d6e9 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Fri, 21 Nov 2014 12:15:50 +0300 Subject: [PATCH] Fix build errors --- cores/esp8266/Arduino.h | 29 +- cores/esp8266/HardwareSerial.cpp | 468 +++++++++++++++---------- cores/esp8266/HardwareSerial.h | 115 ++---- cores/esp8266/HardwareSerial_private.h | 123 ------- cores/esp8266/WCharacter.h | 3 + cores/esp8266/WString.cpp | 12 +- cores/esp8266/abi.cpp | 4 +- cores/esp8266/new.cpp | 15 +- 8 files changed, 335 insertions(+), 434 deletions(-) delete mode 100644 cores/esp8266/HardwareSerial_private.h diff --git a/cores/esp8266/Arduino.h b/cores/esp8266/Arduino.h index 92bdc63a6..ea0917c5e 100644 --- a/cores/esp8266/Arduino.h +++ b/cores/esp8266/Arduino.h @@ -138,27 +138,6 @@ void loop(void); // greater than 255, so we can't store them in uint8_t's. #define PROGMEM -extern const uint16_t PROGMEM port_to_mode_PGM[]; -extern const uint16_t PROGMEM port_to_input_PGM[]; -extern const uint16_t PROGMEM port_to_output_PGM[]; - -extern const uint8_t PROGMEM digital_pin_to_port_PGM[]; -// extern const uint8_t PROGMEM digital_pin_to_bit_PGM[]; -extern const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[]; -extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; - -// Get the bit location within the hardware port of the given virtual pin. -// This comes from the pins_*.c file for the active board configuration. -// -// These perform slightly better as macros compared to inline functions -// -#define digitalPinToPort(P) ( pgm_read_byte( digital_pin_to_port_PGM + (P) ) ) -#define digitalPinToBitMask(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM + (P) ) ) -#define digitalPinToTimer(P) ( pgm_read_byte( digital_pin_to_timer_PGM + (P) ) ) -#define analogInPinToBit(P) (P) -#define portOutputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_output_PGM + (P))) ) -#define portInputRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_input_PGM + (P))) ) -#define portModeRegister(P) ( (volatile uint8_t *)( pgm_read_word( port_to_mode_PGM + (P))) ) #define NOT_A_PIN 0 #define NOT_A_PORT 0 @@ -208,14 +187,8 @@ extern const uint8_t PROGMEM digital_pin_to_timer_PGM[]; #include "WCharacter.h" #include "WString.h" -/* -#include "HardwareSerial.h" -#include "USBAPI.h" -#if defined(HAVE_HWSERIAL0) && defined(HAVE_CDCSERIAL) -#error "Targets with both UART0 and CDC serial not supported" -#endif -*/ +#include "HardwareSerial.h" uint16_t makeWord(uint16_t w); uint16_t makeWord(byte h, byte l); diff --git a/cores/esp8266/HardwareSerial.cpp b/cores/esp8266/HardwareSerial.cpp index 41935e320..9708f7d91 100644 --- a/cores/esp8266/HardwareSerial.cpp +++ b/cores/esp8266/HardwareSerial.cpp @@ -1,25 +1,25 @@ /* - HardwareSerial.cpp - Hardware serial library for Wiring - Copyright (c) 2006 Nicholas Zambetti. All right reserved. + HardwareSerial.cpp - 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 - - Modified 23 November 2006 by David A. Mellis - Modified 28 September 2010 by Mark Sproul - Modified 14 August 2012 by Alarus - Modified 3 December 2013 by Matthijs Kooijman + 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 23 November 2006 by David A. Mellis + Modified 28 September 2010 by Mark Sproul + Modified 14 August 2012 by Alarus + Modified 3 December 2013 by Matthijs Kooijman */ #include @@ -28,225 +28,305 @@ #include #include "Arduino.h" +extern "C" { +#include "osapi.h" +#include "ets_sys.h" +#include "mem.h" +#include "uart_register.h" +#include "user_interface.h" +} + #include "HardwareSerial.h" -#include "HardwareSerial_private.h" -// this next line disables the entire HardwareSerial.cpp, -// this is so I can support Attiny series and any other chip without a uart -#if defined(HAVE_HWSERIAL0) || defined(HAVE_HWSERIAL1) || defined(HAVE_HWSERIAL2) || defined(HAVE_HWSERIAL3) +typedef void (*uart_rx_handler_t)(char); -// SerialEvent functions are weak, so when the user doesn't define them, -// the linker just sets their address to 0 (which is checked below). -// The Serialx_available is just a wrapper around Serialx.available(), -// but we can refer to it weakly so we don't pull in the entire -// HardwareSerial instance if the user doesn't also refer to it. -#if defined(HAVE_HWSERIAL0) - void serialEvent() __attribute__((weak)); - bool Serial0_available() __attribute__((weak)); -#endif +uart_t* uart0_init(int baud_rate, uart_rx_handler_t rx_handler); +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 -#if defined(HAVE_HWSERIAL1) - void serialEvent1() __attribute__((weak)); - bool Serial1_available() __attribute__((weak)); -#endif +void uart_set_debug(int enabled); +int uart_get_debug(); -#if defined(HAVE_HWSERIAL2) - void serialEvent2() __attribute__((weak)); - bool Serial2_available() __attribute__((weak)); -#endif - -#if defined(HAVE_HWSERIAL3) - void serialEvent3() __attribute__((weak)); - bool Serial3_available() __attribute__((weak)); -#endif - -void serialEventRun(void) +struct uart_ { -#if defined(HAVE_HWSERIAL0) - if (Serial0_available && serialEvent && Serial0_available()) serialEvent(); -#endif -#if defined(HAVE_HWSERIAL1) - if (Serial1_available && serialEvent1 && Serial1_available()) serialEvent1(); -#endif -#if defined(HAVE_HWSERIAL2) - if (Serial2_available && serialEvent2 && Serial2_available()) serialEvent2(); -#endif -#if defined(HAVE_HWSERIAL3) - if (Serial3_available && serialEvent3 && Serial3_available()) serialEvent3(); -#endif + int baud_rate; + uart_rx_handler_t rx_handler; +}; + + + +#define UART_TX_FIFO_SIZE 0x7f + +void uart0_rx_handler(uart_t* uart) +{ + if (READ_PERI_REG(UART_INT_ST(0)) & 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; + + for(int cnt = 0; cnt < rx_count; ++cnt) + { + char c = READ_PERI_REG(UART_FIFO(0)) & 0xFF; + (*uart->rx_handler)(c); + } + } + WRITE_PERI_REG(UART_INT_CLR(0), UART_RXFIFO_FULL_INT_CLR); + } } -// Actual interrupt handlers ////////////////////////////////////////////////////////////// - -void HardwareSerial::_tx_udr_empty_irq(void) +void uart0_wait_for_tx_fifo(size_t size_needed) { - // If interrupts are enabled, there must be more data in the output - // buffer. Send the next byte - unsigned char c = _tx_buffer[_tx_buffer_tail]; - _tx_buffer_tail = (_tx_buffer_tail + 1) % SERIAL_TX_BUFFER_SIZE; - - *_udr = c; - - // clear the TXC bit -- "can be cleared by writing a one to its bit - // location". This makes sure flush() won't return until the bytes - // actually got written - sbi(*_ucsra, TXC0); - - if (_tx_buffer_head == _tx_buffer_tail) { - // Buffer empty, so disable interrupts - cbi(*_ucsrb, UDRIE0); - } + 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; + } } -// Public Methods ////////////////////////////////////////////////////////////// +void uart0_wait_for_transmit(uart_t* uart) +{ + uart0_wait_for_tx_fifo(UART_TX_FIFO_SIZE); +} + +void uart0_transmit_char(uart_t* uart, char c) +{ + WRITE_PERI_REG(UART_FIFO(0), c); +} + +void 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; + + uart0_wait_for_tx_fifo(part_size); + for(;part_size;--part_size, ++buf) + WRITE_PERI_REG(UART_FIFO(0), *buf); + } +} + +void 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 uart0_interrupt_enable(uart_t* uart) +{ + WRITE_PERI_REG(UART_INT_CLR(0), 0x1ff); + ETS_UART_INTR_ATTACH(&uart0_rx_handler, uart); + SET_PERI_REG_MASK(UART_INT_ENA(0), UART_RXFIFO_FULL_INT_ENA); + ETS_UART_INTR_ENABLE(); +} + +void uart0_interrupt_disable(uart_t* uart) +{ + SET_PERI_REG_MASK(UART_INT_ENA(0), 0); + ETS_UART_INTR_DISABLE(); +} + +void uart0_set_baudrate(uart_t* uart, int baud_rate) +{ + uart->baud_rate = baud_rate; + uart_div_modify(0, UART_CLK_FREQ / (uart->baud_rate)); +} + +int uart0_get_baudrate(uart_t* uart) +{ + return uart->baud_rate; +} + +uart_t* uart0_init(int baudrate, uart_rx_handler_t rx_handler) +{ + uart_t* uart = (uart_t*) os_malloc(sizeof(uart_t)); + + uart->rx_handler = rx_handler; + + PIN_PULLUP_DIS(PERIPHS_IO_MUX_U0TXD_U); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD); + + uart0_set_baudrate(uart, baudrate); + WRITE_PERI_REG(UART_CONF0(0), 0x3 << UART_BIT_NUM_S); // 8n1 + + uart0_flush(uart); + uart0_interrupt_enable(uart); + + WRITE_PERI_REG(UART_CONF1(0), ((0x01 & UART_RXFIFO_FULL_THRHD) << UART_RXFIFO_FULL_THRHD_S)); + + return uart; +} + +void uart0_uninit(uart_t* uart) +{ + uart0_interrupt_disable(uart); + // TODO: revert pin functions + os_free(uart); +} + + +void +uart_ignore_char(char c) +{ +} + +void +uart_write_char(char c) +{ + if (c == '\n') + WRITE_PERI_REG(UART_FIFO(0), '\r'); + + WRITE_PERI_REG(UART_FIFO(0), c); +} + +int s_uart_debug_enabled = 1; +void uart_set_debug(int enabled) +{ + s_uart_debug_enabled = enabled; + if (enabled) + ets_install_putc1((void *)&uart_write_char); + else + ets_install_putc1((void *)&uart_ignore_char); +} + +int uart_get_debug() +{ + return s_uart_debug_enabled; +} + +HardwareSerial Serial; + +void serial_rx_handler(char c) +{ + Serial._rx_complete_irq(c); +} void HardwareSerial::begin(unsigned long baud, byte config) { - // Try u2x mode first - uint16_t baud_setting = (F_CPU / 4 / baud - 1) / 2; - *_ucsra = 1 << U2X0; - - // hardcoded exception for 57600 for compatibility with the bootloader - // shipped with the Duemilanove and previous boards and the firmware - // on the 8U2 on the Uno and Mega 2560. Also, The baud_setting cannot - // be > 4095, so switch back to non-u2x mode if the baud rate is too - // low. - if (((F_CPU == 16000000UL) && (baud == 57600)) || (baud_setting >4095)) - { - *_ucsra = 0; - baud_setting = (F_CPU / 8 / baud - 1) / 2; - } - - // assign the baud_setting, a.k.a. ubrr (USART Baud Rate Register) - *_ubrrh = baud_setting >> 8; - *_ubrrl = baud_setting; - - _written = false; - - //set the data bits, parity, and stop bits -#if defined(__AVR_ATmega8__) - config |= 0x80; // select UCSRC register (shared with UBRRH) -#endif - *_ucsrc = config; - - sbi(*_ucsrb, RXEN0); - sbi(*_ucsrb, TXEN0); - sbi(*_ucsrb, RXCIE0); - cbi(*_ucsrb, UDRIE0); + _uart = uart0_init(baud, &serial_rx_handler); } void HardwareSerial::end() { - // wait for transmission of outgoing data - while (_tx_buffer_head != _tx_buffer_tail) - ; - - cbi(*_ucsrb, RXEN0); - cbi(*_ucsrb, TXEN0); - cbi(*_ucsrb, RXCIE0); - cbi(*_ucsrb, UDRIE0); - - // clear any received data - _rx_buffer_head = _rx_buffer_tail; + uart0_uninit(_uart); } int HardwareSerial::available(void) { - return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail)) % SERIAL_RX_BUFFER_SIZE; + return ((unsigned int)(SERIAL_RX_BUFFER_SIZE + _rx_buffer_head - _rx_buffer_tail)) % SERIAL_RX_BUFFER_SIZE; } int HardwareSerial::peek(void) { - if (_rx_buffer_head == _rx_buffer_tail) { - return -1; - } else { - return _rx_buffer[_rx_buffer_tail]; - } + if (_rx_buffer_head == _rx_buffer_tail) { + return -1; + } else { + return _rx_buffer[_rx_buffer_tail]; + } } int HardwareSerial::read(void) { - // if the head isn't ahead of the tail, we don't have any characters - if (_rx_buffer_head == _rx_buffer_tail) { - return -1; - } else { - unsigned char c = _rx_buffer[_rx_buffer_tail]; - _rx_buffer_tail = (rx_buffer_index_t)(_rx_buffer_tail + 1) % SERIAL_RX_BUFFER_SIZE; - return c; - } + // if the head isn't ahead of the tail, we don't have any characters + if (_rx_buffer_head == _rx_buffer_tail) { + return -1; + } else { + unsigned char c = _rx_buffer[_rx_buffer_tail]; + _rx_buffer_tail = (rx_buffer_index_t)(_rx_buffer_tail + 1) % SERIAL_RX_BUFFER_SIZE; + return c; + } } int HardwareSerial::availableForWrite(void) { -#if (SERIAL_TX_BUFFER_SIZE>256) - uint8_t oldSREG = SREG; - cli(); -#endif - tx_buffer_index_t head = _tx_buffer_head; - tx_buffer_index_t tail = _tx_buffer_tail; -#if (SERIAL_TX_BUFFER_SIZE>256) - SREG = oldSREG; -#endif - if (head >= tail) return SERIAL_TX_BUFFER_SIZE - 1 - head + tail; - return tail - head - 1; + tx_buffer_index_t head = _tx_buffer_head; + tx_buffer_index_t tail = _tx_buffer_tail; + if (head >= tail) return SERIAL_TX_BUFFER_SIZE - 1 - head + tail; + return tail - head - 1; } + void HardwareSerial::flush() { - // If we have never written a byte, no need to flush. This special - // case is needed since there is no way to force the TXC (transmit - // complete) bit to 1 during initialization - if (!_written) - return; - - while (bit_is_set(*_ucsrb, UDRIE0) || bit_is_clear(*_ucsra, TXC0)) { - if (bit_is_clear(SREG, SREG_I) && bit_is_set(*_ucsrb, UDRIE0)) - // Interrupts are globally disabled, but the DR empty - // interrupt should be enabled, so poll the DR empty flag to - // prevent deadlock - if (bit_is_set(*_ucsra, UDRE0)) - _tx_udr_empty_irq(); - } - // If we get here, nothing is queued anymore (DRIE is disabled) and - // the hardware finished tranmission (TXC is set). + if (!_written) + return; } + size_t HardwareSerial::write(uint8_t c) { - // If the buffer and the data register is empty, just write the byte - // to the data register and be done. This shortcut helps - // significantly improve the effective datarate at high (> - // 500kbit/s) bitrates, where interrupt overhead becomes a slowdown. - if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(*_ucsra, UDRE0)) { - *_udr = c; - sbi(*_ucsra, TXC0); - return 1; - } - tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE; - - // If the output buffer is full, there's nothing for it other than to - // wait for the interrupt handler to empty it a bit - while (i == _tx_buffer_tail) { - if (bit_is_clear(SREG, SREG_I)) { - // Interrupts are disabled, so we'll have to poll the data - // register empty flag ourselves. If it is set, pretend an - // interrupt has happened and call the handler to free up - // space for us. - if(bit_is_set(*_ucsra, UDRE0)) - _tx_udr_empty_irq(); - } else { - // nop, the interrupt handler will free up space for us - } - } + WRITE_PERI_REG(UART_FIFO(0), c); + // // If the buffer and the data register is empty, just write the byte + // // to the data register and be done. This shortcut helps + // // significantly improve the effective datarate at high (> + // // 500kbit/s) bitrates, where interrupt overhead becomes a slowdown. + // if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(*_ucsra, UDRE0)) { + // *_udr = c; + // sbi(*_ucsra, TXC0); + // return 1; + // } + // tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE; + + // // If the output buffer is full, there's nothing for it other than to + // // wait for the interrupt handler to empty it a bit + // while (i == _tx_buffer_tail) { + // if (bit_is_clear(SREG, SREG_I)) { + // // Interrupts are disabled, so we'll have to poll the data + // // register empty flag ourselves. If it is set, pretend an + // // interrupt has happened and call the handler to free up + // // space for us. + // if(bit_is_set(*_ucsra, UDRE0)) + // _tx_udr_empty_irq(); + // } else { + // // nop, the interrupt handler will free up space for us + // } + // } - _tx_buffer[_tx_buffer_head] = c; - _tx_buffer_head = i; - - sbi(*_ucsrb, UDRIE0); - _written = true; - - return 1; + // _tx_buffer[_tx_buffer_head] = c; + // _tx_buffer_head = i; + + // sbi(*_ucsrb, UDRIE0); + // _written = true; + + // return 1; +} + +void HardwareSerial::_rx_complete_irq(char c) +{ + rx_buffer_index_t i = (unsigned int)(_rx_buffer_head + 1) % SERIAL_RX_BUFFER_SIZE; + + if (i != _rx_buffer_tail) { + _rx_buffer[_rx_buffer_head] = c; + _rx_buffer_head = i; + } } -#endif // whole file +// void HardwareSerial::_tx_udr_empty_irq(void) +// { +// // If interrupts are enabled, there must be more data in the output +// // buffer. Send the next byte +// unsigned char c = _tx_buffer[_tx_buffer_tail]; +// _tx_buffer_tail = (_tx_buffer_tail + 1) % SERIAL_TX_BUFFER_SIZE; + +// *_udr = c; + +// // clear the TXC bit -- "can be cleared by writing a one to its bit +// // location". This makes sure flush() won't return until the bytes +// // actually got written +// sbi(*_ucsra, TXC0); + +// if (_tx_buffer_head == _tx_buffer_tail) { +// // Buffer empty, so disable interrupts +// cbi(*_ucsrb, UDRIE0); +// } +// } + diff --git a/cores/esp8266/HardwareSerial.h b/cores/esp8266/HardwareSerial.h index 7dc2aa98c..8c4810fc3 100644 --- a/cores/esp8266/HardwareSerial.h +++ b/cores/esp8266/HardwareSerial.h @@ -28,67 +28,46 @@ #include "Stream.h" -// Define constants and variables for buffering incoming serial data. We're -// using a ring buffer (I think), in which head is the index of the location -// to which to write the next incoming character and tail is the index of the -// location from which to read. -// NOTE: a "power of 2" buffer size is reccomended to dramatically -// optimize all the modulo operations for ring buffers. #if !(defined(SERIAL_TX_BUFFER_SIZE) && defined(SERIAL_RX_BUFFER_SIZE)) -#if (RAMEND < 1000) -#define SERIAL_TX_BUFFER_SIZE 16 -#define SERIAL_RX_BUFFER_SIZE 16 -#else #define SERIAL_TX_BUFFER_SIZE 64 #define SERIAL_RX_BUFFER_SIZE 64 #endif -#endif -#if (SERIAL_TX_BUFFER_SIZE>256) -typedef uint16_t tx_buffer_index_t; -#else -typedef uint8_t tx_buffer_index_t; -#endif -#if (SERIAL_RX_BUFFER_SIZE>256) -typedef uint16_t rx_buffer_index_t; -#else -typedef uint8_t rx_buffer_index_t; -#endif -// Define config for Serial.begin(baud, config); -#define SERIAL_5N1 0x00 -#define SERIAL_6N1 0x02 -#define SERIAL_7N1 0x04 -#define SERIAL_8N1 0x06 -#define SERIAL_5N2 0x08 -#define SERIAL_6N2 0x0A -#define SERIAL_7N2 0x0C -#define SERIAL_8N2 0x0E -#define SERIAL_5E1 0x20 -#define SERIAL_6E1 0x22 -#define SERIAL_7E1 0x24 -#define SERIAL_8E1 0x26 -#define SERIAL_5E2 0x28 -#define SERIAL_6E2 0x2A -#define SERIAL_7E2 0x2C -#define SERIAL_8E2 0x2E -#define SERIAL_5O1 0x30 -#define SERIAL_6O1 0x32 -#define SERIAL_7O1 0x34 -#define SERIAL_8O1 0x36 -#define SERIAL_5O2 0x38 -#define SERIAL_6O2 0x3A -#define SERIAL_7O2 0x3C -#define SERIAL_8O2 0x3E +typedef uint32_t tx_buffer_index_t; +typedef uint32_t rx_buffer_index_t; +// // Define config for Serial.begin(baud, config); +// #define SERIAL_5N1 0x00 +// #define SERIAL_6N1 0x02 +// #define SERIAL_7N1 0x04 +// #define SERIAL_8N1 0x06 +// #define SERIAL_5N2 0x08 +// #define SERIAL_6N2 0x0A +// #define SERIAL_7N2 0x0C +// #define SERIAL_8N2 0x0E +// #define SERIAL_5E1 0x20 +// #define SERIAL_6E1 0x22 +// #define SERIAL_7E1 0x24 +// #define SERIAL_8E1 0x26 +// #define SERIAL_5E2 0x28 +// #define SERIAL_6E2 0x2A +// #define SERIAL_7E2 0x2C +// #define SERIAL_8E2 0x2E +// #define SERIAL_5O1 0x30 +// #define SERIAL_6O1 0x32 +// #define SERIAL_7O1 0x34 +// #define SERIAL_8O1 0x36 +// #define SERIAL_5O2 0x38 +// #define SERIAL_6O2 0x3A +// #define SERIAL_7O2 0x3C +// #define SERIAL_8O2 0x3E + +struct uart_; +typedef uart_ uart_t; class HardwareSerial : public Stream { protected: - volatile uint8_t * const _ubrrh; - volatile uint8_t * const _ubrrl; - volatile uint8_t * const _ucsra; - volatile uint8_t * const _ucsrb; - volatile uint8_t * const _ucsrc; - volatile uint8_t * const _udr; + uart_t* _uart; // Has any byte been written to the UART since begin() bool _written; @@ -97,18 +76,13 @@ class HardwareSerial : public Stream volatile tx_buffer_index_t _tx_buffer_head; volatile tx_buffer_index_t _tx_buffer_tail; - // Don't put any members after these buffers, since only the first - // 32 bytes of this struct can be accessed quickly using the ldd - // instruction. unsigned char _rx_buffer[SERIAL_RX_BUFFER_SIZE]; unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE]; public: - inline HardwareSerial( - volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, - volatile uint8_t *ucsra, volatile uint8_t *ucsrb, - volatile uint8_t *ucsrc, volatile uint8_t *udr); - void begin(unsigned long baud) { begin(baud, SERIAL_8N1); } + HardwareSerial() : _uart(0) { } + + void begin(unsigned long baud) { begin(baud, 0); } void begin(unsigned long, uint8_t); void end(); virtual int available(void); @@ -125,27 +99,10 @@ class HardwareSerial : public Stream operator bool() { return true; } // Interrupt handlers - Not intended to be called externally - inline void _rx_complete_irq(void); + void _rx_complete_irq(char c); void _tx_udr_empty_irq(void); }; -#if defined(UBRRH) || defined(UBRR0H) - extern HardwareSerial Serial; - #define HAVE_HWSERIAL0 -#endif -#if defined(UBRR1H) - extern HardwareSerial Serial1; - #define HAVE_HWSERIAL1 -#endif -#if defined(UBRR2H) - extern HardwareSerial Serial2; - #define HAVE_HWSERIAL2 -#endif -#if defined(UBRR3H) - extern HardwareSerial Serial3; - #define HAVE_HWSERIAL3 -#endif - -extern void serialEventRun(void) __attribute__((weak)); +extern HardwareSerial Serial; #endif diff --git a/cores/esp8266/HardwareSerial_private.h b/cores/esp8266/HardwareSerial_private.h deleted file mode 100644 index 761a5e559..000000000 --- a/cores/esp8266/HardwareSerial_private.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - HardwareSerial_private.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 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 - - Modified 23 November 2006 by David A. Mellis - Modified 28 September 2010 by Mark Sproul - Modified 14 August 2012 by Alarus -*/ - -#include "wiring_private.h" - -// this next line disables the entire HardwareSerial.cpp, -// this is so I can support Attiny series and any other chip without a uart -#if defined(HAVE_HWSERIAL0) || defined(HAVE_HWSERIAL1) || defined(HAVE_HWSERIAL2) || defined(HAVE_HWSERIAL3) - -// Ensure that the various bit positions we use are available with a 0 -// postfix, so we can always use the values for UART0 for all UARTs. The -// alternative, passing the various values for each UART to the -// HardwareSerial constructor also works, but makes the code bigger and -// slower. -#if !defined(TXC0) -#if defined(TXC) -// Some chips like ATmega8 don't have UPE, only PE. The other bits are -// named as expected. -#if !defined(UPE) && defined(PE) -#define UPE PE -#endif -// On ATmega8, the uart and its bits are not numbered, so there is no TXC0 etc. -#define TXC0 TXC -#define RXEN0 RXEN -#define TXEN0 TXEN -#define RXCIE0 RXCIE -#define UDRIE0 UDRIE -#define U2X0 U2X -#define UPE0 UPE -#define UDRE0 UDRE -#elif defined(TXC1) -// Some devices have uart1 but no uart0 -#define TXC0 TXC1 -#define RXEN0 RXEN1 -#define TXEN0 TXEN1 -#define RXCIE0 RXCIE1 -#define UDRIE0 UDRIE1 -#define U2X0 U2X1 -#define UPE0 UPE1 -#define UDRE0 UDRE1 -#else -#error No UART found in HardwareSerial.cpp -#endif -#endif // !defined TXC0 - -// Check at compiletime that it is really ok to use the bit positions of -// UART0 for the other UARTs as well, in case these values ever get -// changed for future hardware. -#if defined(TXC1) && (TXC1 != TXC0 || RXEN1 != RXEN0 || RXCIE1 != RXCIE0 || \ - UDRIE1 != UDRIE0 || U2X1 != U2X0 || UPE1 != UPE0 || \ - UDRE1 != UDRE0) -#error "Not all bit positions for UART1 are the same as for UART0" -#endif -#if defined(TXC2) && (TXC2 != TXC0 || RXEN2 != RXEN0 || RXCIE2 != RXCIE0 || \ - UDRIE2 != UDRIE0 || U2X2 != U2X0 || UPE2 != UPE0 || \ - UDRE2 != UDRE0) -#error "Not all bit positions for UART2 are the same as for UART0" -#endif -#if defined(TXC3) && (TXC3 != TXC0 || RXEN3 != RXEN0 || RXCIE3 != RXCIE0 || \ - UDRIE3 != UDRIE0 || U3X3 != U3X0 || UPE3 != UPE0 || \ - UDRE3 != UDRE0) -#error "Not all bit positions for UART3 are the same as for UART0" -#endif - -// Constructors //////////////////////////////////////////////////////////////// - -HardwareSerial::HardwareSerial( - volatile uint8_t *ubrrh, volatile uint8_t *ubrrl, - volatile uint8_t *ucsra, volatile uint8_t *ucsrb, - volatile uint8_t *ucsrc, volatile uint8_t *udr) : - _ubrrh(ubrrh), _ubrrl(ubrrl), - _ucsra(ucsra), _ucsrb(ucsrb), _ucsrc(ucsrc), - _udr(udr), - _rx_buffer_head(0), _rx_buffer_tail(0), - _tx_buffer_head(0), _tx_buffer_tail(0) -{ -} - -// Actual interrupt handlers ////////////////////////////////////////////////////////////// - -void HardwareSerial::_rx_complete_irq(void) -{ - if (bit_is_clear(*_ucsra, UPE0)) { - // No Parity error, read byte and store it in the buffer if there is - // room - unsigned char c = *_udr; - rx_buffer_index_t i = (unsigned int)(_rx_buffer_head + 1) % SERIAL_RX_BUFFER_SIZE; - - // if we should be storing the received character into the location - // just before the tail (meaning that the head would advance to the - // current location of the tail), we're about to overflow the buffer - // and so we don't write the character or advance the head. - if (i != _rx_buffer_tail) { - _rx_buffer[_rx_buffer_head] = c; - _rx_buffer_head = i; - } - } else { - // Parity error, read byte but discard it - *_udr; - }; -} - -#endif // whole file diff --git a/cores/esp8266/WCharacter.h b/cores/esp8266/WCharacter.h index 79733b50a..724f2700b 100644 --- a/cores/esp8266/WCharacter.h +++ b/cores/esp8266/WCharacter.h @@ -21,6 +21,9 @@ #define Character_h #include +#define isascii(__c) ((unsigned)(__c)<=0177) +#define toascii(__c) ((__c)&0177) + // WCharacter.h prototypes inline boolean isAlphaNumeric(int c) __attribute__((always_inline)); diff --git a/cores/esp8266/WString.cpp b/cores/esp8266/WString.cpp index ea995945a..1e4019e38 100644 --- a/cores/esp8266/WString.cpp +++ b/cores/esp8266/WString.cpp @@ -21,6 +21,12 @@ #include "WString.h" #include "stdlib_noniso.h" +extern "C" { +#include "osapi.h" +#include "ets_sys.h" +#include "mem.h" +} + /*********************************************/ /* Constructors */ /*********************************************/ @@ -115,7 +121,7 @@ String::String(double value, unsigned char decimalPlaces) String::~String() { - free(buffer); + os_free(buffer); } /*********************************************/ @@ -131,7 +137,7 @@ inline void String::init(void) void String::invalidate(void) { - if (buffer) free(buffer); + if (buffer) os_free(buffer); buffer = NULL; capacity = len = 0; } @@ -183,7 +189,7 @@ void String::move(String &rhs) rhs.len = 0; return; } else { - free(buffer); + os_free(buffer); } } buffer = rhs.buffer; diff --git a/cores/esp8266/abi.cpp b/cores/esp8266/abi.cpp index 8d719b8e6..294ed3c30 100644 --- a/cores/esp8266/abi.cpp +++ b/cores/esp8266/abi.cpp @@ -24,12 +24,12 @@ extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__)); void __cxa_pure_virtual(void) { // We might want to write some diagnostics to uart in this case //std::terminate(); - abort(); + while(true) {} } void __cxa_deleted_virtual(void) { // We might want to write some diagnostics to uart in this case //std::terminate(); - abort(); + while(true) {} } diff --git a/cores/esp8266/new.cpp b/cores/esp8266/new.cpp index cf6f89c17..9c52a7e0e 100644 --- a/cores/esp8266/new.cpp +++ b/cores/esp8266/new.cpp @@ -16,21 +16,26 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#include +extern "C" { +#include "osapi.h" +#include "ets_sys.h" +#include "mem.h" +} + void *operator new(size_t size) { - return malloc(size); + return os_malloc(size); } void *operator new[](size_t size) { - return malloc(size); + return os_malloc(size); } void operator delete(void * ptr) { - free(ptr); + os_free(ptr); } void operator delete[](void * ptr) { - free(ptr); + os_free(ptr); }