tokomak has joined #rust-embedded
starblue1 has quit [Ping timeout: 250 seconds]
starblue1 has joined #rust-embedded
fabic has joined #rust-embedded
PyroPeter has quit [Ping timeout: 240 seconds]
PyroPeter has joined #rust-embedded
PyroPeter has quit [Ping timeout: 250 seconds]
PyroPeter has joined #rust-embedded
tokomak has quit [Read error: Connection reset by peer]
tokomak has joined #rust-embedded
<re_irc> <> Does anyone here know if it's "OK" to forward PoE? I'm thinking of making a small Ethernet based device that has one Ethernet in, one out and RMII to the MCU (so I'll have a 3 port swich IC on the board), but I'd like it to work from PoE and forward the PoE to the next unit. Just connecting the power center taps and forward the power seems to work fine - but I'm not sure if this can cause problems with like...
<re_irc> ... PoE+ equipment. Does anyone know here? I have only tried with passive PoE.
<re_irc> <> I can see that causing problems when the downstream devices wants to use LLDP to negotiate PoE+. You'd have to forward that as well.
<re_irc> <> Hmm right
<re_irc> <> Can one be sneaky and only go with passive PoE? Or is that a bad thing today?
<re_irc> <> I mean, I really don't care about other equipment - I just want to forward the PoE for it to work with more of my units in series
<re_irc> <> It's difficult for people to know what type of PoE their switch is providing
<re_irc> <> But I want to use Ethernet and normal cabling
<re_irc> <> So it would manifest as "some devices work fine" and others just don't at all, and it wouldn't be clear why
<re_irc> <> Maybe just mark the outport as "not ethernet"
<re_irc> <> Though that seems doomed to fail xD
<re_irc> <> Passive PoE with 100BaseT over the unused pairs is likely to work just fine IME.
<re_irc> <> Yeah, I have tested exactly this just as a PoC
<re_irc> <> ... also with "high end" PSE.
<re_irc> <> I connected about 600m of cable in the end with 12 units to evaluate
<re_irc> <> No problemo
<re_irc> <> But the PoE stuff scares me :P
<re_irc> <> So if you just forward and don't deal with LLDP, you would support basic PoE, but not PoE+ or PoE++
<re_irc> <> Most COTS stuff is likely to be PoE+ or PoE++ from what I've seen
<re_irc> <> Since most switches are gigabit nowadays since they're all pretty cheep
<re_irc> <> Right
<re_irc> <> What happens if you connect a "stupid" passive PoE device into a PoE+ PSE?
<re_irc> <> Without negotiation chip
<re_irc> <> Do they fallback to passive PoE or just nothing?
<re_irc> <> It depends on the PSE - if it supports basic PoE, it might work? Would have to dig into the standards
<re_irc> <> Makes sense
<re_irc> <> Maybe I should upgrade my house switch to support PoE+ :D
<re_irc> <> I haven't looked into how negotiation via LLDP works
<re_irc> <> I checked ICs such as MAX5969, but it would only make sense for the unit actually connecting to the PSE
<re_irc> <> But then I can request 25W Class 4 PoE
<re_irc> <> Quite a fun design challenge
<re_irc> <> Ah, so handle negotiation, but just reserve it for your downstream?
<re_irc> <> I just want to connect my sensors together and not be dependent on a star network
<re_irc> <> That's an interesting idea
<re_irc> <> But still stay in Ethernet land
<re_irc> <> As I don't want to hack my own communication protocols and all that :P
<re_irc> <> And <3 ethernet
<re_irc> <> But thanks for discussing! I need to experiment some more :)
<re_irc> <> And actually maybe read the standard xD
<re_irc> <> Oh, that negotiation chip can be used to enable power downstream
<re_irc> <> And if it sees actual PoE voltage it just turns on and assumes passive PoE
<re_irc> <> So the top unit would negotiate, and all the rest would just turn on
<re_irc> <> And then you just forward the PoE signals to the other ethernet port?
<re_irc> <> Yeah
<re_irc> <> One would need a switch to enable downstream power though probably...
<re_irc> <> But that can be solved
<re_irc> <> I think the various PoE implementations put the DC voltage on different pairs depending on the link speed. You may need to handle moving DC bias from gigabit pairs over to unused ethernet pairs
<re_irc> <> Hmm yeah
<re_irc> <> Might be simplified if you only assume 100Mbit PHYs?
<re_irc> <> Yeah, I force the managed switch IC to 100MBit currently
<re_irc> <> It supportes 10 and 100 MBit
<re_irc> <> (testing with the LAN9303)
<re_irc> <> It's not like my IoT sensors need 100 MBit either xD
<re_irc> <> But having 100Mbit "backbone" makes sure there are no perf issues ever
<re_irc> <> Nowadays it's probably more work to go 10MB only than to just go for 10/100 ;)
<re_irc> <> Yeah
<re_irc> <> They also auto negoitate 100 Mbit, so it was quite nice
<re_irc> <> Plug and play
<re_irc> <> You don't even need special crossover cables to go NIC-to-NIC anymore. Magic!
fabic has quit [Ping timeout: 265 seconds]
<re_irc> <> Though Auto-MDIX is cursed, too. High-end equipment still has problems with Auto-MDIX and even autonegotiation today so people still disable those features...
cr1901 has quit [Ping timeout: 260 seconds]
Amadiro has quit [Remote host closed the connection]
<re_irc> <> in general 802.3af (PoE) PSEs will not supply any "passive" PoE, only negotiated, and 802.3at/bt PoE+/++ PSEs will all (that I've ever seen...) also negotiate 802.3af/PoE just fine
<re_irc> <> I think your plan of having a PoE(+) PD chip on the upstream-facing switch port and then applying the DC power to a spare pair on the downstream port should work OK
<re_irc> <> Cool, so as long as one has the "negotiation chip" all should be fine I guess
<re_irc> <> unless your first device in the chain is always special, maybe just give them all the negotiation chip?
<re_irc> <> then any of them can be powered by passive or active PoE(+)
<re_irc> <> Yeah, I was sort of thinking the same
<re_irc> <> I wonder if it
<re_irc> <> If one only forwards the pairs
<re_irc> <> Else each unit would need to disable downstream power while negotiating
<re_irc> <> the PD chip in the most upstream device would not enable output power until it's negotiated
<re_irc> <> the PD chips typically gate the power out
<re_irc> <> you can buy PSE chips too, so could do active downstream PoE, but I don't think there's that much point
<re_irc> <> except _maybe_ safety concerns if you worry about 48V being live on a disconnected cable?
<re_irc> <> Yeah, but it's "in parallel" with just forwarding the PoE
<re_irc> <> Oh right
<re_irc> <> it wouldn't be in parallel, each PD would only turn on when it either negotiates PoE or detects enough voltage from a passive PoE
<re_irc> <> Ah, I mean if one just connects the center taps between the 2 connectors
<re_irc> <> they have to anyway, to control the current drawn from the PSE which is used for signalling
<re_irc> <> oh, yea, don't do that I guess
<re_irc> <> That's my sneaky current method
<re_irc> <> Yeah, adding a switch is no problem
<re_irc> <> if you have a bunch of uncontrolled loads I don't think PoE negotiation would succeed at all
<re_irc> <> usually the PD chips contain the switch
<re_irc> <> Yeah, but the PD chip is after a rectifier so you'd pay for the voltage drop per node
<re_irc> <> Hmm, but that can be cirumvented
<re_irc> <> asking for trouble without the rectifier
<re_irc> <> if someone uses a crossover cable by mistake...
<re_irc> <> how long are you imagining the chain being, given you only have like 12 or maybe 25W to play with?
<re_irc> <> So far with the "stupid" forward 600m was fine
<re_irc> <> sorry, I mean, how many devices?
<re_irc> <> Ah not sure, but I guess max 20
<re_irc> <> They draw just under 1W it seems
<re_irc> <> So with class 4 PoE I get 25W
<re_irc> <> - losses
<re_irc> <> hmm, yea, I guess 20 diode voltage drops would be pretty annoying
<re_irc> <> I guess each node can have a rectifier and just not daisychain the power through it
<re_irc> <> I have no idea to be honest I just like the idea of many units in a daisychain :)
<re_irc> <> use the PD power-good output to enable a bypass switch for supplying downstream
<re_irc> <> Yeah, something like that
<re_irc> <> I think just 2 back to back P fets would do it
<re_irc> <> so the device's own power comes through the PoE chip, and once the device is turned on, it can also turn on a switch to supply downstream directly from upstream pairs
<re_irc> <> Exactly
<re_irc> <> I think that would work and with low Rds on
<re_irc> <> don't forget about isolation, unless your whole device is not otherwise connected to anything else
<re_irc> <> but yea seems pretty reasonable. worth experimenting at least
<re_irc> <> It's all in a box, does one need isolated then?
<re_irc> <> Currently I just have a DCDC that supports up to 60V
<re_irc> <> not if the only external connection is ethernet
<re_irc> <> I like the TPS2378 PoE+ PD chip btw, though they're basically all the same
<re_irc> <> Yeah that's the only external connected the rest is radio and temp sensors :)
<re_irc> <> Oh
<re_irc> <> I have to take a look at that one
<re_irc> <> I currently have the MAX5969
<re_irc> <> That I can experiment with
<re_irc> <> I'm sure it's basically the same
<re_irc> <> I'll check :)
<re_irc> <> Ah yes it also connects the GND when negotiation is OK
<re_irc> <> Sweet always good to have more options in today chip shortage xD
<re_irc> <> To test the ethernet I'm harvesting STM32s from devboards xD
<re_irc> <> desperate times
<re_irc> <> Yeah
<re_irc> <> Luckily the devboards are almost the price of the ICs
<re_irc> <> Like i wanted the KSZ8863RLL 3port switch I
<re_irc> <> As it has finished Rust driver
<re_irc> <> Buuuut like 100 weeks leadtime xD
<re_irc> <> D:
<re_irc> <> And devboards with it is 100 euros
<re_irc> <> So no go there haha
<re_irc> <> I ended up with some irritating realtek rgmii phy recently because all the micrel/microchip rgmii were completely out of stock, frustrating
<re_irc> <> Luckily they had more that was equivalent
<re_irc> <> and of course all you can get for those is leaked datasheets with half the numbers redacted
<re_irc> <> OIof
<re_irc> <> guess what value of RSET current-setting resistor to use based on an ST app note for their MP1 dev board that used a similar realtek rgmii phy
<re_irc> <> seems to have worked, lol
<re_irc> <> xD
<re_irc> <> Haha awesome
<re_irc> <> As you said, deperate times
dreamcat4 has quit [Quit: Connection closed for inactivity]
<re_irc> <> But thanks for letting me pick your brain! :D
<re_irc> <> Now I need to get lunch
cr1901 has joined #rust-embedded
<re_irc> <> Hey adamgreig I remember sometime long ago you pointed me to an Ethernet based bootloader you liked, but I cannot for the life of me find it. Could you help me find it again?
<re_irc> <> in rust? maybe ?
<re_irc> <> Awesome that looks like it!
<re_irc> <> On a different note, how is the DHCP support in Rust Ethernet today is anyone knows?
<re_irc> <> smoltcp has good dhcp support
<re_irc> <> Sweet
<re_irc> <> thanks to some tireless work from dirbaio among others
<re_irc> <> Awesome!
<re_irc> <> Yeah, have been using smoltcp DHCP support for a while with great success :)
<re_irc> <> Next drive is DNS
<re_irc> <> Very nice to hear! I generally see in all examples that people use a static IP
<re_irc> <> I'll google around a bit for an DHCP example
<re_irc> <> If you're looking for a NAL/example of DHCP, take a look at stabilizer ( + smoltcp-nal (
<re_irc> <> there's also smoltcp's examples in
<re_irc> <> Awesome, thank you!
<re_irc> <> ryan-summers: One thing I saw, I saw that you got the MAC from an EEPROM
<re_irc> <> A newbie question there
<re_irc> <> The EEPROM is actually a MAC chip with like 128 bytes of EEPROM as well
<re_irc> <> It comes from microchip with a hardware unique MAC to use
<re_irc> <> Ahh cool
<re_irc> <> I saw that MAC is assigned based on company and such
<re_irc> <> So I was sort of wondering if it's like with USB where one needs to buy a AMC
<re_irc> <> Yeah, we just buy the chips from microchip, so the MAC is using Microchips company code
<re_irc> <> AFAIK the chips are still really cheap
<re_irc> <> Nice
<re_irc> <> Awesome, another worry laid to rest :
<re_irc> <> Thanks!
<re_irc> <> No worries!
<re_irc> <> you can also buy a small MAC prefix (4096 addresses) for not much money, but then you have to organise assigning them to hardware
<re_irc> <> the MAC EEPROMs are really nice, I've used them on a bunch of things
<re_irc> <> advantage of buying an actual prefix is that wireshark will eventually update to show your company name in the decodes which is pretty fun
<re_irc> <> (still $780, so only "not much money" compared to a USB VID)
<re_irc> <> you can also use a random locally administered mac address 🙈
<re_irc> <> you can also just make them up and use locally administered ones, if you just want to watch the world burn :P
<re_irc> <> Hehe
<re_irc> <> and hope no network admin gets angry at you
<re_irc> <> lol
<re_irc> <> I saw you typing and knew what you were about to say :P
<re_irc> <> ahhahah 🤣
<re_irc> <> Huh but this reminds me of a thing
<re_irc> <> Aren't phones and such always using random MAC?
<re_irc> <> I guess that's maybe only for WiFi though
<re_irc> <> Cable connected stuff might now be as happy with the idea
<re_irc> <> well you can assign a random mac at factory, so it's random per device, not per boot
<re_irc> <> Yeah
<re_irc> <> Would that pass certification tests?
<re_irc> <> I don't think there's any such test for ethernet (?)
<re_irc> <> Ah well then, no problem :D
<re_irc> <> the only downsides are
<re_irc> <> very remote chance of collision, in practice none because literally nobody uses the locally administered range
<re_irc> <> and it's rude to network admins because they can't see what company made the device
<re_irc> <> Right, thanks for the clarification!
<re_irc> <> some SBCs do that too, orange pis for example
<re_irc> <> If you share a network with android and ios phones then all of them will default to locally administered random macs.
<re_irc> <> yea, for wifi there are privacy implications of using a fixed mac on a personal portable device
<re_irc> <> eg on android, on wifi network details, you can set random/device MAC per-network
<re_irc> <> they still have 46 bits of entropy, collisions should be ultra rare
<re_irc> <> just pointing out that locally administered addresses are in fact very common and the chance of collision isn't zero. you expect to have one collision in a set of couple million.
<re_irc> <> 🤔 how do android/ios deal with these collisions then?
<re_irc> <> No idea. Guessing that they either pray or do probing similar to stateless autoconf for ip6
ni has quit [Quit: WeeChat 2.8]
ni has joined #rust-embedded
fabic has joined #rust-embedded
<re_irc> <> How would I go about making the linker put a whole module (say, everything in crate::external, into another section of flash) and also, how would I do the same with a whole library?
<re_irc> <> (trying to bring back a project I put on hold a couple months ago because I could not figure this out
<re_irc> <> )
<re_irc> <> I ended up with two binaries, and copying one of them with include_bytes into the other.
<re_irc> <> Good question. I was also not able to solve that particular problem.
<re_irc> <> + Some linker script magic and awful code
<re_irc> <> ah, do you have a link to code that I could look at? (linker script magic)
<re_irc> <> Unfortunately no, but I can summarize:
<re_irc> <> include_bytes into a static array with #[link_section].
<re_irc> <> And then use that section in the linker script, to put it where you want.
<re_irc> <> I don't know a good guide for linker scripts, I learned by example
<re_irc> <> I was able to call into that code then, by declaring a struct of function pointers, and assigning the correct address, with the help of the linker script.
<re_irc> <> The blob in the static array contained a trampoline at t beginning, which forwarded to the correct address inside.
<re_irc> <> Of course everything extern C. Maybe that was unnecessary.
<re_irc> <> that's a pretty neat way of ensuring the code doesn't call into functions that end up in flash or anything
<re_irc> <> i mean, a bit horrid, maybe you could use or something to really tidy it up, but as a concept it's pretty neat..
<re_irc> <> Yep
<re_irc> <> In my case it was a bootloader, which had functions that were callable (size optimization)
<re_irc> <> I used a Makefile, had to call strip objcopy etc...
<re_irc> <> To be honest, the array was probably unnecessary in the end. Could have concated the binaries together.
<re_irc> <> how did you deal with position-independent code/relocations? did the blob just get compiled for a fixed known start address and that's the section you put the static array into?
<re_irc> <> I started on something similar by stripping riscv-rt into "module-rt" that does nothing but basic entrypoint stuff. Idea is pretty much same to what ruabmbua is doing AFAICS. Load the binary to a predefined location and jump to it. TockOS does things exactly this way in an established way tho, sadly they don't use embedded-hal for drivers
<re_irc> <> adamgreig: Fixed address.
<re_irc> <> I tried with relocatable code in my os kernel, but that failed in the end with rust bugs (core::fmt) generated completely wrong code for some reason
<re_irc> <> yea, llvm support for PIC on armv7 is incomplete and a bunch of things just don't work
<re_irc> <> vtables especially?
<re_irc> <> Was actually riscv
<re_irc> <> I can't remember, but every time I called a fmt macro, it would crash
<re_irc> <> yea, similar problem atm I think
<re_irc> <> hm
<re_irc> <> ARM has both the "normal" PIC and the "freestanding" ROPI/RWPI PIC
<re_irc> <> "normal" pic should work, but only with a dynamic loader to do the relocation fixups and stuff
<re_irc> <> while ROPI/RWPI shouldn't need it but is incomplete
<re_irc> <> does riscv have an equivalent of that?
<re_irc> <> I think it just has "normal" pic (?)
<re_irc> <> the r-v link ^ is about designing a spec like ropi/rwpi for risc-v
<re_irc> <> ropi/rwpi being an llvm/keil invention for arm specifically
<re_irc> <> (and in current llvm doesn't support c++ because it doesn't support vtables, but in armclang it does due to extra patches not merged upstream)
<re_irc> <> I did eventually do manual relocation ^^
<re_irc> <> adamgreig: woot, link?
<re_irc> <> ah interesting, with a custom loader?
<re_irc> <> ooh that's cool! /me reads
<re_irc> <> it's not been updated since early 2020 though
<re_irc> <> adamgreig: No custom format, just elf
<re_irc> <> an elf loader in your firmware?
<re_irc> <> or a desktop tool to relocate to a new .bin?
<re_irc> <> I was thinking about doing the same with elf, but it seemed cheaper to do elf -> bin + some metadata (e.g. data start, bss size) and load from that
<re_irc> <> Yes, that would maybe be a better idea.
<re_irc> <> I want to reduce the amount of assembly used to 0
<re_irc> <> If anyone has a good idea tell me 😅
<re_irc> <> i was aiming for just something that hopefully objcopy + awk or such could do :D
<re_irc> <> objcopy -> bin and objdump -> awk the metadata and store that as some bin header
<re_irc> <> thing is tho, the e310 core has such small RAM I didn't try to go any further
<re_irc> <> what are your use cases? dynamically flashable modules, a/b partition firmware updates?
<re_irc> <> gameboy mini :D
<re_irc> <> i wanted to build something like with pluggable usb module setups
<re_irc> <> But you still need to patch a the address references in the binary, so a table of all of them is still required, unless you use something like ROPI/RWPI
<re_irc> <> yeah I never got anywhere near usable, then found out about TockOS and then decided its notwhere near feasible with 16k total RAM
<re_irc> <> adamgreig: Just a small part of a kernel, that is completely PIC, and relocates the rest to match the physical address.
<re_irc> <> Is partially obsolete, because I finally started with MMU based memory management, but that is far from done
<re_irc> <> cool!
<re_irc> <> fancy
<re_irc> <> I just want it for a/b partition firmware updates... so if I send a device a bad update it doesn't get bricked
<re_irc> <> the addresses of the two partitions are known though, so I could do the ultra-low-tech solution of just building the firmware twice lol
<re_irc> <> you can re-flash the flash from runtime no?
<re_irc> <> can you remap two flash banks?
<re_irc> <> nope, no flash mapping in nrf52 :(
<re_irc> <> ah shame
<re_irc> <> on the dual-bank stm32 you can just rotate the banks
<re_irc> <> almindor: yeah, but the issue is devices are completely unattended
<re_irc> <> so a solution like "when bricked, power up holding the BOOT button and then flash a new firmware with your phone via BLE" is not good
<re_irc> <> Are you still at hardware design phase? One approach I often take is "staging" the new firmware in an external EEPROM
<re_irc> <> Then validating it before doing the copy to flash
<re_irc> <> (Jumping in totally in the middle here, so I'm very lacking in context if this makes no sense)
<re_irc> <> I have enough internal flash for two copies and I do crc stuff before applying the update
<re_irc> <> so it's safe from corruption
<re_irc> <> Ah gotcha, that works equally well
<re_irc> <> the thing I'm scared of is a firmware update having a bug where the device can no longer connect to the server
<re_irc> <> or crashes on startup or whatever
<re_irc> <> like a smoltcp DHCP bug, lol
<re_irc> <> So your bootloader doesn't have the capability of communicating with the server? The app itself gets the new app and stages it, then has the bootloader do the copy?
<re_irc> <> Or do you not even have a formal bootloader?
<re_irc> <> the app gets the new firmware, yes. The bootloader is dumb, it just crc's and copies
<re_irc> <> pasting a whole copy of the entire protocol inside the bootloader was too big...
<re_irc> <> Gotcha. So the bootloader doesn't actually handle image acquisition
<re_irc> <> it can run over a custom BLE mesh or over ethernet or over mobile (AT/PPP), has crypto and stuff...
<re_irc> <> so it's too big :C
<re_irc> <> so ideally
<re_irc> <> Yeah, trust me I understand
<re_irc> <> how does it work out if the A firmware is bad and it should retry the B firmware?
<re_irc> <> as in, passes the CRC but has a latent bug
<re_irc> <> Ultimately, firmware can only do self detection of its own bugs imo, e.g. via watchdogs, self tests, etc.
<re_irc> <> And it could theoretically tell the bootloader" I'm having issues, give the other guy a shot"
<re_irc> <> ?
<re_irc> <> yea
<re_irc> <> If the firmware is a dud, I don't think you can do much
<re_irc> <> Maybe on first execution, have it explicitly say "Yes, I'm working"
<re_irc> <> I guess bootloader can at least start a watchdog that the main firmware only clears if it's happy or something
<re_irc> <> And if the BL comes back around and that wasn't indicated, fall back
<re_irc> <> yea, or even just bootloader sets a flag in ram
<re_irc> <> but eh, that won't help if the firmware gets stuck
<re_irc> <> Ideally a flag via some NVM
<re_irc> <> it'd work something like this
<re_irc> <> - bootloader sets up some watchdog "if not connected to the server in 10min, reboot"
<re_irc> <> - app on slot 1 downloads new firmware on slot 2
<re_irc> <> - app tells bootloader to boot slot 2 in "trial mode"
<re_irc> <> Yeah, but you also have to consider non-functional firmware in slot 2 locking up
<re_irc> <> So you need something like a hardware watchdog
<re_irc> <> Or if the user can power cycle, that works too
<re_irc> <> yeah the nrf has multiple hardware watchdogs
<re_irc> <> I have one to detect "firmware hanged"
<re_irc> <> I could use another to detect "firmware not hanged, but having trouble connecting to the server"
<re_irc> <> But yeah, the general outline you proposed is likely what I'd do
<re_irc> <> if something goes wrong and the bootloader sees a 2nd reboot while still in trial mode, it'd revert back to slot 1
<re_irc> <> Yeah then flag it as "Woops, that didn't work" and figure out what went wrong at a later date
<re_irc> <> mcuboot does kinda this
<re_irc> <> but SWAPPING the firmware images
<re_irc> <> with extra hoops to ensure it can recover if the swap is interrupted by a power cycle
<re_irc> <> it needs slot 1, slot 2 and a scratch partition to hold chunks while swapping and the "swap process"
<re_irc> <> with the advantage being no PIC needed?
<re_irc> <> yep... no pic and no "build firmware twice"
<re_irc> <> but does seem simpler to just build two images, one for each slot
<re_irc> <> image A is already asking the server for the new FW, shouldn't be hard for it to ask for A vs B firmware I guess
<re_irc> <> yeah... if I'm custom-rolling everything it's not that much extra effort :S
<re_irc> <> idk
<re_irc> <> it's all so cursed :D
<re_irc> <> for now I'm just yoloing it and praying for no bricks
<re_irc> <> do we have something like a generic SPI interface type in the e-h or something that's widely used? something like
<re_irc> <> right now it's very messy for the drivers wrt. working with CS pin in manual vs auto mode and "HW" vs "SW" control of it + framing
<re_irc> <> that was the motivation for the `ManagedCS` marker trait thing
<re_irc> <> but it's a bit stuck
<re_irc> <> so the issue imo is a bit bigger than that
<re_irc> <> there are I think 4 configurations that the drivers need to cope with somehow:
<re_irc> <> 1. managedCS with Transactional support (proper CS framing)
<re_irc> <> 2. unmanagedCS with Transactional support
<re_irc> <> 3. managedCS without Transactional support
<re_irc> <> 4. unmanagedCS without Transactional support
<re_irc> <> it's a big mess, because if a driver needs transactional (framing) it needs to handle possibly all 4 cases someho
<re_irc> <> I think the idea was that
<re_irc> <> if you're writing a driver for a device that requires a CS pin, you require `T: Transactional+ManagedCS`
<re_irc> <> yeah but that leaves out a lot of HALs right now :(
<re_irc> <> you don't accept Unmanaged CS at all
<re_irc> <> and only because of the abstraction, you can still make it work with non-transactional non-managed CS too
<re_irc> <> instead, the user must wrap their unmanaged SPI with something like `SpiWithCs` from that PR
<re_irc> <> it takes a `Transactional` and an `OutputPin` and gives you a `Transactional+ManagedCS`
<re_irc> <> is there any actual MCU that has a reason to not have `Transactional` ?
<re_irc> <> or the HAL can provide a Transactionsl+ManagedCS if there's a more efficient way of implementing it via hardware-managed CS or whatever
<re_irc> <> but the point is as a driver writer you don't care
<re_irc> <> you just require `T: Transactional+ManagedCS`
<re_irc> <> so you have the guarantee *something* is driving CS for you
<re_irc> <> almindor: you can always impl `Transactional` out of `Write + Transfer`, so it should be available everywher
<re_irc> <> ee
<re_irc> <> yeah the reality is I had to construct this wrapper myself (even if this trait existed) because a lot of xxx-hals don't have Transactional at all
<re_irc> <> e.g. gv32xx
<re_irc> <> you can always impl it with software
<re_irc> <> but some mcus can "chain DMAs" or whatever so you can do all the operations back-to-back without pauses which is neat
<re_irc> <> yes, what I'm saying is we shouldn't have spi::Write and spi::Transfer as mains anymore and IMO should in post 1.0 world force a single Transactional as minimum
<re_irc> <> hm
<re_irc> <> not sure
<re_irc> <> maybe a driver wants just `Transfer + ManagedCS` because all the transfers it does are just a single buffer
<re_irc> <> `Transactional` is quite overcomplicated
<re_irc> <> but the optimization opportunities from it are nice, and it fits nicely with ManagedCs
<re_irc> <> dunno
<re_irc> <> ok then Transactional wrapper that does all 3 in one trait
<re_irc> <> the driver can use singletons but the hals should be forced to have exec
<re_irc> <> IMO hals should just implement it
<re_irc> <> yeah but they don't :)
<re_irc> <> 💩
<re_irc> <> currently stuff is a bit stuck
<re_irc> <> because no HALs implement it, then driver authors work around the lack of it, which means no driver requires it, which means there's no demand for it in HALs
<re_irc> <> chicken-and-egg 🤣
<re_irc> <> example case: and the fix is easy and I'll probably do it but the issue is turnaround time for these can be pretty bug, easier to write a driver hack (also I burned my longan nano 😥)
<re_irc> <> in general I think we should consider adopting a "hal traits should be singletons" strategy as much as possible so that we don't fracture out own backends
<re_irc> <> by "singleton" you mean "a single trait with all the methods"?
<re_irc> <> to force HALs to implement all?
<re_irc> <> yes
<re_irc> <> yeah...
<re_irc> <> they can be compound of course but we should present a forced view for hal implementors
<re_irc> <> the reason they're split is HALs may want a "read-only SPI" or a "write-only SPI"
<re_irc> <> like, if you create an SPI with a MOSI pin but not MISO pin, the HAL could impl Write but not Read
<re_irc> <> that's ok but then make it a special case not the default. In this case it's "we have write and transfer but then there's also this new transactional kid on the block" and so any hals from older times won't have it
<re_irc> <> yeah..
<re_irc> <> damn.. :D
<re_irc> <> also IMO the SPIs should be implemented as Bus + Drivers instead of a single block SPI bus so they can be properly shared (and traited)
<re_irc> <> what if it was like this
<re_irc> <> that's an implementation detail tho
<re_irc> <> ```rust
<re_irc> <> fn read(&mut self, buf: &mut [u8]);
<re_irc> <> trait Read {
<re_irc> <> fn read_batch(&mut self, bufs: &mut [&mut [u8]]) {
<re_irc> <> then HALs would impl ReadWrite, and there would be *no room for missing stuff*
<re_irc> <> yes exactly
<re_irc> <> while still allowing readonly/writeonly
<re_irc> <> uart and i2c could use this treatment too...
<re_irc> <> it's quite a radical change though
<re_irc> <> what's `Operation` look like? could it just be `&[(&[u8], &mut [u8])]`?
<re_irc> <> or do you have an enum for inplace vs separate operations?
<re_irc> <> i think he meant the current e-h Operation enum
<re_irc> <> ah cool, yea
<re_irc> <> I like it. Might need some review w.r.t. DMA still.
<re_irc> <> guess you could have a method to do a single operation too
<re_irc> <> i gt. run but I'd really love if we could fix SPI up properly
<re_irc> <> there's also a problem of non-exposure when it comes to the configs, I made a comment at for that
<re_irc> <> wrt DMA it should be as good as the current traits
<re_irc> <> lol there's WriteIter too, what about that
<re_irc> <> WriteIter is imo a "nice to have" :D
<re_irc> <> but maybe one day someone would come and claim my own point against me hehe
<re_irc> <> it's impossible to impl with DMA though
<re_irc> <> not sure if it should be part of the monolithic ReadWrite triat
<re_irc> <> but again, if it's not then HALs don't implement it, then it's not useful for drivers
<re_irc> <> well.. couldn't the default implementation just for loop it?
<re_irc> <> hmm maybe yeah
<re_irc> <> it's sloooooooow though on DMA impls because you esentially have to do N times 1-byte DMA transfers which are slow to start/stop
<re_irc> <> in nrf's you *must* use DMA, there's no "DR" like in stm32s where you can write bytes
<re_irc> <> yeah it's a pickle, that's why I think making that one optional would work
<re_irc> <> it's such a PITA that Rust doesn't have !Trait support
<re_irc> <> to auto-impl it only when the HAL doesn't already impl it?
<re_irc> <> if there was a ! I could do both sides of the thing with no need for manual wrapper typing by the users
<re_irc> <> yea... that'd be the same as a default trait method though, right?
<re_irc> <> yes in this case, you mean for the "non transactional" side
<re_irc> <> yeah
<re_irc> <> the bare minimum HALs would have to impl is: read, write, transfer, transfer_implace
<re_irc> <> but if they have more efficient ways of impling batching (such as chaining DMAs) then they can override the default impl of the batch methods
<re_irc> <> and writeiter as an optional extra?
<re_irc> <> having it extra makes it useless in practice because HALs wont impl it
<re_irc> <> so I guess make it another default trait method
<re_irc> <> or remove it, idk
<re_irc> <> hmm how about making it default with a "optimized" marker
<re_irc> <> so that you can check if using iter would be considered a happy path
<re_irc> <> hmm but drivers won't bound on the "optimized" marker, as they want their driver to work everyhere even if slow
<re_irc> <> true
<re_irc> <> runtime check? :D
<re_irc> <> and panic if it's slow? same issue :D
<re_irc> <> if spi.iter_optimized() { spi.write_iter(...) } else { spi.batch } :D
<re_irc> <> uuh
<re_irc> <> seems cursed
<re_irc> <> that was a joke, to make things completely clear
<re_irc> <> ah okay 🤣
<re_irc> <> usefulness of iter is mainly for memory reasons I guess
<re_irc> <> Hey folks, I'm an electronics engineer with a bit of embedded C experience to support a firmware engineer. I'm really interested in embedded Rust, and I'm making my way through as well as the main language book. In y'all's opinion, is the embedded Rust job market still pretty sparse for relatively inexperienced people like me to make a career change?
<re_irc> <> Any pointers on how I can level up enough to give myself a better shot at making that jump?
<re_irc> <> When we hire Rust engineers they have 9 Rust experience (generally C embedded devs) and we help them for 1-2 months to learn Rust :)
<re_irc> <> I think many more have the same approach as finding Rust embedded devs is asking a lot
<re_irc> <> Plus I see you're maybe Swedish
<re_irc> <> Come to Luleå ett have 3 companies in the same building hunting Rust embedded devs :)
<re_irc> <> I'm not in any way swedish, unfortunately 😛
<re_irc> <> Aww, well it's never too late to become one ;)
<re_irc> <> But anyways, don't be afraid to hunt Rust jobs
<re_irc> <> Well, if it gives me a better shot at becoming and embedded Rust dev...
<re_irc> <> We have successfully converted 3 C devs :)
<re_irc> <> As long as there is a person that can mentor we have seen the people get into Rust fast
<re_irc> <> But if you have questions feel free to ping
<re_irc> <> honestly faster than new embedded engineers with C I think
<re_irc> <> or maybe slower but better?
<re_irc> <> faster and better :P
<re_irc> <> Yeah
<re_irc> <> The speed at which we have been able to build our system is awesome
<re_irc> <> Hack without fear
<re_irc> <> That is the amazing thing
<re_irc> <> And when crap really breaks I get to step in :D
<re_irc> <> Suddenly wanting to become swedish rn
<re_irc> <> Now I'm mostly a backend person ;P
<re_irc> <> Rust is awesome
<re_irc> <> Do it! In our company we are 15% foreign
<re_irc> <> before rust, with C, almost all my bugs were memory management/corruption bugs
<re_irc> <> The consultancy next to us are like 20 rust embedded people now
<re_irc> <> with Rust these are poof, gone. Bugs are now usually logic bugs, and rust helps a lot with even these with the decent type system
<re_irc> <> They are beginning the university :P
<re_irc> <> I'm mostly amazed Scott the boundaries that don't exist anymore
<re_irc> <> We move data over 4 different CPU architectures with s single library in the end
<re_irc> <> From embedded to backend
<re_irc> <> And it's not even hard :D
fabic has quit [Ping timeout: 252 seconds]
<re_irc> <> (thank you serde)
<re_irc> <> Yeah, I’m trying to teach some other students embedded software for rocketry stuff and I think it’d be a lost cause without rust
<re_irc> <> (Lost cause in the time we have, there’s so much context one needs to know to even use C in this kind is system)
tokomak has quit [Ping timeout: 265 seconds]
<re_irc> <> Re: MAC adresses. I'm sure there are regulations which require that a vendor guarantees that the burned-in MAC address of any shipped networking interface is worldwide unique. Newer Apple and Android devices are using randomly generated locally administered MAC addresses only for network scanning to not disclose their real identity and allow worldwide tracing of devices. For communication they're using...
<re_irc> ... their built-in MAC addresses. Whenever you're using locally administered addresses you're supposed to do duplicate address detection (DAD) and if you detect a conflict you have to either chose a different address or stop communicating.
<re_irc> <> from android 10 onwards, they totally do use random LA MAC addresses for communication on wifi,
<re_irc> <> (in addition to probing)
<re_irc> <> they persist the same random MAC address for the same SSID, but it's random for each SSID
<re_irc> <> iOS14 onwards does the same thing too,
<re_irc> <> Interesting.
<re_irc> <> in both cases enabled by default
<re_irc> <> though I couldn't find the part of AOSP that actually generates the random MAC, so I'm not sure if it's deterministic given the real MAC and the SSID (for example) or totally random but persisted in memory
<re_irc> <> either way, it's unpredictable and has the LA bit set
<re_irc> <> I think they also use the google OUI in android?
<re_irc> <> Hm, I just checked and Apple devices are definitely not the Apple OUI.
<re_irc> <> adamgreig: I'm convinced IEEE doesn't hand out OUIs where the LA bit is set.
<re_irc> <> oh, sorry, I didn't mean to imply that at all
<re_irc> <> they surely do not
<re_irc> <> but one could still set the LA bit and otherwise use their own OUI while generating a random LA address, right?
<re_irc> <> adamgreig: But how could they use the Google OUI then? 😉
<re_irc> <> adamgreig: Hm, maybe.
<re_irc> <> Hey guys,
<re_irc> <> Is there a way to get a 3V output from one pin to toggle on the stm32f4?
<re_irc> <> Now i only measure 0.6 when i set a pin high
<re_irc> <> Apple doesn't seem to do that.
<re_irc> <> do you see any toggling, or do you just measure constant 0.6?
<re_irc> <> Toggling, but I set it to high to measure
<re_irc> <> could the pin have been configured in "open drain" mode in your firmware, instead of "push pull"?
<re_irc> <> It's enough for a LED but not for what I need
<re_irc> <> and, is the pin connected to anything else when you measure it?
<re_irc> <> If you're still open to feedback, I would prefer to see the HAL-utilizing section appear before the raw register manipulations / PAC level code.
<re_irc> <> As a user who doesn't know rust and its ecosystem, and potentially not a whole lot more than Arduino, seeing the register manipulations may scare them off without reading further. IMHO its more important to present how to use Rust in embedded before explaining how it works
<re_irc> <> It is connected to something else, I measure directly on the pins, it is set to pusher pull
<re_irc> <> Into push pull output
<re_irc> <> what is it connected to? the stm32 itself can only drive to its supply voltage (3.3V probably), there's no setting to drive to 0.6, so either it's not actually driving it to 3.3 at all (which would be the case in 'open drain') or something else in the circuit is pulling the voltage down
<re_irc> <> you could try toggling a different pin that's not connected to anything, and see if that reads 3.3V
<re_irc> <> It's connected to a vibration motor
<re_irc> <> I also use ADC on a another pin
<re_irc> <> When I disconnect everything I get 3.3V
<re_irc> <> do you have a part number or anything for the motor?
<re_irc> <> Just salvaged it from a phone
<re_irc> <> maybe it needs more current than the stm32 can deliver, so it pulls the voltage down
<re_irc> <> Oh ok
<re_irc> <> usually for driving a motor you would need some kind of external switch, like a MOSFET or similar, and the stm32 turns that on, and the switch connects power to the motor
<re_irc> <> Thanks, will try that!
<re_irc> <> Directly from the 3.3V pin it works but then I can't toggle
<re_irc> <> Will get a mosfet then
<re_irc> <> Thanks a lot!
<re_irc> <> if you have any transistors lying around that's the thing to try. there's a beginner's guide if that's helpful for you
<re_irc> <> (using an arduino, but you'd only need to look at the circuit)
<re_irc> <> I have transistors, will try
<re_irc> <> Thank you!
<re_irc> <> np!
<cr1901> This is hypothetical: Is it possible in Rust currently to make a library crate such that if you import it into an application, you MUST use a specific function, or your application will fail to compile or link?
<cr1901> Hypothetical use case: library crate that comes w/ an interrupt handler function that you must put into an interrupt handler
<re_irc> <> Should be doable with macros
<re_irc> <> adamgreig: Got it to work!
<re_irc> <> Embassy does something similar
<re_irc> <> You would have to declare and use some global symbol in the library that the application has to define, which can be done with a macro.
<cr1901> embassy was a potential use case too, happy to look at what they do for inspiration
<re_irc> <> Hi, I see that HALs have pins individually typed, like `GPIO::P0::P0_13`
<re_irc> <> How can I write pin independent functions:
<re_irc> <> Mehmet Ali: nrf-hal has .degrade() that gives you instances of `Pin`
<re_irc> <> You use the embedded-hal trait `OutputPin` for example (or Input)
<re_irc> <> So e.g. `impl<PIN> ... where PIN: OutputPin` and then you can do `pin.set_high()` etc.
<re_irc> <> quick overview of how embassy does it:
<re_irc> <> 1. registers the interrupt handler to some embassy-internal handler function
<re_irc> <> 2. checks whether it has been run before with a static bool, panics if it has (similar to `pac::peripherals::take()`)
<re_irc> <> it has a macro `interrupt::take!(USART1)` which:
<re_irc> <> Does that degrade the pin from, being singleton?
<re_irc> <> That's a great point I didn't consider. I'm going to think about this, then make the change if it seems like it's worth the swap. Will add some clarification either way, or a note to skip that section as required. I don't think the direct memory manipulation is a good API for application code, but I wanted to open with that before pulling in dependencies
<re_irc> <> (I think PAC use can be suitable for application-level code in some cases, but not others. For example, I'd be happy writing an entire nRF-52 program using just PAC, but would never do that for STM32)
<re_irc> <> `Pin` instances are still singletons, you can't clone them either. You can't get two `Pin` instances for the same pin. It just makes them into the same type, so you can put them in arrays, or write functions that take any pin, etc
<re_irc> <> I guess my thought process was: "Here's where the magic happens - these `read_volatile` and `write_volatile` commands. This is where you go from abstract computer logic to making things happen! This took me a surprisingly long amount of time to GROK, and I acccepted it as magic. The PAC and HALs are still doing these commands, but with a nicer API
<re_irc> <> yea, I quite like your current sequence of the most basic thing first and then the abstractions
<re_irc> <> but a well-highlighted note to skip to the abstractions might be good... i'm probably not the target audience
<re_irc> <> (also I love just writing the whole application using only the pac on stm32, so I'm definitely an outlier :P)
<re_irc> <> My comment is from the perspective of a relative newbie; and the fustrations I had with how the embeded-rust book was written at the time (may still be? haven't checked in on that recently).
<re_irc> <> As a beginner, i don't want to know what the magic is, i want to know what the "best" / "easiest" way is. Once i have a solid launching point (Writing against a HAL), I have somewhere to rest at so i don't drown deep down the rabbit hole
<re_irc> <> Its very easy to get lost in PAC and below if you don't already know how it all works.
<re_irc> <> I added a scary bold warning note to skip ahead before going into the direct register edit code
<re_irc> <> The "embedded rust learning experience" would perhaps be better served by some noob-friendly stuff in a place like instructables too
<cr1901> dirbaio: using a singleton at runtime wasn't exactly what I had in mind, but even for the smallest targets RAM isn't the limiting factor, so that'll do
<re_irc> <> That is likely enough (waiting on deployment), giving the reader the indication things get better later on is good enough :)
<re_irc> <> Would also help if hal's had like a showcase" section or something for guidance
<re_irc> <> What i found the most useful when i started out was existing codebases honestly
<re_irc> <> I appreciate the feedback
<re_irc> <> i found so little value in the books
<re_irc> <> (sorry if this is coming off bluntly)
<re_irc> <> yeah unfortunately it's not fully zero-cost. I'm not 100% happy with it either, will probably try alternatives in the future
<cr1901> dirbaio: Are the interrupt owned singletons !Send as well as !Sync?
<re_irc> <> They're Send+Sync, but not Copy/Clone
<cr1901> Oh, that works too lol
<re_irc> <> I found the book good for initial reference, but examples + embedded hal docs were like the ones that carried me the most
<re_irc> <> I think part of the reason for the confusion is this article doesn't have great scope control; ie it tries to provide info to people with varying levels of experience in embedded and Rust. Ie, I think the current order makes more sense for someone used to embedded, but not Rust, since they can map the code to the most general way of looking at it
<re_irc> <> yeah, your current article reads as if its target audience is seasoned embedded-C programmers
<re_irc> <> It also demystifies what PAC and HAL are doing. (Going to make another edit clarifying this, that PAC/HAL are really just wrapping these writes
<re_irc> <> But its ALMOST scoped right for newbies too
<re_irc> <> And HAL may just wrap the PAC
<cr1901> dirbaio: I was recently mulling over how to create a "very smol fixed hashmap", and "make it use a 'static buffer, but don't make it Copy/Clone" was one method I considered
<re_irc> <> its wrapping the PAC and implementing device-specific sequences
<cr1901> It seems like an effective strategy for "free Send/Sync" lmao
<re_irc> <> heapless::IndexMap?
<cr1901> Sure, but I wanted to do my own for fun as a mental exercise
<cr1901> and I wanted a `static buffer (unless heapless::IndexMap does that already)
<re_irc> <> I feel that the book is like ok, perhaps just a page of guidance of where to look further would be nice
<cr1901> (fun not guaranteed)
<re_irc> <> `&'static mut IndexMap` :P
<cr1901> Also one of the strategies I mulled over
<cr1901> :P
<cr1901> (I wanted to create multiple impls and have them "duke it out" in benchmarks to see memory usage and speed on a slow micro or simulation. But of course that takes work)
<re_irc> <> Would help if it provided sections for different boards other than the f3 tho. F4's and F1's are the easier to get boards. F4's specially because even if you lack the st link, you can still load binaries via dfu
<re_irc> <> I believe there was a lot of discussion in the embedded book's gh about the availability of various MCUs.
hifi has quit [Ping timeout: 252 seconds]
hifi has joined #rust-embedded
<re_irc> <> how do you guys "provide" a println! to drivers when needing to debug internal stuff?
<re_irc> <> `log` and `defmt` Cargo features, plus [cursed macros](
<re_irc> <> so from inside the crate you can do `info!("test {}", 42);`, and the user can choose whether that goes to `log`, `defmt`, or nowhere
<re_irc> <> I just use
SomeWeirdAnon has joined #rust-embedded
crabbedhaloablut has quit [Remote host closed the connection]
crabbedhaloablut has joined #rust-embedded
crabbedhaloablut has quit [Ping timeout: 276 seconds]
<re_irc> <> for my own applications, i also use rtt-target; quick and simple.
<re_irc> <> for more complicated things i have been convinced to set up defmt but its a handful.
<Lumpio-> Wonder if I should add built-in support for "log" in rtt-target
<re_irc> <> It would be nice to have log levels in rtt-target
<Lumpio-> In theory it's kind of built-in to RTT, as long as you don't want to turn them on/off
<Lumpio-> You can like rprintln!(=> 1, "hi"); to print to different "virtual terminals" but the filtering is all on the host side
crabbedhaloablut has joined #rust-embedded
<re_irc> <> you know, i completely forgot that rtt-target had that feature.
<re_irc> <> and i recently had to poke my head into the init macros since i needed to increase the size of the ringbufer
<re_irc> <> RTT was silently dropping log messages :(
edm is now known as teslahyp
teslahyp has quit [Quit: Updating details, brb]
teslahyp has joined #rust-embedded
<re_irc> <> [defmt](
teslahyp is now known as bpm_bored
bpm_bored is now known as npm_bored
emerent_ has joined #rust-embedded
emerent_ is now known as emerent
emerent is now known as Guest6151
Guest6151 has quit [Ping timeout: 264 seconds]