1457: TL Mbox read and write for stm32wb r=xoviat a=OueslatiGhaith
Hello,
This pull request is related to #1397 and #1401, inspired by #24, built upon the work done in #1405 and #1424, and was tested on an stm32wb55rg.
This pull request aims to add read and write functionality to the TL mailbox for stm32wb microcontrollers
Co-authored-by: goueslati <ghaith.oueslati@habemus.com>
Co-authored-by: xoviat <xoviat@users.noreply.github.com>
1454: stm32f0 flash implementation r=Dirbaio a=jp99
i've copied and modified the f3 implementation and it seems to be working.
Co-authored-by: Jaap Prickartz <jaap@tetra.nl>
Clear and report the error flags one by one and pop the data byte only
after all error flags were handled.
For v1/v2 we emulate the v3/v4 behaviour by buffering the status
register because a read to the data register clears all flags at once
which means we might loose all but the first error.
1424: add TL maibox for stm32wb r=xoviat a=OueslatiGhaith
Hello,
This pull request is related to #1397 and #1401, inspired by #24, build upon the work done in #1405, and was tested on an stm32wb55rg.
This pull request aims to add the transport layer mailbox for stm32wb microcontrollers. For now it's only capable of initializing it and getting the firmware information
Co-authored-by: goueslati <ghaith.oueslati@habemus.com>
Co-authored-by: Ghaith Oueslati <73850124+OueslatiGhaith@users.noreply.github.com>
Co-authored-by: xoviat <xoviat@users.noreply.github.com>
This flag for example permits the following clock tree
configuration on stm32f103r8
let mut config = Config::default();
config.rcc.hse = Some(Hertz(16_000_000));
config.rcc.sys_ck = Some(Hertz(72_000_000));
config.rcc.pclk1 = Some(Hertz(36_000_000));
config.rcc.pclk2 = Some(Hertz(72_000_000));
config.rcc.pllxtpre = true;
Init fails if pllxtpre is false.
1376: rtc: cleanup and consolidate r=Dirbaio a=xoviat
This removes an extra file that I left in, adds an example, and consolidates the files into one 'v2' file.
Co-authored-by: xoviat <xoviat@users.noreply.github.com>
1405: add IPCC peripheral for stm32wb r=xoviat a=OueslatiGhaith
Hello again,
This pull request is related to #1397 and #1401, inspired by #24, and was tested on an stm32wb55rg.
This pull request aims to add the IPCC peripheral for stm32wb microcontrollers.
I am debating whether this should be included in the public API, since the IPCC peripheral would be typically managed by the TL Mailbox, not by the app directly.
Co-authored-by: OueslatiGhaith <ghaith.oueslati@enis.tn>
1412: stm32/uart: abort on error r=Dirbaio a=xoviat
This PR aborts the DMA transfer in the event of a UART error. Otherwise, the transfer will never complete, and an error will not be returned.
Co-authored-by: xoviat <xoviat@users.noreply.github.com>
1370: stm32/i2c: fix races when using dma. r=Dirbaio a=xoviat
This change addresses two races:
1. It removes the `chunks_transferred` state variable that is modified inside the interrupt. Analysis of the code reveals that the only time the waker can be woken is when `chunks_transferred` is incremented. Therefore, waking is enough to signal the `poll_fn` that the `chunks_transferred` has incremented. Moving to `remaining_len` clarifies the code, since there is no need to track how many chunks are remaining.
2. It moves the start of the transfer until after the waker is registered, which could theoretically occur if the clock speed is very low, but probably never would even if this wasn't fixed.
There is another race that I noticed: between writes the waker may not yet be registered. In that case, the code would simply be stuck and the `poll_fn` would never be woken. There is no way to resolve this without broadening the scope of the analysis, and this will likely never occur.
Co-authored-by: xoviat <xoviat@users.noreply.github.com>
1371: RTC r=Dirbaio a=xoviat
This adds RTC for most of the stm32 chips. Nearly all of the work was not done by me, but I took it the last bit by disabling the chips that weren't working. I think it would be easier to enable them in future PRs if requested.
1374: stm32: remove TIMX singleton when used on timer driver r=Dirbaio a=xoviat
After multiple ways of looking at this, this is the best solution I could think of.
Co-authored-by: Mathias <mk@blackbird.online>
Co-authored-by: xoviat <xoviat@users.noreply.github.com>
1360: stm32/rcc: add i2s pll on some f4 micros r=Dirbaio a=xoviat
Adds the i2s pll on some f4 micros.
1361: Executor: Replace unnecessary atomics in runqueue r=Dirbaio a=GrantM11235
Only the head pointer needs to be atomic. The `RunQueueItem` pointers are only loaded and stored, and never concurrently
Co-authored-by: xoviat <xoviat@users.noreply.github.com>
Co-authored-by: Grant Miller <GrantM11235@gmail.com>
1330: stm32/pwm: add complementary pwm r=Dirbaio a=xoviat
This implements complementary PWM with dead time on many supported targets. The specific dead-time programming functions are passed through directly to the user, which is a bit ugly but the best compromise I could reach for now.
Co-authored-by: xoviat <xoviat@users.noreply.github.com>
1333: STM32: Adc V1 r=Dirbaio a=GrantM11235
Based on #947
Co-authored-by: Matthew W. Samsonoff <matt.samsonoff@gmail.com>
Co-authored-by: Grant Miller <GrantM11235@gmail.com>
The internal channels (vbat, vref, and temperature) are not real pins and do
not have the `set_as_analog` method. They must be read using the
`read_internal` method.
1313: (embassy-stm32): rework bufferedUart to get rid of PeripheralMutex r=Dirbaio a=MathiasKoch
New implementation is very similar to the implementation of embassy-nrf & embassy-rp.
Also adds embedded-hal traits to bufferedUart.
**NB**: Still needs testing on actual hardware
Co-authored-by: Mathias <mk@blackbird.online>
1294: Add support for `QSPI` in `stm32` r=Dirbaio a=Mirror0
Implemented with help of Tomasz Grześ <tomasz.grzes@gmail.com>.
Tested only on stm32f777zi.
Co-authored-by: Mateusz Butkiewicz <mateusz@github.butkiewicz.dev>
1228: stm32/sdmmc: Implement proper clock configuration r=chemicstry a=chemicstry
This implements proper clock configuration for sdmmc based on chip family, because `RccPeripheral::frequency()` is almost always incorrect. This can't be fixed in PAC, because sdmmc uses two clock domains, one for memory bus and one for sd card. `RccPeripheral::frequency()` usually returns the memory bus clock, but SDIO clock calculations need sd card domain clock. Moreover, chips have multiple clock source selection bits, which makes this even more complicated. I'm not sure if it's worth implementing all this logic in `RccPeripheral::frequency()` instead of cfg's in sdmmc.
Some chips (Lx, U5, H7) require RCC updates to expose required clocks. I didn't want to mash everything in a single PR so left a TODO comment. I also left a `T::frequency()` fallback, which seemed to work in H7 case even though the clock is most certainly incorrect.
In addition, added support for clock divider bypass for sdmmc_v1, which allows reaching a maximum clock of 48 MHz. The peripheral theoretically supports up to 50 MHz, but for that ST recommends setting pll48 frequency to 50 MHz 🤔
Co-authored-by: chemicstry <chemicstry@gmail.com>
1227: stm32/dma: fix spurious transfer complete interrupts r=Dirbaio a=pattop
DMA interrupts must be acknowledged by writing to the DMA_{L,H}IFCR
register.
Writing to the CR register is unnecessary as the channel (EN bit) is
disabled by hardware on completion of the transfer.
Co-authored-by: Patrick Oppenlander <patrick.oppenlander@gmail.com>
DMA interrupts must be acknowledged by writing to the DMA_{L,H}IFCR
register.
Writing to the CR register is unnecessary as the channel (EN bit) is
disabled by hardware on completion of the transfer.
1200: feat(stm32): Add 16 data bit fmc ctor r=Dirbaio a=rmja
This has been validated with the Is42s16400j sdram on stm32f429.
Co-authored-by: Rasmus Melchior Jacobsen <rmja@laesoe.org>
1199: STM32 SPI: Set clk-pin pull-up/-down to match spi clock polarity r=Dirbaio a=jr-oss
Fixes#1094
There are some proposed solutions in #1094
> Keep the DMA transaction open across calls to read/write
This may be problematic if the user changes bus settings between calls, and also the reference manual says the chip should not be placed into low power mode while SPI is enabled
As already described, this is problematic and against reference manual recommendation
> Set the CLK (and maybe MOSI) pins as pull-down on setup (or pull-up, depending on config - and this would need to be updated if the user modified the config)
This is less good than driving the pin to the correct value, but may be better than nothing
That is also my preferred solution. See below citation from reference manual.
> Document this and require users fix it themselves (add a pull-up/down resistor - or configure the pins as pull-up/pull-down before passing them into SPI setup)
Setting internal pull-up/-down won't work, because `sck.set_as_af()` will change the gpio pull mode to none: https://github.com/embassy-rs/embassy/blob/master/embassy-stm32/src/gpio.rs#L552-L555
> Dig around in the reference manual and determine if there is a better way to start/stop a DMA transaction while keeping active control of the clock the whole time
I haven't found a better way
------
From ST reference manual RM0394 (L4)
(Same note in RM0399 (H7) / RM0038 (L1) / RM0316 /F3)):
40.4.6
Communication formats
...
The idle state of SCK must correspond to the polarity selected in the SPIx_CR1 register (by
pulling up SCK if CPOL=1 or pulling down SCK if CPOL=0).
Co-authored-by: Ralf <jr-oss@gmx.net>
RM0394:
40.4.6
Communication formats
...
The idle state of SCK must correspond to the polarity selected in the SPIx_CR1 register (by
pulling up SCK if CPOL=1 or pulling down SCK if CPOL=0).
- Rename feature to `embedded-sdmmc`.
- Move embedded-sdmmc fork repo to the embassy-rs org.
- Remove unused features in the fork
- Fix impl in embassy-stm32
- Add to CI so it doesn't break again.
1159: stm32 usb otg bug fixes r=Dirbaio a=chemicstry
This fixes a couple of usb otg bugs that surfaced with `usb_ethernet` example from nrf:
- Properly implemented `Endpoint::wait_enabled()`
- Return `EndpointError::Disabled` when neccessary in `Endpoint::write()`
Co-authored-by: chemicstry <chemicstry@gmail.com>
The eth code is always built and available, but has no own API (other
than the embassy-net Device impl) to rx/tx packets. We could add this
API in the future, so the feature only means "embassy-net support".
1082: stm32: Add basic support for DMA priority settings r=lulf a=matoushybl
This adds very basic support for specifying priority for DMA interrupts. Unfortunately, the patch now doesn't allow for specifying different priorities for DMA1/DMA2, or BDMA1/BDMA2, which I didn't know how to support.
1083: stm32: Fix H7 unaligned erase r=lulf a=matoushybl
This PR simplifies erasing sectors on the H7, which was buggy.
Co-authored-by: Matous Hybl <hyblmatous@gmail.com>
1088: stm32: Enable fifo for buffered uart r=lulf a=matoushybl
This PR enables fifo for buffered uart where it is available. This should hopfully get rid of some overrun errors. I tried it in my application where it worked, but more intensive testing is probably required.
Co-authored-by: Matous Hybl <hyblmatous@gmail.com>
1052: stm32: Fix watchdog division by zero for 256 prescaler, add watchdog … r=lulf a=matoushybl
…example for H7
The problem is that `2u8.powi(8) == 0`, which causes division by zero.
1053: Disable MMC interrupts r=lulf a=matoushybl
MMC interrupts can cause firmware hangup - refer to: https://github.com/stm32-rs/stm32h7xx-hal/issues/275 for more information
Fixes#594
Co-authored-by: Matous Hybl <hyblmatous@gmail.com>
1034: stm32/usart: Fix bug where USART idle flag could end a `read` prematuraly r=Dirbaio a=guillaume-michel
on STM32, when setting USART `detect_previous_overrun = true`, the idle flag is not cleared and could result in premature end of the `read` method.
This PR fixes that.
Co-authored-by: Guillaume MICHEL <guillaume@squaremind.io>
1024: stm32/adc: Remove voltage and temperature conversions r=Dirbaio a=GrantM11235
The current conversion utilities are confusing and a bit of a footgun. (Two out of the three examples got it wrong! They didn't measure vref at all, so all the conversions are completely wrong if vcca isn't 3.3v)
I think we should eventually have some sort of conversion utilities in the HAL, but for now I think it is best to just remove it and let the users do their own math.
cc `@chemicstry`
Co-authored-by: Grant Miller <GrantM11235@gmail.com>
1025: Implement I2C timeouts, second attempt r=Dirbaio a=chemicstry
This is an alterrnative to #1022 as discussed there.
Timeouts are implemented using suggested `check_timeout: impl Fn() -> Result<(), Error>` function, which does not depend on `embassy-time` by default and is a noop for regular I2C.
This also adds `time` feature like in `embassy-nrf` to enable `embassy-time` dependencies. While at it, I also gated some other peripherals that depend on `embassy-time`, notably `usb` and (partially) `subghz`.
`TimeoutI2c` is currently only implemented for i2cv1, because i2cv2 has additional complications:
- Async methods still use a lot of busy waiting code in between DMA transfers, so simple `with_timeout()` will not work and it will have to use both types of timeouts. It could probably be rewritten to replace busy waits with IRQs, but that's outside the scope of this PR.
- I2C definition `I2c<'d, T, TXDMA, RXDMA>` is different from i2cv1 `I2c<'d, T>` making it hard to share single `TimeoutI2c` wrapper. A couple of options here:
- Duplicate `TimeoutI2c` code
- Add dummy `TXDMA`, `RXDMA` types to i2cv1 considering that in the future it should also support DMA
Co-authored-by: chemicstry <chemicstry@gmail.com>
959: Generic, executor-agnostic queue implementation r=ivmarkov a=ivmarkov
Hopefully relatively well documented.
Implementation relies on a fixed-size `SortedLinkedList` from `heapless`. (By default, for up to 128 timer schedules, but we can lower this number to - say - 64.)
As discussed earlier, on queue overflow, the `WakerRegistration` approach is utilized, whereas the waker that is ordered first in the queue is awoken to make room for the incoming one (which might be the waker that would be awoken after all!). Wakers are compared with `Waker::will_wake`, so the queue should actually not fill up that easily, if at all.
I've left provisions for the user to manually instantiate the queue using a dedicated macro - `generic_queue!` so that users willing to adjust the queue size, or users (like me) who have to use the queue in a complex "on-top-of-RTOS-but-the-timer-driver-calling-back-from-ISR" scenario can customize the mutex that protects the queue.
The one thing I'm not completely happy with is the need to call `{ embassy_time::queue::initialize() }` early on before any futures using embassy-time are polled, which is currently on the shoulders of the user. I'm open to any ideas where we can get rid of this and do it on the first call to `_embassy_time_schedule_wake`, without introducing very complex combinations of critical sections, atomics and whatnot.
Co-authored-by: ivmarkov <ivan.markov@gmail.com>
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
1014: Add memory barriers to H7 flash driver to mitigate PGSERR errors r=lulf a=matoushybl
The stm32h7xx-hal uses only the ordering barrier, while the CubeMX uses the DSB and ISB instructions, to be on the safe side, both are used here.
Without the barrier, the PG bit is not set, when the writes are being done, resulting in an error.
Co-authored-by: Matous Hybl <hyblmatous@gmail.com>
1004: Fix internal channels for adc v2 r=lulf a=chemicstry
Internal channel reading was broken on adc_v2, because `Adc::read()` requires gpio pin trait, which was not implemented by `VrefInt`, `Temperature`, `Vbat`. The required configuration bits `tsvrefe`, `vbate` were not enabled either. This PR makes it a bit closer to how adc_v4 works.
While at it, I also changed adc_v2 to use `RccPeripheral` instead of permanently enabling all ADCs.
Co-authored-by: chemicstry <chemicstry@gmail.com>
992: (embassy-stm32): remove flash lock/unlock public API from stm32 flash r=lulf a=MathiasKoch
Instead, perform the unlocking and locking automatically on erase and write operations.
This makes the `embedded-storage` abstraction actually useable in libraries, while still keeping the flash peripheral locked the majority of the time.
Co-authored-by: Mathias <mk@blackbird.online>
960: Add non blocking Bxcan constructor r=Dirbaio a=andyblarblar
This PR adds a non-blocking constructor to the Bxcan Can wrapper struct. This allows for the creation of the Can periferal without blocking for a sync with the Can bus.
Co-authored-by: Andrew Ealovega <Andrew@Ealovega.dev>
839: Misc LoRaWAN improvements r=lulf a=timokroeger
Trying too get `embassy-lora` running on a [LoRa-E5 Dev Board](https://wiki.seeedstudio.com/LoRa_E5_Dev_Board/).
I can see the join message arriving in the The Things Network console but the device does not receive the accept message yet.
Opening this PR anyway because I think there are some nice things to decouple the lora crate from the nucleo board.
`@lulf` Could you test if this PR breaks your LoRa setup? Marking as draft for the time being.
Co-authored-by: Timo Kröger <timokroeger93@gmail.com>
Co-authored-by: Ulf Lilleengen <lulf@redhat.com>
Old code used `cfg_if!` because rustc still parses code inside disabled cfg's, and Rust stable at that time couldn't parse the new GAT where-clause location. This is not the case anymore.
* `MSIRGSEL = 1` was required for MSI accept the updated MSI range
* Reorder enable and clock switching to properly handle the jump from
the default 4MHz MSI to a higher MSI freuquency
876: Add defmt support to embassy-embedded-hal errors r=Dirbaio a=matoushybl
`defmt::unwrap!()` should now work with shared buses. I tested it only with I2C as I don't have SPI in the target project.
Co-authored-by: Matous Hybl <hyblmatous@gmail.com>
550da471be previously refactored the STM32
PWM logic in such a way to preclude use of non-contiguous channels (e.g.
channel 2 but not channel 1). Refactor it yet again to yet again allow
this sort of usage.
866: F4 flash fixes r=Dirbaio a=chemicstry
This discontinuous flash sector layout is too cursed and I left some mistakes in last PR. Erasing last sector did not work and it wasn't possible to erase between memory banks for 1MB dual-bank devices. So I changed the erase function to iterate over memory addresses (which is continuous) instead of sector numbers.
It should also be possible to implement erase across memory banks for H7, but it requires special handling for write too. I don't have an H7 to test now so left it as is.
I wasn't sure how to add tests to `embassy-stm32` and it seems that there are none, except for `subghz`, but no test runner? Anyway, I tested the `get_sector` on playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=13b59339fe6c70a3249e6183e81f869e
Also fixed erase alignment requirements on `Flash::blocking_erase()`, as it previously only checked alignment on size, but not on offsets.
P.S. the diff is a bit messed up, I recommend looking at files directly
Co-authored-by: chemicstry <chemicstry@gmail.com>
858: embassy-stm32: Simplify time r=Dirbaio a=GrantM11235
- Remove unused `MilliSeconds`, `MicroSeconds`, and `NanoSeconds` types
- Remove `Bps`, `KiloHertz`, and `MegaHertz` types that were only used
for converting to `Hertz`
- Replace all instances of `impl Into<Hertz>` with `Hertz`
- Add `hz`, `khz`, and `mhz` methods to `Hertz`, as well as
free function shortcuts
- Remove `U32Ext` extension trait
Co-authored-by: Grant Miller <GrantM11235@gmail.com>
- Remove unused `MilliSeconds`, `MicroSeconds`, and `NanoSeconds` types
- Remove `Bps`, `KiloHertz`, and `MegaHertz` types that were only used
for converting to `Hertz`
- Replace all instances of `impl Into<Hertz>` with `Hertz`
- Add `hz`, `khz`, and `mhz` methods to `Hertz`, as well as
free function shortcuts
- Remove `U32Ext` extension trait
810: Takes care of power for nRF USB devices r=Dirbaio a=huntc
Modifies the usb-serial example to illustrate how to setup USB for situations where the USB power can be detected and removed.
Gaps:
~~* No support for the nrf-softdevices as yet, although this should be possible via another constructor.~~
* No support for the nrf5340, although this should be possible via USBREG.
The change is tested and appears to work. Some notes:
* There's an existing field named self_powered as a UsbDevice field. It doesn't ever appear to get set. I'm wondering if this field is intended to signal that a device has the nRF VBUS power situation or not. I'm not presently using it.
* The new PowerDetected event is generated on the bus initially in situations where just new is used i.e. without power management, including on STM. We can therefore rely on this event always being generated.
Old description:
~~EnabledUsbDevice is a wrapper around the `UsbDevice` where its enablement is also subject to external events, such as `POWER` events for nRF. It is introduced generically to support other platforms should they also require external signaling for enablement.~~
Co-authored-by: huntc <huntchr@gmail.com>
854: Implement IWDG timeout calculation r=Dirbaio a=chemicstry
Allow specifying `IndependentWatchdog` timeout as `Duration` instead of prescaler value.
Since IWDG is clocked from LSI, which differs between families, I standardized HSI/LSI definitions in RCC and used that.
Co-authored-by: chemicstry <chemicstry@gmail.com>
851: Gpio dynamic flex r=Dirbaio a=AntoineMugnier
Add Flex GPIO type for embassy-stm32 as it is the case for embassy-nrf.
Co-authored-by: amugniere@gmail.com <antoine.mugnier@depixus.com>
It currently contains whoever was first to write some code for the crate,
even if many more people have contributed to it later.
The field is "sort of" deprecated, it was made optional recently:
https://rust-lang.github.io/rfcs/3052-optional-authors-field.html
Due the the reasons listed there I believe removing it is better than
setting it to generic fluff like "The Embassy contributors".
- Move Interrupt and InterruptExecutor from `embassy` to `embassy-cortex-m`.
- Move Unborrow from `embassy` to `embassy-hal-common` (nothing in `embassy` requires it anymore)
- Move PeripheralMutex from `embassy-hal-common` to `embassy-cortex-m`.
Following the project's decision that "leak unsafe" APIs are not marked as "unsafe",
update PeripheralMutex to accept non-'static state without unsafe.
Fixes#801
The stm32 time drivers support arbitrary tick rates but the associated
Cargo features do not. Enabling any time driver presently enables
`embassy/time-tick-32768hz`; instead, enable only `embassy/time`.
This is a breaking change: users must now choose a tick rate. The
previous behavior is available by enabling the
`embassy/time-tick-32768hz` feature, but now users may also choose
`embassy/time-tick-1000hz` or `embassy/time-tick-1mhz` instead.
781: embassy-net v2 r=Dirbaio a=Dirbaio
- No more `dyn`
- It's no longer a global singleton, you can create muliple net stacks at once.
- You can't tear them down though, the Device it still has to be `'static` due to restrictions with smoltcp's "fake GAT" in the Device trait. :(
- Removed `_embassy_rand` hack, random seed is passed on creation.
785: stm32: g0: add PLL clock source r=Dirbaio a=willglynn
STM32G0 SYSCLK can be sourced from PLLRCLK. Given that the HSI runs at 16 MHz and the HSE range is 4-48 MHz, the PLL is the only way to reach 64 MHz. This commit adds `ClockSrc::PLL`.
The PLL sources from either HSI16 or HSE, divides it by `m`, and locks its VCO to multiple `n`. It then divides the VCO by `r`, `p`, and `q` to produce up to three associated clock signals:
* PLLRCLK is one of the inputs on the SYSCLK mux. This is the main reason the user will configure the PLL, so `r` is mandatory and the output is enabled unconditionally.
* PLLPCLK is available as a clock source for the ADC and I2S peripherals, so `p` is optional and the output is conditional.
* PLLQCLK exists only on STM32G0B0xx, and exists only to feed the MCO and MCO2 peripherals, so `q` is optional and the output is conditional.
When the user specifies `ClockSrc::PLL(PllConfig)`, `rcc::init()` calls `PllConfig::init()` which initializes the PLL per [RM0454]. It disables the PLL, waits for it to stop, enables the source oscillator, configures the PLL, waits for it to lock, and then enables the appropriate outputs. `rcc::init()` then switches the clock source to PLLRCLK.
`rcc::init()` is now also resonsible for calculating and setting flash wait states. SYSCLCK < 24 MHz is fine in the reset state, but 24-48 MHz requires waiting 1 cycle and 48-64 MHz requires waiting 2 cycles. (This was likely a blocker for anyone using HSE >= 24 MHz, with or without the PLL.) Flash accesses are now automatically slowed down as needed before changing the clock source, and sped up as permitted after changing the clock source. The number of flash wait states also determines if flash prefetching will be profitable, so that is now handled automatically too.
[RM0454]: https://www.st.com/resource/en/reference_manual/rm0454-stm32g0x0-advanced-armbased-32bit-mcus-stmicroelectronics.pdf
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
Co-authored-by: Will Glynn <will@willglynn.com>
STM32G0 SYSCLK can be sourced from PLLRCLK. Given that the HSI runs at
16 MHz and the HSE range is 4-48 MHz, the PLL is the only way to reach
64 MHz. This commit adds `ClockSrc::PLL`.
The PLL sources from either HSI16 or HSE, divides it by `m`, and locks
its VCO to multiple `n`. It then divides the VCO by `r`, `p`, and `q`
to produce up to three associated clock signals:
* PLLRCLK is one of the inputs on the SYSCLK mux. This is the main
reason the user will configure the PLL, so `r` is mandatory and
the output is enabled unconditionally.
* PLLPCLK is available as a clock source for the ADC and I2S
peripherals, so `p` is optional and the output is conditional.
* PLLQCLK exists only on STM32G0B0xx, and exists only to feed the
MCO and MCO2 peripherals, so `q` is optional and the output is
conditional.
When the user specifies `ClockSrc::PLL(PllConfig)`, `rcc::init()`
calls `PllConfig::init()` which initializes the PLL per [RM0454]. It
disables the PLL, waits for it to stop, enables the source
oscillator, configures the PLL, waits for it to lock, and then
enables the appropriate outputs. `rcc::init()` then switches the
clock source to PLLRCLK.
`rcc::init()` is now also resonsible for calculating and setting flash
wait states. SYSCLCK < 24 MHz is fine in the reset state, but 24-48 MHz
requires waiting 1 cycle and 48-64 MHz requires waiting 2 cycles. (This
was likely a blocker for anyone using HSE >= 24 MHz, with or without
the PLL.) Flash accesses are now automatically slowed down as needed
before changing the clock source, and sped up as permitted after
changing the clock source. The number of flash wait states also
determines if flash prefetching will be profitable, so that is now
handled automatically too.
[RM0454]: https://www.st.com/resource/en/reference_manual/rm0454-stm32g0x0-advanced-armbased-32bit-mcus-stmicroelectronics.pdf
776: Automatically set ADC clock prescaler on v2 ADC to respect max frequency r=Dirbaio a=matoushybl
Co-authored-by: Matous Hybl <hyblmatous@gmail.com>
PLL settings remained intact because these bits are not writable when PLL is enabled,
but prescaler settings were overwritten by selecting PLL as sysclk (CFGR.SW[1:0]).
The replacement is `embassy-usb`. There's a WIP driver for stm32 USBD in #709,
there's no WIP driver for stm32 USB_OTG. This means we're left without
USB_OTG support for now.
Reason for removing is I'm going to soon remove `embassy::io`, and
USB uses it. I don't want to spend time maintaining "dead" code
that is going to be removed. Volunteers welcome, either to update
old USB to the new IO, or write a USB_OTG driver fo the new USB.
743: Add PLL config support for F2 r=Dirbaio a=Gekkio
- minor changes to make the F2 RCC API a bit more flexible
- low-level PLL config with assertions based on datasheet specs. It shouldn't be very difficult to later add a "reverse API" where you pass the clocks you want to a function and it generates a `PLLConfig` struct for you
- PLL API tested on my custom board with 12 MHz HSE as source for PLL to generate max clocks for SYSCLK/AHB/APB/APB1/PLL48
- the example *should* work but is untested since I don't have the Nucleo board 😞
Co-authored-by: Joonas Javanainen <joonas.javanainen@gmail.com>
SMI Ethernet PHYs all share a common base set of registers that can do
90% of all tasks. The LAN8742 driver used some vendor-specific
registers to check link negotiation status, but the need for that was
debatable, so I migrated it to a generic driver instead, anybody who
wants extra functionality can copy it and impl their own on top of it.
This makes the configuration more flexible and closer to the underlying
configuration register structure. For example, we could use HSI for the
system clock, but use HSE to output a clock with MCO.
* Add flash drivers for L0, L1, L4, WB and WL. Not tested for WB, but
should be similar to WL.
* Add embassy-boot-stm32 for bootloading on STM32.
* Add flash examples and bootloader examples
* Update stm32-data
714: add more clock options for l4 and l5 r=Dirbaio a=ant32
- added an assert so it panics if pll48div is not 48Mhz
- added MSI as a clock source for PLL
- removed hsi48 option for MCUs mentioned in l4 rcc presentation
- copied some code from l4 to l5, but don't have a way of testing it.
Co-authored-by: Philip A Reimer <antreimer@gmail.com>
715: stm32/dac: Check proper channel r=Dirbaio a=michalsrb
Small fix. Otherwise it panics when trying to use channel 1 if channel 2 does not exist.
Co-authored-by: Michal Srb <michalsrb@gmail.com>
669: Add SDMMC v1 and SDIO support r=Dirbaio a=chemicstry
SDMMC v2 peripheral is an extension of SDMMC v1 (or SDIO) so I managed to reuse most of the code, with some cfg's.
Apart from small differeces in registers, the biggest change is that v2 uses internal DMA, while v1 has to use shared DMA peripheral. This makes code a bit uglier, because DMA channel for v1 has to be passed around. Not sure if it's possible to make it any cleaner.
This also adds `TransferOptions` structure to DMA, because SDMMC v1 requires setting peripheral flow control and burst transfers. Let me know if some alternative way would be prefered.
I tested this on STM32F429ZIT6 (with sd card) and STM32H745ZIT6 (with oscilloscope).
Depends on: https://github.com/embassy-rs/stm32-data/pull/130
Co-authored-by: chemicstry <chemicstry@gmail.com>
673: Inline GPIO functions r=Dirbaio a=nviennot
All GPIO functions are monomorphized (per pin). Inlining these make the ROM smaller when using opt-level="z"
Co-authored-by: Nicolas Viennot <nicolas@viennot.biz>
* Keeps existing API for usart, but wraps it in Tx and Rx sub-types
* Adds split() method similar to nRF for getting indepdendent TX and RX
parts
* Implements e-h traits for TX and RX types
* Add stm32h7 example
Previously, every dma interrupt handler called the same `on_irq`
function which had to check the state of every dma channel.
Now, each dma interrupt handler only calls an `on_irq` method for its
corresponding channel or channels.
Approach is similar to USB OTG.
STM32L49x and STML4Ax have CAN1 and CAN2.
All others STM32L4xx do only have CAN1.
STM32F72x and STM32F73x are the only F7 devices with only CAN1.
652: Use new stm32-data registers and fix AHB clock calculation r=Dirbaio a=msamsonoff
This is the follow-on to my PR against stm32-data that added new register enums for the G0. I have updated the G0 RCC module to use those new enums.
I have also fixed an issue with the calculation of the AHB clock rate. 32 is not available as an AHB prescaler. The sequence jumps from 16 to 64. The original bit shifting math did not account for this gap. I have replaced it with a `match` instead.
653: Fixes for rustdoc building. r=Dirbaio a=Dirbaio
Co-authored-by: Matthew W. Samsonoff <matt.samsonoff@gmail.com>
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
The original code for calculating the AHB clock did not account for the gap in
prescaler values (32 is not an available value.) The bit shifting and math has
been replaced by a `match`.
These files end up containing chip-specific info, so they deduplicate
really badly when building docs for all 1200 chips.
The doc generator removes files starting with `_`.
* On v1 interrupts cannot be cleared individually.
Instead they are cleared implicitly by reading or writing DR (which we do now).
* Multiple error flags can be set at the same time:
Handle them all in one go intstead of re-entering the ISR for each one so that
we do not lose any error flags on v1 hardware.
* Wake when the RX buffer becomes full: This allows fast running chips to pull data
from the buffer before receiving the next byte.
608: stm32f4: add adc + example r=Dirbaio a=ain101
Example tested on stm32f407vg Discovery Board.
minimal adc: no vref, dma, complex sequence
Co-authored-by: Frederik <frederik@frederik.at>
601: [part 1/n] Change macrotables to build.rs codegen r=lulf a=Dirbaio
This PR replaces the "macrotables" (the macros like `stm32_data::peripherals!`) with a `const METADATA`.
Macrotables had some problems:
- Hard to debug
- Somewhat footgunny (typo the "pattern" and then nothing matches and the macro now expands to nothing, silently!)
- Limited power
- Can't count, so we had to add a [special macrotable for that](f50f3f0a73/embassy-stm32/src/dma/bdma.rs (L26)).
- Can't remove duplicates, so we had to fallback to [Rust code in build.rs](f50f3f0a73/embassy-stm32/build.rs (L105-L145))
- Can't include the results as a listto another macro, so again [build.rs](https://github.com/embassy-rs/embassy/blob/master/embassy-stm32/build.rs#L100-L101).
They work fine for the 95% of cases, but for the remaining 5% we need Rust code in build.rs. So we might as well do everything with Rust code, so everything is consistent.
The new approach generates a `const METADATA: Metadata = Metadata { ... }` with [these structs](https://github.com/embassy-rs/embassy/blob/unmacrotablize/stm32-metapac-gen/src/assets/metadata.rs) in `stm32-metapac`. `build.rs` can then read that and generate whatever code.
Co-authored-by: Dario Nieuwenhuis <dirbaio@dirbaio.net>
602: Add stm32 USB OTG peripherals r=Dirbaio a=chemicstry
Fixes#557. This is similar to #580, but for synopsys IP.
I could add examples to other chips, but I have no way of testing them. The F4 example is tested and working.
Co-authored-by: chemicstry <chemicstry@gmail.com>
The rcc code was taken from stm32-rs which uses 'x' features, but
embassy uses features with full chip names.
Add these 'x' wildcards as cfgs and use them in rcc.
They will be useful for USB too.