From 291b7f7b8a19c43e267ab01b32fdaa9204b14c70 Mon Sep 17 00:00:00 2001 From: Georg Icking-Konert Date: Fri, 8 Nov 2019 06:06:04 +0100 Subject: [PATCH 1/8] added optional custom handler to Serial interrupt added optional custom handler to Serial interrupt. Is minor enhancement of NeoHWSerial by SlashDevin (https://github.com/SlashDevin/NeoHWSerial), as user function also gets UART status as parameter to e.g. detect LIN break in user routine. Added as core extension instead of library due to similar extension for Due (https://github.com/gicking/ArduinoCore-sam) which AFAIK cannot be implemented as library. --- cores/arduino/HardwareSerial.cpp | 10 ++++++ cores/arduino/HardwareSerial.h | 11 ++++++ cores/arduino/HardwareSerial0.cpp | 2 ++ cores/arduino/HardwareSerial1.cpp | 2 ++ cores/arduino/HardwareSerial2.cpp | 2 ++ cores/arduino/HardwareSerial3.cpp | 2 ++ cores/arduino/HardwareSerial_private.h | 50 ++++++++++++++++---------- 7 files changed, 61 insertions(+), 18 deletions(-) diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index e99d503d8..56eb744fa 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -20,6 +20,8 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman + Modified 2 November 2015 by SlashDev + Modified 7 November 2019 by Georg Icking-Konert */ #include @@ -278,4 +280,12 @@ size_t HardwareSerial::write(uint8_t c) return 1; } +void HardwareSerial::attachInterrupt( isr_t fn ) +{ + uint8_t oldSREG = SREG; + cli(); + _isr = fn; + SREG = oldSREG; +} + #endif // whole file diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index 17000c2cc..1bb395d8a 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -19,6 +19,8 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman + Modified 2 November 2015 by SlashDev + Modified 7 November 2019 by Georg Icking-Konert */ #ifndef HardwareSerial_h @@ -137,6 +139,15 @@ class HardwareSerial : public Stream // Interrupt handlers - Not intended to be called externally inline void _rx_complete_irq(void); void _tx_udr_empty_irq(void); + + typedef void (* isr_t)( uint8_t d=0x00, uint8_t s=0x00 ); + void attachInterrupt( isr_t fn ); + void detachInterrupt() { attachInterrupt( (isr_t) NULL ); }; + private: + isr_t _isr; + + HardwareSerial( const HardwareSerial & ); + HardwareSerial & operator =( const HardwareSerial &); }; #if defined(UBRRH) || defined(UBRR0H) diff --git a/cores/arduino/HardwareSerial0.cpp b/cores/arduino/HardwareSerial0.cpp index 1146eebab..ece78a636 100644 --- a/cores/arduino/HardwareSerial0.cpp +++ b/cores/arduino/HardwareSerial0.cpp @@ -20,6 +20,8 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman + Modified 2 November 2015 by SlashDev + Modified 7 November 2019 by Georg Icking-Konert */ #include "Arduino.h" diff --git a/cores/arduino/HardwareSerial1.cpp b/cores/arduino/HardwareSerial1.cpp index 19625e235..c436e1690 100644 --- a/cores/arduino/HardwareSerial1.cpp +++ b/cores/arduino/HardwareSerial1.cpp @@ -20,6 +20,8 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman + Modified 2 November 2015 by SlashDev + Modified 7 November 2019 by Georg Icking-Konert */ #include "Arduino.h" diff --git a/cores/arduino/HardwareSerial2.cpp b/cores/arduino/HardwareSerial2.cpp index fd334ae15..5558b17d1 100644 --- a/cores/arduino/HardwareSerial2.cpp +++ b/cores/arduino/HardwareSerial2.cpp @@ -20,6 +20,8 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman + Modified 2 November 2015 by SlashDev + Modified 7 November 2019 by Georg Icking-Konert */ #include "Arduino.h" diff --git a/cores/arduino/HardwareSerial3.cpp b/cores/arduino/HardwareSerial3.cpp index a68095b37..f6ba55460 100644 --- a/cores/arduino/HardwareSerial3.cpp +++ b/cores/arduino/HardwareSerial3.cpp @@ -20,6 +20,8 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman + Modified 2 November 2015 by SlashDev + Modified 7 November 2019 by Georg Icking-Konert */ #include "Arduino.h" diff --git a/cores/arduino/HardwareSerial_private.h b/cores/arduino/HardwareSerial_private.h index 761a5e559..72a9063b3 100644 --- a/cores/arduino/HardwareSerial_private.h +++ b/cores/arduino/HardwareSerial_private.h @@ -19,6 +19,8 @@ Modified 23 November 2006 by David A. Mellis Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus + Modified 2 November 2015 by SlashDev + Modified 7 November 2019 by Georg Icking-Konert */ #include "wiring_private.h" @@ -92,7 +94,8 @@ HardwareSerial::HardwareSerial( _ucsra(ucsra), _ucsrb(ucsrb), _ucsrc(ucsrc), _udr(udr), _rx_buffer_head(0), _rx_buffer_tail(0), - _tx_buffer_head(0), _tx_buffer_tail(0) + _tx_buffer_head(0), _tx_buffer_tail(0), + _isr(0) { } @@ -100,24 +103,35 @@ HardwareSerial::HardwareSerial( 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; + // user function was attached -> call it with data and status byte + if (_isr) { + unsigned char status = *_ucsra; + unsigned char data = *_udr; + _isr( data, status ); + } - // 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; - }; + // default: save data in ring buffer + else { + if (bit_is_clear(*_ucsra, UPE0)) { + unsigned char c = *_udr; + // No Parity error, read byte and store it in the buffer if there is + // room + 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 From e5fd810fc507217143ad93fe92b70abb9ba73aea Mon Sep 17 00:00:00 2001 From: Georg Icking-Konert Date: Sat, 9 Nov 2019 18:00:59 +0100 Subject: [PATCH 2/8] fixed compiler warnings fixed compiler warnings when compiling with max. waring level --- cores/arduino/HardwareSerial.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index 1bb395d8a..f8a3bc65b 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -140,7 +140,7 @@ class HardwareSerial : public Stream inline void _rx_complete_irq(void); void _tx_udr_empty_irq(void); - typedef void (* isr_t)( uint8_t d=0x00, uint8_t s=0x00 ); + typedef void (* isr_t)( uint8_t d, uint8_t s ); void attachInterrupt( isr_t fn ); void detachInterrupt() { attachInterrupt( (isr_t) NULL ); }; private: From 8665c0367d9fddffdfa1777a7cdda0fa6bd8427c Mon Sep 17 00:00:00 2001 From: Georg Icking-Konert Date: Sun, 17 Nov 2019 09:08:23 +0100 Subject: [PATCH 3/8] add Serial.attachInterrupt_Send() add Serial.attachInterrupt_Send() rename Serial.attachInterrupt() to Serial.attachInterrupt_Receive() --- cores/arduino/HardwareSerial.cpp | 31 ++++++++++++++++++++++++-- cores/arduino/HardwareSerial.h | 15 ++++++++----- cores/arduino/HardwareSerial0.cpp | 16 +++++++++++-- cores/arduino/HardwareSerial1.cpp | 14 ++++++++++-- cores/arduino/HardwareSerial2.cpp | 17 ++++++++++++-- cores/arduino/HardwareSerial3.cpp | 8 +++++-- cores/arduino/HardwareSerial_private.h | 10 ++++----- 7 files changed, 91 insertions(+), 20 deletions(-) diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 56eb744fa..417e77af1 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -114,6 +114,14 @@ void HardwareSerial::_tx_udr_empty_irq(void) } } +void HardwareSerial::_tx_complete_irq(void) +{ + // user send function was attached -> call it + if (_isrTx) { + _isrTx(); + } +} + // Public Methods ////////////////////////////////////////////////////////////// void HardwareSerial::begin(unsigned long baud, byte config) @@ -160,6 +168,7 @@ void HardwareSerial::end() cbi(*_ucsrb, TXEN0); cbi(*_ucsrb, RXCIE0); cbi(*_ucsrb, UDRIE0); + cbi(*_ucsrb, TXCIE0); // clear any received data _rx_buffer_head = _rx_buffer_tail; @@ -280,11 +289,29 @@ size_t HardwareSerial::write(uint8_t c) return 1; } -void HardwareSerial::attachInterrupt( isr_t fn ) +void HardwareSerial::attachInterrupt_Receive( isrRx_t fn ) +{ + uint8_t oldSREG = SREG; + cli(); + _isrRx = fn; + SREG = oldSREG; +} + +void HardwareSerial::attachInterrupt_Send( isrTx_t fn ) +{ + uint8_t oldSREG = SREG; + cli(); + _isrTx = fn; + sbi(*_ucsrb, TXCIE0); + SREG = oldSREG; +} + +void HardwareSerial::detachInterrupt_Send() { uint8_t oldSREG = SREG; cli(); - _isr = fn; + _isrTx = NULL; + cbi(*_ucsrb, TXCIE0); SREG = oldSREG; } diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index f8a3bc65b..1e3de78a7 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -139,12 +139,17 @@ class HardwareSerial : public Stream // Interrupt handlers - Not intended to be called externally inline void _rx_complete_irq(void); void _tx_udr_empty_irq(void); - - typedef void (* isr_t)( uint8_t d, uint8_t s ); - void attachInterrupt( isr_t fn ); - void detachInterrupt() { attachInterrupt( (isr_t) NULL ); }; + void _tx_complete_irq(void); + + typedef void (* isrRx_t)( uint8_t d, uint8_t s ); + void attachInterrupt_Receive( isrRx_t fn ); + void detachInterrupt_Receive() { attachInterrupt_Receive( (isrRx_t) NULL ); }; + typedef void (* isrTx_t)( void ); + void attachInterrupt_Send( isrTx_t fn ); + void detachInterrupt_Send( void ); private: - isr_t _isr; + isrRx_t _isrRx; + isrTx_t _isrTx; HardwareSerial( const HardwareSerial & ); HardwareSerial & operator =( const HardwareSerial &); diff --git a/cores/arduino/HardwareSerial0.cpp b/cores/arduino/HardwareSerial0.cpp index ece78a636..9f507b6c2 100644 --- a/cores/arduino/HardwareSerial0.cpp +++ b/cores/arduino/HardwareSerial0.cpp @@ -20,8 +20,7 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman - Modified 2 November 2015 by SlashDev - Modified 7 November 2019 by Georg Icking-Konert + Modified 17 November 2019 by Georg Icking-Konert */ #include "Arduino.h" @@ -66,6 +65,19 @@ ISR(USART_UDRE_vect) Serial._tx_udr_empty_irq(); } +#if defined(UART0_TX_vect) +ISR(UART0_TX_vect) +#elif defined(USART0_TX_vect) +ISR(USART0_TX_vect) +#elif defined(USART_TX_vect) +ISR(USART_TX_vect) +#else + #error "Don't know what the Transmission Complete vector is called for Serial" +#endif +{ + Serial._tx_complete_irq(); +} + #if defined(UBRRH) && defined(UBRRL) HardwareSerial Serial(&UBRRH, &UBRRL, &UCSRA, &UCSRB, &UCSRC, &UDR); #else diff --git a/cores/arduino/HardwareSerial1.cpp b/cores/arduino/HardwareSerial1.cpp index c436e1690..800191700 100644 --- a/cores/arduino/HardwareSerial1.cpp +++ b/cores/arduino/HardwareSerial1.cpp @@ -20,8 +20,7 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman - Modified 2 November 2015 by SlashDev - Modified 7 November 2019 by Georg Icking-Konert + Modified 17 November 2019 by Georg Icking-Konert */ #include "Arduino.h" @@ -60,6 +59,17 @@ ISR(USART1_UDRE_vect) Serial1._tx_udr_empty_irq(); } +#if defined(UART1_TX_vect) +ISR(UART1_TX_vect) +#elif defined(USART1_TX_vect) +ISR(USART1_TX_vect) +#else + #error "Don't know what the Transmission Complete vector is called for Serial1" +#endif +{ + Serial1._tx_complete_irq(); +} + HardwareSerial Serial1(&UBRR1H, &UBRR1L, &UCSR1A, &UCSR1B, &UCSR1C, &UDR1); // Function that can be weakly referenced by serialEventRun to prevent diff --git a/cores/arduino/HardwareSerial2.cpp b/cores/arduino/HardwareSerial2.cpp index 5558b17d1..c87607a47 100644 --- a/cores/arduino/HardwareSerial2.cpp +++ b/cores/arduino/HardwareSerial2.cpp @@ -20,8 +20,7 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman - Modified 2 November 2015 by SlashDev - Modified 7 November 2019 by Georg Icking-Konert + Modified 17 November 2019 by Georg Icking-Konert */ #include "Arduino.h" @@ -38,6 +37,9 @@ #if defined(HAVE_HWSERIAL2) +// xxx +extern int count; + ISR(USART2_RX_vect) { Serial2._rx_complete_irq(); @@ -45,9 +47,20 @@ ISR(USART2_RX_vect) ISR(USART2_UDRE_vect) { + // xxx + Serial.println(++count); + digitalWrite(LED_BUILTIN, HIGH); + delayMicroseconds(50); + digitalWrite(LED_BUILTIN, LOW); + Serial2._tx_udr_empty_irq(); } +ISR(USART2_TX_vect) +{ + Serial2._tx_complete_irq(); +} + HardwareSerial Serial2(&UBRR2H, &UBRR2L, &UCSR2A, &UCSR2B, &UCSR2C, &UDR2); // Function that can be weakly referenced by serialEventRun to prevent diff --git a/cores/arduino/HardwareSerial3.cpp b/cores/arduino/HardwareSerial3.cpp index f6ba55460..aaac520a5 100644 --- a/cores/arduino/HardwareSerial3.cpp +++ b/cores/arduino/HardwareSerial3.cpp @@ -20,8 +20,7 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman - Modified 2 November 2015 by SlashDev - Modified 7 November 2019 by Georg Icking-Konert + Modified 17 November 2019 by Georg Icking-Konert */ #include "Arduino.h" @@ -48,6 +47,11 @@ ISR(USART3_UDRE_vect) Serial3._tx_udr_empty_irq(); } +ISR(USART3_TX_vect) +{ + Serial3._tx_complete_irq(); +} + HardwareSerial Serial3(&UBRR3H, &UBRR3L, &UCSR3A, &UCSR3B, &UCSR3C, &UDR3); // Function that can be weakly referenced by serialEventRun to prevent diff --git a/cores/arduino/HardwareSerial_private.h b/cores/arduino/HardwareSerial_private.h index 72a9063b3..ac61bed20 100644 --- a/cores/arduino/HardwareSerial_private.h +++ b/cores/arduino/HardwareSerial_private.h @@ -20,7 +20,7 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 2 November 2015 by SlashDev - Modified 7 November 2019 by Georg Icking-Konert + Modified 17 November 2019 by Georg Icking-Konert */ #include "wiring_private.h" @@ -95,7 +95,7 @@ HardwareSerial::HardwareSerial( _udr(udr), _rx_buffer_head(0), _rx_buffer_tail(0), _tx_buffer_head(0), _tx_buffer_tail(0), - _isr(0) + _isrRx(0), _isrTx(0) { } @@ -103,11 +103,11 @@ HardwareSerial::HardwareSerial( void HardwareSerial::_rx_complete_irq(void) { - // user function was attached -> call it with data and status byte - if (_isr) { + // user receive function was attached -> call it with data and status byte + if (_isrRx) { unsigned char status = *_ucsra; unsigned char data = *_udr; - _isr( data, status ); + _isrRx( data, status ); } // default: save data in ring buffer From f7f584b1ba5078517e391fad8a3da1c627ad6960 Mon Sep 17 00:00:00 2001 From: Georg Icking-Konert Date: Mon, 18 Nov 2019 18:26:43 +0100 Subject: [PATCH 4/8] add Serial.attachInterrupt_Send() --- cores/arduino/HardwareSerial.cpp | 1 + cores/arduino/HardwareSerial2.cpp | 9 --------- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 417e77af1..ffabbb735 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -120,6 +120,7 @@ void HardwareSerial::_tx_complete_irq(void) if (_isrTx) { _isrTx(); } + } // Public Methods ////////////////////////////////////////////////////////////// diff --git a/cores/arduino/HardwareSerial2.cpp b/cores/arduino/HardwareSerial2.cpp index c87607a47..1a3b7d754 100644 --- a/cores/arduino/HardwareSerial2.cpp +++ b/cores/arduino/HardwareSerial2.cpp @@ -37,9 +37,6 @@ #if defined(HAVE_HWSERIAL2) -// xxx -extern int count; - ISR(USART2_RX_vect) { Serial2._rx_complete_irq(); @@ -47,12 +44,6 @@ ISR(USART2_RX_vect) ISR(USART2_UDRE_vect) { - // xxx - Serial.println(++count); - digitalWrite(LED_BUILTIN, HIGH); - delayMicroseconds(50); - digitalWrite(LED_BUILTIN, LOW); - Serial2._tx_udr_empty_irq(); } From 307a108582edf6786a0e8d8c7fa4c6d4f78143e4 Mon Sep 17 00:00:00 2001 From: Georg Icking-Konert Date: Sat, 23 Nov 2019 09:11:38 +0100 Subject: [PATCH 5/8] optimized runtime for TXC custom function optimized runtime for TXC custom function --- cores/arduino/HardwareSerial.cpp | 32 +++++++++++--------------- cores/arduino/HardwareSerial.h | 14 +++++++---- cores/arduino/HardwareSerial_private.h | 11 ++++++++- 3 files changed, 32 insertions(+), 25 deletions(-) diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index ffabbb735..74ee0040a 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -79,6 +79,9 @@ void serialEventRun(void) #endif } +// dummy function attached to TxC interrupt. Is faster than if(NULL) check +void dummyFct(void) { /* dummy */} + // macro to guard critical sections when needed for large TX buffer sizes #if (SERIAL_TX_BUFFER_SIZE>256) #define TX_BUFFER_ATOMIC ATOMIC_BLOCK(ATOMIC_RESTORESTATE) @@ -114,15 +117,6 @@ void HardwareSerial::_tx_udr_empty_irq(void) } } -void HardwareSerial::_tx_complete_irq(void) -{ - // user send function was attached -> call it - if (_isrTx) { - _isrTx(); - } - -} - // Public Methods ////////////////////////////////////////////////////////////// void HardwareSerial::begin(unsigned long baud, byte config) @@ -158,6 +152,7 @@ void HardwareSerial::begin(unsigned long baud, byte config) sbi(*_ucsrb, TXEN0); sbi(*_ucsrb, RXCIE0); cbi(*_ucsrb, UDRIE0); + //cbi(*_ucsrb, TXCIE0); } void HardwareSerial::end() @@ -300,20 +295,19 @@ void HardwareSerial::attachInterrupt_Receive( isrRx_t fn ) void HardwareSerial::attachInterrupt_Send( isrTx_t fn ) { - uint8_t oldSREG = SREG; - cli(); - _isrTx = fn; - sbi(*_ucsrb, TXCIE0); - SREG = oldSREG; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + _isrTx = fn; + sbi(*_ucsra, TXC0); // clear TXC status + sbi(*_ucsrb, TXCIE0); // activate TXC interrupt + } } void HardwareSerial::detachInterrupt_Send() { - uint8_t oldSREG = SREG; - cli(); - _isrTx = NULL; - cbi(*_ucsrb, TXCIE0); - SREG = oldSREG; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { + _isrTx = NULL; + cbi(*_ucsrb, TXCIE0); // deactivate TXC interrupt + } } #endif // whole file diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index 1e3de78a7..a9354877b 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -114,6 +114,12 @@ class HardwareSerial : public Stream // instruction. unsigned char _rx_buffer[SERIAL_RX_BUFFER_SIZE]; unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE]; + + // custom handlers for RX and TXC interrupts + typedef void (* isrRx_t)( uint8_t d, uint8_t s ); + typedef void (* isrTx_t)( void ); + isrRx_t _isrRx; + isrTx_t _isrTx; public: inline HardwareSerial( @@ -139,17 +145,15 @@ class HardwareSerial : public Stream // Interrupt handlers - Not intended to be called externally inline void _rx_complete_irq(void); void _tx_udr_empty_irq(void); - void _tx_complete_irq(void); + inline void _tx_complete_irq(void); - typedef void (* isrRx_t)( uint8_t d, uint8_t s ); + // attach custom handlers for RX and TXC interrupts void attachInterrupt_Receive( isrRx_t fn ); void detachInterrupt_Receive() { attachInterrupt_Receive( (isrRx_t) NULL ); }; - typedef void (* isrTx_t)( void ); void attachInterrupt_Send( isrTx_t fn ); void detachInterrupt_Send( void ); + private: - isrRx_t _isrRx; - isrTx_t _isrTx; HardwareSerial( const HardwareSerial & ); HardwareSerial & operator =( const HardwareSerial &); diff --git a/cores/arduino/HardwareSerial_private.h b/cores/arduino/HardwareSerial_private.h index ac61bed20..575d519f4 100644 --- a/cores/arduino/HardwareSerial_private.h +++ b/cores/arduino/HardwareSerial_private.h @@ -84,6 +84,9 @@ #error "Not all bit positions for UART3 are the same as for UART0" #endif +// dummy custom function attached and TXC interrupt. Is faster than if(NULL) check +void dummyFct(void); + // Constructors //////////////////////////////////////////////////////////////// HardwareSerial::HardwareSerial( @@ -95,7 +98,7 @@ HardwareSerial::HardwareSerial( _udr(udr), _rx_buffer_head(0), _rx_buffer_tail(0), _tx_buffer_head(0), _tx_buffer_tail(0), - _isrRx(0), _isrTx(0) + _isrRx(dummyFct), _isrTx(dummyFct) { } @@ -134,4 +137,10 @@ void HardwareSerial::_rx_complete_irq(void) } } +void HardwareSerial::_tx_complete_irq(void) +{ + // user send function was attached -> call it + _isrTx(); +} + #endif // whole file From cbcc356652ec3c5be1ae07df87311fafee1ecd67 Mon Sep 17 00:00:00 2001 From: Georg Icking-Konert Date: Sat, 23 Nov 2019 13:57:38 +0100 Subject: [PATCH 6/8] minor cosmetics minor cosmetics --- cores/arduino/HardwareSerial.cpp | 10 +++++----- cores/arduino/HardwareSerial.h | 5 ++++- cores/arduino/HardwareSerial_private.h | 5 +---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 74ee0040a..fc3716bc4 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -79,9 +79,6 @@ void serialEventRun(void) #endif } -// dummy function attached to TxC interrupt. Is faster than if(NULL) check -void dummyFct(void) { /* dummy */} - // macro to guard critical sections when needed for large TX buffer sizes #if (SERIAL_TX_BUFFER_SIZE>256) #define TX_BUFFER_ATOMIC ATOMIC_BLOCK(ATOMIC_RESTORESTATE) @@ -89,6 +86,9 @@ void dummyFct(void) { /* dummy */} #define TX_BUFFER_ATOMIC #endif +// dummy custom function for TxC interrupt. Is faster than check if(fct==NULL) +void dummyTxFct(void) { /* dummy */} + // Actual interrupt handlers ////////////////////////////////////////////////////////////// void HardwareSerial::_tx_udr_empty_irq(void) @@ -296,7 +296,7 @@ void HardwareSerial::attachInterrupt_Receive( isrRx_t fn ) void HardwareSerial::attachInterrupt_Send( isrTx_t fn ) { ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { - _isrTx = fn; + _isrTx = fn; // set custom function sbi(*_ucsra, TXC0); // clear TXC status sbi(*_ucsrb, TXCIE0); // activate TXC interrupt } @@ -305,7 +305,7 @@ void HardwareSerial::attachInterrupt_Send( isrTx_t fn ) void HardwareSerial::detachInterrupt_Send() { ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { - _isrTx = NULL; + _isrTx = dummyTxFct; // restore dummy function cbi(*_ucsrb, TXCIE0); // deactivate TXC interrupt } } diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index a9354877b..b39590496 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -92,6 +92,9 @@ typedef uint8_t rx_buffer_index_t; #define SERIAL_7O2 0x3C #define SERIAL_8O2 0x3E +// dummy custom function for TxC interrupt. Is faster than check if(fct==NULL) +void dummyTxFct(void); + class HardwareSerial : public Stream { protected: @@ -149,7 +152,7 @@ class HardwareSerial : public Stream // attach custom handlers for RX and TXC interrupts void attachInterrupt_Receive( isrRx_t fn ); - void detachInterrupt_Receive() { attachInterrupt_Receive( (isrRx_t) NULL ); }; + void detachInterrupt_Receive( void ) { attachInterrupt_Receive( (isrRx_t) NULL ); }; void attachInterrupt_Send( isrTx_t fn ); void detachInterrupt_Send( void ); diff --git a/cores/arduino/HardwareSerial_private.h b/cores/arduino/HardwareSerial_private.h index 575d519f4..5446ab619 100644 --- a/cores/arduino/HardwareSerial_private.h +++ b/cores/arduino/HardwareSerial_private.h @@ -84,9 +84,6 @@ #error "Not all bit positions for UART3 are the same as for UART0" #endif -// dummy custom function attached and TXC interrupt. Is faster than if(NULL) check -void dummyFct(void); - // Constructors //////////////////////////////////////////////////////////////// HardwareSerial::HardwareSerial( @@ -98,7 +95,7 @@ HardwareSerial::HardwareSerial( _udr(udr), _rx_buffer_head(0), _rx_buffer_tail(0), _tx_buffer_head(0), _tx_buffer_tail(0), - _isrRx(dummyFct), _isrTx(dummyFct) + _isrRx(NULL), _isrTx(dummyTxFct) { } From b4f39848dd457d7e5342295fcbd98d6153ee297e Mon Sep 17 00:00:00 2001 From: Georg Icking-Konert Date: Sat, 23 Nov 2019 14:14:39 +0100 Subject: [PATCH 7/8] updated modification date - updated modification date to sync with SAM core - no functional change --- cores/arduino/HardwareSerial.cpp | 2 +- cores/arduino/HardwareSerial.h | 2 +- cores/arduino/HardwareSerial0.cpp | 2 +- cores/arduino/HardwareSerial1.cpp | 2 +- cores/arduino/HardwareSerial2.cpp | 2 +- cores/arduino/HardwareSerial3.cpp | 2 +- cores/arduino/HardwareSerial_private.h | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index fc3716bc4..39984fc36 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -21,7 +21,7 @@ Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman Modified 2 November 2015 by SlashDev - Modified 7 November 2019 by Georg Icking-Konert + Modified 23 November 2019 by Georg Icking-Konert */ #include diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index b39590496..b7368ccc5 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -20,7 +20,7 @@ Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman Modified 2 November 2015 by SlashDev - Modified 7 November 2019 by Georg Icking-Konert + Modified 23 November 2019 by Georg Icking-Konert */ #ifndef HardwareSerial_h diff --git a/cores/arduino/HardwareSerial0.cpp b/cores/arduino/HardwareSerial0.cpp index 9f507b6c2..33810d21d 100644 --- a/cores/arduino/HardwareSerial0.cpp +++ b/cores/arduino/HardwareSerial0.cpp @@ -20,7 +20,7 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman - Modified 17 November 2019 by Georg Icking-Konert + Modified 23 November 2019 by Georg Icking-Konert */ #include "Arduino.h" diff --git a/cores/arduino/HardwareSerial1.cpp b/cores/arduino/HardwareSerial1.cpp index 800191700..2dbad872d 100644 --- a/cores/arduino/HardwareSerial1.cpp +++ b/cores/arduino/HardwareSerial1.cpp @@ -20,7 +20,7 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman - Modified 17 November 2019 by Georg Icking-Konert + Modified 23 November 2019 by Georg Icking-Konert */ #include "Arduino.h" diff --git a/cores/arduino/HardwareSerial2.cpp b/cores/arduino/HardwareSerial2.cpp index 1a3b7d754..a06569a37 100644 --- a/cores/arduino/HardwareSerial2.cpp +++ b/cores/arduino/HardwareSerial2.cpp @@ -20,7 +20,7 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman - Modified 17 November 2019 by Georg Icking-Konert + Modified 23 November 2019 by Georg Icking-Konert */ #include "Arduino.h" diff --git a/cores/arduino/HardwareSerial3.cpp b/cores/arduino/HardwareSerial3.cpp index aaac520a5..b010858ba 100644 --- a/cores/arduino/HardwareSerial3.cpp +++ b/cores/arduino/HardwareSerial3.cpp @@ -20,7 +20,7 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 3 December 2013 by Matthijs Kooijman - Modified 17 November 2019 by Georg Icking-Konert + Modified 23 November 2019 by Georg Icking-Konert */ #include "Arduino.h" diff --git a/cores/arduino/HardwareSerial_private.h b/cores/arduino/HardwareSerial_private.h index 5446ab619..ee1dd611d 100644 --- a/cores/arduino/HardwareSerial_private.h +++ b/cores/arduino/HardwareSerial_private.h @@ -20,7 +20,7 @@ Modified 28 September 2010 by Mark Sproul Modified 14 August 2012 by Alarus Modified 2 November 2015 by SlashDev - Modified 17 November 2019 by Georg Icking-Konert + Modified 23 November 2019 by Georg Icking-Konert */ #include "wiring_private.h" From eb648c1efd108f01c189193d33700a9259626fa3 Mon Sep 17 00:00:00 2001 From: Georg Icking-Konert Date: Fri, 24 Dec 2021 09:28:45 +0100 Subject: [PATCH 8/8] added optional argument pointer added optional argument pointer, see https://github.com/arduino/ArduinoCore-sam/pull/95#issuecomment-999825944 --- cores/arduino/HardwareSerial.cpp | 3 ++- cores/arduino/HardwareSerial.h | 5 +++-- cores/arduino/HardwareSerial_private.h | 6 +++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/cores/arduino/HardwareSerial.cpp b/cores/arduino/HardwareSerial.cpp index 39984fc36..e8eae9524 100644 --- a/cores/arduino/HardwareSerial.cpp +++ b/cores/arduino/HardwareSerial.cpp @@ -285,11 +285,12 @@ size_t HardwareSerial::write(uint8_t c) return 1; } -void HardwareSerial::attachInterrupt_Receive( isrRx_t fn ) +void HardwareSerial::attachInterrupt_Receive( isrRx_t fn, void* args ) { uint8_t oldSREG = SREG; cli(); _isrRx = fn; + _rxArg = args; SREG = oldSREG; } diff --git a/cores/arduino/HardwareSerial.h b/cores/arduino/HardwareSerial.h index b7368ccc5..14c29c2ce 100644 --- a/cores/arduino/HardwareSerial.h +++ b/cores/arduino/HardwareSerial.h @@ -119,10 +119,11 @@ class HardwareSerial : public Stream unsigned char _tx_buffer[SERIAL_TX_BUFFER_SIZE]; // custom handlers for RX and TXC interrupts - typedef void (* isrRx_t)( uint8_t d, uint8_t s ); + typedef void (* isrRx_t)( uint8_t data, uint8_t status, void* args ); typedef void (* isrTx_t)( void ); isrRx_t _isrRx; isrTx_t _isrTx; + void* _rxArg; public: inline HardwareSerial( @@ -151,7 +152,7 @@ class HardwareSerial : public Stream inline void _tx_complete_irq(void); // attach custom handlers for RX and TXC interrupts - void attachInterrupt_Receive( isrRx_t fn ); + void attachInterrupt_Receive( isrRx_t fn, void *args = NULL ); void detachInterrupt_Receive( void ) { attachInterrupt_Receive( (isrRx_t) NULL ); }; void attachInterrupt_Send( isrTx_t fn ); void detachInterrupt_Send( void ); diff --git a/cores/arduino/HardwareSerial_private.h b/cores/arduino/HardwareSerial_private.h index ee1dd611d..652622508 100644 --- a/cores/arduino/HardwareSerial_private.h +++ b/cores/arduino/HardwareSerial_private.h @@ -95,7 +95,7 @@ HardwareSerial::HardwareSerial( _udr(udr), _rx_buffer_head(0), _rx_buffer_tail(0), _tx_buffer_head(0), _tx_buffer_tail(0), - _isrRx(NULL), _isrTx(dummyTxFct) + _isrRx(NULL), _isrTx(dummyTxFct), _rxArg(NULL) { } @@ -103,11 +103,11 @@ HardwareSerial::HardwareSerial( void HardwareSerial::_rx_complete_irq(void) { - // user receive function was attached -> call it with data and status byte + // user receive function was attached -> call it with data, status byte and optional argument pointer if (_isrRx) { unsigned char status = *_ucsra; unsigned char data = *_udr; - _isrRx( data, status ); + _isrRx( data, status, _rxArg ); } // default: save data in ring buffer