Skip to content

Commit

Permalink
Update MCUdude corefiles
Browse files Browse the repository at this point in the history
Merge commit 'ace44ebf634b27f18b113c05074c099643cdbb18'
  • Loading branch information
MCUdude committed Jan 21, 2023
2 parents 3bef82e + ace44eb commit ab32882
Show file tree
Hide file tree
Showing 11 changed files with 242 additions and 119 deletions.
3 changes: 2 additions & 1 deletion avr/cores/MCUdude_corefiles/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 avr/cores/MCUdude_corefiles/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 avr/cores/MCUdude_corefiles/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 avr/cores/MCUdude_corefiles/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 avr/cores/MCUdude_corefiles/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 avr/cores/MCUdude_corefiles/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 avr/cores/MCUdude_corefiles/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 ab32882

Please sign in to comment.