Age | Commit message (Collapse) | Author |
|
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).
|
|
This is slightly more clear than the previous explicit comparison.
|
|
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.
|
|
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.
|
|
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
|
|
|
|
operator bool()
|
|
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.
|
|
Fixes #1568
|
|
This removes the need for doing an extra pointer dereference on every
access to the buffers, shrinking the code by around 100 bytes.
The members for these buffers must be public for now, since the
interrupt handlers also need to access them. These can later be made
private again.
Furthermore, the struct ring_buffer was removed. This allows the all
head and tail pointers to be put into the HardwareSerial struct before
the actual buffers, so the pointers all end up in the first 32 bytes of
the struct that can be accessed using a single instruction (ldd).
References: #947
|
|
Since the buffers aren't bigger than 64 bytes, these values can be
smaller. This saves a few bytes of ram, but also saves around 50 bytes
of program space, since the values can now be loaded using a single
instruction.
To prevent problems when people manually increase the buffer size, a
compile-time check is added.
Closes: #1078
|
|
See #881
|
|
Fixes #831 #881 #955 #1123 #1140
|
|
|
|
Otherwise, you get an error when compiling for processors with no serial port because the header file is always compiled.
See, for an example of the problem: https://github.com/damellis/attiny/issues/8
|
|
Before, the UMSELn1 bit was being to set to 1, putting the UART into a reserved mode. Now, we only set the high (0x80) bit to 1 for the ATmega8, which is needed to access UCSRnC (whose i/o address is shared with UBRRH).
Also, no longer bitwise-or the new config with the existing register value, because we're actually configuring all the settings in the register. (We're not using UCPOL, but it's supposed to be 0 in asynchronous mode.)
|
|
Serial.begin() parameter to set data bits, parity, stop bits.
|
|
http://code.google.com/p/arduino/issues/detail?id=871
|
|
New Serial.begin(baud, config);
|
|
New Serial.begin(baud, config);
|
|
Adding advanced begin (); with the ability to specify the length of bits, parity, stop bits.
|
|
Adding advanced begin (); with the ability to specify the length of bits, parity, stop bits.
|
|
Adding advanced begin (); with the ability to specify the length of bits, parity, stop bits.
|
|
is ready to send data.
Mostly useful for Leonardo - simple way to test whether the port is actually opened by an application and ready to receive data. For Serial objects attached to real UARTs always returns true.
|
|
http://code.google.com/p/arduino/issues/detail?id=776
|
|
|
|
new-extension
Conflicts:
build/linux/dist/tools/avrdude.conf
|
|
http://code.google.com/p/arduino/issues/detail?id=626
|
|
arduino protocol for Leonardo avrdude upload.
|
|
new-extension
Conflicts:
build/macosx/dist/tools-universal.zip
build/windows/avr_tools.zip
hardware/arduino/cores/arduino/HardwareSerial.cpp
|
|
http://code.google.com/p/arduino/issues/detail?id=584
|
|
|
|
write(), print(), println() now return size_t (and don't use negative values to signal errors).
Print adds writeError() for checking for write errors, clearWriteError() to reset the flag to false, and a protected setWriteError() for signalling errors.
http://code.google.com/p/arduino/issues/detail?id=598
|
|
|
|
The type is long, and negative values indicate errors. Needs more testing.
http://code.google.com/p/arduino/issues/detail?id=551
|
|
|
|
|
|
Because UBBR is only 12 bits, we were overflowing it at 300 baud because of the use of the U2X bit. Now we turn off U2X if it would yield a UBBR value that would overflow.
Note that this breaks 300 baud communication with the computer on the Uno and Mega 2560 because the 8U2 USB-serial firmware has this same bug (and previously they cancelled each other out). Since, however, it seems more likely that people will need to use 300 baud to communicate with other (legacy) hardware than with the computer, I'm making this change. Issue for 8U2 firmware bug: http://code.google.com/p/arduino/issues/detail?id=542
http://code.google.com/p/arduino/issues/detail?id=522
|
|
begin(long) -> begin(unsigned long)
Conflicts:
hardware/arduino/cores/arduino/HardwareSerial.h
|
|
Called from within the serial receive interrupt. These are implemented as an empty weak function in the core that be overridden by the user's sketch.
http://code.google.com/p/arduino/issues/detail?id=263
|
|
|
|
This brings it in line with most other uses of flush(), both in and out of Arduino.
http://code.google.com/p/arduino/issues/detail?id=497
|
|
That is, waiting for outgoing data to transmit and dropping any received data.
|
|
|
|
Now Serial.write() places characters in the transmit buffer, and the data register empty interrupt reads and transmit them. Based loosely on the implementation here: ftp://wookey.org.uk/arduino.
http://code.google.com/p/arduino/issues/detail?id=262
|
|
|
|
http://code.google.com/p/arduino/issues/detail?id=391
|
|
57600 baud at 16 MHz.
http://code.google.com/p/arduino/issues/detail?id=394
|
|
Mark Sproul's patches, via Christian Maglie.
http://code.google.com/p/arduino/issues/detail?id=315
|
|
|