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>