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
fabic has joined #rust-embedded
starblue has quit [Ping timeout: 248 seconds]
starblue has joined #rust-embedded
explore has joined #rust-embedded
fabic has quit [Ping timeout: 240 seconds]
dreamcat4 has joined #rust-embedded
explore has quit [Quit: Connection closed for inactivity]
fabic has joined #rust-embedded
dreamcat4 has quit [Quit: Connection closed for inactivity]
dc740 has joined #rust-embedded
dc740 has quit [Remote host closed the connection]
dc740 has joined #rust-embedded
diagprov has quit [Ping timeout: 260 seconds]
<re_irc> <barafael> I need some help using "cross". I just want to build my program for "armv7-unknown-linux-musleabihf", which works fine with "--target armv7-unknown-linux-musleabihf". Except, in one configuration, my program has some xcb dependencies which I need to "apt install" or whatever. Is there a way to have a simple own dockerfile in "cross" that extends the dockerfile which "cross" already applies for...
<re_irc> ... "armv7-unknown-linux-musleabihf"?
diagprov has joined #rust-embedded
<re_irc> <dcz> how do I make the codegen emit floating point instructions on arm?
dreamcat4 has joined #rust-embedded
<Lumpio-> By choosing a target that has floating point
<Lumpio-> Usually ends in "hf" or something iirx
<Lumpio-> iirc*
<re_irc> <dcz> should the output of "rustc --target thumbv7em-none-eabihf --print cfg" change?
fabic has quit [Ping timeout: 240 seconds]
<re_irc> <riskable> Can someone point me to some good articles about programming patterns for embedded Rust? Trying to sharpen my skills.
<re_irc> <firefrommoonlight> http://cliffle.com/p/dangerust/
<re_irc> <firefrommoonlight> Long, but detailed
<re_irc> <firefrommoonlight> https://docs.rust-embedded.org/book/
<re_irc> <firefrommoonlight> Overview article I wrote - https://www.anyleaf.org/blog/writing-embedded-firmware-using-rust
<re_irc> <riskable> firefrommoonlight: I just had a look at these three links and they're not really what I'm looking for. I'm looking for useful _patterns_. Like, if I want to have something like an event-based system (in "no_std" Rust) what's a good way to go about doing that? Or if I want to make a crate that works with plugins/extensions, how do you do that in a static way? Or if you have a lot of user-configurable, hardware-speciic...
<re_irc> ... preferences how do you manage that in an embedded Rust project?
<re_irc> <riskable> I'm trying to make a keyboard firmware crate that works with many different kinds of keyboard hardware (more than just matrices of switches with diodes; analog keyboards and the like too). If I make a function that needs to check the state of a lot of things (e.g. sensors, pins, I2C stuff) in order to decide on which user-defined action to take how do you do that in a way that keeps rustc happy? Things like that.
<re_irc> <riskable> For example, I have an analog rotary encoder design that uses two hall effect sensors that need to be read regularly and their values/state needs to be tracked in order for it to work. Let's say I wanted to add support for this kind of rotary encoder to my keyboard firmware... What's the best way to go about that? End users would need to have some way to specify in their own code how many encoders they have and some...
<re_irc> ... way to pass in the analog channel readings to the functions that determine the resolution and direction the encoder was turned. Then that function needs to call some action that gets defined by the end user.
<re_irc> <riskable> Since the size of everything in embedded rust needs to be known at compile time (for the most part) I need some mechanism for the _amounts_ of everything to be known not only by the firmware but the other crates & things the firmware is using in the background. I want programming patterns related to that sort of thing
dreamcat4 has quit [Quit: Connection closed for inactivity]
<re_irc> <riskable> I've got code that works but it's _ugly_. I have functions that take arguments like this:
<re_irc> layout: &mut Layout<C, R, L, CustomActions<C,R,L>>,
<re_irc> <riskable> ...and just to call the function you have to do stuff like this: "event_scanner::<16,3,4>(<the args>)"
<re_irc> <riskable> That "<16,3,4>" bit is what gets in the way of everything: Because every little ".rs" file needs to know those values and they can't just be passed around as arguments
<re_irc> <riskable> So the end user (who may not know much Rust) has to hard-code a bunch of "const" values a the top of some ".rs" file. I made a "build.rs" that can generate a "userconfig.rs" from a .toml file but it seems very heavy-handed for something so simple as a handful of numeric values.
<re_irc> <riskable> There's got to be "a better way"
<re_irc> <robtsuk> Have you tried using traits?
<re_irc> <riskable> robtsuk: Yeah but you can't use "dyn Trait" if you have things like arrays since they'll lack "Sized"
<re_irc> <riskable> (and literally everything needs arrays of stuff when it comes to keyboard hardware haha)
<re_irc> <robtsuk> yah, not dyn trait
<re_irc> <robtsuk> so there's the part of your system that you want to be generic and then the parts that you want other developers to customize
<re_irc> <robtsuk> can you define traits to express the interface between the generic parts and the customizable parts?
<re_irc> <riskable> robtsuk: Exactly. And there's a 3rd part: That end users can customize that may not have written the firmware themselves (they just "git clone"d it)
<re_irc> <riskable> Think: End users writing their own keyboard macros
<re_irc> <riskable> So if I make a generic firmware _system_ of sorts it'll need to somehow statically know about things like end user macros
<re_irc> <riskable> ...but since such a crate would merely be a dependency I can't just fix it all by writing a "build.rs" that generates everything
<re_irc> <robtsuk> So, if you can define a trait to express the interface between your system and the parts you want to make customizable
<re_irc> <riskable> (main crate can't pass things through to dependency "build.rs", sadly)
<re_irc> <robtsuk> you can have your parts take references that implement those traits
<re_irc> <robtsuk> then your developers just have to implement them
<re_irc> <riskable> I tried to do that but every trait needs to take things that require arrays of indeterminate lengths (i.e. using const generics)
<re_irc> <robtsuk> why arrays and not slices?
<re_irc> <riskable> So when calling the function you pass in a slice of the array instead of the whole thing?
<re_irc> <robtsuk> right, although I think an array automatically derefs to a slice
<re_irc> <robtsuk> since slices carry their lengths, the length of the data doesn't have to be part of the type
<re_irc> <riskable> I swear I tried something like this but the borrow checker wasn't letting me. I can't remember the problem though
<re_irc> <riskable> That was before I learned about "heapless::Vec" though :D
<re_irc> <riskable> This is why I need a good reference doc of useful programming patterns in embedded Rust 😄
<re_irc> <robtsuk> anyway, traits are the way I usually chose to provide an interface to a developer, since for me, generics are harder to work with
<re_irc> <riskable> I guess the problem I have with doing it via traits is that it doesn't provide any benefit to the firmware developer: The logic for checking key sensor/encoder state is a bit complicated and if I just make a trait available that defines what functions they need to write I'm not really making their lives easier... They still have to figure out all that logic "them damned selves"
<re_irc> <robtsuk> if that's the case then I think your traits aren't narrowly defined enough
aspe has joined #rust-embedded
<re_irc> <robtsuk> they should express only the questions you need to ask the firmware developer and the information you need to give them
<re_irc> <firefrommoonlight> Create a configuration program that runs on the PC the keyboard connects to. Using a GUI etc, send data to the MCU over USB. This will be stored in either onboard-MCU, or offboard flash. Use programming logic as required
<re_irc> <firefrommoonlight> +on the MCU to enable or disable features etc
<re_irc> <riskable> Key states aren't too bad; it's just threshold checking and whatnot. The analog encoder logic is this _enormous_ conditional, haha
<re_irc> <firefrommoonlight> +based on the flash contents. When able, have the MCU auto-detect which hardware is connected
<re_irc> <firefrommoonlight> Also, DIY keyboards have been done to death
<re_irc> <riskable> It's not about "DIY keyboards" it's about giving the end user the ability to make their keyboard do what they want (even for a store-bought keyboard)
<re_irc> <firefrommoonlight> Sorry; that was a derail
<re_irc> <firefrommoonlight> (deleted comment was snarky comment about DIY keyboards being common)
<re_irc> <riskable> For reference, I don't think _anyone_ has really solved this problem. If you look at how to customize QMK, for example, it's a nightmare. End users are expected to write C, haha
<re_irc> <riskable> I think we can do better than that and "embedded-hal" is 90% of the magic to make it happen
<re_irc> <riskable> ...but I still need to provide some crate(s) that handle mapping keys to functions/events in a way that makes it easy for the end user to customize
<re_irc> <firefrommoonlight> struct PeripheralsConnected {
<re_irc> pub racing_leds: LedColor,
<re_irc> // ...
<re_irc> pub click_amplifier: bool,
<re_irc> <riskable> firefrommoonlight: That's kinda like what I've got now:
<re_irc> /// All the analog channel state information is owned here which is important
<re_irc> pub struct PeripheralStates<'a> {
<re_irc> /// because it allows sibling 'states to mutably access it
<re_irc> <riskable> The problem comes when the end user's configuration comes into play: I won't know how many sequences/layers/whatever they've configured at compile time
<re_irc> <riskable> The hardware-specific firmware will know that though
<re_irc> <riskable> (because that's where the end user config will live)
aspe has quit [Quit: aspe]
<re_irc> <riskable> I'm planning on moving from "channel_states", "encoder_states", and "mouse_state" to an enum that can represent any of those things (and a regular matrix) eventually.
<re_irc> <riskable> That way my code can just iterate over an array (or "heapless::Vec") of that enum and handle each peripheral type accordingly
<re_irc> <firefrommoonlight> Do you need to know at compile time? Obviously knowing at comp time will help you keep flash size down, but I don't know if that's an issue
<re_irc> <riskable> I already do that with encoder_states: My firmware logic supports regular digital encoders (including ones with a Z channel), analog encoders, absolute digital encoders (with up to 12 position channels), and analog absolute positional encoders.
<re_irc> <firefrommoonlight> If not, what's the problem you're running into?
<re_irc> <riskable> firefrommoonlight: This is the problem... Every keyboard-to-USB crate requires all that stuff be known at compile time. I guess I'll have to write my own if I want to handle this problem
<re_irc> <riskable> (rather, "crate that generates USB key events"
<re_irc> <riskable> * events")
<re_irc> <robtsuk> I'm afraid I've got no suggestions for that one
<re_irc> <kristoff ⚡️> Hi all, Somebody from our radioclub had this idea: attach some kind of device to a kite, fly it in the air, take a photo and transmit it using a handheld radio on the kite.
<re_irc> <kristoff ⚡️> problem is that a photo takes pretty long (20 ro 30 seconds), so we have to make sure that the photo is a good one
<re_irc> <kristoff ⚡️> idea is to take a number of photo;s and do some analysis .. like 'is there something on the image' (or it is just all gray), or is the image sharp
<re_irc> <kristoff ⚡️> are there rust libraries that can do this kind of analysis
<re_irc> <kristoff ⚡️> the idea is to use a ESP32CAM (so esp32 + ov2640 cam)
<re_irc> <kristoff ⚡️> (but if somebody has an idea for a better hardware sollution, that would also be nice) :-)
<re_irc> <adamgreig> a very simple analysis if you are getting jpeg out the ov2640 is to just check the file size and transmit the biggest, since it's probably the most interesting
<re_irc> <kristoff ⚡️> ok .. good point .. more detail in the image will probably result in bigger jpeg file
<re_irc> <kristoff ⚡️> my idea was to do edge-detection of the image, and then take the average of all the pixels
<re_irc> <kristoff ⚡️> a sharper image with more details should have more edges
<re_irc> <kristoff ⚡️> question is .. are there rust libraries for this?
<re_irc> <kristoff ⚡️> my first idea was to do this with a raspberry pi with python but due to mechanical stability something like an ESP32 is probably better ...
<re_irc> <kristoff ⚡️> hence . rust
<re_irc> <kristoff ⚡️> there is a crate called raster that seems to be able to do "sharpen" but no "edge detection"
<re_irc> <adamgreig> I'm not aware of any, but searching for "sobel" which is a type of edge detection brings up a few crates, but I don't know that many of them would work on no-std
<re_irc> <adamgreig> maybe on esp32 you can use std anyway though
<re_irc> <adamgreig> still, the basic algorithms for edge detection can be quite simple, so maybe you can implement it?
<re_irc> <adamgreig> but I think the JPEG file size will also increase with more edges, so it might be simple and good enough
<re_irc> <kristoff 🇪🇺 🇧🇪> adamgreig: yes, good point ... i'll do some experiments
<re_irc> <kristoff ⚡️> thanks :-)
<re_irc> <adamgreig> np! I knew of people who did something like this for photos from a high altitude balloon and the jpeg file size was useful i think
<re_irc> <kristoff ⚡️> (sorry,for the double reply ... experimenting with a matrix server on my pi4, so i'm currently loged into this room twice ... )
<re_irc> <kristoff ⚡️> thx :-) ... i'll start with that .. would be nice as the OV2640 can output images in jpeg format, so I do not even need to uncompress them to determine which one is best .. (saves memory)
Lumpio- has quit [Ping timeout: 246 seconds]
aspe has joined #rust-embedded
Lumpio- has joined #rust-embedded
hifi has quit [Remote host closed the connection]
hifi has joined #rust-embedded
explore has joined #rust-embedded
aspe has quit [Quit: aspe]
<re_irc> <henrikssn> During interrupt handling on rust cortex-m there is a call to read BASEPRI register at interrupt start and write it at interrupt end. No matter what compiler optimization I use these won't be inlined. How can I get them to be inlined?
<re_irc> <adamgreig> are you using RTIC?
<re_irc> <henrikssn> Yes, using rtic
<re_irc> <adamgreig> anyway the answer is probably to use nightly rust and set the inline-asm feature on the cortex-m crate
<re_irc> <dirbaio> isn't it stable now?
<re_irc> <adamgreig> those reads/writes are coming from rtic rather than anything inherent to rust, I expect
<re_irc> <adamgreig> oh, yea, I guess you can enable the feature without needing nightly rust?
<re_irc> <adamgreig> the feature is gone in the not-yet-released cortex-m 0.8
<re_irc> <adamgreig> it still has "#![cfg_attr(feature = "inline-asm", feature(asm))]" in the 0.7 release though so I don't think it will work on stable? :/
<re_irc> <dirbaio> ah, not yet released
<re_irc> <henrikssn> error[E0554]: `#![feature]` may not be used on the stable release channel
<re_irc> --> /home/erik/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-0.7.4/src/lib.rs:58:45
<re_irc> 58 | #![cfg_attr(feature = "inline-asm", feature(asm))]
<re_irc> |
<re_irc> <henrikssn> So yeah, I guess I'm waiting for 0.8 then :)
<re_irc> <adamgreig> if you can use nightly rust, "rustup install --toolchain nightly" and "rustup target add thumbvXXXX" and "cargo +nightly build --release" or something like that, but yea, it's "fixed" in cortex-m 0.8 now that rust supports inline assembly in stable
<re_irc> <henrikssn> Is there already a planned release date for 0.8?
<re_irc> <henrikssn> This would probably shave off >10 cpu cycles which is very significant for my use case
<re_irc> <dirbaio> you can fork 0.7.x and remove that line
<re_irc> <adamgreig> or just [patch.crates-io] cortex-m = { git = "https://github.com/rust-embedded/cortex-m" }, I think
<re_irc> <adamgreig> that's probably the easiest thing to quickly try
<re_irc> <adamgreig> it will still read and write BASEPRI, just it will be inlined
dc740 has quit [Remote host closed the connection]
<re_irc> <adamgreig> I wonder if we could release 0.7.5 with just that line removed 🤔
<re_irc> <adamgreig> I guess it would be a big MSRV bump
<re_irc> <henrikssn> Thanks for the help! I'll patch cortex-m in the meanwhile and am eagerly waiting for 0.7.5 or 0.8 :)
<re_irc> <dirbaio> maybe some build.rs magic to detect rust version?
<re_irc> <adamgreig> hmmm I suppose if it remains behind a feature gate and we just remove the cfg line it would be OK?
<re_irc> <dirbaio> oh, because it was already nightly-only, so unstable?
<re_irc> <adamgreig> yea
<re_irc> <dirbaio> very true
<re_irc> <adamgreig> not as slick as the full rework of asm in 0.8 but a very simple easy change that would let you use inline-asm on stable 0.7 today, I think
<re_irc> <dirbaio> sounds good to me
<Lumpio-> LTO can't inline the external asm objects in older cortex-m?
<re_irc> <dirbaio> no :(
<re_irc> <dirbaio> dunno if it's supposed to
<re_irc> <dirbaio> but it didn't for me, at least
<re_irc> <adamgreig> it can with the lto plugin business
<Lumpio-> aw
<re_irc> <adamgreig> but it's fiddly?
<Lumpio-> I always thought those get inlined, shows what I know ┐( ̄ー ̄)┌
<Lumpio-> I never checked
<re_irc> <adamgreig> (the "linker-plugin-lto" feature on cortex-m)
<re_irc> <adamgreig> hmm, what else to backport...
cr1901 has quit [Ping timeout: 252 seconds]
<re_irc> <adamgreig> ok, https://github.com/rust-embedded/cortex-m/pull/441 for 0.7.5, though I won't be able to test it tonight, and please shout if anything else wants backporting
tafama has joined #rust-embedded
tafa has quit [Read error: Connection reset by peer]
explore has quit [Quit: Connection closed for inactivity]
<re_irc> <willeml> I am trying to write a function to let me boot a program in QSPI flash on stm32f7, but I cann't get it to boot, eventually probe-rs says "HardFaultTrampoline" and stack overflow while the code (blinky) does not get executed.
<re_irc> <willeml> I have tried 3 methods, one using asm (replacing r0 and r1 with reset vector and stack pointer respectively)
<re_irc> msr msp, r1
<re_irc> bx r0
<re_irc> The third method I tried was what is done in https://github.com/karthickai/rustboot/blob/master/src/main.rs
<re_irc> I also tried using "cortex_m::asm::bootstrap" and also "cortex_m::asm::bootload".
<re_irc> <adamgreig> is your qspi already memory-mapped correctly? if you try reading the first word of the vector table in qspi do you read the right thing, before jumping to it?
<re_irc> <willeml> As far as I know it is memory mapped correctly (I can read from it using a pointer "let read_slice = unsafe { core::slice::from_raw_parts(0x90000000 as *const u16, 32) };"
<re_irc> <willeml> And I get the correct data
<re_irc> <adamgreig> is the code you've programmed to the qspi built with a memory.x that has the qspi addresses in it?
<re_irc> <willeml> Yes
<re_irc> <willeml> I spent a while making sure of that
<re_irc> <willeml> (it was a problem initially, but according to objdump it is now fixed)
<re_irc> <willeml> The reset vector I read from the flash are "valid" (they point to positions inside the flash's address space)
<re_irc> <willeml> * is "valid" (it points
<re_irc> <dirbaio> if the booted code uses interrupts you'll have to set VTOR
<re_irc> <dirbaio> perhaps there's some weird thing with the memory buses where you can read but not execute?
<re_irc> <adamgreig> f7 allows xip from qspi in memory mapped mode so _should_ be ok
<re_irc> <adamgreig> it will even pre-fetch the next few words for you
<re_irc> <willeml> Could it be incorrect mpu settings?
<re_irc> <dirbaio> but maybe it requires extra config or it explides (?)
<re_irc> <dirbaio> * explodes
<re_irc> <adamgreig> yea, maybe there's some config needed in qspi
<re_irc> <adamgreig> are you configuring the mpu at all?
<re_irc> <adamgreig> by default at reset the mpu is off and execute from qspi should be fine
<re_irc> <willeml> I am configuring the mpu
<re_irc> <willeml> completely
<re_irc> <willeml> Should I not be doing that?
<re_irc> <adamgreig> could you try not configuring it, just in case?
<re_irc> <adamgreig> I don't think it should be necessary? not 100% sure, I haven't tried xip on f7
<re_irc> <willeml> Well, it's not necessary (flash works without it configured) but it does not fix the problem (it still doesn't execute the code)
<re_irc> <adamgreig> presumably not an mpu related issue then
<re_irc> <adamgreig> are you able to attach gdb and single-step through the boot?
<re_irc> <willeml> I could try to set up gdb, I have probe-rs running with an stlink
<re_irc> <willeml> And you mean step by step through the "os"/blink program or the bootloader?
<re_irc> <willeml> I already know that the failure point is "cortex_m::asm::bootload(0x90000000u32 as *const u32)"
<re_irc> <willeml> (everything up to that point is executed)
<re_irc> <willeml> #[entry]
<re_irc> fn main() -> ! {
<re_irc> // Initialize RTT printing (for debugging).
<re_irc> rtt_init_print!(NoBlockTrim, 4096);
<re_irc> <adamgreig> I mean step through instruction-by-instruction from that call to see what faults
<re_irc> <adamgreig> probe-rs can do gdb via cargo-embed
<re_irc> <willeml> Oh, so not at code level, at instruction level
<re_irc> <adamgreig> yea
<re_irc> <adamgreig> if you end up in the hardfault handler, you could then follow https://interrupt.memfault.com/blog/cortex-m-fault-debug to try and pin down the hardfault, but
<re_irc> <adamgreig> if you're single stepping it might become more obvious what the problem is
<re_irc> <adamgreig> like, perhaps it boots fine, and the memory initialisation from cortex-m-rt causes a fault a few instructions later
<re_irc> <willeml> Ah ok, will try that now then...
<re_irc> Valid user code at 90000000
<re_irc> sp: 0x90000000
<re_irc> Also not sure if this is relevant but here is the output of the code I posted above:
<re_irc> <willeml> Posting because the derefs look wierd
<re_irc> <adamgreig> they sure do, what was the earlier output where it dumped the first 8 bytes of flash?
<re_irc> <adamgreig> (you can just do "rprintln!("{:02x?}", read_slice)" btw)
<re_irc> <willeml> Oh thanks for that snippet, was trying to figure out a better way of doing it