starblue1 has quit [Ping timeout: 252 seconds]
starblue1 has joined #rust-embedded
tokomak has joined #rust-embedded
PyroPeter has quit [Ping timeout: 250 seconds]
PyroPeter has joined #rust-embedded
emerent has joined #rust-embedded
fabic has joined #rust-embedded
fabic has quit [Remote host closed the connection]
fabic has joined #rust-embedded
tokomak has quit [Read error: Connection reset by peer]
tokomak has joined #rust-embedded
fabic has quit [Ping timeout: 245 seconds]
<re_irc> <> Hi all,
<re_irc> <> i'm new to this channel, so it's cool that there is some extra community for embedded rust!
<re_irc> <> Currently i am on to follow this Tutorial right here:
<re_irc> <> [The Embedonomicon - Memory layout](
crabbedhaloablut has quit [Remote host closed the connection]
crabbedhaloablut has joined #rust-embedded
hifi has quit [Remote host closed the connection]
hifi has joined #rust-embedded
tokomak has quit [Read error: Connection reset by peer]
tokomak has joined #rust-embedded
<re_irc> <> What does the objdump look like?
starblue1 has quit [Ping timeout: 265 seconds]
fabic has joined #rust-embedded
<re_irc> <> i get this as objdump output:
<re_irc> <> the program should at the end always go to 0x0800000c (Reset is located 0x08000004, +0x8 goes to 0x0800000c)
<re_irc> <> another interesting thing: the cortex-m4 manual told that the resetvector is located at 0x08000004, at 0x08000000 resides
<re_irc> <> the initial stackpointer value. in this case we have space for a 16bit word, so if the SP should point to 0x20000000 + Ram Size, a
<re_irc> <> huh? `0x08000004` - `0x08000000` = 4 bytes, aka 32 bits
<re_irc> <> Benjamin Wilhelm: if you just want to get code running on the f3 disco board, you might be jumping in at the deep end a little
<re_irc> <> it looks like you have the actual reset function starting at 0x0800_0004, but it should instead be the 32-bit address of the start of the function
<re_irc> <> are you setting the stack pointer? if it's just left at 0 or uninitialised, then as soon as you have those local variables they try to be written to the stack, but the SP is set wrong and it causes a fault
<re_irc> <> but probably what's actually happening is the cpu is interpreting "sub sb, #4; movs r0, #42" as a four-byte pointer to the reset handler and jumping to it, which causes it to try and execute from invalid memory
<re_irc> <> (the space after 0x0800_0004 contains the addresses of all the other interrupt/exception handles, i.e. it's the vector table)
fabic has quit [Ping timeout: 245 seconds]
starblue1 has joined #rust-embedded
fabic has joined #rust-embedded
fabic has quit [Ping timeout: 252 seconds]
<re_irc> <> Just published a blog post on lorawan and rust - thanks to newam and jorgeig for their help with stm32wl
GenTooMan has quit [Ping timeout: 250 seconds]
fabic has joined #rust-embedded
GenTooMan has joined #rust-embedded
starblue1 has quit [Ping timeout: 245 seconds]
fabic has quit [Ping timeout: 245 seconds]
fabic has joined #rust-embedded
<re_irc> <> I just managed to link with the a C hal for arduino. That certainly opens the door for some cheating when implementing embedded-hal's for boards with arduino hals
starblue1 has joined #rust-embedded
tokomak has quit [Ping timeout: 252 seconds]
fabic has quit [Ping timeout: 246 seconds]
xnor has joined #rust-embedded
xnor has quit [Changing host]
fabic has joined #rust-embedded
fabic has quit [Ping timeout: 268 seconds]
<re_irc> <> hi room, meeting time again! Agenda's, please add anything you'd like to discuss, we'll start in 5min
<re_irc> <> ok, let's start! does anyone have any announcements?
<re_irc> <> guess not! first thing I had on the agenda is a quick discussion about the send/sync stuff we've been talking about for a while, I'd like to write something up in the book at least as a first draft we can build on
<re_irc> <> the gist would be what we (as in the wg) think send and sync mean in the context of an embedded no_std environment, or possibly specifically in the context of a microcontroller architecture like cortex-m
<re_irc> <> probably that will have to include defining priorities/execution contexts/threads, and probably also some discussion about multi-core considerations
<re_irc> <> the goal would be to have some more structured baseline for talking about these concerns and having a reference that other crates can use to help establish a more uniform approach to what's safe to do
<re_irc> <> it might turn out this cannot be consistent 😅 but given the recent conversations about it, it seems worth trying for?
<re_irc> <> Hm, are there any new insights? 😅
<re_irc> <> In no_std is there an easy way to convert a u8 to a &str so I can pass it to a debugging function that only takes &str?
<re_irc> <> I don't think so, which is why I think it's a good time to collect the insights and discussions and distill it into a useful page
<re_irc> <> please hold off on other questions until after the meeting, but maybe you want
<re_irc> <> I thought we had a useful page covering all the problems already.
<re_irc> <> which is what? I didn't think we had anything defining what send or sync mean in this context
<re_irc> <> the discussion that sparked this was whether "execution context = priority level" or "execution context = irq number"
<re_irc> <> both definitions are sound, but mixing crates that use both can create unsoundness
<re_irc> <> and there's no "official decree" saying which definition is the good one
<re_irc> <> oh, yea! I regularly forget about that RFC's existence, it does cover a lot of what we've talked about, but doesn't resolve exactly the priority level vs irq number thing
<re_irc> <> Indeed it doesn't cover those aspects.
<re_irc> <> perhaps that RFC could be distilled into a book chapter, but maybe it's fine as-is too, then, and we just extend it somewhat.
<re_irc> <> Hmm... Trying `from_utf8()` but now I'm confused since it apparently needs a static &str?
<re_irc> <> Re execution contexts. There was also some discussion and ideas floating around the proposal to remove `static mut` from the language with regards to modelling IRQ handlers as something Rust would consider a thread.
<re_irc> <> IMO that RFC needs adjusting a bit though
<re_irc> <> One of the larger problems with `Send` and `Sync` in the context of embedded is that from the compiler perspective there's only a single thread.
<re_irc> <> it says `Declare that Send is not sufficient to transfer resources between cores`, but there are many multicores that have exactly the same memory map, so you can use Send/Sync for multicore sending
<re_irc> <> RP2040's two cores have exactly the same memory map
<re_irc> <> both have some cpu-private peripherals at the same address, don't they?
<re_irc> <> I think multicore STM32H7's too, or almost (?)
<re_irc> <> the sram is the same, but not the whole memory map
<re_irc> <> adamgreig: yes, like the one that tells you which core you're on
<re_irc> <> there's a cpu-private SIO at the same address. I don't think that justifies banning Send/Sync for multicore sending though
<re_irc> <> how could you manage exclusive access to the private peripherals if it was possible to Send them between cores?
<re_irc> <> IMO the HAL simply shouldn't have an owned singleton for SIO
<re_irc> <> it's also the case for all the cortex-m0 peripherals, isn't it?
<re_irc> <> We could have different Singletons for global and core-specific peripherals
<re_irc> <> It was suggested that with compiler internals it would actually be possible to model interrupt handlers as separate threads (and of course multiple cores, too) which might unlock a whole world of new possibilities.
<re_irc> <> does the compiler know anything about multiple threads on hosted platforms?
<re_irc> <> it doesn't
<re_irc> <> right, I didn't think so, but clearly threads work OK on hosted platforms with send/sync
<re_irc> <> what sort of compiler support could help?
<re_irc> <> rustc just handles send/sync as any other auto trait, with the extra rule that `static mut` must be send+sync
<re_irc> <> enforcing "stuff must be Send to send it to other threads" is left to std
<re_irc> <> That abstraction is provided by the std/core libs, but if the threading is accurately modelled thinks like Send+Sync will work out of the box.
<re_irc> <> right, and so our objective here is to provide libraries to allow us to safely move things between threads by relying on Send+Sync?
<re_irc> <> the "std" equivalent for us is cortex-m, cortex-m-rt
<re_irc> <> e.g. cortex_m::interrupt::Mutex, albeit with the usual caveats
<re_irc> <> or maybe rtic
<re_irc> <> Yes, but you can't model a threading model without compiler internals.
<re_irc> <> how do you mean?
<re_irc> <> does core/std use some compiler internals to model hosted threads?
<re_irc> <> There're some magic primitives you can't access from regular crates.
<re_irc> <> huh, what do they do?
<re_irc> <> I don't know exactly, that's above my paygrade.
<re_irc> <> it's not clear what we'd need it for compared to what we already have, which seems to be enough to make things work, assuming agreement on what counts as "safe"
<re_irc> <> As I said, that was suggested in the `let's get rid of static mut` discussion.
<re_irc> <> perhaps the compiler thread stuff is more to do with stacks and TLS that the microcontroller hardware deals with for us for interrupt handlers?
<re_irc> <> Probably need to interview people like Ralf, lokathor, Simon Sapin and/or nagisa about that.
<re_irc> <> as far as I can dig out quickly it is just to do with TLS, so maybe not a huge concern for us atm, but yes
<re_irc> <> I think the problem is that interrupt handlers are just free floating functions which seem to be never called from anywhere from the compilers perspective.
<re_irc> <> That makes it hard to reason about data flow.
<re_irc> <> hm, sure, but that's also true of spawning a new OS thread that calls some function, I thought
<re_irc> <> anyway, that's probably enough time on the point for today, thanks for the insights
<re_irc> <> hm
<re_irc> <> not sure why the compiler should care
<re_irc> <> std::thread does unsafe ffi calls to pthread or windows api or whatever, passing a function pointer to the thread's main fn. Then magically the new execution context appears and calls that function
<re_irc> <> the cortex-m equivalent is the irq handler function pointer is stored somewhere (the vectors) and it gets magically called by the hardware
<re_irc> <> both of these are inherently unsafe, it's up to libraries (std, cortex-m, rtic, cmim..) to build safe abstractions on top
<re_irc> <> definitely rustc does have some compiler internals that std uses for TLS
<re_irc> <> but afaict it's only used for TLS
<re_irc> <> anyway I guess that's more or less independent of defining an execution context wrt priority/irq num
<re_irc> <> let's leave this for now and have a quick skim of the e-h PRs
<re_irc> <> 310 on reference impls is just waiting for a changelog tidyup then hopefully ready to merge
<re_irc> <> the errors,, has been quieter for a while, is anything else pending there?
<re_irc> <> adamgreig: Oh yeah, does anyone have a quick suggestion for that?
<re_irc> <> I'd remove the `Crc` error for Spi
<re_irc> <> there's no trait/method to do CRC stuff
<re_irc> <> so someone using CRCs will have to use HAL-specific methods, so they may as well use the HAL-specific error type for checking for CRC errors
<re_irc> <> "Add impls of all traits for `&T`/`&mut T` when T implements the trait" maybe? not sure where it's &T vs &mut T
<re_irc> <> like, the Error enums should only refer to functionality in E-H
<re_irc> <> adamgreig: It depends on the trait, most are `&mut T`
<re_irc> <> well for i2c you'd still want an error about lost arbitration even though that's not a "concept" in e-h?
<re_irc> <> That is a rather vague definition.
<re_irc> <> "arbitratino loss" is a "concept" of i2c itself isn't it?
<re_irc> <> It is, but has nothing to do with e-g.
<re_irc> <> I can see the argument against CRC in SPI specifically, it's very niche, but it could be _enabled_ by the HAL at configuration time (out of scope of e-h) while causing errors at runtime (in the e-h methods)
<re_irc> <> but yea, it's not really "part" of SPI in the same way arbitration and NAK is in I2C
<re_irc> <> I also agree that CRC is not a SPI concept.
<re_irc> <> adamgreig: HALs will have their own Error enum with more cases.
<re_irc> <> yea
<re_irc> <> has anyone here ever used the mcu's own spi crc?
<re_irc> <> `FoobarHal::spi::Error::Crc` would map to `embedded_hal::spi::ErrorKind::Other`
<re_irc> <> The original idea was to handle as many peripheral specific errors as possible in a generic way.
<re_irc> <> > Add impls of all traits for references (`&T` or `&mut T` depending on the trait) when `T` implements the trait.
<re_irc> <> How does that sound?
<re_irc> <> sgtm!
<re_irc> <> maybe "for reference types"?
<re_irc> <> what would a HAL-independent driver *even do* with a CRC error?
<re_irc> <> it hasn't enabled CRCing itself
<re_irc> <> it has no idea how the hardware is doing the CRC framing
<re_irc> <> a HAL-independent driver would almost surely be computing the CRCs itself, I expect
<re_irc> <> No need to argue about CRC in SPI, we're all in agreement here!
<re_irc> <> if one or two variants in the enums are the only remaining concerns hopefully we can land 296 soon then
<re_irc> <> DelusUs unification:
<re_irc> <> Alright I can remove the crc variant for spi then
<re_irc> <> it would be good to know if there are any further concerns with the rest of types
<re_irc> <> only outstanding one on the PR thread is about NoAcknowledge in I2C for data/addr nak
<re_irc> <> or perhaps leaving it at NoAcknowledge is not that bad
<re_irc> <> What would be your opinion on that as a hal impl-er therealprof ?
<re_irc> <> - NoAcknowledge: NAK after addr or data byte, the hardware is incapable of distinguishing them.
<re_irc> <> - NoAcknowledgeData: NAK after data byte
<re_irc> <> - NoAcknowledgeAddress: NAK after address byte
<re_irc> <> I think there are devices where a driver does need to distinguish data nak / address nak
<re_irc> <> ooi which stm32 were you looking at that has data/addr nak separate? all the stm32s i quickly checked seem to only have one nak flag
<re_irc> <> but perhaps something else happens if nak occurs after address
<re_irc> <> even arduino can distinguish address/data naks ðŸĪŠ
<re_irc> <> hmm I think you can distinguish them by *when* the nak flag gets set
<re_irc> <> does that work with a DMA-based impl?
<re_irc> <> maybe that is the reason why nrf supports that natively?
<re_irc> <> and other people do it time-based?
<re_irc> <> i2c+dma is ultra cursed
<re_irc> <> I can imagine, yeah
<re_irc> <> ah, yes, I see, there's a nice flow diagram in this RM
<re_irc> <> you write the addr to transmit to SADDR, then set the START bit
<re_irc> <> if you then get NACKF it means it nak'd the address
<re_irc> <> otherwise you can start writing to RXDR
<re_irc> <> I haven't seen any use of the more specific causes yet.
<re_irc> <> if you were going to do DMA, I guess you start it after the address has been ACK'd anyway
<re_irc> <> so probably most implementations could distinguish?
<re_irc> <> in principle it sounds useful to me
<re_irc> <> If we make it three kinds that means everyone has to always check all three.
<re_irc> <> that is also true
<re_irc> <> like this in f4xx
<re_irc> <> I'm not convinced of the usefulness but again that could be just me.
<re_irc> <> it's two different places the implementation might return early with an error, and I guess if you wanted to do something like implement an i2c address scanner using e-h you'd need to tell them apart, right?
<re_irc> <> or if you had a generic driver and you know the device can take any of 4 addresses, maybe you want to scan them?
<re_irc> <> Nope, you don't.
<re_irc> <> I2C scanning doesn't involve sending data.
<re_irc> <> it would be useful to distinguish if the device is not responding at all or if it is just busy and you can retry later
<re_irc> <> don't you send start + addr then check for ack/nak?
<re_irc> <> ah, right
<re_irc> <> if you send an empty slice and get nak, obviously it was from the addr
<re_irc> <> Yes, but no data. So you don't care when the ACK happens. 😉
<re_irc> <> or anyway you care but it could only have been to the addr
<re_irc> <> still, it feels like a meaningfully different error condition, since nak to addr means "no device responded to this addr" while nak to data means "a device did respond to this addr, but didn't like this command"
<re_irc> <> Hm...
<re_irc> <> do you have an example for a device where it is needed?
<re_irc> <> needing to have a catch-all NoAcknowledge for hardware that can't distinguish them is a bit of a shame in terms of user ergonomics
<re_irc> <> adamgreig: Dunno. Haven't seen such a situation yet but if people see it as usefull, that is okay with me.
<re_irc> <> I wonder if any impl really can't tell them apart
<re_irc> <> adamgreig: now that we know stm32 can distinguish them
<re_irc> <> is there any mcu that can't?
<re_irc> <> I would check on linux's i2cdev
<re_irc> <> even arduino can lol
<re_irc> <> Well, one version of the I2C peripheral can. 😉
<re_irc> <> it's non_exhaustive so if we did realise someone needs it later, it could be added as a non-breaking change, right?
<re_irc> <> 2:received NACK on transmit of address
<re_irc> <> 3:received NACK on transmit of data
<re_irc> <> "even arduino" is unfair given the ATmega has a pretty decent I2C implementation
<re_irc> <> though I guess the point is more "even the arduino HAL", which is implemented for a lot of different hardware
<re_irc> <> yep, that
<re_irc> <> Honestly "Arduino does it" doesn't mean it is useful.
<re_irc> <> but it does mean it can be done :P
<re_irc> <> adamgreig: That doesn't say that all hardware does it, only that ATMega does.
<re_irc> <> really, isn't it implemented for all the arduino boards?
<re_irc> <> mcu i2c slaves will data-nak when their rx buffer is full
<re_irc> <> Last time I checked there was a huge gap in implementation even for Arduino brand boards.
<re_irc> <> wow, I'm struggling to find what errors the linux i2cdev methods can return, lol
<re_irc> <> adamgreig: indeed, me too
<re_irc> <> yep, still no luck, "check errno"
<re_irc> <> but none of the errnos are i2c specific anyway
<re_irc> <> i could well believe it's different
<re_irc> <> maybe let's split into NoAcknowledgeData and NoAcknowledgeAddr for now, get the PR merged, and if during the next alpha release we find HALs struggle we can combine them or add a single NoAcknowledge?
<re_irc> <> it seems like HALs should all already be able to distinguish them fairly easily, and seems like there are some cases where it would be useful to tell them apart
<re_irc> <> yeah seems reasonable to me
<re_irc> <> Not sure about the latter but okay for me.
<re_irc> <> great, thanks all! that's it for time today
* re_irc needs to leave, thanks everybody!
<re_irc> <> we can look at deluyus, separate buffers, and CAN v4 next time
<re_irc> <> been scrolling through my datasheets folder
<re_irc> <> oh, and I've finally added some points to the newsletter, but if anyone has anything else they'd like linked or mentioned please let me know or PR it
<re_irc> <> adamgreig: already on there?
<re_irc> <> not yet!
<re_irc> <> PCA9632 data-naks invalid commands, you can use that to distinguish "chip not on the bus" to "chip in the bus but wrong command". Arguably it's not *necessary* because a driver shouldn't be sending wrong commands though
<re_irc> <> Also chip-not-on-the bus is usually only relevant during first communication.
<re_irc> <> Which can be easily detected with an empty send.
<re_irc> <> cpt212b (silabs touch sensor) did have some super weird behavior when updating the config: you have to send it in chunks and it data-naks each end of the chunk, so you can send next chunk on data-nak, vs abort on address-nak. That chip sucks anyway, I'm 99% sure it's a MCU in disguise with a pre-made firmware, we ended up not using it in the final product
<re_irc> <> arguably, its necessary for the person writing the driver to know if they did something wrong 😛
emerent has quit [Ping timeout: 252 seconds]
emerent has joined #rust-embedded