<therealprof[m]>
<GrantM11235[m]> "Does rust-for-linux use the..." <- They would also be a user of the MMIO stuff.
<therealprof[m]>
<thalesfragoso[m]> "Why would we need inline asm ?" <- Currently that's the only way to guarantee that there won't be any reordering, tearing or misaligned accesses, at at once.
<SbastiendHerbais>
dirbaio: How does stm32-metapac "choose" the correct version it implements for a given chip? (i.e between lptim_v1, lptim_v2, etc.)
<MathiasKoch[m]>
Hmm. For context, I am using it for AWS IoT Shadows. They work by sending a delta between a "desired" and a "reported" json struct to a /delta topic, where some or all of the fields may or may not be (regular diff between jsons), thus the optional struct.... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/lOJOeoReNXGcSmMudNzCdoer>)
<ryan-summers[m]>
That all looks quite reasonable. So your struggle is just figuring out the correct depth and then the custom impl? Also, we would happily accept PRs for deriving impls for newtype enums :)
<ryan-summers[m]>
We just haven't needed them yet, so they aren't there
<ryan-summers[m]>
Generally, I've found that the compiler does a nice job of yelling at you if the depth is specified incorrectly and will only compile when specified correctly. We wanted rustc to be able to infer things properly, but turned out to not really be supported yet
<MathiasKoch[m]>
Absolutely, and it seems to work with the `new_depth = if orig_depth < 2 { orig_depth + 1 } else { orig_depth + 2 };`.. I was mostly seeking to understand why to increment it by 2 in deeper cases :o
<ryan-summers[m]>
It should be depth + 1 of the type that it wraps
<ryan-summers[m]>
I'm unsure why you need to do depth + 2....
<MathiasKoch[m]>
Great, I will see if I can figure out how to handroll my enum implementations, and if I manage to find a reasonable pattern, I will throw up a PR 👍️
<MathiasKoch[m]>
I can try to put up a short repro case.. hang on :)
<t-moe[m]>
Interesting. you seem to be in the middle of discussing something which is heavily related to what I just asked. Should have read/followed the current chat first...
<t-moe[m]>
(Trying to find the start of the discussion now):
<t-moe[m]>
I'm also using aws iot shadow and have my impl of it. Are you using some public crates to handle the proto ?
<ryan-summers[m]>
QUARTIQ wrote a crate over the last few years that lets you iterate over rust struct types as (key, value) pairs using any key or serialization format you want, called https://github.com/quartiq/miniconf
<ryan-summers[m]>
So essentially, sounds like for AWS IOT Shadow, the idea is that you receive your JSON, deserialize it into your patch struct, then iterate over all of the present fields using miniconf and apply them to your active struct
<ryan-summers[m]>
Just makes it nice for never having to manually maintain new fields as your struct increases in size
<ryan-summers[m]>
The key structure and serialized representation of the values is configurable, there's built-in support for JSON and postcard, as well as bit-packed indices (for small keys) or JSON path notation as well, or standard path-like keys using a character separator (i.e. /outer/inner/value)
<t-moe[m]>
I see. miniconf looks interesting. I have to take a deeper look.
<t-moe[m]>
One question I have at the top of my head: How would I share `Settings` with the different parts of my app. I dont like passing `RefCell<Settings>`around when I in fact only need `RefCell<SubSetting>`for certain components...
<ryan-summers[m]>
t-moe[m]: > <@t-moe:matrix.org> I see. miniconf looks interesting. I have to take a deeper look.
<ryan-summers[m]>
> One question I have at the top of my head: How would I share `Settings` with the different parts of my app. I dont like passing `RefCell<Settings>`around when I in fact only need `RefCell<SubSetting>`for certain components...
<ryan-summers[m]>
One thing I've been updating all our apps to do is to literally have a singleton `Settings` struct for the entire app that gets passed by reference to modules that need to update their internal state. It ensures that all of your settings have a single source of truth
<ryan-summers[m]>
But you can always borrow subfields in rust, for example do `&settings.inner.module`
<MathiasKoch[m]>
Hi t-moe
<MathiasKoch[m]>
I am using https://github.com/BlackbirdHQ/rustot/ but we are currently in the middle of a super hefty bottom-up rewrite to fully async, where i am basing the IoT shadows heavy lifting on miniconf
<MathiasKoch[m]>
* Hi t-moe
<MathiasKoch[m]>
I am using and maintaining https://github.com/BlackbirdHQ/rustot/ but we are currently in the middle of a super hefty bottom-up rewrite to fully async, where i am basing the IoT shadows heavy lifting on miniconf
<MathiasKoch[m]>
It is super opinionated, but mostly batteries included for iot jobs, ota, shadows etc
<t-moe[m]>
MathiasKoch[m]: > <@mathias_koch:matrix.org> Hi t-moe
<t-moe[m]>
> I am using and maintaining https://github.com/BlackbirdHQ/rustot/ but we are currently in the middle of a super hefty bottom-up rewrite to fully async, where i am basing the IoT shadows heavy lifting on miniconf
<t-moe[m]>
Oh shoot. How long has that been up there :). I swear I searched for a create like this when i started with my current client. Now i have my own impls of Shadow, Stream + Jobs :). I'll take a look...
<t-moe[m]>
* Oh shoot. How long has that been up there :) ?. I swear I searched for a create like this when i started with my current client. Now i have my own impls of Shadow, Stream + Jobs :). I'll take a look...
<ryan-summers[m]>
One of the problems of having a vibrant ecosystem is that there's often 10 crates to do the job :)
<MathiasKoch[m]>
Been there for a few years in varying states :p
<MathiasKoch[m]>
Our async rewrite is based on a still not public async MQTT v5 client though.. mostly finished, but needs a bit of docs :p
<ryan-summers[m]>
If you want a non async v5 client, check out minimq ;)
<ryan-summers[m]>
I dislike that async/non-async divides things so harshly
<t-moe[m]>
i want an async v3 client :(
<ryan-summers[m]>
To be fair, migrating a v5 client to v3 is probably quite easy? You just need to omit properties, right?
<MathiasKoch[m]>
I have checked it out extensively in my rewrite of our non-async mqttrust crate.. but i wanted something that feels for rust-like especially around subscriptions
<MathiasKoch[m]>
our new async version does both, though we only use the v5 part, so the v3 might be less tested :p
<ryan-summers[m]>
MathiasKoch[m]: How so? I'm also not a fan of the `subscribe` API. Do you mean that you like the semantics of `client.subscribe("/topic").await` and knowing you're immediately subscribed?
<t-moe[m]>
ryan-summers[m]: we have a v3 only modem
<t-moe[m]>
s//-/
<ryan-summers[m]>
Yeah I'm saying taking a v5 client and modifying it to only send v3 content is probably trivial
<ryan-summers[m]>
Just a few [cfg(feature ] "v3")] flags would likely be fine
<ryan-summers[m]>
s//`/, s/]/=/, s//`/
<t-moe[m]>
sure, as long as it does not rely on any v5 features
<t-moe[m]>
Much to take it and read up on right now 😀.... Thanks already
<ryan-summers[m]>
Feel free to ping me with any questions :)
<t-moe[m]>
<ryan-summers[m]> "> <@t-moe:matrix.org> I see..." <- Hmm, kinda consider global singletons (even if passed by ref to the ctor) bad practice? This makes putting stuff into own crates hard. also its not nice for (unit) testing....
<ryan-summers[m]>
In our case, its a settings structure for the end firmware application, and is considered an RTIC resource
<MathiasKoch[m]>
Yeah, and this is absolutely not that. In our case performance is less important than ergonomics and maintainability
<MathiasKoch[m]>
I have not benchmarked it versus other implementations though.. Just verified that it is more than good enough for our case
<ryan-summers[m]>
Yeah we're honestly not using it anything super throughput-critical either
<ryan-summers[m]>
For that, we went with raw UDP socket + multicast
ninjasource[m] has joined #rust-embedded
<ninjasource[m]>
<SbastiendHerbais> "Mind you I also have a modified..." <- I'm a little late to this party but I'm working on similar things to you. Also trying to get slint working. Have you tried to use an external loader from ST and using their STM32CubeProgrammer CLI tool? This is the script I use to program my STM32H735G-DK that allows me to... (full message at
<t-moe[m]>
<ryan-summers[m]> "This is how we're doing it if..." <- Ok, intersting. I'm not on RTIC yet though...
<t-moe[m]>
I wonder if i could create a modified RefCell. e.g. lets say I have a global RefCell<GlobalSettings> instead of passing this downwards, it would be nice if I could map it to RefCell<SubSetting> (or SubRefCell<'_, SubSetting>) which I then pass downwards . Similar to how RefMut::map_split works, only that it also works on not-yet-borrowed data.
<ryan-summers[m]>
I would strongly advise against doing static globals + cells yourself and using a framework like embassy or RTIC
<ryan-summers[m]>
Its very easy to get yourself into trouble
<t-moe[m]>
I do use embassy.
<t-moe[m]>
and I'm not talking about static mut globals..
<ryan-summers[m]>
Gotcha, I misunderstood :)
<t-moe[m]>
with rtic you have rtic which manages your singleton. But you pass GlobalSettings down, which makes it hard to unit-test
<t-moe[m]>
I would much more prefer to pass SubSetting down.
<ryan-summers[m]>
Yeah I'm confused, can't you easily do that by borrowing out the subfield?
<ryan-summers[m]>
What I generally do is whenever a global settings update happens, I borrow out the settings to all of the underlying modules to update their internal states
<ryan-summers[m]>
So those lower level modules (i.e. each motor, sensor, etc.) has a local copy of its current operating state. Those local copies get updated whenever the global settings are changed
<ryan-summers[m]>
So it's not truly a singleton in all senses
<t-moe[m]>
I see. that nice.
M9names[m] has quit [Quit: Idle timeout reached: 172800s]
<t-moe[m]>
I want updates in both directions though for some components
<t-moe[m]>
but I could do this from outside.
<t-moe[m]>
* but I could do this from outside, thats true
<ryan-summers[m]>
Ah that is... ood
<ryan-summers[m]>
s/ood/odd? Why are your motors modifying the settings?/
<t-moe[m]>
you think so? What about motor calibration data?
<ryan-summers[m]>
Calibration data would be part of the GlobalSettings initialization process, so during the initial settings construction they define the default settings state, but they don't do any modification during runtime
<ryan-summers[m]>
I.e. they'd be part of `GlobalSettings::new(&motor)`
<t-moe[m]>
Well, we callibrate our motor from time to time again :)
<ryan-summers[m]>
Hmm, generally what I'd likely do is handle it via out-of-band communication and then send it down through the main settings interface
<ryan-summers[m]>
But that's an interesting use case for sure
<t-moe[m]>
what do you mean by out-of-band communication? can you clarify?
<ryan-summers[m]>
Well, you're commanding your motors to calibrate and then getting the result somehow, right?
<ryan-summers[m]>
Or are you just sending a command to calibrate and then seeing it in the settings later?
<t-moe[m]>
both :)
<ryan-summers[m]>
Yeah so the loop could change to "Command -> Read result -> Write result back via MQTT settings modifications"
<t-moe[m]>
maybe I can separate out of band communication ("send calibrate") from general telemetry.
<t-moe[m]>
But with aws shadow stuff it also makes sense to combine the two...
<t-moe[m]>
But with aws shadow stuff it also makes sense to combine the two...
<t-moe[m]>
* maybe I can separate out of band communication ("send calibrate") from general telemetry ("some internal calibration setting changed automatically").
<ryan-summers[m]>
Yeah I wouldn't know, having used aws shadow
<t-moe[m]>
* maybe I can separate out of band communication ("send calibrate") from general telemetry ("some internal calibration setting changed automatically").
<t-moe[m]>
But the way aws shadow stuff is shaped, it also makes sense to combine the two...
<t-moe[m]>
Do you go offline with the modem during sleep cycles and reconnect on wakeup, or the modem stays (at least semi-)awake all the time and can catch shadow delta messages?
<MathiasKoch[m]>
We are running of power all time, so we maintain a stable mqtt connection at all times
<t-moe[m]>
ah you lucky guy :)
<MathiasKoch[m]>
Yup, I feel incredibly lucky not having to worry about power consumption and battery :o
<ryan-summers[m]>
Wall power is a blessing. Batteries are brutal
<t-moe[m]>
yep, that must be nice. We're setting up automatic CI/CD power consumption measurements, so that we can at least automatically catch power regressions in the future :).
<t-moe[m]>
With AWS shadow it is a bit of a pain, because when the device comes back online (clean_session=0) you dont know whether there are any delta messages pending and about to be delivered or if there were just no updates.
<t-moe[m]>
anyways, thanks for the hint with rustot. I'll take a look and see what i can copy or maybe even migrate to it...
<MathiasKoch[m]>
Hmm.. AWS only sends the delta on clean_session=1 subscriptions?
<t-moe[m]>
no. but aws only sends delta messages when there are actual deltas.
<t-moe[m]>
So you dont know whether some more deltas are coming (=> you've waited long enough after reconnecting to the broker)
<t-moe[m]>
or whether there is just no delta
<t-moe[m]>
and since mqtt has no "all cached messages have been transmitted"-msg....
<t-moe[m]>
* and since the broker does not tell you when all cached messages have been transmitted, there is no way of knowing in which case you're in
<t-moe[m]>
* no delta and you can happily go back to sleep and disconnect the modem
<MathiasKoch[m]>
<ryan-summers[m]> "Does anyone know if there's a..." <- You could put a default bound on the associated type, and return Self::Error::default() in the default impl
Foxyloxy has joined #rust-embedded
Foxyloxy_ has quit [Ping timeout: 245 seconds]
d3zd3z[m] has quit [Quit: Idle timeout reached: 172800s]