sparky[m] has quit [Quit: Idle timeout reached: 172800s]
Lumpio- has quit [Ping timeout: 255 seconds]
Lumpio- has joined #rust-embedded
starblue has quit [Ping timeout: 258 seconds]
dreamcat4 has quit [Quit: Connection closed for inactivity]
starblue has joined #rust-embedded
johngigantic[m] has quit [Quit: Idle timeout reached: 172800s]
crabbedhaloablut has joined #rust-embedded
emerent has quit [Ping timeout: 258 seconds]
emerent has joined #rust-embedded
duderonomy has quit [Quit: My MacBook has gone to sleep. ZZZzzz…]
Shellhound is now known as Shell
<thejpster[m]>
I have two rust binaries, Crate A and Crate B, and they talk in memory through extern "C" function using types defined in some interface crate, Crate I. Is it possible to add a variant to an enum in Crate I without it being a breaking change? I tried to make the enums non_exhaustive, and rustc said that non_exhaustive enums were not FFI-safe.
<adamgreig[m]>
do you have a specific repr on the enum?
<adamgreig[m]>
if it was repr(rust) or repr(c) I'd worry that adding more variants could change the representation, but if it's repr(u16) it seems like it should be fine
<adamgreig[m]>
just guessing here though
<thejpster[m]>
oh, well. It was repr(C). Maybe repr(u8) will fix it.
<thejpster[m]>
no, doesn't help. And the non-ffi-safeness taints any other enums or structs you put it in.
<adamgreig[m]>
I think the problem ultimately is that if you're going through FFI then Rust can't know that C didn't put some random nonsense in the enum, whether or not it's marked non_exhaustive
<adamgreig[m]>
so your best bet may be to use u8 directly and parse it into the enum on the receiving side, although it's a bit annoying of course
<thejpster[m]>
the extern C functions are already unsafe to call
<wllenyj[m]>
It maybe help you.
<thejpster[m]>
I've read it, I use it and I'm afraid I'm not sure it's relevant here.
<thejpster[m]>
This is about some basic enum like enum MemoryType { Ram, Rom, Reserved, Stack }
<thejpster[m]>
What if the BIOS (Crate A) at a later date knows about some new type of memory, that the OS (Crate B) does not.
<diondokter[m]>
I feel like non-exhaustive is only for api changes, not for potential binary changes. Both sides of the API still need to agree on the same binary layout
<thejpster[m]>
binary layout sure
<thejpster[m]>
I just want the OS to think "OK, I know about the first four, but there may be additional bit patterns I don't know about which I will treat with a wildcard"
<diondokter[m]>
I don't think you can do that with Rust enums
<diondokter[m]>
You'd have an enum in an illegal state
<thejpster[m]>
having to recast all my FFI enum types as `struct FakeEnum(u8)` with `fn convert(self) -> Option<RealEnum>` would be a giant PITA
<diondokter[m]>
I think it's the only option you have.
<diondokter[m]>
Or create a macro that does it for you. Like a macro that generates the 'real' extern c function, but with the enum swapped to a number, and some glue to do the conversions. Don't know if that exists
<diondokter[m]>
Also, with num-enum it's less of a pain
<adamgreig[m]>
even if you don't have non_exhaustive, aren't they still not FFI safe?
fu5ha[m] has joined #rust-embedded
<fu5ha[m]>
Yeah. You can't use enums as C enums, there's no way to do it right now in rust. I was just talking about this the other day in a different context. You'll need to use a bitflags or enumflags-like crate or do the conversion from int to real enum like that
<fu5ha[m]>
adamgreig[m]: define "FFI safe". If you use a specific repr the layout and ABI is *stably defined*, but it is not the *same* as a C enum of the same layout.
<dirbaio[m]>
why isn't a repr(u8) non_exhaustive enum not ffi-safe though?
<dirbaio[m]>
I can't think of any reason
<fu5ha[m]>
non_exhaustive does absolutely nothing to the ABI
<fu5ha[m]>
so that's irrelevant
<diondokter[m]>
An enum in C is just an integer. An enum in Rust is an exact set of bitpatterns. You can't have a value that doesn't correspond to a variant. That'd be UB
<fu5ha[m]>
and the reason it could be defined as not FFI-safe is that if you give it a discriminant value on the other side of the FFI that is not one of the defined variants in your Rust code, you now created undefined behavior on the Rust side.
<diondokter[m]>
* An enum in C is just an integer. An enum in Rust is an exact set of bitpatterns. You can't have a value that doesn't correspond to a variant. That'd be UB
<adamgreig[m]>
dirbaio[m]: for one thing, inside the crate that defines it it's still allowed to just match every variant
<adamgreig[m]>
(so if you had been given it from C and it'd set an invalid value, that's UB)
<dirbaio[m]>
but that has nothing to do with nonexhaustive
<dirbaio[m]>
non_exhaustive means "I (the crate defining the enum) reserve the right to add more variants"
<diondokter[m]>
dirbaio[m]: Yes, on an API level
<dirbaio[m]>
that doesn't mean the C side can send any u8 value
<fu5ha[m]>
Yes. But only from a Rust semver perspective -- which always assumes static linking!
<adamgreig[m]>
right, but the practical implication is that users have to have a wildcard match, which you might hope would mean it'd be safe for unexpected variants to appear
<adamgreig[m]>
but it's not the case
<dirbaio[m]>
I can add more variants, not the C code
<adamgreig[m]>
ah, are you agreeing that a non_exhaustive enum still can't be FFI safe?
<dirbaio[m]>
if the C code gives me an invalid u8, it's ub. same as without non_exhaustive
<adamgreig[m]>
yea
<dirbaio[m]>
no
<dirbaio[m]>
I'd think if a #[repr(u8)] enum is FFI-safe, then a #[non_exhaustive] #[repr(u8)] enum should be too
<adamgreig[m]>
I think we're all agreeing on that point, but saying one might have hoped non_exhaustive could mean it could be FFI safe if you thought it meant everyone has to handle unknown varients/C code might add unknown variants
<fu5ha[m]>
Depends what you mean by "ffi safe". If you mean "you can send any bit pattern back" as "ffi safe" then it's not. If you just mean "there's a defined set of inputs where this is valid, if you violate them that's your fault" then it is
<adamgreig[m]>
ah, sure, please ignore my first message suggesting repr(u8), it's not right
<adamgreig[m]>
* the representation, <strikeout>but if, * be fine</strikeout>
<dirbaio[m]>
fu5ha: "FFI safe" is an actual defined thing the compiler enforces
<adamgreig[m]>
* the representation, ~but if, * be fine~
<dirbaio[m]>
it warns if you use non FFI safe types in calls to C
<adamgreig[m]>
* the representation, <strikethrough>but if, * be fine</strikethrough>
<dirbaio[m]>
what we mean by FFI safe is what the compiler means by FFI safe
<adamgreig[m]>
* the representation, ~but if, * be fine~ (no)
<dirbaio[m]>
rustc does consider #[non_exhaustive] #[repr(u8)] enum ffi-safe
<diondokter[m]>
Wait yeah... no warning
<dirbaio[m]>
perhaps it's only if you do the FFI call in another crate?
<dirbaio[m]>
because non_exhaustive is taken to mean "I reserve the right to add more variants, which means I might change it from repr(u8) to repr(u16) if I run out of bits?
<dirbaio[m]>
* because non\_exhaustive is taken to mean "I reserve the right to add more variants, which means I might change it from repr(u8) to repr(u16) if I run out of bits"?
<adamgreig[m]>
seems like this shouldn't be OK but perhaps it's wrapped inside the "well you called an unsafe FFI function"
<diondokter[m]>
adamgreig[m]: Yeah, this can't be correct
<dirbaio[m]>
non_exhaustive doesn't mean the C code is allowed to invent variants
<fu5ha[m]>
#[non_exhaustive] has no affect on ABI
<dirbaio[m]>
C code is still required to only return the defined variants
<fu5ha[m]>
I guess "FFI-safe" as defined by the compiler just means "has a defined ABI"
<adamgreig[m]>
adding/removing non_exhaustive to that enum doesn't make a difference though, I'm not sure it's involved at all
<fu5ha[m]>
I can't find any normative documentation that uses the term "FFI safety" anyway
<fu5ha[m]>
adamgreig[m]: Yes, it doesn't
<adamgreig[m]>
you get the warning if it's repr(rust) and not if it's repr(u8) or repr(c)
<adamgreig[m]>
so I guess the point is a) if it's repr(c) or repr(u8) then the ABI is at least well-defined (though you're still in trouble if one day the C side adds more variants and changes its idea of the ABI), and b) the call to an unsafe ffi function includes a contract that the C side doesn't produce unknown enum values?
<adamgreig[m]>
I'm not sure if it's legal in C to put unknown variants into an enum but it's certainly commonplace lol
<dirbaio[m]>
non_exhaustive means the Rust side can add more variants, not the C side
<adamgreig[m]>
doesn't non_exhaustive just mean foreign crates must include a wildcard match?
<fu5ha[m]>
The "rust side" is a bit ill-defined. You could be talking Rust-to-Rust over FFI and neither side would be able to add variants.
<fu5ha[m]>
Yes exactly
<dirbaio[m]>
adamgreig[m]: yes, to allow the Rust side to add variants without being semver-breaking
<dirbaio[m]>
that doesn't mean the C side can return a value of 4 for an enum with variants 1,2,3
<dirbaio[m]>
that's UB
<dirbaio[m]>
same as C returning a value of 2 for a bool
<dirbaio[m]>
* that's UB, with or without non_exhaustive
<fu5ha[m]>
#[non_exhaustive] is entirely a red-herring here, it has no affect on FFI conversation. It only allows Rust code to add variants without breaking external code that depends on it, assuming that the external code is still compiled within the same compilation! Thus the "external" code still has knowledge of the new variant when it is compiled. If the external rust code is on the other side of the FFI, #[non_exhaustive] is still
<fu5ha[m]>
entirely useless
<dirbaio[m]>
non_exhaustive doesn't relax the bit pattern validity requirements
<adamgreig[m]>
yes, I think we all agree it's still UB, not least because in the defining crate you can still exhaustively match
<fu5ha[m]>
Indeed
<dirbaio[m]>
the "forced" wildcard match in foreign crates will be compiled to nothing
<adamgreig[m]>
yes
<dirbaio[m]>
until you actually add a new variant
<dirbaio[m]>
so
<dirbaio[m]>
the original question is
<adamgreig[m]>
so your C code had better not give you an invalid value
<thejpster[m]>
in my case, it's defined in the API crate which both the OS binary the BIOS binary use
<adamgreig[m]>
so if there's an external non_exhaustive enum it takes it as a warning that the other side might still add new variants and it woudln't know about them through the FFI barrier and therefore warns you...
<thejpster[m]>
and both binaries are compiled independently and loaded next to each other into flash
<adamgreig[m]>
curious
<fu5ha[m]>
adamgreig[m]: indeed
<adamgreig[m]>
even though C code on the other side of the FFI could add new variants any time it wanted
<fu5ha[m]>
JamesMunns[m]: Not if you specify an explicit `#[repr(C)]` or `#[repr(int)]` which you need to do anyhow
<adamgreig[m]>
repr(c) can still change the size, right?
<JamesMunns[m]>
fu5ha[m]: Sorry are we strictly talking about valueless enums, right?
<adamgreig[m]>
on some platforms anyway
<fu5ha[m]>
JamesMunns[m]: yeah
<JamesMunns[m]>
adamgreig[m]: seems so, on cortex-m, I think jp noticed it bascally uses -fshort-enums
<thejpster[m]>
yes
<fu5ha[m]>
Yeah makes sense
notgull has quit [Ping timeout: 246 seconds]
notgull has joined #rust-embedded
waveguide[m] has quit [Quit: Idle timeout reached: 172800s]
kenny has quit [Quit: WeeChat 4.1.1]
frankplow_ has joined #rust-embedded
<frankplow_>
Hi there. Does anyone know if there's a way to set up SWO using the embassy-nrf HAL? The nRF-specific part is setting a value in the CLOCK.TRACECONFIG register. A quick grep doesn't show this being used anywhere in the source but embassy-nrf generally has a good coverage of the device's peripherals so it seems a little strange this is missing.
<ryan-summers[m]>
frankplow_: Those debug registers are usually configured by the probe via the SWD interface, not usually by the application
<ryan-summers[m]>
Any reason you want your app to do it instead of leaving it to the debug probe?
<frankplow_>
<ryan-summers[m]>: Yeah I made a patch to OpenOCD to do it, however it is not in the latest release yet and I don't want colleagues to have to use my fork.
<ryan-summers[m]>
Probe-rs also supports SWO and trace captures as well
<ryan-summers[m]>
But in any case you can always access the registers directly through the PAC
<ryan-summers[m]>
They may be provided from the cortex-m crate as well depending on which registers they are exactly.
<frankplow_>
<ryan-summers[m]>: The Cortex-M-generic part is fine, its the target specific config just to set up the pins.
<ryan-summers[m]>
Yeah, those would be exposed in the PAC, not the HAL. You're likely going to need to do teh manual register manips
<ryan-summers[m]>
s/teh/the/
<frankplow_>
<ryan-summers[m]>: Yeah I will resort to register-level for now. I might make a PR to add it in the long term because it can cause some funkiness if you try to use those pins elsewhere. Thanks.
frankplow_ is now known as frankplow
kenny has joined #rust-embedded
Guest7221 has left #rust-embedded [Error from remote client]
duderonomy has joined #rust-embedded
sourcebox[m] has joined #rust-embedded
<sourcebox[m]>
s/just/sjust/
<sourcebox[m]>
I'm using embedded-graphics on a 800x480 display. The largest built-in font is 10x20, which is still quite small on this display to use in some situations like a startup screen. Is there a better solution than including a larger external one? What would be a decent solution is to have the built-in font just scaled up by a factor of 2 or 3. Yes, this would make the pixels more visible, but that's ok for the purpose.
PhilMarkgraf[m] has joined #rust-embedded
<PhilMarkgraf[m]>
<sourcebox[m]> "I'm using embedded-graphics on..." <- You might have better luck asking this at: https://matrix.to/#/#rust-embedded-graphics:matrix.org
<PhilMarkgraf[m]>
<sourcebox[m]> "I'm using embedded-graphics on..." <- I'm using a library called ProFont for getting more font sizes and it has been nice to use. This doesn't help with your criteria of not adding an external font, of course!
<thejpster[m]>
Getting macro_rules to generate documentation was not easy.
<thejpster[m]>
(hence the string-literals for docs)
<sourcebox[m]>
<PhilMarkgraf[m]> "I'm using a library called..." <- In my specific case, I could easily use an external font because there's enough memory to store it. But in general, fonts often take a good amount of flash when they are large. So for just displaying a splash screen for a second on startup, it's probably not really worth to waste this amount of memory.
<sourcebox[m]>
Don't know if anyone here ran into this: in comparison to the F0 series, the G0 series uses the new internal IOPORT bus to access the GPIOs. This makes access faster, but also prevents to use the DMA on them.
<thejpster[m]>
Well I spent ages on this FFI-safe enum nonsense. Did I make it better?
<thejpster[m]>
I think I can now add enum variants without making it a semver-breaking-change on the FFI crate.
<thejpster[m]>
(of course, this change is a massive breaking one, but hopefully we avoid breakage and/or UB later on)
ryanpaulgannon[m has quit [Quit: Idle timeout reached: 172800s]
burrbull[m] has quit [Quit: Idle timeout reached: 172800s]
GrantM11235[m] has quit [Quit: Idle timeout reached: 172800s]
kevlan[m] has quit [Quit: Idle timeout reached: 172800s]
therealprof[m] has quit [Quit: Idle timeout reached: 172800s]
tamme[m] has quit [Quit: Idle timeout reached: 172800s]
M9names[m] has quit [Quit: Idle timeout reached: 172800s]
jake_001[m] has quit [Quit: Idle timeout reached: 172800s]
datdenkikniet[m] has quit [Quit: Idle timeout reached: 172800s]
barafael[m] has joined #rust-embedded
<barafael[m]>
on my firmware that uses CDC-ACM serial USB, sending from the device to the host works nicely. However, whenever I call tokio_serial::new to create the host-side endpoint, it seems to be sending these bytes on the channel:
<dirbaio[m]>
some software you have installed that probes all serial ports indiscriminately?
<dirbaio[m]>
trying to figure out if they're its device
<barafael[m]>
?! how is that happening
<barafael[m]>
I mean, it sounds like it is me?
<barafael[m]>
oh, I decoded these wrong. I suspected something like this, but didn't decode as hex
<barafael[m]>
My own device ID's itself as the string above on a new connection. It works all fine when I remove that identification. However, I am absolutely clueless why the device would read bytes on the bus that it writes itself?!
therealprof[m] has joined #rust-embedded
<therealprof[m]>
<diondokter[m]> "Oh cool haha, turns out some stm..." <- STM has been doing that for ages. They're not going to mask out hundreds of variants of their chips but simply have a few and then somethings disable features after the fact via lasering some connections but often they're just relabelling the chips accordingly.
<therealprof[m]>
That's e.g. how most of the STM32F103 boards came to be. Someone discovered that they all have 128kB despite being sold as much cheaper 64kB versions.
<diondokter[m]>
therealprof[m]: What a waste of silicon. But oh well, every silicon company does this
<therealprof[m]>
They could do binning, but with such chips, what are the odds that exactly one of those functions (and only those) fail which would allow them to make them a different chip.
<therealprof[m]>
diondokter[m]: Not really. The savings in silicon would be minimal by using a different mask but the cost of creating it, the dedicated processes for fabbing and testing and handling and the yield would probably not be much better.
<therealprof[m]>
Off course professional companies can't get away by using them either... so this is really just a nice tidbit for tinkerers...
<therealprof[m]>
s/Off/Of/
<diondokter[m]>
I don't literally mean the silicon. It's just a waste to intentionally disable features. The cost of the component stays the same. But I get that it's the most economical thing is to do.
<diondokter[m]>
Just like in cars. Order one without seat warmers, odds are pretty big they are installed in the seats and disabled by software
<diondokter[m]>
s/is//
<therealprof[m]>
Nowadays chances are high at least the cables are there.
<therealprof[m]>
With processors it's worth spending a bit more effort for binning but for MCUs, nah...
<diondokter[m]>
No, I get that! It's economically optimal. It just *feels* dumb and like you're being cheated
<adamgreig[m]>
Maybe more annoying when it's software features you have to pay loads to unlock on hardware things like test gear (and cars...)
<therealprof[m]>
Well, that's life... you're also getting the same bananas, whether you buy it from the big super market or from the little mom and pop fruit shop around the corner...
<adamgreig[m]>
But it does mean if you're willing to void the warranty or whatever you can get features way cheaper than you might otherwise, so...
<therealprof[m]>
adamgreig[m]: Indeed.
neceve has quit [Ping timeout: 240 seconds]
<JamesMunns[m]>
adamgreig[m]: I've seen it too in avionics, where you super aren't allowed to void the warranty :p
<dirbaio[m]>
<diondokter[m]> "Oh cool haha, turns out some stm..." <- the XML data files from stm32cubemx have a "silicon die ID" for all chips, so you can see which ones share a die
<dirbaio[m]>
could be useful for hunting more instances of that, I'm sure there are more
<therealprof[m]>
dirbaio[m]: That's a really good tip.
<adamgreig[m]>
JamesMunns[m]: Haha yea, plus also in those cases I can see developing the feature costs a fortune and not that much volume of customers so...
<therealprof[m]>
... and of course if you're using STM tooling, they'll happily tell you when you're trying to do something with a chip that's not supposed to have the hardware for that according to the specs.
<therealprof[m]>
"I see you developed this application for a STM32G041 and now you're trying to flash it onto a STM32G030... I can't let you do that, Dave"
<dirbaio[m]>
go to the ST store to buy the USART4 DLC!
<dirbaio[m]>
only $0.000005 per byte sent or received!
<adamgreig[m]>
and also the usart now has a gsm modem inside it for billing reasons
waveguide[m] has joined #rust-embedded
<waveguide[m]>
is there an embedded-audio type thing
<waveguide[m]>
I was looking at wrapping the sai interface for imxrt and realized maybe someone had an interface for such things designed as a set of traits