_whitelogger has joined ##stm32-rs
<TimSmall> peauters: Pretty sure someone posted some example SPI DMA (or maybe PWM DMA) code for related LEDs on stm32f4xx on here in the past. Maybe search for some LED part numbers in the history of this room.
<peauters[m]> thanks, will do
<theJPster> Morning all. Are there any examples for getting PWM out of a timer channel?
wyre has left ##stm32-rs ["WeeChat 3.1"]
<henrik_alser[m]> <theJPster "Morning all. Are there any examp"> Do you mean like outputting pwm on a pin at a specific freq and duty cycle? On a hal or pac level? What family of devices?
<theJPster> STM32F767. I want a periodic waveform out of a timer pin, and an interrupt once per cycle
<theJPster> There seems to be PWM examples in the F3 codebase, but not the F7
<theJPster> and I'm really struggling with the svd2rust output as it appears utterly impenetrable
<theJPster> Much worse that I've seen with the nRF9160
<theJPster> or the TM4C
<theJPster> Like TIM2 (https://docs.rs/stm32f7xx-hal/0.3.0/stm32f7xx_hal/pac/struct.TIM2.html) has a Status Register field. I can find that by going into RegisterBlock.
<theJPster> But every field in the Register Block is of type "Reg" and I can't work out how to see the fields I can get/set for any given Reg. I just get the generic read/write API documentation.
<dirbaio[m]> TIM2 derefs to tim2::RegisterBlock
<dirbaio[m]> no idea why rustdoc shows methods from the deref target but not fields 🤷‍♂️
<theJPster> "Reg" is useless, and "_SR" is not a hyperlink
<dirbaio[m]> yep the rustdoc output of svd2rust crates is abominable
<henrik_alser[m]> Seems the pwm functionality is yet to be implemented in the f7xx hal
<dirbaio[m]> you're better off reading the RM
<dirbaio[m]> or discovering stuff through rust-analyzer autocomplete :S
<henrik_alser[m]> Haha yes it’s a pain to navigate
<theJPster> Am attempting to read the RM. Have VS Code open but it doesn't seem to be autocompleting very much.
<henrik_alser[m]> Are you in a proc macro?
<firefrommoonligh> RM will have explicit steps for PWM, and its' mostly the same across families
<henrik_alser[m]> Yes you could probably copy paste most stuff from the f4xx hal
<theJPster> I feel like there should be an answer that isn't copy-paste though.
<firefrommoonligh> Ther'es a lot of interesting / advanced PWM settings btw
<firefrommoonligh> What you're probably looking for as a nice default is edge-aligned, upcounting mode, and not using asymmetric/combined etc
<dirbaio[m]> <theJPster "I feel like there should be an a"> aka a hal for all stm32 families... sounds vaguely familiar :
<dirbaio[m]> > <@thejpster:matrix.org> I feel like there should be an answer that isn't copy-paste though.
<dirbaio[m]> * aka a hal for all stm32 families... sounds vaguely familiar :D
<firefrommoonligh> Or perhaps a PAC for all
<dirbaio[m]> yeah, wouldn't that be cool?
<theJPster> That's where I got to. The output looks OK, but I don't seem to be interrupting at the rate I expect.
<henrik_alser[m]> (Just meant if you were to PR something similar into the f7xx hal it could be a starting point)
<theJPster> Also, if I want to clear an interrupt flag, am I writing a 1 or a 0 to the bit to clear it?
<theJPster> Oh no ... "Software can read as well as clear this bit by writing 0. Writing 1 has no effect on the bit value"
<theJPster> You write a /zero/ to clear it?
<theJPster> What on earth are they doing over in France.
<henrik_alser[m]> Haha! What problem were you facing rate-wise?
<theJPster> I seem to be getting 500,000 interrupts per second and I only expect 250,000
<henrik_alser[m]> If the interrupt is triggering on the update event i guess it will update twice per period in pwm mode
<henrik_alser[m]> Do you want it to trip on the reload or the compare event?
<theJPster> On the compare event
<theJPster> I've worked around it by checking that the CC1IF bit is set before doing the work
<theJPster> But I'd like it to not interrupt in the update.
<theJPster> I also think there's an off-by-one on the period setting. I asked for 250 kHz and I'm getting 249.421 kHz
<henrik_alser[m]> I guess if you remove your `latch_timer.listen(hal::timer::Event::TimeOut);`
<henrik_alser[m]> I think it checks UIE
<theJPster> Ah, yes I took that out alreadyu
<henrik_alser[m]> Ahh ok
<theJPster> I did try and take out all the HAL code and paste it into my app, but the RCC fields used in tim2() are not public.
<theJPster> Hence why I had to make the timer object and then immediately destroy it.
<henrik_alser[m]> Or you could use unsafe pointer access ☠️
<theJPster> It feels like the STM32 HAL is all or nothing
<theJPster> You're either using the HAL, and you don't mind some bits of the chip are hidden from you, or you use the PAC directly.
<theJPster> Trying to do both is ... messy
<firefrommoonligh> That clear process is annoying; most periphs it's a set bit to clear
<henrik_alser[m]> <theJPster "Trying to do both is ... messy"> `unsafe { (*TIM2::ptr()).foo.modify(|_, w| w.bar().set_bit())}` but yeah, i feel your pain hehe
<theJPster> Specifically my issue was with the RCC code
<theJPster> `apb.enr().modify(|_, w| w.$timXen().set_bit());`
<theJPster> if you substitute in the appropriate values of $timXen, it says "enr() is not public"
<firefrommoonligh> Fork the HAL
<firefrommoonligh> And ideally, PR
<dirbaio[m]> you can definitely write to RCC apbenr with the PAC public API
<theJPster> But my RCC has been constrained
<henrik_alser[m]> Yes but by the method above
<dirbaio[m]> `unsafe { (*pac::RCC::ptr()).apbenr.blahblah`
<dirbaio[m]> yolo
<dirbaio[m]> steal everything
<firefrommoonligh> Your 2 main options are #1: Use raw pointers, and #2: Fork the HAL to either not consume RCC, or to add the functionality you need with it constrained. #1 is probably easiest
<henrik_alser[m]> * `unsafe {(*RCC::ptr()).apb1enr.modify(|_, w| w.tim2en().set_bit());}`
<firefrommoonligh> Ie what henrik_alser posted
<firefrommoonligh> And dirbaio posted
<henrik_alser[m]> Depending on what the constrain() does, you can sometimes get away with doing your stuff on RCC before the constrain() call
<theJPster> `self.tim.dier.write(|w| w.uie().clear_bit());`
<theJPster> Shouldn't that be modify?
<theJPster> I thought `write()` set `w` to the reset value, whilst `modify()` read the current value.
<henrik_alser[m]> It does, so it will reset any other interrupt sources that way...
<henrik_alser[m]> But since that's the only one provided as is, i guess the author didn't care?
<henrik_alser[m]> So does it work better with `cc1ie` than `uie`?
<theJPster> I seem to have it in a state where it's interrupting at the correct rate using cc1ie
<theJPster> I'm not entirely sure what i did
<henrik_alser[m]> You removed the hal's listen function and enabled dier cc1ie manually?
<theJPster> Yeah, but I'd done that already.
<henrik_alser[m]> Ahh
<theJPster> I'm happy - it works
<theJPster> What's the easiest way of checking the reset value used in a write call?
<theJPster> Ah, have found the PAC source
<theJPster> So those rcw0 fields are going to be a right pain
<theJPster> I think you have to w.bits(0xFFFF_FFFF).your_field().clear_bit()
<henrik_alser[m]> What do you mean for example?
<theJPster> If you want to clear a status bit, and you do a `write(|w| w.your_field().clear_bit() )` you will clear all the status bits
<theJPster> `write` will load the 'reset value', which is zero, give it to you as w. You then clear a bit (which is already cleared) and write 0 to the register, clearing all the bits.
<theJPster> I had /assumed/ (wrongly) that write would default the value of `w` to be 0xFFFF_FFFF, because that is the no-op.
<theJPster> I guess there is a difference between "what value would cause the least changes here / be a no-op" and "what value does this register have if you read it at boot-up"
<therealprof[m]> Yeah, I also wouldn't rely on the SVD files being correct.
<firefrommoonligh> [Updated the L41x / L42x RTC issue with the reg layouts, verified working on hardware for wakeup and time-keeping functionality.](https://github.com/stm32-rs/stm32-rs/issues/555)
<firefrommoonligh> Yep... The changes I made are almost identical to the newer variants
<firefrommoonligh> * Confirmed... The changes I made are identical to L5 and G.
<firefrommoonligh> dirbaio: Perhaps this is relevant on your spreadsheet. Ie maybe L41x and L42x could be marked v3 RTC. L5 could probably be marked that as well
<firefrommoonligh> (L5 is p much the same plus a few security features)
<firefrommoonligh> (which are marked as reserved on L41x/42x and G
<firefrommoonligh> * (L5 is p much the same plus 2 security regs)
<firefrommoonligh> * (which are marked as reserved on L41x/42x and G)
<dirbaio[m]> noted
<dirbaio[m]> L4+ is always v2?
<firefrommoonligh> I don't know anything about L4+
<firefrommoonligh> L412 and L422 are V3 (ie are teh same as L5, G0 and G4), and L43 and higher are V2
<firefrommoonligh> I'm still not up to fixing the SVDs, and have modded the nightlies for my purposes
<firefrommoonligh> * L41x and L42x are V3 (ie are teh same as L5, G0 and G4), and L43 and higher are V2
<firefrommoonligh> The reason it's not a quick fix is SVD and PAC makes the distinctions on the 3rd digit, while this is on the second
<dirbaio[m]> yeah. it'd need whole new feature names
<firefrommoonligh> Or twin RTC modules selectable by the user
<firefrommoonligh> I can't think of a good solution
<dirbaio[m]> noo that's a nasty footgun
<firefrommoonligh> Doubling the number of modules for one peripheral seems excessive, although is the "safest" solution in some ways
<firefrommoonligh> Sure, but I don't know tfi the alternatives are better
<dirbaio[m]> I think the only reliable way in the end is to have one Cargo feature per ST SKU 🤣
<dirbaio[m]> that's what the metapac does
<dirbaio[m]> ohterwise you get surprises like this
<firefrommoonligh> We're dealing with a categorization issue: Ie what categorization scheme makes the most sense. Too coarse won't provide the right functionality, and too fine is unmaintainable
<firefrommoonligh> Current L4 breakdown (Not sure how L4+ fits in): L4x1, L4x2, L4x3, L4x5, L4x6. We could do, L411, L412, L413, L415, L416, and L431, L432, L433, L435, L436, but you're doubling the module count for 1 peripheral. Not saying I disagree or it's wrong, but that's the downside
<dirbaio[m]> <firefrommoonligh "We're dealing with a categorizat"> not unmaintainable if it's generated! :D
<dirbaio[m]> Python scripts don't get tired
<firefrommoonligh> I wasn't even trying to find an edge case or make the most general solution; I ran into this when switching MCU due to a stock issue
<firefrommoonligh> Touche
<firefrommoonligh> From my engineering / launching-a-product perspective, the solution was easy - just patch the `rtc.rs` file in the nighly, and add a dummy file for a missing reg I use, and only add the fields I need. Problem solved, product can launch. The related issue is how do we prevent this going forward
<firefrommoonligh> (after you and adamgreig showed me how to do that)
<dirbaio[m]> so yea it would have caught that they're different
<dirbaio[m]> but I don't see any correlation between version number and "old vs new" register layout 🤣
<firefrommoonligh> No idea - All I got is that L5, G0, G4, and L41[2]x reg layouts are similar/identical (L5 has 2 extra regs), and these are incompat with the other L4s
<dirbaio[m]> so it seems rtc3=new
<dirbaio[m]> with the exception of L5 🤷‍♂️
<firefrommoonligh> looks like it!
<firefrommoonligh> The other "v3" ones have reserved blocks to accomodate L5, so weird it's on a diff #
<firefrommoonligh> ie accomdate m33 stuf
<firefrommoonligh> * ie accommodate m33 stuff
<dirbaio[m]> who knows lol
<dirbaio[m]> metapac treats these versions as "opaque" strings anyway
<dirbaio[m]> manually mapping to the versions from the chibios table
<dirbaio[m]> different versions in same family -> suspicious, check RMs
<firefrommoonligh> It sounds like you're able to split in a very fine way. When do you expect metapac to be usable broadly?
<firefrommoonligh> Yea - I found out the hard way when trying to find out why my RTC doesn't work "I can't have soldered something wrong since it's internal!!"
<dirbaio[m]> maybe in a few months.. it's super WIP
<firefrommoonligh> Sweet. Looking fwd to seeing it
<firefrommoonligh> Could mean a reduction in issues like this
<dirbaio[m]> there's still room for human error though 🤣
<dirbaio[m]> mapping these versions to v2/v3 is manual, a human could've gone and said "the SVDs say L4 is always v2"
<dirbaio[m]> but at least fixing that would've been easy since chips aren't grouped
<dirbaio[m]> the groupings in the SVDs come from ST
<firefrommoonligh> Hopefully we crush things like this as they come up
<dirbaio[m]> so it's ST's fault there lol
<firefrommoonligh> Yea - hopefully the permanent solution with meta-pac will be as easy as my bandaid here
<firefrommoonligh> If I'd realized it was a future periph, would have been even easier by copy+pasting
<firefrommoonligh> as adamgreig suggested IIRC