Skip to content

Commit ccefff5

Browse files
Make blocking behaviour of HardwareSerial::write optional
This introduces two new methods, Serial.setBlocking() and Serial.getBlocking(), which can be used to enable or disable blocking. References: arduino#672 --- TODO: This commit is probably not ready to merge, I'm not sure what the proper API for this feature would be (the current enum approach requires qualifying the constants with HardwareSerial:: for example). I'm also not sure where and how to add the new function to a keywords.txt file.
1 parent 28fe88c commit ccefff5

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

Diff for: hardware/arduino/cores/arduino/HardwareSerial.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ HardwareSerial::HardwareSerial(
253253
_ucsrb = ucsrb;
254254
_ucsrc = ucsrc;
255255
_udr = udr;
256+
_blocking = SERIAL_BLOCK_ALWAYS;
256257
}
257258

258259
// Public Methods //////////////////////////////////////////////////////////////
@@ -312,6 +313,16 @@ void HardwareSerial::end()
312313
_rx_buffer_head = _rx_buffer_tail;
313314
}
314315

316+
void HardwareSerial::setBlocking(blocking_behaviour when)
317+
{
318+
_blocking = when;
319+
}
320+
321+
HardwareSerial::blocking_behaviour HardwareSerial::getBlocking()
322+
{
323+
return _blocking;
324+
}
325+
315326
int HardwareSerial::available(void)
316327
{
317328
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
@@ -374,6 +385,8 @@ size_t HardwareSerial::write(uint8_t c)
374385
// wait for the interrupt handler to empty it a bit
375386
while (i == _tx_buffer_tail) {
376387
if (!interrupts_enabled) {
388+
if (!(_blocking & SERIAL_BLOCK_NON_INTERRUPTIBLE))
389+
return 0;
377390
// Interrupts were disabled at the start of this function, so we
378391
// can't just enable them (that would allow other interrupts to
379392
// trigger as well!). We'll have to poll the data register empty
@@ -382,6 +395,8 @@ size_t HardwareSerial::write(uint8_t c)
382395
if(bit_is_set(*_ucsra, UDRE0))
383396
_tx_udr_empty_irq();
384397
} else {
398+
if (!(_blocking & SERIAL_BLOCK_INTERRUPTIBLE))
399+
return 0;
385400
// Interrupts were enabled, so we can temporarily enable them so
386401
// our tx interrupt can fire and free up some space. Note that we
387402
// can't just use the UDRE polling approach here instead of

Diff for: hardware/arduino/cores/arduino/HardwareSerial.h

+16
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,19 @@
3939

4040
class HardwareSerial : public Stream
4141
{
42+
public:
43+
// Describes the blocking behaviour for writing (note that flushing
44+
// will _always_ block until the transmission is complete).
45+
enum blocking_behaviour {
46+
// Never block, discard data when buffer is full
47+
SERIAL_BLOCK_NEVER = 0,
48+
// Block only when interrupts are enabled
49+
SERIAL_BLOCK_INTERRUPTIBLE = 1 << 0,
50+
// Block only when interrupts are disabled
51+
SERIAL_BLOCK_NON_INTERRUPTIBLE = 1 << 1,
52+
// Always block, never discard data
53+
SERIAL_BLOCK_ALWAYS = SERIAL_BLOCK_INTERRUPTIBLE | SERIAL_BLOCK_NON_INTERRUPTIBLE,
54+
};
4255
protected:
4356
volatile uint8_t *_ubrrh;
4457
volatile uint8_t *_ubrrl;
@@ -48,6 +61,7 @@ class HardwareSerial : public Stream
4861
volatile uint8_t *_udr;
4962
// Has any byte been written to the UART since begin()
5063
bool _written;
64+
blocking_behaviour _blocking;
5165

5266
volatile uint8_t _rx_buffer_head;
5367
volatile uint8_t _rx_buffer_tail;
@@ -68,6 +82,8 @@ class HardwareSerial : public Stream
6882
void begin(unsigned long);
6983
void begin(unsigned long, uint8_t);
7084
void end();
85+
void setBlocking(blocking_behaviour when);
86+
blocking_behaviour getBlocking();
7187
virtual int available(void);
7288
virtual int peek(void);
7389
virtual int read(void);

0 commit comments

Comments
 (0)