--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+...@arduino.cc.
size_t HardwareSerial::write(uint8_t c)
{
int i = (_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE;
// If the output buffer is full, there's nothing for it other than to
// wait for the interrupt handler to empty it a bit
// ???: return 0 here instead?
while (i == _tx_buffer->tail)
;
--
You received this message because you are subscribed to the Google Groups "Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to developers+unsubscribe@arduino.cc.
Is this a virtual method in Stream that will be implemented in HardwareSerial?
Does this have broader application?
> +1 for writeBufferFree()
Ditto.
We've talked about this API many times, always with a consensus it makes sense. Recently, I've had more users request a way to avoid blocking in Serial.write(). I'm implementing it now on Teensy, and I hope someday it'll be implemented in Arduino's core library.
My hope is we can agree on the name for this function, so when/if it's ever implemented in Arduino's core library, we'll end up with the same name. Long-term, I'd like to stay as compatible with the Arduino API as possible. Yesterday I committed code with "room", but since it's only 1 day old, changing is still pretty easy.
Previously, I had preferred Serial.ready(). This forum thread swayed me to Serial.room().
http://forum.arduino.cc/index.php/topic,165574.0.html
Really, I don't care what the name end up being. Feedback I've heard from several people is a design for a longer, more descriptive name. Suggestions have included Serial.availableWrite(), Serial.writeAvailable(), Serial.readyWrite(), Serial.TxAvailable(), and other variations. Any of these names is fine. Agreeing on a name, so all boards implementing this remain compatible, seems like a good idea.
Regarding the feature itself, the last time I brought it up was item #3 on this API wish list.
https://groups.google.com/a/arduino.cc/d/msg/developers/PcOW-MCuDHc/KxLcOKLlNhoJ
There are at least 2 pending requests on the issue tracker:
https://github.com/arduino/Arduino/issues/672
https://github.com/arduino/Arduino/issues/1408
Today we have a situation where reads are non blocking and writes are blocking.
What is missing in the library is the ability to control or configure the library's behavior
from the sketch.
Or instead of a specific function to get the tx buffer information
consider adding a real i/o control interface as a single or pair of API functions
that could be used to query/set library parameters similar to the way i/o control
calls work in normal OS drivers.
So the sketch could query the library for the free room in the buffer
by simply making query call and asking for the desired parameter.
The sketch could also configure the library behavior using this interface.
This adds at most 2 API functions, but then can be infinitely expanded
to provide all kinds of information.
This keeps the API from exploding with all the "random" function names.
i.e. by adding just 2 functions, the sketch could then set or get library
specific parameters, behaviors, status, etc...
Paul posts for me on this topic. At this point there is a description of the function, and there’s an agreed-upon name. I think we’ve fulfilled what Paul was looking for when he started the topic (correct me if I’m wrong, Paul), and we can move onto other matters.
t.
On Jul 5, 2014, at 5:28 AM, Paul Stoffregen <pa...@pjrc.com> wrote:
Today we have a situation where reads are non blocking and writes are blocking.
What is missing in the library is the ability to control or configure the library's behavior
from the sketch.
This sort of symmetry and configurability, while beautiful from a pure software design perspective, I believe would be a terrible mistake for Arduino's mission to be accessible for novices.
Arduino's approach, where reading is non-blocking and writing is blocking, has proven to be very easy for ordinary people to understand. Yes, it lacks symmetry, but it has the much more important quality of simplicity for people without professional programming experience. It's a perfect example of "if it ain't broke, don't fix it".
Hell, we might as well add a callback function that gets called with the data when there is some... that could be useful instead of everyone trying to implement their own polling solutions. Would asynchronous callbacks even make sense on a platform like Arduino?
On 07/14/2014 09:02 AM, Paul Stoffregen wrote:
> The default return value is still an unresolved question.
>
> I believe it should be 1. I know Bill, Jan, Matthijs and others will
> probably disagree. Let me quickly explain my thinking...
Oh, sorry I thought you agreed on the return value too. If you need to send the pull request go ahead without the Print addition while we try to figure it out.
> But this user wants to control the motor wirelessly, so they edit the
> example from "Serial" to "myRF22", which is a communication library not
> yet implementing the new function. If the default value is some large
> number, the motor control library will suffer too much latency to
> control the motor while the communication library blocks. If the
> default is some error number, odds are good the library author only ever
> tested on Arduino Uno and never added code to check for that error. But
> if they do, what are their options? The motor still needs to be
> controlled and the status messages still need to be sent over whatever
> communication link the user needs. They're still going to need to fall
> back on some default in their code. Sending only 1 byte is the safest
> default, when you can't know. It's the most likely to allow projects to
> actually work, because if write() does block, the latency will be the
> smallest possible.
I'm trying to imagine the condition written by the user to check if the transmission blocks or not. I guess that the majority of use cases are like the following:
String position = readMotorPosition(...);
/* If write will not block then send position otherwise skip sending */
if (stream.availableForWrite() >= position.length()) {
stream.write(position);
}
Now let's suppose we want to be on the safe side and that we set the default of availableForWrite() to 1. In the example above the transmission will never happen anyway, unless the message length is exactly 1, but in this case returning 1 is not the safest possible value because it will quickly lead to blocking. I guess that to really be on the safe side we should return 0 because, since the availableForWrite is not implemented, we don't know how many bytes we can write without blocking and even 1 could block.
On the other hand, if we set the default of availableForWrite() to -1 (i.e. the maximum possible unsigned integer) we get the opposite result: the transmission will always happen and will likely block, but in this case we have the chance to check if the function is implemented, something like:
if (stream.availableForWrite() == -1) {
[...abort in some graceful way...]
}
String position = readMotorPosition(...);
/* If write will block then skip sending and retry later */
if (stream.availableForWrite() >= position.length()) {
stream.write(position);
}
Now I hardly imagine someone that implements the [...abort in some graceful way...] part (at least not me :-)), I'd better write something that skips transmission like:
String position = readMotorPosition(...);
/* If write will block then skip sending */
int avail = stream.availableForWrite();
if (avail != -1 && avail >= position.length()) {
stream.write(position);
}
that is basically equivalent to the first hypotesys (when availableForWrite returns 0).
Does this analisys sounds correct? Is there something that I'm missing?
C
I'm trying to imagine the condition written by the user to check if the transmission blocks or not. I guess that the majority of use cases are like the following:
String position = readMotorPosition(...);
/* If write will not block then send position otherwise skip sending */
if (stream.availableForWrite() >= position.length()) {
stream.write(position);
}
Now let's suppose we want to be on the safe side and that we set the default of availableForWrite() to 1. In the example above the transmission will never happen anyway, unless the message length is exactly 1, but in this case returning 1 is not the safest possible value because it will quickly lead to blocking. I guess that to really be on the safe side we should return 0 because, since the availableForWrite is not implemented, we don't know how many bytes we can write without blocking and even 1 could block.
On the other hand, if we set the default of availableForWrite() to -1 (i.e. the maximum possible unsigned integer) we get the opposite result: the transmission will always happen and will likely block, but in this case we have the chance to check if the function is implemented, something like:
if (stream.availableForWrite() == -1) {
[...abort in some graceful way...]
}
String position = readMotorPosition(...);
/* If write will block then skip sending and retry later */
if (stream.availableForWrite() >= position.length()) {
stream.write(position);
}
Now I hardly imagine someone that implements the [...abort in some graceful way...] part (at least not me :-)), I'd better write something that skips transmission like:
String position = readMotorPosition(...);
/* If write will block then skip sending */
int avail = stream.availableForWrite();
if (avail != -1 && avail >= position.length()) {
stream.write(position);
}
that is basically equivalent to the first hypotesys (when availableForWrite returns 0).
Does this analisys sounds correct? Is there something that I'm missing?
> What is your solution?
pragmatically - I would do a test with the device library. I often do just to learn if the device and the driver lib behaves as expected or has anomalies.
You received this message because you are subscribed to a topic in the Google Groups "Developers" group.
To unsubscribe from this topic, visit https://groups.google.com/a/arduino.cc/d/topic/developers/ls3hkviFYM4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to developers+...@arduino.cc.
Note, it is possible to use 0 as the default value to indicate that the "write() available" function
is not supported.
The way this could work is that the application could do call to to availableForWrite() *before* it
sends any data. If it gets 0 then it knows that availableForWrite() is not implemented and it should
not be used.
On 07/16/2014 12:27 PM, Bill Perry wrote:
Note, it is possible to use 0 as the default value to indicate that the "write() available" function
is not supported.
The way this could work is that the application could do call to to availableForWrite() *before* it
sends any data. If it gets 0 then it knows that availableForWrite() is not implemented and it should
not be used.
My current implementation on Teensy, which I'm planning to use as the model for a pull request to Arduino, does in fact return zero when the HardwareSerial transmit buffer is full. I believe this is correct behavior, if it will later return a positive integer when space becomes available in the buffer.
If that's not correct, please explain? I really want to get this right for end users.
Regarding the rest of this lengthy thread, it seems the practical result of non-consensus, at least in the short-term, is probably going to be omitting this function from the Print/Stream class definition. Perhaps this lengthy but well-intentioned argument is ultimately counterproductive? It seems to be only reducing the likelihood of defining a virtual function, with any default value!