ChanServ changed the topic of #rust-embedded to: Welcome to the Rust Embedded IRC channel! Bridged to and logged at, code of conduct at
dc740 has quit [Remote host closed the connection]
starblue has quit [Ping timeout: 240 seconds]
starblue has joined #rust-embedded
emerent has quit [Ping timeout: 244 seconds]
emerent has joined #rust-embedded
cr1901 has quit [Quit: Maintenance... be back when I wake up]
<re_irc> <thalesfragoso> korken89: Are there any libs with PTP support out there ? I know adam has some work on it, but iirc it was for a specific application
<re_irc> <korken89> thalesfragoso: I do the same as he did, I got some pointers from him. As long as it is only "within your own thing" there is no need to support IEEE1588
iyed has joined #rust-embedded
iyed is now known as iyedonshismed
<re_irc> <James Munns> thalesfragoso i think tweedegolf recently did some work there? cc diondokter
iyedonshismed has quit [Quit: WeeChat 3.5]
<re_irc> <James Munns> (I don't know enough about PTP to tell if this is useful 😅)
<re_irc> <James Munns> oh. also realizing that isn't no_std. whoops.
<re_irc> <leobalduf> Hello! I'm new to embedded programming in Rust (I know Rust, and I've done embedded programming in C, but not in Rust). I'm looking to program some AVR mc as an I2C slave, which then reads out a bunch of devices via 1wire. I've done something very similar in C before (see here ( Now, as far as I can tell, I2C slave mode with embedded Rust might be difficult. So I was...
<re_irc> ... thinking: How about I write the I2C ISR stuff in C (basically copy what I've done before ( and link that in... somehow. Am I on the right track here?
<re_irc> <K900> I don't see why it should be difficult in Rust?
<re_irc> <leobalduf> I went by what I found in embedded_hal, which to me looks like functionality for I2C master.. but as I said: I'm new to embedded Rust, so I'm happy about any pointers :)
<re_irc> <K900> Well, you don't really have to use embedded_hal
<re_irc> <K900> There's usually a lower level library sitting below that that exposes APIs for the individual registers and such
<re_irc> <K900> Which would be pretty similar to what you'd do in C
<re_irc> <James Munns> The reason we haven't written good "I2C Peripheral/Slave" modes is that it's been hard to abstract as well as Controller/Master, where you can rely on blocking code
<re_irc> <James Munns> (just to add some flavor to what 9names is saying)
<re_irc> <9names (> I haven't said anything yet 🤣
<re_irc> <James Munns> Sorry, K900 :D
<re_irc> <K900> xd
<re_irc> <James Munns> So it's possible, there just aren't as many "off the shelf" abstractions handy
<re_irc> <James Munns> since it sort of relies on how you respond to the requests (e.g. polling, interrupts, async, etc)
<re_irc> <leobalduf> hmm, I see I see
<re_irc> <James Munns> that being said - not sure if the AVR HAL has abstractions for I2C peripheral mode (I've not really used AVR)
<re_irc> <barafael> This topic of i2c in peripheral mode keeps coming up. I guess it's hard because of the required "block until address match"?
<re_irc> <barafael> I made this smbus request parser thingy a while back:
<re_irc> <barafael> There is example code for setting up an stm32f0 there fwiw
<re_irc> <diondokter> Yes! Our PTP implementation is pretty minimal right now. The plan is to make it no_std and make a driver for the stm32 with smoltcp
<re_irc> <diondokter> Also, a blog is in the making which will be released any time now
<re_irc> <James Munns> barafael: Yeah, unlike controller where it's "do this now", it's "when X happens, you have N us to respond"
<re_irc> <James Munns> Which really requires either interrupts, or busy-polling
causal has quit [Quit: WeeChat 3.5]
<re_irc> <James Munns> You can get a little help from clock stretching, but the timeout is kinda short, and not every controller/peripheral supports it, so it's pretty situational
<re_irc> <James Munns> It's really the same with SPI peripherals too
<re_irc> <James Munns> It's definitely possible in Rust, I wrote an I2C bootloader for the stm32g0 acting as an I2C peripheral
<re_irc> <James Munns> but I also wasn't using any interrupts, and was basically busy polling the address match flag
<re_irc> <James Munns> (and not really doing anything else)
<re_irc> <James Munns> And I've written RTIC code acting as a SPI peripheral
<re_irc> <barafael> A crate could just offer an "address match callback" and leave the rest to the firmware right? Just a little clumsy that's all
<re_irc> <James Munns> It could! Though the callback would probably need to be "Sync + 'static"
<re_irc> <James Munns> The more typical "callback" approach I see is making a struct like "SomeI2CPeriph", which has a "handle_interrupt()" method
<re_irc> <James Munns> but that's usually when giving the struct to RTIC to manage as a resource
<re_irc> <James Munns> You'd probably want something like:
<re_irc> fn register_callback<F>(&mut self, F)
<re_irc> where
<re_irc> F: FnMut(Addr, &mut [u8]) -> Result<&mut [u8], Error>
<re_irc> <James Munns> but... storing that gets weird
<re_irc> <James Munns> and how you trigger ACK/NAK etc is also a little wierd...
<re_irc> <James Munns> And I guess that's only the "Read" callback, not the "write" callback
<re_irc> <James Munns> (oh and I forgot the "Sync + 'static" bound)
<re_irc> <barafael> Oh wow. Way more complicated than I thought.
<re_irc> <James Munns> Mostly the challenge is: That callback can be called at any time, so it needs to be "thread safe"
<re_irc> <James Munns> you also need somewhere to "store" that callback, and some kind of interrupt handler to call that callback
<re_irc> <James Munns> (not really storing the callback, but any data it needs to work)
<re_irc> <James Munns> like storing the "context" of a closure
<re_irc> <James Munns> Unless you're just responding with a fixed message or something
<re_irc> <James Munns> as a note, it's not that this is any _harder_ that it is in C, Rust just makes it harder to ignore when you could potentially get it wrong.
<re_irc> <James Munns> all those bounds and stuff for the callback are just as true in C, you just can't see them.
<re_irc> I found a few positive experience reports, I'm just curious if anyone knows what speeds I can expect, seems like a lot of setup.
<re_irc> <newam> Has anyone here tried fuzzing within QEMU?
<re_irc> <newam> That and it seems like no_std fuzzing in QEMU is not very well explored, but that should be relatively easy to hack in (I hope).
bjc has quit [Remote host closed the connection]
aspe has joined #rust-embedded
starblue has quit [Ping timeout: 240 seconds]
starblue has joined #rust-embedded
<re_irc> <James Munns> Just as a question: What kind of stuff do you plan on fuzzing?
<re_irc> <James Munns> I ask, because I feel like I wouldn't super trust QEMU's faithfulness of any actual hardware stuff (especially stuff like atomic ordering - but I could be wrong), and if you're fuzzing logic in a crate, I feel like you could get the same by fuzzing the crate "natively" on a desktop (though again - atomic orderings will probably be different between ARM and x86)
<re_irc> <James Munns> The other big difference would be 32 vs 64 bit, but you might be able to cross compile for "i686-unknown-linux-gnu" (at least on linux) as a fuzzing target
<re_irc> <James Munns> Not trying to say your plan is bad - but I've had this argument for things like running unit tests on target/on simulator, vs running "natively" on a desktop
<re_irc> <James Munns> It mostly comes down to what kind of bugs are you trying to catch. If it's logic bugs, 99.9% of the time you'll catch them equally regardless of platform. If it's unsafe, platform-specific stuff (or atomic orderings and stuff), yeah, it might need some other attempts.
<re_irc> <yruama_lairba> who already used STM32 i2s here ? i just discovered the "chside" status bit i not very reliable when in master transmit. maybe i issed some errata ?
<re_irc> <coljnr9> If anyone has experience with the stm32f7xx_hal and Serial DMA + RTIC (and also has a few free minutes), I'm struggling to get it working. I'm not amazing at Rust, but I've done a few projects in embedded C.
<re_irc> I'm trying to start the transfer from a software task, and then retrievee the data in a hardware task that binds to the DMA stream interrupt. I can only get the interrupt handler task to execute once, though I'd expect it to fire every time the DMA transfer completes.
<re_irc> I put what I think are the relevant bits of code into this gist, but the formatting might be off. Let me know if it's not clear, or if I'm in the wrong channel. Thanks!
<re_irc> <coljnr9> If anyone has experience with the stm32f7xx_hal and Serial DMA + RTIC (and also has a few free minutes), I'm struggling to get it working. I'm not amazing at Rust, but I've done a few projects in embedded C. I'm trying to start the transfer from a software task, and then retrievee the data in a hardware task that binds to the DMA stream interrupt. I can only get the interrupt handler task to execute once, though I'd...
<re_irc> ... expect it to fire every time the DMA transfer completes.
<re_irc> I put what I think are the relevant bits of code into this gist, but the formatting might be off. Let me know if it's not clear, or if I'm in the wrong channel. Thanks!
<re_irc> <coljnr9> If anyone has experience with the stm32f7xx_hal and Serial DMA + RTIC (and also has a few free minutes), I'm struggling to get it working. I'm not amazing at Rust, but I've done a few projects in embedded C. I'm trying to start the transfer from a software task, and then retrieve the data in a hardware task that binds to the DMA stream interrupt. I can only get the interrupt handler task to execute once, though I'd...
<re_irc> ... expect it to fire every time the DMA transfer completes. I put what I think are the relevant bits of code into this gist, but the formatting might be off. Let me know if it's not clear, or if I'm in the wrong channel. Thanks!
bjc has joined #rust-embedded
iyedonhismed has joined #rust-embedded
bjc has quit [Read error: Connection reset by peer]
bjc has joined #rust-embedded
iyedonhismed has quit [Read error: Connection reset by peer]
<re_irc> <yruama_lairba> coljnr9: what is the rtic version ?
<re_irc> <yruama_lairba> i don't understand why you need "interrupt::free" in the init part
<re_irc> <yruama_lairba> normally, with rtic, all interrupt are disabled inside the init context
<re_irc> <coljnr9> v1. Good point about the "free" - I've been pulling a lot from examples in my debugging, it could probably go.
<re_irc> <yruama_lairba> i can't see what return the init function
<re_irc> <yruama_lairba> i have a doubt about the Monotonic type you use, this is required for delayed spawning
<re_irc> <coljnr9> I'll drop this into the gist - I thought maybe it wasn't relevant because tasks are more-or-less working correctly (software tasks for SPI and blinking LED).
<re_irc> The return for "init" is essentially
<re_irc> (
<re_irc> Shared {
<re_irc> <coljnr9> +Monotonic is "SysTick". No idea if that's good, bad, or ugly.
<re_irc> <yruama_lairba> I think SysTick is just the choice by default
<re_irc> <henrikssn> yruama_lairba: This example should give you an idea:
<re_irc> <henrikssn> It is for SPI not UART so you need to adapt that a bit
<re_irc> <yruama_lairba> it's for coljnr9
<re_irc> <henrikssn> But the DMA stuff is very similar as soon as you get the peripheral setup
<re_irc> <henrikssn> Right, coljnr9 :)
<re_irc> <yruama_lairba> personnally, i'm stuck on I2S. i discovered "chside" status flag is not very reliable in master transmit mode
<re_irc> <coljnr9> It's actually been very smooth up to here, the HAL is great. I think the one I'm using ("stm32f7xx-hal") doesn't provide the "Transfer::clear_transfer_complete_interrupt()" method, but maybe I can do it "manually". Nice example, thanks henrikssn
<re_irc> <yruama_lairba> this make nearly impoosible to make a reliable hal on top of that
<re_irc> <yruama_lairba> is there a MCU hal supporing single buffer cycling DMA ?
<re_irc> <henrikssn> I would just recommend using the SVD crate at setting the registers manually if you need special DMA stuff
<re_irc> <henrikssn> * and
<re_irc> <yruama_lairba> i did a crazy stuff with DMA throught the pac interface : 2 single buffer cycling DMA stream working on the same buffer :p
<re_irc> <henrikssn> But I found bbqueue to be very helpful when working with DMA channels
<re_irc> <henrikssn> It is a much better alternative to a static buffer IMO
<re_irc> <yruama_lairba> henrikssn: link to bbqueue ?
<re_irc> <firefrommoonlight> yruama_lairba: As in a circular DMA buffer? The one I use does that
<re_irc> <firefrommoonlight> It's a field in a configuration struct; enum "Circular" with "Enabled" and "Disabled" variants
<re_irc> <dirbaio> stm32 circular dma is impossible to use safely in rust
<re_irc> <dirbaio> :(
<re_irc> <firefrommoonlight> Why's that? I've used it in a few cases and haven't encountered anythign weird
<re_irc> <firefrommoonlight> Specifically, I'm using it for SAI reads, SAI writes, and UART reads
<re_irc> <dirbaio> you have DMA do circular write to a buf. While it's writing to one half, rust code reads the other half with a "&[u8]"
<re_irc> <dirbaio> if that rust code is too slow, DMA will wrap around and overwrite the "&[u8]"
<re_irc> <firefrommoonlight> That's teh approach I'm using for SAI
<re_irc> <dirbaio> while the code is using it -> UB
<re_irc> <dirbaio> like
<re_irc> <dirbaio> it's impossible to make a HAL with a safe API for it
<re_irc> <dirbaio> unsafe, sure
<re_irc> <dirbaio> and ask the user "don't be slow or bad stuff will happen!"
<re_irc> <firefrommoonlight> When you say UB, you're referring to anomalies beyond corrupted data?
<re_irc> <yruama_lairba> it's depend the type, the right way to do it is to use a buffer of volatile cells with "u8","u16","u32" ... inside
<re_irc> <firefrommoonlight> I've encountered corrupted data it that circumstance, although nothing worse so far
<re_irc> <dirbaio> it's undefined behavior to modify data behind a "&[u8]" slice
<re_irc> <dirbaio> if you do that, ANYTHING can happen, not "just" data corruption
<re_irc> <firefrommoonlight> Gotcha
<re_irc> <dirbaio> by definition of UB
<re_irc> <yruama_lairba> the same issue may exist with double buffering ?
<re_irc> <dirbaio> yes.......
<re_irc> <dirbaio> :(
<re_irc> <dirbaio> I'm not saying you can't use it, i'm saying you can't expose a safe API for it
<re_irc> <dirbaio> at least I'm 99% sure it's impossible
<re_irc> <firefrommoonlight> It shouldn't stop anyone from wanting to use circular DMA in a rust program
<re_irc> <firefrommoonlight> It's a very useful tool
<re_irc> <dirbaio> the only way to make it safe is to use modes that DMA won't wrap around "by default"
<re_irc> <dirbaio> instead, the CPU gives it "permission" to wrap around
<re_irc> <firefrommoonlight> And if this UB manifests frequently / in surprising places, it's a significant blow to Rust's capabilites on embedded
<re_irc> <yruama_lairba> dirbaio: i think it's possible for type having shared mutability and approprite memory fence
<re_irc> <dirbaio> even if you fence or lock or whatever, in the end you'll give a "&[u8]" to the user
<re_irc> <dirbaio> or "&mut [u8]"
<re_irc> <dirbaio> in both cases it's UB if the user holds to the slice for too long that DMA wraps aroun
<re_irc> <dirbaio> * around
<re_irc> <dirbaio> and the only ways I know to do this are
<re_irc> - start next chunk by software, in the transfer complete interrupt
<re_irc> - use the fancy new stm32u5 gpdma
<re_irc> OR
<re_irc> <dirbaio> 😭
<re_irc> <yruama_lairba> dirbaio: you miss understand me, i was precisely think about a type provided to user that provide shared mutability and appropriate synchronisation throught methods
<re_irc> <dirbaio> these methods still can't create the "&[u8]" slice internally
<re_irc> <dirbaio> * internally, they'd have UB even if they don't give the slice to user code
<re_irc> <dirbaio> only thing you can really do is do all reads from the buffer as "volatile"
<re_irc> <yruama_lairba>
<re_irc> <dirbaio> that _would not_ be UB even if DMA wraps around, but it'll trash performance because the compiler won't be able to reorder/optimize buffer accesses
<re_irc> <dirbaio> vcell uses volatile internally
<re_irc> <dirbaio> also vcell is unsound
<re_irc> <thalesfragoso> dirbaio: Volatile doesn't sync, it would still be UB, even in theory
<re_irc> <dirbaio> hmm i'm not sure
<re_irc> <dirbaio> AIUI volatile means "translate this exactly to one hardware load/store instruction, then use the value it gives you"
<re_irc> <thalesfragoso> firefrommoonlight: It's the same in C, or any language for that matter
<re_irc> <dirbaio> so not sure how could volatile give UB
<re_irc> <thalesfragoso> dirbaio: Yep, it probably won't cause bigger problems, but it can still cause a data race, which is UB
<re_irc> <thalesfragoso> Honestly, I don't see how the compiler could do much more than buffer corruption and wrong reads, a panic on buffer overrun could probably save you from all problems, but yep, still UB
cr1901 has joined #rust-embedded
<re_irc> <adamgreig> dirbaio: isn't double buffered fine? iirc lots of the stm32 hals do that safely
<re_irc> <thalesfragoso> Just use a DMA with double buffering, hah
<re_irc> <adamgreig> circular mode is the troublesome one
<re_irc> <dirbaio> adamgreig: same issue, if user code holds on to one buffer for too long, DMA will wraparound
<re_irc> <adamgreig> yea but loads of easy fixes, either use three buffers that you rotate through or use the dma poisoning technique, either way the dma can never start writing to a buffer the user still has access to
<re_irc> <adamgreig> but you don't give up continuous reception
<re_irc> <dirbaio> matoushybl tried the "dma poisoning" thing for embassy, it didn't work
<re_irc> <dirbaio> on stm32h7 DMA
<re_irc> <dirbaio> it doesn't stop cleanly
<re_irc> <adamgreig> 🤔
<re_irc> <dirbaio> it continues writing to the other buffer
<re_irc> <thalesfragoso> dirbaio: What happened ? People were using in the H7 hal
<re_irc> <dirbaio> or something like that, I don't remember
<re_irc> <thalesfragoso> dirbaio: What ? Weird, was the write poisoning done in the right time ? You can't write to the ptr register while it's active
<re_irc> <dirbaio> I dunno, I didn't do it
<re_irc> <thalesfragoso> Which is very racy
<re_irc> <dirbaio> now _triple_ buffering is something I didn't think about 🤔🤔🤔
<re_irc> <dirbaio> that would definitely work
<re_irc> <adamgreig> triple buffering is the same as the poisoning idea but the third buffer is 0x0
<re_irc> <thalesfragoso> dirbaio: Done that for the F4 Hal, then Adam came up with the poisoning idea
<re_irc> <dirbaio> is there some impl of the poisoning somewhere?
<re_irc> <thalesfragoso> I think the safe interface of the F4 Hal still does triple buffering
<re_irc> <dirbaio> I had the understanding nobody had actually tried it
<re_irc> <dirbaio> +yet
<re_irc> <thalesfragoso> dirbaio: Last time I checked, H7 HAL used that
<re_irc> <thalesfragoso> stm32h7xx-hal
<re_irc> <thalesfragoso> Or was the f7 one, not sure
<re_irc> <dirbaio> 👀
<re_irc> <dirbaio> introduced here
<re_irc> <dirbaio> is it actually tested?
<re_irc> <dirbaio> does DMA actually stop cleanly? :P
* re_irc dirbaio grabs a random nucleo
<re_irc> <dirbaio> what's the easiest way to get a peripheral to blast lots of data at me?
<re_irc> <dirbaio> SPI read I guess
<re_irc> <dirbaio> too lazy to set it up
<re_irc> <dirbaio> is there a way to get DMA to spam reads as fast as it can?
<re_irc> <adamgreig> memory to memory?
<re_irc> <adamgreig> might be too fast to ever beat it lol
<re_irc> <dirbaio> or on a timer? :P
<re_irc> <adamgreig> yea, timer triggered m2m or gpio or something would work
<re_irc> <adamgreig> or just timer triggered read of timer count register, whatever
<re_irc> <yruama_lairba> why memory to memory is not good?
<re_irc> <adamgreig> it's very fast, so not the best thing to make it easy to choose whether to trigger race conditions
<re_irc> <firefrommoonlight> I will stay vigilant. Currently haven't had any demons show up from circular DMA
<re_irc> <firefrommoonlight> Single and double; in and out
<re_irc> <firefrommoonlight> For an example of single-buf, listening for signals from a UART-connected Rx receiver for drone flight control data
<re_irc> <firefrommoonlight> DMA continuously reads. On UART IDLE ISR, find the start of the packet in the buffer, and handle accordingly. Uses a buf size equal to packet size
<re_irc> <dirbaio> do I use TIM5_UP or TIM5_TRG?
<re_irc> <firefrommoonlight> *Of note, I haven't seen what happens if the receiver transmits on an irregular interval. That could actually be a trap
<re_irc> <dirbaio> to trigger a DMA on a timer
<re_irc> <firefrommoonlight> UP
<re_irc> <firefrommoonlight> *Actually I'm not sure re the timer trigger. UP is the answer for timer burst DMA.
<re_irc> <dirbaio> hmhmh do I have to enable anything special?
<re_irc> <dirbaio> the timer works but DMA doesn't
<re_irc> <dirbaio> (on stm32f767zi)
<re_irc> <firefrommoonlight> Not sure; nothing's jumping out. F7 is not mux, right?
<re_irc> <dirbaio> no dmamux, no
<re_irc> <dirbaio> dunno what the URS thing is, I copypasted it
<re_irc> <firefrommoonlight> Update Request Source
<re_irc> <firefrommoonlight> Counter overflow/underflow only, or any
<re_irc> <firefrommoonlight> Eg, if you haev over/under only, setting the UG bit or an update through teh slave mode controller won't trigger the Update event
<re_irc> <firefrommoonlight> *Which with TIMxUP, is what should be triggering your DMA
<re_irc> <dirbaio> DIER.UDE Update DMA request enable
<re_irc> <dirbaio> mayyyybe if I want the update dma request to work I should enable that 🙈😂
<re_irc> <dirbaio> panicked at 'DMA: error on DMA40026000 channel 0'
<re_irc> <dirbaio> now we're going places
<re_irc> <firefrommoonlight> Oh yea
<re_irc> <firefrommoonlight> That's requried
<re_irc> <dirbaio> I figured 😂
<re_irc> <dirbaio> now, why is it not happy reading from GPIOA.IDR? :P
<re_irc> <jannic> That's the tricky thing about UB: it often just works, until it doesn't. Regarding reading from a &mut [u8], as long as the buffer is sufficiently large and read sequentially, I don't see how the compiler would generate code that wouldn't work, even if the buffer gets modified concurrently by the DMA. But you can probably construct some access patterns where optimizations kick in which would become confused and actually...
<re_irc> ... cause bad results.
<re_irc> <firefrommoonlight> Hmm haven't tried that
<re_irc> <dirbaio> ah they're not on APB
<re_irc> <dirbaio> wohoo DMA goes brr
<re_irc> <dirbaio> [2022-05-22T21:27:54Z INFO device] Hello World!
<re_irc> [2022-05-22T21:27:54Z INFO device] ndtr=3ff isr=0
<re_irc> [2022-05-22T21:27:54Z INFO device] ndtr=400 isr=0
<re_irc> [2022-05-22T21:27:54Z INFO device] ndtr=3fe isr=0
<re_irc> [2022-05-22T21:27:54Z INFO device] ndtr=3fd isr=0
<re_irc> <dirbaio> +...
<re_irc> <firefrommoonlight> nice!
<re_irc> <firefrommoonlight> DMA goes bsrr
<cr1901> Amanieu: Something I've been thinking about: you told me inline asm has to restore SP by the time the block exits, right? 1/2
<re_irc> <yruama_lairba> > now, why is it not happy reading from GPIOA.IDR? :P
<re_irc> consult errata, there is a note about it for stm32f4
<cr1901> Does this apply if we jump out and never return to the inline asm block?
<cr1901> (To avoid XY problem: Thinking about how to do a minimal timer interrupt-based context switcher in Rust. SP will naturally need to be moved when switching threads)
<re_irc> <dirbaio> // WITHOUT POISONING
<re_irc> [2022-05-22T21:38:18Z INFO device] State { ndtr: 0004, tcif: 0000, teif: 0000, htif: 0000, cr_en: 0001, cr_ct: 0000 }
<re_irc> [2022-05-22T21:38:18Z INFO device] State { ndtr: 0003, tcif: 0000, teif: 0000, htif: 0000, cr_en: 0001, cr_ct: 0000 }
<re_irc> [2022-05-22T21:38:18Z INFO device] State { ndtr: 0002, tcif: 0000, teif: 0000, htif: 0001, cr_en: 0001, cr_ct: 0000 }
<re_irc> <dirbaio> so yeah it does stop 🤔
dc740 has joined #rust-embedded
<re_irc> <dirbaio> same if you poison m0ar later
<re_irc> <dirbaio> [2022-05-22T21:43:10Z INFO device] State { ndtr: 4, tcif: 0, teif: 0, htif: 0, cr_en: 1, cr_ct: 0 }
<re_irc> [2022-05-22T21:43:10Z INFO device] State { ndtr: 3, tcif: 0, teif: 0, htif: 0, cr_en: 1, cr_ct: 0 }
<re_irc> [2022-05-22T21:43:10Z INFO device] State { ndtr: 1, tcif: 0, teif: 0, htif: 1, cr_en: 1, cr_ct: 0 }
<re_irc> [2022-05-22T21:43:10Z INFO device] State { ndtr: 2, tcif: 0, teif: 0, htif: 1, cr_en: 1, cr_ct: 0 }
<re_irc> <dirbaio> well now I'm confused :P
<Amanieu> cr1901: If you never return then you don't need to restore anything.
<cr1901> And to be clear, re-entering the asm block due to another interrupt does not count as returning?
<re_irc> <dirbaio> cr1901: it should be fine as long as you save/restore the context properly
<re_irc> <dirbaio> dunno how interrupts work in msp430, but
<re_irc> <dirbaio> when entering an interrupt, isn't the "old" SP (from the non-interrupt) code pushed somewhere? it might be easier to manipulate that
<re_irc> <dirbaio> * somewhere by the hardware?
<re_irc> <adamgreig> the compiler cries at you if you so much as dare to call a function from within an interrupt
<re_irc> <adamgreig> (the TI msp430 compiler)
<re_irc> <adamgreig> +C
<re_irc> <dirbaio> then you do a normal interrupt return, except it returns to the "new" SP
<cr1901> No, only FLAGS and IP are saved
<cr1901> Unlike ARM Cortex M, the interrupt calling convention isn't C. Rather, the interrupt calling convention is: all registers are callee saved (seems reasonable enough :P).
<re_irc> <dirbaio> ah
<cr1901> well all except FLAGS and IP*
<re_irc> <dirbaio> actually I think SP is not pushed in ARM either
<re_irc> <dirbaio> BUT there's two stack pointers, so you can have interrupts use MSP while they manipulate PSP as they wish
<re_irc> <dirbaio> I think
<cr1901> No different modes for MSP430. My plan thinking about this was "deliberately remove the FLAGS and IP from the stack, save all registers _at that point_ as the context, restore new context, then unconditionally jump out of the timer interrupt
<cr1901> (timer interrupt active bit auto-clears itself when serviced)
<cr1901> I think it can be done w/ a relative small Rust crate, but it relies on being able to manipulate SP and unconditionally jumping out of an inline asm block back to Rust being non-UB
<cr1901> right Amanieu: Is "unconditionally jumping out of an inline asm block back to Rust" UB? I seem to recall "inline asm blocks can only jump to other inline asm blocks"
<cr1901> which, well, I don't think I can accommodate that as described lol
<Amanieu> I
<Amanieu> I'm having trouble seeing what exactly you are talking about, maybe some code would help?
<Amanieu> Basically, yes you can jump out of asm and enter Rust code, that's just calling a Rust from function from asm which is explicitly allowed.
<cr1901> it's going to be "psuedocode", but I'll link a playground snippet
<cr1901> and ack
<Amanieu> Normally I'd say "be sensible, don't exit from an asm block you haven't entered".
<Amanieu> But I have seen so much whacky (read: wrong) shit done with inline asm...
<cr1901> Amanieu: Almost done
<re_irc> <James Munns> SP isn't push on Arm, but interrupts ALWAYS use MSP
<re_irc> <James Munns> (thread mode is also using MSP, unless you explicitly enable it, which basically only OSs (Tock, Hubris, MnemOS) do)
<re_irc> <James Munns> SP isn't pushed on Arm, but interrupts ALWAYS use MSP
<re_irc> <James Munns> but yeah, you can muck around with PSP (or even MSP) from interrupts
<re_irc> <James Munns> (the latter would be a very bad thing to do in Rust)
<Amanieu> No no no, you can't do stuff like that.
<re_irc> <James Munns> (also, I think it's doing that thing again where Amanieu's responses aren't showing up on matrix again
<re_irc> <dirbaio> yeah I don't see them either
<re_irc> <James Munns> (if he's responding, I just see cr1901 talking into the void)
<cr1901> I can see Amanieu's responses
<cr1901> short version: I'm doing something he doesn't approve of :P
<re_irc> <James Munns> You're both on IRC right?
<cr1901> Yes
<re_irc> <James Munns> I think his messages just aren't bridged for some reason.
<cr1901> Amanieu: At least I asked for permission :)?
<Amanieu> You should have the whole function in assembly
<Amanieu> and call some Rust code for the middle part.
<re_irc> <James Munns> (there is another Amaneu here, which maybe the bridge doesn't like)
<re_irc> <9names (> As usual, you can follow along at
<re_irc> <Amanieu d'Antras> Hmm I didn't realize I still had this one.
<cr1901> I wish Libera got their shit together w/ this bridge
<cr1901> It's like the only single pain point compared to Fleenode
<re_irc> <dirbaio> fleenode, lol
<re_irc> <dirbaio> it's not libera's bridge, it's a custom one deployed by adamgreig
<re_irc> <dirbaio> because the room was too big to bridge or something iirc
<cr1901> Indeed, and I was hoping Libera staff would've gotten around to fixing it by now
<Shell> this bridge was set up before Matrix ran a bridge to Libera at all, I'm pretty sure.
<cr1901> Amanieu: Anyways, I sketched out this playground snippet on the fly. I didn't even realize before I linked it to you that I was uhhh... modifying SP without restoring in the first ASM snippet lmao
<Amanieu> timer_int definitely should be a naked function.
<cr1901> And apparently, TIL naked functions can't return either. So they're perfect for inline asm that never returns
<Amanieu> Basically, push all registers to the stack, call a rust function with a pointer to the saved registers as an argument, then restore all registers and return.
<cr1901> I think my struct is going to have to be packed in order to _guarantee_ the correct alignment of the struct
<cr1901> But "pointer to the saved registers as an argument" implies unsafe anyway
<cr1901> so maybe I should just skip the nicety of trying to access the saved registers as a struct
<Amanieu> I mean, the argument could be a &mut SavedRegs. No need for unsafe there.
<Amanieu> Of course, this code is inherently unsafe since you can mess with the register state of an interrupted task.
* cr1901 nods
<cr1901> Also, Rust should _never_ change the layout of SavedRegs to be anything but "contiguous u16s", but since no-padding isn't guaranteed without packed, I think I need the packed specifier
<cr1901> Or I could assume "Rust does the right thing and cut a patch release if Rust ever decides to change the layout of a struct of u16s" :P
<re_irc> <thalesfragoso> cr1901: repr(C) seems better
<cr1901> yea that's fair, and unlikely to change
<re_irc> <thalesfragoso> And I don't think repr(packed) guarantees order by itself, and can be quite unsafe
<re_irc> <dirbaio> "repr(C, packed)"?
<re_irc> <thalesfragoso> packed is better avoided, although I think rust will warn you w.r.t references to packed fields
<cr1901> if packed doesn't guarantee order, then it doesn't seem that useful for "treating wire protocols as if they're structs w/o having to copy to a linear buffer"
<cr1901> what does smoltcp do?
<re_irc> <dirbaio> &[u8] and manually encode/decode
<re_irc> <dirbaio> but
<re_irc> <dirbaio> repr(C) does guarantee order
<re_irc> <thalesfragoso> And all of our MMIO depends on it, heh
<re_irc> <thalesfragoso> But yes, C does guarantees order and will never change
<re_irc> <thalesfragoso> * guarantee
<re_irc> <dirbaio> and so does "repr(C, packed)", it's guaranteed to match a C struct with "__attributes__(packed)" or however it's written (?)
<re_irc> <thalesfragoso> Probably more underscores :)
<re_irc> <dirbaio> "repr(packed)" is the same as "repr(Rust, packed)" which doesn't guarante eanything
causal has joined #rust-embedded
<cr1901> repr(C) is probably what I want. I would question the compiler's credentials if it laid out "a struct of u16s" as anything except contiguous
<re_irc> <thalesfragoso> cr1901: I think C also guarantees no padding if not needed
<re_irc> <thalesfragoso> And rust wont probably add too, the problem would be more the ordering
<cr1901> Ahh hmmm...
<re_irc> <thalesfragoso> Although the order thing is actually to avoid padding automatically
<cr1901> well that's fair
<re_irc> <James Munns> theres an unstable flag that makes the compiler re-order fields to make sure you haven't made any assumption :p
<re_irc> <dirbaio> repr(C) guarantees "fields are laid out in the order they're written, and padding is inserted when encountering a field that needs it"
<re_irc> <James Munns> (e.g. re-order them on every compile, iirc)
<re_irc> <thalesfragoso> dirbaio: Nice docs, let's time I saw it was more like "it's exactly like C, whatever that means"
<re_irc> <thalesfragoso> * last
<re_irc> <dirbaio> well I think it's up to C's ABI
<re_irc> <dirbaio> there might be architectures with weird ABIs that do weirder things
<re_irc> <thalesfragoso> But of course that makes sense, because it's made for C FFI
<re_irc> <dirbaio> but that's what all abis I've seen do that
<re_irc> <thalesfragoso> James Munns: Now I need a RNG for rustc
<re_irc> <James Munns> I need to find that cursed "HashRng" that firefox uses...
dc740 has quit [Remote host closed the connection]
<re_irc> <James Munns> IIRC if the program uses ASLR, it uses that address to seed a PRNG
<re_irc> <James Munns> Now I need to find a citation for that, but it was from some desire to get rand without any dependencies. Not sure if it's still in use anywhere
<re_irc> <James Munns> Ah, I was mixing two stories:
<re_irc> <James Munns> They used DefaultHasher to generate some random numbers for non-load-bearing things, and someone on that thread using the ptr value of "main" (when ASLR is active) as additional entropy. I think there were also some random crates that used it as a lowest-value-entropy-source