<JamesMunns[m]>
JamesMunns[m]: The answer is "not yet, mostly only because James hasn't needed it yet"
<i509vcb[m]>
Okay, I was thinking about a generic IO expander firmware library that I would use for both the AP to use an MCU as an io expander and for an MCU to use another MCU as an io expander
<JamesMunns[m]>
Yup, definitely interested in that kind of ability, but I haven't written it yet. Feel free to add any notes to that issue! As I've mentioned, I think if you only need simple endpoint control, it should be very straightfoward. Handling topic RX and multiple-in-flight-endpoints is a harder challenge.
<thejpster[m]>
reminder again: defmt-1.0 is coming.
<thejpster[m]>
I have written up some notes on how I plan to proceed at https://github.com/knurling-rs/defmt/discussions/888. If I get it wrong, I'll split the ecosystem and everyone will be really cross (because defmt is a crate where you **can only have** a single versions in your dependency tree, due to extern symbol shenanigans).
<thejpster[m]>
Thoughts and input welcome.
<danielb[m]>
> If I get it wrong, I'll split the ecosystem and everyone will be really cross
<danielb[m]>
Aim for a beta release first, then :)
<thejpster[m]>
Assuming the plan of "just ship 0.3.9 as 1.0 and ship 0.3.10 as 1.0 wearing a hat with 'I am 0.3' written on it" then I should be able to get this out before new year.
<thejpster[m]>
beta releases of semver-hacks are almost impossible from what I can see
<thejpster[m]>
1.0 by itself will sit there and be ignored. It's the 0.3.10 that imports and re-exports 1.0 that will force everyone to upgrade.
<thejpster[m]>
* Assuming the plan of "just ship 1.0 as a copy of 0.3.9, and ship 0.3.10 as 1.0 wearing a hat with 'I am 0.3' written on it" then I should be able to get this out before new year.
adamgreig[m] has joined #rust-embedded
<adamgreig[m]>
Hi @room ! It's meeting time again but I'm unexpectedly not able to run, the agenda is on gh discussion and I didn't have any announcements from my end
<jannic[m]>
I mentioned https://github.com/rust-embedded/embedded-hal/issues/577 because it's a ticket that seems valid and didn't get much attention. It's about how UART specific error codes could be returned using embedded-io / embedded-io-async. But I don't have much to tell about it. Anyone interested in that topic?
<bartmassey[m]>
I think the plan of adding new ErrorKinds and letting old drivers take care of themselves is probably the best way forward.
<bartmassey[m]>
I feel like the "9-bit serial" plan is best served by a separate trait set and/or drivers, since it's so far outside the norm for serial. Maybe not, but it seems weird to be looking at parity errors explicitly in the caller to decode a symbol.
<jannic[m]>
Sure. I think 9 bit serial was only mentioned because it's sometimes possible to receive 9bit data using an UART that can only do 8 bit my misusing parity.
<dirbaio[m]>
9 bit serial was discussed when embedded-io was introduced, the decision was it's OK to not support it since it's quite rare
<dirbaio[m]>
and the advantage of having standard "byte stream" traits applicable to more than that (e.g. tcp conns) was worth it
<dirbaio[m]>
imo they should be separate traits
<bartmassey[m]>
(10-bit serial by using two stop bits and looking for framing errors 😀)
<jannic[m]>
I agree. UART is quite generic, so there will always be things that you can do with a UART peripheral that's not possible using the traits.
<jannic[m]>
But more fine-grained error reporting would be easy to add and I don't see serious disadvantages.
<dirbaio[m]>
about parity/framing/etc: is there a situation where a generic driver cares about them?
<dirbaio[m]>
(other than the cursed 9bit thing)
<dirbaio[m]>
ie is there some situation where a driver might want to ask "is this a parity error, or a framing error?" and do different things based on that?
<dirbaio[m]>
I think drivers just care about "I rx'd some garbage, let's just try to recover"
<bartmassey[m]>
I think autobauding maybe?
<dirbaio[m]>
how would you autobaud if we don't have a "set baudrate" trait? :D
<jannic[m]>
I'd leave that question for people with more practical experience with actual real-world devices.
cinemaSundays has joined #rust-embedded
<bartmassey[m]>
dirbaio: Fair enough :grinning:. Why do we not have a way to set baud rate?
<dirbaio[m]>
lol
<bartmassey[m]>
s/:grinning:./😀./
<dirbaio[m]>
maybe we should, but that's a whole other conversation
<bartmassey[m]>
True that
<bartmassey[m]>
Anyway, off to do class prep and head for class. Talk to everybody next week! 👋
<dirbaio[m]>
so I dunno, we can add them as error variants to e-io but i'm not sure if the use cases are very compelling
<dirbaio[m]>
can you even detect parity/framing/etc errors on a linux serial port?
<rmsyn[m]>
is the e-io stuff for host-side in Linux/OS?
<dirbaio[m]>
it's supposed to be implementable everywhere that has a serial port
<jannic[m]>
If we had a way to signal Break, I guess it would be fine to leave framing+parity as part of the Other kind for most use cases.
<dirbaio[m]>
on a bare-metal mcu with a hardware uart, or on a linux pc with either an uart in the mobo or an usb-to-uart converter...
<rmsyn[m]>
the low-level registers on the UART controller of a board I'm working on have a number of ways for error detection
<dirbaio[m]>
and what's the contract? does the byte that failed parity/framing still get returned, or not? is the info of which byte failed parity/framing available or is it just "meh some byte failed, dunno whicH"?
<dirbaio[m]>
s/which/_which_/, s/whicH/which/
<rmsyn[m]>
not saying we should cover all of them, but maybe some of them common to a number of controllers?
<dirbaio[m]>
rmsyn[m]: I was thinking more about the linux TTY subsystem, where you let the kernel handle everything for you.
<rmsyn[m]>
dirbaio[m]: I'm a fan of returning the bad value in the error, yes
<dirbaio[m]>
* for you. (of course if you poke registers directly you can get all the info out)
<dirbaio[m]>
many uarts can't do that
<dirbaio[m]>
nrf's uart just has a "lol some parity error happened somewhere"bit
<dirbaio[m]>
* happened somewhere" bit
<dirbaio[m]>
* for example nrf's uart, * happened somewhere" bit
<rmsyn[m]>
dirbaio[m]: right, but then the kernel could use one of the higher-level variants
<rmsyn[m]>
dirbaio[m]: right, but then the offending byte could be returned
<jannic[m]>
https://www.man7.org/linux/man-pages/man3/termios.3.html "PARMRK: If this bit is set, input bytes with parity or framing errors are marked when passed to the program. [...] The way erroneous bytes are marked is with two preceding bytes, \377 and \0."
<dirbaio[m]>
you don't know which byte is the offending byte
<jannic[m]>
And (with the correct settings), break is signalled as \377 \0 \0. So you can't distinguish between a 0 byte with some error, and a break.
<jannic[m]>
I guess there are about 2 1/2 alternative ways to configure a linux serial port and get these values in some other, similarly cursed way.
<dirbaio[m]>
lol
<dirbaio[m]>
well that kinda makes sense, a break is kinda a zero byte with broken framing...? 😅
<jannic[m]>
Indeed :-)
<jannic[m]>
Well, back to topic, even if we define separate error codes: Drivers can always just return Other if they are unable to properly support these error codes.
<dirbaio[m]>
but then a driver depending on it won't work
<rmsyn[m]>
how so?
<jannic[m]>
Yes, but that would be on hardware where the driver can't work at all.
<jannic[m]>
Of course, it's not perfect from a type safety point of view.
<dirbaio[m]>
if the driver needs the hal to report breaks because the protocol requires, and the hal doesn't (or reports them as Other)
<dirbaio[m]>
it'll compile, but it won't work at runtime
<dirbaio[m]>
and you'd be able to do nonsense things like passing a TCP socket to your DMX driver:P
<dirbaio[m]>
* DMX driver :P
<rmsyn[m]>
ah, wouldn't that be something for driver authors to take up with individual HAL authors, though?
<jannic[m]>
We could define a separate `trait UartError: embedded_io::Error + Debug { fn is_break() -> bool } ` or similar.
<rmsyn[m]>
like, "hey, I noticed your hardware supports XYZ error-handling scenario, but you nope out with ErrorKind::Other. please support ErrorKind::XYZ"
<dirbaio[m]>
jannic[m]: hmm so drivers do `where T: Uart<Error: UartError>`
<dirbaio[m]>
that prevents the user from doing nonsense things like passing a TCP socket
<dirbaio[m]>
and by implementing the trait, the HAL would be declaring it supports reporting breaks etc properly
<dirbaio[m]>
s/Uart/embedded_io::Read/
<dirbaio[m]>
could work!
<jannic[m]>
Could also contain functions like `fn data() -> Option<u8>` to retrieve the (potentially broken) byte that had a parity error, if the driver supports that.
<dirbaio[m]>
i'm not a fan of "if the driver supports it" options, that's exactly what causes things to not work at runtime.
<dirbaio[m]>
it should either be mandatory or not there at all
<jannic[m]>
But then we might end up with several different UartError types depending on hardware features.
<dirbaio[m]>
that might be okay
<dirbaio[m]>
dunno
<jannic[m]>
The good thing is we wouldn't need a separate trait for every combination, because a driver could depend on UartError + ReportsDataError + ....
<dirbaio[m]>
the thing is, embedded-hal's goal is to allow writing drivers that work on any hal
<jannic[m]>
Right. Once your driver becomes hardware specific, there's no need to use the embedded-hal traits.
<dirbaio[m]>
so we shouldn't exposes something just because some hardware out there can do it
<dirbaio[m]>
s/exposes/expose/
<dirbaio[m]>
we should expose something when there's some driver that needs it
<jannic[m]>
And I like to have at least one (and preferably multiple) actual users before defining an API.
<dirbaio[m]>
for example a "DMX receiver driver" is something that makes a lot of sense that you'd want to write HAL-independent, and needs detecting uart breaks
<jannic[m]>
DMX sounds very reasonable. So support for Break is obviously useful.
<dirbaio[m]>
but detecting parity/framing etc seems less obvious to me
<dirbaio[m]>
and detecting on which byte which parity/framing error occured even less obvious
<dirbaio[m]>
(other than the abuse to do 9bit uart but imo if we wanted to support that it'd make more sense to make a real "9bit uart" trait)
<jannic[m]>
On the other hand it's very common for UART implementations to report these as separate kinds of errors. But yes, it doesn't pass the "actual use case" test yet. Ignoring the 9bit example that feels more like a hack than an actual use case.
<dirbaio[m]>
yep
<jannic[m]>
I wouldn't call an error type that only adds break support "UartError" though. So we can still bikeshed a better name.
<jannic[m]>
Anyway, we don't need to decide that today, and maybe more people have opinions. I'll summarize the discussion in the ticket.
<dirbaio[m]>
yeah if it's just break maybe `trait BreakError { fn is_break(&self) -> bool; }` makes more sense
<jannic[m]>
Looks like everyone is asleep by now. Was the io error discussion so boring?
<rmsyn[m]>
regarding CI, we could also use the Alpine setup on top of Ubuntu for emulation
<rmsyn[m]>
instead of qemu
M9names[m] has joined #rust-embedded
<M9names[m]>
What is that?
<M9names[m]>
> the alpine setup
<rmsyn[m]>
is qemu-system the new equivalent package on ubuntu 24.04?
apirkle has joined #rust-embedded
<M9names[m]>
No, we're using `qemu-system-arm` and the package for that is called `qemu-system-arm`.
<M9names[m]>
We were already installing that, plus the removed package `qemu` that we weren't using.
<M9names[m]>
Can you please clarify what "the alpine setup" is? It's going to be very hard for the group to consider an option that only exists in your head
<thejpster[m]>
Sorry I missed the meeting. I see defmt didn’t come up but hopefully you all saw the note.
cinemaSundays has quit [Quit: Connection closed for inactivity]
<thejpster[m]>
Also, Ferrocene 24.11 is out today. Adds Medical qualification, support for QNX Neutrino and experimental support for developing on Arm Linux (because Graviton goes brrrr). Still only €25/month.
<thejpster[m]>
Given we shipped 24.05, 24.08 and 24.11 I guess you might expect me back again posting about it in February. I couldn’t say at this point.