aboutsummaryrefslogtreecommitdiff
path: root/embassy-stm32/src
diff options
context:
space:
mode:
authorBen Gamari <[email protected]>2021-07-30 16:48:13 -0400
committerDario Nieuwenhuis <[email protected]>2021-08-20 00:15:11 +0200
commite2f71ffbbdeac4f64b0468fc7e93452388c16eee (patch)
treec88ac34d8a25021a0257966bf8aa3b918c8ac374 /embassy-stm32/src
parent174c51f09707b8a475382071f99e0d9c44f93ab7 (diff)
Add support for STM32G0
Diffstat (limited to 'embassy-stm32/src')
-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
4 files changed, 246 insertions, 11 deletions
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