The current check is still always false when the old check was, but
additionally it will not disable the interrupts when they were never
enabled (which shouldn't matter much, but this is more consistent).
In this case, SoftwareSerial::begin will not have enabled the
interrupts, so better not allow the SoftwareSerial instance to enter the
listening state either.
Before enabling interupts, begin would see if the given receive pin
actually has an associated PCINT register. If not, the interrupts would
not be enabled.
Now, the same check is done, but when no register is available, the rx
parameters are not loaded at all (which in turn prevents the interrupt
from being enabled). This allows all code to use the same "is rx
enabled" (which will be added next).
Previously, it could happen that SPI::beginTransaction was
interrupted by an ISR, while it is changing the SPI_AVR_EIMSK
register or interruptSave variable (it seems that there is
a small window after changing SPI_AVR_EIMSK where an interrupt
might still occur). If this happens, interruptSave is overwritten
with an invalid value, permanently disabling the pin interrupts.
To prevent this, disable interrupts globally while changing
these values.
From https://github.com/arduino/Arduino/pull/2376#issuecomment-59671152
Quoting Andrew Kroll:
[..this commit..] introduces a small delay that can prevent the wait
loop form iterating when running at the maximum speed. This gives
you a little more speed, even if it seems counter-intuitive. At
lower speeds, it is unnoticed. Watch the output on an oscilloscope
when running full SPI speed, and you should see closer back-to-back
writes.
Quoting Paul Stoffregen:
I did quite a bit of experimenting with the NOP addition. The one
that's in my copy gives about a 10% speedup on AVR.
Previously, when verbose uploads were enabled, avrdude was run with four
-v options, causing it to dump all raw bytes exchanged with the
bootloader. This floods the console so much that meaningful output
mostly disappears.
Most users probably want to enable verbose mode just to see what avrdude
command is ran. Furthermore, users that benefit from the raw bytes
dumped are perfectly capable of either running avrdude manually, or
modifying platform.txt. Given that, running avrdude with just one -v
should be plenty.
This fixes#891.
When checking the `left` argument, it previously allowed having
left == len. However, this means the substring starts one past the last
character in the string and should return the empty string. In practice,
this already worked correctly, because buffer[len] contains the trailing
nul, so it would (re)assign the empty string to `out`.
However, fixing this check makes it a bit more logical, and prevents a
fairly unlikely out-of-buffer write (to address 0x0) when calling
substring on an invalidated String:
String bar = (char*)NULL;
bar.substring(0, 0);
Previously, this method calculated the length of the string from the
given index onwards. However, the other remove() method called already
contains code for this calculation, which is used when the count passed
in is too big. This means we can just pass in a very big count that is
guaranteed to point past the end of the string, shrinking the remove
method by a few bytes.
Previously, if you passed in a very big index and/or count, the
`index + count` could overflow, making the count be used as-is instead
of being truncated (causing the string to be updated wrongly and
potentially writing to arbitrary memory locations).
We can rewrite the comparison to use `len - index` instead. Since we
know that index < len, we are sure this subtraction does not overflow,
regardless of what values of index and count we pass in.
As an added bonus, the `len - index` value already needed be calculated
inside the if, so this saves a few instructions in the generated code.
To illustrate this problem, consider this code:
String foo = "foo";
Serial.println(foo.length()); // Prints 3
foo.remove(1, 65535); // Should remove all but first character
Serial.println(foo.length()); // Prints 4 without this patch
Not shown in this is example is that some arbitrary memory is written
as well.
The following empty stubs has been replaced by the gcc
flag -fno-threadsafe-static:
int __cxa_guard_acquire(__guard *);
void __cxa_guard_release (__guard *);
void __cxa_guard_abort (__guard *);
The following empty stubs has been moved into their specific
module abi.cpp:
void __cxa_pure_virtual(void) __attribute ((noreturn));
void __cxa_deleted_virtual(void) __attribute ((noreturn));
Fix#107
Stream::find(char *target) passes an empty terminator string to
Stream::findUntil(char *target, char *terminator) which caused a compiler
warning with the updated toolchain, so cast it to a char*.
These chips were previously supported, but since parity error checking
was added, this support has broken. Most chips define UPE0 (etc.) for
the parity error bit. Some chips don't have numbered UARTS so only
define UPE and even fewer define PE instead of UPE. This adds support
for those chips again.
Closes: #2137
Some devices, such as the atmega2560 or the atmega256rfr2 have a timer1c
output. It seems this output is not connected to anything on the Arduino
Mega, but this allows using it on third party hardware nonetheless.
Before, HardwareSerial1+.cpp were a copy of HardwareSerial1.cpp with all
0's replaced by the corresponding number. This would mean that e.g.
the Serial1 object would use the UBRRL register instead of UBRR1L when
it was defined, or the USART_RX_vect instead of USART1_RX_vect.
In practice, this would neve actually cause problems, since:
- No avr chip currently has both the non-numbered registers as well as
numbered registers.
- HardwareSerial.h would only define HAVE_HWSERIALx when the
corresponding numbered register is defined (except for
HAVE_HWSERIAL0, which is also defined when the unnumbered registers
are present).
Furthermore, before both the UARTx_xx_vect and USART_x_xx_vect was used.
Looking at the include files, only UART1_xx_vect is actually used (by
iom161.h), the others use USARTx_xx_vect. For this reason,
HardwareSerial1.cpp keeps the preprocessor conditional to select either
UART or USART and the other files use USART unconditionally.
While we're here, also fix the compiler error message when no valid ISR
name was found (it previously said "for the first UART" in all cases).
Previously, this relied on an (ugly, avr-specific) magic default for the
compiler.path variable, set by the IDE. This allowed the IDE to fall
back to a system-wide toolchain when no bundled toolchain was found (by
making compiler.path empty).
However,
- this only worked for avr, not sam,
- this worked only for gcc, a system-wide avrdude would break on the
avrdude.conf path in platform.txt, and
This would mean that automatic system-wide fallback didn't work in all
situations, so you'd still have to modify platform.txt (or create
platform.local.txt). Since doing that explictly is the most reliable
way, this commit removes the partial-working ability to do this
automatically.
Note that the code to automatically set compiler.path is still kept
around, in case third-party hardware still relies on this. At some
point, this code should be removed, but for now it just shows a warning
message.
In commit 0e97bcb (Put each HardwareSerial instance in its own .cpp
file), the serial event handling was changed. This was probably a
copy-paste typo.
The effect of this bug was that SerialEvent3 would not run, unless
SerialEvent2 was defined, but also that if SerialEvent2 is defined but
SerialEvent3 is not, this could cause a reset (call to NULL pointer).
This closes#1967, thanks to Peter Olson for finding the bug and fix.
Added support for buffer sizes bigger than 256 bytes.
Added possibility to overrule the default size.
Added support for different size of TX and RX buffer sizes.
The default values remain the same. You can however specify a different
value for TX and RX buffer
Added possibility to overrule the default size.
If you want to have different values
define SERIAL_TX_BUFFER_SIZE and SERIAL_RX_BUFFER_SIZE on the command
line
Added support for buffer sizes bigger than 256 bytes.
Because of the possibility to change the size of the buffer sizes longer
than 256 must be supported.
The type of the indexes is decided upon the size of the buffers. So
there is no increase in program/data size when the buffers are smaller
than 257
Added support for different size of TX and RX buffer sizes.
Added support for buffer sizes bigger than 256 bytes.
Added support for different size of TX and RX buffer sizes.
The default values remain the same. If you want to have different values
define SERIAL_TX_BUFFER_SIZE and SERIAL_RX_BUFFER_SIZE on the command
line
Added support for buffer sizes bigger than 256 bytes.
The type of the indexes is decided upon the size of the buffers. So
there is no increase in program/data size when the buffers are smaller
than 257
peekNextDigit() returns an int, so it can return -1 in addition to all
256 possible bytes. By putting the result in a signe char, all bytes
over 128 will be interpreted as "no bytes available". Furthermore, it
seems that on SAM "char" is unsigned by default, causing the
"if (c < 0)" line a bit further down to always be false.
Using an int is more appropriate.
A different fix for this issue was suggested in #1399. This fix helps
towards #1728.
In C++, true and false are language keywords, so there is no need to
define them as macros. Including stdbool.h in C++ effectively changes
nothing. In C, true, false and also the bool type are not available, but
including stdbool.h will make them available.
Using stdbool.h means that we get true, false and the bool type in
whatever way the compiler thinks is best, which seems like a good idea
to me.
This also fixes the following compiler warnings if a .c file includes
both stdbool.h and Arduino.h:
warning: "true" redefined [enabled by default]
#define true 0x1
warning: "false" redefined [enabled by default]
#define false 0x0
This fixes#1570 and helps toward fixing #1728.
This only changed the AVR core, the SAM core already doesn't define true
and false (but doesn't include stdbool.h either).
Previously, pointer casting was used, but this resulted in strict-aliasing warnings:
IPAddress.h: In member function ‘IPAddress::operator uint32_t() const’:
IPAddress.h:46:61: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
operator uint32_t() const { return *((uint32_t*)_address); };
^
IPAddress.h: In member function ‘bool IPAddress::operator==(const IPAddress&) const’:
IPAddress.h:47:81: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
bool operator==(const IPAddress& addr) const { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); };
^
IPAddress.h:47:114: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
bool operator==(const IPAddress& addr) const { return (*((uint32_t*)_address)) == (*((uint32_t*)addr._address)); };
Converting between unrelated types like this is commonly done using a union,
which do not break the strict-aliasing rules. Using that union, inside
IPAddress there is now an attribute _address.bytes for the raw byte
arra, or _address.dword for the uint32_t version.
Since we now have easy access to the uint32_t version, this also removes
two memcpy invocations that can just become assignments.
This patch does not change the generated code in any way, the compiler
already optimized away the memcpy calls and the previous casts mean
exactly the same.
This is a different implementation of a part of #1399 and it helps
toward fixing #1728.
This was already fixed for HardwareSerial.cpp in #1863, but there was
one more case hidden in HardwareSerial_private.h.
The index attributes have been uint8_t for a while, so there is no point
in using int for local variables. This should allow the compiler to
generate slightly more efficient code, but (at least on gcc 4.8.2) it
also confuses the register allocator, causing this change to increase
code size by 2 bytes instead due to extra push/pop instructions (but
this will probably change in the future if the compiler improves).
The index attributes have been uint8_t for a while, so there is no point
in using int for local variables. This should allow the compiler to
generate slightly more efficient code, but (at least on gcc 4.8.2) it
also confuses the register allocator, causing this change to increase
code size by 2 bytes instead due to extra push/pop instructions (but
this will probably change in the future if the compiler improves).
Switch the tx and rx buffer head/tail entries in the HardwareSerial
initialisation list so that they match the order the fields are defined
in. This fixes a compiler warning (repeated for each of the
HardwareSerial source files the header is used in).
This helps improve the effective datarate on high (>500kbit/s) bitrates,
by skipping the interrupt and associated overhead. At 1 Mbit/s the
implementation previously got up to about 600-700 kbit/s, but now it
actually gets up to the 1Mbit/s (values are rough estimates, though).
Moreover, declaring pointers-to-registers as const and using initializer
list in class constructor allows the compiler to further improve inlining
performance.
This change recovers about 50 bytes of program space on single-UART devices.
See #1711
By putting the ISRs and HardwareSerial instance for each instance in a
separate compilation unit, the compile will only consider them for
linking when the instance is actually used. The ISR is always referenced
by the compiler runtime and the Serialx_available() function is always
referenced by SerialEventRun(), but both references are weak and thus do
not cause the compilation to be included in the link by themselves.
The effect of this is that when multiple HardwareSerial ports are
available, but not all are used, buffers are only allocated and ISRs are
only included for the serial ports that are used. On the mega, this
lowers memory usage from 653 bytes to just 182 when only using the first
serial port.
On boards with just a single port, there is no change, since the code
and memory was already left out when no serial port was used at all.
This fixes#1425 and fixes#1259.
Before, this decision was made in few different places, based on
sometimes different register defines.
Now, HardwareSerial.h decides wich UARTS are available, defines
USE_HWSERIALn macros and HardwareSerial.cpp simply checks these macros
(together with some #ifs to decide which registers to use for UART 0).
For consistency, USBAPI.h also defines a HAVE_CDCSERIAL macro when
applicable.
For supported targets, this should change any behaviour. For unsupported
targets, the error messages might subtly change because some checks are
moved or changed.
Additionally, this moves the USBAPI.h include form HardareSerial.h into
Arduino.h and raises an error when both CDC serial and UART0 are
available (previously this would silently use UART0 instead of CDC, but
there is not currently any Atmel chip available for which this would
occur).
Before, the interrupt was disabled when it was triggered and it turned
out there was no data to send. However, the interrupt can be disabled
already when the last byte is written to the UART, since write() will
always re-enable the interrupt when it adds new data to the buffer.
Closes: #1008
When interrupts are disabled, writing to HardwareSerial could cause a
lockup. When the tx buffer is full, a busy-wait loop is used to wait for
the interrupt handler to free up a byte in the buffer. However, when
interrupts are disabled, this will of course never happen and the
Arduino will lock up. This often caused lockups when doing (big) debug
printing from an interrupt handler.
Additionally, calling flush() with interrupts disabled while
transmission was in progress would also cause a lockup.
When interrupts are disabled, the code now actively checks the UDRE
(UART Data Register Empty) and calls the interrupt handler to free up
room if the bit is set.
This can lead to delays in interrupt handlers when the serial buffer is
full, but a delay is of course always preferred to a lockup.
Closes: #672
References: #1147