Skip to content

Commit 7339907

Browse files
committed
Merge branch 'Serial_attachInterrupt'
2 parents 790ff2c + 1557f9c commit 7339907

File tree

2 files changed

+81
-3
lines changed

2 files changed

+81
-3
lines changed

Diff for: cores/arduino/UARTClass.cpp

+68-3
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,15 @@
1414
You should have received a copy of the GNU Lesser General Public
1515
License along with this library; if not, write to the Free Software
1616
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
18+
Modified 23 November 2019 by Georg Icking-Konert
1719
*/
1820

1921
#include <stdlib.h>
2022
#include <stdio.h>
2123
#include <string.h>
2224
#include "UARTClass.h"
25+
#include "Arduino.h"
2326

2427
// Constructors ////////////////////////////////////////////////////////////////
2528

@@ -31,6 +34,9 @@ UARTClass::UARTClass( Uart *pUart, IRQn_Type dwIrq, uint32_t dwId, RingBuffer *p
3134
_pUart=pUart;
3235
_dwIrq=dwIrq;
3336
_dwId=dwId;
37+
38+
_isrRx = NULL;
39+
_isrTx = NULL;
3440
}
3541

3642
// Public Methods //////////////////////////////////////////////////////////////
@@ -162,17 +168,58 @@ size_t UARTClass::write( const uint8_t uc_data )
162168
{
163169
// Bypass buffering and send character directly
164170
_pUart->UART_THR = uc_data;
171+
172+
// if custom routine attached, activate TXBUFE interrupt -> delay call until transmission finished
173+
// must be done here explicitely because UART_TXRDY interrupt is not activated here
174+
if (_isrTx != NULL) {
175+
_pUart->UART_IER = UART_IER_TXEMPTY;
176+
}
165177
}
178+
166179
return 1;
167180
}
168181

182+
void UARTClass::attachInterrupt_Receive( isrRx_t fn )
183+
{
184+
// pause interrupts
185+
uint8_t oldISR = ((__get_PRIMASK() & 0x1) == 0 && (__get_FAULTMASK() & 0x1) == 0); noInterrupts();
186+
187+
// set custom function
188+
_isrRx = fn;
189+
190+
// restore old interrupt setting
191+
if (oldISR != 0) { interrupts(); }
192+
}
193+
194+
void UARTClass::attachInterrupt_Send( isrTx_t fn )
195+
{
196+
// pause interrupts
197+
uint8_t oldISR = ((__get_PRIMASK() & 0x1) == 0 && (__get_FAULTMASK() & 0x1) == 0); noInterrupts();
198+
199+
// set custom function for TX empty
200+
_isrTx = fn;
201+
202+
// restore old interrupt setting
203+
if (oldISR != 0) { interrupts(); }
204+
}
205+
169206
void UARTClass::IrqHandler( void )
170207
{
171208
uint32_t status = _pUart->UART_SR;
172209

173210
// Did we receive data?
174-
if ((status & UART_SR_RXRDY) == UART_SR_RXRDY)
175-
_rx_buffer->store_char(_pUart->UART_RHR);
211+
if ((status & UART_SR_RXRDY) == UART_SR_RXRDY) {
212+
213+
// custom function was attached -> call it with data and status byte
214+
if (_isrRx) {
215+
_isrRx(_pUart->UART_RHR, status);
216+
}
217+
// no custom function attached -> store data in ring buffer
218+
else {
219+
_rx_buffer->store_char(_pUart->UART_RHR);
220+
}
221+
222+
}
176223

177224
// Do we need to keep sending data?
178225
if ((status & UART_SR_TXRDY) == UART_SR_TXRDY)
@@ -185,11 +232,29 @@ void UARTClass::IrqHandler( void )
185232
{
186233
// Mask off transmit interrupt so we don't get it anymore
187234
_pUart->UART_IDR = UART_IDR_TXRDY;
235+
236+
// if custom routine attached, activate TXBUFE interrupt -> delay call until transmission finished
237+
if (_isrTx != NULL) {
238+
_pUart->UART_IER = UART_IER_TXEMPTY;
239+
}
240+
}
241+
242+
}
243+
244+
// Is data transmission finished? Used for call of attached custom function at end of transmission?
245+
if ((status & UART_SR_TXEMPTY) == UART_SR_TXEMPTY)
246+
{
247+
// Mask off interrupt so we don't get it anymore
248+
_pUart->UART_IDR = UART_IDR_TXEMPTY;
249+
250+
// if custom routine attached, call it
251+
if (_isrTx != NULL) {
252+
_isrTx();
188253
}
189254
}
190255

191256
// Acknowledge errors
192-
if ((status & UART_SR_OVRE) == UART_SR_OVRE || (status & UART_SR_FRAME) == UART_SR_FRAME)
257+
if ((status & UART_SR_OVRE) == UART_SR_OVRE || (status & UART_SR_FRAME) == UART_SR_FRAME || (status & UART_SR_RXBRK) == UART_SR_RXBRK)
193258
{
194259
// TODO: error reporting outside ISR
195260
_pUart->UART_CR |= UART_CR_RSTSTA;

Diff for: cores/arduino/UARTClass.h

+13
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
You should have received a copy of the GNU Lesser General Public
1515
License along with this library; if not, write to the Free Software
1616
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
18+
Modified 23 November 2019 by Georg Icking-Konert
1719
*/
1820

1921
#ifndef _UART_CLASS_
@@ -31,6 +33,8 @@
3133
#define SERIAL_8M1 UARTClass::Mode_8M1
3234
#define SERIAL_8S1 UARTClass::Mode_8S1
3335

36+
// missing in CMSIS
37+
#define UART_SR_RXBRK (0x1u << 2)
3438

3539
class UARTClass : public HardwareSerial
3640
{
@@ -60,6 +64,13 @@ class UARTClass : public HardwareSerial
6064

6165
void IrqHandler(void);
6266

67+
typedef void (* isrRx_t)(uint8_t data, uint32_t status);
68+
typedef void (* isrTx_t)( void );
69+
void attachInterrupt_Receive( isrRx_t fn );
70+
void detachInterrupt_Receive( void ) { attachInterrupt_Receive( (isrRx_t) NULL); };
71+
void attachInterrupt_Send( isrTx_t fn );
72+
void detachInterrupt_Send( void ) { attachInterrupt_Send( (isrTx_t) NULL); };
73+
6374
operator bool() { return true; }; // UART always active
6475

6576
protected:
@@ -72,6 +83,8 @@ class UARTClass : public HardwareSerial
7283
IRQn_Type _dwIrq;
7384
uint32_t _dwId;
7485

86+
isrRx_t _isrRx;
87+
isrTx_t _isrTx;
7588
};
7689

7790
#endif // _UART_CLASS_

0 commit comments

Comments
 (0)