ChanServ changed the topic of #rust-embedded to: Welcome to the Rust Embedded IRC channel! Bridged to #rust-embedded:matrix.org and logged at https://libera.irclog.whitequark.org/rust-embedded, code of conduct at https://www.rust-lang.org/conduct.html
dc740 has quit [Remote host closed the connection]
IlPalazzo-ojiisa has quit [Remote host closed the connection]
lehmrob has quit [Ping timeout: 246 seconds]
lehmrob has joined #rust-embedded
starblue has quit [Ping timeout: 252 seconds]
rardiol has quit [Ping timeout: 265 seconds]
starblue has joined #rust-embedded
bjc has quit [Ping timeout: 268 seconds]
starblue has quit [Ping timeout: 276 seconds]
starblue has joined #rust-embedded
cr1901 has quit [Read error: Connection reset by peer]
cr1901 has joined #rust-embedded
starblue has quit [Ping timeout: 268 seconds]
starblue has joined #rust-embedded
starblue has quit [Ping timeout: 250 seconds]
starblue has joined #rust-embedded
bjc has joined #rust-embedded
starblue has quit [Ping timeout: 252 seconds]
starblue has joined #rust-embedded
rardiol has joined #rust-embedded
IlPalazzo-ojiisa has joined #rust-embedded
starblue has quit [Ping timeout: 264 seconds]
starblue has joined #rust-embedded
<re_irc> <@anondev13:matrix.org> Good morning everyone, I'm trying to interface with an AS7331 UV A/B/C sensor over I2C, but am I running into issues using the provided arduino example and converting it to rust. I'm just trying to set up the initial conversation with the device, but when I try and read the device ID I get the wrong value. I've created a snippet with my code and some working arduino code. Can someone help me understand what is happening?...
<re_irc> ... Thank you!!
<re_irc> <@peter9477:matrix.org> anondev13: So it looks like the Rust version gets a result that's bit-shifted once to the left, is that right?
<re_irc> <@peter9477:matrix.org> Are there any other devices on that bus?
<re_irc> <@anondev13:matrix.org> : No, just the AS7331.
<re_irc> <@peter9477:matrix.org> Nothing major is jumping out yet, but I'd try it at 100kHz before trying 400. There are parts that can't do 400, and if it's talking to you and trying its best but the result can come in looking bit-shifted once, I could see that possibly stemming from it not handling the faster clock.
<re_irc> <@peter9477:matrix.org> I take it the result is consistent, if you try it multiple times.
<re_irc> <@peter9477:matrix.org> Also, is it different hardware talking to it, or the same board but just swapping out Arduino for Rust? If different, could there be differences in the external pullups or other parts of the circuit?
<re_irc> <@anondev13:matrix.org> I'll give 100kHz a try, it runs at 400kHz on arduino, but I'll try. Results are consistent. Same hardware just swapping running code.
<re_irc> <@peter9477:matrix.org> Datasheet says it should handle 400 fine...
<re_irc> <@peter9477:matrix.org> Time for a digital scope...
<re_irc> <@ryan-summers:matrix.org> As an aside, have you confirmed which output is actually correct by referring to the AS7331 datasheet?
<re_irc> <@anondev13:matrix.org> The arduino output is correct, I can run the whole arduino example and read results from the sensor.
<re_irc> <@ryan-summers:matrix.org> That's not what I'm asking though. When you check the actual register values, do they look as what you'd expect them to from the datasheet?
<re_irc> <@ryan-summers:matrix.org> You can have a fully functional firmware that runs with one broken assumption for some reason
<re_irc> <@ryan-summers:matrix.org> * reason, as long as that one broken thing is consistent
<re_irc> <@ryan-summers:matrix.org> Other than that, I wouldn't be surprised if the I2C driver had an off-by-one issue in the Rust HAL. I've fixed many various I2C defects in HALs
<re_irc> <@ryan-summers:matrix.org> Not sure how well maintained the esp32c3 hal is
<re_irc> <@anondev13:matrix.org> Sorry, yes, from what I can tell, the arduino outputs are correct when comparing with the expected values from the datasheet.
<re_irc> <@peter9477:matrix.org> anondev13: That register address selects something different if the chip isn't in the configuration state. Any chance that 0x42 is actually an MRES1 result, from the chip being in the measurement state?
<re_irc> <@peter9477:matrix.org> A trick I've used a lot in the past: start at register 0 and read all the registers in one fell swoop, and print them out. Often that has let me identify a problem stemming from something like a misconfiguration.
<re_irc> <@peter9477:matrix.org> like it may not be that read that's failing, but an earlier write...
<re_irc> <@peter9477:matrix.org> Like, isn't line 88 actually turning on the POWER_DOWN bit? And then with no delay, it's clearing that bit and simultaneously setting the Software Reset bit. Not sure what that might do.
<re_irc> <@peter9477:matrix.org> and leaving DOS set the same as it was, rather than forcing it to 0b010 to ensure the configuration state...
<re_irc> <@peter9477:matrix.org> (oh... software reset puts it back to the configuration state apparently? But reading all regs would at least confirm the state as you try reading the AREG.)
<re_irc> <@peter9477:matrix.org> Stray comment: those other reads are getting 0x42 from the address 0 register, which appears a reasonable value (per Figure 46), and just happens to match what you appear to be reading from address 2 at the end. That may hint that the final read is somehow repeating register 0, or somehow not working at all..
<re_irc> <@peter9477:matrix.org> Hmm.... Figure 41 sort of looks like you actually can't read from any register except AGEN? If that's actually true, the code is based on a wrong assumption, that you can read any register and modify bits and write it back...
<re_irc> <@peter9477:matrix.org> it suggests the only time you can read any other register including OSR is when in the measurement mode, not in configuration mode.
<re_irc> <@peter9477:matrix.org> If true, the apparent success with the Arduino code may be a fluke.
starblue has quit [Ping timeout: 264 seconds]
starblue has joined #rust-embedded
<re_irc> <@eldruin:matrix.org> I would plug in the logic analyzer / scope. Failing that, I would try with a different MCU. For example an nrf52, an stm32f103 among many others are pretty battle-tested.
<re_irc> <@eldruin:matrix.org> +(aside from the potential logic problems highlighted above.)
emerent has quit [Ping timeout: 248 seconds]
emerent has joined #rust-embedded
starblue has quit [Ping timeout: 265 seconds]
starblue has joined #rust-embedded
starblue has quit [Ping timeout: 256 seconds]
<re_irc> <@anondev13:matrix.org> I switched to a nrf52833 chip and can immediately read the correct device id. Need to test other functionality still, but thanks for the help all!
starblue has joined #rust-embedded
<re_irc> <@adamgreig:matrix.org> @room good evening, meeting time again! agenda is https://hackmd.io/snlj9FIwS9yC8sBdQDgdyw, please add anything you'd like to announce or discuss and we'll start in 5 min :)
<re_irc> <@adamgreig:matrix.org> ok, let's start! first off, welcome romancardenas to the wg and risc-v team πŸŽ‰
<re_irc> <@adamgreig:matrix.org> you should have invites to the relevant github teams etc but just shout if anything doesn't look right
<re_irc> <@adamgreig:matrix.org> that's all the announcements from me this week, anyone else have anything?
<re_irc> <@CyReVolt:matrix.org> woop woop, RISC-V \o/
<re_irc> <@romancardenas:matrix.org> Thanks for inviting me!
<re_irc> <@dirbaio:matrix.org> I have one. stm32-metapac v1.0.0 released on crates.io :)-
<re_irc> <@dirbaio:matrix.org> * :)
<re_irc> <@adamgreig:matrix.org> now it just needs a readme :P
<re_irc> <@dkhayes117:matrix.org> romancardenas: You're welcome 😊
<re_irc> <@dirbaio:matrix.org> pfft, readmes
<re_irc> <@firefrommoonlight:matrix.org> Hi! My PFA is getting H5 on Stm32-RS. I am having a struggle with build dependencies
<re_irc> <@firefrommoonlight:matrix.org> https://github.com/stm32-rs/stm32-rs/pull/811
<re_irc> <@k900:0upti.me> Somewhat random question: do we have any Slint people here?
<re_irc> <@dirbaio:matrix.org> i'm working on stm32-metapac H5 as we speak btw :)
<re_irc> <@k900:0upti.me> I need forbidden knowledge to commit more crimes
<re_irc> <@adamgreig:matrix.org> thanks , I'll have a look and try and get you unstuck
<re_irc> <@firefrommoonlight:matrix.org> Thx!
<re_irc> <@k900:0upti.me> (and yes this is embedded related, or I guess more Slint platform abstraction related)
<re_irc> <@adamgreig:matrix.org> just briefly then, if anyone has used the unstable Allocator APIs and has an opinion on https://github.com/rust-embedded/embedded-alloc/pull/61 I'd love feedback, otherwise we can get that merged soon I think
<re_irc> <@adamgreig:matrix.org> the discussion about svd2rust unsafe access has been ongoing at https://github.com/rust-embedded/svd2rust/issues/714 if anyone's not following that, but I don't think anything new to talk through today
<re_irc> <@k900:0upti.me> Also, in case someone is interested in highly experimental crimes, https://gitlab.com/K900/bootloader has Slint running somewhat acceptably on bare UEFI
<re_irc> <@k900:0upti.me> Is UEFI considered embedded? Is it not? Fuck if I know
<re_irc> <@adamgreig:matrix.org> I think... it could be? depends what it was running on i guess :P
<re_irc> <@adamgreig:matrix.org> it's defo bare metal...
<re_irc> <@k900:0upti.me> It's been tested on a total of two fairly reasonable x86 machines and also QEMU and so far nothing broke but I don't expect this to last
<re_irc> <@adamgreig:matrix.org> how're you liking slint?
<re_irc> <@k900:0upti.me> It's not bad
<re_irc> <@k900:0upti.me> Very QMLy
<re_irc> <@k900:0upti.me> I like QML so I also like Slint
<re_irc> <@k900:0upti.me> The platform abstraction is weird in a few places which is the parts I wanted to ask about
<re_irc> <@k900:0upti.me> It's actually pretty small (which is good) but the API has some ... unconventional decisions
<re_irc> <@adamgreig:matrix.org> ( , if you wanted a quick reference during the meeting, https://github.com/stm32-rs/stm32-rs/pull/765 added support for c0 so should show you all the places that need touching)
<re_irc> <@k900:0upti.me> Like representing key events with a character, and representing special keys with a _reserved_ character
<re_irc> <@k900:0upti.me> And that leaks all the way to the scripting layer and ooofffff
<re_irc> <@adamgreig:matrix.org> spicy
<re_irc> <@adamgreig:matrix.org> who needs enums
<re_irc> <@k900:0upti.me> Well the Slint language itself doesn't seem to _have_ enums per se
<re_irc> <@adamgreig:matrix.org> there's been some discussion in bxcan (an stm32 hal driver) about handling priority inversion etc (https://github.com/stm32-rs/bxcan/issues/57) which has led to some questions about the embedded-can trait in https://github.com/rust-embedded/embedded-hal/issues/447
<re_irc> <@k900:0upti.me> And I get the idea of wanting to allow just arbitrary characters for weirdly shaped inputs
<re_irc> <@firefrommoonlight:matrix.org> : Thx!
<re_irc> <@adamgreig:matrix.org> I guess most people here with an interest in CAN may have already been flagged up by it but worth checking out if not
<re_irc> <@k900:0upti.me> But that also implies your code needs to actually _handle_ those characters which I'm less sold on
<re_irc> <@k900:0upti.me> And there's a couple more odd things like coordinates being u32
<re_irc> <@k900:0upti.me> Even though there doesn't seem to be any reason to _not_ have them be usize
<re_irc> <@k900:0upti.me> Will I ever have an INT_MAX*INT_MAX display? Probably not, but having to cast coordinates back and forth between UEFI and Slint gets kinda annoying
<re_irc> <@k900:0upti.me> And I'm not sure about other platforms but Wayland is definitely usize
<re_irc> <@thejpster:matrix.org> I had dinner with the slint team at Embedded World, and did my QNX demo with it. I like it.
<re_irc> <@firefrommoonlight:matrix.org> : It looks like in addition to CI, the breaking thing was missing "stm32_part_table.yaml"
<re_irc> <@k900:0upti.me> Also, like, don't get me wrong, having a somewhat reasonable GUI framework _in my bootloader_ is exceptionally cool even despite all the papercuts
<re_irc> <@firefrommoonlight:matrix.org> FYSA I am working on CAN stuff using the "fdcan" crate
<re_irc> <@adamgreig:matrix.org> : did you get a chance to sort out AWS access btw?
<re_irc> <@thejpster:matrix.org> Also, I did an interview where I had to define Embedded Rust. I basically said β€œno-std”.
<re_irc> <@nastevens:matrix.org> : Sorry, not yet
<re_irc> <@thejpster:matrix.org> Also I spoke to two new chip vendors about Rust support (not including Infineon and Espressif). So that’s exciting.
<re_irc> <@adamgreig:matrix.org> nice, hopefully they can also join in with discussions and design!
<re_irc> <@adamgreig:matrix.org> OK, all I had left on the agenda for today is the remaining open embedded-hal PRs, did you want to discuss any here ?
<re_irc> <@dirbaio:matrix.org> yea
<re_irc> <@dirbaio:matrix.org> first is serial Read: https://github.com/rust-embedded/embedded-hal/pull/349
<re_irc> <@dirbaio:matrix.org> rehashing the previous discussions:
<re_irc> - UART impls might be buffered or unbuffered. Unbuffered uses less resources but is harder to use becuase it loses bytes when you're not actively reading.
<re_irc> - This PR adds traits for unbuffered UART read.
<re_irc> - For buffered, I think it'd make more sense to direct users towards "embedded-io"
<re_irc> <@dirbaio:matrix.org> so yes, these traits are not useful in all situations, but they can be in some (like, packet-level comms where you control the timing)
<re_irc> <@dirbaio:matrix.org> so I think this is the solution that makes most sense
<re_irc> <@dirbaio:matrix.org> ping
<re_irc> <@dirbaio:matrix.org> have you guys had time to look through it?
<re_irc> <@adamgreig:matrix.org> so we'd say for buffered uart just ignore embedded-hal? what if you're a generic driver for something that talks over uart - a gps receiver or something - and you don't especially care but you need to be given something?
<re_irc> <@dirbaio:matrix.org> depends on how you use the UART
<re_irc> <@adamgreig:matrix.org> in that case I guess you'd ideally want to work with a uart on std too, where you wouldn't needed embedded-io since you have regular io
<re_irc> <@dirbaio:matrix.org> if the driver needs buffered comms, it'd take "embedded_io::Write + embedded_io::Read"
<re_irc> <@jannic:matrix.org> And embedded-io is nightly only, right?
<re_irc> <@adamgreig:matrix.org> how so? if unbuffered is OK then probably so is buffered?
<re_irc> <@dirbaio:matrix.org> if you take "embedded_io::Read", there's the expectation that the stream doesn't lose bytes when you're not actively reading
<re_irc> <@dirbaio:matrix.org> (up to some reasonable buffer size, ofc, say 4k)
<re_irc> <@dirbaio:matrix.org> when writing a driver for an AT command-based modem, for example, you pretty much need that
<re_irc> <@dirbaio:matrix.org> you can receive data at any time, and you can do parsing that takes a long time, during which you're not actively waiting on a ".read()" call
<re_irc> <@dirbaio:matrix.org> : only async. blocking is stable
<re_irc> <@dirbaio:matrix.org> so, for AT command stuff you'd want a buffered impl
<re_irc> <@adamgreig:matrix.org> what drivers wouldn't want buffered?
<re_irc> <@adamgreig:matrix.org> like I get that some could be designed to not require it, but it seems like those could just read the buffer often
<re_irc> <@dirbaio:matrix.org> for some packet-level comms where you know all bytes come with no gaps, and there's minimum X time between packets, you could use unbuffered "ReadUntilIdle"
<re_irc> <@thejpster:matrix.org> Who decides how big the buffer is?
<re_irc> <@adamgreig:matrix.org> in some sense it feels like the tradeoff (having to use a buffer) is something the user should pick, rather than the driver
<re_irc> <@adamgreig:matrix.org> like, all the UARTs are buffered in that they have a single-word buffer, and if you read it more often than baudrate/10 (which is often pretty slow) you don't lose anything
<re_irc> <@dirbaio:matrix.org> : the impl. The expectation for embedded-io impls is that the buffer is "big enough", if it's not then it's the user fault for misconfiguring it
<re_irc> <@jannic:matrix.org> And what about hardware buffers in the UART peripheral?
<re_irc> <@adamgreig:matrix.org> so specifically saying "Data that arrives when your code is not running a "read_*()" call *is lost*." seems a bit overly harsh?
<re_irc> <@thejpster:matrix.org> Pretty sure arduino gets away without a buffer, and a basic byte at a time API.
<re_irc> <@adamgreig:matrix.org> I feel like the question is just how big the buffer is and therefore how often you have to poll it, but it's never 0
<re_irc> <@adamgreig:matrix.org> (just it's very often 1)
<re_irc> <@dirbaio:matrix.org> buffered traits (embedded-io): the buffer is "big enough"
<re_irc> unbuffered traits: no expectations. there MIGHT be a buffer, but drivers should still work with no buffer, or with a ridiculously tiny buffer (1-4 bytes)
<re_irc> <@dirbaio:matrix.org> * (like the 1-4 bytes hw fifo)
<re_irc> <@adamgreig:matrix.org> arduino is buffered, they use a 64 byte ram buffer for incoming data iirc
<re_irc> <@thejpster:matrix.org> ORLY?
<re_irc> - to allow writing drivers that require buffering
<re_irc> <@dirbaio:matrix.org> we need separate sets of traits
<re_irc> <@dirbaio:matrix.org> +- because the API is different
<re_irc> <@dirbaio:matrix.org> we don't want someone to instantiate an AT driver that expects a buffered uart with an un buffered uart.
<re_irc> <@dirbaio:matrix.org> * uffered
<re_irc> <@dirbaio:matrix.org> * unbuffered
<re_irc> <@adamgreig:matrix.org> it still feels like a difference only in degree
<re_irc> <@jannic:matrix.org> Remembering the magic moment when I replaced the 16450 on my serial card with a 16550... speeds >2400bit/s became so much more reliable :-)
<re_irc> <@dirbaio:matrix.org> the api HAS to be different
<re_irc> <@adamgreig:matrix.org> perhaps more HALs should offer buffered as an option to increase the apparent buffer size, and it's up to the user to work out if the hardware buffer is big enough or they need to configure a bigger buffer in the HAL to support their driver, and some drivers will be fine with very small (1-4 word) buffers, and some need bigger ones for whatever reason (what reason though?)
<re_irc> <@adamgreig:matrix.org> is the only reason to need a bigger buffer "because it might be too slow"?
<re_irc> <@thejpster:matrix.org> Maybe we should offer a buffer wrapper you can easily connect to interrupts
<re_irc> <@thejpster:matrix.org> To save every Hal author getting the fifo Logic right
<re_irc> <@adamgreig:matrix.org> or are you fundamentally imagining that the unbuffered version would literally discard anything received while not actively listening, i.e. flush the hardware fifo at the start of all read() calls?
<re_irc> <@adamgreig:matrix.org> so the api is different because the unbuffered one only listens when you ask it to and never any other time
<re_irc> <@dirbaio:matrix.org> unbuffered:
<re_irc> fn read_exact(&mut self, read: &mut [Word]) -> Result<(), Self::Error>;
<re_irc> buffered:
<re_irc> fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
<re_irc> fn read_until_idle(&mut self, read: &mut [Word]) -> Result<usize, Self::Error>
<re_irc> <@dirbaio:matrix.org> the buffered API mirrors "std::io"
<re_irc> <@dirbaio:matrix.org> +in "embedded-io"
<re_irc> <@dirbaio:matrix.org> unbuffered ("embedded-hal"):
<re_irc> fn read_exact(&mut self, read: &mut [Word]) -> Result<(), Self::Error>;
<re_irc> fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error>;
<re_irc> buffered ("embedded-io"):
<re_irc> fn read_until_idle(&mut self, read: &mut [Word]) -> Result<usize, Self::Error>
<re_irc> <@dirbaio:matrix.org> it allows short reads (you ask for 10 bytes, you receive just 5)
<re_irc> <@dirbaio:matrix.org> that works fine for buffered
<re_irc> <@dirbaio:matrix.org> but it's utterly useless for unbuffered. You ask for 10 bytes, you receive just 5, and then since the "read()" call has returned, you might lose all the next bytes
<re_irc> <@dirbaio:matrix.org> so for unbuffered there's more low level control. Read EXACTLY 10 bytes, or read until line is idle
<re_irc> <@dirbaio:matrix.org> with that low level control, unbuffered becomes usable for SOME applications. Not all.
<re_irc> <@dirbaio:matrix.org> for other applications, just use buffered.
starblue has quit [Ping timeout: 246 seconds]
<re_irc> <@adamgreig:matrix.org> how does this happen? if it's unbuffered either there was only 0 or 1 byte to give you, or you waited until all 10 were read?
<re_irc> <@adamgreig:matrix.org> : reply to this, sorry
<re_irc> <@dirbaio:matrix.org> "unbuffered" means "no guarantee of the buffer size"
<re_irc> <@dirbaio:matrix.org> not "no buffer"
<re_irc> <@adamgreig:matrix.org> πŸ€”
<re_irc> <@dirbaio:matrix.org> for example a stm32 impl with the 4-byte buffer could pop 4 bytes at a time
<re_irc> <@adamgreig:matrix.org> so the distinction is in whether you get to ask it to wait vs only ever give you what was in the buffer
<re_irc> <@adamgreig:matrix.org> but you might well want to read exactly n bytes from the buffer and have it wait while it fills up, or read until idle from a buffer
<re_irc> <@adamgreig:matrix.org> if you're reading a variable length packet or something, even if it's buffered you might want to wait until the line is idle, then return the whole buffer?
<re_irc> <@adamgreig:matrix.org> (or early if the buffer fills up I guess)
<re_irc> <@dkhayes117:matrix.org> Here is an example of what I did for an
<re_irc> nrf9160 serial client
<re_irc> let length = rx.read_until_idle(&mut buffer).await.unwrap();
<re_irc> // read the command from LTE Link Monitor GUI
<re_irc> loop {
<re_irc> // Attempt to send AT command only when rx actually gets some bytes
<re_irc> if length != 0 {
<re_irc> let response = send_at_bytes::<1024>(&buffer[..]).await.unwrap();
<re_irc> tx.write(&response[..].as_bytes()).await.unwrap();
<re_irc> }
<re_irc> }
<re_irc> <@adamgreig:matrix.org> or rather - if buffered drivers are OK not having a "read_until_idle()", then it seems like every driver should be able to use the buffered API and just sometimes the buffer is really small which means you need to read it often enough to not have problems
<re_irc> <@dirbaio:matrix.org> : that code is assuming the command comes with no gaps, which is not the case :)
<re_irc> <@dirbaio:matrix.org> * guaranteed
<re_irc> <@dirbaio:matrix.org> this is the pitfall of unbuffered
<re_irc> <@dirbaio:matrix.org> to really make it reliable, you want "read until \n"
<re_irc> <@dirbaio:matrix.org> and to do that reliably, you need a reasonably big buffer
<re_irc> <@adamgreig:matrix.org> yea, I assume most drivers that are using "unbuffered" are actually going to have to just buffer whatever they read internally until they have enough, and then process it
<re_irc> <@adamgreig:matrix.org> for all those reasons
<re_irc> <@dirbaio:matrix.org> ie, require "embedded_io::Read", not "embedded_hal::serial::ReadUntilIdle"
<re_irc> <@dirbaio:matrix.org> : that's super fragile, it doesn't work if the driver doesn't get polled often enough
<re_irc> <@jannic:matrix.org> : However they might do other (fast) things between the read calls.
<re_irc> <@adamgreig:matrix.org> your buffered stuff also doesn't work if the driver doesn't get polled often enough though, it's just a question of how often is enough
<re_irc> <@dirbaio:matrix.org> this is why you can't write most drivers on top of unbuffered
<re_irc> <@dirbaio:matrix.org> : no, the contract of the buffered impl is "bytes don't get lost, ever"
<re_irc> <@adamgreig:matrix.org> : yea, but that's fine, so long as they check again soon enough that the hardware buffer doesn't overflow
<re_irc> <@dirbaio:matrix.org> +unless the buffer is full
<re_irc> <@adamgreig:matrix.org> yes but "unless the buffer is full" is exactly the contract with unbuffered too
<re_irc> <@dirbaio:matrix.org> and the buffer is BIG
<re_irc> <@dirbaio:matrix.org> "big enough"
<re_irc> <@adamgreig:matrix.org> right, which is my point, it's solely a difference of degree
<re_irc> <@jannic:matrix.org> Even the 1 byte buffer of unbuffered might be big enough if the polling is reliably fast enough.
<re_irc> <@adamgreig:matrix.org> maybe the driver should say "i need a buffer that's at least 256 bytes" and the user can say "ah, i'd better use the hal's buffered interface because the hardware one is only 2 bytes" or whatever
<re_irc> <@dirbaio:matrix.org> well
<re_irc> <@adamgreig:matrix.org> : yea, this is the normal experience for drivers that directly read hardware, I think; they expect to buffer packets themselves
<re_irc> <@dirbaio:matrix.org> yes and no
<re_irc> <@dirbaio:matrix.org> impls are supposed to detect overrun and error out or somehow signal to the user
<re_irc> <@dirbaio:matrix.org> for the embedded-io traits, the contract is that the driver doesn't need to worry about it at alll
<re_irc> <@dirbaio:matrix.org> * all
<re_irc> <@dirbaio:matrix.org> it can assume either there's flow control going on, or the user configured the buffer big enough so that overrun will never happen
<re_irc> <@jannic:matrix.org> Now that's actually a meaningful difference: One interface can report on missed bytes, the other one just drops them?
<re_irc> <@dirbaio:matrix.org> no
<re_irc> <@dirbaio:matrix.org> the difference is that an "embedded_io::Read" is "a logical stream of bytes"
<re_irc> <@dirbaio:matrix.org> vs the "embedded-hal" traits is "an uart that you're directly receiving from"
<re_irc> <@dirbaio:matrix.org> if the driver receives "a logical stream of bytes", it can read from it at its leisure and never worry about overflow etc
<re_irc> <@dirbaio:matrix.org> now
<re_irc> <@dirbaio:matrix.org> how "perfect" is the "logical stream of bytes" implementation is up to the user
<re_irc> <@dirbaio:matrix.org> an implementation that uses RTS/CTS, or that has builtin flow control some other way (like an USB CDC ACM port) is indeed "perfect" in that sense
<re_irc> <@dirbaio:matrix.org> an implementation that doesn't use RTS/CTS but has a big buffer (say, 4kb) is not "perfect", but "good enough"
<re_irc> <@dirbaio:matrix.org> when a driver takes an "embedded_io::Read", it's signaling the user "I want a logical stream of bytes"
<re_irc> <@dirbaio:matrix.org> if the user supplies an impl that's NOT perfect, then it's on the user to manage the consequences
<re_irc> <@dirbaio:matrix.org> the driver is declaring it's not doing any heavy lifting with respect to buffering
<re_irc> <@jannic:matrix.org> I get the impression that buffered/unbuffered is not the distinction here, but something subtly different.
<re_irc> <@dirbaio:matrix.org> it's expecting the user to do it
<re_irc> <@dirbaio:matrix.org> while
<re_irc> <@dirbaio:matrix.org> a driver taking an "embedded_hal::serial::Read" is declaring something completely different
<re_irc> <@dirbaio:matrix.org> it's declaring "you give me a raw UART, I will control when to read, and will make sure i'm always reading when data might be coming"
<re_irc> <@dirbaio:matrix.org> which is something VERY different
<re_irc> <@adamgreig:matrix.org> in the buffered case, can you peek the buffer, check how many bytes are in it, that sort of thing? if all you get to do is read "up to n" bytes but get back less, it seems like you _still_ need to internally buffer whatever you've read until you've assembled a complete packet/frame/message to process
<re_irc> <@adamgreig:matrix.org> in which case you could easily operate with a tiny buffer so long as you check it often enough to accumulate it into your bigger buffer?
<re_irc> <@dirbaio:matrix.org> : that's how std::io works, yes. There's "BufRead" that allows you to peek into the buffer and do zerocopy parsing.
<re_irc> <@adamgreig:matrix.org> BufRead, of course, but now you have two buffers :P
<re_irc> <@jannic:matrix.org> And a firmware author might decide to impl "embedded_io::Read" in terms of "embedded_hal::serial::Read" with effectively a 1-byte buffer. Which of course would break if the firmware polls too slowly, but then it was an active decision by the author and not an accident?
<re_irc> <@dirbaio:matrix.org> let me put it this way
<re_irc> <@adamgreig:matrix.org> I think I see the distinction you're making and it makes sense, but maybe buffered/unbuffered isn't the best way to explain it (to me)
<re_irc> <@dirbaio:matrix.org> if you give a driver an "embedded_io::Read" with a too small buffer and it breaks, it's YOUR fault
<re_irc> if you give a driver an "embedded_hal::serial::Read" with a too small buffer and it breaks, it's THE DRIVER'S fault
<re_irc> <@adamgreig:matrix.org> on the one hand you have drivers that just want to deal with a stream of bytes, might be tcp, might be uart, who cares, they're going to pull frames out somehow and process them and send new things back or whatever they do
<re_irc> <@adamgreig:matrix.org> on the other hand you have drivers that know they are dealing with a uart and are prepared to poll it quickly because otherwise they'll lose data, and might be relying on uart-y things like knowing about idle
<re_irc> <@adamgreig:matrix.org> but, it's still not entirely clear to me that it makes sense to split them, since you could still have idle detection in the stream case (even if you just implement it with a timeout or something), and you still have a (small) buffer in the uart case, I dunno
<re_irc> <@dirbaio:matrix.org> a driver that takes an "embedded-io::Read" is signaling "I want a stream of bytes". The burden is on YOU to give it a "good enough" approximation of "a stream of bytes"
<re_irc> <@adamgreig:matrix.org> does your stream driver basically pull chunks out of the stream into an internal buffer to assemble commands?
<re_irc> <@adamgreig:matrix.org> for your at modem or whatever
<re_irc> <@dirbaio:matrix.org> yeah, I have a "read_line" that reads into another buffer, and then it parses stuff out of that
<re_irc> <@dirbaio:matrix.org> just like you'd do with "std::io"
<re_irc> <@adamgreig:matrix.org> so in principle, could you just call that "quickly" on the small buffer from a uart, and nothing else changes?
<re_irc> <@adamgreig:matrix.org> I appreciate the point is maybe to not have to worry about it
<re_irc> <@dirbaio:matrix.org> yes
<re_irc> <@dirbaio:matrix.org> but I don't want my driver to explode
<re_irc> <@dirbaio:matrix.org> +if it doesn't get polled fast enough
<re_irc> <@dirbaio:matrix.org> and it's REALLY hard to poll it fast enough at, say, 1Mbaud
<re_irc> <@dirbaio:matrix.org> it really doesn't work in practice
<re_irc> <@adamgreig:matrix.org> yea, you need like 100kHz polling at that point with a tiny tiny 1-word buffer
<re_irc> <@dirbaio:matrix.org> so the driver takes a byte stream and that's it
<re_irc> <@adamgreig:matrix.org> but the HAL buffer is presumably running an interrupt at 100kHz to buffer stuff up there
<re_irc> <@dirbaio:matrix.org> no, the HAL uses DMA
<re_irc> <@adamgreig:matrix.org> maybe "direct" and "buffered" are better names?
<re_irc> <@adamgreig:matrix.org> I have to run soon, my cat is making _horrible_ noises in the litter box lol
<re_irc> <@dirbaio:matrix.org> (currently BufferedUart in embassy-rp and embassy-stm32 do use IRQ-driven IO instead of DMA, and yes, they run into issues at high baudrates)
<re_irc> <@dirbaio:matrix.org> but the whole point of "embedded-io" is that the burden of providing a quality buffered uart impl is on the HAL/user, not on the driver
<re_irc> <@dirbaio:matrix.org> so you can easily write robust drivers
<re_irc> <@dirbaio:matrix.org> there's no way to write an AT command parser on top of the unbuffered traits
<re_irc> <@dirbaio:matrix.org> * a reliable
<re_irc> <@adamgreig:matrix.org> any idea if the std io traits might end up in core if/when error does?
<re_irc> <@adamgreig:matrix.org> I feel like it's been talked about for many years
<re_irc> <@dirbaio:matrix.org> no idea
<re_irc> <@dirbaio:matrix.org> the blocker is "io::Error"
<re_irc> <@dirbaio:matrix.org> I think that even if it gets into core, the "core::io::Error" will be more bloated than the "embedded-hal"-style errors ...
<re_irc> <@dirbaio:matrix.org> the "type Error;" associated type, that's typically a 1-byte enum
<re_irc> <@dirbaio:matrix.org> so i'm not very hopeful
<re_irc> <@dirbaio:matrix.org> iirc there was a PR/RFC? can't find it now
<re_irc> <@adamgreig:matrix.org> fair
<re_irc> <@grantm11235:matrix.org> I saw someone suggest making core io traits with an error associated type, and making the std io traits aliases of that where "type Error = std::io::Error;"
<re_irc> <@adamgreig:matrix.org> and you think embedded-io rather than a BufferedUart trait in e-h that provides the Read method?
<re_irc> <@adamgreig:matrix.org> presumably Write is the same in both cases
<re_irc> <@dirbaio:matrix.org> ah, https://github.com/rust-lang/rust/pull/99917
<re_irc> <@adamgreig:matrix.org> I could imagine drivers still wanting to block/await for uart-idle even if buffered, then read out the whole buffer
<re_irc> <@dirbaio:matrix.org> : that doesn't help much in practice, because the received data might've wrapped around the buffer, so it's still not guaranteed to be continuous
<re_irc> <@dirbaio:matrix.org> with "ReadBuf" etc
<re_irc> <@adamgreig:matrix.org> not if the buffer is big enough right :P
<re_irc> <@adamgreig:matrix.org> but, fine
<re_irc> <@dirbaio:matrix.org> you can't simply wait and get a contiguous "&[u8]"
<re_irc> <@adamgreig:matrix.org> so you can assume data isn't lost, but you can't assume you can wait and get a contiguous read
<re_irc> <@dirbaio:matrix.org> : even if it's big enough, it'll wrap.
<re_irc> <@adamgreig:matrix.org> mightn't you still want to wait for idle and then do a couple of reads?
<re_irc> <@adamgreig:matrix.org> or do you imagine just reading it and then using a timer/timeout/etc to check for idle?
<re_irc> <@adamgreig:matrix.org> (I appreciate ideally the protocol tells you when you're done so...)
<re_irc> <@adamgreig:matrix.org> maybe you just end up never caring about idle
<re_irc> <@dirbaio:matrix.org> : not sure what'd be the advantage. eagerly reading is faster, you're parallelizing rxing and copying out of the buffer
<re_irc> <@grantm11235:matrix.org> : only when it gets to the end, which means it's not big enough. Just use an infinite buffer 🀣
<re_irc> <@dirbaio:matrix.org> yeah I think with buffered, it's rare to need idle
<re_irc> <@dirbaio:matrix.org> you typically have some kind of framing
<re_irc> <@adamgreig:matrix.org> the only unambiguous framing is sometimes idle, sadly
<re_irc> <@dirbaio:matrix.org> and "idle" is not well defined everywhere. for example in AT over a CDC ACM
<re_irc> <@adamgreig:matrix.org> but yea, it's not super well defined and also you could still detect it by enough empty buffered reads in a certain time
<re_irc> <@dirbaio:matrix.org> if your framing is "idle" then you probably want the unbuffered ReadUntilIdle
<re_irc> <@dirbaio:matrix.org> but it's rare that the framing is actually "wait for idle"
<re_irc> <@dirbaio:matrix.org> that can't be reliably implemented on a linux PC for example :D
<re_irc> <@dirbaio:matrix.org> linux uart is always buffered
<re_irc> <@dkhayes117:matrix.org> If you are framing with "\n" are you peeking the buffer to detect the new line?
<re_irc> <@dirbaio:matrix.org> yes
<re_irc> <@adamgreig:matrix.org> I have to run (and we're somewhat over time) but I think my position at least has shifted from "maybe they should be the same trait" to "I see why you want two separate traits, but should one be called 'unbuffered' and should e-h still provide both for reading from uarts, and one common trait for writing to them"
<re_irc> <@dirbaio:matrix.org> > should one be called 'unbuffered'
<re_irc> I'm open to bikeshedding. Dunno what the best naming is
<re_irc> <@adamgreig:matrix.org> but to be fair it's not like the actual trait is called Unbuffered
<re_irc> <@adamgreig:matrix.org> it's just called ReadExact and ReadUntilIdle
<re_irc> <@dirbaio:matrix.org> > should e-h still provide both for reading from uarts
<re_irc> embedded-io is for more than just uarts, you can use it for TCP streams etc. I don't think having a trait that's "embedded-io but for just uarts" is valuable.
<re_irc> <@adamgreig:matrix.org> still, for the docs and things I wonder if "direct" is more accurate than "unbuffered (we just mean we don't know how big the buffer is but it's not very big)"
<re_irc> <@dirbaio:matrix.org> that said, it probably makes sense to move "embedded-io" into the embedded WG if "embedded-hal" is directing users to it for buffered uart
<re_irc> <@dirbaio:matrix.org> > and one common trait for writing to them
<re_irc> ahhh this is another can of worms. Currently the unbuffered e-h trait waits until writing everything (it's like "io"'s "write_all"), while the e-io Write trait allows short writes
<re_irc> <@dirbaio:matrix.org> I think that's the setup that makes most sense, and it's consistent with how reading works
<re_irc> <@jannic:matrix.org> If writing can block and reading is unbuffered, bidirectional use really can't be done reliably.
<re_irc> <@dirbaio:matrix.org> : yep, you're supposed to use the buffered ones in that cae
<re_irc> <@dirbaio:matrix.org> * case
<re_irc> <@dirbaio:matrix.org> (or πŸ‘»nbπŸ‘»)
<re_irc> <@dirbaio:matrix.org> unbuffered only works if you control the timing, for example if you know the peer won't talk when you're talking etc
<re_irc> <@dirbaio:matrix.org> ping , have you had some time to look at the PRs? πŸ‘€
<re_irc> <@eldruin:matrix.org> sorry, didn't make it today
<re_irc> <@eldruin:matrix.org> I have not gone through the serial PR yet
<re_irc> <@dirbaio:matrix.org> the serial one, or the others
<re_irc> <@dirbaio:matrix.org> I think they're all we're missing for 1.0
<re_irc> <@dirbaio:matrix.org> +...
starblue has joined #rust-embedded
Shell has quit [Remote host closed the connection]
Shell- has joined #rust-embedded
dnm_ is now known as dnm
<re_irc> <@therealprof:matrix.org> : Sorry, have a to lead some meeting sessions this week, no spare time at the moment to look at PRs.
IlPalazzo-ojiisa has quit [Quit: Leaving.]
IlPalazzo-ojiisa has joined #rust-embedded
IlPalazzo-ojiisa has quit [Client Quit]
IlPalazzo-ojiis1 has joined #rust-embedded
IlPalazzo-ojiis1 has quit [Client Quit]
IlPalazzo-ojiisa has joined #rust-embedded
IlPalazzo-ojiisa has quit [Client Quit]
IlPalazzo-ojiisa has joined #rust-embedded
lehmrob has quit [Ping timeout: 268 seconds]
IlPalazzo-ojiisa has quit [Ping timeout: 276 seconds]
dc740 has joined #rust-embedded
IlPalazzo-ojiisa has joined #rust-embedded
IlPalazzo-ojiisa has quit [Client Quit]
IlPalazzo-ojiisa has joined #rust-embedded
IlPalazzo-ojiisa has quit [Client Quit]
IlPalazzo-ojiis1 has joined #rust-embedded
IlPalazzo-ojiis1 has quit [Ping timeout: 255 seconds]
IlPalazzo-ojiisa has joined #rust-embedded
dc740 has quit [Remote host closed the connection]
IlPalazzo-ojiisa has quit [Remote host closed the connection]