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
<firefrommoonligh> <thejpster[m]> "Did I make it better: https://..." <- Nice. I use macros
<firefrommoonligh> Would love to replace them with something better
<firefrommoonligh> This is doing the mutex syntax under the hood
<firefrommoonligh> (Or RTIC)
innegatives_ has quit [Quit: Connection closed for inactivity]
GenTooMan has quit [Read error: Connection reset by peer]
cybernaut has joined #rust-embedded
GabeR[m] has quit [Quit: Idle timeout reached: 172800s]
ryan-summers[m] has joined #rust-embedded
<ryan-summers[m]> [This PR](https://github.com/stm32-rs/stm32h7xx-hal/pull/483) brought it to my attention that apparently rustc is looking to deprecate `static mut` usage? Seems like this may impact embedded?
<ryan-summers[m]> It looks like just static mut references for now, but seeing that almost all frameworks use static muts underneath for storage, seems like it would impact us a lot. Is the general recommendation to instead use MaybeUninit cells and friends?
<JamesMunns[m]> I've been working on a crate to capture some actually nice and not UB patterns here: https://docs.rs/grounded/latest/grounded/
<JamesMunns[m]> Collecting thoughts/use cases here: https://github.com/jamesmunns/grounded/issues/1
<JamesMunns[m]> (I'm strongly of the opinion that `static mut` is a footgun in many cases, especially recommending it to beginners). The `grounded` crate is my work towards "don't just tell people what NOT to do, tell them what to do instead)
<ryan-summers[m]> Yeah because MaybeUninit seems like a horrible recommendation for newcomers. Even I have difficulty parsing it
<JamesMunns[m]> idk, I see it sort of like "simple vs easy", or "why does Rust have so many string types", or whatever
<JamesMunns[m]> we can recommend they use static mut, and that looks easier
<JamesMunns[m]> but like, getting static mut usage right is not trivial. especially for static muts that aren't like scope hidden in a module, or within a function.
<ryan-summers[m]> Yeah I don't disagree
<JamesMunns[m]> You have to guarantee so much is EXACTLY correct, no re-entrance, no aliasing, etc.
<ryan-summers[m]> They're tricky and easy to cause UB
<JamesMunns[m]> but yeah, having better data structures, like embassy's StaticCell, and better building blocks, I'm hoping to make it not painful
romancardenas[m] has quit [Quit: Idle timeout reached: 172800s]
IlPalazzo-ojiisa has joined #rust-embedded
<thejpster[m]> James Munns: That looks like a place I could put my irqstate types? I was thinking of spinning them off into a crate.
<thejpster[m]> Also, is it even possible to rewrite the cortex-m macros to not use static mut?
<JamesMunns[m]> yes, anything you can do with static mut you can do with other types
<JamesMunns[m]> (that being said, macro-hidden static muts are generally fine)
<JamesMunns[m]> or rather: with review, they can be :D
<JamesMunns[m]> thejpster[m]: Open to PRs! Happy to discuss if you have any specific questions. Hoping to keep that crate generally arch-agnostic.
<JamesMunns[m]> tho container types that work with critical-section deps are totally cool
<thejpster[m]> Not if the compiler removes them
<JamesMunns[m]> thejpster[m]: I'm not sure what you're saying. a `GroundedCell` can be used anywhere a `static mut` would be.
<JamesMunns[m]> and really, an UnsafeCell - though that isn't Sync, so you need a wrapper type like GroundedCell to be able to unsafe impl Sync for ...
<thejpster[m]> It was a response to
<thejpster[m]> > (that being said, macro-hidden static muts are generally fine)
<thejpster[m]> they may not be generally fine if the compiler takes them away
<thejpster[m]> I was just checking we do actually have a mechanism we can use to replace the macro-hidden static mut in cortex-m if we have to
<JamesMunns[m]> I was responding to "is it even possible to rewrite the cortex-m macros to not use static mut"
<JamesMunns[m]> if the compiler doesn't take away the static muts today, it wouldn't take away the unsafecell alternatives
<thejpster[m]> i guess unsafecell and an unsafe conversion to a mut reference is the general replacement for statuc mut
<JamesMunns[m]> Yes, ideally with some kind of synchronization, rather than "I pinkie promise this is legit"
<JamesMunns[m]> like, it could be macro-transform or cortex-m-rt knowledge like it is today, or it could be mutexes/once-checks for user code
<cr1901> FOr a second I started panicking, thinking they're gonna deprecate &MY_STATIC lol
<Ecco> I'm trying to use stm32-metapac. I've found this great sample project: https://github.com/cbiffle/stm32c0-metapac-example/blob/main/src/main.rs
<Ecco> Now, for example, in "rcc.cr().modify(|v|", where is "modify" implemented?
<thejpster[m]> I like yoshua's posts today about patterns in Rust and about how you can have an API that is either run-time checked or compile-time checked, depending on the caller.
<Ecco> thejpster[m]: Indeed
<Ecco> How did you find this doc? :)
<Ecco> And tried to look for "Reg"
<Ecco> but didn't find anything
<Ecco> Ha, you have to get in "common"
<Ecco> meh, I wish there was a search field
<Ecco> Thanks thejpster[m] :)
<thejpster[m]> i typed "modify" in the search box, lokl
<thejpster[m]> s/lokl/lol/
dne has quit [Remote host closed the connection]
<Ecco> Damn
* Ecco really feels like an idiot now
<Ecco> Thanks tho
dne has joined #rust-embedded
<firefrommoonligh> If static mut goes away, what's the best way to handle DMA buffers, ie making sure they don't drop while a peripheral is writing them?
<firefrommoonligh> I also am a fan of them for inserting debug statements at a reasonable rates in a high-rate function, with a counter
<firefrommoonligh> s/with/as/
<firefrommoonligh> So the console isn't spamming at 8kHz or whatever, I use a ratio of that
<dirbaio[m]> you can always replace `static mut FOO: T` with `static FOO: UnsafeCell<T>`
<dirbaio[m]> they're 100% equivalent
<dirbaio[m]> * (well you have to wrap the UnsafeCell in something with unsafe impl Send+Sync)
<dirbaio[m]> they're 100% equivalent
<dirbaio[m]> * (well, you also have to wrap the UnsafeCell in something with unsafe impl Send+Sync)
<dirbaio[m]> removing static mut doesn't take away any functionality, just convenience
<dirbaio[m]> you can still write the same thing, it's just now longer
<dirbaio[m]> and still equally unsafe
<dirbaio[m]> ¯\_(ツ)_/¯
<firefrommoonligh> Thx for the info
<firefrommoonligh> Maybe macro time if this happens
nohit has quit [Ping timeout: 268 seconds]
chrysn[m] has quit [Quit: Idle timeout reached: 172800s]
nohit has joined #rust-embedded
<thejpster[m]> yeah, you can replace `static mut FOO: T` with `struct DodgyCell(T); unsafe impl<T> Send for DodgyCell<T> {} static FOO: DodgyCell = DodgyCell(T);`. It's definitely more typing.
<thejpster[m]> * FOO: DodgyCell<T> =
<dirbaio[m]> DodgyCell 🤣 love it
<thejpster[m]> * `struct DodgyCell(UnsafeCell<T, * T>); unsafe, * FOO: DodgyCell<T> =
<JamesMunns[m]> <thejpster[m]> "yeah, you can replace `static..." <- Fwiw this is going to be called RacyUnsafeCell or SyncUnsafeCell in the stdlib
<JamesMunns[m]> Also, please, please don't push or suggest people to just find and replace like that. It's still marginally better, IF you don't make long lived references from it.
<JamesMunns[m]> Holding multiple `&UnsafeCell<T>`s is sound, while just holding a single & when you make a simultaneous &mut is immediate ub
xiretza[cis] has quit [Quit: Idle timeout reached: 172800s]
<thejpster[m]> James Munns: sent you some PRs for grounded. I proposed adding CI, which ran when I merged it into my fork, but won't run when I PR it against your upstream. I guess because arbitrarily running code on someone's repo is bad?
<thejpster[m]> I can't think of a good module name for the Global and Local types.
<firefrommoonligh> <thejpster[m]> "yeah, you can replace `static..." <- Dear ChatGPT: Please write a macro to simplify this syntax. The API to call it should be `access_dodgy(variable_name)`
<firefrommoonligh> And yea - I'm not doing anything until this is removed. This was the first I'd heard of that...
<firefrommoonligh> I'm just looking for a way to do DMA with a guarantee the buf won't drop while a periph is writing to it
<firefrommoonligh> *Also FFI things like CMSIS DSP filter state where the API uses pointers
marmrt[m] has quit [Quit: Idle timeout reached: 172800s]
swaits[m] has quit [Quit: Idle timeout reached: 172800s]
<JamesMunns[m]> <firefrommoonligh> "I'm just looking for a way to do..." <- https://docs.rs/grounded/latest/grounded/alloc_single/struct.AllocSingle.html should work for that
<JamesMunns[m]> The trick is that you need to couple together:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/bDfkDfKNVfLLBSRVsQSOQVci>)
<JamesMunns[m]> So, you need something like `Box`, that when forgotten, leaks the memory permanently, so the now "out of control" DMA is fine to write to the leaked memory with no visible side effects.
<JamesMunns[m]> or, you take the approach that embassy (and others, to be fair) take, and say "we don't consider `forget`-ing a DMA transfer to be safe".
<JamesMunns[m]> though in that case, you do still want to guard access to your source/dest memory with some kind of "stop DMA on drop" guard.
<firefrommoonligh> I appreciate the info! What would that look like in practice?
<JamesMunns[m]> You can look at embassy's various DMA abstractions, but generally you'd impl Drop for some DmaTransaction entity
<firefrommoonligh> Also, for anyone know knows, what is the chance static mut is being removed?
<Shell> this reminds me of io_uring in Rust, heh
<JamesMunns[m]> firefrommoonligh: I mean, at the MOST aggressive it gets deprecated in 2024, and removed in 2027
<JamesMunns[m]> Shell: yeah, same thing, actually
<firefrommoonligh> Oh! I will cease and desist
<firefrommoonligh> That is a lot of time in the future, so happy to keep using it
<JamesMunns[m]> I think they are adding deprecation warnings
<JamesMunns[m]> so you might get some of those. I don' think they can remove remove it until 2027 tho.
<JamesMunns[m]> (this is NOT forget safe, for this to be forget safe it would have to take ownership of the buffer).
marmrt[m] has joined #rust-embedded
<marmrt[m]> <firefrommoonligh> "Also, for anyone know knows..." <- https://github.com/orgs/rust-lang/projects/43/views/5 Here "remove static mut" is listed as rejected
<JamesMunns[m]> (which is under the "would like to accept" column)
<thejpster[m]> can you call a method on a static mut if you cannot create a reference to a static mut?
<thejpster[m]> Because x.foo() is just X::foo(&x).
<JamesMunns[m]> See the issue. you can "remake" a reference using `addr_of_mut!()`, but that (and your request) are nearly certainly UB.
<JamesMunns[m]> <JamesMunns[m]> "so you might get some of those..." <- oh, interesting:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/YsnKOrWoZZMaRjmNPUhfwGpf>)
<JamesMunns[m]> maybe they are calling it deprecated in 2021 edition, hard error in 2024 edition?
<thejpster[m]> we've got 12 months to fix cortex-m-rt then.
FreeKill[m] has joined #rust-embedded
<FreeKill[m]> Hello - I'm getting caught out with defmt right from the get go, with a link error = note: rust-lld: error: undefined symbol: _defmt_timestamp
<FreeKill[m]> is that familiar? I'm compiling for an stm32f072 with defmt and defmt_rtt
<FreeKill[m]> also getting address overlap warnings with the .text section
<FreeKill[m]> >>> .defmt.{"package":"f072-usb","tag":"defmt_info","data":"Poll!","disambiguator":"14953186050799278861","crate_name":"f072_usb"} range is [0x80000C0, 0x80000C0]
<FreeKill[m]> >>> .text range is [0x80000C0, 0x801B84B]
<thejpster[m]> does cargo tree show duplicate versions?
<FreeKill[m]> Er it shows it once as a direct dependency and once via defmt_rtt, but they're both the same version
<FreeKill[m]> Neeeeeeeeeeeeeeever mind, dumb typo
<FreeKill[m]> "link-arg=Tdefmt.x" instead of "link-arg=-Tdefmt.x" ... :'(
<firefrommoonligh> Btw, there was a breaking change in a recent rust version about ptr casting
<firefrommoonligh> You can tag the lines in question with an allow, or use UnsafeCell
stuw1 has quit [Ping timeout: 246 seconds]
stuw1 has joined #rust-embedded
<JamesMunns[m]> <firefrommoonligh> "Btw, there was a breaking change..." <- can you link what you're talking about?
stuw1 has quit [Ping timeout: 252 seconds]
stuw1 has joined #rust-embedded
pbsds has quit [Ping timeout: 276 seconds]
pbsds has joined #rust-embedded
notgull has joined #rust-embedded
jessebraham[m] has joined #rust-embedded
<jessebraham[m]> I've had a few people ask me now, haven't seen anything myself. But I'll ask anyway, is there any work going on to support Zigbee that I've missed?
cybernaut has quit [Quit: Leaving]
GenTooMan has joined #rust-embedded
notgull has quit [Ping timeout: 264 seconds]
notgull has joined #rust-embedded
reitermarkus[m] has quit [Quit: Idle timeout reached: 172800s]
sashin has joined #rust-embedded
sashin has quit [Remote host closed the connection]
sashin has joined #rust-embedded
vollbrecht[m] has quit [Quit: Idle timeout reached: 172800s]
<PhilMarkgraf[m]> Can I set the compiler used with a feature flag? I have a version of a library that has different behaviors depending on whether or not the MCU has an FPU. To support this I added the following to the .cargo/config.toml file:... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/iFaHKBXGLjsPbPGrkRvWWbYt>)
<dirbaio[m]> no, you can't :(
holo[m] has quit [Quit: Idle timeout reached: 172800s]
notgull has quit [Ping timeout: 260 seconds]
<PhilMarkgraf[m]> <dirbaio[m]> "no, you can't :(..." <- That is unfortunate. -- Thank you for the answer, though. It is good knowing.
adamgreig[m] has quit [Quit: Idle timeout reached: 172800s]
bumblebee[m] has quit [Quit: Idle timeout reached: 172800s]
barnabyw[m] has quit [Quit: Idle timeout reached: 172800s]
cgc17[m] has quit [Quit: Idle timeout reached: 172800s]
<JomerDev[m]> Hello. I'm looking for a bit of help with an issue on the rp2040 where I don't really know how to debug/progress further.
<JomerDev[m]> I'm trying to combine defmt-serial with embassy's uart over usb. Since all the uart methods are async but defmt-serial needs a sync method I pass the sender of a pipe, very similar to embassy's usb logger. However the rp2040 crashes on the first call to sender.try_write. I assume it's a mutex issue but I don't know how to get something better than the call stack with the rpi probe nor what to try to fix it
<dirbaio[m]> do you have your full code uploaded in some repo?
<JomerDev[m]> Sure, give me a second to push the latest changes
holo[m] has joined #rust-embedded
<holo[m]> Hey, i get in to problem with i2c trait in embassy. Im trying to move my sensor reading to separate async task but i can not satisfy, generic. Here is my implementation of sensor readings: https://github.com/holotrack/scd41-embassy-rs/blob/main/src/sdc41.rs... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/NkFYmuplxeJEnaseawnneMwB>)
<holo[m]> * Hey, i get in to problem with i2c trait in embassy. Im trying to move my sensor reading to separate async task but i can not satisfy, generic. Here is my implementation of sensor readings: https://github.com/holotrack/scd41-embassy-rs/blob/main/src/sdc41.rs... (full message at <https://catircservices.org/_matrix/media/v3/download/catircservices.org/UNPIvfeGqELGetgjTxmFeIdb>)
<dirbaio[m]> holo: try using the actual HAL i2c type:
<dirbaio[m]> `async fn measurments_task(sensor: SDC41<embassy_rp::i2c::I2c<'static, I2c0, Blocking>>) -> ! {`
<dirbaio[m]> (Async instead of Blocking if you need async)
<JomerDev[m]> dirbaio: https://github.com/JomerDev/MTBus/tree/main/source/mtbus-translator is the code I'm trying to run. It has some breakpoints already inside, one on start, one before the first try_write call and one in the hard fault handler
<dirbaio[m]> you're using it to convert a closure (that captures stuff) into a function pointer (that can't capture stuff)
<JomerDev[m]> I got that from defmt-serial. I only changed the type it expects in the defmt_serial call
<JomerDev[m]> * I got that from defmt-serial. I only changed the type it expects in the defmt_serial call
<dirbaio[m]> if the closure captures stuff, that stuff must be somewhere
<dirbaio[m]> s/somewhere/stored _somewhere_/
<dirbaio[m]> it's stored in wfn as a local variable in fn defmt_serial
<dirbaio[m]> so it's gone when that returns
<dirbaio[m]> so I think it's some sneaky use-after-free
<JomerDev[m]> The original `defmt_serial` call got a impl Writer<u8> + `static
<dirbaio[m]> yeah defmt-serial looks equally suspicious
<dirbaio[m]> the + 'static doesn't fix it, that just means it can live for 'static, but you have to store it somewhere for it to actually live forever
<dirbaio[m]> and it's not storing it anywhere beyond the local var in fn defmt_serial()
<dirbaio[m]> you'd have to take a `&'static mut impl Writer`, and then store *two* pointers in global variables: one to the closure and one to the writer.
<JomerDev[m]> If I store the writer in a global variable, can't I just not have the closure and use the writer directly?
<dirbaio[m]> or use alloc to put it in a Box or something
<dirbaio[m]> ah yeah
<dirbaio[m]> in your case you know the actual type (`Writer<M, N>`) so you can just store that
<dirbaio[m]> that's easier, yes
<dirbaio[m]> in the defmt-serial case it doesn't know the type (it takes an impl Writer, which can be any type impleenting Write) so it's harder
<dirbaio[m]> might be good to file an issue in defmt-serial too
<JomerDev[m]> Will do
<holo[m]> <dirbaio[m]> "holo: try using the actual HAL i..." <- > <@dirbaio:matrix.org> holo: try using the actual HAL i2c type:
<holo[m]> > `async fn measurments_task(sensor: SDC41<embassy_rp::i2c::I2c<'static, I2c0, Blocking>>) -> ! {`
<holo[m]> i can not find I2c0 type in that i2c.rs and compiler too. Where can i find it?
<dirbaio[m]> embassy_rp::peripherals::I2C0
<dirbaio[m]> or I2C1 if you're using I2C1
<JomerDev[m]> Hmm, I can't take `&'static mut impl Writer` since Writer is not a trait
<dirbaio[m]> yeah in your case just take a `Writer<M, N>` and put it in a `static mut writer: Option<Writer<M, N>>`
<dirbaio[m]> ah nooo you still need generics for M, N :(
<dirbaio[m]> well you can hardcode them
<dirbaio[m]> `Writer<'static, CriticalSectionRawMutex, 1024>`
<holo[m]> <dirbaio[m]> "or I2C1 if you're using I2C1" <- ahh ok capital C but now i have exactly same errors what with previous syntax: https://pastebin.com/PeKArfZ4
<dirbaio[m]> and make sure I2c refers to the actual driver struct
<dirbaio[m]> I2c can refer to the embedded-hal trait I2c, or the embassy-rp struct I2c
<dirbaio[m]> you want the struct I2c so it's an actual full type
<dirbaio[m]> don't use dyn
<dirbaio[m]> no generics
<dirbaio[m]> s//embassy-rp `/, s//`/
<Ecco> I'm writing a Rust wrapper around a C library. The C library provides me with a function pointer that it wants me to call in an interrupt. I think the only sane way is to store this pointer in the .data segment (i.e., in a global variable). But then using a "static mut" means it's unsafe. What would be the proper way to make this safe?
<holo[m]> <dirbaio[m]> "no generics" <- so i should not use this trait from this crate: use embedded_hal_async::i2c::I2c; but something else?
<dirbaio[m]> `static FN_PTR: critical_section::Mutex<Cell<Option<fn(whatever)>>>;`
<dirbaio[m]> * Ecco: `static FN_PTR:
<dirbaio[m]> holo[m]: exactly: `use embassy_rp::i2c::I2c`
<Ecco> oh, wow, let me digest this :)
<Ecco> I was considering using an AtomicPtr
<Ecco> The Option<fn> part, I understand
<Ecco> Everything on top of that I need to discover :)
<dirbaio[m]> AtomicPtr is somewhat cursed to store function pointers, you have to unsafely cast them
<holo[m]> dirbaio[m]: i took it from examples, let me try to look at it
<holo[m]> s/it/this one/
<Ecco> Yes, indeed, the cast back would be unsafe
<Ecco> But supposedly with Ordering::Relaxed they just don't really generate any runtime code
<Ecco> Out of curiosity, what runtime cost would critical_section::Mutex<Cell<Option<fn(whatever have ?
<dirbaio[m]> Cell is zero-cost
<dirbaio[m]> Option is zero-RAM-cost because fn() is not allowed to be null
<dirbaio[m]> but it still has to do the null check when reading it
<dirbaio[m]> and Mutex does a few instructions on entry and exit to disable/reenable interrupts
<Ecco> yes, I wanted to use Option anyway
<dirbaio[m]> so it does have some cost but it's quite small
<Ecco> ok, so Mutex will, on every single call, disable/renable interurpts?
<dirbaio[m]> yeah
<Ecco> ok, interesting. Thank you so much for taking your time to explain all this
<dirbaio[m]> so yes, AtomicPtr will be a bit faster
<Ecco> It's kind of sub-optimal for my use-case tho
<Ecco> ok :)
<dirbaio[m]> if you reaaaally need the speed it might be worth the extra unsafe, but you probably don't
<Ecco> Indeed, I don't
<Ecco> I'm just curious how this will behave tho
<Ecco> because I'm going to read the function from an interrupt handler
<Ecco> so I'm not quite sure what's going to happen if interrupts are disabled *within* the handler
<dirbaio[m]> it's allowed, it'll prevent other interrupts from firing while running that interrupt handler
<GrantM11235[m]> You should probably copy the fnptr out of the mutex and unlock it before you call the fnptr
<dirbaio[m]> (this can happen if the other interrupt has a higher priority than the currently-handled one)
<Ecco> ok, makes perfect sense
<Ecco> GrantM11235[m]: Not sure what you meant :)
<GrantM11235[m]> something like `let maybe_fn: Option<fn()> = critical_section::with(|cs| mutex.borrow(cs).get());`
<GrantM11235[m]> That ensures that the critical section is as short as possible, so you won't delay any higher priority interrupts for too long
<Ecco> oooooh
<Ecco> got it
<Ecco> I wonder if it wouldn't be easier to just try and code something on top of AtomicPtr tho
<JomerDev[m]> dirbaio: It seems to work now, no more crashes, thank you! I had to make the pipe static mut too and use unsafe to split it sadly. And I'm not sure if the serial connection is set up correctly, but thats a different problem
<Ecco> sure, *some* unsafe call would be required
<dirbaio[m]> JomerDev[m]: if you want to avoid that unsafe, you can put the pipe in a StaticCell
<JomerDev[m]> Thank you!
<JomerDev[m]> Also, maybe I said no more crashes too soon 😅
<JomerDev[m]> But I do get defmt logs now!
IlPalazzo-ojiisa has quit [Quit: Leaving.]
Foxyloxy has quit [Read error: Connection reset by peer]
Foxyloxy has joined #rust-embedded
emerent has quit [Ping timeout: 256 seconds]
emerent has joined #rust-embedded
<GrantM11235[m]> <Ecco> "I wonder if it wouldn't be..." <- It's not to hard, if you trust this transmute https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=9002ec82751306391a8716a3cc3e11d6
<GrantM11235[m]> You might need to change those fn()s to extern "C" fn()
<JomerDev[m]> Now I've got the next fun question. Why is the default config triggering multiple asserts in clock::init in embassy 🤔
<dirbaio[m]> the defmt logs might be corrupted?
<dirbaio[m]> these are assertions from rcc init, which runs before usb init. if that's failing, usb wouldn't work at all
<dirbaio[m]> and there's multiple assertions, it'd normally stop at the first one
<dirbaio[m]> maybe you're decoding it with a different .elf than the one you flashed
<dirbaio[m]> s/rcc/clocks/
<JomerDev[m]> 🤦 That makes perfect sense, I get an adc assertion failed every three seconds, which is the time I'm logging a I'm alive message
<dirbaio[m]> fun :D
<JomerDev[m]> Ahhhh. Yeah, it would probably help if I didn't pick the .elf of the wrong project (mtbus-controller instead of mtbus-translator)