<cr1901>
Lumpio[m]: What is the idiomatic way to check for whether a usb_device has been disconnected (and so I know to render buffers invalid)? Self-powered of course
adamgreig[m] has joined #rust-embedded
<adamgreig[m]>
detect vbus
<adamgreig[m]>
the protocol can at best tell you if you've been suspended
sajattack[m]1 has quit [Quit: Idle timeout reached: 172800s]
<cr1901>
unsure how to do that with atsamd lol
<cr1901>
Any USB stuff I've done has empathetically assumed bus power (not a great idea)
danielb[m] has quit [Quit: Idle timeout reached: 172800s]
<Lumpio->
cr1901: I think in most cases you'd be fine by just checking UsbDevice::state after a poll and checking for a status that's not "Configured"
<Lumpio->
You might even _want_ to reset stuff if the driver only suspends you as opposed to disconnecting Vbus
<Lumpio->
What comes to monitoring Vbus some chips have a dedicated pin for that, some don't and you're expected to just use GPIO (and GPIO interrupts if desired)
JamesMunns[m] has joined #rust-embedded
<JamesMunns[m]>
And I'm guessing sticking a powered hub in between the device and PC would cause all kind of trouble
<JamesMunns[m]>
(e.g. disconnecting the hub from PC, so you still have power)
thejpster[m] has joined #rust-embedded
<thejpster[m]>
I have a suggestion to collapse the -eabi and -eabihf target docs into one file. What do you think?
<sourcebox[m]>
ryan-summers: The owner of `usbd-midi` has agreed on tranferring the crate to rust-embedded-community, but I think now either you or some other maintainer of the group has to join the conversation for the details. https://github.com/btrepp/usbd-midi/issues/14#issuecomment-2082240533
wose has joined #rust-embedded
bradleyharden[m] has quit [Quit: Idle timeout reached: 172800s]
M9names[m] has quit [Quit: Idle timeout reached: 172800s]
<sourcebox[m]>
thejpster: I think the ownership on crates.io should also be transferred. Are there any details how to do this?
<sourcebox[m]>
JamesMunns[m]: So it would be `cargo owner --add rust-embedded-community`?
M9names[m] has joined #rust-embedded
<M9names[m]>
is rust-embedded-community a github user? you usually want to nominate a user as well as a team, because teams cannot change crate ownership
<ryan-summers[m]>
I think you can make Github teams owners on crates.io
<ryan-summers[m]>
So maybe it'd be rust-embedded-community:usb-device as the owner
<sourcebox[m]>
So what advice should we give to the crate owner?
<ryan-summers[m]>
1. Transfer the repo, 2. If he'd like, we can add him to the `usb-device` group as well so he can retain some access to the repo, 3. Add crates.io ownership to the usb-device team
<ryan-summers[m]>
s/some//
<ryan-summers[m]>
We should add these instructions to the meta repo so we can easily just point to this in the future. I'll open an issue
<sourcebox[m]>
Ok, I added this to the GH issue.
hmw has quit [Quit: Bye.]
hmw has joined #rust-embedded
spinfast[m] has joined #rust-embedded
<spinfast[m]>
how much rom does postcard take up typically?
<spinfast[m]>
* James Munns: how much
<JamesMunns[m]>
spinfast[m]: 🌈 it depends 🌈
<JamesMunns[m]>
JamesMunns[m]: generally scales with the number of types that implement serialize and that you use
<JamesMunns[m]>
postcard itself is pretty dumb and small, and doesn't add a lot over the serde impls
<JamesMunns[m]>
and for basic types serde impls aren't huge
<JamesMunns[m]>
I've used postcard in 4-8k binaries, generally it doesn't show up high on cargo-bloat. is there a reason you ask?
<JamesMunns[m]>
(in most cases, the serde impls end up mostly just being memcpy's :p)
<spinfast[m]>
using nanopb and noticing it takes up a decent amount of memory
<spinfast[m]>
for a C project sadly, but wondering if I could perhaps reuse the postcard encoding
<JamesMunns[m]>
oh, it will take drastically less RAM and ROM than nanopb. But also does much less.
<JamesMunns[m]>
yeah, you could hand-write postcard encoding, the format is very dumb and simple. But it only covers like the center 30% of what nanopb does. it doesn't handle changing schemas, evolution of schemas, etc.
<spinfast[m]>
oh that's a very interesting point on the scheme evolution aspect
<JamesMunns[m]>
yep, postcard is faster and lighter than protobufs/nanopb by cheating and doing less
<JamesMunns[m]>
that might be acceptable for you! and postcard-rpc helps handle *some* of that (though more "detecting" and not "handling" changed schemas)
<spinfast[m]>
yeah absolutely, thanks for the very informative answer
<spinfast[m]>
I think I have my answer in the schema evolution alone, that I believe would be important in this case
<JamesMunns[m]>
yep. I've switched from nanopb to postcard in cases where perf was important, in a very unscientific but relevant to my customer at the time test, switching from nanopb to postcard brought our ser/de times down from 100-200us to 1.5-2.5us, so the speedup can be a lot (this was a relatively large 500ish byte struct, with 30-40 fields).
<JamesMunns[m]>
for that customer we ended up putting the serde stuff in a FFI, as the main binary was C. We ended up writing a code gen tool for it tho.
<JamesMunns[m]>
Speed was important because we were sending/receiving data at like 10kHz, so 100us to deser, process, then serialize an answer was the whole budget we had
<JamesMunns[m]>
(they WERE just doing "memcpy to raw packet buffers", but had a lot of "oops data corrupted" bugs. so they were looking to switch to nanopb or something
dirbaio[m] has joined #rust-embedded
<dirbaio[m]>
what clock freq? even in fastest mcus 1.5-2.5us is only a couple hundred clock cycles, seems to good to be true?
<JamesMunns[m]>
dirbaio[m]: 600mhz imxrt
<dirbaio[m]>
hmm wow
<JamesMunns[m]>
so yeah, 900-1500 cycles, pretty simple types. I might be wrong by a bit, but it was triple digit us to single digit us
<spinfast[m]>
fire up the 1176 and load everything in sram... never wait again
<spinfast[m]>
It'd be interesting to see whats faster, p3 1ghz circa 2000 or the imxrt 1176 m7 core circa 2021
dne has quit [Remote host closed the connection]
dne has joined #rust-embedded
<ryan-summers[m]>
Shameless plug, but Robert just added postcard native support for miniconf as well, so if you are looking for compact settings ser/de into nice rust structs, check it out: https://github.com/quartiq/miniconf?tab=readme-ov-file#formats
<cr1901>
Is it no-alloc as well?
<ryan-summers[m]>
miniconf? Yup. All no-alloc no-std stuff
<cr1901>
Very good, I'll try it w/ the postcard feature and be sure to complain when it doesn't work for my bespoke use case ;) (de/serializing potentially compressed data from/to small I2C eproms)
<ryan-summers[m]>
tl;dr is that it transforms a struct to a Tree, so you can do something like my_struct.set_by_key("some/path/into/struct", b"1.0")
<ryan-summers[m]>
So you can store things as key/value in some EEPROM/Flash and then reload it at runtime, potentially where only partial settings are available
<ryan-summers[m]>
So you don't have to serialize everything and/or care about the settings format changing between firmware revs
<cr1901>
I haven't worked out the details, but the eeprom24x crate has support for embedded-storage traits. I'll probably have to create a postcard flavor that reads/writes from embedded-storage traits, which in turn is wrapped by miniconf
<cr1901>
ryan-summers[m]: So array_option_tree... if I had [Option<Inner>; 12], and the first 10 of those were "Some", the remaining 2 "None" would take up minimal space in the EEPROM storage?
<ryan-summers[m]>
Miniconf isn't the binary format in storage, that's postcard etc. - Miniconf is just a way to update a run-time struct from key/value pairs
<ryan-summers[m]>
So you'd store your key/value pairs in EEPROM, then load them in at run-time via miniconf
<ryan-summers[m]>
You can make the binary formats as big or as small as you want
<cr1901>
Ahhh right, and I already know that postcard compresses "None" efficiently from staring at sample runs
<cr1901>
Yea, I'll play with this and make it work
<ryan-summers[m]>
But Robert did just make it so that you can make a key that is a u32 that can be used to index into a struct
<ryan-summers[m]>
Or shorter. It uses bitpacking for indices
<ryan-summers[m]>
So you could theoretically probably use a u16 for most structs. Maybe even a u8
<cr1901>
By u32, you mean e.g. /array_tree2/1/b line (the "1")?
<ryan-summers[m]>
But if you had None in a miniconf struct, the way you'd store that in memory would be by actively not having anything in there
<ryan-summers[m]>
Like, don't put anything in memory
<ryan-summers[m]>
yeah, so instead of /array_tree2/1/b, that key can also be represented in a binary bit packed format like 0b1_11_01_1 or something
<ryan-summers[m]>
(Miniconf will calculate that key for you)
<JamesMunns[m]>
(postcard would serialize each None as one byte, in this example)
<ryan-summers[m]>
Yeah but the way Miniconf treats a None would be that it wouldn't even be provided to the code, so you'd never even serialize anything
<cr1901>
Yea, that is what I want. I essentially want to mimic "variable length array", where I don't care about RAM usage that much, but I Very Much care about EEPROM usages
<ryan-summers[m]>
Miniconf can definitely do that, Robert has some test cases for it
<JamesMunns[m]>
fair, no idea about miniconf, postcard would do that for `&[Inner]` but not `[Option<Inner>; 12]`
<ryan-summers[m]>
He's been working a lot on it over the last week or two to make it super binary-compact
<cr1901>
ryan-summers[m]: >Miniconf will calculate that key for you <-- how? I see a Packed key, but I don't see a compile-time way to convert friendly string keys to packed?
RobertJrdens[m] has joined #rust-embedded
<RobertJrdens[m]>
cr1901: you have to store that mapping yourself somewhere if you need it offline
<cr1901>
(I'd like to note that the bits patterns for each depth in the Packed example are all palindromes, so it's not clear to me that e.g. 4-bit index 0001 becomes 1000)
<cr1901>
and I also screwed up the order again :P
fuse117[m] has joined #rust-embedded
<fuse117[m]>
in need of some general troubleshooting help. the release build of my app has an issue that is not present in the debug build. a background task is either not running or publishing its data in the release build. data from other tasks is published correctly though. the background task runs fine and publishes correctly in a debug build though. im not sure how to debug this as the issue is showing up under a release build in
<fuse117[m]>
which i have logging turned almost off
<fuse117[m]>
* in need of some general troubleshooting help. the release build of my app has an issue that is not present in the debug build. a background task is either not running or publishing its data in the release build. data from other tasks is published correctly though. the background task runs fine and publishes correctly in a debug build. im not sure how to debug this as the issue is showing up under a release build in which
<fuse117[m]>
i have logging turned almost off
<fuse117[m]>
* in need of some general troubleshooting help. the release build of my app has an issue that is not present in the debug build. a background task is either not running or publishing its data in the release build. data from other tasks is published correctly though. the background task runs fine and publishes correctly in a debug build. im not sure how to debug this as the issue is showing up under a release build in which
<fuse117[m]>
i have logging turned almost off. any suggestions?
corecode has left #rust-embedded [ERC 5.5.0.29.1 (IRC client for GNU Emacs 29.3)]
_whitelogger has joined #rust-embedded
<cr1901>
RobertJrdens[m]: Perfect, tyvm. I'll use the lookup branch for now
<cr1901>
Looks like I don't need necessarily need a Borrow impl either
IlPalazzo-ojiis1 has joined #rust-embedded
<cr1901>
ryan-summers[m], RobertJrdens[m]: Okay so from what I can gather, in order to use miniconf, you have to know ahead of time at what position the given key's data starts?
<cr1901>
(position in a buffer, for instance. I.e. I have to read out the EEPROM first, do a test deserialization to figure out where each key's data begins, and then keep copies of the buffer position for each key)
<RobertJrdens[m]>
framing is out-of-scope. use e.g. sequential-storage or ekv or others depending on the use-case.
<cr1901>
Yes, sequential-storage is what I want... I forgot about it (sadly async only, and this ain't an async app. Guess I'll be calling poll manually)
diondokter[m] has joined #rust-embedded
<diondokter[m]>
cr1901: You can use the block-on function from e.g. embassy-futures
<diondokter[m]>
It's really hard to support both async and blocking 🥲
<diondokter[m]>
At least you can make async block. But you can't make blocking async. So that's why the crate is async
<cr1901>
I haven't done that benchmark yet, so it's "just vibes" at this point
<diondokter[m]>
cr1901: Hah yeah. I wish things were better too. Haven't done real benchmarks either, but I think async Rust is a bit larger on code size than the blocking equivalent. It needs to do more things and I feel like the extra complexity can prevent some optimizations from happening. But that conclusion is also vibes based
<dirbaio[m]>
async vs blocking is apples-to-oranges
<dirbaio[m]>
the "real" comparison is async vs hand-written nonblocking state machine
<cr1901>
That may be apples-to-oranges, but I'm still not happy going around my elbow to get to my ass to get a blocking API in code that I may have to debug. 1/2
<dirbaio[m]>
what I mean is, it's expected that async (or state machines) are bigger than plain old blocking code
<diondokter[m]>
Idk if MaybeAsync as a concept would solve all this, but I feel like something should be done because the status quo isn't great
<dirbaio[m]>
in theory async code size should be the same as handwritten state machines. this is what people refer to when they say async rust is "zero cost"
pflanze has quit [Remote host closed the connection]
pflanze has joined #rust-embedded
<dirbaio[m]>
unfortunately this doesn't help if you want blocking code 🤣
<dirbaio[m]>
i'm not optimistic at all
<cr1901>
dirbaio[m]: I know all this. My complaint is that libraries do async, say "use an executor if you want blocking" (or worse, a specific executor), and then call it a day without thinking "hey, is it possible that all this extra code brought in will drastically increases debugging burden if/when things go wrong"?
<dirbaio[m]>
* at all re maybe_async or keyword generics
<dirbaio[m]>
agreed
<dirbaio[m]>
but if the library author is only going to use the library async, why are they obligated to also support blocking?
<JamesMunns[m]>
dirbaio[m]: Yep, +1 to that
<dirbaio[m]>
as a lib author I have the option of either take on more work to support blocking, or support just async
<dirbaio[m]>
if I personally want only async, I don't get any return from the extra work from supporting blocking
<diondokter[m]>
cr1901: Well, sequential-storage being async is not out of laziness. I genuinely don't know how to support blocking without having two copies of most of the code or using macro hacks
<cr1901>
I can't control what other ppl decide what's important
<dirbaio[m]>
the maybe_async macro is terrible, and completely fails if you want use join, select or mutexes in your code.
<diondokter[m]>
Also, sequential-storage started out blocking and it took a lot of work to make it async and do async well including cancellation support
<dirbaio[m]>
same boat for ekv, basically
<dirbaio[m]>
"if you want blocking use it through block_on" is an okay compromise, and if that doesn't work for you then you're encouraged to fork it and deasincify it :P
<diondokter[m]>
Keeping it blocking might block your entire processor for 100's of milliseconds if you have a big storage over a slow spi connection
<diondokter[m]>
dirbaio[m]: Yes! Or if you do know how to support it, open an issue or PR!
<cr1901>
I've already accounted for that in my app; blocking is acceptable when writing to the EEPROM flash
<dirbaio[m]>
it's acceptable for your use case, it wasn't for ours
<diondokter[m]>
Yep, I couldn't stop processing incoming messages when I update my config somewhere else
<diondokter[m]>
So async to the rescue
<cr1901>
To be clear, "if you want blocking use it through block_on" _is_ an okay compromise
<cr1901>
for me
<cr1901>
It is probably unlikely that I'll be using sequential-storage in such a complex way that I'll need to debug the resultant assembly (it's already not been fun to look at 20kB of blocking ARM from objdump -D)
<dirbaio[m]>
why are you even debugging 20kb of asm 🤯
<diondokter[m]>
cr1901: Just nerdsnipe me into looking into the assembly 😋
<cr1901>
B/c the application is 20kB so far
<dirbaio[m]>
but why the asm
<dirbaio[m]>
surely there's other ways, like adding logs or something
<cr1901>
I couldn't figure out why an interrupt wasn't firing... it turns out I called a HAL function in the wrong order, and it _disabled_ ints after I enabled them
<cr1901>
and it wasn't obvious to me what was wrong until I looked at the I/O port writes
<cr1901>
(which sucks on ARM b/c it uses a g*ddamn literal pool which complicates CTRL+F)
<cr1901>
>it's acceptable for your use case, it wasn't for ours <-- re: this, all I can do is try to build the future I want to see. It is highly unlikely I'll ever have an async only library, and I will eat the cost of supporting blocking from the beginning as well.
<cr1901>
(I don't think keyword generics will help much, after seeing _a lot_ of pushback)
<dirbaio[m]>
keyword generics is probably not happening, mo
<JamesMunns[m]>
I think you're really missing out, but there's certainly nothing stopping you.
<dygear[m]>
Has there been hardware that the team have used that really helped you debug embedded chips? I'm mostly programming Adafruit Feather chips, some are RP2040s mostly now ESP32-S2/3 and soon the ESP32-C6. The Adafruit designs do not break out the SWD pins like the Raspberry Pi Pico implemntation for their RP2040 chips. So it looks like I have to follow the white rabbit by listening to the I2C and UART ports when I'm sending signals that
<dygear[m]>
way. What hardware has helped you debug problems there? Should I just bite the bullet I buy a Seleae? I'm trying to make sure that I don't blocked while writing code, or if I do get blocked that I can provide a decent report.
<diondokter[m]>
RobertJrdens[m]: Ah, right, of course. I hadn't connected your name to stabilizer good enough yet in my mind
<cr1901>
RobertJrdens[m]: Oh, interesting, you use a map. I was gonna use a queue based on Settings::iter_packed() (b/c small EPROM, less overhead).
<diondokter[m]>
Some people are so good with names. Idk how they do it
K900 has joined #rust-embedded
<K900>
They WHAT
<cr1901>
I assume a queue has less overhead than a map :P
<K900>
Like literally there's a big box in the middle that says "SWD"
<dygear[m]>
Hit head on the table
<JamesMunns[m]>
K900: Saleae is really very good but is now very expensive. That being said there are often test points on a fruit boards for swd, and esp-c6 has built in USB jtag
<dygear[m]>
One day I'll be able to ask a question in here without putting my foot in my mouth. That day is NOT TODAY!
<dygear[m]>
Yeah, I REALLY hate that WebUSB / WebSerial is Chrome only. That kills me. I hope that WWDC brings some good news to Safari and maybe iOS / iPadOS given their scrutiny by the EU.
Lumpio[m] has quit [Quit: Idle timeout reached: 172800s]
<dirbaio[m]>
hahaha you know the situation is dire when you hope fucking safari is the savior
<dygear[m]>
Yeah, I just want another player in that space. Chrome owning the WebUSB / WebSerial feels like IE6 all over again.
<dirbaio[m]>
safari is the new IE6 :P
<diondokter[m]>
dygear[m]: Yeah, the EU mandated browser selection screen does work though. Apparently some smaller browsers are seeing 2x or 3x their normal downloads
<dygear[m]>
That's fair. Easpically as they closed their Windows implementation.
<dygear[m]>
I think Brave got a huge bump! Good for them! (I'm sure you can tell I'm a Web Programmer by background now.)
<dirbaio[m]>
I hope the EU tears Apple to pieces :P
<cr1901>
diondokter[m]: Oh right, ack re: use main branch. I've decided to take a little diversion and implement a fake embedded-storage device that just writes to an in-memory buffer. Just to get an idea on memory usage
IlPalazzo-ojiis1 has quit [Remote host closed the connection]
barnabyw[m] has quit [Quit: Idle timeout reached: 172800s]
<whitequark[cis]>
you could conceivably bring third party webusb support to firefox
<whitequark[cis]>
they have a webserial polyfill that's allowed by mozilla
<whitequark[cis]>
and my understanding is that the current policy is to allow that sort of thing and see if they regret it
<dirbaio[m]>
oh, with an extension that communicates to a process running outside the browser. wtf
<whitequark[cis]>
well how else would you do it?
<whitequark[cis]>
you can't ship XPCOM anymore
<dirbaio[m]>
yea... I guess it's the only way
<dirbaio[m]>
still, cursed
<whitequark[cis]>
the UX of that is kind of garbage, which is why I'm not up in arms writing a webusb version of the same
<whitequark[cis]>
you'd need an autoupdater of sorts, and put all the right stuff in the registry, and maybe register it as a service or something... eh
<whitequark[cis]>
and I don't really want to be taking that risk either
<whitequark[cis]>
so I'll let someone much less concerned about engineering mistakes impacting their downstream users to implement it instead, I guess
<cr1901>
diondokter[m]: Is it possible to use sequential storage with an EEPROM that only implements (Read)Storage and not the NorFlash traits?
<cr1901>
lots of my_fun<S: NorFlash> :o
<diondokter[m]>
cr1901: Not out of the box. You could write a wrapper around it I guess to emulate the NorFlash traits
<sourcebox[m]>
Btw. is a new release of sequential-storage planned soon?
<diondokter[m]>
Yeah, kinda waiting on one last thing to make it in
<sourcebox[m]>
Because the changes are quite significant as I've seen.
<diondokter[m]>
Yup, much better map API IMO
<sourcebox[m]>
So the keys don't have to be stored with the values anymore?
<diondokter[m]>
The original API was fine for my initial usecase, but this new one generalizes a lot better
<diondokter[m]>
sourcebox[m]: They are still, but they're defined separately
<diondokter[m]>
This allows you to use multiple value types too
<diondokter[m]>
Like if you know key 11 is always Bar and key 12 is Foo you can just do that now
<sourcebox[m]>
That means, you don't need to have a dedicated field for the key in you data?
<diondokter[m]>
Indeed
<diondokter[m]>
Logical for enums, super weird when storing structs
<sourcebox[m]>
In addition to the migration, I want to move away from the internal flash of the ESP32 to a dedicated SPI flash chip. This is because execution is always stalled when flash is written. But I have no idea yet what stack of crates has to be used for that.
<diondokter[m]>
If there's an existing driver, just use that
<diondokter[m]>
Otherwise you'll have to create one, probably on top of embedded-hal
<sourcebox[m]>
SPI is done by esp-hal, but what crate handles the flash commands?
<diondokter[m]>
The driver
<sourcebox[m]>
So there must be a driver which implements both embedded-hal and embedded-storage.
<diondokter[m]>
I'd call that a good driver yeah
<sourcebox[m]>
To connect things together.
<diondokter[m]>
Yep
<sourcebox[m]>
I can do this on my own, but I'm quite sure it already exists.
<diondokter[m]>
Depends on the flash chip you use!
<diondokter[m]>
For example, for a chip we used there wasn't a driver yet.