From cbc97758e391d981d497bf37fe63b5a35913c115 Mon Sep 17 00:00:00 2001 From: Matous Hybl Date: Wed, 9 Nov 2022 14:10:46 +0100 Subject: [PATCH 1/5] stm32: Fix watchdog division by zero for 256 prescaler, add watchdog example for H7 --- embassy-stm32/src/wdg/mod.rs | 8 ++++---- examples/stm32h7/src/bin/wdg.rs | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 examples/stm32h7/src/bin/wdg.rs diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs index 85176eef..92b9a5ca 100644 --- a/embassy-stm32/src/wdg/mod.rs +++ b/embassy-stm32/src/wdg/mod.rs @@ -13,12 +13,12 @@ pub struct IndependentWatchdog<'d, T: Instance> { const MAX_RL: u16 = 0xFFF; /// Calculates maximum watchdog timeout in us (RL = 0xFFF) for a given prescaler -const fn max_timeout(prescaler: u8) -> u32 { +const fn max_timeout(prescaler: u16) -> u32 { 1_000_000 * MAX_RL as u32 / (LSI_FREQ.0 / prescaler as u32) } /// Calculates watchdog reload value for the given prescaler and desired timeout -const fn reload_value(prescaler: u8, timeout_us: u32) -> u16 { +const fn reload_value(prescaler: u16, timeout_us: u32) -> u16 { (timeout_us / prescaler as u32 * LSI_FREQ.0 / 1_000_000) as u16 } @@ -33,12 +33,12 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> { // Find lowest prescaler value, which makes watchdog period longer or equal to timeout. // This iterates from 4 (2^2) to 256 (2^8). let psc_power = unwrap!((2..=8).find(|psc_power| { - let psc = 2u8.pow(*psc_power); + let psc = 2u16.pow(*psc_power); timeout_us <= max_timeout(psc) })); // Prescaler value - let psc = 2u8.pow(psc_power); + let psc = 2u16.pow(psc_power); // Convert prescaler power to PR register value let pr = psc_power as u8 - 2; diff --git a/examples/stm32h7/src/bin/wdg.rs b/examples/stm32h7/src/bin/wdg.rs new file mode 100644 index 00000000..2b0301aa --- /dev/null +++ b/examples/stm32h7/src/bin/wdg.rs @@ -0,0 +1,24 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::*; +use embassy_executor::Spawner; +use embassy_stm32::wdg::IndependentWatchdog; +use embassy_time::{Duration, Timer}; +use {defmt_rtt as _, panic_probe as _}; + +#[embassy_executor::main] +async fn main(_spawner: Spawner) { + let p = embassy_stm32::init(Default::default()); + info!("Hello World!"); + + let mut wdg = IndependentWatchdog::new(p.IWDG1, 20_000_000); + + unsafe { wdg.unleash() }; + + loop { + Timer::after(Duration::from_secs(1)).await; + unsafe { wdg.pet() }; + } +} From 99682d313b54409c33d471e066ef6aba9f628a68 Mon Sep 17 00:00:00 2001 From: Matous Hybl Date: Tue, 25 Oct 2022 09:47:30 +0200 Subject: [PATCH 2/5] Disable MMC interrupts MMC interrupts can cause firmware hangup - refer to: https://github.com/stm32-rs/stm32h7xx-hal/issues/275 for more information --- embassy-stm32/src/eth/v2/mod.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs index a81ee118..5b76d1e7 100644 --- a/embassy-stm32/src/eth/v2/mod.rs +++ b/embassy-stm32/src/eth/v2/mod.rs @@ -116,6 +116,24 @@ impl<'d, T: Instance, P: PHY, const TX: usize, const RX: usize> Ethernet<'d, T, mac.macqtx_fcr().modify(|w| w.set_pt(0x100)); + // disable all MMC RX interrupts + mac.mmc_rx_interrupt_mask().write(|w| { + w.set_rxcrcerpim(true); + w.set_rxalgnerpim(true); + w.set_rxucgpim(true); + w.set_rxlpiuscim(true); + w.set_rxlpitrcim(true) + }); + + // disable all MMC TX interrupts + mac.mmc_tx_interrupt_mask().write(|w| { + w.set_txscolgpim(true); + w.set_txmcolgpim(true); + w.set_txgpktim(true); + w.set_txlpiuscim(true); + w.set_txlpitrcim(true); + }); + mtl.mtlrx_qomr().modify(|w| w.set_rsf(true)); mtl.mtltx_qomr().modify(|w| w.set_tsf(true)); From bcec55464f22069c45f07745efdd0fa45a4959c4 Mon Sep 17 00:00:00 2001 From: Johannes Neyer Date: Fri, 11 Nov 2022 11:06:38 +0100 Subject: [PATCH 3/5] [doc] Fix line indices of basic example --- docs/modules/ROOT/pages/basic_application.adoc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/modules/ROOT/pages/basic_application.adoc b/docs/modules/ROOT/pages/basic_application.adoc index 4dc4a635..f20ddf53 100644 --- a/docs/modules/ROOT/pages/basic_application.adoc +++ b/docs/modules/ROOT/pages/basic_application.adoc @@ -21,7 +21,7 @@ Then, what follows are some declarations on how to deal with panics and faults. [source,rust] ---- -include::example$basic/src/main.rs[lines="11..12"] +include::example$basic/src/main.rs[lines="10"] ---- === Task declaration @@ -30,7 +30,7 @@ After a bit of import declaration, the tasks run by the application should be de [source,rust] ---- -include::example$basic/src/main.rs[lines="13..22"] +include::example$basic/src/main.rs[lines="12..20"] ---- An embassy task must be declared `async`, and may NOT take generic arguments. In this case, we are handed the LED that should be blinked and the interval of the blinking. @@ -45,7 +45,7 @@ The `Spawner` is the way the main application spawns other tasks. The `Periphera [source,rust] ---- -include::example$basic/src/main.rs[lines="23..-1"] +include::example$basic/src/main.rs[lines="22..-1"] ---- `#[embassy_executor::main]` takes an optional `config` parameter specifying a function that returns an instance of HAL's `Config` struct. For example: @@ -76,7 +76,7 @@ The project definition needs to contain the embassy dependencies: [source,toml] ---- -include::example$basic/Cargo.toml[lines="8..9"] +include::example$basic/Cargo.toml[lines="9..11"] ---- Depending on your microcontroller, you may need to replace `embassy-nrf` with something else (`embassy-stm32` for STM32. Remember to update feature flags as well). From ea61c192807df7a1422ea04480cca0562cbc3bb2 Mon Sep 17 00:00:00 2001 From: Johannes Neyer Date: Tue, 15 Nov 2022 10:07:35 +0100 Subject: [PATCH 4/5] [doc] Fix some grammar --- docs/modules/ROOT/pages/basic_application.adoc | 2 +- docs/modules/ROOT/pages/layer_by_layer.adoc | 8 ++++---- docs/modules/ROOT/pages/stm32.adoc | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/modules/ROOT/pages/basic_application.adoc b/docs/modules/ROOT/pages/basic_application.adoc index f20ddf53..d233d77c 100644 --- a/docs/modules/ROOT/pages/basic_application.adoc +++ b/docs/modules/ROOT/pages/basic_application.adoc @@ -61,7 +61,7 @@ async fn main(_spawner: Spawner, p: embassy_nrf::Peripherals) { } ``` -What happens when the `blinker` task have been spawned and main returns? Well, the main entry point is actually just like any other task, except that you can only have one and it takes some specific type arguments. The magic lies within the `#[embassy::main]` macro. The macro does the following: +What happens when the `blinker` task has been spawned and main returns? Well, the main entry point is actually just like any other task, except that you can only have one and it takes some specific type arguments. The magic lies within the `#[embassy::main]` macro. The macro does the following: . Creates an Embassy Executor . Initializes the microcontroller HAL to get the `Peripherals` diff --git a/docs/modules/ROOT/pages/layer_by_layer.adoc b/docs/modules/ROOT/pages/layer_by_layer.adoc index a96dd9fe..a78a64a9 100644 --- a/docs/modules/ROOT/pages/layer_by_layer.adoc +++ b/docs/modules/ROOT/pages/layer_by_layer.adoc @@ -8,7 +8,7 @@ The application we'll write is a simple 'push button, blink led' application, wh == PAC version -The PAC is the lowest API for accessing peripherals and registers, if you don't count reading/writing directly to memory addresses. It provide distinct types +The PAC is the lowest API for accessing peripherals and registers, if you don't count reading/writing directly to memory addresses. It provides distinct types to make accessing peripheral registers easier, but it does not prevent you from writing unsafe code. Writing an application using the PAC directly is therefore not recommended, but if the functionality you want to use is not exposed in the upper layers, that's what you need to use. @@ -20,13 +20,13 @@ The blinky app using PAC is shown below: include::example$layer-by-layer/blinky-pac/src/main.rs[] ---- -As you can see, there are a lot of code needed to enable the peripheral clocks, configuring the input pins and the output pins of the application. +As you can see, a lot of code is needed to enable the peripheral clocks and to configure the input pins and the output pins of the application. Another downside of this application is that it is busy-looping while polling the button state. This prevents the microcontroller from utilizing any sleep mode to save power. == HAL version -To simplify our application, we can use the HAL instead. The HAL exposes higher level APIs that handle details such +To simplify our application, we can use the HAL instead. The HAL exposes higher level APIs that handle details such as: * Automatically enabling the peripheral clock when you're using the peripheral * Deriving and applying register configuration from higher level types @@ -39,7 +39,7 @@ The HAL example is shown below: include::example$layer-by-layer/blinky-hal/src/main.rs[] ---- -As you can see, the application becomes a lot simpler, even without using any async code. The `Input` and `Output` hides all the details accessing the GPIO registers, and allow you to use a much simpler API to query the state of the button and toggle the LED output accordingly. +As you can see, the application becomes a lot simpler, even without using any async code. The `Input` and `Output` types hide all the details of accessing the GPIO registers and allow you to use a much simpler API for querying the state of the button and toggling the LED output. The same downside from the PAC example still applies though: the application is busy looping and consuming more power than necessary. diff --git a/docs/modules/ROOT/pages/stm32.adoc b/docs/modules/ROOT/pages/stm32.adoc index 8ed9ab04..7bfc0592 100644 --- a/docs/modules/ROOT/pages/stm32.adoc +++ b/docs/modules/ROOT/pages/stm32.adoc @@ -4,9 +4,9 @@ The link:https://github.com/embassy-rs/embassy/tree/master/embassy-stm32[Embassy == The infinite variant problem -STM32 microcontrollers comes in many families and flavors, and supporting all of them is a big undertaking. Embassy has taken advantage of the fact +STM32 microcontrollers come in many families, and flavors and supporting all of them is a big undertaking. Embassy has taken advantage of the fact that the STM32 peripheral versions are shared across chip families. Instead of re-implementing the SPI -peripheral for every STM32 chip family, embassy have a single SPI implementation that depends on +peripheral for every STM32 chip family, embassy has a single SPI implementation that depends on code-generated register types that are identical for STM32 families with the same version of a given peripheral. === The metapac From 9505a6f7527cee9af73117e49322169f2d568a39 Mon Sep 17 00:00:00 2001 From: Johannes Neyer Date: Tue, 15 Nov 2022 10:07:45 +0100 Subject: [PATCH 5/5] [doc] Remove obsolete code sample --- docs/modules/ROOT/pages/basic_application.adoc | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/docs/modules/ROOT/pages/basic_application.adoc b/docs/modules/ROOT/pages/basic_application.adoc index d233d77c..3f4f16e2 100644 --- a/docs/modules/ROOT/pages/basic_application.adoc +++ b/docs/modules/ROOT/pages/basic_application.adoc @@ -48,19 +48,6 @@ The `Spawner` is the way the main application spawns other tasks. The `Periphera include::example$basic/src/main.rs[lines="22..-1"] ---- -`#[embassy_executor::main]` takes an optional `config` parameter specifying a function that returns an instance of HAL's `Config` struct. For example: - -```rust -fn embassy_config() -> embassy_nrf::config::Config { - embassy_nrf::config::Config::default() -} - -#[embassy_executor::main(config = "embassy_config()")] -async fn main(_spawner: Spawner, p: embassy_nrf::Peripherals) { - // ... -} -``` - What happens when the `blinker` task has been spawned and main returns? Well, the main entry point is actually just like any other task, except that you can only have one and it takes some specific type arguments. The magic lies within the `#[embassy::main]` macro. The macro does the following: . Creates an Embassy Executor