-
Notifications
You must be signed in to change notification settings - Fork 59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a tx only and a rx only serial instance #34
Conversation
e5ca471
to
bd3478f
Compare
I have some thoughts on this, will put together an actual review in a bit, kinda busy atm |
let rxpin = (); | ||
let mut serial = Serial { usart, pins: (txpin, rxpin) }; | ||
serial.enable(baud_rate, clocks); | ||
serial |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not have the Tx only constructor just return a Tx<USART>
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to enable listen
and potential future things for Rx/Tx only usarts. Returning a Tx
would also make release
pretty hard to do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To be fair currently if you split()
an interface you already lose the ability to release
, so maybe Tx
and Rx
need to keep hold of their pins and implement release
each. Also I could see claim for being able to call listen/unlisten on Tx
and Rx
instances, or even just make the listening methods on some global type, given they are atomic and not bound to a given object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's why stm32-rs/stm32f4xx-hal#49 was done. As a side effect, this is also accomplished by this pull request (an separate object sounds really annoying)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see how that fixes split usarts from being unable to release their pins?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose I tend to see splitting usarts as a useful and important feature as it allows them to be partially shared into interrupt handlers in a sensible way without lock contention.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@HarkonenBade I'm not quite sure about the usefulness of splitting, to me that is mostly a historical thing rather than a practicality. It would make most sense if Rx and Tx were mostly used independently but I really haven't seen that being used anywhere in the wild. In fact I often have to share Rx/Tx together with my interrupt handlers to make use of them (unless I only need one of them).
Maybe it would make sense to actually implement the serial traits directly on the serial port handle to allow direct use of a bi- or unidirectional serial channel with release capability but also keep the possibility to split in case a serial port is meant to be used in two separate places. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds reasonable to me, also I'm unsure over the use of generating temporary Tx/Rx instances to impl the Read/Write traits, it would seem more appropriate to move the implementations out to free functions that take a *const USART argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved it out in separate functions with RegisterBlock, I could remove the USART parameter from Tx
& Rx
type, not sure if I should.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd leave it there, its potentially relevant to distinguish Tx and Rx objects from different USART types.
let txpin = (); | ||
let mut serial = Serial { usart, pins: (txpin, rxpin) }; | ||
serial.enable(baud_rate, clocks); | ||
serial |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above but for Rx
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there are a few bits that might need thinking about further.
4edc669
to
8a00351
Compare
6d7d30a
to
ec1fa41
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've taken another look over and everything LGTM 👍
src/serial.rs
Outdated
} | ||
} | ||
|
||
/// Tries to write a byte to the uart |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Tries to write a byte to the uart | |
/// Tries to write a byte to the UART |
src/serial.rs
Outdated
} | ||
} | ||
|
||
/// Tries to read a byte from the uart |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// Tries to read a byte from the uart | |
/// Tries to read a byte from the UART |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be great if we could get a doc example for unidirectional use. Otherwise LGTM.
Actually, would it also be worth updating at least one of the examples that doesn't really need split under this? Maybe the plain echo? |
I haven't looked in detail but is this even a possibility, i.e. does the implementation allow for multiple independent uses of the chosen Anyway, I'd be okay with modifying the examples or adding another, like a plain hello world, but I strongly favour better documentation over examples. |
@therealprof It doesn't let you define multiple usarts with the same pins, but the way the impls of read and write for usarts are worded also implements them for duplex usarts. So a full duplex usart can have both read and write called on it, and thus doesn't require splits if you don't need to send the parts to different places. |
@HarkonenBade Sorry, I misunderstood you then. Sure, go ahead. |
Though this has raised an interesting question for me, could we shift it so that It would mean that we would need to be more careful in future if we offer any ability to re-configure the peripheral at runtime. |
I think this would make a destructor pretty hard. It also has issues with the listen/unlisten calls (the classic race condition thing). I also don't like two serials of the same port existing, for me it looks like a hack (because it is). |
That's fair, it was just a thought based on the pleasing way the read/write impls turned out. |
Also add the `Write` implementation for Serial
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
This also makes the serial stuff in #27 obsolete.
Additionally by virtue of how it works also implements stm32-rs/stm32f4xx-hal#49 here.
Not sure how we should handle the release method. It currently works but you get a
()
for the unused pin back.Currently untested