Skip to content

Commit

Permalink
Squashed 'avr/cores/MCUdude_corefiles/' changes from 0d56ecc53..55de1…
Browse files Browse the repository at this point in the history
…dc14

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
  • Loading branch information
MCUdude committed Jan 21, 2023
1 parent 65f1bee commit de3c03d
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 de3c03d

Please sign in to comment.