<M762spr[m]>
I have a question that isn't directly related to embedded, but I think the problem is DEFMT so I'm hoping someone here can point me in the right direction...
<M762spr[m]>
I wrote a library for a radio module. Works fine, no problems there. It has a fairly elaborate builder for the radio config that prevents incorrect configuration combinations and I want to re-use that code so on my desktop app that communicates with the STM32 I can make sure I have a correct configuration, and send it over. tl;dr I want to use the same library for a desktop app
<M762spr[m]>
The problem arises when I include my library in the source of my desktop app and build I get a linker error and a wall of output text. At the end it seems to reference DEFMT so I suspect that's the problem. any ideas?
<M762spr[m]>
I tried adding defmt and defmt-rtt to my cargo.toml with no change
<M762spr[m]>
ok yeah it's definitly defmt
<M762spr[m]>
I removed it from my library which was mostly just used for info! prints and now it compiled on the desktop
<M762spr[m]>
BUT without defmt, I can't derive Fromat which means in my embedded environment I can't print any of my custom structs/enums
<mameluc[m]>
M762spr[m]: without knowing what is in the wall of text it is hard to say what might be wrong. however adding defmt needs some flags to work
<M762spr[m]>
oh! yeah I obviously haven't done the linker script mods that makes sense
<M762spr[m]>
it's been a while since I setup the embedded environment that I use it with so I forgot all about it
<M762spr[m]>
hm. adding the rustflag didn't work. which makes sense I guess because I am compiling a desktop app
<M762spr[m]>
I think this is what I need. I don't really understand macros so I will try to process it
sethiam[m] has joined #rust-embedded
<sethiam[m]>
In your library you could define the info! macro as either from use tracing::info or equivalent or use defmt::info based on a feature flag you define in your cargo.toml. That flag should also gate the defmt dependency when compiling for std.
<M762spr[m]>
makes sense
<M762spr[m]>
I will use the embassy file as reference and see if I can get it figured out
<sethiam[m]>
That way you can include the library for ur std app with a feature flag that allows std and some logging framework for std, and without said flag, compile for no_std and with defmt.
<GrantM11235[m]>
Just copy that file into you crate and add pub(crate) mod fmt to the top of your lib.rs or main.rs (It must be BEFORE any other modules)
<M762spr[m]>
haha well that's easy I'll see how it goes! thanks!
<M762spr[m]>
so if I'm reading this right, the library should use log and the app should use env_logger?
<GrantM11235[m]>
I think so. And the library only needs to use the log crate if your log feature is enabled
vanner- has joined #rust-embedded
vanner has quit [Read error: Connection reset by peer]
<M762spr[m]>
awesome. ALMOST compiling. It's just mad that:
<M762spr[m]>
``the trait `UpperHex` is not implemented for `[u8; 5]```
<M762spr[m]>
now but I can probably just live without that
<M762spr[m]>
* awesome. ALMOST compiling. It's just mad that:
<M762spr[m]>
`\`\`the trait `UpperHex` is not implemented for \`\[u8; 5\]\`\`\`
<M762spr[m]>
now but I can probably just live without that
<M762spr[m]>
s/`//, s/```/``/
cr1901_ has joined #rust-embedded
cr1901 has quit [Ping timeout: 252 seconds]
<M762spr[m]>
GrantM11235: sethiam it seems to be working now, HUGE thanks to both of you I probably wouldn't have been able to figure that out on my own!
<M762spr[m]>
RE: the UpperHex issue, I noticed the fmt.rs file had something for LowerHex but obviously it had to be implemented for a custom type
<M762spr[m]>
not 100% sure if that would print the desired results BUT I don't really care on the desktop app anyway I'm just using a small portion to make the configuration
<M762spr[m]>
anyway, thanks again! 🙏
<gmarull[m]>
Hi, I observe the following warning on enums when using `chiptool`: `variant 'X_Y_Z' should have an upper camel case name`. Shouldn't `chiptool` be adding `#[allow(non_camel_case_types)]`? Am I missing something? dirbaio
<ivmarkov[m]>
Absolutely, really, 100% sure? Asking, because the documentation is realy NOT explicit about that.
<JamesMunns[m]>
iirc std::io::Read agrees with option A as well
<dirbaio[m]>
docs could be more explicit ... but they refer to std::io, and std::io works like that. Also std::io in turn follows posix io
<dirbaio[m]>
* posix io, which also works like that.
<dirbaio[m]>
option B is bad because it doesn't allow doing certain things. for example you can't read until newline with bigger buffers because it'll block until the buffer is full, which may be more than just one line
<dirbaio[m]>
you're forced to do 1-byte read calls
<dirbaio[m]>
which would be bad
<dirbaio[m]>
basically the semantics are "when a byte arrives, I want to see it ASAP. Don't wait more"
<JamesMunns[m]>
tbh I can't find anything that says Option B is wrong, but it definitely doesn't match how most OSs implement it (down to the syscall level)
<ivmarkov[m]>
Fair enough. Thanks! I really wanted to confirm that these are official, specified (somewhere??) semantics, and not an internal implementation detail that is leaking through the API, and people just abusing it (sub)consciously.
<ivmarkov[m]>
JamesMunns[m]: But that's the problem! Are we relying on a well-defined, documented semantics, or on an internal implementation detail? That's what I'm trying to understand, but Dario seems super convinced yes.
<dirbaio[m]>
uhhh it's worked like this forever
<dirbaio[m]>
and it's the way that makes "the most sense"
<JamesMunns[m]>
like, an OS may be allowed to wait a little longer even if data is ready if it thinks it's likely to get more asap, but always blocking until the full read is available would definitely be odd
<JamesMunns[m]>
(that's what read_exact is for)
<vollbrecht[m]>
in this case its about defining a good enough timeout that is short enough, but not to short. Such that if the buffer is not full it will return internally with all it got?
<vollbrecht[m]>
* good enough internal timeout that
<JamesMunns[m]>
fwiw for sockets and stuff this is controlled "out of band" by configuring the read timeout
<dirbaio[m]>
read timeout is a different thing
<JamesMunns[m]>
(at least out of band to the call to the read syscall)
<vollbrecht[m]>
well its different, but here we are talking about returning even if somewhere only 1 byte was internally but into the read buffer
<ivmarkov[m]>
JamesMunns[m]: No, `read_exact` is just a convenience if you want to avoid the OS returning you a partial buffer. I don't think its mere existence rules out that Option B" is a valid contract for `Read::read`.
<vollbrecht[m]>
s/but/put/
<ivmarkov[m]>
... and it is implemented on top of Read::read anyway
<JamesMunns[m]>
I didn't say "invalid", just "weird"
<JamesMunns[m]>
s/weird/odd/
<ivmarkov[m]>
* out that "Option B"
<dirbaio[m]>
it's invalid
<JamesMunns[m]>
dirbaio[m]: I would be very interested in a citation for that
<JamesMunns[m]>
like, I agree it's not how linux/mac/windows work
<ivmarkov[m]>
JamesMunns[m]: Me too :(. show me _something_. Could be a POSIX documentation, where it is super clear on that subject. I'm struggling to fine it. :(
<ivmarkov[m]>
s/fine/find/
<ivmarkov[m]>
(BTW my oroblem is weird ESP IDF UART does Option B, and I now have a user who claims I'm not fullfilling the contract of Read, as he interprets it as Option A.)
<JamesMunns[m]>
And for the record, I think you SHOULD do Option A, and that Option B is odd
<dirbaio[m]>
well we can just expand embedded-io docs to make B illegal 😎
<JamesMunns[m]>
but at least in a quick search, I can't find anything that says option B is wrong, just odd, and likely to cause confusion
<dirbaio[m]>
if people are going to contract-lawyer this I think we should
<dirbaio[m]>
because if impls doing Option B proliferate they'll cause interop problems
<dirbaio[m]>
I didn't explicitly document this because I thought it was obvious :|
<JamesMunns[m]>
The recv syscall DOES talk about this
<dirbaio[m]>
> When attempting to read from an empty pipe or FIFO:
<dirbaio[m]>
> (...)
<dirbaio[m]>
> If some process has the pipe open for writing and O_NONBLOCK is clear, read() shall block the calling thread **until some data is written** or the pipe is closed by all processes that had the pipe open for writing.
<dirbaio[m]>
> If fildes refers to a socket, read() shall be equivalent to recv() with no flags set.
<dirbaio[m]>
and recv() is quite explicit about this as James said
<JamesMunns[m]>
Yeah, I think some of the wavyness is that io::Read covers all kinds of readable things, like files (which are more likely to read exact), but also sockets (which only ever read until nonzero that I've ever seen), and we're talking about serial ports here specifically
<dirbaio[m]>
yeah, posix is a bad standard
<dirbaio[m]>
* bad standard if it allows different behavior for different kinds of fileds
<dirbaio[m]>
* bad standard if it allows different behavior for different kinds of fd's
<dirbaio[m]>
I don't think we have to copy this "badness"
<dirbaio[m]>
also even with serial ports, read() in linux returns available data, it doesn't wait for all N bytes to be received
<JamesMunns[m]>
anyway, I think you could probably rules lawyer Option B as "technically correct", but I think that a serial port being more socket-y than file-y would make the case that doing Option B is very odd and shouldn't be done.
<JamesMunns[m]>
(even if it's SHOULD not SHALL)
<dirbaio[m]>
then we just edit the docs to explicitly make option B illegal
<JamesMunns[m]>
we could, but then is it valid to implement embedded_io::Read on top of a std::io::Read?
<JamesMunns[m]>
std::io::Read doesn't make that claim.
<JamesMunns[m]>
I think we SHOULD add a SHOULD there though, to make it more clear in the future :)
<dirbaio[m]>
there's no std::io::Read impls out there that do the "wait until all N bytes have been received"
<ivmarkov[m]>
Ok. I declare defeat. I'll do option A on top of option B. But maybe editing the docs to be more explicit about option A would be a good idea.
<dirbaio[m]>
the closest is reading from files, but that kinda makes sense because data from files is always "immediately available", it's on a local disk so it can't take an unbounded amount of time to arrive
<JamesMunns[m]>
Even then linux will cap out a read at < 32 bits worth
<dirbaio[m]>
so i'd argue if an std::io::Read impl waits for full buffer, it's also wrong
<ivmarkov[m]>
In fact, maybe we should ping STD as _they_ have to be more explicit too?
<JamesMunns[m]>
I think adding a "should" or a note "hey you really shouldn't treat this like read_exact", and "here's how posix recv talks about it" is a good idea
<JamesMunns[m]>
I think opening an issue for std is reasonable too, at least citing recv. I don't know if they'd make it "normative"
<mameluc[m]>
Don't know if this is a common problem but serde got and std. Something somewhere is passing the std feature to serde and now my no_std project won't compile anymore.
<diondokter[m]>
Yeah, next version 1.81 has it right?
siho[m] has joined #rust-embedded
<siho[m]>
Is anyone up to help me with a beginner question?
K900 has joined #rust-embedded
<K900>
Just ask
<K900>
Don't ask to ask
ryan-summers[m] has joined #rust-embedded
<ryan-summers[m]>
Just shoot :)
<siho[m]>
I'm trying to use svd2rust to generate a PAC for an unsupported device. That works fine, now I just want to blink a LED. The problem is that the field i need to toogle is the type of FieldWriter and i really can't get the writer to be &mut
<siho[m]>
If it's not obvious this is a efm32 device
<siho[m]>
I'm sorry for the bad formatting but I've only setup matrix on my phone for now.
<ryan-summers[m]>
What's the error you're getting exactly?
<siho[m]>
The error I get is that the method set is only available on a &mut W<efm32> while what I apparently is not. It's totally fine to just set the bits raw but I kind of wanted to have the register length check
<ryan-summers[m]>
Ah so doing like .set_bits()... works fine? It's probably a bug in the SVG then not properly marking the field as writable
<siho[m]>
This is sort of close to what I'm generating
<siho[m]>
ryan-summers[m]: `.bits()`.works fine inside an unsafe block. The field is marked as read-write in the svd
<ryan-summers[m]>
I wonder if Rust is accidentally picking up the dout() for DOUT_R instead of DOUT_W? Sorry, I haven't done much with PAC generation myself so I'm unsure here
<ryan-summers[m]>
The copy-pasted error from the compile would be helpful in sorting that out though
<siho[m]>
Well I probably should do something different that I'm aware of xD
<ryan-summers[m]>
tl;dr I think your code works fine if you replace the set() with bits()
<siho[m]>
Yes that's true it's just that set exists in the FieldWriter and I want to use:)
<ryan-summers[m]>
The compiler is saying it doesn't, and I don't see it on the docs. How do you know it exists?
<siho[m]>
The PAC I linked too was generated with an old svd2rust
<ryan-summers[m]>
In the error, it's saying that `set()` exists on (another type) &mut W<...>, but your type is `FieldWriter<..>`, so it doesn't have the same API as W<..>
<siho[m]>
ryan-summers[m]: I don't know how readable this is
<PaulDFaria[m]>
If it does exist on FieldWriter (I'm thinking not given the comments and screenshot above) then there's likely a trait not in scope or a trait bound on one of the generics that's not being upheld.
<ryan-summers[m]>
My guess is the register doesn't implement the proper trait bounds to expose set()
<PaulDFaria[m]>
Are you sure the fields are implementing the bounds correctly?
<siho[m]>
Please correct me if the set does not exist for the FieldWriter. I just assumed it did according to the docs in the photo
<ryan-summers[m]>
It does only if the trait bounds are met.
<ryan-summers[m]>
So in this case, those bounds may not be met, meaning set may not be available on this register
<dirbaio[m]>
svd2rust docs are quite hard to read 🙃
<PaulDFaria[m]>
You need to check whether PortbDoutSpec implements RegisterSpec and Writable, and Dout implements FieldSpec.
<ryan-summers[m]>
Yeah its also super opaque to figure out what types impl what
<ryan-summers[m]>
That's why I tend to just listen to the compiler. You can reason through it, but it'll take a while
<siho[m]>
It should be available but I guess that's where the bug is in the svd let me try to setup Matrix on my machine xD
<PaulDFaria[m]>
In the docs, I would search for the types in the error. Then check what traits they impl
<PaulDFaria[m]>
If they impl the traits then maybe you just need to import the traits?
<PaulDFaria[m]>
Though I've never run into that before
<JamesMunns[m]>
Or if you don't have Rust Analyzer installed, it can give you autocomplete, which is super helpful working with svd2rust!
<siho[m]>
Anyways thanks for all the pointers and sorry for being so insistent on trying to use set. I just wanted to have some safety when setting the bits
<ryan-summers[m]>
There's likely other APIs other than set by the way that are safe
<ryan-summers[m]>
But maybe newer svd2rust replaced them all with set... IDK
<siho[m]>
There is .variant I have no idea what that API is trying to communicate
<ryan-summers[m]>
The .variant is allowing you to use variants specified in the SVD as allowable for that field
<ryan-summers[m]>
So like, if there's an enumeration of allowable values, those are exposed via SVD2Rust and you can use them directly
<siho[m]>
Using variant I get IsEnum is not implemented since the field doesn't have any enumerated values
<ryan-summers[m]>
The enum would be auto-generated by svd2rust, and I didn't think it generated the variant() accessor if no enums existed in the svd
<siho[m]>
I walked down that path and added them myself XD but I just thought 💭 that if the FieldWriter had the register size I could use that Safety instead
<ryan-summers[m]>
I don't think the intent is that you'd ever manually add to the svd2rust generated outputs, and if you did that, it's likely why the enum you crated isn't working
<ryan-summers[m]>
The intent would be to correct the svd so that it generates the correct code instead
<siho[m]>
I meant I added the enumerated fields to the svd
<ryan-summers[m]>
Gotcha, yeah I see the frustration. Maybe take a look at how the stm projects patch the SVDs? Maybe you patched it in a way that didn't quite fully fix the issue
SiHo[m]1 has joined #rust-embedded
<SiHo[m]1>
So what I kind of want to know is how to add the constraints needed to make it so that I can use `set`
<SiHo[m]1>
burrbull[m]: You still have to find and manually define the YAMLs for patching it right?
<SiHo[m]1>
* to find missing values and manually
<dirbaio[m]>
yep
dygear[m] has joined #rust-embedded
<dygear[m]>
<JamesMunns[m]> "(we're now live on the Inside..." <- The Embedded WG is conducting a MICRO survey. Coincidence I think not!
AdinAck[m] has joined #rust-embedded
<AdinAck[m]>
how can i know which target to use for a chip? the STM32G4 claims to be a Cortex M4 "with FPU", does that imply thumbv7em-none-eabihf? i've flashed it with and without the hf seems to work the same
<diondokter[m]>
AdinAck[m]: Yep!
<diondokter[m]>
It's kind of a mess, but in this you're right
<AdinAck[m]>
ok, iirc Embassy has no hf assigned to the G4, let me check again
<diondokter[m]>
Well... It works fine, it just won't use the hardware FPU instructions
<diondokter[m]>
So, if you want a nice embassy PR, there ya go!
<AdinAck[m]>
is there a cost-benefit decision here? what's the cost of enabling it?
<diondokter[m]>
AdinAck[m]: None that I know of
<AdinAck[m]>
hm, okey dokey, thanks again!
<diondokter[m]>
Maybe more power usage? But I'd think the faster instructions would counter that
<JamesMunns[m]>
IIRC there is a TINY penalty in some cases if you definitely never use floating point ops, but all floating point capable hardware can run with soft floats
<JamesMunns[m]>
if you DO use floats, you definitely want hf
<JamesMunns[m]>
the difference (IIRC?) in memory usage is around register stacking, in that interrupts will reserve space for stacking registers on interrupt call if the floating point core is enabled
<JamesMunns[m]>
but the registers are only ACTUALLY stacked lazily (unless you enable always-stack mode for determinism reasons)
<AdinAck[m]>
i am converting fixed numbers to f32 and assumed the binary size would be larger without hf but it was the same! maybe that conversion isn't accelerated by the FP instructions
<JamesMunns[m]>
and the target triple is used by cortex-m-rt to decide whether to enable the fp regs at boot time
<JamesMunns[m]>
maybe converting to fp doesn't use floating ops? doing math with it would definitely show noticable difference
<dirbaio[m]>
the target that matters is the one you put when building your firmware
<dirbaio[m]>
if the chip has a FPU, both -eabi and -eabihf work. -eabi will not use the FPU, so everything still works but floats are slower.
<SiHo[m]1>
* svd2rust generics. I don't understand what trait or constraint I'm not satisfying :/
<burrbull[m]>
SiHo: what values have you passed in writeConstraint?
<PaulDFaria[m]>
SiHo @siho0:matrix.org: in an earlier snippet, you had FI being filled by Dout. Can you paste that type's implementation? It should implement FieldSpec
<SiHo[m]1>
burrbull[m]: Sorry I don't see this field so I'm not really certain on what you are asking for?
<PaulDFaria[m]>
You have PortbDoutSpec as the register
<PaulDFaria[m]>
PaulDFaria[m]: And Dout as FI, 6 as WI
<burrbull[m]>
SiHo[m]1: `width` just specify size of field
<burrbull[m]>
burrbull[m]: It does not say what Values are safe to write there
<SiHo[m]1>
burrbull[m]: That makes a little bit of sense :) is there anyway of saying all values in the field are safe to write too?
<SiHo[m]1>
SiHo[m]1: so the full width can be used or do you still have to specify the writeconstraint?
<SiHo[m]1>
PaulDFaria[m]: Ah oki :) I'll look for wher Dout comes from
<burrbull[m]>
SiHo[m]1: `writeconstraint`
<burrbull[m]>
burrbull[m]: by default we consider all fields more 1 bit width are unsafe
<burrbull[m]>
burrbull[m]: and only `unsafe bits()` implemented
<burrbull[m]>
* only `unsafe fn bits()` implemented
<burrbull[m]>
burrbull[m]: `svdtools` was initially created to easy add `enumeratedValues` and `writeConstraint`
<SiHo[m]1>
burrbull[m]: Makes sense since a lot of RW registers have some settable and nonsettable values.
<burrbull[m]>
* `svdtools` was initially created to easy add `enumeratedValues` and `writeConstraint`
<burrbull[m]>
But then many functions for fixing bugs, collecting registers in arrays, etc. were added
<SiHo[m]1>
<SiHo[m]1> "Ah oki :) I'll look for wher..." <- Eh.. I can't find `Dout` from the generated code in the PAC. Anyways burrbull explained well in the above thread why I wasn't able to set it.
heksa[m] has quit [Quit: Idle timeout reached: 172800s]
jannic[m] has quit [Quit: Idle timeout reached: 172800s]
Henk[m] has quit [Quit: Idle timeout reached: 172800s]
bartmassey[m] has quit [Quit: Idle timeout reached: 172800s]
d3zd3z[m] has joined #rust-embedded
<d3zd3z[m]>
In developing Rust+Zephyr, I'm trying to reconcile the worlds of time between them. Fugit seems common in Rust. However, it rounds things down, so for example a Duration on a 32768 Hz clock would convert 10 ms to 327. Zephyr's conversion macros, on the other hand, always round up, so that any delay is always at least as long as requested. I can understand why Zephyr does it this way, but I'm not real sure how to reconcile things,
<d3zd3z[m]>
at least not without adding significant code on top of Fugit. Any thoughts?
<d3zd3z[m]>
My gut feeling on this, is that Fugit is actually just wrong about this. That when trying to convert time to a tick based timer, durations should always wait at least as long as the requested duration. At least this is how most RTOSes interpret this.
<d3zd3z[m]>
So, I'm trying to figure out the best way to handle this. One is to just use Fugit's Duration/Instant as my delay type, and document the caveats. It's likely going to trip up people that are from Zephyr (or pretty much any other RTOS for that matter). Another would be to basically make my own Duration/Instant types. Since the rounding happens before I get the values, I'm not sure if there is a way to actually handle this just using
<d3zd3z[m]>
the library.
<d3zd3z[m]>
Actually, looking further, I think I just need to document that it is important to use millis_at_least in the fugit library. I think that will do what I need.
<GrantM11235[m]>
It might be simpler and easier to use if you just define your own duration and instant types, the Fugit crate is pretty complicated because it tries to be very generic
<d3zd3z[m]>
Implementing it myself would also be fairly complicated. The Zephyr macros are pretty complex as well. The problem of changing a time base is just kind of inherently complex, especially to make it do as much as possible at compile time.
<d3zd3z[m]>
In my case, though, I will likely have a `pub type Duration = fugit::Duration<Tick, 1, SYS_FREQUENCY>;` where `Tick` and the `SYS_FREQUENCY` get defined based on the particular build and configuration being done.
<d3zd3z[m]>
So, it should be pretty much as easy to use as a custom type, but someone can use more of Fugit if that is helpful to them.