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
<re_irc> < (@jamesmunns:beeper.com)> Charles ⚡️: an nRF52840 on one half and like an nRF52810 on the other half would probably work pretty well
<re_irc> < (@jamesmunns:beeper.com)> do ESB or something between the halves, with USB or BLE to the PC
<re_irc> <Charles ⚡️> maybe i should have edited my post but i think bluetooth is probably a bad idea due to latency
<re_irc> <Charles ⚡️> : yeah basically
<re_irc> < (@jamesmunns:beeper.com)> that being said - I dunno if coexistence stuff works in Rust?
<re_irc> <Charles ⚡️> coexistence?
<re_irc> < (@jamesmunns:beeper.com)> using ESB and BLE on the same chip at the same time
<re_irc> < (@jamesmunns:beeper.com)> basically interleaving radio time
<re_irc> <Charles ⚡️> ah
<re_irc> <Charles ⚡️> i think it would be best to do ESB and have a dongle
<re_irc> < (@jamesmunns:beeper.com)> but USB to PC and just ESB between nrf chips should also work
<re_irc> <Charles ⚡️> * dongle, so three chips total
<re_irc> < (@jamesmunns:beeper.com)> Oh, you could do that too
<re_irc> < (@jamesmunns:beeper.com)> the 52 and 51 chips can do ESB btw: docs.rs/esb/
<re_irc> <Charles ⚡️> i found this video https://youtu.be/Zn7WjyIvAWA which suggests that bluetooth latency is awful
<re_irc> < (@dirbaio:matrix.org)> yeah mixing esb+ble is not going to be easy
<re_irc> <Charles ⚡️> thankfully i don't have to do it :)
<re_irc> <Charles ⚡️> i just realized i'm basically about to reinvent the nice!nano
<re_irc> < (@dirbaio:matrix.org)> there's no ready-to-use code for it out there
<re_irc> < (@jamesmunns:beeper.com)> Yeah, I guess it all comes down to "what are you doing your project for"
<re_irc> < (@jamesmunns:beeper.com)> like, if it's for fun, put a 52840 on each half and in the dongle lol
<re_irc> <Charles ⚡️> yeah the answer is fun, i'm not trying to mass produce anything
<re_irc> < (@dirbaio:matrix.org)> is the "esb" crate low-power?
<re_irc> <Charles ⚡️> i doubt anybody would want to build a second one of these
<re_irc> < (@jamesmunns:beeper.com)> : Theoretically it's all interrupt driven
<re_irc> < (@jamesmunns:beeper.com)> so it's not NOT low power? Not sure if anyone has tested it tho
<re_irc> < (@jamesmunns:beeper.com)> really only the PTX side needs to be/should be low power
<re_irc> < (@jamesmunns:beeper.com)> PRX is "dongle side" and really should be RX'ing at all times
<re_irc> < (@dirbaio:matrix.org)> but, like, does it need to have radio always-on? I guess PRX yes, PTX no?
<re_irc> < (@dirbaio:matrix.org)> yeah, that
<re_irc> < (@jamesmunns:beeper.com)> nah, ptx is "fire and forget" in most cases, you can wait around for a deadlined ack if you want
<re_irc> < (@jamesmunns:beeper.com)> you can tweak the timeout, and I think thales got all the quick-turnaround radio stuff working
<re_irc> < (@jamesmunns:beeper.com)> (as long as you don't need nrf21 compat)
<re_irc> < (@jamesmunns:beeper.com)> * nrf24
<re_irc> <Charles ⚡️> yeah if i have a dongle the architecture i would go for is like
<re_irc> left right
<re_irc> \ /
<re_irc> \ /
<re_irc> dongle
<re_irc> < (@jamesmunns:beeper.com)> yeah, in that case left and right would both be ptx
<re_irc> < (@jamesmunns:beeper.com)> and the dongle would be the prx
<re_irc> <Charles ⚡️> yeah
<re_irc> <Charles ⚡️> which seems to line up well with power draw
<re_irc> <Charles ⚡️> i don't think the halves would really care about acks lol
<re_irc> < (@jamesmunns:beeper.com)> you could probably run keyberon on the dongle itself, and just process keypresses
<re_irc> <Charles ⚡️> yeah, the dongle would do the heavy lifting
<re_irc> < (@jamesmunns:beeper.com)> yeah, a missed ack would mean a missed keypress (or release, depending on how you send messages)
<re_irc> <Charles ⚡️> how much would i need to worry about packet loss and do retransmissions if i miss acks?
<re_irc> < (@jamesmunns:beeper.com)> that depends on a lot, like your antennas, and how busy the 2.4GHz band is
<re_irc> < (@jamesmunns:beeper.com)> if you like... send the full state continuously, then dropping a few packets won't matter, but you'll also be sending a lot
<re_irc> < (@jamesmunns:beeper.com)> but that's also sending a lot lol
<re_irc> <Charles ⚡️> yeah figuring out a way to send diffs would be good
<re_irc> <Charles ⚡️> or "just stuff that's important"
genpaku has quit [Remote host closed the connection]
<re_irc> < (@jamesmunns:beeper.com)> I mean, a bit for every keystate is only like... 110 bits or so lol
<re_irc> <Charles ⚡️> keys will be analog on this board
<re_irc> < (@jamesmunns:beeper.com)> half for each keyboard half, you could totally send 8 bytes/half every ms or something lol
<re_irc> < (@jamesmunns:beeper.com)> I guess it depends on whether you do the key press logic on the local halves (and do binary only upstream), or send all the raw analog stuff. Someone did a hall effect keyboard here (wired?) recently
<re_irc> <Charles ⚡️> > Someone did a hall effect keyboard here (wired?) recently
<re_irc> oh cool
<re_irc> <Charles ⚡️> yeah i got the idea from the Wooting 60HE and the void switch
<re_irc> <Charles ⚡️> > I guess it depends on whether you do the key press logic on the local halves (and do binary only upstream), or send all the raw analog stuff.
<re_irc> yeah, i think depending on how i want this to work it'll be hard to predict this before testing it and seeing what actually works
genpaku has joined #rust-embedded
<re_irc> <Charles ⚡️> at the very least i know what MCUs i need so now i can order parts and start making/breaking stuff
<re_irc> < (@jamesmunns:beeper.com)> https://github.com/riskable/riskeyboard70
<re_irc> <Charles ⚡️> yes that's it
<re_irc> <Charles ⚡️> the void switches are still kinda binary due to their mechanical design though, at least they are with the default magnet spacing
<re_irc> <Charles ⚡️> like it's hard to press the key halfway without bottoming out first
<re_irc> < (@grantm11235:matrix.org)> I think normal keyboards send some data the other way, for example the state of the capslock light
<re_irc> < (@jamesmunns:beeper.com)> the way ESB works is that the PTX (the keyboard) always initiates a send, and you can also optionally include "response" data in the ACKs I've mentioned
<re_irc> < (@jamesmunns:beeper.com)> so if you wanted capslock lights, you would at least sometimes enable the ack function, just so you can send response data
<re_irc> < (@jamesmunns:beeper.com)> (so you "pre-load" outgoing data in the PRX, so when it gets a packet from PTX, it can immediately include the next response payload)
<re_irc> <Charles ⚡️> i'm not gonna have any lights on the keyboards or stuff so i don't expect to need to get data to a half from elsewhere
<re_irc> <Charles ⚡️> : clever
<re_irc> < (@jamesmunns:beeper.com)> Yeah, ESB is a super simple little protocol, but it's full of fun little clever design points, that are pretty perfect for "a keyboard", or really any other simple ptp link or "wall powered receiver, battery powered sender" configurations
<re_irc> <Charles ⚡️> am i gonna need to worry about (d)ecrypting data when using ESB?
<re_irc> < (@jamesmunns:beeper.com)> esb as a protocol doesn't mandate encryption at all
<re_irc> <Charles ⚡️> how difficult would it be to do it if i wanted?
<re_irc> < (@jamesmunns:beeper.com)> the esb crate certainly doesn't support it. i've used chacha8-poly1305 for encryption before, no idea what the little ble receivers do
<re_irc> <Charles ⚡️> okay
<re_irc> < (@jamesmunns:beeper.com)> err, little esb receivers, not ble
<re_irc> <riskable> Charles ⚡️: I've been using and loving the RP2040 lately 👍
<re_irc> < (@jamesmunns:beeper.com)> (like the logitech dongles)
<re_irc> <Charles ⚡️> wait logitech's stuff is also ESB based? lol, neat
<re_irc> < (@jamesmunns:beeper.com)> yeah, I think all the logitech non-ble wireless keyboards are esb + nrf24/nrf51 based?
<re_irc> < (@jamesmunns:beeper.com)> 2004 press release lol: https://www.rfglobalnet.com/doc/logitech-chooses-nordic-semiconductors-24-ghz-0001
<re_irc> <Charles ⚡️> that's pretty cool
<re_irc> < (@jamesmunns:beeper.com)> that might have been pre the "enhanced" part of "enhanced shockburst"
<re_irc> < (@grantm11235:matrix.org)> : Whatever they are doing, I guess it's not enough https://arstechnica.com/information-technology/2015/01/meet-keysweeper-the-10-usb-charger-that-steals-ms-keyboard-strokes/
<re_irc> < (@jamesmunns:beeper.com)> yeah, the nrf24 is just a little 8051 thing, not surprised the encryption is fairly easy to crack
<re_irc> < (@jamesmunns:beeper.com)> I've seen a bunch of demos that use nrf52840 dongles for proof of concept stuff
<re_irc> <Charles ⚡️> riskable: that doesn't have wireless stuff built into it though does it? (also void switches are cool!)
<re_irc> < (@boondocker:matrix.org)> I was trying out tilt five AR glasses today, and as soon as the controller connects it smashes my Logitech wireless 😆.. have to hold the keyboard a foot from the dongle
<re_irc> <riskable> Charles ⚡️: No it doesn't. I like my RGB to be _bright AF_ so I've learned to live with wires 😁
<re_irc> <Charles ⚡️> you're just not using enough 18650 cells
<re_irc> < (@jamesmunns:beeper.com)> I had RGB, but included room for an 18650 so I can power them: https://twitter.com/bitshiftmask/status/1496484158457135115
<re_irc> < (@jamesmunns:beeper.com)> lol
<re_irc> < (@jamesmunns:beeper.com)> exactly
<re_irc> <Charles ⚡️> lmao i was joking
<re_irc> < (@jamesmunns:beeper.com)> that being said, I only ever got the USB part working, not BLE, which is why the battery clips and battery aren't populated lol
<re_irc> <Charles ⚡️> rip
<re_irc> < (@jamesmunns:beeper.com)> (honestly I haven't used it much because I need to redesign the case, that keyboard was too compact for me :p
<re_irc> < (@jamesmunns:beeper.com)> * :p)
<re_irc> <Charles ⚡️> hmm okay next question is what devboards to get
<re_irc> <Charles ⚡️> obviously there's the nice!nano, but there's also this which seems nice because it's got a debug adapter socket right on it https://www.adafruit.com/product/4062
<re_irc> < (@jamesmunns:beeper.com)> I've used those, they are good
<re_irc> < (@jamesmunns:beeper.com)> make sure you have the little 0.05" header cable adapter thingy
<re_irc> < (@jamesmunns:beeper.com)> or there are swdio/swclk pads on the bottom you can solder to
<re_irc> <Charles ⚡️> i've got a j-link edu mini which has the tiny debug socket
<re_irc> < (@jamesmunns:beeper.com)> one thing tho, switching that between up to three boards at once is gunna kinda suck, and those cables are fragile, just as a heads up.
<re_irc> <Charles ⚡️> magsafe debug socket when
<re_irc> < (@jamesmunns:beeper.com)> :)
<re_irc> <Charles ⚡️> seems like flashing them can be done over usb or whatever and i'd only need to break out the real debugger if there's something seriously wrong with my code, so maybe the pain can be mitigated a little bit that way
<re_irc> < (@jamesmunns:beeper.com)> I think there's a tool for that (getting the rust firmware into the right shape for the adafruit bootloader)
<re_irc> <Charles ⚡️> excellent
<re_irc> < (@jamesmunns:beeper.com)> otherwise I think #embassy-rs:matrix.org (https://matrix.to/#/#embassy-rs:matrix.org) has a bootloader that works with the nrf52 I think
<re_irc> < (@jamesmunns:beeper.com)> not sure if they have it wired up to USB, or just BLE?
<cr1901> jamesmunns: So better late than never (respond at your convenience) but re: your question "what would I do with a postcard::Value" type, the idea is to let users put in user-defined data types into a postcard information mem, and have a deserializer tolerate the user data, while deserializing everything else as the correct type
<re_irc> < (@jamesmunns:beeper.com)> My comeback to that is: use "&[u8]".
<re_irc> < (@jamesmunns:beeper.com)> I've done "two stage deser" before
<cr1901> Serialize as InfoMem<T: Serialize>, Deserialize as InfoMem<postcard::value>
<cr1901> ahhh, hmmm
<re_irc> < (@jamesmunns:beeper.com)> put postcard bytes as a byte array (can also be "heapless::Vec<u8>") as a field, like the "payload" of a TCP packet
<re_irc> < (@jamesmunns:beeper.com)> Yeah, "InfoMem<h::Vec<u8, N>>", then do stage-two deser once you know what's inside
<cr1901> What trait bounds should I use, so I can serialize as InfoMem<&[u8]> or InfoMem<h:Vec<u8,N>> and deserialize to the opposite type
<re_irc> < (@jamesmunns:beeper.com)> you'd need some massaging to make it exactly as flexible as the real serde_json::Value
<cr1901> (There is no reason I can think of why you can't serialize to one but deserialize to the other)
<cr1901> serialize from* one
<re_irc> < (@jamesmunns:beeper.com)> uhh, you could have something like:
<re_irc> struct InfoMem<T>
<re_irc> where
<re_irc> #[derive(Serialize, Deserialize)]
<re_irc> < (@jamesmunns:beeper.com)> you can "type pun" two things that fall down to things like borrowed slices
<cr1901> thanks, I'll mull this over tonight
<re_irc> < (@jamesmunns:beeper.com)> that's what "InfoStr" is doing. It doesn't encode the enum variant on the wire, just len and data
* re_irc Charles ⚡️ would also like to say thanks to James for the help/advice/info
<re_irc> < (@jamesmunns:beeper.com)> I don't have a more elegant way to express that than what I do for InfoStr/what the managed crate does
<cr1901> Yea sorry Charles, I wanted to send my q before I forgot
<cr1901> and have James answer after he was done w/ you
<re_irc> <Charles ⚡️> nah you're good i got what i needed
<re_irc> <Charles ⚡️> +(and more)
<re_irc> < (@jamesmunns:beeper.com)> cr1901, i've sorta been mulling what a self-describing version of postcard would look like
<re_irc> < (@jamesmunns:beeper.com)> and I've been doing a lot of forth shenangans lately, which is making me consider writing something that builds itself using a little stack machine and postcard's primitives
<cr1901> I don't know if I would want/need it for what I want to do. The "&[u8]" version is probably good enough for my needs
<cr1901> (Yea also something that I've been meaning to ask: How do you make a forth in Rust whose performance isn't shit when Rust doesn't have computed goto?)
<re_irc> < (@jamesmunns:beeper.com)> I dunno, it kinda works? I'm sure the asm doesn't hold water to something hand-coded, but it runs reasonably snappy
<re_irc> < (@jamesmunns:beeper.com)> I sorta built a little forth-flavored wire/mem format for doing T9 (like the phone keyboard) using this: https://cohost.org/rc/tagged/ajm-00106
<re_irc> < (@jamesmunns:beeper.com)> https://github.com/anachro-rs/anachro-forth literally already uses postcard as a bytecode format for forth
<re_irc> < (@jamesmunns:beeper.com)> and I've been writing a no-std "closer to classic forth" here: https://github.com/jamesmunns/forth3
<re_irc> < (@jamesmunns:beeper.com)> I think they both had _reasonable_ performance, but probably leave a ton on the table.
<cr1901> (What I actually want is Rust to have some way to get the computed goto optimization at all. It's not like it's standard C either.)
<re_irc> < (@jamesmunns:beeper.com)> lotta match statements and pointer shenanigans for making "!Sized" arrays with a bump allocator (in forth3)
<re_irc> < (@jamesmunns:beeper.com)> I wouldn't be surprised if match statements could sometimes be that, especially for basic enums?
<cr1901> Hmmm, just minddumping while it's fresh
<re_irc> < (@jamesmunns:beeper.com)> but like, I also wonder if desktop cpus "like" jump tables from a branch prediction perspective anymore
<re_irc> < (@jamesmunns:beeper.com)> could make sense for MCUs still tho
<re_irc> < (@jamesmunns:beeper.com)> (I have no data to support any of these gut feelings)
<cr1901> Also, "you can "type pun" two things that fall down to things like borrowed slices". Why "two things"? InfoStr is type-punning one thing- a String.
<re_irc> < (@jamesmunns:beeper.com)> I mean
<re_irc> < (@jamesmunns:beeper.com)> you could have "Foo<&[u8]>" and "Foo<alloc::Vec<u8>>" and "Foo<heapless::Vec<u8, 128>>"
<re_irc> < (@jamesmunns:beeper.com)> because they all map to the "byte array" primitive on the wire
<re_irc> < (@jamesmunns:beeper.com)> so like, they will ser/de the exact same way. This is sorta "peeking behind the abstraction"
<cr1901> enum InfoSlice { Borrowed, StackAlloc, HeapAlloc }?
<re_irc> < (@jamesmunns:beeper.com)> You could, though "Borrowed" could actually be a static str or an actual borrowed str from the stack (or heap, or wherever)
<cr1901> I understand if you're not up for making an example, but I think I'm having trouble mapping the type punning back to the DeserializedOwned trait code example you pasted
<re_irc> < (@jamesmunns:beeper.com)> oh
<re_irc> < (@jamesmunns:beeper.com)> so that's sorta two things. IN GENERAL, you can "type pun" things and expect it to work in postcard, like if you literally changed the "Vec" field in a struct to a "&[u8]".
<re_irc> < (@jamesmunns:beeper.com)> if you wanted to leverage that for a sort of generic data type, which does two stage serialization, you'd need that snippet I posted earlier.
<re_irc> < (@jamesmunns:beeper.com)> (I'm proposing a sort of bizarre rube goldberg machine of traits and serde here, I wouldn't recommend it usually, except that I built it once... somewhere.)
<re_irc> < (@jamesmunns:beeper.com)> the use case of that was for a network protocol, where you had sort of "struct { header, payload }" kind of shapes
<cr1901> I think right now I want to punt and just make InfoMem<T: SerializesToPostcardByteArray>
<re_irc> < (@jamesmunns:beeper.com)> a totally fair thing to do
<cr1901> What trait do I need to accomplish this, or do I allow T: Serialize and bail if a byte array wasn't detected?
<cr1901> (bail during deserialization*)
<re_irc> < (@jamesmunns:beeper.com)> uhhhh
<re_irc> < (@jamesmunns:beeper.com)> you don't really "detect" at deser time
<re_irc> < (@jamesmunns:beeper.com)> that's why postcard doesn't do the deserialize_any interface
<re_irc> < (@jamesmunns:beeper.com)> im talking about "you, as cr1901, could use two different types at different times to type pun"
<re_irc> < (@jamesmunns:beeper.com)> like at deser time, you just have "a stream of bytes" basically. the deser is "hardcoded" to the shape of the struct.
<cr1901> I'm probably running into an XY Problem
<cr1901> so lemme explain what I actually want to do
<re_irc> < (@jamesmunns:beeper.com)> yeah, I can help you build this rube goldberg machine, but you probably don't want/need to.
<cr1901> rather than asking you qs about how to _implement_ what I want to do
<cr1901> I want to create a "readpim" (postcard info mem) application that deserializes into an InfoMem<&[u8]>, InfoMem<heapless::Vec<u8, N>> or InfoMem<Vec<u8>> struct. In practice, I only need the last one of these- deserialize the vendor-specific info into a Vec and otherwise ignore it.
<cr1901> But I want to maybe eventually support the other two with the same function without the need for cfg(feature = "std")
<cr1901> this _feels_ like something a single fn foo<T>() should be doable to do
<re_irc> < (@jamesmunns:beeper.com)> probably, make a sealed trait, and impl it for those three types
<re_irc> < (@jamesmunns:beeper.com)> it gets weird if you ever need to carry generics/lifetimes more than like one level of nesting. If you copy and paste that summary as an issue in InfoMem, I can comment on it
<cr1901> (Is [u8; 0] also serialized as a byte array? Context is "type NoVendorData = [u8; 0]" and it would also impl the sealed trait. It is the type-level moral equivalent of Option::None".
<cr1901> jamesmunns: I'll impl the sealed trait approach and then put my comments under an "Is Sealed trait the proper abstraction?" issue
<re_irc> < (@jamesmunns:beeper.com)> so confusingly
<re_irc> < (@jamesmunns:beeper.com)> "byte array" is for slices of u8s
<re_irc> < (@jamesmunns:beeper.com)> an ACTUAL array is serialized as essentially a tuple of the same size
<re_irc> < (@jamesmunns:beeper.com)> so "[u8; 0]" takes zero bytes on the wire, "[u8; 1]" takes one, etc.
<re_irc> < (@jamesmunns:beeper.com)> "&[u8]" is a "byte array", which is len+data
<cr1901> I'm driving you nuts tonight, aren't I :P?
<re_irc> < (@jamesmunns:beeper.com)> nah dude, without a trace of sarcasm, recalling weird arcane knowledge like this is a ton of fun.
<re_irc> < (@jamesmunns:beeper.com)> but I am going to bed ~now, so I wish you luck :D
<cr1901> One last q
<cr1901> Is there a way to produce a byte array of 0 len in postcard, or am I stuck w/ the Option<T>?
<cr1901> (where T: Sealed)
<re_irc> < (@jamesmunns:beeper.com)> literally "let x: &[u8] = &[];" would serialize to a len of 0 and no data
<re_irc> < (@jamesmunns:beeper.com)> so literally "[0]" on the wire
* cr1901 nods fair enough :P
<re_irc> < (@jamesmunns:beeper.com)> ("[u8]" and "[u8; N]" are very distinct types!)
<re_irc> < (@jamesmunns:beeper.com)> (as are "&[u8]" and "&[u8; N]"!)
<cr1901> &[u8] is a fat pointer, &[u8; N] is not
<re_irc> < (@jamesmunns:beeper.com)> it's a slice, specifically, but yeah, "(usize, *const u8)"
<re_irc> < (@jamesmunns:beeper.com)> where yeah, the array is just "*const [u8; N]"
<re_irc> < (@jamesmunns:beeper.com)> "where did we store the length? in the compiler."
<cr1901> alright, get some sleep. I'll mull over this.
<cr1901> LOL
starblue has quit [Ping timeout: 252 seconds]
starblue has joined #rust-embedded
<re_irc> <Félix the Newbie> : That's what I do, but I have to contruct the struct with the data, then write the match in another function. More than half of the code is boilerplate. I'll keep it as is for now, but if that grows too much, I'll see.
crabbedhaloablut has quit [Remote host closed the connection]
crabbedhaloablut has joined #rust-embedded
<re_irc> <Félix the Newbie> My keyboard firmware moves forward well, but I'm tired of pressing the reset button with a needle. How can I put it in flashing state from my code? That way I can assign a key to it.
<Lumpio-> That would depend on the hardware, also using a debugger will usually not have such issues
<re_irc> <Félix the Newbie> I cannot really do that. I don't think it has a way to attach a debugger, and I don't want to mess with soldering, as I never did that.
<re_irc> <Félix the Newbie> Lumpio-: My chip is a stm32f303xb, but I'm not sure about the one that boots it.
tafa has quit [Quit: ZNC - https://znc.in]
tafa has joined #rust-embedded
<Lumpio-> Ah so is there a bootloader?
<Lumpio-> Then there might be a way to trigger it via code and therefore via a key press (or even over USB) but that depends on the bootloader
<re_irc> <Félix the Newbie> I don't really know (I knew basically nothing before beginning writing my firmware). I call it like that because when it's activated, I can give it a bin, and then it installs it.
<re_irc> < (@ryan-summers:matrix.org)> I think that would be a bootloader. I assume you don't have a debug probe attached to your device? If you did, you would have no need for the reset button, but there would also be nothing that is "activated" that you can give a bin - the probe could remotely reset and reprogram the chip
<Lumpio-> I think they just mentioned that they don't have a debugger attached
<re_irc> <Félix the Newbie> Indeed. I don't want to solder anything to the chip.
<Lumpio-> Just out of interest what program do you use to upload a binary
<re_irc> <Félix the Newbie> Lumpio-: It's an (open-source) tool written by the manufacturer https://www.zsa.io/wally
<re_irc> < (@ryan-summers:matrix.org)> Indeed smells like a bootloader impl :) Sorry, just got online so I'm out of the loop
<re_irc> <Félix the Newbie> I'm pretty sure it's dead simple, like I must set a register, or a bit in memory :/
<re_irc> < (@ryan-summers:matrix.org)> You can definitely reset to bootloader! That's not hard
<re_irc> < (@ryan-summers:matrix.org)> Let me find you the function, just a sec
<re_irc> < (@ryan-summers:matrix.org)> If it's a bootloader, likely all you need to do is reset the chip. There _might_ be a custom method to boot into it, although this is rare
<re_irc> <Félix the Newbie> I thought it was something standard.
<re_irc> <Félix the Newbie> : Just resetting it works. Is that something standard?
<re_irc> < (@ryan-summers:matrix.org)> https://docs.rs/cortex-m/0.7.7/cortex_m/peripheral/struct.SCB.html#method.sys_reset
<re_irc> < (@ryan-summers:matrix.org)> So you would just call "cortex_m::peripheral::SCB::sys_reset()"
<re_irc> <Félix the Newbie> Oh, that's _that_ simple. Thanks a lot.
<re_irc> < (@ryan-summers:matrix.org)> Read into the docs on the bootloader a bit if that doesn't work for you. There might be something else required to execute the bootloader
<re_irc> < (@ryan-summers:matrix.org)> But likely, the pin you're poking is just the external RST pin
IlPalazzo-ojiisa has joined #rust-embedded
steew has quit [Ping timeout: 246 seconds]
<Lumpio-> Bootloaders sometimes react to the reset method (internal reset, external reset, etc), and sometimes they need a special bit set somewhere
<Lumpio-> That is, to activate the update mode instead of running the application
<Lumpio-> So if just the sys_reset doesn't work, maybe we could look into the bootloader source next
starblue has quit [Ping timeout: 248 seconds]
steew has joined #rust-embedded
starblue has joined #rust-embedded
<re_irc> < (@jamesmunns:beeper.com)> The hardware is just using the built in stm32 DFU mode
<Lumpio-> ah
<Lumpio-> I'm sure there is a way to trigger that then
<re_irc> < (@jamesmunns:beeper.com)> You uh... Can jump to the ROM bootloader, I've done it on other stm32 chips. There's a reference note that has all the code addrs in it. It gets... Weird though, I probably wasn't setting up the stacks or MCU state properly by just jumping to it
<re_irc> < (@jamesmunns:beeper.com)> If you're gonna do it, it's probably smart to set a flag and do a sys_reset first, then jump to DFU code
<re_irc> < (@jamesmunns:beeper.com)> Here I use panic-persist, and jump to bootloader after panicking and resetting: https://github.com/jamesmunns/feather-405/blob/master/hello-405/src/main.rs
<re_irc> < (@jamesmunns:beeper.com)> let start_ptr = &mut _panic_dump_start as *mut u8;
<re_irc> Should be
<re_irc> let start_ptr = core::ptr::addr_of_mut!(_panic_dump_start);
<re_irc> < (@jamesmunns:beeper.com)> (also the DFU address changes chip to chip, you'll have to find the app note that says what the addr is for the stm32f3 you are using is)
<re_irc> < (@jamesmunns:beeper.com)> Fair warning, it would sometimes act weird and either not bootload, or act funny after bootloading, like I said, there's probably some setup step I'm missing. A full power cycle would set it right.
<re_irc> < (@jamesmunns:beeper.com)> (the F0 was more reliable than the F4, iirc, but they both did work most of the time)
<re_irc> < (@ryan-summers:matrix.org)> Booster implements a reset-to-DFU mude. It's.... not trivial. See https://github.com/quartiq/booster/blob/84e8170551dbce48f02ab7b2fb95e2a833efba3c/src/hardware/platform.rs#L120
<re_irc> < (@ryan-summers:matrix.org)> The main issue is that you have to reset the core peripherals that you configure that the bootloader needs, and then you have to jump to it. Would be much nicer to e.g. use a flag, like James recommends, then jump to BL before setup occurs to rely on the chip reset to set everything up
<re_irc> < (@ryan-summers:matrix.org)> You have to deconfigure pretty much everything you used
<re_irc> < (@jamesmunns:beeper.com)> Ohhhh, that's a good reference for the future. Yeah I cheated and let sys reset do everything for me
<re_irc> < (@ryan-summers:matrix.org)> That doesn't cover necessarily everything, and was mostly trial-and-error
<re_irc> < (@ryan-summers:matrix.org)> Just the things booster used that needed deconfig
<re_irc> < (@jamesmunns:beeper.com)> Panic persist HAPPENS to both set a flag in uninit mem and sys reset the device
<re_irc> < (@ryan-summers:matrix.org)> But it allows you to send a "dfu" command over USB-serial and put the device into DFU mode without needing to press the DFU bootload hardware pins
<re_irc> < (@jamesmunns:beeper.com)> Which is why I was looking for its magic word to trigger the jump to dfu
<re_irc> < (@jamesmunns:beeper.com)> (also there was something momentarily hilarious to me about a firmware resetting into DFU after a panic. The ultimate "welp, I give up, replace me")
<re_irc> < (@ryan-summers:matrix.org)> That's pretty funny to be honest :P
<re_irc> < (@jamesmunns:beeper.com)> It was honestly a pretty nice dev cycle, when the DFU worked reliably :p
<re_irc> < (@jamesmunns:beeper.com)> But yeah, you could trigger that on a fancy keybinding instead
<re_irc> < (@jamesmunns:beeper.com)> (or process a USB serial endpoint command, etc)
<re_irc> < (@adamgreig:matrix.org)> if you are doing that, you can implement a tiny bit of the usb dfu protocol as an extra interface, then usb-dfu etc software can detect it and tell it to reboot into bootloader
<re_irc> < (@adamgreig:matrix.org)> (rather than needing a special usb-serial command or keybinding etc)
<re_irc> <Félix the Newbie> : I'm lost here. Do I have to write all this code? I just want to put it in a state where my tool can flash a new bin
<re_irc> < (@adamgreig:matrix.org)> you just need these DFU descriptors: https://github.com/adamgreig/ffp/blob/master/firmware/src/hal/usb/descriptors.rs#L209-L228 and then if you receive a DFU request to the setup endpoint you acknowledge and reboot into bootload https://github.com/adamgreig/ffp/blob/37e163752ae6e86887806ae7a17294925f3c6bbf/firmware/src/hal/usb/control_endpoint.rs#L372
<re_irc> < (@adamgreig:matrix.org)> if you are doing that, you can implement a tiny bit of the usb dfu protocol as an extra interface, then dfu-tool etc software can detect it and tell it to reboot into bootloader
<re_irc> < (@adamgreig:matrix.org)> Félix the Newbie: for stm32f0 I did this: https://github.com/adamgreig/ffp/blob/37e163752ae6e86887806ae7a17294925f3c6bbf/firmware/src/hal/bootload.rs
<re_irc> < (@adamgreig:matrix.org)> basically as people have suggested, you set a flag in ram and trigger a system reset, then at startup before doing any chip setup, you see if that ram flag is set, and if so, you jump to the internal system bootloader
<re_irc> < (@jamesmunns:beeper.com)> > Do I have to write all this code? I just want to put it in a state where my tool can flash a new bin
<re_irc> You need to call/reboot into the hardware DFU bootloader. We're explaining different ways to do that.
<re_irc> < (@adamgreig:matrix.org)> these days use cortex_m::asm::bootload() to make it easier
<re_irc> < (@adamgreig:matrix.org)> but if you do that just after a reset, you don't have to reconfigure any hardware peripherals, because the bootloader's designed to work out of a reset state
<re_irc> <Félix the Newbie> Alright, thanks to everyone.
<re_irc> <Félix the Newbie> : I don't get where I'm supposed to use that
<re_irc> < (@adamgreig:matrix.org)> it replaces these lines of code, in the function I call just after reset: https://github.com/adamgreig/ffp/blob/37e163752ae6e86887806ae7a17294925f3c6bbf/firmware/src/hal/bootload.rs#L28-L35
<re_irc> < (@adamgreig:matrix.org)> (it gets called here, in pre_init: https://github.com/adamgreig/ffp/blob/37e163752ae6e86887806ae7a17294925f3c6bbf/firmware/src/main.rs#L29)
<re_irc> <Félix the Newbie> Why is there 2 steps? Why not to jump to the internal bootloader directly? Is it so that the chip is in a consistent state each time?
<re_irc> < (@adamgreig:matrix.org)> yep - if you just jump to the internal bootloader in the middle of your normal code, it won't work, because you've configured all these peripherals in ways it doesn't expect
<re_irc> < (@adamgreig:matrix.org)> 's example above de-configures those peripherals before jumping to it, mine and 's examples reset the chip to reset all of the peripherals, but leave a flag behind so it knows to jump to bootloader at start
<re_irc> <Félix the Newbie> OK, that's clear now. Thanks for the explanation!
<re_irc> <Félix the Newbie> I think I'll go for the latter, it looks easier.
<re_irc> < (@adamgreig:matrix.org)> https://www.st.com/resource/en/application_note/cd00167594-stm32-microcontroller-system-memory-boot-mode-stmicroelectronics.pdf is the document mentioned btw, it explains how the bootloader is configured for your particular stm32
<re_irc> < (@adamgreig:matrix.org)> including which address you need to jump to
<re_irc> <Félix the Newbie> Just a question: if I set a flag before the reset, why isn't it reset as well?
<re_irc> < (@jamesmunns:beeper.com)> at least with panic-persist, it keeps a section of non-initialized memory outside of the main ram.
<re_irc> < (@jamesmunns:beeper.com)> so it doesn't get reset.
<re_irc> <Félix the Newbie> What if I use "cortex_m::peripheral::SCB::sys_reset()": does it keep the same section as is?
<re_irc> < (@jamesmunns:beeper.com)> nothing in RAM gets reset by sys_reset
<re_irc> < (@jamesmunns:beeper.com)> that's done by cortex-m-rt after boot, and it only initializes the .data and .bss sections. The panic-persist section is outside of both of those.
<re_irc> < (@adamgreig:matrix.org)> if you check the flag in pre_init, it happens before cortex-m-rt zeroes/initialises the memory
<re_irc> < (@adamgreig:matrix.org)> so you don't even need an extra linker section that you leave uninitialised
<re_irc> < (@jamesmunns:beeper.com)> (can pre-init still be in Rust these days? that seems super UB)
<re_irc> < (@adamgreig:matrix.org)> (but if you're using panic-persist anyway, then it's convenient to use its flag to detect a panic, and I guess manually set it if you want to trigger a bootload)
<re_irc> <Félix the Newbie> Oh, so that's even easier. I just need to:
<re_irc> - call the "SCB::sys_reset()" function,
<re_irc> - check the flag at the beginning of the main,
<re_irc> - jump to the right bootloader address
<re_irc> - set the flag,
<re_irc> < (@jamesmunns:beeper.com)> Yes, that's what my feather-405 example does :)
<re_irc> < (@adamgreig:matrix.org)> that's almost right, but if you check the flag in main(), then the code that runs before main() will have zeroed out the flag for you, unless you put the flag in a different linker section that's not zeroed
<re_irc> <Félix the Newbie> : I've been given a ton of links, I haven't seen them all :3
<re_irc> < (@adamgreig:matrix.org)> so either you can use a normal static variable flag and check it in pre_init, or you can put a static variable flag into a different memory section and check it in main
<re_irc> <Félix the Newbie> : I don't know yet how to do the latter, I'll have a look at that.
<re_irc> <Félix the Newbie> : What is the canonical memory section to put that?
<re_irc> < (@adamgreig:matrix.org)> I don't think there's anything "canonical", it'd be some special made up section just for this
<re_irc> < (@adamgreig:matrix.org)> call it bootload_flag or something
<re_irc> <Félix the Newbie> You mean that I can create an entirely new section? I didn't know it's possible.
<re_irc> < (@adamgreig:matrix.org)> there's an example here: https://docs.rs/cortex-m-rt/latest/cortex_m_rt/#extra-sections
<re_irc> <Félix the Newbie> It looks like the compiler doesn't like that in the latest edition
<re_irc> < (@adamgreig:matrix.org)> oh?
<re_irc> <Félix the Newbie> > declaration of a static with "link_section" the program's behavior with overridden link sections on items is unpredictable and Rust cannot provide guarantees when you manually override them
<re_irc> There is a “forbid unsafe” in my code, that's why it doesn't like it. It's considered as unsafe now.
<re_irc> < (@adamgreig:matrix.org)> I guess you can "#[allow]" it for this declaration, then
<re_irc> <Félix the Newbie> I was naive, wanting to write my full firmware without an unsafe instruction. Jumping to the bootloader is unsafe anyway, so…
<re_irc> < (@adamgreig:matrix.org)> you might find it's nice to put all the "logic" of the firmware in a separate crate which can be entirely safe code, and then the final application crate pulls in that logic and has a few unsafe bits where necessary to interact directly with things like jumping to bootloader
<re_irc> < (@adamgreig:matrix.org)> this particular instance is a bit tricky to be honest: it's UB to read from uninitialised memory, which is basically what you'd be doing by having an extra link section with a variable in it
<re_irc> < (@adamgreig:matrix.org)> a lot could be said on the topic... probably today the only way to be completely sure you're not touching rust UB while preserving this flag across reboots is to write everything that deals with the flag in assembly and use a memory address the compiler doesn't know about, but that's a bit laborious
<re_irc> < (@adamgreig:matrix.org)> (for example: change memory.x to tell it SRAM is 4 bytes shorter than it really is, then use the address of that final 4 bytes as your flag variable, and read/write it using asm, but, ugh..)
<re_irc> <Félix the Newbie> This is UB?
<re_irc> static BOOTLOAD_FLAG: AtomicU8 = AtomicU8::new(0);
<re_irc> Maybe I can write it inside a regular static, as you were saying, and check in pre-init.
<re_irc> #[link_section = ".bootload_flag"]
<re_irc> Is it totally impossible to write in the flash memory? I guess so
<re_irc> <Félix the Newbie> : Yeah, maybe it's a bit too much 😅
<re_irc> < (@adamgreig:matrix.org)> in _practice_ that's unlikely to go wrong (but AtomicBool could be deadly as the SRAM might contain some invalid value for a bool), but by the letter it's still UB because that static will never actually get initialised
<re_irc> < (@adamgreig:matrix.org)> using flash memory doesn't really help you here
emerent has quit [Ping timeout: 248 seconds]
<re_irc> < (@adamgreig:matrix.org)> (you still have to read some random uninitialised memory)
emerent has joined #rust-embedded
<re_irc> < (@adamgreig:matrix.org)> and writing it is slow, a pain, have to erase potentially several kB of flash, wears out the flash, etc
<re_irc> <Félix the Newbie> Oh, OK. Is there a way to deal with the UB of reading uninitialized memory with "MaybeUninit"?
<re_irc> < (@adamgreig:matrix.org)> you need to read it before it gets initialised, because you want to know what was written when you rebooted, but you might have just booted instead
<re_irc> < (@adamgreig:matrix.org)> I wonder if you could argue the case for "check reset cause, if it was sysreq then assume init", but I don't think it would actually buy you anything here
<re_irc> < (@adamgreig:matrix.org)> sorry, this happens to jump into a silly deep end of the edges of what's well defined in rust at the moment, in practice personally I'd just be doing a static mut and read_volatile/write_volatile to it, understanding that it's technically UB at present
<re_irc> < (@adamgreig:matrix.org)> I think if you wanted to definitely avoid UB, you'd do this using "asm!()"
<re_irc> <Félix the Newbie> But I'd need to modify the memory file, because otherwise, I'd have no way to know if it's used by something else. That file is autogenerated in my project, I don't want to mess up with it.
<re_irc> <Félix the Newbie> * the address is
<re_irc> < (@adamgreig:matrix.org)> indeed
<re_irc> < (@adamgreig:matrix.org)> _maybe_ you could have a static mut that you only access from asm blocks, heh
crabbedhaloablut has quit [Quit: No Ping reply in 180 seconds.]
<re_irc> <Félix the Newbie> : Is there no other way to tell the compiler that I want to read a byte, but have no way to know if it was initialized?
Foxyloxy_ has joined #rust-embedded
crabbedhaloablut has joined #rust-embedded
<re_irc> <Félix the Newbie> In theory (outside of the Rust model), the compiler could just chose to read whatever value is at that address.
Foxyloxy has quit [Ping timeout: 264 seconds]
Foxyloxy has joined #rust-embedded
Foxyloxy_ has quit [Ping timeout: 268 seconds]
Foxyloxy_ has joined #rust-embedded
Foxyloxy has quit [Ping timeout: 260 seconds]
<re_irc> <Félix the Newbie> The doc says it's UB to read any static variable: https://docs.rs/cortex-m-rt/latest/cortex_m_rt/attr.pre_init.html
<re_irc> Does it change anything, if it's done with the "asm!" macro?
<re_irc> < (@adamgreig:matrix.org)> in asm, there's not really a concept of "uninitialised", you just tell the cpu to read an address, and it does it, and if the address isn't mapped it faults
<re_irc> < (@adamgreig:matrix.org)> arguably taking a reference to a static to pass into the asm block could get you in trouble too, but maybe addr_of could help there
<re_irc> < (@adamgreig:matrix.org)> probably worth getting this "jump to bootloader" feature working first and maybe come back to worrying about the precise semantics though, so little of this is fully documented or has any guarantees at all, since you're really operating outside of what rust knows about
<re_irc> <Félix the Newbie> : Yes, but it's no real ASM, it's a Rust wrapper which, maybe, holds the same guarantee as any other Rust code.
<re_irc> Anyway, you're right, I'll implement that stuff, then I'll see the exact semantic.
<re_irc> <Félix the Newbie> : Which pointer should I put here?
<re_irc> < (@adamgreig:matrix.org)> the one from that ST PDF, depends on your stm32
<re_irc> <Félix the Newbie> * What pointer should I put here? https://docs.rs/cortex-m/latest/cortex_m/asm/fn.bootload.html
<re_irc> < (@adamgreig:matrix.org)> ^this one
<re_irc> < (@adamgreig:matrix.org)> looks like 0x1FFFD800 for all stm32f3
<re_irc> <Félix the Newbie> : It says:
<re_irc> > 8 Kbyte starting from address 0x1FFFD800, contains the bootloader firmware.
<re_irc> < (@adamgreig:matrix.org)> so "cortex_m::asm::bootload(0x1FFFD800 as *const u32)"
<re_irc> <Félix the Newbie> I dunno why it's called vector table or something in the doc, it's just the bootloader firmware address 🤔
<re_irc> < (@jamesmunns:beeper.com)> it's the vector table of the bootloader firmware
<re_irc> < (@adamgreig:matrix.org)> yea, the docs could perhaps be clearer - the bootloader firmware starts with a vector table
<re_irc> < (@jamesmunns:beeper.com)> vector table includes two things in consecutive words - the initial stack pointer and the reset vector
<re_irc> < (@adamgreig:matrix.org)> generally most cortex-m firmware images will start with a vector table, the first u32 of which is the initial stack pointer, then after that the reset vector which is the address to actually start running code from
<re_irc> < (@adamgreig:matrix.org)> you might also need to make the bootloader vector table active, on an f3 by writing to the VTOR register
<re_irc> < (@jamesmunns:beeper.com)> oh, does bootload not do that?
<re_irc> < (@adamgreig:matrix.org)> no (since no vtor on cm0 etc)
<re_irc> < (@jamesmunns:beeper.com)> (I guess that makes sense it doesn't, might also explain why I had issues if the bootloader code expects that)
<re_irc> < (@adamgreig:matrix.org)> and you might not want to in general necessarily, I guess? still
<re_irc> < (@jamesmunns:beeper.com)> yeah, makes sense
<re_irc> <Félix the Newbie> Is it related to this? https://docs.rs/cortex-m/latest/cortex_m/asm/fn.bootstrap.html
<re_irc> < (@jamesmunns:beeper.com)> yeah, bootload is basically that but with sequential pointers
<re_irc> < (@jamesmunns:beeper.com)> so rv == (msp.add(1))
<re_irc> < (@adamgreig:matrix.org)> bootload is a higher-level convenience wrapper around bootstrap
<re_irc> < (@jamesmunns:beeper.com)> (1 word, or 4 bytes)
<re_irc> < (@adamgreig:matrix.org)> assuming you have already taken the cortex_m peripherals (or rtic does this for you), it's "cp.SCB.vtor.write(0x1FFFD800);"
<re_irc> <Félix the Newbie> : Oh, thank you
<re_irc> <Félix the Newbie> : Uh, but I need that before init, right? And I get the peripherals as a init parameter.
<re_irc> < (@adamgreig:matrix.org)> hah, you're right, that's a good point. "unsafe { (*cortex_m::peripheral::SCB::PTR).vtor.write(0x1FFFD800) };"
<re_irc> <Félix the Newbie> It works, thanks everyone 🥳
<re_irc> <Félix the Newbie> Here is the code:
<re_irc> use core::{arch::asm, ptr};
<re_irc> pub mod bootload {
<re_irc> const BOOTLOAD_OFF: u8 = 0;
<re_irc> <Félix the Newbie> I use the "asm!" macro, but I'm really interested in its semantic, maybe it's semantically the same thing as a pointer read.
<re_irc> < (@adamgreig:matrix.org)> it's probably worth putting BOOTLOAD_ON to something less likely to occur by chance
<re_irc> < (@adamgreig:matrix.org)> maybe use a u32 and some distinct pattern
<re_irc> <Félix the Newbie> : Can all the bits be put to 1 by chance?
<re_irc> < (@adamgreig:matrix.org)> I guess it might be more likely than all being some specific other value you pick, though I'm not really sure what the distribution is at power-on
<re_irc> <Félix the Newbie> I did what you said. It cannot hurt anyway.
Dr_Who has joined #rust-embedded
<re_irc> < (@adamgreig:matrix.org)> Félix the Newbie: oh, I don't think your asm is donig the right thing here, it's causing the compiler to do a normal read of BOOTLOAD_FLAG into a register, than you just copy the value from that register to a new register, then you check it
<re_irc> <Félix the Newbie> But it works tho
<re_irc> < (@adamgreig:matrix.org)> you probably want something more like "asm!("ldr {0}, {1}", out(reg) flag, in(reg) addr_of!(BOOTLOAD_FLAG))" maybe
<re_irc> < (@adamgreig:matrix.org)> * [{1}]",
<re_irc> < (@adamgreig:matrix.org)> (which makes the compiler load the address of FLAG into a register and then your assembly causes a read from memory at that address into a new register is "flag")
<re_irc> <Félix the Newbie> : It's not "ldr", but I cannot see a list of operands.
<re_irc> > The set of memory locations that assembly code is allowed to read and write are the same as those allowed for an FFI function.
<re_irc> < (@adamgreig:matrix.org)> what do you mean you can't see a list of operands?
<re_irc> <Félix the Newbie> ldr isn't a thing, so I'm looking for an exhaustive list of the operands. Sorry, at you can see, English isn't my native language, so I don't always express myself clearly.
<re_irc> < (@adamgreig:matrix.org)> ldr is a thing - asm emits assembly for your specific target, which is an ARMv7-M CPU, and that ARM instruction set has "ldr" among others
<re_irc> < (@adamgreig:matrix.org)> it's directly platform-specific assembly, not translated into anything else
<re_irc> < (@adamgreig:matrix.org)> you want section A7.7.45 in https://developer.arm.com/documentation/ddi0403/ee/
<re_irc> <Félix the Newbie> Oh, my bad, I forgot to add the [] pair. BTW, I didn't know it's direct assembly. I thought it was translated somehow.
crabbedhaloablut has quit [Remote host closed the connection]
<re_irc> < (@adamgreig:matrix.org)> * A7.7.43
crabbedhaloablut has joined #rust-embedded
<re_irc> <Félix the Newbie> I just tested it, it works fine, thanks 🙏
<re_irc> <Félix the Newbie> : I just tested it, it works fine, thanks 🙏
<re_irc> < (@adamgreig:matrix.org)> I forgot to put the [] in when i wrote it at first 😅
<re_irc> < (@adamgreig:matrix.org)> cool! I think that's pretty sound as these things go then, you avoid accessing the uninitialised static directly from rust
<re_irc> < (@adamgreig:matrix.org)> hi room , meeting time again! agenda is https://hackmd.io/VxqI1m1iRhG9uMzQ8wnfXw, please add anything you'd like to announce or discuss, and we'll start in a few min
crabbedhaloablut has quit [Remote host closed the connection]
<re_irc> < (@adamgreig:matrix.org)> ok, let's start! two quick release announcements, probe-rs 0.16 (and 0.15!) are out with a bunch of new features, bugs fixed, target support, etc, and stm32-eth is out with support for using the ptp hardware among other fixes
<re_irc> < (@adamgreig:matrix.org)> and, if anyone's interested in helping maintain the aarch64-cpu crate (and other cortex-a stuff in the wg), please let me know, as one of the current maintainers had to step down
<re_irc> < (@adamgreig:matrix.org)> does anyone else have any announcements?
crabbedhaloablut has joined #rust-embedded
<re_irc> < (@adamgreig:matrix.org)> cool, otherwise there's a new issue on e-h that might be worth a discussion about Delay taking &mut, https://github.com/rust-embedded/embedded-hal/issues/435
<re_irc> < (@adamgreig:matrix.org)> it does seem pretty common that people have one Delay, maybe from cortex_m's SysTick or from a timer in their HAL, and need several and get stuck
<re_irc> < (@adamgreig:matrix.org)> but possibly the answer is to encourage HALs etc to provide cloneable/freely created Delays and keep the traits as &mut for implementations that do need to be unique?
<re_irc> < (@adamgreig:matrix.org)> perhaps cortex-m could lead by example here by having something that consumes systick and runs a background timer that can be used for lots of delays, but that requires binding the interrupt somehow...
<re_irc> < (@jannic:matrix.org)> Currently, the Delay from cortex_m busy waits on self.syst.has_wrapped(), no interrupts involved.
<re_irc> Would it be possible to just leave the counter running and detect the wraparound by comparing values? Then multiple delay instances could use the same peripheral.
<re_irc> < (@jannic:matrix.org)> Worst case, a delay may miss a wraparound and wait for too long, but that's a) not probable, and b) not strictly forbidden, the delay may always be longer than asked for.
<re_irc> < (@adamgreig:matrix.org)> yea, maybe? just leave systick running, and the Delay impl busy-polls reading it, detecting wraparound, and waits for its expected delay?
<re_irc> < (@adamgreig:matrix.org)> it can miss wraparound if an interrupt happens but it'd have to be a pretty long interrupt
<re_irc> < (@jamesmunns:beeper.com)> systick rolls REALLY fast on faster CPUs
<re_irc> < (@jamesmunns:beeper.com)> (every 262ms at 128MHz)
<re_irc> < (@jamesmunns:beeper.com)> like, "longer than an interrupt", but "can't delay for more than 262ms" is sorta a weird UI, unless you also are watching/counting wraps.
<re_irc> < (@adamgreig:matrix.org)> yea, you'd watch the wraparounds to delay for longer than one period
<re_irc> < (@adamgreig:matrix.org)> the issue is just if you miss one wraparound happening you'd delay longer, but you don't need to see the moment it happens, you just need to be blocked for more than half the period
<re_irc> < (@adamgreig:matrix.org)> +not
<re_irc> < (@jannic:matrix.org)> The current implementation already counts wraparounds, so that wouldn't change.
<re_irc> < (@jannic:matrix.org)> And if it gets blocked for more than one period, it would also only count one wraparound.
<re_irc> < (@jannic:matrix.org)> So the change would be "waits too long if interrupted for more than 1 period" to "waits too long if interrupted for more than 1/2 period"
<re_irc> < (@adamgreig:matrix.org)> oh indeed
<re_irc> < (@adamgreig:matrix.org)> seems kinda nice
<re_irc> < (@adamgreig:matrix.org)> I guess you'd have a struct that takes ownership of SYST, configures and starts it running, and then gives out as many Delay impls as you want
<re_irc> < (@adamgreig:matrix.org)> so long as the impls don't outlive the parent struct
<re_irc> < (@dirbaio:matrix.org)> these'd have to be "!Send" though
<re_irc> < (@jannic:matrix.org)> I wonder if it should support freeing the SYST again. That would require some kind of reference counting.
<re_irc> < (@dirbaio:matrix.org)> otherwise you could have one delay preempting another
<re_irc> < (@jamesmunns:beeper.com)> you could look at groundhog, this is basically how it works
<re_irc> < (@dirbaio:matrix.org)> which would screw up the preempted one
<re_irc> < (@jamesmunns:beeper.com)> (though it doesn't really count overflows, I mostly mean the "GlobalRollingTimer" interface I have)
<re_irc> < (@adamgreig:matrix.org)> how would they pre-empt?
<re_irc> < (@jannic:matrix.org)> : How so, if they all just read the timer value?
<re_irc> < (@jamesmunns:beeper.com)> (conversation has drifted, we started with interrupts, and moved to "counting overflows" in a blocking manner)
<re_irc> < (@dirbaio:matrix.org)> if a delay gets preempted for longer than an overflow
<re_irc> < (@dirbaio:matrix.org)> ah but it'd wait for _at least_ the requested time so it might still be fine
<re_irc> < (@jannic:matrix.org)> Some interrupt based delay might be nice for energy efficiency, but it's a completely different beast.
<re_irc> < (@jannic:matrix.org)> And might be a good reason to use async instead.
<re_irc> < (@adamgreig:matrix.org)> yea, in frameworks like embassy you get a system time counter and all the energy-efficient delays you want, right
<re_irc> < (@korken89:matrix.org)> Feel free to copy paste of8 you want https://github.com/rtic-rs/cortex-m-rtic/blob/rticv2/rtic-monotonics/src/systick_monotonic.rs :)
<re_irc> < (@adamgreig:matrix.org)> but for really simple examples a lot of people want some Delays and only getting one out of cortex-m seems a regular pain
<re_irc> < (@adamgreig:matrix.org)> : does that help? the objective is to not need interrupts
<re_irc> < (@korken89:matrix.org)> Ah wait, this was the non async
<re_irc> < (@korken89:matrix.org)> Feel free to copy paste if you want https://github.com/rtic-rs/cortex-m-rtic/blob/rticv2/rtic-monotonics/src/systick_monotonic.rs :)
<re_irc> < (@dirbaio:matrix.org)> systick is not great
<re_irc> < (@korken89:matrix.org)> Not great, not terrible
<re_irc> < (@dirbaio:matrix.org)> for free-running interrupt-based timers
<re_irc> < (@dirbaio:matrix.org)> all it can do is "interrupt on overflow"
<re_irc> < (@adamgreig:matrix.org)> it's alright if you just want like a 1ms counter right?
<re_irc> < (@dirbaio:matrix.org)> set freq too high, you have interrupt spam. set freq too low, you don't have good resolution
<re_irc> < (@dirbaio:matrix.org)> this is why embassy-time has no systick impl :D
<re_irc> < (@adamgreig:matrix.org)> but since you can poll the current value and turn the interrupt off, we can set reload to 0xffffff and just read it until enough counts have happened
<re_irc> < (@korken89:matrix.org)> : Yep, this is what the stock monotonic does
<re_irc> < (@adamgreig:matrix.org)> current e-h Delay is all blocking anyway, so
<re_irc> < (@korken89:matrix.org)> * systick
<re_irc> < (@dirbaio:matrix.org)> yeah for blocking it doesn't matter
<re_irc> < (@jannic:matrix.org)> : I think that's the point here: Some beginner friendly way to pass delays to multiple drivers. They'd never run at the same time anyways, so all those preemption questions won't apply, and if a delay still happens to take slightly longer, it wouldn't be too bad either. But I still remember that, as a beginner, I was really confused when I noticed that I couldn't easily get multiple Delay instances. I...
<re_irc> ... think back then I just reached for "cortex_m::asm::delay" because I just didn't care if the delay took double the time requested.
<re_irc> < (@adamgreig:matrix.org)> and cortex_m::asm::delay doesn't even impl Delay, so it's no use for drivers that require that be passed in
<re_irc> < (@adamgreig:matrix.org)> (perhaps it should, heh)
<re_irc> < (@jannic:matrix.org)> Right! I don't remember the details, I probably just needed a delay to have a reasonable blinky frequency, and already used the one Delay I had for some driver which needed it.
<re_irc> < (@adamgreig:matrix.org)> the other option is to make Delay traits take &self and then you can pass around &, but that seems like solving the wrong problem
<re_irc> < (@adamgreig:matrix.org)> (which is what the new issue is about)
<re_irc> < (@dirbaio:matrix.org)> traits shouldn't take "&self", no
<re_irc> < (@adamgreig:matrix.org)> perhaps cortex-m could gain a Delay impl based on asm::delay where you tell it CPU freq and it tries its best (probably all delays are twice as long on non-multiple-issue platforms because ugh), as well as a systick-based one where you tell it apb freq and it watches for overflows so multiple instances can exist without writing to SYST
<re_irc> < (@adamgreig:matrix.org)> HALs would be better placed to set up some sort of system timekeeping that you could then Delay against, using actual timers and perhaps interrupts, I guess
<re_irc> < (@adamgreig:matrix.org)> anyway I suppose that means we can close the e-h issue
<re_irc> < (@dkhayes117:matrix.org)> Wrap around value checking seems like a good take for usefulness and simplicity
<re_irc> < (@adamgreig:matrix.org)> yea
<re_irc> < (@adamgreig:matrix.org)> ok, final thing on the agenda (thanks ) is this other new issue about svd2rust, https://github.com/rust-embedded/svd2rust/issues/708
<re_irc> < (@adamgreig:matrix.org)> specifically about wanting to be able to store the "W" writer so that you can write a register with most fields the same but one changed
<re_irc> < (@adamgreig:matrix.org)> you could just do "modify()", but that involves pointless re-reading and re-computing the value at each step
<re_irc> < (@dirbaio:matrix.org)> heh
<re_irc> < (@dirbaio:matrix.org)> chiptool can do it thanks to having 1 struct representing a "register value", instead of the R/W proxies
<re_irc> < (@dirbaio:matrix.org)> so you can read, get/set whatever fields, then write
<re_irc> < (@adamgreig:matrix.org)> I was about to say "waiting for to mention how chiptool solves this problem" :P
<re_irc> < (@jamesmunns:beeper.com)> I guess you could do this to_bits/from_bits, with proper typeck?
<re_irc> < (@jamesmunns:beeper.com)> like the impl should be possible I think, it's just "is this a reasonable api surface to add"
<re_irc> < (@dirbaio:matrix.org)> : well, I had this exact problem with svd2rust too :)
<re_irc> < (@dirbaio:matrix.org)> but removing the R/W proxies has downsides, like you can't easily support different enumeratedValues for read/write
<re_irc> < (@dirbaio:matrix.org)> (svd2rust already violates these with ".modify()" though)
<re_irc> < (@dirbaio:matrix.org)> and adding a _third_ struct for "represents a value of the register" will bloat compile times even more
<re_irc> < (@dirbaio:matrix.org)> so idk
<re_irc> < (@adamgreig:matrix.org)> and there's no way to pass a W into the closure atm
<re_irc> < (@adamgreig:matrix.org)> you could imagine write() returning the W and a new write_from(w: W, |w| w...)
<re_irc> < (@dirbaio:matrix.org)> the "W" is not a great fir for "represents a value of the reg" either
<re_irc> < (@dirbaio:matrix.org)> you can't read fields
<re_irc> < (@dirbaio:matrix.org)> the "W" is not a great fit for "represents a value of the reg" either
<re_irc> < (@emilgardis:matrix.org)> I suppose this shouldn't be implemented, and instead suggest to create a "WFoo::write(&mut W)" which does what you want. or redirect to chiptool which has the capability
<re_irc> < (@adamgreig:matrix.org)> what do you mean by a "WFoo::write"?
<re_irc> < (@adamgreig:matrix.org)> inside svd2rust?
<re_irc> < (@emilgardis:matrix.org)> a struct which holds the presets, if that makes sense. No, in user code
<re_irc> < (@adamgreig:matrix.org)> ah, sure
<re_irc> < (@adamgreig:matrix.org)> I guess that should compile out to the same thing in the end
<re_irc> < (@adamgreig:matrix.org)> if write() did return the W, could you use that in a closure and ignore the one it gives you?
<re_irc> < (@adamgreig:matrix.org)> "let w = reg.field.write(|w| w.field1().val()); reg.field.write(|_| w.field2().val());"
<re_irc> < (@emilgardis:matrix.org)> technically you can already take it out with mem::swap no
<re_irc> < (@emilgardis:matrix.org)> * no?
<re_irc> < (@adamgreig:matrix.org)> hah
<re_irc> < (@dirbaio:matrix.org)> spicy
<re_irc> < (@adamgreig:matrix.org)> that is spicy lol
<re_irc> < (@adamgreig:matrix.org)> is there a downside to having write() return W? it wouldn't mean any new functions so hopefully codegen/file size/compile time isn't very affected
<re_irc> < (@adamgreig:matrix.org)> I guess the downside is that W isn't meant to be especially handled by user code
<re_irc> < (@adamgreig:matrix.org)> ok, that's all we have time for this week, thanks everyone!
<re_irc> < (@dirbaio:matrix.org)> yea... what this use case needs is a struct representing a "value of the reg" ...
<re_irc> < (@dkhayes117:matrix.org)> When are "we" going to have another embedded Rust conference? ie Oxidize 2k23 :D
<re_irc> < (@lulf_:matrix.org)> Fosdem the coming weekend :)
<re_irc> < (@adamgreig:matrix.org)> I wonder if we should try and hook on to an existing conference and just have a lot of embedded people show up or something
<re_irc> < (@adamgreig:matrix.org)> it would be great to see people again! but I don't think I/the wg are up to organising a conference...
<re_irc> < (@dkhayes117:matrix.org)> : Yeah, would be alot cooler if he did 🤙 lol
<re_irc> < (@dkhayes117:matrix.org)> * we
<re_irc> < (@dkhayes117:matrix.org)> +(matthew mcconaughey voice)
<re_irc> < (@diondokter:matrix.org)> : Oh cool! We've just started porting our Rust PTP to no-std and the stm32 :D
<re_irc> < (@tiwalun:matrix.org)> and me will also be at fosdem, if anyone wants to meet up and talk about probe-rs :)
<re_irc> < (@adamgreig:matrix.org)> ah cool! I'll be interested in that, I also have a rust "ptp" impl on stm32 (though it doesn't impl all the ieee wire messages, just the concept, the hardware, the control loops, etc)
<re_irc> < (@adamgreig:matrix.org)> (I'm not involved in the stm32-eth driver work though, that's )
<re_irc> < (@diondokter:matrix.org)> We're going for the full IEEE compatibility
<re_irc> < (@datdenkikniet:matrix.org)> The main difficulty in our case came from trying to decipher ST's less-than-stellar description of how their PTP peripheral works
<re_irc> < (@datdenkikniet:matrix.org)> but now it's fully working and allows you to adjust the rate of the clock quite precisely!
<re_irc> < (@diondokter:matrix.org)> It's not yet ready to use, but the repo is here: https://github.com/tweedegolf/statime
<re_irc> < (@datdenkikniet:matrix.org)> but as adamgreig said: no wire or protocol, just the interaction with the peripheral
<re_irc> < (@diondokter:matrix.org)> Well, you saved us quite some hours of work haha
<re_irc> < (@diondokter:matrix.org)> We also have a PR open to make it async. Will be much nicer than the previous manually polling api
<re_irc> < (@adamgreig:matrix.org)> will you keep statime standalone and just have a pluggable stm32 driver, or include stm32 support directly in it?
<re_irc> < (@datdenkikniet:matrix.org)> : This looks cool! Would be super interesting to see if it can get going on STM32, and if it does we have a pretty cool usecase for it :D
<re_irc> < (@datdenkikniet:matrix.org)> * interesting
<re_irc> < (@datdenkikniet:matrix.org)> TDMA in an IoT setting, hopefully :)
<re_irc> < (@datdenkikniet:matrix.org)> +synchronized by PTP,
<re_irc> < (@diondokter:matrix.org)> So the setup is kinda messy right now and we're refactoring things, but the idea is that statime is a library and we'll provide a deamon application for linux and probably some (example?) drivers for stm32
<re_irc> < (@diondokter:matrix.org)> Basically, any platform needs to implement the network traits and the clock trait and then it can be plugged into the library
<re_irc> < (@adamgreig:matrix.org)> sounds good!
<re_irc> < (@burrbull:matrix.org)> : What you think about making some registers 16-bit? https://github.com/stm32-rs/stm32-rs/pull/802
<re_irc> < (@adamgreig:matrix.org)> : interesting, I think it makes sense, though are there any advantages compared to treating them all as 32-bit? also, sorry for the inactivity on stm32-rs stuff recently, I should have more time for it in feb
crabbedhaloablut has quit [Remote host closed the connection]
crabbedhaloablut has joined #rust-embedded
IlPalazzo-ojiisa has quit [Remote host closed the connection]