aboutsummaryrefslogtreecommitdiff
AgeCommit message (Collapse)Author
2014-02-19Use a union in IPAddress for uint8_t[] <-> uint32_t conversionMatthijs Kooijman
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.
2014-02-18Merge pull request #1870 from matthijskooijman/ide-1.5.x-serial-intCristian Maglie
In HardwareSerial::_rx_complete_irq, don't use int for buffer index
2014-02-18In HardwareSerial::_rx_complete_irq, don't use int for buffer indexMatthijs Kooijman
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).
2014-02-14Merge pull request #1863 from matthijskooijman/ide-1.5.x-serial-intCristian Maglie
In HardwareSerial, don't use int for buffer indices
2014-02-14Merge branch 'ide-1.5.x' of github.com:dpslwk/Arduino into dpslwk-ide-1.5.xCristian Maglie
2014-02-14In HardwareSerial, don't use int for buffer indicesMatthijs Kooijman
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).
2014-02-13Merge remote-tracking branch 'arduino/master' into ide-1.5.xCristian Maglie
2014-02-13Added license for Client, IPAddressm and Server (master branch)Cristian Maglie
See #1847 and #1117
2014-02-13Added license for Arduino.h, binary.h and main.cpp (master branch)Cristian Maglie
See #1847 and #1117
2014-02-12Merge branch 'master' into ide-1.5.xCristian Maglie
2014-02-12Revert "Changed pins definition in variants from constants to #defines."Cristian Maglie
This reverts commit 7fcba37acfd11313640b3f5d5c813d63d2f59999.
2014-02-10Added license for Arduino.h, binary.h and main.cppCristian Maglie
See #1847
2014-02-10Added license for Client, IPAddressm and ServerCristian Maglie
See #1847
2014-02-10Added license for avr/HardwareSerial.Cristian Maglie
See #1847
2014-01-29Reorder HardwareSerial init to fix compiler warnMatt Robinson
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).
2014-01-28Clean up unused var from HardwareSerial_private.hMatt Robinson
2014-01-27Merge branch 'serial-patch-2' into ide-1.5.xCristian Maglie
2014-01-22In HardwareSerial::write, bypass the queue when it's emptyMatthijs Kooijman
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).
2014-01-22Inlined HardwareSerial calls to RX ISR.Cristian Maglie
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
2014-01-22Put each HardwareSerial instance in its own .cpp fileMatthijs Kooijman
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.
2014-01-22Centrally decide which hardware UARTS are availableMatthijs Kooijman
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).
2014-01-22Disable the UDRE interrupt sooner in HardwareSerialMatthijs Kooijman
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
2014-01-22Fix lockup when writing to HardwareSerial with interrupts disabledMatthijs Kooijman
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
2014-01-22Fix HardwareSerial::flush() when interrupts are kept disabled for a whileMatthijs Kooijman
It turns out there is an additional corner case. The analysis in the previous commit wrt to flush() assumes that the data register is always kept filled by the interrupt handler, so the TXC bit won't get set until all the queued bytes have been transmitted. But, when interrupts are disabled for a longer period (for example when an interrupt handler for another device is running for longer than 1-2 byte times), it could happen that the UART stops transmitting while there are still more bytes queued (but these are in the buffer, not in the UDR register, so the UART can't know about them). In this case, the TXC bit would get set, but the transmission is not complete yet. We can easily detect this case by looking at the head and tail pointers, but it seems easier to instead look at the UDRIE bit (the TX interrupt is enabled if and only if there are bytes in the queue). To fix this corner case, this commit: - Checks the UDRIE bit and only if it is unset, looks at the TXC bit. - Moves the clearing of TXC from write() to the tx interrupt handler. This (still) causes the TXC bit to be cleared whenever a byte is queued when the buffer is empty (in this case the tx interrupt will trigger directly after write() is called). It also causes the TXC bit to be cleared whenever transmission is resumed after it halted because interrupts have been disabled for too long. As a side effect, another race condition is prevented. This could occur at very high bitrates, where the transmission would be completed before the code got time to clear the TXC0 register, making the clear happen _after_ the transmission was already complete. With the new code, the clearing of TXC happens directly after writing to the UDR register, while interrupts are disabled, and we can be certain the data transmission needs more time than one instruction to complete. This fixes #1463 and replaces #1456.
2014-01-22Improve HardwareSerial::flush()Matthijs Kooijman
The flush() method blocks until all characters in the serial buffer have been written to the uart _and_ transmitted. This is checked by waiting until the "TXC" (TX Complete) bit is set by the UART, signalling completion. This bit is cleared by write() when adding a new byte to the buffer and set by the hardware after tranmission ends, so it is always guaranteed to be zero from the moment the first byte in a sequence is queued until the moment the last byte is transmitted, and it is one from the moment the last byte in the buffer is transmitted until the first byte in the next sequence is queued. However, the TXC bit is also zero from initialization to the moment the first byte ever is queued (and then continues to be zero until the first sequence of bytes completes transmission). Unfortunately we cannot manually set the TXC bit during initialization, we can only clear it. To make sure that flush() would not (indefinitely) block when it is called _before_ anything was written to the serial device, the "transmitting" variable was introduced. This variable suggests that it is only true when something is transmitting, which isn't currently the case (it remains true after transmission is complete until flush() is called, for example). Furthermore, there is no need to keep the status of transmission, the only thing needed is to remember if anything has ever been written, so the corner case described above can be detected. This commit improves the code by: - Renaming the "transmitting" variable to _written (making it more clear and following the leading underscore naming convention). - Not resetting the value of _written at the end of flush(), there is no point to this. - Only checking the "_written" value once in flush(), since it can never be toggled off anyway. - Initializing the value of _written in both versions of _begin (though it probably gets initialized to 0 by default anyway, better to be explicit).
2014-01-22Use bit_is_clear in HardwareSerial::flush()Matthijs Kooijman
This is slightly more clear than the previous explicit comparison.
2014-01-21Compile with -x assembler-with-cpp instead of -assembler-with-cpp.Jimmy Hedman
- Newer avr-gcc doesn't use -assembler-with-cpp, but uses -x assembler-with-cpp. This works with older compilers as well.
2014-01-16Move interrupt handlers into HardwareSerial classMatthijs Kooijman
The actual interrupt vectors are of course defined as before, but they let new methods in the HardwareSerial class do the actual work. This greatly reduces code duplication and prepares for one of my next commits which requires the tx interrupt handler to be called from another context as well. The actual content of the interrupts handlers was pretty much identical, so that remains unchanged (except that store_char was now only needed once, so it was inlined). Now all access to the buffers are inside the HardwareSerial class, the buffer variables can be made private. One would expect a program size reduction from this change (at least with multiple UARTs), but due to the fact that the interrupt handlers now only have indirect access to a few registers (which previously were just hardcoded in the handlers) and because there is some extra function call overhead, the code size on the uno actually increases by around 70 bytes. On the mega, which has four UARTs, the code size decreases by around 70 bytes.
2014-01-16Use constants for register bit positions in HardwareSerialMatthijs Kooijman
Previously, the constants to use for the bit positions of the various UARTs were passed to the HardwareSerial constructor. However, this meant that whenever these values were used, the had to be indirectly loaded, resulting in extra code overhead. Additionally, since there is no instruction to shift a value by a variable amount, the 1 << x expressions (inside _BV and sbi() / cbi()) would be compiled as a loop instead of being evaluated at compiletime. Now, the HardwareSerial class always uses the constants for the bit positions of UART 0 (and some code is present to make sure these constants exist, even for targets that only have a single unnumbered UART or start at UART1). This was already done for the TXC0 constant, for some reason. For the actual register addresses, this approach does not work, since these are of course different between the different UARTs on a single chip. Of course, always using the UART 0 constants is only correct when the constants are actually identical for the different UARTs. It has been verified that this is currently the case for all targets supported by avr-gcc 4.7.2, and the code contains compile-time checks to verify this for the current target, in case a new target is added for which this does not hold. This verification was done using: for i in TXC RXEN TXEN RXCIE UDRIE U2X UPE; do echo $i; grep --no-filename -r "#define $i[0-9]\? " /usr/lib/avr/include/avr/io* | sed "s/#define $i[0-9]\?\s*\(\S\)\+\s*\(\/\*.*\*\/\)\?$/\1/" | sort | uniq ; done This command shows that the above constants are identical for all uarts on all platforms, except for TXC, which is sometimes 6 and sometimes 0. Further investigation shows that it is always 6, except in io90scr100.h, but that file defines TXC0 with value 6 for the UART and uses TXC with value 0 for some USB-related register. This commit reduces program size on the uno by around 120 bytes.
2014-01-16Define a _NOP() macroMatthijs Kooijman
Recent avr-libc releases define one, but this allows using it also on older avr-libc releases.
2014-01-16Simplify HardwareSerial::begin()Matthijs Kooijman
This simplifies the baud rate calculation, removing the need for a goto and shortening the code a bit. Other than that, this code should not use any different settings than before. Code was suggested by Rob Tillaart on github. Closes: #1262
2014-01-16Remove unused variableMatthijs Kooijman
2014-01-16Slightly reduce code utilization by inlining HardwareSerail begin(baud) and ↵Cristian Maglie
operator bool()
2014-01-16Remove duplicate code from HardwareSerial::begin() methods.Matthijs Kooijman
There are two begin methods, one which accepts just a baud rate and uses the default bit settings and one which accepts both a baudrate and a bit config. Previously, both of these contained a complete implementation, but now the former just calls the latter, explicitely passing the default 8N1 configuration. Technically, this causes a small change: Before the UCSRC register was untouched when calling begin(baud), now it is explicitely initialized with 8N1. However, since this is the default configuration for at least the Uno and the Mega (didn't check any others), probably for all avrs, this shouldn't effectively change anything. Given that the Arduino documentation also documents this as the default when none is passed, explicitly setting it is probably a good idea in any case.
2014-01-15Make some operators in IPAddress constMatthijs Kooijman
These functions do not modify the IPAddress object, but were not marked as const. This meant that you could not do: void set_ip(const IPAddress& ip) { uint32_t copy = ip; } Since calling operator uint32_t() on ip would discard the constness of the reference.
2014-01-09Merge pull request #1790 from cmaglie/platform-pathsCristian Maglie
Fixed "runtime.hardware.path" and "runtime.platform.path" values
2014-01-07Merge pull request #1794 from arduino/ide-1.5.x-eulerCristian Maglie
Added new EULER constant
2014-01-07Merge branch 'master' into ide-1.5.xCristian Maglie
Conflicts: build/windows/dist/drivers/arduino.cat
2014-01-06Removed = char from #define. See ↵Federico Fissore
https://github.com/arduino/Arduino/issues/1792#issuecomment-31650586
2014-01-06Added new EULER constant. Fixes #1792Federico Fissore
2014-01-05Fixed "runtime.hardware.path" and "runtime.platform.path" valuesCristian Maglie
"runtime.hardware.path" now contains the path to the hardware folder of the currently selected board and "runtime.platform.path" the path to the specific platform. This should fix #1176 and #1761.
2014-01-01Improved portability of String class (maniacbug)Cristian Maglie
2013-12-31Merge branch 'cast' of github.com:Lauszus/Arduino into Lauszus-castCristian Maglie
Conflicts: hardware/arduino/avr/cores/arduino/Print.cpp
2013-12-31Use PGM_P instead of prog_charMatthijs Kooijman
On later versions of avr-libc, prog_char is deprecated. In 0acebeeff48 the one occurence of prog_char was replaced by "char PROGMEM", which is not entirely correct (PROGMEM is supposed to be an attribute on a variable, not on a type, even though this is how things work in older libc versions). However, in 1130fede3a2 a few new occurences of prog_char are introduced, which break compilation on newer libc versions again. This commit changes all these pointer types to use the PGM_P macro from <avr/pgmspace.h>. This macro is just "const char *" in newer libc versions and "const prog_char *" in older versions, so it should always work. References #795
2013-12-30Merge pull request #1762 from matthijskooijman/ide-1.5.x-write-charCristian Maglie
Support both char* and uint8* in Stream and Print
2013-12-27Use reinterpret_cast to cast __FlashStringHelper to const char*Kristian Lauszus
2013-12-24Remove unneeded casts in Print::write(const String&)Matthijs Kooijman
Now that Print::write(const char*) is also available, these casts are no longer needed.
2013-12-24Add uint8_t* versions of methods in StreamMatthijs Kooijman
The new functions just call their char* equivalents, but this allows reading bytes into a buffer of uint8_t as well as chars.
2013-12-24Add Print::write(const char *, size_t)Matthijs Kooijman
The new function just calls Print::write(const uint8_t *, size_t), but this allows writing out a buffer of chars (without having to learn about casts).
2013-12-23Print.print optimization. Closes #1760Federico Fissore