Skip to content

Commit

Permalink
Squashed 'avr/cores/MCUdude_corefiles/' changes from 0d56ecc5..55de1dc1
Browse files Browse the repository at this point in the history
55de1dc1 ISO c++ doesn't support binary contants however GNU c++ does
c3890dc8 Fix weak attributions on operator new and delete
22d364ec Mute unused variable warnings
2ffc04d4 Update abi and new It's now up to date with the one ArduinoCore-avr uses
133dcfd3 Fix unused variable and guard warning
7827dd8b 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
6103f33f Formatting
c8bef0bf Improvements to HardwareSerial.cpp
45437133 Add null pointer check to String destructor
811b5167 Adding parenthesis around 'bitvalue' allowing correct macro expansion when using with ternary operator such as bitWrite(value, bit, some_computed_value == 5 ? 1: 0);
e16f14c7 Add bitToggle macro
221900dc Removes unnecessary if branch(because length is checked in while statement below the if-clause).
13d1f760 Improve wiring_shift function
64786bc1 Use ADC instead of combining ADCL and ADCH

git-subtree-dir: avr/cores/MCUdude_corefiles
git-subtree-split: 55de1dc14dc8c530388cb162564b6e1c95eb7a39
  • Loading branch information
MCUdude committed Jan 21, 2023
1 parent 9dde154 commit ace44eb
Show file tree
Hide file tree
Showing 11 changed files with 242 additions and 119 deletions.
3 changes: 2 additions & 1 deletion Arduino.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ void yield(void);
#define bitRead(value, bit) (((value) >> (bit)) & 0x01)
#define bitSet(value, bit) ((value) |= (1UL << (bit)))
#define bitClear(value, bit) ((value) &= ~(1UL << (bit)))
#define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit))
#define bitToggle(value, bit) ((value) ^= (1UL << (bit)))
#define bitWrite(value, bit, bitvalue) ((bitvalue) ? bitSet(value, bit) : bitClear(value, bit))

// avr-libc defines _NOP() since 1.6.2
#ifndef _NOP
Expand Down
62 changes: 46 additions & 16 deletions HardwareSerial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <util/atomic.h>
#include "Arduino.h"

#include "HardwareSerial.h"
Expand Down Expand Up @@ -76,6 +77,13 @@ void serialEventRun(void)
#endif
}

// macro to guard critical sections when needed for large TX buffer sizes
#if (SERIAL_TX_BUFFER_SIZE>256)
#define TX_BUFFER_ATOMIC ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
#else
#define TX_BUFFER_ATOMIC
#endif

// Actual interrupt handlers //////////////////////////////////////////////////////////////

void HardwareSerial::_tx_udr_empty_irq(void)
Expand All @@ -89,8 +97,14 @@ void HardwareSerial::_tx_udr_empty_irq(void)

// clear the TXC bit -- "can be cleared by writing a one to its bit
// location". This makes sure flush() won't return until the bytes
// actually got written
*_ucsra |= _BV(TXC0);
// actually got written. Other r/w bits are preserved, and zeroes
// written to the rest.

#ifdef MPCM0
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << MPCM0))) | (1 << TXC0);
#else
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << TXC0)));
#endif

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

int HardwareSerial::availableForWrite(void)
{
#if (SERIAL_TX_BUFFER_SIZE>256)
uint8_t oldSREG = SREG;
cli();
#endif
tx_buffer_index_t head = _tx_buffer_head;
tx_buffer_index_t tail = _tx_buffer_tail;
#if (SERIAL_TX_BUFFER_SIZE>256)
SREG = oldSREG;
#endif
tx_buffer_index_t head;
tx_buffer_index_t tail;

TX_BUFFER_ATOMIC {
head = _tx_buffer_head;
tail = _tx_buffer_tail;
}
if (head >= tail) return SERIAL_TX_BUFFER_SIZE - 1 - head + tail;
return tail - head - 1;
}
Expand Down Expand Up @@ -215,8 +227,22 @@ size_t HardwareSerial::write(uint8_t c)
// significantly improve the effective datarate at high (>
// 500kbit/s) bitrates, where interrupt overhead becomes a slowdown.
if (_tx_buffer_head == _tx_buffer_tail && bit_is_set(*_ucsra, UDRE0)) {
*_udr = c;
*_ucsra |= _BV(TXC0);
// If TXC is cleared before writing UDR and the previous byte
// completes before writing to UDR, TXC will be set but a byte
// is still being transmitted causing flush() to return too soon.
// So writing UDR must happen first.
// Writing UDR and clearing TC must be done atomically, otherwise
// interrupts might delay the TXC clear so the byte written to UDR
// is transmitted (setting TXC) before clearing TXC. Then TXC will
// be cleared when no bytes are left, causing flush() to hang
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
*_udr = c;
#ifdef MPCM0
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << MPCM0))) | (1 << TXC0);
#else
*_ucsra = ((*_ucsra) & ((1 << U2X0) | (1 << TXC0)));
#endif
}
return 1;
}
tx_buffer_index_t i = (_tx_buffer_head + 1) % SERIAL_TX_BUFFER_SIZE;
Expand All @@ -237,9 +263,13 @@ size_t HardwareSerial::write(uint8_t c)
}

_tx_buffer[_tx_buffer_head] = c;
_tx_buffer_head = i;

*_ucsrb |= _BV(UDRIE0);
// make atomic to prevent execution of ISR between setting the
// head pointer and setting the interrupt flag resulting in buffer
// retransmission
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
_tx_buffer_head = i;
*_ucsrb |= _BV(UDRIE0);
}

return 1;
}
Expand Down
1 change: 0 additions & 1 deletion Stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,6 @@ size_t Stream::readBytes(char *buffer, size_t length)

size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
{
if (length < 1) return 0;
size_t index = 0;
while (index < length) {
int c = timedRead();
Expand Down
34 changes: 17 additions & 17 deletions Tone.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ static int8_t toneBegin(uint8_t _pin)

void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
{
uint8_t prescalarbits = 0b001;
uint8_t prescalarbits = 0x01;
long toggle_count = 0;
uint32_t ocr = 0;
int8_t _timer;
Expand All @@ -295,38 +295,38 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
if (_timer == 0 || _timer == 2)
{
ocr = F_CPU / frequency / 2 - 1;
prescalarbits = 0b001; // ck/1: same for both timers
prescalarbits = 0x01; // ck/1: same for both timers
if (ocr > 255)
{
ocr = F_CPU / frequency / 2 / 8 - 1;
prescalarbits = 0b010; // ck/8: same for both timers
prescalarbits = 0x02; // ck/8: same for both timers

if (_timer == TIMER_WITH_FULL_PRESCALER && ocr > 255)
{
ocr = F_CPU / frequency / 2 / 32 - 1;
prescalarbits = 0b011;
prescalarbits = 0x03;
}

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

if (_timer == TIMER_WITH_FULL_PRESCALER && ocr > 255)
{
ocr = F_CPU / frequency / 2 / 128 - 1;
prescalarbits = 0b101;
prescalarbits = 0x05;
}

if (ocr > 255)
{
ocr = F_CPU / frequency / 2 / 256 - 1;
prescalarbits = _timer != TIMER_WITH_FULL_PRESCALER ? 0b100 : 0b110;
prescalarbits = _timer != TIMER_WITH_FULL_PRESCALER ? 0x04 : 0x06;
if (ocr > 255)
{
// Can't do any better than /1024
ocr = F_CPU / frequency / 2 / 1024 - 1;
prescalarbits = _timer != TIMER_WITH_FULL_PRESCALER ? 0b101 : 0b111;
prescalarbits = _timer != TIMER_WITH_FULL_PRESCALER ? 0x05 : 0x07;
}
}
}
Expand All @@ -335,13 +335,13 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
#if defined(TCCR0B)
if (_timer == 0)
{
TCCR0B = (TCCR0B & 0b11111000) | prescalarbits;
TCCR0B = (TCCR0B & 0xf8) | prescalarbits;
}
else
#endif
#if defined(TCCR2B)
{
TCCR2B = (TCCR2B & 0b11111000) | prescalarbits;
TCCR2B = (TCCR2B & 0xf8) | prescalarbits;
}
#else
{
Expand All @@ -354,30 +354,30 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration)
// two choices for the 16 bit timers: ck/1 or ck/64
ocr = F_CPU / frequency / 2 - 1;

prescalarbits = 0b001;
prescalarbits = 0x01;
if (ocr > 0xffff)
{
ocr = F_CPU / frequency / 2 / 64 - 1;
prescalarbits = 0b011;
prescalarbits = 0x03;
}

if (_timer == 1)
{
#if defined(TCCR1B)
TCCR1B = (TCCR1B & 0b11111000) | prescalarbits;
TCCR1B = (TCCR1B & 0xf8) | prescalarbits;
#endif
}
#if defined(TCCR3B)
else if (_timer == 3)
TCCR3B = (TCCR3B & 0b11111000) | prescalarbits;
TCCR3B = (TCCR3B & 0xf8) | prescalarbits;
#endif
#if defined(TCCR4B)
else if (_timer == 4)
TCCR4B = (TCCR4B & 0b11111000) | prescalarbits;
TCCR4B = (TCCR4B & 0xf8) | prescalarbits;
#endif
#if defined(TCCR5B)
else if (_timer == 5)
TCCR5B = (TCCR5B & 0b11111000) | prescalarbits;
TCCR5B = (TCCR5B & 0xf8) | prescalarbits;
#endif

}
Expand Down Expand Up @@ -486,7 +486,7 @@ void disableTimer(uint8_t _timer)
TCCR2A = (1 << WGM20);
#endif
#if defined(TCCR2B) && defined(CS22)
TCCR2B = (TCCR2B & 0b11111000) | (1 << CS22);
TCCR2B = (TCCR2B & 0xf8) | (1 << CS22);
#endif
#if defined(OCR2A)
OCR2A = 0;
Expand Down
3 changes: 2 additions & 1 deletion WString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,8 @@ String::String(double value, unsigned char decimalPlaces)

String::~String()
{
free(buffer);
if(buffer)
free(buffer);
}

/*********************************************/
Expand Down
15 changes: 8 additions & 7 deletions abi.cpp
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,16 @@
extern "C" void __cxa_pure_virtual(void) __attribute__ ((__noreturn__));
extern "C" void __cxa_deleted_virtual(void) __attribute__ ((__noreturn__));

namespace std {
[[gnu::weak, noreturn]] void terminate() {
abort();
}
}

void __cxa_pure_virtual(void) {
// We might want to write some diagnostics to uart in this case
//std::terminate();
abort();
std::terminate();
}

void __cxa_deleted_virtual(void) {
// We might want to write some diagnostics to uart in this case
//std::terminate();
abort();
std::terminate();
}

66 changes: 66 additions & 0 deletions new
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
Copyright (c) 2014 Arduino. All right reserved.

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef NEW_H
#define NEW_H

#include <stdlib.h>

namespace std {
struct nothrow_t {};
extern const nothrow_t nothrow;

// These are not actually implemented, to prevent overhead and
// complexity. They are still declared to allow implementing
// them in user code if needed.
typedef void (*new_handler)();
new_handler set_new_handler(new_handler new_p) noexcept;
new_handler get_new_handler() noexcept;

// This is normally declared in various headers that we do not have
// available, so just define it here. We could also use ::size_t
// below, but then anyone including <new> can no longer assume
// std::size_t is available.
using size_t = ::size_t;
} // namespace std

void * operator new(std::size_t size);
void * operator new[](std::size_t size);

void * operator new(std::size_t size, const std::nothrow_t tag) noexcept;
void * operator new[](std::size_t size, const std::nothrow_t& tag) noexcept;

void * operator new(std::size_t size, void *place) noexcept;
void * operator new[](std::size_t size, void *place) noexcept;

void operator delete(void * ptr) noexcept;
void operator delete[](void * ptr) noexcept;

#if __cplusplus >= 201402L
void operator delete(void* ptr, std::size_t size) noexcept;
void operator delete[](void * ptr, std::size_t size) noexcept;
#endif // __cplusplus >= 201402L

void operator delete(void* ptr, const std::nothrow_t& tag) noexcept;
void operator delete[](void* ptr, const std::nothrow_t& tag) noexcept;

void operator delete(void* ptr, void* place) noexcept;
void operator delete[](void* ptr, void* place) noexcept;

#endif

Loading

0 comments on commit ace44eb

Please sign in to comment.