Skip to content

Commit de3c03d

Browse files
committed
Squashed 'avr/cores/MCUdude_corefiles/' changes from 0d56ecc53..55de1dc14
55de1dc14 ISO c++ doesn't support binary contants however GNU c++ does c3890dc86 Fix weak attributions on operator new and delete 22d364ecc Mute unused variable warnings 2ffc04d4f Update abi and new It's now up to date with the one ArduinoCore-avr uses 133dcfd3d Fix unused variable and guard warning 7827dd8b3 Improve how TXCn bit is cleared in USCRnA register Preserve values of configuration bits MPCMn and U2Xn. Avoid setting other read-only bits for datasheet conformance. See arduino/ArduinoCore-avr#120 for details 6103f33f3 Formatting c8bef0bf5 Improvements to HardwareSerial.cpp 45437133d Add null pointer check to String destructor 811b51677 Adding parenthesis around 'bitvalue' allowing correct macro expansion when using with ternary operator such as bitWrite(value, bit, some_computed_value == 5 ? 1: 0); e16f14c78 Add bitToggle macro 221900dc9 Removes unnecessary if branch(because length is checked in while statement below the if-clause). 13d1f7607 Improve wiring_shift function 64786bc16 Use ADC instead of combining ADCL and ADCH git-subtree-dir: avr/cores/MCUdude_corefiles git-subtree-split: 55de1dc14dc8c530388cb162564b6e1c95eb7a39
1 parent 65f1bee commit de3c03d

11 files changed

+242
-119
lines changed

Arduino.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ void yield(void);
152152
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
153153
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
154154
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
155-
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
155+
#define bitToggle(value, bit) ((value) ^= (1UL << (bit)))
156+
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))
156157

157158
// avr-libc defines _NOP() since 1.6.2
158159
#ifndef _NOP

HardwareSerial.cpp

+46-16
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <stdio.h>
2727
#include <string.h>
2828
#include <inttypes.h>
29+
#include <util/atomic.h>
2930
#include "Arduino.h"
3031

3132
#include "HardwareSerial.h"
@@ -76,6 +77,13 @@ void serialEventRun(void)
7677
#endif
7778
}
7879

80+
// macro to guard critical sections when needed for large TX buffer sizes
81+
#if (SERIAL_TX_BUFFER_SIZE>256)
82+
#define TX_BUFFER_ATOMIC ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
83+
#else
84+
#define TX_BUFFER_ATOMIC
85+
#endif
86+
7987
// Actual interrupt handlers //////////////////////////////////////////////////////////////
8088

8189
void HardwareSerial::_tx_udr_empty_irq(void)
@@ -89,8 +97,14 @@ void HardwareSerial::_tx_udr_empty_irq(void)
8997

9098
// clear the TXC bit -- "can be cleared by writing a one to its bit
9199
// location". This makes sure flush() won't return until the bytes
92-
// actually got written
93-
*_ucsra |= _BV(TXC0);
100+
// actually got written. Other r/w bits are preserved, and zeroes
101+
// written to the rest.
102+
103+
#ifdef MPCM0
104+
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << MPCM0))) | (1 << TXC0);
105+
#else
106+
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << TXC0)));
107+
#endif
94108

95109
if (_tx_buffer_head == _tx_buffer_tail) {
96110
// Buffer empty, so disable interrupts
@@ -174,15 +188,13 @@ int HardwareSerial::read(void)
174188

175189
int HardwareSerial::availableForWrite(void)
176190
{
177-
#if (SERIAL_TX_BUFFER_SIZE>256)
178-
uint8_t oldSREG = SREG;
179-
cli();
180-
#endif
181-
tx_buffer_index_t head = _tx_buffer_head;
182-
tx_buffer_index_t tail = _tx_buffer_tail;
183-
#if (SERIAL_TX_BUFFER_SIZE>256)
184-
SREG = oldSREG;
185-
#endif
191+
tx_buffer_index_t head;
192+
tx_buffer_index_t tail;
193+
194+
TX_BUFFER_ATOMIC {
195+
head = _tx_buffer_head;
196+
tail = _tx_buffer_tail;
197+
}
186198
if (head >= tail) return SERIAL_TX_BUFFER_SIZE - 1 - head + tail;
187199
return tail - head - 1;
188200
}
@@ -215,8 +227,22 @@ size_t HardwareSerial::write(uint8_t c)
215227
// significantly improve the effective datarate at high (>
216228
// 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
217229
if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(*_ucsra, UDRE0)) {
218-
*_udr = c;
219-
*_ucsra |= _BV(TXC0);
230+
// If TXC is cleared before writing UDR and the previous byte
231+
// completes before writing to UDR, TXC will be set but a byte
232+
// is still being transmitted causing flush() to return too soon.
233+
// So writing UDR must happen first.
234+
// Writing UDR and clearing TC must be done atomically, otherwise
235+
// interrupts might delay the TXC clear so the byte written to UDR
236+
// is transmitted (setting TXC) before clearing TXC. Then TXC will
237+
// be cleared when no bytes are left, causing flush() to hang
238+
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
239+
*_udr = c;
240+
#ifdef MPCM0
241+
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << MPCM0))) | (1 << TXC0);
242+
#else
243+
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << TXC0)));
244+
#endif
245+
}
220246
return 1;
221247
}
222248
tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE;
@@ -237,9 +263,13 @@ size_t HardwareSerial::write(uint8_t c)
237263
}
238264

239265
_tx_buffer[_tx_buffer_head] = c;
240-
_tx_buffer_head = i;
241-
242-
*_ucsrb |= _BV(UDRIE0);
266+
// make atomic to prevent execution of ISR between setting the
267+
// head pointer and setting the interrupt flag resulting in buffer
268+
// retransmission
269+
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
270+
_tx_buffer_head = i;
271+
*_ucsrb |= _BV(UDRIE0);
272+
}
243273

244274
return 1;
245275
}

Stream.cpp

-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,6 @@ size_t Stream::readBytes(char *buffer, size_t length)
218218

219219
size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
220220
{
221-
if (length < 1) return 0;
222221
size_t index = 0;
223222
while (index < length) {
224223
int c = timedRead();

Tone.cpp

+17-17
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ static int8_t toneBegin(uint8_t _pin)
279279

280280
void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
281281
{
282-
uint8_t prescalarbits = 0b001;
282+
uint8_t prescalarbits = 0x01;
283283
long toggle_count = 0;
284284
uint32_t ocr = 0;
285285
int8_t _timer;
@@ -295,38 +295,38 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
295295
if (_timer == 0 || _timer == 2)
296296
{
297297
ocr = F_CPU / frequency / 2 - 1;
298-
prescalarbits = 0b001; // ck/1: same for both timers
298+
prescalarbits = 0x01; // ck/1: same for both timers
299299
if (ocr > 255)
300300
{
301301
ocr = F_CPU / frequency / 2 / 8 - 1;
302-
prescalarbits = 0b010; // ck/8: same for both timers
302+
prescalarbits = 0x02; // ck/8: same for both timers
303303

304304
if (_timer == TIMER_WITH_FULL_PRESCALER && ocr > 255)
305305
{
306306
ocr = F_CPU / frequency / 2 / 32 - 1;
307-
prescalarbits = 0b011;
307+
prescalarbits = 0x03;
308308
}
309309

310310
if (ocr > 255)
311311
{
312312
ocr = F_CPU / frequency / 2 / 64 - 1;
313-
prescalarbits = _timer != TIMER_WITH_FULL_PRESCALER ? 0b011 : 0b100;
313+
prescalarbits = _timer != TIMER_WITH_FULL_PRESCALER ? 0x03 : 0x04;
314314

315315
if (_timer == TIMER_WITH_FULL_PRESCALER && ocr > 255)
316316
{
317317
ocr = F_CPU / frequency / 2 / 128 - 1;
318-
prescalarbits = 0b101;
318+
prescalarbits = 0x05;
319319
}
320320

321321
if (ocr > 255)
322322
{
323323
ocr = F_CPU / frequency / 2 / 256 - 1;
324-
prescalarbits = _timer != TIMER_WITH_FULL_PRESCALER ? 0b100 : 0b110;
324+
prescalarbits = _timer != TIMER_WITH_FULL_PRESCALER ? 0x04 : 0x06;
325325
if (ocr > 255)
326326
{
327327
// Can't do any better than /1024
328328
ocr = F_CPU / frequency / 2 / 1024 - 1;
329-
prescalarbits = _timer != TIMER_WITH_FULL_PRESCALER ? 0b101 : 0b111;
329+
prescalarbits = _timer != TIMER_WITH_FULL_PRESCALER ? 0x05 : 0x07;
330330
}
331331
}
332332
}
@@ -335,13 +335,13 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
335335
#if defined(TCCR0B)
336336
if (_timer == 0)
337337
{
338-
TCCR0B = (TCCR0B & 0b11111000) | prescalarbits;
338+
TCCR0B = (TCCR0B & 0xf8) | prescalarbits;
339339
}
340340
else
341341
#endif
342342
#if defined(TCCR2B)
343343
{
344-
TCCR2B = (TCCR2B & 0b11111000) | prescalarbits;
344+
TCCR2B = (TCCR2B & 0xf8) | prescalarbits;
345345
}
346346
#else
347347
{
@@ -354,30 +354,30 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
354354
// two choices for the 16 bit timers: ck/1 or ck/64
355355
ocr = F_CPU / frequency / 2 - 1;
356356

357-
prescalarbits = 0b001;
357+
prescalarbits = 0x01;
358358
if (ocr > 0xffff)
359359
{
360360
ocr = F_CPU / frequency / 2 / 64 - 1;
361-
prescalarbits = 0b011;
361+
prescalarbits = 0x03;
362362
}
363363

364364
if (_timer == 1)
365365
{
366366
#if defined(TCCR1B)
367-
TCCR1B = (TCCR1B & 0b11111000) | prescalarbits;
367+
TCCR1B = (TCCR1B & 0xf8) | prescalarbits;
368368
#endif
369369
}
370370
#if defined(TCCR3B)
371371
else if (_timer == 3)
372-
TCCR3B = (TCCR3B & 0b11111000) | prescalarbits;
372+
TCCR3B = (TCCR3B & 0xf8) | prescalarbits;
373373
#endif
374374
#if defined(TCCR4B)
375375
else if (_timer == 4)
376-
TCCR4B = (TCCR4B & 0b11111000) | prescalarbits;
376+
TCCR4B = (TCCR4B & 0xf8) | prescalarbits;
377377
#endif
378378
#if defined(TCCR5B)
379379
else if (_timer == 5)
380-
TCCR5B = (TCCR5B & 0b11111000) | prescalarbits;
380+
TCCR5B = (TCCR5B & 0xf8) | prescalarbits;
381381
#endif
382382

383383
}
@@ -486,7 +486,7 @@ void disableTimer(uint8_t _timer)
486486
TCCR2A = (1 << WGM20);
487487
#endif
488488
#if defined(TCCR2B) && defined(CS22)
489-
TCCR2B = (TCCR2B & 0b11111000) | (1 << CS22);
489+
TCCR2B = (TCCR2B & 0xf8) | (1 << CS22);
490490
#endif
491491
#if defined(OCR2A)
492492
OCR2A = 0;

WString.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,8 @@ String::String(double value, unsigned char decimalPlaces)
121121

122122
String::~String()
123123
{
124-
free(buffer);
124+
if(buffer)
125+
free(buffer);
125126
}
126127

127128
/*********************************************/

abi.cpp

100755100644
+8-7
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,16 @@
2121
extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__));
2222
extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__));
2323

24+
namespace std {
25+
[[gnu::weak, noreturn]] void terminate() {
26+
abort();
27+
}
28+
}
29+
2430
void __cxa_pure_virtual(void) {
25-
// We might want to write some diagnostics to uart in this case
26-
//std::terminate();
27-
abort();
31+
std::terminate();
2832
}
2933

3034
void __cxa_deleted_virtual(void) {
31-
// We might want to write some diagnostics to uart in this case
32-
//std::terminate();
33-
abort();
35+
std::terminate();
3436
}
35-

new

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
Copyright (c) 2014 Arduino. All right reserved.
3+
4+
This library is free software; you can redistribute it and/or
5+
modify it under the terms of the GNU Lesser General Public
6+
License as published by the Free Software Foundation; either
7+
version 2.1 of the License, or (at your option) any later version.
8+
9+
This library is distributed in the hope that it will be useful,
10+
but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12+
See the GNU Lesser General Public License for more details.
13+
14+
You should have received a copy of the GNU Lesser General Public
15+
License along with this library; if not, write to the Free Software
16+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17+
*/
18+
19+
#ifndef NEW_H
20+
#define NEW_H
21+
22+
#include <stdlib.h>
23+
24+
namespace std {
25+
struct nothrow_t {};
26+
extern const nothrow_t nothrow;
27+
28+
// These are not actually implemented, to prevent overhead and
29+
// complexity. They are still declared to allow implementing
30+
// them in user code if needed.
31+
typedef void (*new_handler)();
32+
new_handler set_new_handler(new_handler new_p) noexcept;
33+
new_handler get_new_handler() noexcept;
34+
35+
// This is normally declared in various headers that we do not have
36+
// available, so just define it here. We could also use ::size_t
37+
// below, but then anyone including <new> can no longer assume
38+
// std::size_t is available.
39+
using size_t = ::size_t;
40+
} // namespace std
41+
42+
void * operator new(std::size_t size);
43+
void * operator new[](std::size_t size);
44+
45+
void * operator new(std::size_t size, const std::nothrow_t tag) noexcept;
46+
void * operator new[](std::size_t size, const std::nothrow_t& tag) noexcept;
47+
48+
void * operator new(std::size_t size, void *place) noexcept;
49+
void * operator new[](std::size_t size, void *place) noexcept;
50+
51+
void operator delete(void * ptr) noexcept;
52+
void operator delete[](void * ptr) noexcept;
53+
54+
#if __cplusplus >= 201402L
55+
void operator delete(void* ptr, std::size_t size) noexcept;
56+
void operator delete[](void * ptr, std::size_t size) noexcept;
57+
#endif // __cplusplus >= 201402L
58+
59+
void operator delete(void* ptr, const std::nothrow_t& tag) noexcept;
60+
void operator delete[](void* ptr, const std::nothrow_t& tag) noexcept;
61+
62+
void operator delete(void* ptr, void* place) noexcept;
63+
void operator delete[](void* ptr, void* place) noexcept;
64+
65+
#endif
66+

0 commit comments

Comments
 (0)