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
emerent has quit [Ping timeout: 240 seconds]
emerent has joined #rust-embedded
brazuca has quit [Quit: Client closed]
crabbedhaloablut has quit [Remote host closed the connection]
crabbedhaloablut has joined #rust-embedded
GenTooMan has quit [Ping timeout: 244 seconds]
<re_irc> <jlipstate> good evening, i tried to clone the cortex-m-quickstart and as soon as it is setup to load onto a f3 discovery board, i get all manner of lang_item issues as well as Result not existing, resulting in ~500 build errors. anyone have any pointers as to what i'm doing wrong?
<re_irc> <jlipstate> it is the same if i try examples from this repo: https://github.com/rust-embedded/discovery
GenTooMan has joined #rust-embedded
<re_irc> <hartan> I have a question about the "SpiDevice" (https://docs.rs/embedded-hal/1.0.0-alpha.8/embedded_hal/spi/blocking/trait.SpiDevice.html) trait in embedded-hal. It requires "transaction" to be implemented and provides all other methods for "read", or "write". However, for example "read" requires that the underlying SPI bus implements "SpiBusRead". What happens if the Bus is write-only and doesn't implement the trait for...
<re_irc> ... reading? Will the client still offer "read", or am I unable to derive the "SpiDevice" trait in these cases?
<re_irc> <GrantM11235> You can still derive the "SpiDevice" trait, it just won't have the "read" method
<re_irc> <GrantM11235> A "where" clause on a trait method means "this method only exists in the trait if the following conditions are met"
<re_irc> <hartan> Why is the design of the SPI interface as it is right now? I'm just thinking out loud from the perspective of a user that's trying to use the traits, and a guy that's trying to patch some dependencies he needs from alpha.7 to alpha.8. In the current situation I find it hard to decide whether to patch old code to use a "SpiBus" or a "SpiDevice". I assume that the "SpiDevice" is preferable, but knowing whether this...
<re_irc> ... "Device" can really write requires me to ask whether "SpiDevice::Bus::SpiBusWrite<Word>" is implemented. Also then I need to find some HAL that implements the "SpiDevice", or I have to do it myself in my own code. But it's a distinction in either case: I can't just work with either a bus or a device in the same code. That feels weird to me. Why isn't there a trait "SpiWrite", "SpiRead" and "SpiTransaction" that each declares...
<re_irc> ... what this Spi entity can do, and an additional "SpiBus" or "SpiClient" marker trait? This way the driver doesn't have to ask for a "Bus" or "Client", it requests to have something with "SpiWrite" and then uses the traits from that. As I understand the docs, the only distinction between a "Bus" and "Client" is the shared access. But why should the code dictate this to the user? If I have a single SPI bus connected to a single...
<re_irc> ... device, why do all the locking against concurrent access and everything when I can just use the thing unconditionally? Of course this only works for simple code where the SPI is handled in one central location, but that's entirely fine for a lot of uses.
<re_irc> <GrantM11235> The PR for that new api has quite a lot of good background information and discussion about the design https://github.com/rust-embedded/embedded-hal/pull/351
<re_irc> <GrantM11235> As for how to upgrade, in most cases you should replace "where SPI: Write" with "where SPI: SpiDevice, SPI::Bus: SpiBusWrite"
<re_irc> <hartan> GrantM11235: Thanks for the info! I'll try that then.
<re_irc> <GrantM11235> dirbaio: I think I found a soundness hole in the async spi traits. A user can impl "SpiDevice::transaction" by (safely) creating an invalid pointer and passing it to the closure. Then that pointer will get deref'd in the (safe) convenience methods.
<re_irc> <GrantM11235> I think "SpiDevice" needs to be unsafe to impl
<re_irc> <9names (@9names:matrix.org)> jlipstate: did you install rust via rustup from https://rustup.rs/?
<re_irc> "rustup target add thumbv7em-none-eabihf"
<re_irc> have you installed the toolchain for your target via
<re_irc> are you compiling for your microcontroller by passing the target as an argument via the command line or .cargo/config.toml
<re_irc> cargo build --release --target thumbv7em-none-eabihf
starblue has quit [Ping timeout: 268 seconds]
starblue has joined #rust-embedded
causal has quit [Quit: WeeChat 3.6]
GenTooMan has quit [Ping timeout: 244 seconds]
GenTooMan has joined #rust-embedded
Guest14 has joined #rust-embedded
Guest14 is now known as brazuca
dc740 has joined #rust-embedded
<re_irc> <xgroleau> For those who use a crate which uses bindgen and cc to compile a C library, do you always set the environment variable manually for the CC and AR before cargo build, or is there anyway to set those variables conditionally like the target runner can be probe-run only for arm none targets.
<re_irc> <xgroleau> Nvm saw this issue (https://github.com/rust-lang/cargo/issues/8801) which is pretty much what I am experiencing
explore has joined #rust-embedded
<re_irc> <skylardive1> Does anyone know of any lighter alternative to "sprintf"?
<re_irc> <James Munns> If you are using C, there are usually a variety of differently-optimized versions for embedded (you don't mention if you are looking for optimizing for CPU time, RAM usage, code size, or a balance of some mix of those)
<re_irc> <James Munns> In Rust, there is "ufmt": https://docs.rs/ufmt/latest/ufmt/
<re_irc> <James Munns> then there are other options, like "don't format at all", using something like "defmt" or "postcard" to send your data instead.
<re_irc> <skylardive1> Nice, I'll check that out
<re_irc> <skylardive1> does it use std?
<re_irc> <James Munns> none of the things I mentioned do.
<re_irc> <skylardive1> Great
<re_irc> <James Munns> defmt and postcard aren't _exactly_ what you asked for, but still might help you:
<re_irc> defmt uses compile time trickery to make things that _look_ like printf, but automatically make a sort of ad-hoc serialization format. Instead of sending the contents, you say "this is message 5, and here's the data for it", and send that instead. Your PC "decodes" this using the original program binary and a PC side tool
<re_irc> <skylardive1> Have you used any of these crates, if so, which one have you had best experiences with?
<re_irc> <James Munns> postcard is just a general "serde" serialization format, which can allow you to do something similar, but with you specifying the "wire protocol" yourself. Still, if you want to get data off of your device, that is much cheaper than formatting it to a human readable format.
<re_irc> <James Munns> well, I wrote postcard, and I use defmt a ton (and worked at Ferrous when it was written)
<re_irc> <K900> I'm pretty sure they're still just trying to write no_std for the fun of it, for a desktop target
<re_irc> <James Munns> so, good things to say all around
<re_irc> <James Munns> ohhhh
<re_irc> <K900> Not for _actually_ embedded
<re_irc> <K900> So the answer is probably use ufmt
<re_irc> <James Munns> yeah, I agree with K900, sorry I was missing the context.
<re_irc> <James Munns> defmt could probably be made to work with non-embedded no_std envs, but it's not an "out of the box" experience.
<re_irc> <K900> They asked about writing a very small no_std binary with just libc dependencies
<re_irc> <K900> For the fun of it
<re_irc> <K900> As much as I don't find it fun, I'd also find defmt to be cheating in this particular exercise
<re_irc> <K900> * fun in the first place,
<re_irc> <James Munns> I dunno about cheating, but it certainly is a "redefine the problem" sort of approach.
<re_irc> <James Munns> but yeah, give ufmt a shot.
<re_irc> <skylardive1> Thanks.
<re_irc> <chemicstry> I was using "defmt" until I needed to log into other sinks (sd card, serial) and was really hyped about "ufmt", but it is very inconvenient that you have to replace all "Debug" traits. So just using write from core for now, which does increase code size a lot. Also are there any logging libraries that work with "ufmt"?
<re_irc> <James Munns> that's closest to what you probably want: "printf, but smol"
<re_irc> <James Munns> chemicstry: Not as far as I know. Also, you can use something other than RTT to collect defmt logs
<re_irc> <James Munns> (though, you still need to figure out the right binary to decode the message)
<re_irc> <skylardive1> chemicstry: I think I just ran into the same issue as you: ```
<re_irc> the method "do_as_formatter" exists for mutable reference "&mut [{integer}; 24]", but its trait bounds were not satisfied
<re_irc> the following trait bounds were not satisfied:
<re_irc> "[{integer}; 24]: uWrite"
<re_irc> <James Munns> https://github.com/jamesmunns/defmt-bbq/ can be used to collect defmt msgs to put wherever you want
<re_irc> <skylardive1> * you
<re_irc> <skylardive1> I forgot, how do you convert CStr into a regular str?
<re_irc> <chemicstry> yeah I know about different defmt sinks, but I also wanted to see logs from both bootloader and firmware, which are different binaries
<re_irc> <James Munns> gotcha
<re_irc> <James Munns> I'm looking at making/customizing something for mnemos
<re_irc> <James Munns> probably heavier weight than defmt
<re_irc> <James Munns> but a lot less than a general purpose approach
<re_irc> <James Munns> I actually really like tracing, and have a way that you can serialize tracing messages with postcard: https://github.com/jamesmunns/tracing-serde-structured
<re_irc> <James Munns> (note: tracing v0.1 still requires "alloc", but the unreleased v0.2 doesn't)
<re_irc> <James Munns> tracing is extremely good, but it doesn't do a great job of de-duplication, especially of large string contents, like file paths
<re_irc> <chemicstry> skylardive1: it seems that "ufmt" does not implement "uWrite" for slices, unlike "Write" from core. You will have to wrap your slice into a struct and then implement "uWrite" on it
<re_irc> <skylardive1> I'm not even using structs at all haha
<re_irc> <skylardive1> i am just trying to write a simple formatted string into a buffer
<re_irc> <skylardive1> ("abcde{}", "fgh")
<re_irc> <skylardive1> * (mybuf, "abcde{}",
<re_irc> <chemicstry> yeah the problem is not the string, but your buffer. Buffer must implement "uWrite"
<re_irc> <skylardive1> oh
<re_irc> <skylardive1> is there any easy wait to convert it back to u8?
<re_irc> <James Munns> chemicstry I have nothing for you today, but I am vaguely thinking about how to mash up defmt and tracing basically.
<re_irc> <James Munns> (some of my work on rethinking bbqueue is to help this, but again, hitting a bit of a wall there as well)
<re_irc> <chemicstry> skylardive1: "struct WriteBuf<'a>(&'a mut buf);" then implement "uWrite" for it (see ufmt example, just copy string into your slice) and you will be able to do "uwrite!(WriteBuf(&mut buf), "hello {}", "world")"
<re_irc> <skylardive1> Where do I place struct WriteBuf<'a>(&'a mut buf);?
<re_irc> <skylardive1> My buffer isn't globally accessible
<re_irc> <skylardive1> I have it inside of a scope
<re_irc> <James Munns> Basically my current thought is to use the defmt approach of "interned chunks", but to include them in the binary itself, instead of the elf file.
<re_irc> But you can chose when (if ever) you send the interned chunks, for writing to a file (like an SD card), you could put it once at the top of the file.
<re_irc> If you are doing it over a wire protocol, you could send it once at the time of first connection, or on request, or whatever.
<re_irc> <chemicstry> * [u8]);"
<re_irc> <James Munns> * choose
<re_irc> <chemicstry> skylardive1: sorry, I fixed the definition of "WriteBuf" in my message. It is just an adapter struct for any "&mut [u8]"
<re_irc> <James Munns> (or never, if you want a similar pre-shared approach as in defmt)
<re_irc> <James Munns> but again, this is still in "whiteboard doodle" stage, so don't wait on me, and feel free to steal my idea if you need it sooner. Happy to share notes :D
<re_irc> <James Munns> (as long as you promise to make it a crate I can use in mnemos later :D)
<re_irc> <chemicstry> seems a bit complicated, wouldn't it be easier to just use something like "ufmt"? Since "defmt" has the same problem with "Format" like "uDebug"
brazuca has quit [Quit: Client closed]
<re_irc> <James Munns> but "tracing's API, with defmt's wire format" is very compelling to me.
<re_irc> <James Munns> yeah, again, this wouldn't be a a "printf" replacement, it'd be a "tracing" replacement.
<re_irc> <James Munns> e.g. structured logging, rather than formatted logging
<re_irc> <James Munns> which may or may not be what you want, but it is what I want :D
<re_irc> <James Munns> so instead of saying:
<re_irc> "temp fault: temp was {}, over limit {}"
<re_irc> <skylardive1> the method `do_as_formatter` exists for struct `WriteBuf<'_>`, but its trait bounds were not satisfied
<re_irc> the following trait bounds were not satisfied:
<re_irc> `WriteBuf<'_>: uWrite`
<re_irc> which is required by `WriteBuf<'_>: UnstableDoAsFormatter`rustcE0599
<re_irc> <skylardive1> let mut parsed = [0u8; 24];
<re_irc> ufmt::uwrite!(WriteBuf(&mut parsed), "{}", "Hello").unwrap();
<re_irc> warn!(
<re_irc> <James Munns> you would instead do something like:
<re_irc> "Temperature fault",
<re_irc> temperature_c = cur_temp,
<re_irc> <James Munns> think of it more like json with fields, one of which is a text field describing the message type.
<re_irc> <James Munns> (gotta run for a bit!)
<re_irc> <chemicstry> yeah, I've used tracing for a couple of std projects, it's really nice. The scope derive thing even captures function arguments, which is so cool (although might be too heavy for embedded). But implementing structured logging on top of defmt will require additions to their wire format, or do you have something else in mind?
<re_irc> <chemicstry> skylardive1: did you implement "uWrite" for "WriteBuf" like I said? Also, now that I think about it, you will also need a write index in your "WriteBuf" struct, because ufmt will call "uWrite::write_str" multiple times during formatting so you don't want to write at the beginning of the slice each time
<re_irc> <skylardive1> I'm new to Rust, I don't think I understood everything you just said
<re_irc> <chemicstry> skylardive1: first argument to "uwrite!" is the sink, which must implement "uWrite" trait. The formatter will repeatedly call "write_str()" function (from "uWrite" trait) on this type. For example with "uwrite!(output, "Hello {}", "world")" it might call "write_str("Hello ")" and "write_str("world")" on the variable "output". So if you want to use "&mut [u8]" as an output, it must implement "uWrite" trait and have...
<re_irc> ... the associated "write_str()" functions. The problem is that you can't implement foreign traits for foreign types, which is a rust limitation to avoid colliding implementation from different crates. So you create a new type (struct), which wraps "&mut [u8]" and implement the "uWrite" trait for it
<re_irc> <chemicstry> * function.
<re_irc> <skylardive1> Oh, something like
<re_irc> }
<re_irc> struct myFmtBuffer {
<re_irc> data: &mut [u8]
<re_irc> <skylardive1> * like?
<re_irc> <chemicstry> yes
<re_irc> <chemicstry> but you also need an "index: usize" in "myFmtBuffer", which you increment on each "write_str()" call so you don't write at the start of the slice each time
<re_irc> <skylardive1> Not sure I follow. Can you elaborate on my example please?
<re_irc> <chemicstry> your "write_str()" implementation should look something like:
<re_irc> fn write_str(&mut self, s: &str) -> Result<(), Self::Error> {
<re_irc> self.index += s.len();
<re_irc> self.data[self.index..].copy_from_slice(s.as_bytes());
<re_irc> <chemicstry> you might also want to check if there is enough space in the buffer and return an error, otherwise it will panic
<re_irc> <James Munns> chemicstry: Yeah, sorry, more "defmt inspired" than "actually on top of defmt"
<re_irc> <skylardive1> chemicstry: Is there any full program code for this?
<re_irc> <chemicstry> no, I just written it here, might have compile errors
<re_irc> <skylardive1> Ah, can you try creating a usable example on the Rust Playground?
<re_irc> <skylardive1> (if you have time of course!)
<re_irc> <chemicstry> playground doesn't have ufmt, only top 100 crates
<re_irc> <chemicstry> check dependants of ufmt, some of them for sure have a similar implementation https://crates.io/crates/ufmt/reverse_dependencies
<re_irc> <chemicstry> I see that heapless is one of them, maybe you can just use their buffers ("Vec")
<re_irc> <skylardive1> Last time I did anything with "Vec" my binary size shot up by 100 kilobytes.
<re_irc> <chemicstry> "Vec" from "alloc" uses heap, the one from "heapless" is a replacement with constant size
<re_irc> <skylardive1> I'm in a no_std environment. Even If i use "alloc" for vec my final size will still be pretty large.
<re_irc> <James Munns> heapless vec is totally unrelated to alloc vec.
<re_irc> <skylardive1> "heapless" doesn't have any formatting features like "{}" etc.
<re_irc> <James Munns> using heapless vec will not use alloc at all.
<re_irc> <skylardive1> chemicstry: can you implement your example with ufmt on your own machine perhaps?
<re_irc> <James Munns> the suggestion: Use heapless vec as the _Storage_, and use ufmt as the _formatter_
<re_irc> <James Munns> so format your data INTO a heapless Vec/String.
<re_irc> <James Munns> which on the inside, is a slice of bytes you can write to the console, or whatever you have.
<re_irc> <James Munns> in a putchar loop or whatever.
<re_irc> <skylardive1> I don't see any formatters in "heapless" though.
<re_irc> <skylardive1> so instead of a u8 buffer, i use a heapless::String?
<re_irc> <James Munns> we're suggesting you use two crates.
<re_irc> <James Munns> yes
<re_irc> <James Munns> heapless types implement the "uformat" trait
GenTooMan has quit [Ping timeout: 245 seconds]
<re_irc> <chemicstry> also don't forget to enable "ufmt-impl" feature on the "heapless" crate in "Cargo.toml"
<re_irc> <skylardive1> I have tiny_vec, and as I understand it this can be used as a alternative to vec![] too?
<re_irc> <K900> Possibly
<re_irc> <James Munns> yes, they are very similar. With tiny vec, you'll have to write your own ufmt impl as well
<re_irc> <skylardive1> Ummm. So I have to do let mut a = heapless::String::new("testing ")
<re_irc> a.write_str("world")
<re_irc> <James Munns> also look at the "uwrite" macro
GenTooMan has joined #rust-embedded
<re_irc> <skylardive1> Yeah but It's all pretty confusing to me.
<re_irc> <James Munns> https://docs.rs/ufmt/latest/ufmt/ has a lot of really good examples.
<re_irc> <James Munns> try some stuff out, then share with us:
<re_irc> - What you got
<re_irc> - What you expected
<re_irc> - What you tried
<re_irc> <James Munns> and we will be able to help you much more, without guessing.
<re_irc> <skylardive1> Alright
<re_irc> <skylardive1> Cargo.toml:
<re_irc> ufmt = "0.1.0"
<re_irc> heapless = {version = "0.7.15", features=["ufmt-impl"]}
<re_irc> <James Munns> btw
<re_irc> <James Munns> sharing a git repo helps a lot
<re_irc> <James Munns> that way we can actually clone and run the project to see the same thing you do.
<re_irc> <skylardive1> I don't think your approaches are convenient. I just tested using printf from libc and my binaries is about 10kb smaller than if i were to use heapless+ufmt
<re_irc> <skylardive1> Is there anything in libc lighter than printf?
<re_irc> <James Munns> Not sure. Sorry I couldn't help. Good luck with your search.
<re_irc> <chemicstry> are you building with "--release"?
<re_irc> <skylardive1> yes
<re_irc> <chemicstry> and are you actually observing the output of "printf"? it could be optimized out. Seems strange for heapless and ufmt to use 10kb
<re_irc> <skylardive1> *sprintf
<re_irc> <James Munns> couple more suggestions, then I'll really be done:
<re_irc> <James Munns> 1. Make sure you are measuring stripped binaries. You might be measuring debuginfo if you just look at file size.
<re_irc> 2. If you really care about size, make sure you aren't just using --release, but you also customize your profile to use opt-level 's' or 'z', since Rust is REALLY inline heavy (especially if you only use something once or twice), which is faster, but larger code size
<re_irc> 3. C just plain cheats, by dynamically linking almost everything from libc in, so everything is going to be smaller than doing it yourself a lot of the time.
<re_irc> <skylardive1> i'm statically linking.
<re_irc> <James Munns> That being said, I don't have any specific "bare metal on top of an OS", so I'll avoid making any further suggestion. Hope that helps.
<re_irc> <skylardive1> i'm using every optimization
<re_irc> <skylardive1> yes, which is why i asked if there was anything in libc so i don't have to use anything new haha
<re_irc> <James Munns> Still check "ldd", "static" on desktop linux can still sort of be a lie :)
<re_irc> <James Munns> I'd suggest you won't get a ton of libc experience here, as what you are doing is less about rust or embedded, and more about C, tbh.
Guest14 has joined #rust-embedded
Guest14 is now known as brazuca
<re_irc> <skylardive1> I agree
<re_irc> <skylardive1> Might vsprintf be lighter?
smach has joined #rust-embedded
Amadiro has quit [Ping timeout: 240 seconds]
smach has quit [Quit: Leaving]
dc740 has quit [Remote host closed the connection]
dc740 has joined #rust-embedded
bjc` has joined #rust-embedded
re_irc_ has joined #rust-embedded
tafama has joined #rust-embedded
seer_ has joined #rust-embedded
bjorn has joined #rust-embedded
emerent_ has joined #rust-embedded
emerent has quit [Killed (platinum.libera.chat (Nickname regained by services))]
emerent_ is now known as emerent
WSalmon_ has joined #rust-embedded
inara has joined #rust-embedded
bjc has quit [*.net *.split]
Lumpio- has quit [*.net *.split]
seer has quit [*.net *.split]
bjoto has quit [*.net *.split]
re_irc has quit [Ping timeout: 240 seconds]
WSalmon has quit [Ping timeout: 240 seconds]
tafa has quit [Ping timeout: 240 seconds]
inara` has quit [Ping timeout: 240 seconds]
re_irc_ is now known as re_irc
Lumpio- has joined #rust-embedded
edm has quit [Ping timeout: 240 seconds]
edm has joined #rust-embedded
brazuca has quit [Ping timeout: 252 seconds]
Guest14 has joined #rust-embedded
Guest14 is now known as brazuca
_whitelogger_ has joined #rust-embedded
neceve has joined #rust-embedded
nohit has quit [Ping timeout: 240 seconds]
eigenform has quit [Ping timeout: 240 seconds]
nohit_ is now known as nohit
fooker has quit [Ping timeout: 240 seconds]
_whitelogger has quit [Ping timeout: 240 seconds]
fooker has joined #rust-embedded
neceve has quit [Ping timeout: 268 seconds]
dc740 has quit [Remote host closed the connection]
Socke has quit [Ping timeout: 272 seconds]
brazuca has quit [Ping timeout: 252 seconds]
Socke has joined #rust-embedded