ChanServ changed the topic of #rust-embedded to: Welcome to the Rust Embedded IRC channel! Bridged to and logged at, code of conduct at
<re_irc> <firefrommoonlight> btw, "num_traits" has abs too
<re_irc> <dngrs (spookyvision@github)> it's been working out
<re_irc> <firefrommoonlight> it tears apart the float and analyzes the sign bit, which is presumably faster than checking for < 0
<re_irc> <adamgreig> "fn abs(x: f32) -> f32 { f32::from_bits(x.to_bits() & 0x7FFF_FFFF) }" is optimal on armv7
<re_irc> <adamgreig> shouldn't need to branch on the sign bit or analyse it
<re_irc> <adamgreig> compiles to a single "bic" instruction to clear the sign bit
<re_irc> <adamgreig> where are you seeing num_traits? it seems to have a default impl that does check for <0 or it can call libm::fabs
<re_irc> <Ryan Butler> dirbaio: I think that information is quite old and out of date. The current implementation has a panicking accessor, or a panic/bounds check free accessor that can be run after flatbuffer verification. See
<re_irc> <dirbaio> oh, wtf
<re_irc> <dirbaio> well I'd have loved to have that bit of info a while back when I evaluated serialization formats lol
<re_irc> <dirbaio> I discarded protobuf as too bloated and flatbuffers as unsafe for untrusted data, ended up rolling it manually 😂
<re_irc> <dirbaio> well I'd have loved to have that bit of info a few months back when I evaluated serialization formats lol
<re_irc> <dngrs (spookyvision@github)> dirbaio: did it have to be protobuf? (I'm quite happy with postcard)
<re_irc> <Ryan Butler> dirbaio: To backtrack at least a little, I'm not yet sure if using a verifier lets you skip the bounds checks
<re_irc> But the UB is definitely fixed, and a Rust verifier exists now
<re_irc> <dirbaio> dngrs (spookyvision@github): one requirement I had was "no alloc" while still being able to deserialize variable-length arrays
<re_irc> <Ryan Butler> * little on my statement, I'm not yet sure if using a verifier lets you skip the bounds checks because I haven't used the Rust Flatbuffer verifier since these changes were introduced.
<re_irc> <dirbaio> yes I know I could use heapless
<re_irc> <dngrs (spookyvision@github)> "heapless:Vec<{u16::MAX}>"
<re_irc> <dirbaio> in the end with manual deserialization it's easier to chomp the bytes and process the data as you go
* re_irc dngrs (spookyvision@github) runs
<re_irc> <dngrs (spookyvision@github)> yeah, streaming is nice
<re_irc> <dirbaio> because usually you need to iterate the deserialized stuff left-to-right anyway
<re_irc> <dngrs (spookyvision@github)> yeah
<re_irc> <dngrs (spookyvision@github)> you _could_ use postcard and stream individual "Item::Chunk" structs and end with "Iterm::Terminal" 😬
<re_irc> <dngrs (spookyvision@github)> * "Item::Terminal"
<re_irc> <dirbaio> and also needed a comaptible Go implementation (backend is go, devices are rust)
<re_irc> <dngrs (spookyvision@github)> my condolences
<re_irc> <dirbaio> Go is not that bad
<re_irc> <dngrs (spookyvision@github)> I find it frustratingly mediocre and full of strange pitfalls, but yeah it kinda works I guess
<re_irc> <dngrs (spookyvision@github)> there's just nothing in it that excites me in any way
<re_irc> <Ryan Butler> dirbaio: Go C FFI performance overhead go brrrrr
<re_irc> <dngrs (spookyvision@github)> yeah cgo is no fun
<re_irc> <dirbaio> hhehehe
<re_irc> <dirbaio> no cgo
<re_irc> <dirbaio> it's just your average CRUD JSON REST API backend
starblue1 has quit [Ping timeout: 272 seconds]
<re_irc> <dalepsmith> Go cross compiles amazingly well out-of-the box. Also, compiles seems to finish before I can take my finger off the enter key.
<re_irc> Rust is not bad, but I need to fuss with installing linkers and adding things with cargo and editing some files. Not bad, just a bit more stuff to fuss with.
<re_irc> <dalepsmith> I'd rather code in go than python.
starblue1 has joined #rust-embedded
<re_irc> <dalepsmith> But it's useless for embedded. And it's kinda quirky in area.
<re_irc> <ian_rees> I'm trying to measure RTT bandwidth, using rtt-target with "rtt_init_print!(BlockIfFull);" and cargo-embed for the terminal, but it still seems to be dropping prints - is that expected?
<re_irc> <ian_rees> Disregard, user error
gsalazar has joined #rust-embedded
<re_irc> <thejpster> I've done a bit of Go, but I'm inclined to agree with Amos wrt. implicit vs explicit. I like that Rust is explicit about a lot of things.
<re_irc> <K900> My work is mostly a Python shop, and some people were talking about trying Go
<re_irc> <K900> I basically spammed them with Amos posts until they stopped
<re_irc> <eldruin> 9names: Looks pretty cool! would you add a link to it to the newsletter (
<re_irc> <9names (> will do
Guest2 has joined #rust-embedded
starblue1 has quit [Ping timeout: 256 seconds]
starblue1 has joined #rust-embedded
<re_irc> <chrysn (> I'm thankful for the thorough discussion and classification of erase-based memory technologies that is happening at embedded-storage ( It is even useful when overhauling existing MTD APIs because it shows which weird things can come up.
<cr1901> 9names: It's funny you should mention this. A cargo generate template is actually exactly what I want:
<cr1901> cargo-generate is probably smart enough nowadays that a GH template and what's in the repo now can coexist if you don't want to maintain two repos
<re_irc> <allexoll> Is there a way to use a usb serial/acm device from a desktop platform with embedded-hal traits?
Guest2 has quit [Quit: Client closed]
rardiol has joined #rust-embedded
rardiol has quit [Client Quit]
<re_irc> <chrysn (> On the desktop platform the USB serial would be expressed as an OS serial device, which you can use through the linux-embedded-hal ( crate
rardiol has joined #rust-embedded
<re_irc> <9names (> I should revisit cargo-generate, it would make it easier to fix up project name/authors etc. I also need to check the docs to see if files can be excluded from the github template generator - users are currently saddled with the project readme, licence, contributor file, which is not awesome. If not possible, we should just remove those files - I'm sure we can make them accessible somewhere else.
<re_irc> <9names (> My biggest problem with the template is that for me it defaults to creating the repo under rp-rs, which is usually not what what I want! :)
<re_irc> <firefrommoonlight> adamgreig: I don't remember and maybe was wrong. Looking now, it's just the traits there, and probably points to libm if you use it without "default_features", which might use this?, which is what you posted
<re_irc> <adamgreig> ah yea, nice. for the f32 version
<re_irc> <firefrommoonlight> That's your version!
rardiol has quit [Quit: - Chat comfortably. Anywhere.]
<cr1901> 9names: Feel free to use msp430-quickstart for inspiration (see cargo-generate.toml and Cargo.toml for conditional code inclusion)
<cr1901> Also, rp-hal works like a charm :)
<cr1901> (although I have to manually run elf2uf2-rs and then copy the file... I'm not spending time debugging why it doesn't work)
jackneill has quit [Remote host closed the connection]
jackneilll has joined #rust-embedded
<re_irc> <chmanie> James Munns: I am aiming to improve the max11300 driver implementation we talked about. I'd like to add the typestate transitions between the pin/port modes after all. Thing is that would be 13*12=156 state transitions that I'd have to add. Is there an easy way for that (I'm thinking about using the "seq!" macro but even then it's quite a mess. Did you have something in mind for that when we talked about it earlier?
<re_irc> <James Munns> That's a lot of state!
<re_irc> <James Munns> I don't generally have anything for that (off the top of my head), sadly.
<re_irc> <James Munns> Where does the 13 * 12 come from?
<re_irc> <chmanie> There are 13 modes. That means I'd have to add 12 state transitions into the other modes for each of them
<re_irc> <James Munns> oh, you can often make those a blanket impl, if any-to-any transitions are valid
<re_irc> <chmanie> (given a mode cannot be transitioned into itself)
<re_irc> <James Munns> lemme make you an example again
<re_irc> <chmanie> Oh yeah, that'd be wonderful!
<re_irc> <James Munns> it wont protect you from going delta -> delta, but that's probably fine in most cases
<re_irc> <James Munns> (you should still have the sealed trait bounds on the type/impl, I left them out here because lazy)
<re_irc> <chmanie> Yes, I think that's not super important
<re_irc> <James Munns> If there is some complicated transition (e.g. going from Beta to Delta is different than Alpha to Delta), then this may not work out, or you may need to go back to some "common" state first
<re_irc> <James Munns> But if you can just issue "from any mode to mode X" commands somehow, then this means you only need "to_X" function per destination state.
<re_irc> <chmanie> No, this should work fine, all transitions are pretty much the same
<re_irc> <James Munns> Nice!
<re_irc> <chmanie> Thank you so much, I'll try that!
<re_irc> <James Munns> You can read that impl as roughly "From any mode/state 'N', we can transition into a new given state (constrained by the return type of each function"
<re_irc> impl Container<Gamma> {
<re_irc> <James Munns> Then you can do things like have:
<re_irc> }
<re_irc> fn do_gamma_things(&mut self, data: &[u8]) { /* ... */ }
<re_irc> <James Munns> to enable functions ONLY for a given mode
<re_irc> <chmanie> Yes, that's exactly what I had in mind. Perfect!
<re_irc> <chmanie> This is much nicer as I can also prevent pins from being configured twice by always consuming them (as is done in most of the HALs)
<re_irc> <James Munns> If you have some common modes, like Alpha and Beta can both do input things, you could have another sealed trait, like:
<re_irc> impl InputCapable for Alpha {}
<re_irc> trait InputCapable { }
<re_irc> impl InputCapable for Beta {}
<re_irc> <chmanie> YAS
<re_irc> <chmanie> That's what I was missing, too
<re_irc> <chmanie> Thanks you, all super helpful
<re_irc> <chmanie> * Thank
<re_irc> <James Munns> By the way, this concept of using 'empty' traits as bounds are called "Marker Traits"
<re_irc> <James Munns> ("Send" and "Sync" are the most common marker traits you know)
<re_irc> <James Munns> And using sealed traits + marker traits, you can often limit capability in ways that help constrain things, like this.
gsalazar_ has joined #rust-embedded
<re_irc> <chmanie> Right. This makes a lot of sense.
<re_irc> <James Munns> Though, beware, all of dirbaio's warnings about "monomorphization bloat" still apply here!
<re_irc> <James Munns> Just because they are grouped into a single impl block, rustc will generate two versions of "get_input" here (one for Alpha, one for Beta)
<re_irc> <James Munns> (or if you do your full 13 -> 12 transitions, you WILL end up with 156 impls compiled into your binary)
<re_irc> <James Munns> THAT BEING SAID
gsalazar has quit [Ping timeout: 240 seconds]
<re_irc> <James Munns> most people will only use a few of them, so the "dead code" will go away, and in many cases, it could be possible that LTO will de-monomorphize them, or there are some manual ways to do this
<re_irc> <chmanie> Yes, I would expect most use cases to really remove almost all of them
<re_irc> <chmanie> And if you end up needing them, well, then you need them ;)
<re_irc> <James Munns> "Manual demonomorphizing" would look something like this:
<re_irc> <James Munns> e.g., make the "monomorphized" functions very small shims on top of larger functions
<re_irc> <James Munns> so that way the "shims" multiply, but the "core functionality" only is produced once (here I marked it with "#[inline(never)]" to make sure the compiler doesn't undo that with inlining).
gsalazar__ has joined #rust-embedded
<re_irc> <chmanie> James Munns: Nice!
<re_irc> <James Munns> Still: I recommend you include a "RuntimeChecked" mode, in case someone wants to be very dynamic with what they are doing!
<re_irc> <dirbaio> for code size bloat it often helps to implement the logic in non-generic, like this
<re_irc> fn set_state(&mut self, channel: u32, mode: Mode);
<re_irc> fn read(&mut self, channel: u32) -> u32;
<re_irc> and then build the public generic typestate API on top of that
gsalazar_ has quit [Ping timeout: 272 seconds]
<re_irc> <chmanie> Yes, that is necessary anyways, to support sequential reading/writing (with auto incrementing of the register addresses, etc.)
<re_irc> <dirbaio> this way the non-generic fns are shared, and the generic fns are just a call through to the non-generic ones, which gets inlined
<re_irc> <James Munns> Well, you DON'T want them to be inlined (if you care about code size) tho
<re_irc> <James Munns> but, I agree with the approach, even if you don't do it for code size! It helps keep the logic more clear
gsalazar_ has joined #rust-embedded
<re_irc> <dirbaio> the generic fn gets inlined into user code, but that's just one single fn call
<re_irc> the non-generic fn stays non-inlined
<re_irc> <James Munns> ah, gotcha
<re_irc> <James Munns> I was imagining "non-generic function is inlined into generic method"
<re_irc> <James Munns> (which is why I put that "#[inline(never)]" there in my example)
gsalazar__ has quit [Ping timeout: 256 seconds]
<re_irc> <James Munns> I'm looking forward to your blog post chmanie, you're asking all the right questions!
<re_irc> <chmanie> dirbaio: Just to understand correctly, in my case I would also pass the spi bus object along to these functions you described there?
<re_irc> <chmanie> Well, a mutable reference to it
<re_irc> <James Munns> (not dirbaio), but here you would have two choices (I think):
<re_irc> <dirbaio> yes, or have them in your "main" struct if you have it, either works
<re_irc> <chmanie> Haha, yeah I'm also looking forward to that blog post :)
<re_irc> <James Munns> Use another generic like I did in my example
<re_irc> <James Munns> or use an Extension Trait to add that functionality
<re_irc> <James Munns> both will get monomorphized, BUT you really only expect the user to use one kind of SPI port across their whole project.
<re_irc> <James Munns> If they don't, then those monomorphizations multiply too!
<re_irc> <James Munns> so 3 spi ports * 156 transition methods, if they go all-out :D
<re_irc> <dirbaio> nooooo not extension traits :D
<re_irc> <James Munns> (yeah, I'd favor a method over extension traits too)
<re_irc> <dirbaio> I personally find them very confusing as a user, to have to import some random trait to be able to call methods
<re_irc> <chmanie> Ah "main" struct being the one that holds the above functions basically
<re_irc> <dirbaio> and they're not great for docs either, as the methods get "hidden" in the docs into the impls section
<re_irc> <chmanie> Got it, I think I'm set
<re_irc> <James Munns> You don't want it on "Container" in my example
<re_irc> <James Munns> because if you do it on "Container<N, SPI>", it'll get monomorphized too
<re_irc> <James Munns> (that's why I had a separate function, only generic over SPI, so it doesn't get monomorphized for N)
<re_irc> <James Munns> So if you have 12 "N"s, and only one "SPI", you'll only get one "do_expensive_thing" in my example
<re_irc> <James Munns> Re: The blog post, I'm super happy to help review/edit, or fill in any gaps on stuff you aren't sure about! I really would love to have a good reference to point people too (and it might be a good way to update the embedded book on it!)
<re_irc> <James Munns> (especially with regard to "best practices" or "tradeoffs", since I don't think we discuss that currently, but you can tell dirbaio and I are full of battle stories and opinions about them :) )
<re_irc> <chmanie> James Munns: Thank you! I’ll do my best to condense all my learnings here.
<re_irc> <James Munns> 💪🧠 you got this!
crabbedhaloablut has quit [Write error: Connection reset by peer]
crabbedhaloablut has joined #rust-embedded
<re_irc> <monacoprinsen> Are there any good wifi and bluetooth modules that you can use in combination with an STM32 board?
<re_irc> Don't need it to be all than an ESP32 is but it might not exist so many other options....
<re_irc> <James Munns> For bluetooth, nrf5x is probably a good choice
<re_irc> <James Munns> I don't know many BT+Wifi in one options, other than ESP32
<re_irc> <monacoprinsen> Need wifi as well
<re_irc> <monacoprinsen> Ok i suspected that, Thanks!
<re_irc> <James Munns> Yeah, I'm not aware of any combo modules (accessible at low quantities) other than ESP32. If you're a big company, broadcom and others might be an option, but that's in the 1M MOQ range
<re_irc> <monacoprinsen> Is it better to use separated modules instead than both in one?
<re_irc> <dirbaio> if you're getting an esp32 you might as well run everything in the esp32
<re_irc> <James Munns> monacoprinsen: It depends on a lot of stuff, unfortunately. That being said, you probably can't out-price the ESP32 either
<re_irc> <dirbaio> unless you need the stm32 for better io or something
<re_irc> <James Munns> Separate modules can also be complicated, since you have to prevent them from transmitting over eachother (this is typically called "coexistance")
<re_irc> <monacoprinsen> Are there any good HAL crates for the esp32 with rust?
<re_irc> <James Munns>
<re_irc> <James Munns> They are very active in adding rust support now!
<re_irc> <James Munns> (AFAIK, the only "first party" to be doing so)
<re_irc> <monacoprinsen> Exciting!
<re_irc> <James Munns> Also check out (, lots of helpful folks there.
<re_irc> <monacoprinsen> Will defenetky do, thanks for the help
<re_irc> <monacoprinsen> * definitely
rardiol has joined #rust-embedded
gsalazar_ has quit [Quit: Leaving]
gsalazar has joined #rust-embedded
<re_irc> <Lachlan Sneff> Is there a crate with bluetooth traits that can be used to create hardware independent bluetooth apps?
Shell has quit [Quit: ZNC 1.8.2 -]
Shell has joined #rust-embedded
jringstad__ has joined #rust-embedded
Shell has quit [Quit: ZNC 1.8.2 -]
Amadiro has quit [Ping timeout: 250 seconds]
Shell has joined #rust-embedded
<re_irc> <James Munns> Not that im aware of, but I think thats what the HCI layer is for
<re_irc> <Lachlan Sneff> HCI?
<re_irc> <James Munns> Bluetooth Host Controller Interface
<re_irc> <dirbaio> there's this
<re_irc> <dirbaio> but it's quite bloated: event deserialization ("Event::new()") alone is ~40kb
<re_irc> <dirbaio> I guess if you want to have good code size you need to work with "#[repr(c)]" structs mirroring the actual wire format...