aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/rust.yml3
-rw-r--r--embassy-stm32/Cargo.toml104
-rw-r--r--embassy-stm32/gen_features.py1
-rw-r--r--embassy-stm32/src/adc/v3.rs1
-rw-r--r--embassy-stm32/src/exti.rs44
-rw-r--r--embassy-stm32/src/rcc/g0/mod.rs190
-rw-r--r--embassy-stm32/src/rcc/mod.rs22
-rw-r--r--examples/stm32g0/.cargo/config.toml18
-rw-r--r--examples/stm32g0/Cargo.toml34
-rw-r--r--examples/stm32g0/build.rs31
-rw-r--r--examples/stm32g0/memory.x7
-rw-r--r--examples/stm32g0/src/bin/blinky.rs31
-rw-r--r--examples/stm32g0/src/bin/button.rs29
-rw-r--r--examples/stm32g0/src/bin/button_exti.rs31
-rw-r--r--examples/stm32g0/src/example_common.rs17
m---------stm32-data0
-rw-r--r--stm32-metapac-gen/src/lib.rs4
17 files changed, 554 insertions, 13 deletions
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml
index 7b6f0c39b..3ddda1a34 100644
--- a/.github/workflows/rust.yml
+++ b/.github/workflows/rust.yml
@@ -92,7 +92,8 @@ jobs:
92 target: thumbv7em-none-eabihf 92 target: thumbv7em-none-eabihf
93 - package: examples/stm32f0 93 - package: examples/stm32f0
94 target: thumbv6m-none-eabi 94 target: thumbv6m-none-eabi
95 95 - package: examples/stm32g0
96 target: thumbv6m-none-eabi
96 steps: 97 steps:
97 - uses: actions/checkout@v2 98 - uses: actions/checkout@v2
98 with: 99 with:
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml
index 38cc12d16..f3b2e0e44 100644
--- a/embassy-stm32/Cargo.toml
+++ b/embassy-stm32/Cargo.toml
@@ -281,6 +281,110 @@ stm32f479vg = [ "stm32-metapac/stm32f479vg",]
281stm32f479vi = [ "stm32-metapac/stm32f479vi",] 281stm32f479vi = [ "stm32-metapac/stm32f479vi",]
282stm32f479zg = [ "stm32-metapac/stm32f479zg",] 282stm32f479zg = [ "stm32-metapac/stm32f479zg",]
283stm32f479zi = [ "stm32-metapac/stm32f479zi",] 283stm32f479zi = [ "stm32-metapac/stm32f479zi",]
284stm32g030c6 = [ "stm32-metapac/stm32g030c6",]
285stm32g030c8 = [ "stm32-metapac/stm32g030c8",]
286stm32g030f6 = [ "stm32-metapac/stm32g030f6",]
287stm32g030j6 = [ "stm32-metapac/stm32g030j6",]
288stm32g030k6 = [ "stm32-metapac/stm32g030k6",]
289stm32g030k8 = [ "stm32-metapac/stm32g030k8",]
290stm32g031c4 = [ "stm32-metapac/stm32g031c4",]
291stm32g031c6 = [ "stm32-metapac/stm32g031c6",]
292stm32g031c8 = [ "stm32-metapac/stm32g031c8",]
293stm32g031f4 = [ "stm32-metapac/stm32g031f4",]
294stm32g031f6 = [ "stm32-metapac/stm32g031f6",]
295stm32g031f8 = [ "stm32-metapac/stm32g031f8",]
296stm32g031g4 = [ "stm32-metapac/stm32g031g4",]
297stm32g031g6 = [ "stm32-metapac/stm32g031g6",]
298stm32g031g8 = [ "stm32-metapac/stm32g031g8",]
299stm32g031j4 = [ "stm32-metapac/stm32g031j4",]
300stm32g031j6 = [ "stm32-metapac/stm32g031j6",]
301stm32g031k4 = [ "stm32-metapac/stm32g031k4",]
302stm32g031k6 = [ "stm32-metapac/stm32g031k6",]
303stm32g031k8 = [ "stm32-metapac/stm32g031k8",]
304stm32g031y8 = [ "stm32-metapac/stm32g031y8",]
305stm32g041c6 = [ "stm32-metapac/stm32g041c6",]
306stm32g041c8 = [ "stm32-metapac/stm32g041c8",]
307stm32g041f6 = [ "stm32-metapac/stm32g041f6",]
308stm32g041f8 = [ "stm32-metapac/stm32g041f8",]
309stm32g041g6 = [ "stm32-metapac/stm32g041g6",]
310stm32g041g8 = [ "stm32-metapac/stm32g041g8",]
311stm32g041j6 = [ "stm32-metapac/stm32g041j6",]
312stm32g041k6 = [ "stm32-metapac/stm32g041k6",]
313stm32g041k8 = [ "stm32-metapac/stm32g041k8",]
314stm32g041y8 = [ "stm32-metapac/stm32g041y8",]
315stm32g050c6 = [ "stm32-metapac/stm32g050c6",]
316stm32g050c8 = [ "stm32-metapac/stm32g050c8",]
317stm32g050f6 = [ "stm32-metapac/stm32g050f6",]
318stm32g050k6 = [ "stm32-metapac/stm32g050k6",]
319stm32g050k8 = [ "stm32-metapac/stm32g050k8",]
320stm32g051c6 = [ "stm32-metapac/stm32g051c6",]
321stm32g051c8 = [ "stm32-metapac/stm32g051c8",]
322stm32g051f6 = [ "stm32-metapac/stm32g051f6",]
323stm32g051f8 = [ "stm32-metapac/stm32g051f8",]
324stm32g051g6 = [ "stm32-metapac/stm32g051g6",]
325stm32g051g8 = [ "stm32-metapac/stm32g051g8",]
326stm32g051k6 = [ "stm32-metapac/stm32g051k6",]
327stm32g051k8 = [ "stm32-metapac/stm32g051k8",]
328stm32g061c6 = [ "stm32-metapac/stm32g061c6",]
329stm32g061c8 = [ "stm32-metapac/stm32g061c8",]
330stm32g061f6 = [ "stm32-metapac/stm32g061f6",]
331stm32g061f8 = [ "stm32-metapac/stm32g061f8",]
332stm32g061g6 = [ "stm32-metapac/stm32g061g6",]
333stm32g061g8 = [ "stm32-metapac/stm32g061g8",]
334stm32g061k6 = [ "stm32-metapac/stm32g061k6",]
335stm32g061k8 = [ "stm32-metapac/stm32g061k8",]
336stm32g070cb = [ "stm32-metapac/stm32g070cb",]
337stm32g070kb = [ "stm32-metapac/stm32g070kb",]
338stm32g070rb = [ "stm32-metapac/stm32g070rb",]
339stm32g071c6 = [ "stm32-metapac/stm32g071c6",]
340stm32g071c8 = [ "stm32-metapac/stm32g071c8",]
341stm32g071cb = [ "stm32-metapac/stm32g071cb",]
342stm32g071eb = [ "stm32-metapac/stm32g071eb",]
343stm32g071g6 = [ "stm32-metapac/stm32g071g6",]
344stm32g071g8 = [ "stm32-metapac/stm32g071g8",]
345stm32g071gb = [ "stm32-metapac/stm32g071gb",]
346stm32g071k6 = [ "stm32-metapac/stm32g071k6",]
347stm32g071k8 = [ "stm32-metapac/stm32g071k8",]
348stm32g071kb = [ "stm32-metapac/stm32g071kb",]
349stm32g071r6 = [ "stm32-metapac/stm32g071r6",]
350stm32g071r8 = [ "stm32-metapac/stm32g071r8",]
351stm32g071rb = [ "stm32-metapac/stm32g071rb",]
352stm32g081cb = [ "stm32-metapac/stm32g081cb",]
353stm32g081eb = [ "stm32-metapac/stm32g081eb",]
354stm32g081gb = [ "stm32-metapac/stm32g081gb",]
355stm32g081kb = [ "stm32-metapac/stm32g081kb",]
356stm32g081rb = [ "stm32-metapac/stm32g081rb",]
357stm32g0b0ce = [ "stm32-metapac/stm32g0b0ce",]
358stm32g0b0ke = [ "stm32-metapac/stm32g0b0ke",]
359stm32g0b0re = [ "stm32-metapac/stm32g0b0re",]
360stm32g0b0ve = [ "stm32-metapac/stm32g0b0ve",]
361stm32g0b1cb = [ "stm32-metapac/stm32g0b1cb",]
362stm32g0b1cc = [ "stm32-metapac/stm32g0b1cc",]
363stm32g0b1ce = [ "stm32-metapac/stm32g0b1ce",]
364stm32g0b1kb = [ "stm32-metapac/stm32g0b1kb",]
365stm32g0b1kc = [ "stm32-metapac/stm32g0b1kc",]
366stm32g0b1ke = [ "stm32-metapac/stm32g0b1ke",]
367stm32g0b1mb = [ "stm32-metapac/stm32g0b1mb",]
368stm32g0b1mc = [ "stm32-metapac/stm32g0b1mc",]
369stm32g0b1me = [ "stm32-metapac/stm32g0b1me",]
370stm32g0b1ne = [ "stm32-metapac/stm32g0b1ne",]
371stm32g0b1rb = [ "stm32-metapac/stm32g0b1rb",]
372stm32g0b1rc = [ "stm32-metapac/stm32g0b1rc",]
373stm32g0b1re = [ "stm32-metapac/stm32g0b1re",]
374stm32g0b1vb = [ "stm32-metapac/stm32g0b1vb",]
375stm32g0b1vc = [ "stm32-metapac/stm32g0b1vc",]
376stm32g0b1ve = [ "stm32-metapac/stm32g0b1ve",]
377stm32g0c1cc = [ "stm32-metapac/stm32g0c1cc",]
378stm32g0c1ce = [ "stm32-metapac/stm32g0c1ce",]
379stm32g0c1kc = [ "stm32-metapac/stm32g0c1kc",]
380stm32g0c1ke = [ "stm32-metapac/stm32g0c1ke",]
381stm32g0c1mc = [ "stm32-metapac/stm32g0c1mc",]
382stm32g0c1me = [ "stm32-metapac/stm32g0c1me",]
383stm32g0c1ne = [ "stm32-metapac/stm32g0c1ne",]
384stm32g0c1rc = [ "stm32-metapac/stm32g0c1rc",]
385stm32g0c1re = [ "stm32-metapac/stm32g0c1re",]
386stm32g0c1vc = [ "stm32-metapac/stm32g0c1vc",]
387stm32g0c1ve = [ "stm32-metapac/stm32g0c1ve",]
284stm32h723ve = [ "stm32-metapac/stm32h723ve",] 388stm32h723ve = [ "stm32-metapac/stm32h723ve",]
285stm32h723vg = [ "stm32-metapac/stm32h723vg",] 389stm32h723vg = [ "stm32-metapac/stm32h723vg",]
286stm32h723ze = [ "stm32-metapac/stm32h723ze",] 390stm32h723ze = [ "stm32-metapac/stm32h723ze",]
diff --git a/embassy-stm32/gen_features.py b/embassy-stm32/gen_features.py
index 4eb57e2a3..bb569fd79 100644
--- a/embassy-stm32/gen_features.py
+++ b/embassy-stm32/gen_features.py
@@ -15,6 +15,7 @@ os.chdir(dname)
15supported_families = [ 15supported_families = [
16 "STM32F0", 16 "STM32F0",
17 'STM32F4', 17 'STM32F4',
18 'STM32G0',
18 'STM32L0', 19 'STM32L0',
19 'STM32L4', 20 'STM32L4',
20 'STM32H7', 21 'STM32H7',
diff --git a/embassy-stm32/src/adc/v3.rs b/embassy-stm32/src/adc/v3.rs
index db6a4e512..2781fc4dc 100644
--- a/embassy-stm32/src/adc/v3.rs
+++ b/embassy-stm32/src/adc/v3.rs
@@ -188,6 +188,7 @@ impl<'d, T: Instance> Adc<'d, T> {
188 /// Calculates the system VDDA by sampling the internal VREF channel and comparing 188 /// Calculates the system VDDA by sampling the internal VREF channel and comparing
189 /// the result with the value stored at the factory. If the chip's VDDA is not stable, run 189 /// the result with the value stored at the factory. If the chip's VDDA is not stable, run
190 /// this before each ADC conversion. 190 /// this before each ADC conversion.
191 #[cfg(not(rcc_g0))] // TODO is this supposed to be public?
191 #[allow(unused)] // TODO is this supposed to be public? 192 #[allow(unused)] // TODO is this supposed to be public?
192 fn calibrate(&mut self, vref: &mut Vref) { 193 fn calibrate(&mut self, vref: &mut Vref) {
193 let vref_cal = unsafe { crate::pac::VREFINTCAL.data().read().value() }; 194 let vref_cal = unsafe { crate::pac::VREFINTCAL.data().read().value() };
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs
index 659daa377..8e4989a3e 100644
--- a/embassy-stm32/src/exti.rs
+++ b/embassy-stm32/src/exti.rs
@@ -11,7 +11,8 @@ use embedded_hal::digital::v2::InputPin;
11use crate::gpio::{AnyPin, Input, Pin as GpioPin}; 11use crate::gpio::{AnyPin, Input, Pin as GpioPin};
12use crate::interrupt; 12use crate::interrupt;
13use crate::pac; 13use crate::pac;
14use crate::pac::{EXTI, SYSCFG}; 14use crate::pac::exti::regs::Lines;
15use crate::pac::EXTI;
15use crate::peripherals; 16use crate::peripherals;
16 17
17const EXTI_COUNT: usize = 16; 18const EXTI_COUNT: usize = 16;
@@ -28,19 +29,37 @@ fn cpu_regs() -> pac::exti::Exti {
28 EXTI 29 EXTI
29} 30}
30 31
32#[cfg(not(any(exti_g0, exti_l5)))]
33fn exticr_regs() -> pac::syscfg::Syscfg {
34 pac::SYSCFG
35}
36#[cfg(any(exti_g0, exti_l5))]
37fn exticr_regs() -> pac::exti::Exti {
38 EXTI
39}
40
31pub unsafe fn on_irq() { 41pub unsafe fn on_irq() {
32 let bits = EXTI.pr(0).read(); 42 #[cfg(not(any(exti_g0, exti_l5)))]
43 let bits = EXTI.pr(0).read().0;
44 #[cfg(any(exti_g0, exti_l5))]
45 let bits = EXTI.rpr(0).read().0 | EXTI.fpr(0).read().0;
33 46
34 // Mask all the channels that fired. 47 // Mask all the channels that fired.
35 cpu_regs().imr(0).modify(|w| w.0 &= !bits.0); 48 cpu_regs().imr(0).modify(|w| w.0 &= !bits);
36 49
37 // Wake the tasks 50 // Wake the tasks
38 for pin in BitIter(bits.0) { 51 for pin in BitIter(bits) {
39 EXTI_WAKERS[pin as usize].wake(); 52 EXTI_WAKERS[pin as usize].wake();
40 } 53 }
41 54
42 // Clear pending 55 // Clear pending
43 EXTI.pr(0).write_value(bits); 56 #[cfg(not(any(exti_g0, exti_l5)))]
57 EXTI.pr(0).write_value(Lines(bits));
58 #[cfg(any(exti_g0, exti_l5))]
59 {
60 EXTI.rpr(0).write_value(Lines(bits));
61 EXTI.fpr(0).write_value(Lines(bits));
62 }
44} 63}
45 64
46struct BitIter(u32); 65struct BitIter(u32);
@@ -117,10 +136,21 @@ impl<'a> ExtiInputFuture<'a> {
117 fn new(pin: u8, port: u8, rising: bool, falling: bool) -> Self { 136 fn new(pin: u8, port: u8, rising: bool, falling: bool) -> Self {
118 cortex_m::interrupt::free(|_| unsafe { 137 cortex_m::interrupt::free(|_| unsafe {
119 let pin = pin as usize; 138 let pin = pin as usize;
120 SYSCFG.exticr(pin / 4).modify(|w| w.set_exti(pin % 4, port)); 139 exticr_regs()
140 .exticr(pin / 4)
141 .modify(|w| w.set_exti(pin % 4, port));
121 EXTI.rtsr(0).modify(|w| w.set_line(pin, rising)); 142 EXTI.rtsr(0).modify(|w| w.set_line(pin, rising));
122 EXTI.ftsr(0).modify(|w| w.set_line(pin, falling)); 143 EXTI.ftsr(0).modify(|w| w.set_line(pin, falling));
123 EXTI.pr(0).write(|w| w.set_line(pin, true)); // clear pending bit 144
145 // clear pending bit
146 #[cfg(not(any(exti_g0, exti_l5)))]
147 EXTI.pr(0).write(|w| w.set_line(pin, true));
148 #[cfg(any(exti_g0, exti_l5))]
149 {
150 EXTI.rpr(0).write(|w| w.set_line(pin, true));
151 EXTI.fpr(0).write(|w| w.set_line(pin, true));
152 }
153
124 cpu_regs().imr(0).modify(|w| w.set_line(pin, true)); 154 cpu_regs().imr(0).modify(|w| w.set_line(pin, true));
125 }); 155 });
126 156
diff --git a/embassy-stm32/src/rcc/g0/mod.rs b/embassy-stm32/src/rcc/g0/mod.rs
new file mode 100644
index 000000000..863db709d
--- /dev/null
+++ b/embassy-stm32/src/rcc/g0/mod.rs
@@ -0,0 +1,190 @@
1pub use super::types::*;
2use crate::pac;
3use crate::peripherals::{self, RCC};
4use crate::rcc::{get_freqs, set_freqs, Clocks};
5use crate::time::Hertz;
6use crate::time::U32Ext;
7use core::marker::PhantomData;
8use embassy::util::Unborrow;
9use embassy_hal_common::unborrow;
10
11/// HSI speed
12pub const HSI_FREQ: u32 = 16_000_000;
13
14/// LSI speed
15pub const LSI_FREQ: u32 = 32_000;
16
17/// System clock mux source
18#[derive(Clone, Copy)]
19pub enum ClockSrc {
20 HSE(Hertz),
21 HSI16,
22 LSI,
23}
24
25impl Into<u8> for APBPrescaler {
26 fn into(self) -> u8 {
27 match self {
28 APBPrescaler::NotDivided => 1,
29 APBPrescaler::Div2 => 0x04,
30 APBPrescaler::Div4 => 0x05,
31 APBPrescaler::Div8 => 0x06,
32 APBPrescaler::Div16 => 0x07,
33 }
34 }
35}
36
37impl Into<u8> for AHBPrescaler {
38 fn into(self) -> u8 {
39 match self {
40 AHBPrescaler::NotDivided => 1,
41 AHBPrescaler::Div2 => 0x08,
42 AHBPrescaler::Div4 => 0x09,
43 AHBPrescaler::Div8 => 0x0a,
44 AHBPrescaler::Div16 => 0x0b,
45 AHBPrescaler::Div64 => 0x0c,
46 AHBPrescaler::Div128 => 0x0d,
47 AHBPrescaler::Div256 => 0x0e,
48 AHBPrescaler::Div512 => 0x0f,
49 }
50 }
51}
52
53/// Clocks configutation
54pub struct Config {
55 mux: ClockSrc,
56 ahb_pre: AHBPrescaler,
57 apb_pre: APBPrescaler,
58}
59
60impl Default for Config {
61 #[inline]
62 fn default() -> Config {
63 Config {
64 mux: ClockSrc::HSI16,
65 ahb_pre: AHBPrescaler::NotDivided,
66 apb_pre: APBPrescaler::NotDivided,
67 }
68 }
69}
70
71impl Config {
72 #[inline]
73 pub fn clock_src(mut self, mux: ClockSrc) -> Self {
74 self.mux = mux;
75 self
76 }
77
78 #[inline]
79 pub fn ahb_pre(mut self, pre: AHBPrescaler) -> Self {
80 self.ahb_pre = pre;
81 self
82 }
83
84 #[inline]
85 pub fn apb_pre(mut self, pre: APBPrescaler) -> Self {
86 self.apb_pre = pre;
87 self
88 }
89}
90
91/// RCC peripheral
92pub struct Rcc<'d> {
93 _rb: peripherals::RCC,
94 phantom: PhantomData<&'d mut peripherals::RCC>,
95}
96
97impl<'d> Rcc<'d> {
98 pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self {
99 unborrow!(rcc);
100 Self {
101 _rb: rcc,
102 phantom: PhantomData,
103 }
104 }
105
106 // Safety: RCC init must have been called
107 pub fn clocks(&self) -> &'static Clocks {
108 unsafe { get_freqs() }
109 }
110}
111
112/// Extension trait that freezes the `RCC` peripheral with provided clocks configuration
113pub trait RccExt {
114 fn freeze(self, config: Config) -> Clocks;
115}
116
117impl RccExt for RCC {
118 #[inline]
119 fn freeze(self, cfgr: Config) -> Clocks {
120 let rcc = pac::RCC;
121 let (sys_clk, sw) = match cfgr.mux {
122 ClockSrc::HSI16 => {
123 // Enable HSI16
124 unsafe {
125 rcc.cr().write(|w| w.set_hsion(true));
126 while !rcc.cr().read().hsirdy() {}
127 }
128
129 (HSI_FREQ, 0x00)
130 }
131 ClockSrc::HSE(freq) => {
132 // Enable HSE
133 unsafe {
134 rcc.cr().write(|w| w.set_hseon(true));
135 while !rcc.cr().read().hserdy() {}
136 }
137
138 (freq.0, 0x01)
139 }
140 ClockSrc::LSI => {
141 // Enable LSI
142 unsafe {
143 rcc.csr().write(|w| w.set_lsion(true));
144 while !rcc.csr().read().lsirdy() {}
145 }
146 (LSI_FREQ, 0x03)
147 }
148 };
149
150 unsafe {
151 rcc.cfgr().modify(|w| {
152 w.set_sw(sw.into());
153 w.set_hpre(cfgr.ahb_pre.into());
154 w.set_ppre(cfgr.apb_pre.into());
155 });
156 }
157
158 let ahb_freq: u32 = match cfgr.ahb_pre {
159 AHBPrescaler::NotDivided => sys_clk,
160 pre => {
161 let pre: u8 = pre.into();
162 let pre = 1 << (pre as u32 - 7);
163 sys_clk / pre
164 }
165 };
166
167 let (apb_freq, apb_tim_freq) = match cfgr.apb_pre {
168 APBPrescaler::NotDivided => (ahb_freq, ahb_freq),
169 pre => {
170 let pre: u8 = pre.into();
171 let pre: u8 = 1 << (pre - 3);
172 let freq = ahb_freq / pre as u32;
173 (freq, freq * 2)
174 }
175 };
176
177 Clocks {
178 sys: sys_clk.hz(),
179 ahb: ahb_freq.hz(),
180 apb: apb_freq.hz(),
181 apb_tim: apb_tim_freq.hz(),
182 }
183 }
184}
185
186pub unsafe fn init(config: Config) {
187 let r = <peripherals::RCC as embassy::util::Steal>::steal();
188 let clocks = r.freeze(config);
189 set_freqs(clocks);
190}
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs
index 9c8da4a98..791b86c0d 100644
--- a/embassy-stm32/src/rcc/mod.rs
+++ b/embassy-stm32/src/rcc/mod.rs
@@ -8,15 +8,26 @@ mod types;
8#[derive(Clone, Copy)] 8#[derive(Clone, Copy)]
9pub struct Clocks { 9pub struct Clocks {
10 pub sys: Hertz, 10 pub sys: Hertz,
11
12 #[cfg(rcc_g0)]
13 pub apb: Hertz,
14 #[cfg(rcc_g0)]
15 pub apb_tim: Hertz,
16
17 #[cfg(not(rcc_g0))]
11 pub apb1: Hertz, 18 pub apb1: Hertz,
19 #[cfg(not(rcc_g0))]
20 pub apb1_tim: Hertz,
21
22 #[cfg(not(rcc_g0))]
12 pub apb2: Hertz, 23 pub apb2: Hertz,
24 #[cfg(not(rcc_g0))]
25 pub apb2_tim: Hertz,
26
13 #[cfg(rcc_wl5)] 27 #[cfg(rcc_wl5)]
14 pub apb3: Hertz, 28 pub apb3: Hertz,
15 29
16 pub apb1_tim: Hertz, 30 #[cfg(any(rcc_l0, rcc_f0, rcc_f0x0, rcc_g0))]
17 pub apb2_tim: Hertz,
18
19 #[cfg(any(rcc_l0, rcc_f0, rcc_f0x0))]
20 pub ahb: Hertz, 31 pub ahb: Hertz,
21 32
22 #[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb, rcc_wl5))] 33 #[cfg(any(rcc_l4, rcc_f4, rcc_h7, rcc_wb, rcc_wl5))]
@@ -77,6 +88,9 @@ cfg_if::cfg_if! {
77 } else if #[cfg(any(rcc_f0, rcc_f0x0))] { 88 } else if #[cfg(any(rcc_f0, rcc_f0x0))] {
78 mod f0; 89 mod f0;
79 pub use f0::*; 90 pub use f0::*;
91 } else if #[cfg(any(rcc_g0))] {
92 mod g0;
93 pub use g0::*;
80 } 94 }
81} 95}
82 96
diff --git a/examples/stm32g0/.cargo/config.toml b/examples/stm32g0/.cargo/config.toml
new file mode 100644
index 000000000..1f7c3ecdd
--- /dev/null
+++ b/examples/stm32g0/.cargo/config.toml
@@ -0,0 +1,18 @@
1[target.'cfg(all(target_arch = "arm", target_os = "none"))']
2# replace STM32G071C8Rx with your chip as listed in `probe-run --list-chips`
3runner = "probe-run --chip STM32G071RBTx"
4
5rustflags = [
6 # LLD (shipped with the Rust toolchain) is used as the default linker
7 "-C", "link-arg=--nmagic",
8 "-C", "link-arg=-Tlink.x",
9 "-C", "link-arg=-Tdefmt.x",
10
11 # Code-size optimizations.
12 "-Z", "trap-unreachable=no",
13 "-C", "inline-threshold=5",
14 "-C", "no-vectorize-loops",
15]
16
17[build]
18target = "thumbv6m-none-eabi"
diff --git a/examples/stm32g0/Cargo.toml b/examples/stm32g0/Cargo.toml
new file mode 100644
index 000000000..83f535b91
--- /dev/null
+++ b/examples/stm32g0/Cargo.toml
@@ -0,0 +1,34 @@
1[package]
2authors = ["Dario Nieuwenhuis <[email protected]>", "Ben Gamari <[email protected]>"]
3edition = "2018"
4name = "embassy-stm32g0-examples"
5version = "0.1.0"
6resolver = "2"
7
8[features]
9default = [
10 "defmt-default",
11]
12defmt-default = []
13defmt-trace = []
14defmt-debug = []
15defmt-info = []
16defmt-warn = []
17defmt-error = []
18
19[dependencies]
20embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-trace"] }
21embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features = ["defmt"] }
22embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "defmt-trace", "time-driver-tim2", "stm32g071rb", "unstable-pac"] }
23embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" }
24
25defmt = "0.2.0"
26defmt-rtt = "0.2.0"
27
28cortex-m = "0.7.1"
29cortex-m-rt = "0.7.0"
30embedded-hal = { version = "0.2.4" }
31panic-probe = { version = "0.2.0", features= ["print-defmt"] }
32futures = { version = "0.3.8", default-features = false, features = ["async-await"] }
33rtt-target = { version = "0.3", features = ["cortex-m"] }
34heapless = { version = "0.7.1", default-features = false }
diff --git a/examples/stm32g0/build.rs b/examples/stm32g0/build.rs
new file mode 100644
index 000000000..d534cc3df
--- /dev/null
+++ b/examples/stm32g0/build.rs
@@ -0,0 +1,31 @@
1//! This build script copies the `memory.x` file from the crate root into
2//! a directory where the linker can always find it at build time.
3//! For many projects this is optional, as the linker always searches the
4//! project root directory -- wherever `Cargo.toml` is. However, if you
5//! are using a workspace or have a more complicated build setup, this
6//! build script becomes required. Additionally, by requesting that
7//! Cargo re-run the build script whenever `memory.x` is changed,
8//! updating `memory.x` ensures a rebuild of the application with the
9//! new memory settings.
10
11use std::env;
12use std::fs::File;
13use std::io::Write;
14use std::path::PathBuf;
15
16fn main() {
17 // Put `memory.x` in our output directory and ensure it's
18 // on the linker search path.
19 let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
20 File::create(out.join("memory.x"))
21 .unwrap()
22 .write_all(include_bytes!("memory.x"))
23 .unwrap();
24 println!("cargo:rustc-link-search={}", out.display());
25
26 // By default, Cargo will re-run a build script whenever
27 // any file in the project changes. By specifying `memory.x`
28 // here, we ensure the build script is only re-run when
29 // `memory.x` is changed.
30 println!("cargo:rerun-if-changed=memory.x");
31}
diff --git a/examples/stm32g0/memory.x b/examples/stm32g0/memory.x
new file mode 100644
index 000000000..02d59c83f
--- /dev/null
+++ b/examples/stm32g0/memory.x
@@ -0,0 +1,7 @@
1MEMORY
2{
3 /* NOTE 1 K = 1 KiBi = 1024 bytes */
4 /* These values correspond to the STM32G071C8 */
5 FLASH : ORIGIN = 0x08000000, LENGTH = 64K
6 RAM : ORIGIN = 0x20000000, LENGTH = 36K
7}
diff --git a/examples/stm32g0/src/bin/blinky.rs b/examples/stm32g0/src/bin/blinky.rs
new file mode 100644
index 000000000..a30887f7d
--- /dev/null
+++ b/examples/stm32g0/src/bin/blinky.rs
@@ -0,0 +1,31 @@
1#![no_std]
2#![no_main]
3#![feature(trait_alias)]
4#![feature(type_alias_impl_trait)]
5#![allow(incomplete_features)]
6
7#[path = "../example_common.rs"]
8mod example_common;
9use embassy::executor::Spawner;
10use embassy::time::{Duration, Timer};
11use embassy_stm32::gpio::{Level, Output, Speed};
12use embassy_stm32::Peripherals;
13use embedded_hal::digital::v2::OutputPin;
14use example_common::*;
15
16#[embassy::main]
17async fn main(_spawner: Spawner, p: Peripherals) {
18 info!("Hello World!");
19
20 let mut led = Output::new(p.PB7, Level::High, Speed::Low);
21
22 loop {
23 info!("high");
24 unwrap!(led.set_high());
25 Timer::after(Duration::from_millis(300)).await;
26
27 info!("low");
28 unwrap!(led.set_low());
29 Timer::after(Duration::from_millis(300)).await;
30 }
31}
diff --git a/examples/stm32g0/src/bin/button.rs b/examples/stm32g0/src/bin/button.rs
new file mode 100644
index 000000000..a834b2fce
--- /dev/null
+++ b/examples/stm32g0/src/bin/button.rs
@@ -0,0 +1,29 @@
1#![no_std]
2#![no_main]
3#![feature(trait_alias)]
4#![feature(type_alias_impl_trait)]
5#![allow(incomplete_features)]
6
7#[path = "../example_common.rs"]
8mod example_common;
9use cortex_m_rt::entry;
10use embassy_stm32::gpio::{Input, Pull};
11use embedded_hal::digital::v2::InputPin;
12use example_common::*;
13
14#[entry]
15fn main() -> ! {
16 info!("Hello World!");
17
18 let p = embassy_stm32::init(Default::default());
19
20 let button = Input::new(p.PC13, Pull::Up);
21
22 loop {
23 if unwrap!(button.is_high()) {
24 info!("high");
25 } else {
26 info!("low");
27 }
28 }
29}
diff --git a/examples/stm32g0/src/bin/button_exti.rs b/examples/stm32g0/src/bin/button_exti.rs
new file mode 100644
index 000000000..c55d6408c
--- /dev/null
+++ b/examples/stm32g0/src/bin/button_exti.rs
@@ -0,0 +1,31 @@
1#![no_std]
2#![no_main]
3#![feature(trait_alias)]
4#![feature(type_alias_impl_trait)]
5#![allow(incomplete_features)]
6
7#[path = "../example_common.rs"]
8mod example_common;
9use embassy::executor::Spawner;
10use embassy_stm32::exti::ExtiInput;
11use embassy_stm32::gpio::{Input, Pull};
12use embassy_stm32::Peripherals;
13use embassy_traits::gpio::{WaitForFallingEdge, WaitForRisingEdge};
14use example_common::*;
15
16#[embassy::main]
17async fn main(_spawner: Spawner, p: Peripherals) {
18 info!("Hello World!");
19
20 let button = Input::new(p.PC13, Pull::Up);
21 let mut button = ExtiInput::new(button, p.EXTI13);
22
23 info!("Press the USER button...");
24
25 loop {
26 button.wait_for_falling_edge().await;
27 info!("Pressed!");
28 button.wait_for_rising_edge().await;
29 info!("Released!");
30 }
31}
diff --git a/examples/stm32g0/src/example_common.rs b/examples/stm32g0/src/example_common.rs
new file mode 100644
index 000000000..54d633837
--- /dev/null
+++ b/examples/stm32g0/src/example_common.rs
@@ -0,0 +1,17 @@
1#![macro_use]
2
3use defmt_rtt as _; // global logger
4use panic_probe as _;
5
6pub use defmt::*;
7
8use core::sync::atomic::{AtomicUsize, Ordering};
9
10defmt::timestamp! {"{=u64}", {
11 static COUNT: AtomicUsize = AtomicUsize::new(0);
12 // NOTE(no-CAS) `timestamps` runs with interrupts disabled
13 let n = COUNT.load(Ordering::Relaxed);
14 COUNT.store(n + 1, Ordering::Relaxed);
15 n as u64
16 }
17}
diff --git a/stm32-data b/stm32-data
Subproject 12be5f3da4ba38850d94ab865d2b920bd936300 Subproject bf50912000cd6c24ef5cb8cc7a0372a11645712
diff --git a/stm32-metapac-gen/src/lib.rs b/stm32-metapac-gen/src/lib.rs
index 8646accfa..390793a5d 100644
--- a/stm32-metapac-gen/src/lib.rs
+++ b/stm32-metapac-gen/src/lib.rs
@@ -444,7 +444,9 @@ pub fn gen(options: Options) {
444 Some(clock) => clock.as_str(), 444 Some(clock) => clock.as_str(),
445 None => { 445 None => {
446 // No clock was specified, derive the clock name from the enable register name. 446 // No clock was specified, derive the clock name from the enable register name.
447 Regex::new("([A-Z]+\\d*).*") 447 // N.B. STM32G0 has only one APB bus but split ENR registers
448 // (e.g. APBENR1).
449 Regex::new("([A-Z]+\\d*)ENR\\d*")
448 .unwrap() 450 .unwrap()
449 .captures(enable_reg) 451 .captures(enable_reg)
450 .unwrap() 452 .unwrap()