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 joined #rust-embedded
<dirbaio[m]> `llvm-objdump -x dedup.elf | grep -v 00000000 | grep -v defmt | sed -n '/^SYMBOL TABLE:$/,$p' | cut -d " " -f 2- > dedup.txt `
<dirbaio[m]> yay
jiande2020 has quit [Quit: Ping timeout (120 seconds)]
jiande2020 has joined #rust-embedded
<dirbaio[m]> so... a bunch of functions get a bit bigger. 20 bytes here, 40 bytes there...
<JamesMunns[m]> cargo show-asm?
<dirbaio[m]> too much asm :D
<JamesMunns[m]> you can pick the functions by name
<JamesMunns[m]> like cargo show-asm --release -- name-of-symbol, iirc
IlPalazzo-ojiisa has quit [Quit: Leaving.]
<dirbaio[m]> ... I can't see a pattern
<dirbaio[m]> it's just random slightly different decisions made by the inliner
<JamesMunns[m]> yep, could be different debuginfo/path affecting optimizer juice
<dirbaio[m]> it just seems to want to inline more with my branch
<dirbaio[m]> which makes the binary bigger
<dirbaio[m]> but putting inline(never) doesn't help
<dirbaio[m]> * but putting inline(never) doesn't help because then it doesn't inline other stuff that would be helpful to inline
<JamesMunns[m]> did your branch change any #[inline] tags?
<JamesMunns[m]> or #[inline] vs #[inline(always)]?
<dirbaio[m]> nope
<JamesMunns[m]> 🔮
<JamesMunns[m]> look into the optimizer
<dirbaio[m]> well actually
<dirbaio[m]> main has #[inline] on Vec methods which forward to VecView, then no #[inline] in the VecView methods
<dirbaio[m]> while i've moved the "meat" of the methods back to Vec, but kept the #[inlin]e
<dirbaio[m]> s/#/#\/, s/inlin/inline/
<dirbaio[m]> yep removing some of the #[inline]s fixes it
<dirbaio[m]> grrrrrr
<dirbaio[m]> okay let's restore all the #[inline]s as they were in v0.8
<dirbaio[m]> okay i've optimized a bit
<dirbaio[m]> I get this now
<dirbaio[m]> it's a bit less bad
<dirbaio[m]> 0.02% bloat since v0.8, it's well within the margin of error
crabbedhaloablut has quit []
ubernerd[m] has quit [Quit: Idle timeout reached: 172800s]
SArpnt[m] has quit [Quit: Idle timeout reached: 172800s]
<jannic[m]> <dirbaio[m]> "Iirc that one had bugs where..." <- Do you remember more about that? It should not happen because the low level code is written in assembly. But optimizers are strange.
<ivmarkov[m]> <dirbaio[m]> "and my other concern is code..." <- dirbaio: (So sorry for the ping. It is really difficult to follow the `SliceVec` conversation that had happened yesterday as it is intermingled with other stuff... maybe we need threads?)... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/YwlLBGrXPPTrBPbtjRoGwUpS>)
<ivmarkov[m]> * dirbaio: (So sorry for the ping. It is really difficult to follow the `SliceVec` conversation that had happened yesterday as it is intermingled with other stuff... maybe we need threads?)... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/qVYQlrBzKTKfCXfRUhvBJExy>)
<ivmarkov[m]> James Munns Sorry for the ping and only if you know it up front, otherwise I'll test. If I do:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/HQgzVPYMoHtvhZMneEROZhFs>)
<ivmarkov[m]> * James Munns Sorry for the ping and only if you know it up front, otherwise I'll test. If I do:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/qokeYRKZakTOHLClGSpUgDkT>)
<ivmarkov[m]> * James Munns Sorry for the ping and only if you know it up front, otherwise I'll test. If I do:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/zTbPSuTINlBKuIOiselgbcow>)
<ivmarkov[m]> * James Munns Sorry for the ping and only if you know it up front, otherwise I'll test. If I do:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/YSOwKfQFNVTsPInDOrwWXIzj>)
<ivmarkov[m]> * James Munns Sorry for the ping and only if you know it up front, otherwise I'll test. If I do:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/IHgtXHEWQwVDzXskrQojvNRO>)
<ivmarkov[m]> * James Munns Sorry for the ping and only if you know it up front, otherwise I'll test. If I do:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/ZNuoDbBuKZJyHTXrrsTGJEQh>)
<ivmarkov[m]> * James Munns Sorry for the ping and only if you know it up front, otherwise I'll test. If I do:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/poIigZBQDnkPFyhamxkiCbKo>)
<JamesMunns[m]> <ivmarkov[m]> " James Munns Sorry for the..." <- > <@ivmarkov:matrix.org> James Munns Sorry for the ping and only if you know it up front, otherwise I'll test. If I do:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/poeuBMpGinTYDKJrcynywuPX>)
<FrreJacques[m]> May play around with embedded-hal-async teached me that I overcomplicated my question from two weaks ago with the attempt to create a struct that has a field with a type that implements a trait.
<FrreJacques[m]> Since the traits in async are async, I cant create a trait object. But I learned that also for zhe non async case it would be completely fine to have the struct completely generic and just define in the trait I want to create, what traits the generics need to implement.
<dirbaio[m]> <jannic[m]> "Do you remember more about that?..." <- yea it does look good. I think I'm confusing it with another impl that didn't do asm. maybe an early embassy one. sorry for the confusion!
<dirbaio[m]> <ivmarkov[m]> "dirbaio: (So sorry for the ping...." <- > The verdict (kind of) for now is that SliceVec won't be because it is difficult to introduce it in the post 0.8 codebase without a lot of code duplication?
<dirbaio[m]> yeah, mostly.
<dirbaio[m]> dirbaio[m]: also because it can't work at the same time as VecView
<dirbaio[m]> dirbaio[m]: like
<dirbaio[m]> dirbaio[m]: my hopes were that you can either do
<dirbaio[m]> Vec<T, N> -> VecView<T>
<dirbaio[m]> SliceVec<T> -> VecView<T>
<dirbaio[m]> dirbaio[m]: ie VecView<T> type-erases *both* the const generic, and the fact whether you chose to use Vec or SliceVec
<dirbaio[m]> dirbaio[m]: but that's not possible
<ivmarkov[m]> dirbaio[m]: Fair enough, thanks.
<ryan-summers[m]> Hmm, somewhat of a tangent, but yesterday the discussion about UB behavior when having global statics made me realize this might be one of those pesky things that would make me somewhat hesitant to use Rust for sensitive projects. If it's that easy to invoke UB, its a little nerve-wracking
<ryan-summers[m]> By sensitive, I mean safety critical etc.
<dirbaio[m]> I don't think Rust is more UB-happy than C/C++ here tho?
<dirbaio[m]> using uninit data in C/C++ is UB too
<ryan-summers[m]> Doch. I think its a lot easier to invoke Rust UB with pointer aliasing etc.
<ryan-summers[m]> And uninitialized refs etc. At least in C/C++ its easy to get the runtime to ensure everythings initialized for you. The second you use a custom linker section with the RT in Rust you're opening up the footgun box it seems
<ryan-summers[m]> Maybe this could be addressed at the RT layer to support custom sections?
<dirbaio[m]> ivmarkov[m]: it's still possible to add it, it'd just be "incompatible" with VecView
<JamesMunns[m]> ryan-summers[m]: Yeah, we discussed this yesterday
<JamesMunns[m]> Any time you are writing linker scripts, it is wildly unsafe, because you are acting as a "system integrator", and are responsible for upholding the invariants of the language.
<JamesMunns[m]> this is the same in C and C++.
<ryan-summers[m]> Yeah and I totally think its fair to be wildly unsafe there, but once you're at the end user stage, you should assume your RT did things properly for you
<JamesMunns[m]> Same for managing the "rt" or "crt0" of a language.
<ryan-summers[m]> But right now it'll happily leave custom linker sections as totally UB
<JamesMunns[m]> ryan-summers[m]: cortex-m-rt defines its integration requirements.
<dirbaio[m]> dirbaio[m]: have you looked into VecView? does it work for your use case? why/whynot?
<ryan-summers[m]> I get that they may define the range of what they do, but the fact of the matter is in C/C++ you don't have to think about this, and now suddenly with Rust you do
<JamesMunns[m]> ryan-summers[m]: I disagree with this assertion
<JamesMunns[m]> you DO have to care.
<dirbaio[m]> dirbaio[m]: the difference vs SliceVec is you have to put the entire Vec in the weird-ram with len+data, vs just data.
<JamesMunns[m]> the "environmental" requirements for Rust are generally even simpler than C++, and approximately the same as C.
<ryan-summers[m]> Hmm I was going to say that C/C++ zero-init all custom linker sections, but I don't think they do
<JamesMunns[m]> ryan-summers[m]: that's a property of the `crt0` you choose, not the language
<JamesMunns[m]> your VENDOR may define a more flexible setup routine than cortex-m-rt, that's not a property of the language
<JamesMunns[m]> that's why that code is in asm, not rust: It's not possible to guarantee in C, C++, or Rust.
<ivmarkov[m]> dirbaio[m]: I haven't because so far I was not really interested in erasing the `N` const generic from my types anyway.
<ivmarkov[m]> The question is more like: where I currently use my own `SliceVec<T>` simply because I need something which looks like a `Vec` to which I can pass `&'a mut [MaybeUninit<T>; N]` ... whether I can use something else. Given that the memory I'm working with only reliably supports `.noinit` _and_ C-level malloc/free-like APIs
<JamesMunns[m]> (within a single executable)
<ryan-summers[m]> It'd be nice if the language constructs made it easier to not invoke UB then, so I see where the removal of static mut is going to be helpful
<JamesMunns[m]> ryan-summers[m]: agreed, but the language can't cover all "system" details: nothing north of assembly does.
<ryan-summers[m]> In any case, this is all purely theoretical, I agree with the points you're outlining here though James
<ivmarkov[m]> ivmarkov[m]: I just want to allocate (via "malloc" a large *mut [MaybeUninit<T>; N]` then leak it and pass it to my `SliceVec` at program startup. That's all.
<ryan-summers[m]> Yeah I get that, mainly thinking aloud some shower thoughts I had after the discussions yesterday
<JamesMunns[m]> Yep! Just want to push back on some pretty serious points :)
<ivmarkov[m]> * I just want to allocate (via "malloc") a large `*mut \[MaybeUninit<T>; N]`then leak it and pass it to my`SliceVec\` at program startup. That's all.
<ivmarkov[m]> * I just want to allocate (via "malloc") a large `*mut [MaybeUninit<T>; N]`then leak it and pass it to my`SliceVec\` at program startup. That's all.
<ivmarkov[m]> * I just want to allocate (via "malloc") a large `*mut [MaybeUninit<T>; N]`then leak it and pass it to my`SliceVec` at program startup. That's all.
<JamesMunns[m]> It's the "spanish flu" problem: we need to be careful that just because Rust is the only ecosystem COMMUNICATING that UB is possible, we don't get it twisted that it is any different in C or C++.
<JamesMunns[m]> it's just "head in the sand" different.
<ryan-summers[m]> Thanks for humoring me and clarifying things. I agree that I actually no longer think there's a huge difference between C/C++ and Rust. I suspect my consternation arises from the fact that Rust has more contracts that must be upheld for data (largely because of the memory safety stuff) than C/C++ does, but that might just be my perception and not represent reality
<ivmarkov[m]> dirbaio[m]: Yes, that's it 100%.
<JamesMunns[m]> ryan-summers[m]: At least with respect to "initialized statics", in the conversation from yesterday, Rust has no requirements beyond C, afaik.
<ryan-summers[m]> Specifically around pointer provenance etc. and other complex topics that I actively want to avoid. In C/++, I can pretty much just zero-init everything and be fine
<ivmarkov[m]> ivmarkov[m]: I can do "malloc", then zero the resulting MaybeUninit and treat is as `Vec` though.
<ryan-summers[m]> Granted, there's no memory safety so yeah
<ivmarkov[m]> ivmarkov[m]: Because a `Vec` seems to be compatible with an all-zero chunk of mem which is properly aligned
<JamesMunns[m]> Also note that pointer provenance:
<JamesMunns[m]> * isn't formally agreed upon (e.g. stacked borrows vs tree borrows)
<JamesMunns[m]> * is overly conservative
<JamesMunns[m]> so, I DO try and make sure that we keep the ecosystem honest, even in the most restrictive provenance models
<ivmarkov[m]> ivmarkov[m]: So I'll get a `&mut Vec` after these tricks, which might be good enough!
<ryan-summers[m]> Trust me, I don't even have a basic definition of what it is and would like to keep it that way if possible 😅
<ivmarkov[m]> * a `&static mut Vec`
<JamesMunns[m]> often when I say "Is UB", I mean "Would be considered UB under the currently defined strict provenance models"
<ivmarkov[m]> * a `&'static mut Vec`
<JamesMunns[m]> and fwiw, I think the ERGONOMICS of writing "correct unsafe code" could be better in Rust, for sure. Gankra has a really good post about this. Doing it right does require:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/vpjimpGjVMmGxCQKGWVbmLew>)
<JamesMunns[m]> https://faultlore.com/blah/fix-rust-pointers/ is a very good read, btw.
<ryan-summers[m]> Thanks, will definitely give that a read
<ivmarkov[m]> <JamesMunns[m]> "> <@ivmarkov:matrix.org> James..." <- (Moving to a dedicated thread because having > 2 conversations in the main channel is next to unbearable :) )
IlPalazzo-ojiisa has joined #rust-embedded
<ryan-summers[m]> Damn you, you've taught me pointer provenance
<ryan-summers[m]> * pointer provenance😂
<ryan-summers[m]> * Damn it, you've taught me pointer provenance😂
<FreeKill[m]> Those posts broke my brain
<JamesMunns[m]> And to be clear, this is definitely like "research level understanding": the goal is to make much simpler and easier to follow rules for "end users".
<ryan-summers[m]> At some point as a software developer you realize that everything we use is just a giant, fragile house of cards and accept it
<JamesMunns[m]> This is kinda the response to the industry and optimizing compilers being 50 years of Vibes, and realizing it's better to more fundamentally define important things we rely on.
<ryan-summers[m]> Honestly the internet as a whole is somewhat of a miracle to me that any of it works
<ryan-summers[m]> Yeah the first post does a nice job of caveating that while they're saying they're "fast and loose", they're far more rigorous than anyone else until this point still. I like the perspective taken
<ryan-summers[m]> Welp, officially not getting much actual work done today because of this. Thanks for the links though James, this is intriguing reading
<JamesMunns[m]> ryan-summers[m]: I'm a little less nihilistic about it, but it's good to realize there is no magical architect making sure everything is totally correct, any more than any other body of science :)
<JamesMunns[m]> ryan-summers[m]: happy friday :)
<ryan-summers[m]> Well you also have to take the pragmatic approach that we've already built lots of stuff that mostly works most of the time. So it definitely has worked out to an extent. And I like that we're still trying to improve on that with i.e. new languages that solve lots of the problems that cause things to only mostly work
<JamesMunns[m]> But LIKE other (physical) sciences: the more we understand and establish rules, the more interesting *second order* things you're allowed to do or not do.
<JamesMunns[m]> Like, Rust HAS strict rules because it means you can make sound abstractions over them.
<JamesMunns[m]> (computer science is just fun because we also get to invent how the underlying universe behaves, though often only indirectly: it's still down to the whims of hardware and compiler developers and hardware/system integrators to actualize it)
<JamesMunns[m]> but we've definitely invented further than we've formalized, which is hilarious, for sure.
<ryan-summers[m]> But then as a computer engineer you realize that the laws can be broken entirely once in a blue moon because of random silicon defects and/or acutal physics (i.e. single bit events)
<ryan-summers[m]> s/acutal/actual/
<JamesMunns[m]> yep :)
<JamesMunns[m]> that's why programming languages work on abstract models!
<JamesMunns[m]> it's impossible to incorporate the full extent of certain possibilities, so compilers/languages have to draw the line somewhere at "that can't ever happen"
<JamesMunns[m]> (and it's up to hardware designers/integrators to make that so, or the language says "welp all bets are off", this is why safety critical systems often require integrity checks and watchdogs!)
<ryan-summers[m]> Yeah because things almost always inevitably go sideways somehow. Fault tolerance is really fun to reason about. For medical devices its only single fault tolerant, but when I was doing space stuff its two, and two fault tolerance is much harder than one
<ryan-summers[m]> * Yeah because things almost always inevitably go sideways somehow. Fault tolerance is really fun to reason about. For medical devices its only single fault tolerant, but when I was doing space stuff it was two, and two fault tolerance is much harder than one
<FreeKill[m]> I also find it interesting in fault tolerance how the limits change depending on if it's a fault you can detect or not - at least for SIL
<ryan-summers[m]> FreeKill[m]: Whatcha mean by this? I'm unfamiliar with SIL
<FreeKill[m]> At least when I was designing fault tolerance stuff in the marine industry
<FreeKill[m]> The acceptable occurrence rates were higher if it was a fault you would know happened
<ryan-summers[m]> Ah yes, that is definitely a thing
<FreeKill[m]> So if a valve gets stuck open and you get an alarm, then that can be a 1 in 10^6 event, for example
<FreeKill[m]> But if it gets stuck and is just silently wrong, that's only 1 in 10^8, for example
<FreeKill[m]> (numbers made up)
<ryan-summers[m]> Yeah formal risk analysis is a weird business for sure. Especially because so much of the data is extrapolated
<birdistheword99[> This feels like I'm committing a despicable crime to get around an uninitialized section, but is this OK or a big no-no? I am only using sram3 for various buffers (Ethernet and I2C4), the linker is set up to only use AXISRAM for the rest of it, so it would only be for specfically marked and linked sections:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/VWgmGYEHCVGvBOyHZcBTDbYh>)
<JamesMunns[m]> yes, this is crimes and UB
<birdistheword99[> s/preinit/pre_init/
<JamesMunns[m]> I don't have a better solution for you (other than I need to fix groundedcell to allow anything to be Sync, or you could copy/fork grounded to do that).
<birdistheword99[> I am using `MaybeUnint` to defer initialisation until runtime, but I understand your points.... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/WYtSTQDSFxgSkpPHFbydkgws>)
<JamesMunns[m]> > so surely this ensures proper provenance... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/LJLRKKMWjpesSyPMSNPcsOaS>)
<JamesMunns[m]> additionally, you are mutably aliasing that section of memory, both PACKETS and your pointer derived from _sram3_start are pointing to the same memory range
<JamesMunns[m]> additionally, you are creating a mutable pointer from a `&u8`, which is UB
<JamesMunns[m]> * mutable pointer and writing through from a
<JamesMunns[m]> Agreed that since PACKETS is maybeuninit: it's not UB to init it at runtime. It is UB how you are currently init'ing it tho.
<JamesMunns[m]> I know I am being pedantic and not actually useful towards what you want to do: but I do want to be as accurate as possible.
<JamesMunns[m]> (this is WHY I'm working on grounded: this stuff is subtle and important to get right)
<ivmarkov[m]> <ivmarkov[m]> "(Moving to a dedicated thread..." <- No sorry - was about to ask whether you have / have thought of implementing a `Box` which is generic over its (de)-allocator. So that it can be used with any pooled implementation, including with a raw non-pooled `malloc`/`free` based (de)allocator. But I have something which at least type-checks in the meantime (based on my previous adventures with writing a custom `Box` for
<ivmarkov[m]> Espressif's SPIRAM memory - as I'm also trying to enter the "roll your own custom allocator business :p ):
<ivmarkov[m]> * No sorry - was about to ask whether you have / have thought of implementing a `Box` which is generic over its (de)-allocator. So that it can be used with any pooled implementation, including with a raw non-pooled `malloc`/`free` based (de)allocator. But I have something which at least type-checks in the meantime (based on my previous adventures with writing a custom `Box` for Espressif's SPIRAM memory - as I'm also trying to
<ivmarkov[m]> enter the "roll your own custom allocator" business :p ):
<JamesMunns[m]> ivmarkov[m]: > <@ivmarkov:matrix.org> No sorry - was about to ask whether you have / have thought of implementing a `Box` which is generic over its (de)-allocator. So that it can be used with any pooled implementation, including with a raw non-pooled `malloc`/`free` based (de)allocator. But I have something... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/rwFizSdOxXhYfTahjtTTmPSF>)
<JamesMunns[m]> * phew, I can't wrap my head around that. Feel free to ping me about that later, but "how you deallocate" is a property of the container. It sounds like you are re-inventing the `Allocator` trait, which is the hidden `A` parameter of `Box<T, A>`
<JamesMunns[m]> JamesMunns[m]: (sorry, deallocation is a property of the CONTAINER, the destructor is a property of the ITEM)
<ivmarkov[m]> ivmarkov[m]: The problem with the `Allocator` trait is that it is not typified by `T` (as in `Box<T, A>`). It seems they abandoned this idea already in 2017 (was looking at the RFC Rust issue a couple of hours ago)
<ivmarkov[m]> ivmarkov[m]: (Ditto for the deallocator)
<ivmarkov[m]> ivmarkov[m]: And yes, my piece of code has the deallocator as a property of `Box`. Not asking to review or anything, just to check if I'm inventing the wheel (again).
<ivmarkov[m]> <ivmarkov[m]> "And yes, my piece of code has..." <- Here, JFYI: https://github.com/rust-lang/rust/issues/32838#issuecomment-270480959
<birdistheword99[> <JamesMunns[m]> "I know I am being pedantic and..." <- No this is great info, I wouldn't have asked the question if I didn't think it smelled funny! I come from an embedded C background, and although there are 'Best Practices' and the MISRA standard etc, its way too easy to take UB shortcuts, and end up picking up some bad habits!
<birdistheword99[> I'm trying to introduce embedded rust at the place I work because the projects I have been a part of in the last few years have all had at least 1 or 2 awkward horrible runtime-bug which was hard to replicate and would have been prevented by the things that the rust compiler enforces
<birdistheword99[> s/bug/bugs/
<birdistheword99[> So I am invested in knowing the 'right' way to do it, not just take more shortcuts!
<ryan-summers[m]> I would probably do section init in asm blobs
<ryan-summers[m]> As an aside, does cortex-m-rt expose a method along the lines of "init section" where you just pass start, end, and data pointers?
<JamesMunns[m]> ryan-summers[m]: not afaik, other than maybe it has a stable asm label name
<JamesMunns[m]> JamesMunns[m]: and "init" can mean either bss zero or data copying
<JamesMunns[m]> but really, ALL BSS and DATA sections should be initialized before the first Rust code runs
<ryan-summers[m]> Yeah, so could you put this in the #[pre_init] hook?
<JamesMunns[m]> at least, as far as I am aware (this is probably grey-ish area: but it would definitely be UB to use an uninitialized static)
<ryan-summers[m]> Ah but its still rust code...
<JamesMunns[m]> yeah, my opinion is that we shouldn't have rust pre_init
<JamesMunns[m]> it should be an asm-only hook
<ryan-summers[m]> Yeah so my use case would be to initialize ITCM: https://github.com/quartiq/stabilizer/blob/main/src/hardware/setup.rs#L158 (yes I know this is probably UB, we have an issue to look at it)
<ryan-summers[m]> Which is very similar to the question above ^
<JamesMunns[m]> how you're doing it is probably UB: we used to do that in c-m-rt, and moved away because if it
<JamesMunns[m]> (for the reasons I mentioned today: you have a 4-byte static and are writing more than 4 bytes to it)
<ryan-summers[m]> Hmm but I don't think we are. We conjure up a slice from raw parts for writing
<ryan-summers[m]> But there is the problem that the dst slice is not initialized, so we have a slice pointing to uninit data, which is UB
<JamesMunns[m]> the pointer derive from the start static has the provenance of the static
<JamesMunns[m]> e.g. no more than 4 bytes is "inbounds"
<ryan-summers[m]> Even though we explicitly construct a slice from it later?
<JamesMunns[m]> ryan-summers[m]: yes
<ryan-summers[m]> I.e. we don't write to sitcm ever, we write to the constructed slice
<JamesMunns[m]> yes, pointers are not numbers
<JamesMunns[m]> they have metadata, like "what was the size of the object I come from"
<ryan-summers[m]> Yeah this goes back to that article above
<ryan-summers[m]> Makes sense
<JamesMunns[m]> yes, you are violating strict provenance, as it is currently defined, as far as I am aware
<JamesMunns[m]> the slice thing is also bad :)
<JamesMunns[m]> fwiw you can probably avoid ever making a slice by casting the pointers to u8 ptrs and using https://doc.rust-lang.org/std/ptr/fn.copy_nonoverlapping.html
<ryan-summers[m]> Yeah I'll probably get around to cleaning it up next week
<JamesMunns[m]> which is essentially memcpy
<JamesMunns[m]> buuuuut the whole "static defined by the linker script" approach is UB, imo.
<ryan-summers[m]> Doesn't that still violate the strict pointer provenance?
<JamesMunns[m]> yes
<JamesMunns[m]> you have two ubs, that would fix one, not the provenance one
<JamesMunns[m]> the "I make a u8 slice of uninit memory" is like "clearly UB", not "technically ub under strict provenance"
<ryan-summers[m]> Hmm so how can you ever pass linker memory regions to Rust? Is it just not possible?
<JamesMunns[m]> ryan-summers[m]: I'm not aware of how, honestly.
<JamesMunns[m]> JamesMunns[m]: or: use them in inline asm.
<ryan-summers[m]> This seems like an important detail around rustc? This is more than just embedded
<JamesMunns[m]> ryan-summers[m]: who touches linkers, other than embedded? :p
<JamesMunns[m]> (sorta sarcastically, sorta not)
<ryan-summers[m]> Fair argument
<JamesMunns[m]> JamesMunns[m]: or linker scripts, rather.
<Rustnoob[m]> I have to implement sha256 and my mcu has no hw for it ( nrf52805 ) can someone suggest me a good sw impl with the lowest possible footprint?
<dirbaio[m]> the sha2 crate
<ryan-summers[m]> Yeah the best bet you have is to use someone elses impl. Don't do crypto yourself
<birdistheword99[> JamesMunns[m]: Unfortunately the requirement to place something in a specific memory region or address is way too common in embedded... I appreciate the effort you are making with the 'grounded' crate, it feels like there should be a standard way to address this issue but this is the only crate I have come across that is trying to address it (pun intended)
<diondokter[m]> James, I remember you suggesting to #[linker_section = ".foo"] for this so the linker automatically places it in the right spot
<JamesMunns[m]> birdistheword99[: yes, other people have just been copy/pasting (IMO) wrong patterns for years :p
<JamesMunns[m]> diondokter[m]: yep, but this means the linker script can't set the size
<JamesMunns[m]> JamesMunns[m]: so when I do that, it works, but you need to make sure the "code" and the "linker script" agree on the size.
<ryan-summers[m]> But this feels like an important detail w.r.t the pointer provenance discussion - is there any issue in rustc around this where we could pipe up to get some compiler feedback?
<JamesMunns[m]> JamesMunns[m]: the linker can't "talk back" to the compilation phase.
<JamesMunns[m]> ryan-summers[m]: What do you mean "pipe up"?
<ryan-summers[m]> I mean raise our concern
<JamesMunns[m]> The T-Opsem zulip channel is a good place for broad questions.
<ryan-summers[m]> Like, it feels like we should be able to do this in Rust like we can in C, but right now doesn't seem possible without UB
<ivmarkov[m]> * No sorry - was about to ask whether you have / have thought of implementing a `Box` which is generic over its (de)-allocator. So that it can be used with any pooled implementation, including with a raw non-pooled `malloc`/`free` based (de)allocator. But I have something which at least type-checks in the meantime (based on my previous adventures with writing a custom `Box` for Espressif's SPIRAM memory - as I'm also trying to
<ivmarkov[m]> enter the "roll your own custom allocator" business :p ):
<JamesMunns[m]> ryan-summers[m]: that's assuming "the way things have been done" in C wasn't UB either :)
<JamesMunns[m]> ("it works" does not mean "isn't UB"!)
<ivmarkov[m]> * No sorry - was about to ask whether you have / have thought of implementing a `Box` which is generic over its (de)-allocator. So that it can be used with any pooled implementation, including with a raw non-pooled `malloc`/`free` based (de)allocator. But I have something which at least type-checks in the meantime (based on my previous adventures with writing a custom `Box` for Espressif's SPIRAM memory - as I'm also trying to
<ivmarkov[m]> enter the "roll your own custom allocator" business :p ):
<ivmarkov[m]> * No sorry - was about to ask whether you have / have thought of implementing a `Box` which is generic over its (de)-allocator. So that it can be used with any pooled implementation, including with a raw non-pooled `malloc`/`free` based (de)allocator. But I have something which at least type-checks in the meantime (based on my previous adventures with writing a custom `Box` for Espressif's SPIRAM memory - as I'm also trying to
<ivmarkov[m]> enter the "roll your own custom allocator" business :p ):
<JamesMunns[m]> Anyway, I feel like I've soap-boxed too much (and not done enough client work) today.
<JamesMunns[m]> If you want to make a discussion somewhere (WG-Embedded Zulip, T-Opsem Zulip, rust-embedded/wg repo discussions), I'm happy to answer questions and discuss more
<JamesMunns[m]> I'd love to have all this stuff more referenceable than chat
<ryan-summers[m]> Yeah I'll make a WG issue for now
<firefrommoonligh> Do y'all have safety critical projects you are working in rust? Would be cool story time. I am interested
<firefrommoonligh> I've done drone firmware which has implications, but not on the level of med devices or aerospace/manned vehicles
<ryan-summers[m]> I do not yet, but I'm preparing for when someone comes and asks me. I've heard along the grapevine that one of my colleagues has been pushing rust + medical devices to some clients
<ryan-summers[m]> And honestly I feel they're a great fit
<JamesMunns[m]> I don't currently. Mostly doing some scientific stuff and non-embedded stuff.
<JamesMunns[m]> Definitely aware of some automotive and avionics type stuff in various stages.
<firefrommoonligh> I've been using a 3" quad which is relatively benign compared to a 5"... Those will try to kill you
<firefrommoonligh> Nice. I've been doing some science stuff in rust too - ab-initio chem sims, but that's not embedded
<firefrommoonligh> Have a GUI program for visualizing and manipulating protein structure as well (wgpu/egui)
<JamesMunns[m]> Ah nice. My current scientific thing is generally "automation controller", e.g. a buddy MCU on the side controlling and talking to various control system things, stepper motors, etc.
<JamesMunns[m]> it's not doing much science itself, but it's helping out a PC that's doing all the actual heavy lifting :)
<firefrommoonligh> Trying my hand at writing a gene-cloning tool RN like SnapGene, as a learning project . But SnapGene is v good so not really sure if this has a practical use ...
<firefrommoonligh> V cool re automation control!
<firefrommoonligh> I find programming helps with learning because the computer will do exactly what you tell it - it will expose any problems or impressions in your knowledge... And I know rust isn't usually used for science stuff, but IMO it's a great fit
<firefrommoonligh> s/impressions/imprecision/
<ryan-summers[m]> https://github.com/rust-embedded/wg/issues/771 for those of you with opinions
<JamesMunns[m]> > That is, accesses past the declared size are not generally UB, but the global must be dereferenceable up to the declared size at least.
<JamesMunns[m]> Ah, maybe that has changed recently
<ryan-summers[m]> That's a very relevant issue, nice find
<diondokter[m]> Klemens[m]: Yep
<ryan-summers[m]> Klemens[m]: This is a complex question. Doing that can actually break things if your flash has ECC codes
<ryan-summers[m]> So is platform specific
<ryan-summers[m]> (It's not always possible is what I'm trying to say, might be fine in this case)
<diondokter[m]> This is for the rp2040 with a W25q flash
<diondokter[m]> For that the answer is yes
<ryan-summers[m]> https://github.com/rust-lang/unsafe-code-guidelines/issues/259#issuecomment-1445931387 implies that section initialization is valid as long as the section is not empty. But also might be fine if the markers are declared as ZST (i.e. ())
<ryan-summers[m]> Anyways I also need to go do other things now. Thanks for the links James
<birdistheword99[> Whilst I am aware of the other issues and I am not suggesting that this approach is safe for all types of initialisation, but does using MaybeUninit::zeroed() to zero out the memory and then unsafe { x.write(your_val)} make this somewhat cleaner? for example to place a static_cell, which doesnt contain any pointers
<birdistheword99[> * Whilst I am aware of the other issues and I am not suggesting that this approach is safe for all types of initialisation, but does using MaybeUninit::zeroed() to zero out the memory and then unsafe { x.write(your_val)} make this somewhat cleaner? for example to place a StaticCell, constructed at runtime, which doesn't contain any pointers
<ryan-summers[m]> It depends on whats in the section. Some values don't allow zero as a value
<ryan-summers[m]> s/values/types/
andar1an[m] has joined #rust-embedded
<andar1an[m]> I have stumbled on m5stack and eps-rs. How does this land in rust embedded world?
<andar1an[m]> is esp-hal separate?
<ryan-summers[m]> esp-rs is just another community for Espressif chips. I think they have a full-time engineer that frequents this chat. No clue what m5stack is
<andar1an[m]> I noticed that today, espressif seems to have taken a majority stake in m5stack which seems cool
<andar1an[m]> Would rust-embedded work be upstream of that because it is Rust WG?
<ryan-summers[m]> Not following what you're asking here. Espressif does lots of rust embedded stuff
<andar1an[m]> I understand. I am just trying to understand delineation of WG and projects
<ryan-summers[m]> I'm pretty sure espressif uses lots of the rust-embedded WG crates, like the embedded-hal
<andar1an[m]> Ya, that is what I am trying to understand because I noticed there was also an esp-hal
<ryan-summers[m]> esp-hal is an implementation of the embedded-hal for the Espressif chips. The embedded-hal doesn't do anything for any specific chip, it's just a collection of defined traits to aid in interoperability
<ryan-summers[m]> the embedded-hal is not a HAL in and of itself
<ryan-summers[m]> You need implementers (i.e. embassy, nrf-hal, stm32f/h/lxx-hal, esp-hal, etc.)
<andar1an[m]> Ah, understood. Thanks so much. That helped it click
<ryan-summers[m]> The naming is indeed confusing at first, I remember having trouble with this stuff
<andar1an[m]> is there a better word to think of embedded hal if it is not a hal?
<ryan-summers[m]> The only use of embedded-hal is for i.e. someone to write a driver for a sensor without wanting to tie their driver to a specific platform. They know it talks i.e. over I2C, so they use the e-h abstract I2C trait, which the HALs provide a specific impl of for their platforms
<ryan-summers[m]> embedded-hal is just an interface
<ryan-summers[m]> * an interface definition
<ryan-summers[m]> Hardware-specific HALs actually implement that definition
<ryan-summers[m]> s/definition/interface/
<andar1an[m]> im gonna call it embedded-hali in my head haha
<andar1an[m]> thanks so much
<ryan-summers[m]> Whatever works for you :) It's probably a bit late in the game to rename the crate
<ryan-summers[m]> No worries!
<andar1an[m]> agreed, easy to think of it as that though
<andar1an[m]> now to figure out what hw to buy hehe
<andar1an[m]> thank you for that list as well, I hadn't seen the other options you listed yet either
<ryan-summers[m]> Anything ARM-based is going to be your best bet. Espressif's do their own thing since they need to fork and maintain thair own version of the Rust compiler for their chips
<ryan-summers[m]> STM32 and Nordic nRF chips are probably the most well-supported currently
<diondokter[m]> ryan-summers[m]: Their newer chips as risc-v, and that all works with the normal compiler
<ryan-summers[m]> Sorry, yeah Risc-V is also a safe bet. I just wanted to avoid i.e. Atmel AVR architectures or PIC32
<diondokter[m]> s/as/are/
<andar1an[m]> I saw risc-v in docs, that's probably what I am gonna try to grab
<ryan-summers[m]> Or MSP430. All of that smaller-than-32-bit is a bit funky in Rust and not well supported
<ryan-summers[m]> That being said, I know that AVR and MSP430 rust projects exist
<andar1an[m]> have you seen people build anything with embassy to integrate with home assistant or home hab or similar?
<andar1an[m]> I guess is there something like esphome? sorry if ignorant, this is all net new
<andar1an[m]> embassy appears to be kinda like esphome on first glance, but i dk yet
<andar1an[m]> oh maybe esphome on home assistant can add m5stack atom devices that one builds with embassy
mameluc[m] has joined #rust-embedded
<mameluc[m]> andar1an[m]: embassy is much lower level than esphome. you can build things that speak mqtt or something like that but there is nothing really ready made afaik
<ryan-summers[m]> If you want an MQTT client, check out https://crates.io/crates/minimq - you could definitely build a protocol on top of it
<andar1an[m]> I dk if I will have time to tinker with that yet, most of my work right now is based on baremetal server orchestration, but will bank it for sure. Will be able to evolve as I tinker.
burrbull[m] has quit [Quit: Idle timeout reached: 172800s]
<FrreJacques[m]> Is there any more magic to writing async code that just putting async in front of all relevant functions and await behind calls to them?
<FrreJacques[m]> I am not at a point where I can run the stuff I am writing. But so far the only complains I get from clippy and the compiler is that one function takes to many arguments and that the pub trait I created has async functions. I guess that is okay because I use that trait only internally.
<ryan-summers[m]> AFIT (async-func-in-trait) should be stabilized, so maybe you need to update your rust version?
<ryan-summers[m]> But other than that, async and await are all you need to use async code
<ryan-summers[m]> Writing async stuff can be more complex, but if you're just using existing stuff, nothing to worry about
<FrreJacques[m]> So far mynoob experience was that as I started using the async function from eh-async it was just forcing me to put async in front of each function declaration and await in the end. Seems like a nobrainer so far.
<FrreJacques[m]> I only started with rust a few months ago. So I guess it shouldn't be too much ood.
<FrreJacques[m]> I updated rust, but this waring remains.
<FrreJacques[m]> It says that 'async fun' in public traits is discouraged.
<JamesMunns[m]> FrreJacques[m]: > <@frere_jacques:matrix.org> I updated rust, but this waring remains.
<JamesMunns[m]> yeah, that's expected. If you're doing it for embedded, you can mostly ignore that.
<JamesMunns[m]> > It says that 'async fun' in public traits is discouraged.
Ralph[m] has quit [Quit: Idle timeout reached: 172800s]
<dirbaio[m]> <FrreJacques[m]> "Is there any more magic to..." <- > <@frere_jacques:matrix.org> Is there any more magic to writing async code that just putting async in front of all relevant functions and await behind calls to them?
<dirbaio[m]> > I am not at a point where I can run the stuff I am writing. But so far the only complains I get from clippy and the compiler is that one function takes to many arguments and that the pub trait I created has async functions. I guess that is okay because I use that trait only internally.
<dirbaio[m]> That warning is about Send/Sync which doesn't apply to embedded. Add `#![allow(async_fn_in_trait)]` at the top of lib.rs to silence it
AlexandrosLiarok has quit [Quit: Idle timeout reached: 172800s]
<ivmarkov[m]> <ivmarkov[m]> "Here, JFYI: https://github.com/..."; <- Continuing here because I need to share my progress (or lack of progress thereof) with somebody, even if it is just me listening to myself. :) My ideas from above ^^^ based on your pool idea do work...... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/QxSoSThWKFJgccOXNRoGZAiR>)
<ivmarkov[m]> * Continuing here because I need to share my progress (or lack of progress thereof) with somebody, even if it is just me listening to myself. :) My ideas from above ^^^ based on your pool idea do work...... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/rufsqDjliapKYxeZOvTbBLKY>)
<FrreJacques[m]> Is there a higher possibility to brick a mcu with async stuff?
<FrreJacques[m]> I put my example onto my bluepill with probe-rs embedd. The mvp of the driver doesn't work, but the flashing worked, as I can see from the changed blinky. But if I want to embedd again, I get error that send_jtag_command 242 failed.
<FrreJacques[m]> It seems my board is not listening to the swd bus.
<FrreJacques[m]> I got it responding again after using the boot pin jumpers. To my naive understanding it looks like the probe can't block the execution if the firmware is running.
<firefrommoonligh> If you don't significantly overvolt something, you will probably not brick your MCU
<firefrommoonligh> You may know this by smoke, and bright flash, or an acrid smell
<firefrommoonligh> Or, there may be no physical indication
<firefrommoonligh> * significantly overvolt or short something, you
<FrreJacques[m]> I was just confused, because I could not establish a connection with both boot pins to ground.
<ryan-summers[m]> The probe should always be able to stop execution of the device unless you reconfigure any of the debug IO pins
<FrreJacques[m]> With the other firmware so far that was never an isdze.
<FrreJacques[m]> s/isdze/issue/
<FrreJacques[m]> That didn't work. Maybe I brought it in a strange state while trying to debug it with probe-rs.
<FrreJacques[m]> But I thought that plugging out the stlink and closing the nvim session should bring everything back to previous state. But I could only flash a new firmware after setting BOOT0 to high.
<GrantM11235[m]> Are you using embassy? There should be an option to enable debugging while the mcu is sleeping
<FrreJacques[m]> Yeah, I tried to use embassy to test my attempt of creating an async driver. I used the blinky example for the stmf32f1 as a starting point.
explodingwaffle1 has joined #rust-embedded
<explodingwaffle1> make sure to hook up the reset pin to your debugger and have connectUnderReset in your probe-rs config or cli arg. not really an async specific issue ime
<GrantM11235[m]> Make sure you have config.enable_debug_during_sleep = true; in your embassy-stm32 config
<GrantM11235[m]> Oh, nevermind, that is on by default
<FrreJacques[m]> I have none of that lol. Sorry, I don't know if you are happy with such noob questions.
<FrreJacques[m]> I only connected the swio, the swclk and power and gnd. I will look up where the reset should be connected to.
<FrreJacques[m]> IG the same pin as the button goes too.
<Klemens[m]> <diondokter[m]> "Yep" <- I kinda copied the embassy write implementation and now sequential storage is working
<Klemens[m]> Klemens[m]: thanks you for your help
<diondokter[m]> <Klemens[m]> "I kinda copied the embassy write..." <- 😁
<FrreJacques[m]> <explodingwaffle1> "make sure to hook up the reset..." <- I connected the rst pin from stlink to pin R of the bluepill. When I run `cargo run -- --connect-under-reset` I still get the jtag issue, when both boot pins are at 0.
<FrreJacques[m]> That I have to switch the jumper for flashing is mildly annoying that I can't really inspect the state or interact in anyway after flashing is quite bad for debugging.
<dirbaio[m]> oh yeah I got that too
<dirbaio[m]> probe-rs behaves a bit weird with the stm32f1
<dirbaio[m]> sometimes I had to press the boot button to get it to flash
<dirbaio[m]> 🥲
adamhott[m] has quit [Quit: Idle timeout reached: 172800s]
<FrreJacques[m]> Thats on one hand nice to hear, because it means I am not just to stupid. OTOH there seems to be no easy fix.
<FrreJacques[m]> But it's only if I flash the embassy firmware. If I flash one using stm32f1-hal I can flash and flash, debug and get rtt etc.
<dirbaio[m]> probably due to the wfi
<dirbaio[m]> s/wfi/`wfe`/
<dirbaio[m]> embassy-executor automatically puts the core to sleep with wfe to save power when no tasks are running
<dirbaio[m]> stm32f1xx-hal doesn't. you have to do it yourself and you probably aren't
<dirbaio[m]> there's the "enable debug in sleep" in embassy-stm32 Config which is supposed to fix this, but it doesn't fully fix it ...
<dirbaio[m]> (it's enabled by default)
<dirbaio[m]> so it polls in an infinite loop. the executor still works fine, it just wastes powre
<dirbaio[m]> s/powre/power/
<dirbaio[m]> it'll probably fix the issue
<dirbaio[m]> * the issue for you
<dirbaio[m]> haven't actually tested that myself
<dirbaio[m]> would be interesting to know
<FrreJacques[m]> Okay, too much of a noob again. How could I try that out?... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/ezRCKBgHiiqwEVsmSfoGwfQX>)
<FrreJacques[m]> Although I have to admit that I of course looked at existing solutions to get some orientation.
jistr has quit [Remote host closed the connection]
jistr has joined #rust-embedded
IlPalazzo-ojiisa has quit [Quit: Leaving.]
adept-neophyte has joined #rust-embedded
<adept-neophyte> Hello
<adept-neophyte> This is a chat for the Rust Language right ?
Trurl_m[m] has joined #rust-embedded
<Trurl_m[m]> no? this is the chat for Rust anime :) (joke)
<Trurl_m[m]> * no, this is the chat for Rust anime :) (joke)
<Trurl_m[m]> ep!
<Trurl_m[m]> * no, this is the chat for Rust anime :) (joke)
<Trurl_m[m]> Yep!
<adept-neophyte> haha
<adept-neophyte> I've just started learning Rust, just started chapter 4 of the book
<adept-neophyte> my head hurts but in a good way
<adept-neophyte> I'm trying to understand the difference between garbage collection and Ownership. if in Rust, a the memory for a data type is dropped when it goes out of scope, is that not the same a garbage collection, in say a language like Python?
<dirbaio[m]> adept-neophyte: this channel is about using Rust in embedded systems (microcontrollers, etc). if you have general Rust questions you probably want to ask in #rust:matrix.org
<adept-neophyte> ah thank you :)
adept-neophyte has left #rust-embedded [#rust-embedded]
cr1901 has quit [Read error: Connection reset by peer]
cr1901 has joined #rust-embedded
<dirbaio[m]> `unsafe { FOO }.get_mut(0)` copies the entire `FOO` to a temporary, then .get_mut() gets a reference to that.
<dirbaio[m]> `unsafe { FOO.get_mut(0) }` does the right thing.
<dirbaio[m]> fun footgun
<GrantM11235[m]> I guess that makes sense, `unsafe { FOO }` must return `[u32; 4]` not `&mut [u32; 4]`