ChanServ changed the topic of #rust-embedded to: Welcome to the Rust Embedded IRC channel! Bridged to and logged at, code of conduct at
starblue has quit [Ping timeout: 252 seconds]
starblue has joined #rust-embedded
<AugustoRoman[m]> <haobogu[m]> "Try to make display outlives the..." <- Thanks! That was the hint that unstuck me.
<AugustoRoman[m]> I never figured out the previous problem, but I ended up solving the problem differently: Instead of accepting a closure, I returned my own MutexGuard-like struct that had the MutexGuards that I needed and the lock is now held by the caller for the necessary duration.
<enaut[m]> <juliand> "iirc you can often do something..." <- Oh thank you for the kind response! I somehow missed the thread-answer.
Guest7282 has joined #rust-embedded
M9names[m] has joined #rust-embedded
<M9names[m]> <tony[m]> "is anyone using probe-rs with..." <- > <> is anyone using probe-rs with the hifive1 rev b board?... (full message at <>)
ni has quit [Remote host closed the connection]
starblue has quit [Ping timeout: 264 seconds]
starblue has joined #rust-embedded
ni has joined #rust-embedded
crabbedhaloablut has quit []
crabbedhaloablut has joined #rust-embedded
dreamcat4 has quit [Quit: Connection closed for inactivity]
<orclev[m]> <slabity[m]> "I guess I'm a bit confused where..." <- rp-hal isn't really a thing, it's a workspace that contains a bunch of actual crates. The architecture is basically:... (full message at <>)
<orclev[m]> <orclev[m]> "rp-hal isn't really a thing, it..." <- generally the higher up the HAL stack you can go the better. If you're writing actual firmware typically you need at least that chips HAL if not the boards HAL, but if you're writing some kind of driver crate if you can manage it its better to base it on embedded-hal (so it works on many different chips and boards).
AdamHorden has quit [Quit: Adam Horden |]
AdamHorden has joined #rust-embedded
AdamHorden has quit [Quit: Adam Horden |]
Guest7282 has left #rust-embedded [Error from remote client]
Guest7282 has joined #rust-embedded
AdamHorden has joined #rust-embedded
ryan-summers[m] has joined #rust-embedded
<ryan-summers[m]> Anyone got any no-std hash utilities they can recommend?
JamesMunns[m] has joined #rust-embedded
<JamesMunns[m]> ryan-summers[m]: whatcha hashin for what?
<ryan-summers[m]> Just hashing strings to determine if they're the same as some future string in a little menu display. Nothing crypto or complex
<ryan-summers[m]> ahash looks like it might be fine?
<JamesMunns[m]> ahash probably is good, fnv1a is really easy to throw together at basically any size
<JamesMunns[m]> that being said: at least in the stdlib the original value is kept to ensure collisions don't happen
<ryan-summers[m]> For context, I'm not trying to make a hash map. I just want to:... (full message at <>)
<ryan-summers[m]> * For context, I'm not trying to make a hash map. I just want to:... (full message at <>)
<JamesMunns[m]> yeah - are you cool with false positives? e.g. skipping lines that have the same hash but different contents?
<ryan-summers[m]> Yeah that's probably fine
<ryan-summers[m]> This is just for a user visual display, so if it prints out the string twice, no harm no foul
<JamesMunns[m]> other way around
<JamesMunns[m]> one line is "ABC", the other is "DEF", but you skip DEF because it has the same hash as ABC
IlPalazzo-ojiisa has joined #rust-embedded
<ryan-summers[m]> Ah good point. Hmmm probably also fine
<ryan-summers[m]> As long as it's acceptably rare
<JamesMunns[m]> if the answer is "no", you have to keep the original. If the answer is "yes", you can just use the hash, if the answer is "wellllll not toooooo often" then you have to figure out how much is enough :)
<JamesMunns[m]> has a great table under Probability table
<JamesMunns[m]> "no. of bits" would be your hash length here, e.g. fnv1a32 would be the first line
<JamesMunns[m]> then you just need to pick if it's a 1/thousand or million or billion oopsie :)
<ryan-summers[m]> the fnv1a might be the best bet. I don't care about exact probabilities. Anything less than i.e. 1/100 is probably fine for my use case
Abhishek_ has quit [Quit: Connection closed for inactivity]
<JamesMunns[m]> you could also use the 32 bit version too
<ryan-summers[m]> const-fnv1a-hash has 16/32/64/128 bit support
<JamesMunns[m]> I was not aware it existed! I also made mine const in that file :D
<JamesMunns[m]> (postcard's schema hashing does that at const time)
<ryan-summers[m]> If you're at all interested, this is for a little settings management interface that we're building for Stabilizer:
<thejpster[m]> Is anyone going to Embedded World next week?
<thejpster[m]> I have a stand. Feel free to swing by and say hi. I'll be running bare-metal on an RP2040, OxidOS on an STM32F4 and QNX on an iMX8.
diondokter[m] has joined #rust-embedded
<diondokter[m]> <thejpster[m]> "Is anyone going to Embedded..." <- Yep! I'll be sure to visit ๐Ÿ˜„
mabez[m] has joined #rust-embedded
<mabez[m]> Espressif also have a stand, and I'll be attending this year, come say hi!
<mabez[m]> We have some ESP32-P4 demos with slint and a bunch of other cool stuff :)
<dirbaio[m]> I think we need to expand docs on eh1.0 SPI
<dirbaio[m]> I think we need to expand docs on eh1.0 SPI somehow
<dirbaio[m]> because people keep asking for this
<diondokter[m]> <mabez[m]> "Espressif also have a stand, and..." <- Will do! Already looked through the map to see all interesting stands
<adamgreig[m]> perhaps where we say "if you do have a CS pin..., if you do not have a CS pin..." it could be phrased more like "if you have a CS pin and just need normal transactions..., if you do not have a CS pin or need to manually manage the CS pin...."? or just specifically say "e.g. SD cards, some LCD displays, etc" lol
<dirbaio[m]> yeah
<dirbaio[m]> so, guidance on what to do when you DO have a CS pin but can't use SpiDevice
<JamesMunns[m]> "if you are trying to do something that LOOKS like SPI (like SD cards, a display), consider using SpiBus instead so you can control whatever whatever"
<JamesMunns[m]> * a display), but isn't actually SPI, consider using
<dirbaio[m]> and also guidance on how to still get bus sharing with manual SpiBus+CS
<dirbaio[m]> ๐Ÿซ 
<adamgreig[m]> yea
<adamgreig[m]> "can't use spidevice? here's ten different slightly annoying versions of T<SpiBus> you could use instead" :P
<dirbaio[m]> all for people to not read the docs
<dirbaio[m]> * the docs anyway
<adamgreig[m]> at least having it somewhere that's easy to point to rather than having to explain it in disparate issues might be useful for everyone. I think some people do read the docs
<adamgreig[m]> s/some/many/
<dirbaio[m]> totally
IlPalazzo-ojiisa has quit [Quit: Leaving.]
<adamgreig[m]> @room meeting time again! agenda is, please add anything you'd like to announce or discuss, we'll start in a couple mins
<JamesMunns[m]> another week, another "oh wow its tuesday again"
<dirbaio[m]> life is what happens between WG meeting and WG meeting
<adamgreig[m]> especially after a 4 day weekend
<adamgreig[m]> well, let's go! just one quick announcement from me, svd2rust 0.33 and svdtools 0.3.13 both released this week
<adamgreig[m]> anyone else have any announcements?
bartmassey[m] has joined #rust-embedded
<bartmassey[m]> Brief summary of the svd2rust changes?
<dirbaio[m]> breaking changes :D
<bartmassey[m]> Gratz!
AdamHott[m] has joined #rust-embedded
<AdamHott[m]> thanks everyone for your support over these past few months, I landed an internship!
<bartmassey[m]> is this the version that moves to functions for the thingies?
<adamgreig[m]> the main change of note in 0.33 is that bits() on fields is now always unsafe, which was a hole last time
<bartmassey[m]> Ah
<adamgreig[m]> field access has been a function for a while, since uh...
<adamgreig[m]> 0.31
<bartmassey[m]> Ah. Thanks
<adamgreig[m]> not a ton of other points this week, there's a point about the e-h i2c traits merging writes carried over from last week where the question is "could we support non-merged writes for intentional repeated starts"
<adamgreig[m]> besides that, dirbaio did you want to talk about spi device sharing docs?
<dirbaio[m]> not sure if there's much to talk about
<dirbaio[m]> it's been discussed in past meetings quite a bit
<adamgreig[m]> "we should do that" "yes" :P
<dirbaio[m]> it's just that someone should actually go and document it
<dirbaio[m]> because it keeps getting asked again and again
<dirbaio[m]> adamgreig[m]: exactly :D
<dirbaio[m]> who's that "someone" gonna be? any volunteers? :D
<dirbaio[m]> perhaps it'd be good if the approach has been tried on at least one project
<dirbaio[m]> I don't maintain any projects/drivers myself affected by that though..
<JamesMunns[m]> dirbaio[m]: and if none, when do we talk about how to fix this?
<JamesMunns[m]> making people feel more welcome to contribute?
<JamesMunns[m]> lowering the bar of effort?
<dirbaio[m]> candidates are the sdcard stuff, spi displays
<bartmassey[m]> I have been meaning to write SPI touchscreen for a display card I have that also has SPI display. If/when I get to it, I'll be happy to document what I figure out.
<adamgreig[m]> should this sort of thing ideally be an external volunteer with team member reviewing, or be done by a team member to start with? we have a few new people on the hal team now, but with e-h 1.0 out it feels like the primary work has become reviewing changes
<bartmassey[m]> Not sure when that will be though, because low priority
<adamgreig[m]> I feel like the contribution bar mechanically is hopefully not too high: you change the markdown in github, you can try it out with cargo doc locally, so I guess it's more about feeling like you know what to actually write
therealprof[m] has joined #rust-embedded
<therealprof[m]> Indeed.
<JamesMunns[m]> > feeling like you know what to actually write
<JamesMunns[m]> +1 to needing more people who feel like this, IMO.
vollbrecht[m] has joined #rust-embedded
<vollbrecht[m]> yeah but e-hal is this "special" crate where writing documentation is like writing a standard ;D its not like writing something onto some random function
<adamgreig[m]> +1, it's basically writing "here's the intent for these traits"
<therealprof[m]> (I was about to make a snarky comment about how other projects are trying find new contributors but I was able to hold myself back)
AtleoS has joined #rust-embedded
<bartmassey[m]> (I was thinking you managed anyhow, but thought it was obvious so didn't say it)
cbjamo[m] has joined #rust-embedded
<cbjamo[m]> I've shared a spi bus for communicating with both an SD card and a lora radio. Everything seemed to just work once I got both switched from using SpiBus to SpiDevice.
<AdamHott[m]> I'm reading through the issue and the transaction method, I don't know where I'd start
<AdamHott[m]> I'd need to do some kind of example
<adamgreig[m]> cbjamo: were you using the embedded-sdmmc-rs crate with the special CS pin?
<therealprof[m]> bartmassey[m]: Hopefully not, otherwise people might actually try to go down that route. ๐Ÿ˜…
<bartmassey[m]> oh, yeah, that display board has SPI SD on it also. So three SPI devices.
<bartmassey[m]> Bought it to teach students how to SPI.
<AdamHott[m]> bartmassey[m]: What display board did you use?
<bartmassey[m]> I got it from AliExpress. It's super-generic.
<bartmassey[m]> Let me find the link.
<cbjamo[m]> The docs for the transaction function here: Were clear enough for me to understand the point of Device vs Bus.
<adamgreig[m]> huh, interesting
<adamgreig[m]> but SpiDevice only acts with SPI asserted
<adamgreig[m]> and the problem embedded-sdmmc-rs has is that the SD card SPI spec says you have to do some clock cycles with CS deasserted
<dirbaio[m]> yea that seems odd too
<adamgreig[m]> which it's not clear that is actually doing
<cbjamo[m]> Could be that it just happens to work on the two pieces of hardware we're tested against?
<adamgreig[m]> yea, could be
<bartmassey[m]> My notes say 2.4" 240ร—320 Color TFT Display w/ MicroSDAliExpress 3256804356550040
<cbjamo[m]> I was worried about that when I opened the pr, because I don't know a ton about SD spi, but it worked with all the cards I had on hand.
<adamgreig[m]> I wonder how much "do some clocks without CS asserted" is actually a requirement then
<adamgreig[m]> I still like the idea of also taking a dummy SpiDevice that has a dummy no-op CS pin, which will also get you bus access for driving dummy cycles
<adamgreig[m]> but it's a bit tricky on linux where spidevice is sorta tied to the device tree CS pins... stupid linux
<dirbaio[m]> adamgreig[m]: that breaks bus sharing
<adamgreig[m]> I mean you take two SpiDevices, one for access with CS asserted, one for sending clocks without it asserted
<cbjamo[m]> adamgreig[m]: I would guess that the sd cards are being as permissive as possible, and so the embedded-fatfs impl squeaks in.
<dirbaio[m]> the whole point of SpiDevice was that if you see a driver taking SpiDevice you know it's going to play well with sharing
<dirbaio[m]> adamgreig[m]: oh uuuuh interesting
<dirbaio[m]> feels a bit like a hack
<dirbaio[m]> for example it forces the use of a refcell even when you don't want sharing
<adamgreig[m]> yea, it does mean you'd have to be using something that can provide two SpiDevices, and crucially on linux spidev it becomes much more annoying
<adamgreig[m]> so the answer I think remains "take SpiBus and a CS pin, manage CS yourself", but perhaps we need better ergonomics around sharing an SpiBus.. or back to "more docs"
<bartmassey[m]> I wonder if the requirement is just there to guarantee some latency for the device?
<dirbaio[m]> yea.. I don't think we should add an alternative SpiDevice trait
<adamgreig[m]> I think it's because the internal state machine nominally needs the clocks to turn off its bus drivers
<adamgreig[m]> it might be there's just some bus contention at the start of the next transaction
<adamgreig[m]> "just" lol
<adamgreig[m]> but perhaps all SD cards are able to turn off their bus drivers on the state of CS alone, like any other SPI device...
<bartmassey[m]> Yes, that. So enforcing a small delay between accesses might also be sufficient to satisfy such devices
<adamgreig[m]> in theory it's clock pulses they need, not just the time
<bartmassey[m]> When does EH turn off the clock?
<adamgreig[m]> it clocks once per data bit transferred, the clock's not free-running
<adamgreig[m]> and all data bits for an SpiDevice are transferred inside CS being asserted
<bartmassey[m]> Ah. There's the rub. I can never keep track.
<adamgreig[m]> you and everyone else, I worry :p
<bartmassey[m]> gtg. peace
<adamgreig[m]> the other minor point I had the agenda is to bring attention to the proposed async CAN trait for e-h-can,, for people using CAN
<adamgreig[m]> I think it's mostly uncontroversial given almost all the CAN-specific details are the same :P
<adamgreig[m]> but "does it go in embedded-hal-can-async or embedded-hal-can::asynch" and "should it have blocking try_x methods" and "should they return Option<Result<(), Error>>" questions are probably pertinent
<dirbaio[m]> now that AFIT is stable i'd do embedded-hal-can::asynch
<dirbaio[m]> like we already do for embedded-hal-bus
<dirbaio[m]> I think the try_* methods aren't needed tho
<dirbaio[m]> you need them in blocking if you want to write "busypolling-style" code
<dirbaio[m]> * "busypolling-style" code, to poll for multiple things concurrently
<dirbaio[m]> but in async you just use select/join
<dirbaio[m]> and if you want those you can just use the blocking trait even if your code is async ...?
<dirbaio[m]> s/those/`try_*`/
<adamgreig[m]> can you use both at once? it's sometimes useful even in async code right?
<adamgreig[m]> like how embassy_sync::Signal has non-async but also non-blocking try_take() and signaled()
<dirbaio[m]> hmm but you often use that to get async code to speak to non-async code
<dirbaio[m]> same as the channel ones
<adamgreig[m]> whereas with CAN you're probably either async code or not, and you can use the respective trait?
<dirbaio[m]> yeah
<dirbaio[m]> or you could do where T: embedded_can::blocking::Can + embedded_can::asynch::Can
<dirbaio[m]> but it feels like a weird edge case to me
<adamgreig[m]> I guess one main distinction is blocking::Can is fully blocking
<adamgreig[m]> and presumably we want to get rid of nb::Can
<adamgreig[m]> whereas the proposed try_x methods on asynch::Can are non-blocking
<adamgreig[m]> so you can't really use the blocking::Can trait for the same purposes
<dirbaio[m]> ah I thought blocking had try_*
<adamgreig[m]> nope, maybe because nb existed?
<dirbaio[m]> anyway `try_*() -> Option<_>` is definitely not async
<dirbaio[m]> it's "nb without nb"
<dirbaio[m]> feels like they shouldn't be there
<dirbaio[m]> we don't have that for serial, spi, etc either
<AdamHott[m]> Night folks! Gotta run!
<adamgreig[m]> well serial is embedded-io which has ReadReady
<dirbaio[m]> yea but there's no try_read()
<adamgreig[m]> spi only deals in transactions so there's no concept of "have you received a frame I could find out" or "do you have space to enqueue something"
<dirbaio[m]> yeayea
<adamgreig[m]> sure, but there's provision for non-blocking finding out if there's something in the buffer
<adamgreig[m]> don't need that for i2c/spi, might want it for uart/can
<adamgreig[m]> we could just as well have "tx_empty()" and "rx_not_empty()"
<adamgreig[m]> but instead of bools and then having to either hit the blocking or async methods to get the data, try_x seems more conventional
<adamgreig[m]> anyway, that's all we have time for this week, I'll leave a note on the PR. thanks everyone!
timokrgr[m] has joined #rust-embedded
<timokrgr[m]> bit late to the party, but I think try_transmit() makes no sense with async because you will effectivly only be using one mailbox anyway
<timokrgr[m]> the `&mut self` prevents any concurrent code from accessing the mailboxes
<adamgreig[m]> hmm
<timokrgr[m]> so you either await for your ongoing transmission to be finished or you drop the future which aborts the mailobx and frees it
<adamgreig[m]> shame it's not easier to just ask the future "are you ready yet" without having to muck around with pins and contexts
<adamgreig[m]> I can see the use of try_transmit if you weren't also using async I guess, if nothing else to stop you blocking on a full mailbox that's not emptying
<adamgreig[m]> (e.g. nothing else on the bus acking, so nothing leaves the mailbox and you're stuck...)
<timokrgr[m]> mhh maybe the intention of the PR is different: "Awaits until space is available in the transmit buffer."
<timokrgr[m]> that means async fn transmit() can return immediately
<timokrgr[m]> then the try_transmit() sort of makes sense
<timokrgr[m]> but then why use async at all
<adamgreig[m]> that matches the current blocking::Can, right?
<timokrgr[m]> yes
<adamgreig[m]> in terms of "returns once your frame is in the mailbox"
<adamgreig[m]> timokrgr[m]: it's still useful to be able to wait for space to become free, right?
<adamgreig[m]> but maybe not async transmit alongside try_transmit
<timokrgr[m]> yeah I see two async API apporaches:
<timokrgr[m]> 2. `async fn transmit()` returns immediately when buffer is free, waits when full
<timokrgr[m]> 1. `async fn transmit()` waits for the message to be delivered to the bus, single mailbox usage (no `try_transmit()`)
<timokrgr[m]> For the 2. API we must specify a buffering strategy though, which driver delevopers can depend on
<timokrgr[m]> example FIFO or priority based
<adamgreig[m]> I assumed it would be 2 to match blocking::Can and nb::Can, and if they need to more clearly specify the mailbox/queue contract then they all need updating
<timokrgr[m]> nb as a very specific contract (unfortunately)
<timokrgr[m]> priority ordering and fifor for messages with same priority
<adamgreig[m]> though I take your point about drivers
<adamgreig[m]> well
<adamgreig[m]> do you think it's something drivers should rely on, or something the end user application can configure?
<adamgreig[m]> usually CAN peripherals have a mailbox and you can pick FIFO or priority transmission I think?
<adamgreig[m]> are you imagining if we provided "always delivers immediately" then drivers could handle their own in-memory queue with their own fifo-or-priority transmission?
<adamgreig[m]> naively I might not expect that to live in a driver but perhaps I'm not thinking of the right sort of driver
<adamgreig[m]> perhaps something to implement one of the higher-level CAN protocols is what I should imagine, and they have specific contracts to enforce?
<adamgreig[m]> I don't know much about that level of detail for things like CANopen or Cyphal
<timokrgr[m]> adamgreig[m]: correct
<adamgreig[m]> so the approach taken by other embedded-hal things is "let the user configure the hardware, provide abstractions for communication"
<adamgreig[m]> if a crate using the UART requires 9600 baud, the user configures the port appropriately, the driver uses the trait object to send/receive bytes
<adamgreig[m]> the similar concept here would be the CAN trait just says "well there's a mailbox, maybe it has a single slot and always transmits immediately, maybe it has lots of slots and FIFOs or priorities", and it's up to the user to configure their hardware as appropriate
<adamgreig[m]> if there's a mismatch you could imagine their HAL could handle it, or a wrapper crate that talks to the hardware and manages its own queue
<adamgreig[m]> that's probably better than the CAN trait saying "MUST be priority based" and then a driver wanting FIFO or vv
<timokrgr[m]> I think as long as we pick one strategy its fine
<adamgreig[m]> ๐Ÿ‘๏ธ
<timokrgr[m]> so you mean if we lets say have CANopen stack, it documens that it requires its outgoing frames to sent in FIFO
<adamgreig[m]> I wonder if we should add try_transmit and try_receive to the blocking trait and remove the nb trait at the same time as adding the async trait
<timokrgr[m]> then its the users responsibility to configure the CAN hardware correctly?
<adamgreig[m]> yea
<adamgreig[m]> and if their hardware can't be configured for FIFO but is always priority, I was going to say they could have a wrapper in the middle, but actually you can just set the queue depth to 1 I suppose :P
<adamgreig[m]> but yea
<timokrgr[m]> if the driver is in prioriy queue mode and the driver expects it to be in fifo mode, most likely the application will just work
<timokrgr[m]> until it does not
<timokrgr[m]> because it depends on the busload
<timokrgr[m]> its very difficult to diagnose these errors so I would propose not to have the user configure the queing property
<timokrgr[m]> IIRC linux uses FIFO by default
<timokrgr[m]> and socket can is used by real products
<timokrgr[m]> IF we go with option 2.
<timokrgr[m]> what are the downsides of option 1. where each async transmission just waits for the message to be delivered?
<timokrgr[m]> this implicitly also includes support for transmit cancelation (when dropping the future)
<timokrgr[m]> (but then the next question is: do the blocking traits need cancelation too?)
<thejpster[m]> Sorry I missed the meeting. I see SD cards came up again. I propose switching to SpiDevice and telling people about the magic 74 clock cycles, leaving them to work out how to do it. I assume they wonโ€™t and I assume itโ€™ll usually be fine anyway.
<dirbaio[m]> aren't there magic cyclesafter each transfer?
<dirbaio[m]> not just at startup?
<dirbaio[m]> if it's just at startup the users could DIY before creatingthe driver
tony[m] has quit [Quit: Idle timeout reached: 172800s]
<adamgreig[m]> <timokrgr[m]> "this implicitly also includes..." <- Sorry, I had to run, but it's interesting to think about. You'd want cancellation even after transmission has begun? We could also say hardware should be in FIFO by default so HALs know what to do but users could always reconfigure
<adamgreig[m]> If we say it blocks until transmission actually completes you can't really have transmit mailboxes but maybe they're not needed and all the memory space could be used for receive, which I think is usually what I've done...
<timokrgr[m]> "You'd want cancellation even after transmission has begun?" A low priority message is stuck in the mailbox because of medium priority traffic on the bus. You need to transmit high priority message.
<timokrgr[m]> all fifo/queue management would fully be shifted to the software, nothing being done in hardware
<timokrgr[m]> new idea 3. "mailbox trait"
<timokrgr[m]> which only implements `transmit()` a HAL could then have something like `CanPeripheral::new() -> (impl CanReceiver, impl CanTxMailbox, impl CanTxMailbox)`
<timokrgr[m]> when it has two mailbox slots
<timokrgr[m]> but that makes things even more complex lol
<timokrgr[m]> probably "We could also say hardware should be in FIFO by default so HALs know what to do but users could always reconfigure" is the way to go if we want to stay close to the existing traits
IlPalazzo-ojiisa has joined #rust-embedded
<timokrgr[m]> there is also this issue with discussion on FIFO vs priority
Guest7282 has left #rust-embedded [Error from remote client]
IlPalazzo-ojiisa has quit [Quit: Leaving.]
firefrommoonligh has joined #rust-embedded
<firefrommoonligh> <adamgreig[m]> "I don't know much about that..." <- Cyphal is a hot mess
<firefrommoonligh> I would recommend staying away from it
<firefrommoonligh> *very* complex
<firefrommoonligh> I have a DroneCAN lib. The way the CAN ID is packet etc is fine, but some things like the ID negotiation and parameter get/setting are complicated
<firefrommoonligh> The bit level alignment is a pain too, but ... What you can gather is this all operates at a level not directly related to CAN hardware interaction. It's all about how you set the ID, and what messages, in what format, to send at what time .