DepthDeluxe has joined #rust-embedded
<re_irc> <> 1. There are attributes which are not easily discoverable when you need to boot with some cores powered down.
<re_irc> <> 2. If you have a unique entry point for each CPU you cannot load firmware as an ELF file which means you don't get debug symbols when doing emulator-level instruction debugging (GDB still works fine of course)
<re_irc> <> 3. QEMU does not support heterogeneous SoCs at all. There are many different custom implementations for this, none of which are great.
<re_irc> <> 4. The command line options for booting an embedded system are not intuitive when you need to load multiple memory regions (e.g. an external SPI flash and a ROM).
<re_irc> <> 5. The command line argument parsing has poor validation and when using low-level boot options and you can pass multiple incompatible boot options without a warning.
<cr1901> Hmmm, interesting
<re_irc> <> jacobrosenthal: renode is probably good on Windows. From *nix, you get to deal with the extra mono overhead
<re_irc> <> In terms of emulators there is also google's cross VM which is essential QEMU but for chromebooks only, and written in rust:
<re_irc> <> Not very extensible, but it is neat to look at.
fabic has joined #rust-embedded
starblue1 has quit [Ping timeout: 268 seconds]
starblue1 has joined #rust-embedded
DepthDeluxe has quit [Quit: Leaving]
fabic has quit [Ping timeout: 268 seconds]
GenTooMan has quit [Ping timeout: 268 seconds]
GenTooMan has joined #rust-embedded
PyroPeter has quit [Ping timeout: 252 seconds]
PyroPeter has joined #rust-embedded
fabic has joined #rust-embedded
fabic has quit [Ping timeout: 265 seconds]
emerent is now known as Guest6736
Guest6736 has quit [Killed ( (Nickname regained by services))]
emerent has joined #rust-embedded
gsalazar has joined #rust-embedded
<re_irc> <> Is there an accepted trait in embedded that is the "embedded equivalent" of `std::io:Write`? I'm thinking a trait that does `write(buf: &[u8])` and `write_byte(byte: u8)`.
<re_irc> <> I'd like to abstract an RF chip RX/TX buffer so it can be written to directly without the need for an intermediary buffer, which is required if I would choose an `&[u8]` interface.
<re_irc> <> But I'd also not want this trait to be my project only as I'd like to implement this trait in different supporting crates used with radio ICs.
<re_irc> <> So we get a "zero copy" API from serialization of message to the RF chips buffer
starblue1 has quit [Ping timeout: 252 seconds]
<re_irc> <> Yay zero copy! That trait should probably then also be **the** trait for SPI, UART etc. instead of what is currently in `embedded_hal::spi` etc.
<re_irc> <> I.e. why are there multiple different "write" traits in `embedded-hal`?
starblue1 has joined #rust-embedded
<re_irc> <> Ah right, they have their own trait per peripheral type
<re_irc> <> Is everyone rooting for `std::io::Write` eventually becoming `no_std`?
<re_irc> <> Seems like there is space for an `embedded-write` crate :P
<re_irc> <> How do people achieve zero copy interoperability with ICs that has buffers without a trait for it?
<re_irc> <> Maybe there is a usage pattern I have missed?
<re_irc> <> Or do people not do zero copy and simply accept the use of intermediary buffers?
<Lumpio-> Zero copy is overrated
<Lumpio-> But a lot of crates use the curious write callback pattern.
<re_irc> <> What do you mean?
<Lumpio-> write(callback: impl Fn(&mut [u8]) -> usize) instead of write(buf: &[u8])
<Lumpio-> This works if a hardware or library internal buffer exists and can be written to normally
<re_irc> <> Ah right, the first one makes a lot of sense
<Lumpio-> jordens: fwiw most microcontrollers don't have a hardware buffer for SPI and UART or whatnot, so I'm not sure if having a trait like that is so useful for that
<Lumpio-> If you want to write a buffer efficiently you have to put it in memory and use DMA
<re_irc> <> This is the one I'd like a trait for more or less
<Lumpio-> And the buffer allocation usually comes down to user code.
<Lumpio-> And the write trait ends up being very similar, except that it takes some kind of magical DMA safe buffer instead of just &[u8]
<re_irc> <> Sure. Mostly DMA. But also stm32h7 qspi has a decent FIFO for example. In any case, even if your HW does only small xfers (uart, SPI), you probably still want to expose a slice based API. Because that's what people need.
<re_irc> <> I'm not really interested in all the different usage patterns of DMA vs not using DMA, I simply want a trait to express the possibility of a write API. And then if it's used for DMA, zero copy writes to chips or writes to buffers is an orthogonal discussion.
<re_irc> <> And SPI v2 on stm32 generally has FIFOs. So this is not only about DMA. korken89 Right. The need for a good API is orthogonal to the capabilities of the various peripherals.
<re_irc> <> That is not correct. Quite a few STM32 chips have a transmit buffer for SPI (which bit me quite well when trying to make use of it due to software CS) and I've definitely seen some 16550 compatible UARTs out there (though I can't recall exactly where).
<re_irc> <> most microcontrollers aren't quite a few STM32s, so maybe it's true?
<re_irc> <> most of the micros i deal with these days do but i know the future isn't evenly distributed
<re_irc> <> Maybe, maybe not. I don't think anyone here has the quantitive data to say for sure.
<re_irc> <> Allow me to correct myself then: That is likely not correct.
mbuhl has joined #rust-embedded
mbuhl has left #rust-embedded [bye]
fabic has joined #rust-embedded
<re_irc> <> Is it worth adding a `std::io::Write` like trait to `embedded-hal` or some other place so drivers can depend on write APIs?
<re_irc> <> I have not followed the discussion but if the use case is there and drivers would benefit, sure.
starblue1 has quit [Ping timeout: 260 seconds]
starblue1 has joined #rust-embedded
fabic has quit [Ping timeout: 268 seconds]
Obiwankenobi has joined #rust-embedded
Obiwankenobi has left #rust-embedded [#rust-embedded]
<re_irc> <> Yeah, I mean maybe I've been working too much with RF chips but my "dream" to e.g. serialize directly to the chip without intermediary buffers being copied all over the place. The thing is that generally there are like 3-5 crates of `&(mut) [u8]` APIs to go through (serde lib, add header lib for your IEEE 802.15.4, rf lib tx buffer, send to spi) which often copy the entire buffers around as none of the...
<re_irc> ... stages understood how data should be in the end. So you get alignment issues and it's solved with copying the buffer to correct alignment. Or in some cases, lifetime problems, so the drivers duplicate a slice to a buffer to get ownership. Where one should just be able to chain a `write` like API like:
<re_irc> <> spi.write(|s| header.write(s, |w| w.payload.write(|w2| ...)))
<re_irc> <> I think I'll make a proper port of a few libs to use a trait to have as a case-study in a way
<Lumpio-> therealprof: How do you write into the transmit buffer?
<Lumpio-> Is it a memory region you can write into in whatever order you want like &mut [u8]
<re_irc> <> Nope, it's just a single MMIO register you write your "word" into and there's a watermark in another register allowing you to figure out how full the buffer is.
<re_irc> <> For STM32 SPIv2, that is. 😉
<Lumpio-> This was related to whether you can just have something write directly into memory to transmit
<Lumpio-> So yes there's a hardware buffer but it's not a memory region you can just write to normally.
<re_irc> <> Yes. You have to spoonfeed the data in.
<Lumpio-> My wording wasn't the best but read it as "hardware memory buffer" or something
<Lumpio-> jordens: Does the QSPI also have just one FIFO register you repeatedly write to in order or does it expose something you can cast into &mut [u8
<Lumpio-> ]
<re_irc> <> And the buffer is not big for this specific case, only 32bit so at usual 8bit transfer size it's only 4 words.
<Lumpio-> At any rate I do know some hardware that has an actual memory buffer for data, like some USB peripherals
<re_irc> <> one address, deep fifo behind, plus level registers, all for rx and tx.
<Lumpio-> ...but even them some of them are bizarre, there's some STM32 ones where the memory is u16's laid out ever 4 bytes, with two bytes of padding inbetween due to how the bus works
<re_irc> <> Yes, USB is a good example for a dedicated buffer in memory.
<Lumpio-> Anyways for those the "write callback" style trait would get you truly zero-copy, but otherwise it will still need to write into memory somewhere.
<re_irc> <> I guess the problem with the dedicated memory is going to be that your "here's a slice of data" won't work without copying it there.
<Lumpio-> That is, normal allocated memory
fabic has joined #rust-embedded
<re_irc> <> korken89: What is the specific use case you have in mind?
fabic has quit [Ping timeout: 260 seconds]
GenTooMan has quit [Ping timeout: 260 seconds]
GenTooMan has joined #rust-embedded
<re_irc> <> I wrote a bit up about how I'd like to interact with RF chips
fabic has joined #rust-embedded
gsalazar has quit [Ping timeout: 268 seconds]
fabic has quit [Ping timeout: 252 seconds]
<re_irc> <> Shameless plug: high-performance, battle-tested, integer DSP algorithms for embedded:
<re_irc> <> Great dude. I'm messing with DSP now
<re_irc> <> Starting with CMSIS-DSP. Will try your lib too! Don't know what I'm doing atm, but. Reading a DSP book
<re_irc> <> How does this compare with CMSIS DSP?
GenTooMan has quit [Ping timeout: 252 seconds]
GenTooMan has joined #rust-embedded
<re_irc> <> korken got it. Just a thought - it doesn't have to be generic.
<re_irc> <> From what I have seen so far (and when looking for prior art) this is *significantly* better than cmsis dsp.
<re_irc> <> Hell yeah!
<re_irc> <> Will dive in later today
<re_irc> <> Do you mind sharing which RF chips you are working with?
<re_irc> <> As in faster? More functionality? Obv being native Rust reduces some complexity over compiling C and FFI wrapping
<re_irc> <> Better API?
<re_irc> <> faster, significantly more accurate, but certainly less functionality.
<re_irc> <> API probably can use some love and coordination across other crates.
<re_irc> <> jordens: is this `IIR` struct a copy pasta error or do I missunderstand sth?
<re_irc> <> (guess it should be FIR)
<re_irc> <> Oops. Forget about the FIR. That's an accidental copy pasta commit.
<re_irc> <> I see =)
<re_irc> <> If somebody is interested in giving API advice, that's certainly welcome! Certainly w.r.t. inter-crate questions like `num`, `micromath`, `sdr-rs` etc.
<re_irc> <> Awesome. Looking forward to using it
<re_irc> <> API is probably my biggest strength, but I'm not proficient enough with DSP to comment at this time. I'll send suggestions/issues/PRs your way as required later
<re_irc> <> does anyone know what `.option` is in assembly (riscv) and where I can find the docs for that?
<re_irc> <> AFAIK Risc-v has no built in push so I'm guessing it's a meta instruction? but I have no idea where it's from
<re_irc> <> Sure DW1000 and SR1000
<re_irc> <> Reduced memory footprint and faster. I need to give this a try and see where I land.
<re_irc> <> Though API as well, working with slice APIs really don't map well to the operations causing the need for multiple intermediary buffers
<re_irc> <> Great!
<re_irc> <> And re functionality - we can always add PRs with new functions as required. Translating CMSIS as a start
<re_irc> <> almindor: > Modifies RISC-V specific assembler options inline with the assembly code. This is used when particular instruction sequences must be assembled with a specific set of options. For example, since we relax addressing sequences to shorter GP-relative sequences when possible the initial load of GP must not be relaxed and should be emitted as something like
<re_irc> <> .option push
<re_irc> <> la gp, __global_pointer$
<re_irc> <> .option norelax
<re_irc> <> Perfect, thank you!
<re_irc> <> almindor: (The keyword to look for is "directive")
<re_irc> <> yeah, I tried option heh. I was like "never seen this in the riscv simulator before" :D
<re_irc> <> it's funny the deeper I go, I always think "this is the bottom of the stack surely", there's always some tool specific thing
<re_irc> <> almindor: Yeha, too general word. Like when I struggle with matrix/element end to end encryption and I can just find things related to maths…
<re_irc> <> has anyone got an idea how I can debug "called `Option::unwrap()` on a `None` value rust-analyzer(macro-error)"? I cannot find anything in the output tabs of vscode and the proc_macro also compiles just fine when I run cargo build. Like can I get a complete stacktrace somehow?
<re_irc> <> if it builds fine then it's probably a RA bug... it probably refers to an unwrap inside RA's code :S
<re_irc> <> hmm that's really sad because it kills all other analytics in my code
<re_irc> <> it will do autocompletions and hotfix suggestions with "ctrl + ." just fine, but it wont show any errors in my code :/ sadge
<re_irc> <> or maybe the env is different or something so your proc macro does crash
<re_irc> <> I believe it's the env because I feel like I had exactly this error during development of the proc_macro sometimes too when run from the wrong directory or the likes
<re_irc> <> the problem is that I can't really see where it dies
<re_irc> <> maybe wrap your entire macro with a catch_unwind
<re_irc> <> hmm
<re_irc> <> but how would I propagate that into rustanalyzer
<re_irc> <> hmm maybe with a compiler_error!
<re_irc> <> or another panic!, but with the info you want
<re_irc> <> fair point
<re_irc> <> proc_macros are the best and the worst feature of rust simultaneously XD
<re_irc> <> awesome when it works, terrible when you have to debug/write it :D
<re_irc> <> debugging them SUCKS
<re_irc> <> hard agree! whats worse is if 6 different git repos are involved ...
<re_irc> <> anyone know a way to not have to list ALL GHA checks in bors?
<re_irc> <> RTIC would be more approachable beyond a "trust" perspective if you could review its code without the macros
<re_irc> <> cargo-expand?
<re_irc> <> It outputs itself in your target dir as like
<re_irc> <> ah true
<re_irc> <> cargo expand makes code an unreadable mess because it expands all macros, not just yours :D
<re_irc> <> but the relevant parts are readable :)
<re_irc> <> most of the time
<re_irc> <> writing to a file from the macro is a neat hack but only really works if the macro is only supposed to be used once
<re_irc> <> at least that's how I debug proc_macros and I like it quite some :)
<re_irc> <> yeah it's the best we got :S
<re_irc> <> some "expand this macro" in RA would be amazing
<re_irc> <> also sometimes cargo-embed expands to code that doesn't build
<re_irc> <> They do have a little bit of expansion added recently
<re_irc> <> whaaaaaaaaat 🤯
<re_irc> <> YESSS
<re_irc> <> Oh nice. I'll take a look
<re_irc> <> that is awesome!!!
<re_irc> <> nice, cargo-embed can now expand code, didn't know :P
<re_irc> <> cargo-expand >_>
<re_irc> <> ohhhhh nice
<re_irc> <> and it works for both declarative and proc macros :D :D
<re_irc> <> not attribute macros though
<re_irc> <> but still awesome
<re_irc> <> yup, found the panic :D
<re_irc> <> now I need to figure why it fails :D
<re_irc> <> Note: The observable result of a macro should only rely on the tokens and not on this source text. The result of this function is a best effort to be used for diagnostics only.
<re_irc> <> that's not good; I am violating this :/
<re_irc> <> something is seriously wrong :/
<re_irc> <> does r-a use rustc to resolve the proc_macros or does it do it itself somehow?
<re_irc> <> printing the spans inside vscode/r-a results in "4294967295 ----- 26". printing them with cargo build results in "#0 bytes(6374..6382) ----- #0 bytes(6476..6783)" XD
<re_irc> <> like wtf?
<re_irc> <> seems like r-a does this REAL different
<re_irc> <> like as if it replaces the entire token primitives and spans emitted
<re_irc> <> spans are cursed, just treat them like black boxes...
<re_irc> <> I know but I NEED them for diagnostics :/
<re_irc> <> grrr
<re_irc> <> and for parsing of source
<re_irc> <> all of the things one should NOT do but I want to :/
<re_irc> <> why to parse? you need some info that's not on the token list?
<re_irc> <> the parser operates on strings and not rust tokens. so you somehow need to convert the tokens into a string OR make the parser take rust tokens (this leads to other problems; the most prominent being that you have to write and test the parser twice, but also many technical ones).
<re_irc> <> you can convert the tokens into a string without spans. but that leads to code that is not identical to the source (formatting), which makes rustc annotations impossible.
<re_irc> <> guess r-a's backend is just so different
<re_irc> <> :(
<re_irc> <> stringify each token, glue them with spaces, parse that?
<re_irc> <> parse that "reconstructed" string
<re_irc> <> if the gives you a span on that string, work "backwards" to check which tokens are in that reconstructed-string span
<re_irc> <> then back to rust spans?
<re_irc> <> :S
<re_irc> <> that still does not necessairly represent the source exactly, unfortunately
<re_irc> <> I tried, believe me :D
<re_irc> <> because that stuff is what forces me into nightly, basically
<re_irc> <> the issue is that it doesn't parse?
<re_irc> <> or it does parse but then you can't report errors on the right line:column?
<re_irc> <> no the issue is that you cannever get the exact source from the tokens
<re_irc> <> because a tokentree does not have notion of source formatting
<re_irc> <> no spaces, no comments, etc.
<re_irc> <> kind of sad
<re_irc> <> the thing you're parsing cares about newlines/spaces?
<re_irc> <> I tried using a string as the proc_macro input to fix this. but rustc cannot generate arbitrary spans m(
<re_irc> <> so you cannot point to the location in string
<re_irc> <> and I like to
<re_irc> <> no, the diagnostics when there is an error do
<re_irc> <> you can do that with the "working backwards" thing
<re_irc> <> I want to say e.g. "variable with name `hehexd` on line 3 character 5 through to character 11 does not exist" and have rustc annotate that
<re_irc> <> if your macro gets called with tokens `a`, `b`, `c`
<re_irc> <> with spans spanA, spanB, spanC (black boxes)
<re_irc> <> not sure I understand you right but if I do: I do that already
<re_irc> <> glue them into a string "a b c"
<re_irc> <> that string will not match the original Rust source, but it doesn't matter
<re_irc> <> when gluing, keep the info of:
<re_irc> <> - chars 2..3 -> SpanB
<re_irc> <> - chars 0..1 -> SpanA
<re_irc> <> - chars 4..5 -> SpanC
<re_irc> <> hmm I think I know what you mean. could work actually
<re_irc> <> so if your parser gives you the error "shit broken at char 2"
<re_irc> <> you translate "char 2" to SpanB and tell rustc "shit broken at SpanB"
<re_irc> <> I need to make a drawing :D
<re_irc> <> dang why do I always use unfinished APIs :/
<re_irc> <> I think that should even work on stable
<re_irc> <> hmm
<re_irc> <> hmm I need a way to translate token xy -> span
<re_irc> <> because the string parser gives me back a span into the string too
<re_irc> <> and from that I need to determine the initial token/span
<re_irc> <> which means I need to know how much characters a token takes
<re_irc> <> then I can just add spaces between each token I think and we are good
<re_irc> <> what is not trivial is the structure of tokentrees
<re_irc> <> I can't for the life of me get bors working 🤣
<re_irc> <> there's like some length limiting of the statuses names
<re_irc> <> LOL
<re_irc> <> yeah bors has some really weird quirks
<re_irc> <> we hit its limits with probe-rs too :/
<re_irc> <> like, it doesn't "see" the checks with longer name only
<re_irc> <> okay, the check is named literally `check (nightly, defmt defmt-trace medium-ip medium-ethernet proto-ipv6 proto-ipv6 proto-igmp prot...`
<re_irc> <> yes, with the `...`
<re_irc> <> WTF
<re_irc> <> XD
<re_irc> <> guess the GH API has some kind of capped preview/title string?
<re_irc> <> which then in turn bors uses
<re_irc> <> I can't even see statuses from GHA through the github statuses api
<re_irc> <> yeah, idk, but it's kind of weird how GH attaches CI run results to commits/PRs
<re_irc> <> I didn't understand it fully
<re_irc> <> ah stuff from GHA really is "check runs", not "statuses"
<re_irc> <> and yup, it has the `...` there. WTF github
<re_irc> <> down the rabbithole it goes :D
<re_irc> <> save data, idk
<re_irc> <> truncated to exactly 100 chars including the `...`. Something something `varchar(100)` much??
<re_irc> <> XD
<re_irc> <> well after all it's microsoft
<re_irc> <> GHA is full of WTF
<re_irc> <> Sorry, I can't help it. I just found this and have to share 🤣.