mirror of
https://github.com/espressif/arduino-esp32
synced 2024-09-21 02:18:29 +00:00
e04f050639
* fix(spelling): Fix misspellings detected by codespell and enable it * change(tools): Push generated binaries to PR --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
369 lines
14 KiB
C++
369 lines
14 KiB
C++
/*
|
|
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 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 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)
|
|
Modified 25 April 2015 by Thomas Flayols (add configuration different from 8N1 in ESP8266)
|
|
Modified 13 October 2018 by Jeroen Döll (add baudrate detection)
|
|
Baudrate detection example usage (detection on Serial1):
|
|
void setup() {
|
|
Serial.begin(115200);
|
|
delay(100);
|
|
Serial.println();
|
|
|
|
Serial1.begin(0, SERIAL_8N1, -1, -1, true, 11000UL); // Passing 0 for baudrate to detect it, the last parameter is a timeout in ms
|
|
|
|
unsigned long detectedBaudRate = Serial1.baudRate();
|
|
if(detectedBaudRate) {
|
|
Serial.printf("Detected baudrate is %lu\n", detectedBaudRate);
|
|
} else {
|
|
Serial.println("No baudrate detected, Serial1 will not work!");
|
|
}
|
|
}
|
|
|
|
Pay attention: the baudrate returned by baudRate() may be rounded, eg 115200 returns 115201
|
|
*/
|
|
|
|
#ifndef HardwareSerial_h
|
|
#define HardwareSerial_h
|
|
|
|
#include <inttypes.h>
|
|
#include <functional>
|
|
#include "Stream.h"
|
|
#include "esp32-hal.h"
|
|
#include "soc/soc_caps.h"
|
|
#include "HWCDC.h"
|
|
#include "USBCDC.h"
|
|
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "freertos/semphr.h"
|
|
|
|
enum SerialConfig {
|
|
SERIAL_5N1 = 0x8000010,
|
|
SERIAL_6N1 = 0x8000014,
|
|
SERIAL_7N1 = 0x8000018,
|
|
SERIAL_8N1 = 0x800001c,
|
|
SERIAL_5N2 = 0x8000030,
|
|
SERIAL_6N2 = 0x8000034,
|
|
SERIAL_7N2 = 0x8000038,
|
|
SERIAL_8N2 = 0x800003c,
|
|
SERIAL_5E1 = 0x8000012,
|
|
SERIAL_6E1 = 0x8000016,
|
|
SERIAL_7E1 = 0x800001a,
|
|
SERIAL_8E1 = 0x800001e,
|
|
SERIAL_5E2 = 0x8000032,
|
|
SERIAL_6E2 = 0x8000036,
|
|
SERIAL_7E2 = 0x800003a,
|
|
SERIAL_8E2 = 0x800003e,
|
|
SERIAL_5O1 = 0x8000013,
|
|
SERIAL_6O1 = 0x8000017,
|
|
SERIAL_7O1 = 0x800001b,
|
|
SERIAL_8O1 = 0x800001f,
|
|
SERIAL_5O2 = 0x8000033,
|
|
SERIAL_6O2 = 0x8000037,
|
|
SERIAL_7O2 = 0x800003b,
|
|
SERIAL_8O2 = 0x800003f
|
|
};
|
|
|
|
typedef uart_mode_t SerialMode;
|
|
typedef uart_hw_flowcontrol_t SerialHwFlowCtrl;
|
|
|
|
typedef enum {
|
|
UART_NO_ERROR,
|
|
UART_BREAK_ERROR,
|
|
UART_BUFFER_FULL_ERROR,
|
|
UART_FIFO_OVF_ERROR,
|
|
UART_FRAME_ERROR,
|
|
UART_PARITY_ERROR
|
|
} hardwareSerial_error_t;
|
|
|
|
#ifndef ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE
|
|
#define ARDUINO_SERIAL_EVENT_TASK_STACK_SIZE 2048
|
|
#endif
|
|
|
|
#ifndef ARDUINO_SERIAL_EVENT_TASK_PRIORITY
|
|
#define ARDUINO_SERIAL_EVENT_TASK_PRIORITY (configMAX_PRIORITIES - 1)
|
|
#endif
|
|
|
|
#ifndef ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE
|
|
#define ARDUINO_SERIAL_EVENT_TASK_RUNNING_CORE -1
|
|
#endif
|
|
|
|
// UART0 pins are defined by default by the bootloader.
|
|
// The definitions for SOC_* should not be changed unless the bootloader pins
|
|
// have changed and you know what you are doing.
|
|
|
|
#ifndef SOC_RX0
|
|
#if CONFIG_IDF_TARGET_ESP32
|
|
#define SOC_RX0 (gpio_num_t)3
|
|
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
|
#define SOC_RX0 (gpio_num_t)44
|
|
#elif CONFIG_IDF_TARGET_ESP32C2
|
|
#define SOC_RX0 (gpio_num_t)19
|
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
|
#define SOC_RX0 (gpio_num_t)20
|
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
|
#define SOC_RX0 (gpio_num_t)17
|
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
|
#define SOC_RX0 (gpio_num_t)23
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef SOC_TX0
|
|
#if CONFIG_IDF_TARGET_ESP32
|
|
#define SOC_TX0 (gpio_num_t)1
|
|
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
|
#define SOC_TX0 (gpio_num_t)43
|
|
#elif CONFIG_IDF_TARGET_ESP32C2
|
|
#define SOC_TX0 (gpio_num_t)20
|
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
|
#define SOC_TX0 (gpio_num_t)21
|
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
|
#define SOC_TX0 (gpio_num_t)16
|
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
|
#define SOC_TX0 (gpio_num_t)24
|
|
#endif
|
|
#endif
|
|
|
|
// Default pins for UART1 are arbitrary, and defined here for convenience.
|
|
|
|
#if SOC_UART_NUM > 1
|
|
#ifndef RX1
|
|
#if CONFIG_IDF_TARGET_ESP32
|
|
#define RX1 (gpio_num_t)26
|
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
|
#define RX1 (gpio_num_t)4
|
|
#elif CONFIG_IDF_TARGET_ESP32C2
|
|
#define RX1 (gpio_num_t)10
|
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
|
#define RX1 (gpio_num_t)18
|
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
|
#define RX1 (gpio_num_t)15
|
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
|
#define RX1 (gpio_num_t)4
|
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
|
#define RX1 (gpio_num_t)0
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef TX1
|
|
#if CONFIG_IDF_TARGET_ESP32
|
|
#define TX1 (gpio_num_t)27
|
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
|
#define TX1 (gpio_num_t)5
|
|
#elif CONFIG_IDF_TARGET_ESP32C2
|
|
#define TX1 (gpio_num_t)18
|
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
|
#define TX1 (gpio_num_t)19
|
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
|
#define TX1 (gpio_num_t)16
|
|
#elif CONFIG_IDF_TARGET_ESP32C6
|
|
#define TX1 (gpio_num_t)5
|
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
|
#define TX1 (gpio_num_t)1
|
|
#endif
|
|
#endif
|
|
#endif /* SOC_UART_NUM > 1 */
|
|
|
|
// Default pins for UART2 are arbitrary, and defined here for convenience.
|
|
|
|
#if SOC_UART_NUM > 2
|
|
#ifndef RX2
|
|
#if CONFIG_IDF_TARGET_ESP32
|
|
#define RX2 (gpio_num_t)4
|
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
|
#define RX2 (gpio_num_t)19
|
|
#endif
|
|
#endif
|
|
|
|
#ifndef TX2
|
|
#if CONFIG_IDF_TARGET_ESP32
|
|
#define TX2 (gpio_num_t)25
|
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
|
#define TX2 (gpio_num_t)20
|
|
#endif
|
|
#endif
|
|
#endif /* SOC_UART_NUM > 2 */
|
|
|
|
typedef std::function<void(void)> OnReceiveCb;
|
|
typedef std::function<void(hardwareSerial_error_t)> OnReceiveErrorCb;
|
|
|
|
class HardwareSerial : public Stream {
|
|
public:
|
|
HardwareSerial(uint8_t uart_nr);
|
|
~HardwareSerial();
|
|
|
|
// setRxTimeout sets the timeout after which onReceive callback will be called (after receiving data, it waits for this time of UART rx inactivity to call the callback fnc)
|
|
// param symbols_timeout defines a timeout threshold in uart symbol periods. Setting 0 symbol timeout disables the callback call by timeout.
|
|
// Maximum timeout setting is calculacted automatically by IDF. If set above the maximum, it is ignored and an error is printed on Serial0 (check console).
|
|
// Examples: Maximum for 11 bits symbol is 92 (SERIAL_8N2, SERIAL_8E1, SERIAL_8O1, etc), Maximum for 10 bits symbol is 101 (SERIAL_8N1).
|
|
// For example symbols_timeout=1 defines a timeout equal to transmission time of one symbol (~11 bit) on current baudrate.
|
|
// For a baudrate of 9600, SERIAL_8N1 (10 bit symbol) and symbols_timeout = 3, the timeout would be 3 / (9600 / 10) = 3.125 ms
|
|
bool setRxTimeout(uint8_t symbols_timeout);
|
|
|
|
// setRxFIFOFull(uint8_t fifoBytes) will set the number of bytes that will trigger UART_INTR_RXFIFO_FULL interrupt and fill up RxRingBuffer
|
|
// This affects some functions such as Serial::available() and Serial.read() because, in a UART flow of receiving data, Serial internal
|
|
// RxRingBuffer will be filled only after these number of bytes arrive or a RX Timeout happens.
|
|
// This parameter can be set to 1 in order to receive byte by byte, but it will also consume more CPU time as the ISR will be activates often.
|
|
bool setRxFIFOFull(uint8_t fifoBytes);
|
|
|
|
// onReceive will setup a callback that will be called whenever an UART interruption occurs (UART_INTR_RXFIFO_FULL or UART_INTR_RXFIFO_TOUT)
|
|
// UART_INTR_RXFIFO_FULL interrupt triggers at UART_FULL_THRESH_DEFAULT bytes received (defined as 120 bytes by default in IDF)
|
|
// UART_INTR_RXFIFO_TOUT interrupt triggers at UART_TOUT_THRESH_DEFAULT symbols passed without any reception (defined as 10 symbols by default in IDF)
|
|
// onlyOnTimeout parameter will define how onReceive will behave:
|
|
// Default: true -- The callback will only be called when RX Timeout happens.
|
|
// Whole stream of bytes will be ready for being read on the callback function at once.
|
|
// This option may lead to Rx Overflow depending on the Rx Buffer Size and number of bytes received in the streaming
|
|
// false -- The callback will be called when FIFO reaches 120 bytes and also on RX Timeout.
|
|
// The stream of incommig bytes will be "split" into blocks of 120 bytes on each callback.
|
|
// This option avoid any sort of Rx Overflow, but leaves the UART packet reassembling work to the Application.
|
|
void onReceive(OnReceiveCb function, bool onlyOnTimeout = false);
|
|
|
|
// onReceive will be called on error events (see hardwareSerial_error_t)
|
|
void onReceiveError(OnReceiveErrorCb function);
|
|
|
|
// eventQueueReset clears all events in the queue (the events that trigger onReceive and onReceiveError) - maybe useful in some use cases
|
|
void eventQueueReset();
|
|
|
|
// When pins are changed, it will detach the previous ones
|
|
// if pin is negative, it won't be set/changed and will be kept as is
|
|
// timeout_ms is used in baudrate detection (ESP32, ESP32S2 only)
|
|
// invert will invert RX/TX polarity
|
|
// rxfifo_full_thrhd if the UART Flow Control Threshold in the UART FIFO (max 127)
|
|
void begin(
|
|
unsigned long baud, uint32_t config = SERIAL_8N1, int8_t rxPin = -1, int8_t txPin = -1, bool invert = false, unsigned long timeout_ms = 20000UL,
|
|
uint8_t rxfifo_full_thrhd = 112
|
|
);
|
|
void end(void);
|
|
void updateBaudRate(unsigned long baud);
|
|
int available(void);
|
|
int availableForWrite(void);
|
|
int peek(void);
|
|
int read(void);
|
|
size_t read(uint8_t *buffer, size_t size);
|
|
inline size_t read(char *buffer, size_t size) {
|
|
return read((uint8_t *)buffer, size);
|
|
}
|
|
// Overrides Stream::readBytes() to be faster using IDF
|
|
size_t readBytes(uint8_t *buffer, size_t length);
|
|
size_t readBytes(char *buffer, size_t length) {
|
|
return readBytes((uint8_t *)buffer, length);
|
|
}
|
|
void flush(void);
|
|
void flush(bool txOnly);
|
|
size_t write(uint8_t);
|
|
size_t write(const uint8_t *buffer, size_t size);
|
|
inline size_t write(const char *buffer, size_t size) {
|
|
return write((uint8_t *)buffer, size);
|
|
}
|
|
inline size_t write(const char *s) {
|
|
return write((uint8_t *)s, strlen(s));
|
|
}
|
|
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);
|
|
}
|
|
uint32_t baudRate();
|
|
operator bool() const;
|
|
|
|
void setDebugOutput(bool);
|
|
|
|
void setRxInvert(bool);
|
|
|
|
// Negative Pin Number will keep it unmodified, thus this function can set individual pins
|
|
// setPins() can be called after or before begin()
|
|
// When pins are changed, it will detach the previous ones
|
|
bool setPins(int8_t rxPin, int8_t txPin, int8_t ctsPin = -1, int8_t rtsPin = -1);
|
|
// Enables or disables Hardware Flow Control using RTS and/or CTS pins (must use setAllPins() before)
|
|
// UART_HW_FLOWCTRL_DISABLE = 0x0 disable hardware flow control
|
|
// UART_HW_FLOWCTRL_RTS = 0x1 enable RX hardware flow control (rts)
|
|
// UART_HW_FLOWCTRL_CTS = 0x2 enable TX hardware flow control (cts)
|
|
// UART_HW_FLOWCTRL_CTS_RTS = 0x3 enable hardware flow control
|
|
bool setHwFlowCtrlMode(SerialHwFlowCtrl mode = UART_HW_FLOWCTRL_CTS_RTS, uint8_t threshold = 64); // 64 is half FIFO Length
|
|
// Used to set RS485 modes such as UART_MODE_RS485_HALF_DUPLEX for Auto RTS function on ESP32
|
|
// UART_MODE_UART = 0x00 mode: regular UART mode
|
|
// UART_MODE_RS485_HALF_DUPLEX = 0x01 mode: half duplex RS485 UART mode control by RTS pin
|
|
// UART_MODE_IRDA = 0x02 mode: IRDA UART mode
|
|
// UART_MODE_RS485_COLLISION_DETECT = 0x03 mode: RS485 collision detection UART mode (used for test purposes)
|
|
// UART_MODE_RS485_APP_CTRL = 0x04 mode: application control RS485 UART mode (used for test purposes)
|
|
bool setMode(SerialMode mode);
|
|
size_t setRxBufferSize(size_t new_size);
|
|
size_t setTxBufferSize(size_t new_size);
|
|
|
|
protected:
|
|
uint8_t _uart_nr;
|
|
uart_t *_uart;
|
|
size_t _rxBufferSize;
|
|
size_t _txBufferSize;
|
|
OnReceiveCb _onReceiveCB;
|
|
OnReceiveErrorCb _onReceiveErrorCB;
|
|
// _onReceive and _rxTimeout have be consistent when timeout is disabled
|
|
bool _onReceiveTimeout;
|
|
uint8_t _rxTimeout, _rxFIFOFull;
|
|
TaskHandle_t _eventTask;
|
|
#if !CONFIG_DISABLE_HAL_LOCKS
|
|
SemaphoreHandle_t _lock;
|
|
#endif
|
|
|
|
void _createEventTask(void *args);
|
|
void _destroyEventTask(void);
|
|
static void _uartEventTask(void *args);
|
|
};
|
|
|
|
extern void serialEventRun(void) __attribute__((weak));
|
|
|
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
|
#ifndef ARDUINO_USB_CDC_ON_BOOT
|
|
#define ARDUINO_USB_CDC_ON_BOOT 0
|
|
#endif
|
|
#if ARDUINO_USB_CDC_ON_BOOT //Serial used from Native_USB_CDC | HW_CDC_JTAG
|
|
#if ARDUINO_USB_MODE // Hardware CDC mode
|
|
// Arduino Serial is the HW JTAG CDC device
|
|
#define Serial HWCDCSerial
|
|
#else // !ARDUINO_USB_MODE -- Native USB Mode
|
|
// Arduino Serial is the Native USB CDC device
|
|
#define Serial USBSerial
|
|
#endif // ARDUINO_USB_MODE
|
|
#else // !ARDUINO_USB_CDC_ON_BOOT -- Serial is used from UART0
|
|
// if not using CDC on Boot, Arduino Serial is the UART0 device
|
|
#define Serial Serial0
|
|
#endif // ARDUINO_USB_CDC_ON_BOOT
|
|
// There is always Seria0 for UART0
|
|
extern HardwareSerial Serial0;
|
|
#if SOC_UART_NUM > 1
|
|
extern HardwareSerial Serial1;
|
|
#endif
|
|
#if SOC_UART_NUM > 2
|
|
extern HardwareSerial Serial2;
|
|
#endif
|
|
#endif //!defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
|
|
|
|
#endif // HardwareSerial_h
|