From 00e01b13aa862dd658cc4ca13a13207c1d87e9d3 Mon Sep 17 00:00:00 2001 From: ale-trevizoli Date: Thu, 17 Oct 2019 18:12:38 -0300 Subject: [PATCH 1/2] Add setInterrupt method to HardwareSerial class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These changes allow to add an interrupt event for Serial using an method setInterrupt. Simple and Easy! This is a resume of patch: esp32-hal-uart.h change function to allow one second parameter void uartEnableInterrupt(uart_t* uart,void * func ); . . . . #ifdef __cplusplus } #endif void uartDisableInterrupt(uart_t* uart); void uartEnableInterrupt(uart_t* uart,void * func ); #endif /* MAIN_ESP32_HAL_UART_H_ */ esp32-hal-uart.h changes on function _uart_isr and uartEnableInterrupt(uart_t* uart,void * func ); static void IRAM_ATTR _uart_isr(void arg) { uint8_t i, c; BaseType_t xHigherPriorityTaskWoken; uart_t uart; if(arg != NULL) { (*((void(**)())arg))(); } for(i=0;i<3;i++){ uart = &_uart_bus_array[i]; if(uart->intr_handle == NULL){ continue; } uart->dev->int_clr.rxfifo_full = 1; uart->dev->int_clr.frm_err = 1; uart->dev->int_clr.rxfifo_tout = 1; while(uart->dev->status.rxfifo_cnt || (uart->dev->mem_rx_status.wr_addr != uart->dev->mem_rx_status.rd_addr)) { c = uart->dev->fifo.rw_byte; if(uart->queue != NULL && !xQueueIsQueueFullFromISR(uart->queue)) { xQueueSendFromISR(uart->queue, &c, &xHigherPriorityTaskWoken); } } } if (xHigherPriorityTaskWoken) { portYIELD_FROM_ISR(); } } void uartEnableInterrupt(uart_t* uart,void * func) { UART_MUTEX_LOCK(); uart->dev->conf1.rxfifo_full_thrhd = 112; uart->dev->conf1.rx_tout_thrhd = 2; uart->dev->conf1.rx_tout_en = 1; uart->dev->int_ena.rxfifo_full = 1; uart->dev->int_ena.frm_err = 1; uart->dev->int_ena.rxfifo_tout = 1; uart->dev->int_clr.val = 0xffffffff; esp_intr_alloc(UART_INTR_SOURCE(uart->num), (int)ESP_INTR_FLAG_IRAM, _uart_isr, func, &uart->intr_handle); UART_MUTEX_UNLOCK(); } HardwareSerial.h add public function void setInterrupt(void (*arg)() ); and protected void (*intr)() ; class HardwareSerial: public Stream { public: HardwareSerial(int uart_nr); void setInterrupt(void (*arg)() ); 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); void end(); void updateBaudRate(unsigned long baud); int available(void); int availableForWrite(void); int peek(void); int read(void); void flush(void); size_t write(uint8_t); size_t write(const uint8_t *buffer, size_t 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; size_t setRxBufferSize(size_t); void setDebugOutput(bool); protected: void (intr)() ; int _uart_nr; uart_t _uart; }; #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) extern HardwareSerial Serial; extern HardwareSerial Serial1; extern HardwareSerial Serial2; #endif #endif HardwareSerial.c add function void setInterrupt(void (*arg)() ); void HardwareSerial::setInterrupt(void(*arg)() ) { uartDisableInterrupt(_uart); intr = arg; uartEnableInterrupt(_uart,&intr); } FINISH!!! Example of USE Serial1.begin(9600,SERIAL_8N1, 17, 16); //RX,TX Serial1.setInterrupt(&SerialEvent1); void IRAM_ATTR SerialEvent1(){ // ocorre quando o arduino recebe uma transmissão no RX1 while (Serial1.available()>0) { Serial.print(Serial1.read()); } Serial.println(); } --- cores/esp32/HardwareSerial.cpp | 7 +++++++ cores/esp32/HardwareSerial.h | 7 +++---- cores/esp32/esp32-hal-uart.c | 34 ++++++++++++++++++++++++++++++++-- cores/esp32/esp32-hal-uart.h | 3 +++ 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/cores/esp32/HardwareSerial.cpp b/cores/esp32/HardwareSerial.cpp index 545c9b05562..0553daacaa8 100644 --- a/cores/esp32/HardwareSerial.cpp +++ b/cores/esp32/HardwareSerial.cpp @@ -30,6 +30,13 @@ HardwareSerial Serial2(2); HardwareSerial::HardwareSerial(int uart_nr) : _uart_nr(uart_nr), _uart(NULL) {} +void HardwareSerial::setInterrupt(void(*arg)() ) +{ + uartDisableInterrupt(_uart); + intr = arg; + uartEnableInterrupt(_uart,&intr); +} + void HardwareSerial::begin(unsigned long baud, uint32_t config, int8_t rxPin, int8_t txPin, bool invert, unsigned long timeout_ms) { if(0 > _uart_nr || _uart_nr > 2) { diff --git a/cores/esp32/HardwareSerial.h b/cores/esp32/HardwareSerial.h index 5f886650816..ce373686dcd 100644 --- a/cores/esp32/HardwareSerial.h +++ b/cores/esp32/HardwareSerial.h @@ -54,7 +54,7 @@ class HardwareSerial: public Stream { public: HardwareSerial(int uart_nr); - + void setInterrupt(void (*arg)() ); 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); void end(); void updateBaudRate(unsigned long baud); @@ -93,16 +93,15 @@ class HardwareSerial: public Stream void setDebugOutput(bool); protected: + void (*intr)() ; int _uart_nr; uart_t* _uart; }; -extern void serialEventRun(void) __attribute__((weak)); - #if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL) extern HardwareSerial Serial; extern HardwareSerial Serial1; extern HardwareSerial Serial2; #endif -#endif // HardwareSerial_h +#endif diff --git a/cores/esp32/esp32-hal-uart.c b/cores/esp32/esp32-hal-uart.c index 2dee63dc325..7520227a045 100644 --- a/cores/esp32/esp32-hal-uart.c +++ b/cores/esp32/esp32-hal-uart.c @@ -75,6 +75,10 @@ static void IRAM_ATTR _uart_isr(void *arg) BaseType_t xHigherPriorityTaskWoken; uart_t* uart; + if(arg != NULL) { + (*((void(**)())arg))(); + } + for(i=0;i<3;i++){ uart = &_uart_bus_array[i]; if(uart->intr_handle == NULL){ @@ -96,6 +100,22 @@ static void IRAM_ATTR _uart_isr(void *arg) } } +void uartEnableInterrupt(uart_t* uart,void * func) +{ + UART_MUTEX_LOCK(); + uart->dev->conf1.rxfifo_full_thrhd = 112; + uart->dev->conf1.rx_tout_thrhd = 2; + uart->dev->conf1.rx_tout_en = 1; + uart->dev->int_ena.rxfifo_full = 1; + uart->dev->int_ena.frm_err = 1; + uart->dev->int_ena.rxfifo_tout = 1; + uart->dev->int_clr.val = 0xffffffff; + + esp_intr_alloc(UART_INTR_SOURCE(uart->num), (int)ESP_INTR_FLAG_IRAM, _uart_isr, func, &uart->intr_handle); + UART_MUTEX_UNLOCK(); +} + +/* void uartEnableInterrupt(uart_t* uart) { UART_MUTEX_LOCK(); @@ -110,7 +130,7 @@ void uartEnableInterrupt(uart_t* uart) esp_intr_alloc(UART_INTR_SOURCE(uart->num), (int)ESP_INTR_FLAG_IRAM, _uart_isr, NULL, &uart->intr_handle); UART_MUTEX_UNLOCK(); } - + */ void uartDisableInterrupt(uart_t* uart) { UART_MUTEX_LOCK(); @@ -148,9 +168,19 @@ void uartAttachRx(uart_t* uart, uint8_t rxPin, bool inverted) } pinMode(rxPin, INPUT); pinMatrixInAttach(rxPin, UART_RXD_IDX(uart->num), inverted); - uartEnableInterrupt(uart); + uartEnableInterrupt(uart,NULL); } +// void uartAttachRx(uart_t* uart, uint8_t rxPin, bool inverted) +// { + // if(uart == NULL || rxPin > 39) { + // return; + // } + // pinMode(rxPin, INPUT); + // pinMatrixInAttach(rxPin, UART_RXD_IDX(uart->num), inverted); + // uartEnableInterrupt(uart); +// } + void uartAttachTx(uart_t* uart, uint8_t txPin, bool inverted) { if(uart == NULL || txPin > 39) { diff --git a/cores/esp32/esp32-hal-uart.h b/cores/esp32/esp32-hal-uart.h index 821ca9c6ce0..cdf52e86689 100644 --- a/cores/esp32/esp32-hal-uart.h +++ b/cores/esp32/esp32-hal-uart.h @@ -81,4 +81,7 @@ bool uartRxActive(uart_t* uart); } #endif +void uartDisableInterrupt(uart_t* uart); +void uartEnableInterrupt(uart_t* uart,void * func ); + #endif /* MAIN_ESP32_HAL_UART_H_ */ From 36e5f0457ad9cb6e797d38bc2f7289448f5926a6 Mon Sep 17 00:00:00 2001 From: Alexandre Trevizoli Date: Fri, 1 Nov 2019 18:31:30 -0300 Subject: [PATCH 2/2] Add files via upload Corrected all Find, FindUntil and added findMulti function, copy code from Stream.h and Stream.cpp from AVR-CORE. Stream.find was not working when used with Ethernet.find() After copy code from AVR-CORE it is working now --- cores/esp32/Stream.cpp | 110 ++++++++++++++++++++++++++++++++++++++++- cores/esp32/Stream.h | 31 +++++++++++- 2 files changed, 139 insertions(+), 2 deletions(-) diff --git a/cores/esp32/Stream.cpp b/cores/esp32/Stream.cpp index 5c090791968..5727ff6f896 100644 --- a/cores/esp32/Stream.cpp +++ b/cores/esp32/Stream.cpp @@ -85,7 +85,7 @@ void Stream::setTimeout(unsigned long timeout) // sets the maximum number of mi unsigned long Stream::getTimeout(void) { return _timeout; } - +/* // find returns true if the target string is found bool Stream::find(const char *target) { @@ -141,6 +141,114 @@ bool Stream::findUntil(const char *target, size_t targetLen, const char *termina return false; } +*/ + +// ******************** ALEXANDRE + + // find returns true if the target string is found +bool Stream::find(char *target) +{ + return findUntil(target, strlen(target), NULL, 0); +} + +// reads data from the stream until the target string of given length is found +// returns true if target string is found, false if timed out +bool Stream::find(char *target, size_t length) +{ + return findUntil(target, length, NULL, 0); +} + +// as find but search ends if the terminator string is found +bool Stream::findUntil(char *target, char *terminator) +{ + return findUntil(target, strlen(target), terminator, strlen(terminator)); +} + +// reads data from the stream until the target string of the given length is found +// search terminated if the terminator string is found +// returns true if target string is found, false if terminated or timed out +bool Stream::findUntil(char *target, size_t targetLen, char *terminator, size_t termLen) +{ + if (terminator == NULL) { + MultiTarget t[1] = {{target, targetLen, 0}}; + return findMulti(t, 1) == 0 ? true : false; + } else { + MultiTarget t[2] = {{target, targetLen, 0}, {terminator, termLen, 0}}; + return findMulti(t, 2) == 0 ? true : false; + } +} + +int Stream::findMulti( struct Stream::MultiTarget *targets, int tCount) { + // any zero length target string automatically matches and would make + // a mess of the rest of the algorithm. + for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { + if (t->len <= 0) + return t - targets; + } + + while (1) { + int c = timedRead(); + if (c < 0) + return -1; + + for (struct MultiTarget *t = targets; t < targets+tCount; ++t) { + // the simple case is if we match, deal with that first. + if (c == t->str[t->index]) { + if (++t->index == t->len) + return t - targets; + else + continue; + } + + // if not we need to walk back and see if we could have matched further + // down the stream (ie '1112' doesn't match the first position in '11112' + // but it will match the second position so we can't just reset the current + // index to 0 when we find a mismatch. + if (t->index == 0) + continue; + + int origIndex = t->index; + do { + --t->index; + // first check if current char works against the new current index + if (c != t->str[t->index]) + continue; + + // if it's the only char then we're good, nothing more to check + if (t->index == 0) { + t->index++; + break; + } + + // otherwise we need to check the rest of the found string + int diff = origIndex - t->index; + size_t i; + for (i = 0; i < t->index; ++i) { + if (t->str[i] != t->str[i + diff]) + break; + } + + // if we successfully got through the previous loop then our current + // index is good. + if (i == t->index) { + t->index++; + break; + } + + // otherwise we just try the next index + } while (t->index); + } + } + // unreachable + return -1; +} + + + +// ********************************** + + + // returns the first valid (long) integer value from the current position. // initial characters that are not digits (or the minus sign) are skipped // function is terminated by the first character that is not a digit. diff --git a/cores/esp32/Stream.h b/cores/esp32/Stream.h index 4ce31955acd..e9d3b525ebf 100644 --- a/cores/esp32/Stream.h +++ b/cores/esp32/Stream.h @@ -60,6 +60,24 @@ class Stream: public Print void setTimeout(unsigned long timeout); // sets maximum milliseconds to wait for stream data, default is 1 second unsigned long getTimeout(void); + + bool find(char *target); // reads data from the stream until the target string is found + bool find(uint8_t *target) { return find ((char *)target); } + // returns true if target string is found, false if timed out (see setTimeout) + + bool find(char *target, size_t length); // reads data from the stream until the target string of given length is found + bool find(uint8_t *target, size_t length) { return find ((char *)target, length); } + // returns true if target string is found, false if timed out + + bool find(char target) { return find (&target, 1); } + + bool findUntil(char *target, char *terminator); // as find but search ends if the terminator string is found + bool findUntil(uint8_t *target, char *terminator) { return findUntil((char *)target, terminator); } + + bool findUntil(char *target, size_t targetLen, char *terminate, size_t termLen); // as above but search ends if the terminate string is found + bool findUntil(uint8_t *target, size_t targetLen, char *terminate, size_t termLen) {return findUntil((char *)target, targetLen, terminate, termLen); } + +/* bool find(const char *target); // reads data from the stream until the target string is found bool find(uint8_t *target) { @@ -90,7 +108,7 @@ class Stream: public Print { return findUntil((char *) target, targetLen, terminate, termLen); } - +*/ long parseInt(); // returns the first valid (long) integer value from the current position. // initial characters that are not digits (or the minus sign) are skipped // integer is terminated by the first character that is not a digit. @@ -123,6 +141,17 @@ class Stream: public Print // this allows format characters (typically commas) in values to be ignored float parseFloat(char skipChar); // as above but the given skipChar is ignored + + struct MultiTarget { + const char *str; // string you're searching for + size_t len; // length of string you're searching for + size_t index; // index used by the search routine. + }; + + // This allows you to search for an arbitrary number of strings. + // Returns index of the target that is found first or -1 if timeout occurs. + int findMulti(struct MultiTarget *targets, int tCount); + }; #endif