diff --git a/cores/arduino/UARTClass.cpp b/cores/arduino/UARTClass.cpp index 36de1358..cd207faa 100644 --- a/cores/arduino/UARTClass.cpp +++ b/cores/arduino/UARTClass.cpp @@ -20,6 +20,7 @@ #include #include #include "UARTClass.h" +#include "Arduino.h" // Constructors //////////////////////////////////////////////////////////////// @@ -31,6 +32,9 @@ UARTClass::UARTClass( Uart *pUart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer *p _pUart=pUart; _dwIrq=dwIrq; _dwId=dwId; + + _isrRx = NULL; + _isrTx = NULL; } // Public Methods ////////////////////////////////////////////////////////////// @@ -166,13 +170,47 @@ size_t UARTClass::write( const uint8_t uc_data ) return 1; } +void UARTClass::attachInterrupt_Receive( isrRx_t fn ) +{ + // pause interrupts + uint8_t oldISR = ((__get_PRIMASK() & 0x1) == 0 && (__get_FAULTMASK() & 0x1) == 0); noInterrupts(); + + // set custom function + _isrRx = fn; + + // restore old interrupt setting + if (oldISR != 0) { interrupts(); } +} + +void UARTClass::attachInterrupt_Send( isrTx_t fn ) +{ + // pause interrupts + uint8_t oldISR = ((__get_PRIMASK() & 0x1) == 0 && (__get_FAULTMASK() & 0x1) == 0); noInterrupts(); + + // set custom function for TX empty + _isrTx = fn; + + // restore old interrupt setting + if (oldISR != 0) { interrupts(); } +} + void UARTClass::IrqHandler( void ) { uint32_t status = _pUart->UART_SR; // Did we receive data? - if ((status & UART_SR_RXRDY) == UART_SR_RXRDY) - _rx_buffer->store_char(_pUart->UART_RHR); + if ((status & UART_SR_RXRDY) == UART_SR_RXRDY) { + + // custom function was attached -> call it with data and status byte + if (_isrRx) { + _isrRx(_pUart->UART_RHR, status); + } + // no custom function attached -> store data in ring buffer + else { + _rx_buffer->store_char(_pUart->UART_RHR); + } + + } // Do we need to keep sending data? if ((status & UART_SR_TXRDY) == UART_SR_TXRDY) @@ -185,11 +223,29 @@ void UARTClass::IrqHandler( void ) { // Mask off transmit interrupt so we don't get it anymore _pUart->UART_IDR = UART_IDR_TXRDY; + + // if custom routine attached, activate TXBUFE interrupt -> delay call until transmission finished + if (_isrTx != NULL) { + _pUart->UART_IER = UART_IER_TXEMPTY; + } + } + + } + + // Is data transmission finished? Used for call of attached custom function at end of transmission? + if ((status & UART_SR_TXEMPTY) == UART_SR_TXEMPTY) + { + // Mask off interrupt so we don't get it anymore + _pUart->UART_IDR = UART_IDR_TXEMPTY; + + // if custom routine attached, call it + if (_isrTx != NULL) { + _isrTx(); } } // Acknowledge errors - if ((status & UART_SR_OVRE) == UART_SR_OVRE || (status & UART_SR_FRAME) == UART_SR_FRAME) + if ((status & UART_SR_OVRE) == UART_SR_OVRE || (status & UART_SR_FRAME) == UART_SR_FRAME || (status & UART_SR_RXBRK) == UART_SR_RXBRK) { // TODO: error reporting outside ISR _pUart->UART_CR |= UART_CR_RSTSTA; diff --git a/cores/arduino/UARTClass.h b/cores/arduino/UARTClass.h index 3747d8be..693ee3a3 100644 --- a/cores/arduino/UARTClass.h +++ b/cores/arduino/UARTClass.h @@ -31,6 +31,8 @@ #define SERIAL_8M1 UARTClass::Mode_8M1 #define SERIAL_8S1 UARTClass::Mode_8S1 +// missing in CMSIS +#define UART_SR_RXBRK (0x1u << 2) class UARTClass : public HardwareSerial { @@ -60,6 +62,13 @@ class UARTClass : public HardwareSerial void IrqHandler(void); + typedef void (* isrRx_t)(uint8_t data, uint32_t status); + typedef void (* isrTx_t)( void ); + void attachInterrupt_Receive( isrRx_t fn ); + void detachInterrupt_Receive( void ) { attachInterrupt_Receive( (isrRx_t) NULL); }; + void attachInterrupt_Send( isrTx_t fn ); + void detachInterrupt_Send( void ) { attachInterrupt_Send( (isrTx_t) NULL); }; + operator bool() { return true; }; // UART always active protected: @@ -72,6 +81,8 @@ class UARTClass : public HardwareSerial IRQn_Type _dwIrq; uint32_t _dwId; + isrRx_t _isrRx; + isrTx_t _isrTx; }; #endif // _UART_CLASS_