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
IlPalazzo-ojiisa has quit [Quit: Leaving.]
Alistair[m]1 has joined #rust-embedded
<Alistair[m]1> The RISC-V toolchains are in a pretty good state
<Alistair[m]1> Should be comparable to other archs
takkaryx[m] has quit [Quit: Idle timeout reached: 172800s]
korken89[m] has joined #rust-embedded
<korken89[m]> Hey James Munns, would you be up for a PR that adds async support (behind a feature flag) for `BBQueue`?
<korken89[m]> * that adds `async, * async` support
<korken89[m]> I'm at the point of wrapping BBQueue and having async support "on the side" but it seems like I could add it just as simply in BBQueue itself and have the rest of the ecosystem gain some as well :)
<JamesMunns[m]> Tbh I don't have the bandwidth to maintain bbqueue ATM, I also have an async version in mnemos but it's different a little bit
<JamesMunns[m]> I could r-e-c it, ithinel has been helping lately but I want to do a bigger overhaul but I haven't needed it lately and haven't had the time to do it
<korken89[m]> <JamesMunns[m]> "Tbh I don't have the bandwidth..." <- Sounds interesting! What's the difference compared to the original?
<korken89[m]> Thanks for the outline! I'll give it a look and maybe poke at it :) I need a framed buffer for my interfaces to the DTLS lib I'm working on and BBQueue was very close to what I need
<JamesMunns[m]> yeah, I've struggled with:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/pHdxSlhZZeiwNxTlkRcJtyOe>)
<JamesMunns[m]> it's complicated enough that I can't find a way to abstract over it without making it worse for all users, and copy and pasting the code to make 5-6 versions kind of sucks, maintenance wise
<korken89[m]> Yeah, I understand the burden
<korken89[m]> I will start with the vanilla BBQueue and see if I can wrap it to do what I want :) If it makes sense to PR it back I'll give a shout again so you don't need to think about the maintenance burden
IlPalazzo-ojiisa has joined #rust-embedded
IlPalazzo-ojiisa has quit [Ping timeout: 264 seconds]
IlPalazzo-ojiisa has joined #rust-embedded
ijager[m] has joined #rust-embedded
<ijager[m]> I would love to hear some input and opinions on embedded USB Host.
<ijager[m]> A client wants to be able to attach a USB barcode scanner and an USB RFID badge reader to an existing product based on an STM32G031.
<ijager[m]> I saw that newer variants in the G0 series have USB Host support. Is it a bad idea to implement a very specific USB Host (HID class only?) in embedded rust. I am a bit hesitant because I keep reading that it is too complex, not worth it. Or should I look for a linux processor as an easy way out?
<JamesMunns[m]> I don't know if it's a bad idea, but I haven't seen many people doing it (vs lots for usb device). There are some links here, but these are the only instances I've seen: https://github.com/rust-embedded/wg/issues/40
<JamesMunns[m]> if your volume is very small (hundreds-thousands), you are likely to spend less time/money dropping in a linux SoC with USB host support. Hard to give more specific advice without knowing the context
<dirbaio[m]> STM32G031 doesn't have USB
<JamesMunns[m]> g0x1 does
<JamesMunns[m]> I think g0C1?
FreeKill[m] has joined #rust-embedded
<FreeKill[m]> I thought we could resolve this by a volatile read of the interrupt enable, but that has now been shown not to work.
<FreeKill[m]> Hi all, just want to pick your embedded brains. On cortex M, if you clear an interrupt flag in a peripheral and then immediately return from IRQ, the IRQ can retrigger due to the various buffers and latencies meaning that the peripheral flag isn't *really* clear.
<FreeKill[m]> Has anyone got a reliable resolution to this?
<ijager[m]> The C line does
<ijager[m]> Thanks James Munns that's already a helpful perspective
<JamesMunns[m]> FreeKill[m]: > <@larunite:matrix.org> Hi all, just want to pick your embedded brains. On cortex M, if you clear an interrupt flag in a peripheral and then immediately return from IRQ, the IRQ can retrigger due to the various buffers and latencies meaning that the peripheral flag isn't *really* clear.... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/nkFGFZXXdMMLwZyAwBmfMXBz>)
<FreeKill[m]> As in just NOP spin?
<JamesMunns[m]> ijager[m]: yep, I think it'd be totally possible to get the g0c1 working, at least for the specific device(s) you need. It's just a push/pull between "how much do you cost per hour" and "how much more is a cheap linux soc per unit" and "how much more cost is it to integrate the linux soc" and "how many units will you sell/what is your margin"
<JamesMunns[m]> FreeKill[m]: usually "spin on polling a status register"
<FreeKill[m]> Yeah ok, that's not too bad. I really thought a single read of the same register would be enough (since it goes "the same path") but seems not
<dirbaio[m]> most complete usb host I know of is https://github.com/nviennot/turbo-resin/tree/main/src/drivers/usb
<dirbaio[m]> it's for OTG tho, the G0 has USBD instead
<JamesMunns[m]> yeah, that's core specific. It might be that peripherals run on a different clock domain where you might have to wait N periph clock cycles for the source to clear, if I remember correctly.... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/mrJNLeIDMUokvIYXRYHnYaAy>)
<dirbaio[m]> ^ that can hang if a 2nd read event really does fire
<JamesMunns[m]> yeah, fair
<JamesMunns[m]> like I said, probably chip specific
<diondokter[m]> Ah, remember when empty loops were harmful :D
<JamesMunns[m]> diondokter[m]: register reads are always side effectful :)
<dirbaio[m]> in stm32's i've always found a read from the peripheral register fixes the double-interrupt issue though
<dirbaio[m]> because it does wait for the write to get flushed
<dirbaio[m]> what chip are you using where that's not working?
<diondokter[m]> Ah true!
<diondokter[m]> Still, it was the first thing I spotten in your code. It has rotted my brain a little
<FreeKill[m]> Yeah, this is not stm32 it's a cortex asic
<JamesMunns[m]> dirbaio[m]: I *want* to say it was one of the atmel chips, they have all kind of async clock domains, but I can't remember for sure
<dirbaio[m]> FreeKill[m]: oh oof ... no idea then, good luck :D
<dirbaio[m]> maybe isb/dsb/dmb is worth trying too
<JamesMunns[m]> yeah, this is "read the reference manual/errata", hopefully they talk about how many cycles or what steps are sufficient to "flush" clearing an interrupt
<dirbaio[m]> and if not ... a spin wait 🫠
<FreeKill[m]> Tbh I expected that a write/read of a register would lower to code that did the necessary synchronisation not to see the "stale" value, it's slightly scary if not
<diondokter[m]> FreeKill[m]: A read is just a read. Like Dario suggested, there are ISB and DSB instructions for that
<dirbaio[m]> perhaps there's extra buffering/latench in the "peripheral -> nvic" connection
<dirbaio[m]> or perhaps the peripheral needs extra cycles to clear the interrupt line after you request it through the bus...
<dirbaio[m]> diondokter[m]: a read does wait for previous writes to flush
<dirbaio[m]> in "simple" buses like in cortex-m chips at least
<diondokter[m]> Yeah ok
<JamesMunns[m]> yeah, MMIO means it isn't ever necessary that reads and writes are ever consistent
<JamesMunns[m]> like, you could totally NEVER see a write occur
<JamesMunns[m]> (or a read might do nothing at all)
<JamesMunns[m]> (MMIO peripherals LOOK like memory, "API" wise, but they don't necessarily ACT like memory, from a bus perspective)
<FreeKill[m]> Yeah of course, I guess I imagined that the bus might be stalled on a read while the write "got applied"
<JamesMunns[m]> maybe, I'm less familiar with that level of detail (so my default position is just "be suspicious" :D )
<ijager[m]> <dirbaio[m]> "most complete usb host I know of..." <- That's a nice example to have. It looks quite doable, also looking at the reference manual of the *G0C1. I am sure the STM32G0C is much nicer to work with than the LPC4337, the last time I did anything with USB 😆
<ijager[m]> I will give it a shot if they want to pay ;)
<FreeKill[m]> Yep reasonable. I think spinning will actually be fine here since it's just a periodic timer
cr1901_ has joined #rust-embedded
cr1901 has quit [Ping timeout: 240 seconds]
dangroshev[m] has quit [Quit: Idle timeout reached: 172800s]
birdistheword99[ has joined #rust-embedded
<birdistheword99[> Hi guys, quick question: I've seen a lot of embedded rust examples have incremental = false in the cargo.TOML file, which disables the incremental building. Why is this useful? does this not just make compilation longer? usualy this is combained with lto = 'fat' so i don't know if this is an artifact of that?
<dirbaio[m]> i'm not sure, but maybe incremental disables some optimizations?
<dirbaio[m]> maybe not if you have lto=fat, codegen-units=1. but maybe if you do have these then incremental doesn't actually make builds faster?
<birdistheword99[> <dirbaio[m]> "maybe not if you have lto=fat..." <- In all the examples (see Knurling Tools app-template for example: https://github.com/knurling-rs/app-template/blob/main/Cargo.toml) then yes, `lto=fat` and `codegen-units=1`
<birdistheword99[> although in their example template its disabled if on the dev profile, which doesn't do LTO
<birdistheword99[> * although in their example template its even disabled on the dev profile, which doesn't do LTO
<JamesMunns[m]> it's possible incremental builds could produce slightly slower/larger code, but that habit comes from many years ago when incremental was much more sketch than today
<JamesMunns[m]> tbh: it would be very cool to have someone do an investigation/blog post on whether it matters or not anymore
ryan-summers[m] has joined #rust-embedded
<ryan-summers[m]> Random question, but is there a way to get the defmt strings <-> id mappings outside of the ELF file so you can use it somewhere else, i.e. using defmt to send unformatted data over an ethernet connection
<ryan-summers[m]> * Random question, but is there a way to get the defmt strings \<-> id mappings outside of the ELF file so you can use it somewhere else, i.e. using defmt to send unformatted data over an ethernet connection?
<JamesMunns[m]> ryan-summers[m]: Not that I'm aware of, but I want to write something like that some day :D
<JamesMunns[m]> my suggestion would be to take defmt_print, and just hack it after loading the elf to dump the internal table to a TOML instead of starting decoding
<JamesMunns[m]> that's what I was planning to do as a prototype
<ryan-summers[m]> In theory it shouldn't be hard, right? defmt is just a mappng of strings and IDs, isnt it?
<dirbaio[m]> currently the decoder insists on eating an ELF yes
<ryan-summers[m]> It just packs them in the ELF debug info
<dirbaio[m]> you can just feed the elf to the decoder, even if you're doing it through ethernet or whatever
<JamesMunns[m]> IMO it would be very cool to add features to defmt_print that:
<JamesMunns[m]> * allowed you to dump info to a toml/json
<JamesMunns[m]> * allowed you to load the info from a toml/json instead of an elf
<dirbaio[m]> but yea a way to "separate" the table from the elf would be awesome
<ryan-summers[m]> I'll open an issue and look at it. Seems like a useful tool, since elfs are cursed black magic from a programming side of things ;)
<JamesMunns[m]> I thought I had found the table I would want to dump, lemme look again real quick to see if I can spot it
<JamesMunns[m]> My plan was to add serde to that type, then stick a conditional here to just exit and dump the contents: https://github.com/knurling-rs/defmt/blob/75fb317dab468a9fc786fe1f1da421b6b24e64d2/print/src/main.rs#L119
<JamesMunns[m]> (it LOOKED very attainable, it just never made it to the top of the todo list :D)
<ryan-summers[m]> I opened https://github.com/knurling-rs/defmt/issues/854, I don't expect this would be hard
<ryan-summers[m]> But also we shall see on my availability too. Lots of fun projects and never any time lol
<JamesMunns[m]> yeah, it's come up a ton, I think it'd be useful for a bunch of other tooling. I know some people who send all their defmt logs to some cloud log ingress server, and need to either go through a special decoding service and give the service all the elf files
<JamesMunns[m]> also on my todo list, in case anyone is interested:
<JamesMunns[m]> Use the same mechanism to contain postcard schemas, so you can do the same kind of thing to extract all the rx/tx message formats from the elf, so you can feed it to https://github.com/jamesmunns/postcard-dyn/
<JamesMunns[m]> (postcard-dyn is sort of like defmt-decoder: you give it schemas + bytes and it gives you back something like `serde_json::Value` you can print to a log store)
<ryan-summers[m]> Yeah tbh this just makes it so you have various TOML/JSON/YAML files, but that seems way more convenient than the whole elf
<JamesMunns[m]> yep
<ryan-summers[m]> We're looking at defmt for i.e. sending unformatted responses over MQTT. Not any real need, just curious to see how far we can push the bounds
<ryan-summers[m]> And I'm curious how awful/convenient it would be for an end-user
<JamesMunns[m]> (further down the yak shaving stack, I'd like to try replacing defmt's encoding with postcard, so you can log any T: Serialize as structured data, sort of like tracing+defmt)
<JamesMunns[m]> (the idea would be to make it easier to ingest into machine-readable formats instead of human/console readable formats)
<ryan-summers[m]> That would definitely be nice. Can defmt even handle something that impl Format?
<ryan-summers[m]> I guess that would be a bit odd given the name, but I'm talking about serializing some random complex struct. What does it do now?
<JamesMunns[m]> defmt has a more println/log style macro
<JamesMunns[m]> so you'd do `defmt::info!("Made ADC Reading: {=i32} {:?}", adc, Instant::now());`
<JamesMunns[m]> tracing actually supports either, if you put things before the string, they become "struct like" structured data, if you put it after the string, you can use them as formatted parameters (it does the formatting and sends the formatted string to the log collector)
<ryan-summers[m]> Ah yeah it can handle Format objects
<ryan-summers[m]> But how does it transfer them? Does it actually do the reformatting on the device and send over the formatted string or does it transfer over some serialized data?
<JamesMunns[m]> who is "it" here? tracing, defmt, or my imaginary postfmt?
<ryan-summers[m]> defmt
<JamesMunns[m]> tracing has it's own "Value" type that gets used (or you can tell it to just do Debug formatting), defmt doesn't format locally unless you use Debug2Format, postfmt would probably never format? not sure tho
<JamesMunns[m]> > Note: The implementation of #[derive(Format)] assumes that no builtin types are shadowed (for example by defining a struct u8;). This allows it to represent them more compactly.
<JamesMunns[m]> Hah, defmt cheats in a way that I was afraid to for my `postcard-forth` experiments :D
<JamesMunns[m]> the trick here is that you could do a match in the proc macro to avoid jumping through a generic, e.g. if the type is "u8", you could call `format_u8()` directly instead of a generic `format::<u8>()`, which probably saves you an indirection.
<JamesMunns[m]> BUT users can shadow builtin types, and proc macros only see the *tokens*, not the resolved types
<dirbaio[m]> yikes
<dirbaio[m]> why would `format::<u8>()` be an indirection tho?
<JamesMunns[m]> if you have something like:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/nSqlFyGufSqgcQueUmJIndnE>)
<JamesMunns[m]> (this was more relevant in postcard-forth where I make a list of ser/de steps, so it's not exactly an inlined function call)
<JamesMunns[m]> idk what defmt does, it probably has some shorter headers for primitive types
<JamesMunns[m]> they shortcut and call the encoding funcs directly for primitives, instead of calling `<u8 as Format>::format(self)` or something
henrik_alser[m] has quit [Quit: Idle timeout reached: 172800s]
Makarov has joined #rust-embedded
embassy-learner[ has joined #rust-embedded
<embassy-learner[> Hi guys! Noob question on Postcard...i am using a cobs accumulator to deserialize a simple struct like:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/DNFXcVJWLjiRDuGYnDyUDRdg>)
<JamesMunns[m]> is it exactly 256 bytes, or up to 256 bytes? You could use `heapless::Vec<u8, 256>`
<embassy-learner[> up to
<JamesMunns[m]> you could also use `&'a [u8]` instead, but that will make passing the struct around a little harder.
<embassy-learner[> yep i was thinking to something like that...
<JamesMunns[m]> (postcard-rpc doesn't support borrowed data atm either)
<embassy-learner[> i am just using postcard atm
<embassy-learner[> rpc is the future! :)
<JamesMunns[m]> oh, sorry, you can only borrow u8 like that, not any T
<JamesMunns[m]> so you could have `&'a [u8]`, but not `&'a [i32]` for example
<JamesMunns[m]> but you could have `heapless::Vec<i32, 64>` though.
<embassy-learner[> so creating a variable like Vec<u8,256> and doing something like...
<embassy-learner[> cobs_buf.feed::<varVec>(window)
<embassy-learner[> should work right?
<JamesMunns[m]> yes, if that's the only type you are receiving
<embassy-learner[> in this special case yes...
<JamesMunns[m]> note that the way enums work in Rust, that will always be ~264 bytes large, even if MyStruct is much smaller
<JamesMunns[m]> but in general you have to be careful not to feed postcard the "wrong kind of data" - the messages themselves have no way of telling what "kind" of data is there, so it can misinterpret the bytes if it's expecting to get a `heapless::Vec<u8, 256>` but you actually give it data for a `MyStruct`.
<embassy-learner[> cool ! In this way success will automatically deserialize the right one?
Henk[m] has quit [Quit: Idle timeout reached: 172800s]
<JamesMunns[m]> yes, if you send Message the same way.
<JamesMunns[m]> you can't just send MyStruct on the PC side and receive Message::Normal(MyStruct) on the MCU side
<embassy-learner[> I could try, maybe I start with easy case with two loops to see if I got everything ok
<JamesMunns[m]> so: both sides need to send and receive the same kind of data (always), or you could get corrupted data.
<embassy-learner[> JamesMunns[m]: Thanks a lot! Will play around...
adamgreig[m] has quit [Quit: Idle timeout reached: 172800s]
bartmassey[m] has quit [Quit: Idle timeout reached: 172800s]
jannic[m] has quit [Quit: Idle timeout reached: 172800s]
sourcebox[m] has quit [Quit: Idle timeout reached: 172800s]
Makarov has quit [Quit: Client closed]
Makarov has joined #rust-embedded
IlPalazzo-ojiisa has quit [Quit: Leaving.]
Makarov has quit [Ping timeout: 250 seconds]
Makarov has joined #rust-embedded
Makarov has quit [Client Quit]
Makarov has joined #rust-embedded
dne has quit [Remote host closed the connection]
dne has joined #rust-embedded
Makarov43 has joined #rust-embedded
Makarov92 has joined #rust-embedded
Makarov has quit [Ping timeout: 250 seconds]
Makarov43 has quit [Ping timeout: 250 seconds]
Makarov92 has quit [Ping timeout: 250 seconds]
rom4ik has quit [Read error: Connection reset by peer]
rom4ik has joined #rust-embedded
rom4ik has quit [Client Quit]
rom4ik has joined #rust-embedded
rom4ik has quit [Client Quit]
rom4ik has joined #rust-embedded