Skip to content

Add setInterrupt method to HardwareSerial class #3376

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions cores/esp32/HardwareSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
7 changes: 3 additions & 4 deletions cores/esp32/HardwareSerial.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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));

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to be restored as this weakly declared method is called, this also breaks the tests which prevent this PR from being considered for merge.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was taken care of in #2991 prior to this :-)

#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SERIAL)
extern HardwareSerial Serial;
extern HardwareSerial Serial1;
extern HardwareSerial Serial2;
#endif

#endif // HardwareSerial_h
#endif
110 changes: 109 additions & 1 deletion cores/esp32/Stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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.
Expand Down
31 changes: 30 additions & 1 deletion cores/esp32/Stream.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
34 changes: 32 additions & 2 deletions cores/esp32/esp32-hal-uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ static void IRAM_ATTR _uart_isr(void *arg)
BaseType_t xHigherPriorityTaskWoken;
uart_t* uart;

if(arg != NULL) {
(*((void(**)())arg))();
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check should be made in the while loop below and byte c should be sent to the callback instead of to the queue. If callback is not in IRAM, things will go really bad really fast.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@me-no-dev I don't think this could be used as an input filter. As written, it triggers once per interrupt, but, the interrupt can empty up to "fifo" of chars. see my comment above.

for(i=0;i<3;i++){
uart = &_uart_bus_array[i];
if(uart->intr_handle == NULL){
Expand All @@ -96,6 +100,22 @@ static void IRAM_ATTR _uart_isr(void *arg)
}
}

void uartEnableInterrupt(uart_t* uart,void * func)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so why didn't you just change the original function?

{
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();
Expand All @@ -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();
Expand Down Expand Up @@ -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)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this method commented out?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, why?

// {
// 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) {
Expand Down
3 changes: 3 additions & 0 deletions cores/esp32/esp32-hal-uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ */