aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSijmen Woutersen <[email protected]>2022-11-20 20:04:23 +0100
committerSijmen Woutersen <[email protected]>2022-11-20 20:04:23 +0100
commit4943dec1a7ea52dc92c1e58f3b7f5860d79d192c (patch)
tree412206a26fbe733c45e115f0cec3823f45d5dc30
parente70ae71eccf370c42043fa323002c14f94a16679 (diff)
parent2528f451387e6c7b27c3140cd87d47521d1971a2 (diff)
Merge remote-tracking branch 'upstream/master'
-rw-r--r--docs/modules/ROOT/pages/basic_application.adoc23
-rw-r--r--docs/modules/ROOT/pages/layer_by_layer.adoc8
-rw-r--r--docs/modules/ROOT/pages/stm32.adoc4
-rw-r--r--embassy-stm32/src/eth/v2/mod.rs18
-rw-r--r--embassy-stm32/src/wdg/mod.rs8
-rw-r--r--examples/stm32h7/src/bin/wdg.rs24
6 files changed, 57 insertions, 28 deletions
diff --git a/docs/modules/ROOT/pages/basic_application.adoc b/docs/modules/ROOT/pages/basic_application.adoc
index 4dc4a6359..3f4f16e28 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.
21 21
22[source,rust] 22[source,rust]
23---- 23----
24include::example$basic/src/main.rs[lines="11..12"] 24include::example$basic/src/main.rs[lines="10"]
25---- 25----
26 26
27=== Task declaration 27=== Task declaration
@@ -30,7 +30,7 @@ After a bit of import declaration, the tasks run by the application should be de
30 30
31[source,rust] 31[source,rust]
32---- 32----
33include::example$basic/src/main.rs[lines="13..22"] 33include::example$basic/src/main.rs[lines="12..20"]
34---- 34----
35 35
36An 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. 36An 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,23 +45,10 @@ The `Spawner` is the way the main application spawns other tasks. The `Periphera
45 45
46[source,rust] 46[source,rust]
47---- 47----
48include::example$basic/src/main.rs[lines="23..-1"] 48include::example$basic/src/main.rs[lines="22..-1"]
49---- 49----
50 50
51`#[embassy_executor::main]` takes an optional `config` parameter specifying a function that returns an instance of HAL's `Config` struct. For example: 51What 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:
52
53```rust
54fn embassy_config() -> embassy_nrf::config::Config {
55 embassy_nrf::config::Config::default()
56}
57
58#[embassy_executor::main(config = "embassy_config()")]
59async fn main(_spawner: Spawner, p: embassy_nrf::Peripherals) {
60 // ...
61}
62```
63
64What 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:
65 52
66. Creates an Embassy Executor 53. Creates an Embassy Executor
67. Initializes the microcontroller HAL to get the `Peripherals` 54. Initializes the microcontroller HAL to get the `Peripherals`
@@ -76,7 +63,7 @@ The project definition needs to contain the embassy dependencies:
76 63
77[source,toml] 64[source,toml]
78---- 65----
79include::example$basic/Cargo.toml[lines="8..9"] 66include::example$basic/Cargo.toml[lines="9..11"]
80---- 67----
81 68
82Depending on your microcontroller, you may need to replace `embassy-nrf` with something else (`embassy-stm32` for STM32. Remember to update feature flags as well). 69Depending on your microcontroller, you may need to replace `embassy-nrf` with something else (`embassy-stm32` for STM32. Remember to update feature flags as well).
diff --git a/docs/modules/ROOT/pages/layer_by_layer.adoc b/docs/modules/ROOT/pages/layer_by_layer.adoc
index a96dd9fe2..a78a64a97 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
8 8
9== PAC version 9== PAC version
10 10
11The 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 11The 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
12to make accessing peripheral registers easier, but it does not prevent you from writing unsafe code. 12to make accessing peripheral registers easier, but it does not prevent you from writing unsafe code.
13 13
14Writing 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. 14Writing 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:
20include::example$layer-by-layer/blinky-pac/src/main.rs[] 20include::example$layer-by-layer/blinky-pac/src/main.rs[]
21---- 21----
22 22
23As 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. 23As 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.
24 24
25Another 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. 25Another 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.
26 26
27== HAL version 27== HAL version
28 28
29To simplify our application, we can use the HAL instead. The HAL exposes higher level APIs that handle details such 29To simplify our application, we can use the HAL instead. The HAL exposes higher level APIs that handle details such as:
30 30
31* Automatically enabling the peripheral clock when you're using the peripheral 31* Automatically enabling the peripheral clock when you're using the peripheral
32* Deriving and applying register configuration from higher level types 32* Deriving and applying register configuration from higher level types
@@ -39,7 +39,7 @@ The HAL example is shown below:
39include::example$layer-by-layer/blinky-hal/src/main.rs[] 39include::example$layer-by-layer/blinky-hal/src/main.rs[]
40---- 40----
41 41
42As 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. 42As 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.
43 43
44The same downside from the PAC example still applies though: the application is busy looping and consuming more power than necessary. 44The same downside from the PAC example still applies though: the application is busy looping and consuming more power than necessary.
45 45
diff --git a/docs/modules/ROOT/pages/stm32.adoc b/docs/modules/ROOT/pages/stm32.adoc
index 8ed9ab04b..7bfc0592b 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
4 4
5== The infinite variant problem 5== The infinite variant problem
6 6
7STM32 microcontrollers comes in many families and flavors, and supporting all of them is a big undertaking. Embassy has taken advantage of the fact 7STM32 microcontrollers come in many families, and flavors and supporting all of them is a big undertaking. Embassy has taken advantage of the fact
8that the STM32 peripheral versions are shared across chip families. Instead of re-implementing the SPI 8that the STM32 peripheral versions are shared across chip families. Instead of re-implementing the SPI
9peripheral for every STM32 chip family, embassy have a single SPI implementation that depends on 9peripheral for every STM32 chip family, embassy has a single SPI implementation that depends on
10code-generated register types that are identical for STM32 families with the same version of a given peripheral. 10code-generated register types that are identical for STM32 families with the same version of a given peripheral.
11 11
12=== The metapac 12=== The metapac
diff --git a/embassy-stm32/src/eth/v2/mod.rs b/embassy-stm32/src/eth/v2/mod.rs
index a81ee1183..5b76d1e7f 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,
116 116
117 mac.macqtx_fcr().modify(|w| w.set_pt(0x100)); 117 mac.macqtx_fcr().modify(|w| w.set_pt(0x100));
118 118
119 // disable all MMC RX interrupts
120 mac.mmc_rx_interrupt_mask().write(|w| {
121 w.set_rxcrcerpim(true);
122 w.set_rxalgnerpim(true);
123 w.set_rxucgpim(true);
124 w.set_rxlpiuscim(true);
125 w.set_rxlpitrcim(true)
126 });
127
128 // disable all MMC TX interrupts
129 mac.mmc_tx_interrupt_mask().write(|w| {
130 w.set_txscolgpim(true);
131 w.set_txmcolgpim(true);
132 w.set_txgpktim(true);
133 w.set_txlpiuscim(true);
134 w.set_txlpitrcim(true);
135 });
136
119 mtl.mtlrx_qomr().modify(|w| w.set_rsf(true)); 137 mtl.mtlrx_qomr().modify(|w| w.set_rsf(true));
120 mtl.mtltx_qomr().modify(|w| w.set_tsf(true)); 138 mtl.mtltx_qomr().modify(|w| w.set_tsf(true));
121 139
diff --git a/embassy-stm32/src/wdg/mod.rs b/embassy-stm32/src/wdg/mod.rs
index 85176eefc..92b9a5ca8 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> {
13const MAX_RL: u16 = 0xFFF; 13const MAX_RL: u16 = 0xFFF;
14 14
15/// Calculates maximum watchdog timeout in us (RL = 0xFFF) for a given prescaler 15/// Calculates maximum watchdog timeout in us (RL = 0xFFF) for a given prescaler
16const fn max_timeout(prescaler: u8) -> u32 { 16const fn max_timeout(prescaler: u16) -> u32 {
17 1_000_000 * MAX_RL as u32 / (LSI_FREQ.0 / prescaler as u32) 17 1_000_000 * MAX_RL as u32 / (LSI_FREQ.0 / prescaler as u32)
18} 18}
19 19
20/// Calculates watchdog reload value for the given prescaler and desired timeout 20/// Calculates watchdog reload value for the given prescaler and desired timeout
21const fn reload_value(prescaler: u8, timeout_us: u32) -> u16 { 21const fn reload_value(prescaler: u16, timeout_us: u32) -> u16 {
22 (timeout_us / prescaler as u32 * LSI_FREQ.0 / 1_000_000) as u16 22 (timeout_us / prescaler as u32 * LSI_FREQ.0 / 1_000_000) as u16
23} 23}
24 24
@@ -33,12 +33,12 @@ impl<'d, T: Instance> IndependentWatchdog<'d, T> {
33 // Find lowest prescaler value, which makes watchdog period longer or equal to timeout. 33 // Find lowest prescaler value, which makes watchdog period longer or equal to timeout.
34 // This iterates from 4 (2^2) to 256 (2^8). 34 // This iterates from 4 (2^2) to 256 (2^8).
35 let psc_power = unwrap!((2..=8).find(|psc_power| { 35 let psc_power = unwrap!((2..=8).find(|psc_power| {
36 let psc = 2u8.pow(*psc_power); 36 let psc = 2u16.pow(*psc_power);
37 timeout_us <= max_timeout(psc) 37 timeout_us <= max_timeout(psc)
38 })); 38 }));
39 39
40 // Prescaler value 40 // Prescaler value
41 let psc = 2u8.pow(psc_power); 41 let psc = 2u16.pow(psc_power);
42 42
43 // Convert prescaler power to PR register value 43 // Convert prescaler power to PR register value
44 let pr = psc_power as u8 - 2; 44 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 000000000..2b0301aad
--- /dev/null
+++ b/examples/stm32h7/src/bin/wdg.rs
@@ -0,0 +1,24 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5use defmt::*;
6use embassy_executor::Spawner;
7use embassy_stm32::wdg::IndependentWatchdog;
8use embassy_time::{Duration, Timer};
9use {defmt_rtt as _, panic_probe as _};
10
11#[embassy_executor::main]
12async fn main(_spawner: Spawner) {
13 let p = embassy_stm32::init(Default::default());
14 info!("Hello World!");
15
16 let mut wdg = IndependentWatchdog::new(p.IWDG1, 20_000_000);
17
18 unsafe { wdg.unleash() };
19
20 loop {
21 Timer::after(Duration::from_secs(1)).await;
22 unsafe { wdg.pet() };
23 }
24}