Skip to content

Commit dee7d53

Browse files
committed
Update MCUdude corefiles
Merge commit 'de3c03de5c9d9011d79e4f8800d174760a3685f8'
2 parents cdd293c + de3c03d commit dee7d53

File tree

11 files changed

+242
-119
lines changed

11 files changed

+242
-119
lines changed

avr/cores/MCUdude_corefiles/Arduino.h

Lines changed: 2 additions & 1 deletion
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

avr/cores/MCUdude_corefiles/HardwareSerial.cpp

Lines changed: 46 additions & 16 deletions
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
}

avr/cores/MCUdude_corefiles/Stream.cpp

Lines changed: 0 additions & 1 deletion
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();

avr/cores/MCUdude_corefiles/Tone.cpp

Lines changed: 17 additions & 17 deletions
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;

avr/cores/MCUdude_corefiles/WString.cpp

Lines changed: 2 additions & 1 deletion
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
/*********************************************/

avr/cores/MCUdude_corefiles/abi.cpp

100755100644
Lines changed: 8 additions & 7 deletions
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-

avr/cores/MCUdude_corefiles/new

Lines changed: 66 additions & 0 deletions
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)