diff options
| -rw-r--r-- | .github/workflows/rust.yml | 2 | ||||
| -rw-r--r-- | embassy-stm32/Cargo.toml | 96 | ||||
| -rw-r--r-- | embassy-stm32/src/exti.rs | 10 | ||||
| -rw-r--r-- | embassy-stm32/src/gpio.rs | 135 | ||||
| -rw-r--r-- | embassy-stm32/src/i2c/mod.rs | 1 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/f1/mod.rs | 214 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 5 | ||||
| -rw-r--r-- | embassy-stm32/src/usart/mod.rs | 1 | ||||
| -rw-r--r-- | examples/stm32f1/.cargo/config.toml | 18 | ||||
| -rw-r--r-- | examples/stm32f1/Cargo.toml | 35 | ||||
| -rw-r--r-- | examples/stm32f1/src/bin/blinky.rs | 29 | ||||
| -rw-r--r-- | examples/stm32f1/src/bin/hello.rs | 27 | ||||
| -rw-r--r-- | examples/stm32f1/src/example_common.rs | 17 | ||||
| -rw-r--r-- | stm32-gen-features/src/lib.rs | 3 |
14 files changed, 573 insertions, 20 deletions
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 5cdf75d7b..b728c0db8 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml | |||
| @@ -101,6 +101,8 @@ jobs: | |||
| 101 | target: thumbv6m-none-eabi | 101 | target: thumbv6m-none-eabi |
| 102 | - package: examples/wasm | 102 | - package: examples/wasm |
| 103 | target: wasm32-unknown-unknown | 103 | target: wasm32-unknown-unknown |
| 104 | - package: examples/stm32f1 | ||
| 105 | target: thumbv7m-none-eabi | ||
| 104 | steps: | 106 | steps: |
| 105 | - uses: actions/checkout@v2 | 107 | - uses: actions/checkout@v2 |
| 106 | with: | 108 | with: |
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index aedb54b74..6881f13e8 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -28,6 +28,7 @@ stm32-metapac = { version = "0.1.0", path = "../stm32-metapac", features = ["rt" | |||
| 28 | vcell = { version = "0.1.3", optional = true } | 28 | vcell = { version = "0.1.3", optional = true } |
| 29 | bxcan = "0.5.1" | 29 | bxcan = "0.5.1" |
| 30 | seq-macro = "0.2.2" | 30 | seq-macro = "0.2.2" |
| 31 | cast = { version = "0.2.2", default-features = false } | ||
| 31 | 32 | ||
| 32 | cfg-if = "1.0.0" | 33 | cfg-if = "1.0.0" |
| 33 | 34 | ||
| @@ -134,6 +135,101 @@ stm32f091vc = [ "stm32-metapac/stm32f091vc" ] | |||
| 134 | stm32f098cc = [ "stm32-metapac/stm32f098cc" ] | 135 | stm32f098cc = [ "stm32-metapac/stm32f098cc" ] |
| 135 | stm32f098rc = [ "stm32-metapac/stm32f098rc" ] | 136 | stm32f098rc = [ "stm32-metapac/stm32f098rc" ] |
| 136 | stm32f098vc = [ "stm32-metapac/stm32f098vc" ] | 137 | stm32f098vc = [ "stm32-metapac/stm32f098vc" ] |
| 138 | stm32f100c4 = [ "stm32-metapac/stm32f100c4" ] | ||
| 139 | stm32f100c6 = [ "stm32-metapac/stm32f100c6" ] | ||
| 140 | stm32f100c8 = [ "stm32-metapac/stm32f100c8" ] | ||
| 141 | stm32f100cb = [ "stm32-metapac/stm32f100cb" ] | ||
| 142 | stm32f100r4 = [ "stm32-metapac/stm32f100r4" ] | ||
| 143 | stm32f100r6 = [ "stm32-metapac/stm32f100r6" ] | ||
| 144 | stm32f100r8 = [ "stm32-metapac/stm32f100r8" ] | ||
| 145 | stm32f100rb = [ "stm32-metapac/stm32f100rb" ] | ||
| 146 | stm32f100rc = [ "stm32-metapac/stm32f100rc" ] | ||
| 147 | stm32f100rd = [ "stm32-metapac/stm32f100rd" ] | ||
| 148 | stm32f100re = [ "stm32-metapac/stm32f100re" ] | ||
| 149 | stm32f100v8 = [ "stm32-metapac/stm32f100v8" ] | ||
| 150 | stm32f100vb = [ "stm32-metapac/stm32f100vb" ] | ||
| 151 | stm32f100vc = [ "stm32-metapac/stm32f100vc" ] | ||
| 152 | stm32f100vd = [ "stm32-metapac/stm32f100vd" ] | ||
| 153 | stm32f100ve = [ "stm32-metapac/stm32f100ve" ] | ||
| 154 | stm32f100zc = [ "stm32-metapac/stm32f100zc" ] | ||
| 155 | stm32f100zd = [ "stm32-metapac/stm32f100zd" ] | ||
| 156 | stm32f100ze = [ "stm32-metapac/stm32f100ze" ] | ||
| 157 | stm32f101c4 = [ "stm32-metapac/stm32f101c4" ] | ||
| 158 | stm32f101c6 = [ "stm32-metapac/stm32f101c6" ] | ||
| 159 | stm32f101c8 = [ "stm32-metapac/stm32f101c8" ] | ||
| 160 | stm32f101cb = [ "stm32-metapac/stm32f101cb" ] | ||
| 161 | stm32f101r4 = [ "stm32-metapac/stm32f101r4" ] | ||
| 162 | stm32f101r6 = [ "stm32-metapac/stm32f101r6" ] | ||
| 163 | stm32f101r8 = [ "stm32-metapac/stm32f101r8" ] | ||
| 164 | stm32f101rb = [ "stm32-metapac/stm32f101rb" ] | ||
| 165 | stm32f101rc = [ "stm32-metapac/stm32f101rc" ] | ||
| 166 | stm32f101rd = [ "stm32-metapac/stm32f101rd" ] | ||
| 167 | stm32f101re = [ "stm32-metapac/stm32f101re" ] | ||
| 168 | stm32f101rf = [ "stm32-metapac/stm32f101rf" ] | ||
| 169 | stm32f101rg = [ "stm32-metapac/stm32f101rg" ] | ||
| 170 | stm32f101t4 = [ "stm32-metapac/stm32f101t4" ] | ||
| 171 | stm32f101t6 = [ "stm32-metapac/stm32f101t6" ] | ||
| 172 | stm32f101t8 = [ "stm32-metapac/stm32f101t8" ] | ||
| 173 | stm32f101tb = [ "stm32-metapac/stm32f101tb" ] | ||
| 174 | stm32f101v8 = [ "stm32-metapac/stm32f101v8" ] | ||
| 175 | stm32f101vb = [ "stm32-metapac/stm32f101vb" ] | ||
| 176 | stm32f101vc = [ "stm32-metapac/stm32f101vc" ] | ||
| 177 | stm32f101vd = [ "stm32-metapac/stm32f101vd" ] | ||
| 178 | stm32f101ve = [ "stm32-metapac/stm32f101ve" ] | ||
| 179 | stm32f101vf = [ "stm32-metapac/stm32f101vf" ] | ||
| 180 | stm32f101vg = [ "stm32-metapac/stm32f101vg" ] | ||
| 181 | stm32f101zc = [ "stm32-metapac/stm32f101zc" ] | ||
| 182 | stm32f101zd = [ "stm32-metapac/stm32f101zd" ] | ||
| 183 | stm32f101ze = [ "stm32-metapac/stm32f101ze" ] | ||
| 184 | stm32f101zf = [ "stm32-metapac/stm32f101zf" ] | ||
| 185 | stm32f101zg = [ "stm32-metapac/stm32f101zg" ] | ||
| 186 | stm32f102c4 = [ "stm32-metapac/stm32f102c4" ] | ||
| 187 | stm32f102c6 = [ "stm32-metapac/stm32f102c6" ] | ||
| 188 | stm32f102c8 = [ "stm32-metapac/stm32f102c8" ] | ||
| 189 | stm32f102cb = [ "stm32-metapac/stm32f102cb" ] | ||
| 190 | stm32f102r4 = [ "stm32-metapac/stm32f102r4" ] | ||
| 191 | stm32f102r6 = [ "stm32-metapac/stm32f102r6" ] | ||
| 192 | stm32f102r8 = [ "stm32-metapac/stm32f102r8" ] | ||
| 193 | stm32f102rb = [ "stm32-metapac/stm32f102rb" ] | ||
| 194 | stm32f103c4 = [ "stm32-metapac/stm32f103c4" ] | ||
| 195 | stm32f103c6 = [ "stm32-metapac/stm32f103c6" ] | ||
| 196 | stm32f103c8 = [ "stm32-metapac/stm32f103c8" ] | ||
| 197 | stm32f103cb = [ "stm32-metapac/stm32f103cb" ] | ||
| 198 | stm32f103r4 = [ "stm32-metapac/stm32f103r4" ] | ||
| 199 | stm32f103r6 = [ "stm32-metapac/stm32f103r6" ] | ||
| 200 | stm32f103r8 = [ "stm32-metapac/stm32f103r8" ] | ||
| 201 | stm32f103rb = [ "stm32-metapac/stm32f103rb" ] | ||
| 202 | stm32f103rc = [ "stm32-metapac/stm32f103rc" ] | ||
| 203 | stm32f103rd = [ "stm32-metapac/stm32f103rd" ] | ||
| 204 | stm32f103re = [ "stm32-metapac/stm32f103re" ] | ||
| 205 | stm32f103rf = [ "stm32-metapac/stm32f103rf" ] | ||
| 206 | stm32f103rg = [ "stm32-metapac/stm32f103rg" ] | ||
| 207 | stm32f103t4 = [ "stm32-metapac/stm32f103t4" ] | ||
| 208 | stm32f103t6 = [ "stm32-metapac/stm32f103t6" ] | ||
| 209 | stm32f103t8 = [ "stm32-metapac/stm32f103t8" ] | ||
| 210 | stm32f103tb = [ "stm32-metapac/stm32f103tb" ] | ||
| 211 | stm32f103v8 = [ "stm32-metapac/stm32f103v8" ] | ||
| 212 | stm32f103vb = [ "stm32-metapac/stm32f103vb" ] | ||
| 213 | stm32f103vc = [ "stm32-metapac/stm32f103vc" ] | ||
| 214 | stm32f103vd = [ "stm32-metapac/stm32f103vd" ] | ||
| 215 | stm32f103ve = [ "stm32-metapac/stm32f103ve" ] | ||
| 216 | stm32f103vf = [ "stm32-metapac/stm32f103vf" ] | ||
| 217 | stm32f103vg = [ "stm32-metapac/stm32f103vg" ] | ||
| 218 | stm32f103zc = [ "stm32-metapac/stm32f103zc" ] | ||
| 219 | stm32f103zd = [ "stm32-metapac/stm32f103zd" ] | ||
| 220 | stm32f103ze = [ "stm32-metapac/stm32f103ze" ] | ||
| 221 | stm32f103zf = [ "stm32-metapac/stm32f103zf" ] | ||
| 222 | stm32f103zg = [ "stm32-metapac/stm32f103zg" ] | ||
| 223 | stm32f105r8 = [ "stm32-metapac/stm32f105r8" ] | ||
| 224 | stm32f105rb = [ "stm32-metapac/stm32f105rb" ] | ||
| 225 | stm32f105rc = [ "stm32-metapac/stm32f105rc" ] | ||
| 226 | stm32f105v8 = [ "stm32-metapac/stm32f105v8" ] | ||
| 227 | stm32f105vb = [ "stm32-metapac/stm32f105vb" ] | ||
| 228 | stm32f105vc = [ "stm32-metapac/stm32f105vc" ] | ||
| 229 | stm32f107rb = [ "stm32-metapac/stm32f107rb" ] | ||
| 230 | stm32f107rc = [ "stm32-metapac/stm32f107rc" ] | ||
| 231 | stm32f107vb = [ "stm32-metapac/stm32f107vb" ] | ||
| 232 | stm32f107vc = [ "stm32-metapac/stm32f107vc" ] | ||
| 137 | stm32f401cb = [ "stm32-metapac/stm32f401cb" ] | 233 | stm32f401cb = [ "stm32-metapac/stm32f401cb" ] |
| 138 | stm32f401cc = [ "stm32-metapac/stm32f401cc" ] | 234 | stm32f401cc = [ "stm32-metapac/stm32f401cc" ] |
| 139 | stm32f401cd = [ "stm32-metapac/stm32f401cd" ] | 235 | stm32f401cd = [ "stm32-metapac/stm32f401cd" ] |
diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs index 6d3de3a15..565b92f32 100644 --- a/embassy-stm32/src/exti.rs +++ b/embassy-stm32/src/exti.rs | |||
| @@ -30,7 +30,7 @@ fn cpu_regs() -> pac::exti::Exti { | |||
| 30 | EXTI | 30 | EXTI |
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | #[cfg(not(any(exti_g0, exti_l5)))] | 33 | #[cfg(not(any(exti_g0, exti_l5, gpio_v1)))] |
| 34 | fn exticr_regs() -> pac::syscfg::Syscfg { | 34 | fn exticr_regs() -> pac::syscfg::Syscfg { |
| 35 | pac::SYSCFG | 35 | pac::SYSCFG |
| 36 | } | 36 | } |
| @@ -38,6 +38,10 @@ fn exticr_regs() -> pac::syscfg::Syscfg { | |||
| 38 | fn exticr_regs() -> pac::exti::Exti { | 38 | fn exticr_regs() -> pac::exti::Exti { |
| 39 | EXTI | 39 | EXTI |
| 40 | } | 40 | } |
| 41 | #[cfg(gpio_v1)] | ||
| 42 | fn exticr_regs() -> pac::afio::Afio { | ||
| 43 | pac::AFIO | ||
| 44 | } | ||
| 41 | 45 | ||
| 42 | pub unsafe fn on_irq() { | 46 | pub unsafe fn on_irq() { |
| 43 | #[cfg(not(any(exti_g0, exti_l5)))] | 47 | #[cfg(not(any(exti_g0, exti_l5)))] |
| @@ -296,6 +300,8 @@ pub(crate) unsafe fn init() { | |||
| 296 | 300 | ||
| 297 | foreach_exti_irq!(enable_irq); | 301 | foreach_exti_irq!(enable_irq); |
| 298 | 302 | ||
| 299 | #[cfg(not(any(rcc_wb, rcc_wl5)))] | 303 | #[cfg(not(any(rcc_wb, rcc_wl5, rcc_f1)))] |
| 300 | <crate::peripherals::SYSCFG as crate::rcc::sealed::RccPeripheral>::enable(); | 304 | <crate::peripherals::SYSCFG as crate::rcc::sealed::RccPeripheral>::enable(); |
| 305 | #[cfg(rcc_f1)] | ||
| 306 | <crate::peripherals::AFIO as crate::rcc::sealed::RccPeripheral>::enable(); | ||
| 301 | } | 307 | } |
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index a67d4e73f..c7b644e94 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs | |||
| @@ -18,6 +18,7 @@ pub enum Pull { | |||
| 18 | Down, | 18 | Down, |
| 19 | } | 19 | } |
| 20 | 20 | ||
| 21 | #[cfg(gpio_v2)] | ||
| 21 | impl From<Pull> for vals::Pupdr { | 22 | impl From<Pull> for vals::Pupdr { |
| 22 | fn from(pull: Pull) -> Self { | 23 | fn from(pull: Pull) -> Self { |
| 23 | use Pull::*; | 24 | use Pull::*; |
| @@ -36,11 +37,25 @@ impl From<Pull> for vals::Pupdr { | |||
| 36 | pub enum Speed { | 37 | pub enum Speed { |
| 37 | Low, | 38 | Low, |
| 38 | Medium, | 39 | Medium, |
| 39 | #[cfg(not(syscfg_f0))] | 40 | #[cfg(not(any(syscfg_f0, gpio_v1)))] |
| 40 | High, | 41 | High, |
| 41 | VeryHigh, | 42 | VeryHigh, |
| 42 | } | 43 | } |
| 43 | 44 | ||
| 45 | #[cfg(gpio_v1)] | ||
| 46 | impl From<Speed> for vals::Mode { | ||
| 47 | fn from(speed: Speed) -> Self { | ||
| 48 | use Speed::*; | ||
| 49 | |||
| 50 | match speed { | ||
| 51 | Low => vals::Mode::OUTPUT2, | ||
| 52 | Medium => vals::Mode::OUTPUT, | ||
| 53 | VeryHigh => vals::Mode::OUTPUT50, | ||
| 54 | } | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | #[cfg(gpio_v2)] | ||
| 44 | impl From<Speed> for vals::Ospeedr { | 59 | impl From<Speed> for vals::Ospeedr { |
| 45 | fn from(speed: Speed) -> Self { | 60 | fn from(speed: Speed) -> Self { |
| 46 | use Speed::*; | 61 | use Speed::*; |
| @@ -68,9 +83,29 @@ impl<'d, T: Pin> Input<'d, T> { | |||
| 68 | cortex_m::interrupt::free(|_| unsafe { | 83 | cortex_m::interrupt::free(|_| unsafe { |
| 69 | let r = pin.block(); | 84 | let r = pin.block(); |
| 70 | let n = pin.pin() as usize; | 85 | let n = pin.pin() as usize; |
| 71 | r.pupdr().modify(|w| w.set_pupdr(n, pull.into())); | 86 | #[cfg(gpio_v1)] |
| 72 | r.otyper().modify(|w| w.set_ot(n, vals::Ot::PUSHPULL)); | 87 | { |
| 73 | r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT)); | 88 | let crlh = if n < 8 { 0 } else { 1 }; |
| 89 | match pull { | ||
| 90 | Pull::Up => r.bsrr().write(|w| w.set_bs(n, true)), | ||
| 91 | Pull::Down => r.bsrr().write(|w| w.set_br(n, true)), | ||
| 92 | Pull::None => {} | ||
| 93 | } | ||
| 94 | if pull == Pull::None { | ||
| 95 | r.cr(crlh) | ||
| 96 | .modify(|w| w.set_cnf(n % 8, vals::Cnf::OPENDRAIN)); | ||
| 97 | } else { | ||
| 98 | r.cr(crlh) | ||
| 99 | .modify(|w| w.set_cnf(n % 8, vals::Cnf::ALTPUSHPULL)); | ||
| 100 | } | ||
| 101 | r.cr(crlh).modify(|w| w.set_mode(n % 8, vals::Mode::INPUT)); | ||
| 102 | } | ||
| 103 | #[cfg(gpio_v2)] | ||
| 104 | { | ||
| 105 | r.pupdr().modify(|w| w.set_pupdr(n, pull.into())); | ||
| 106 | r.otyper().modify(|w| w.set_ot(n, vals::Ot::PUSHPULL)); | ||
| 107 | r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT)); | ||
| 108 | } | ||
| 74 | }); | 109 | }); |
| 75 | 110 | ||
| 76 | Self { | 111 | Self { |
| @@ -85,6 +120,13 @@ impl<'d, T: Pin> Drop for Input<'d, T> { | |||
| 85 | cortex_m::interrupt::free(|_| unsafe { | 120 | cortex_m::interrupt::free(|_| unsafe { |
| 86 | let r = self.pin.block(); | 121 | let r = self.pin.block(); |
| 87 | let n = self.pin.pin() as usize; | 122 | let n = self.pin.pin() as usize; |
| 123 | #[cfg(gpio_v1)] | ||
| 124 | { | ||
| 125 | let crlh = if n < 8 { 0 } else { 1 }; | ||
| 126 | r.cr(crlh) | ||
| 127 | .modify(|w| w.set_cnf(n % 8, vals::Cnf::OPENDRAIN)); | ||
| 128 | } | ||
| 129 | #[cfg(gpio_v2)] | ||
| 88 | r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING)); | 130 | r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING)); |
| 89 | }); | 131 | }); |
| 90 | } | 132 | } |
| @@ -129,10 +171,19 @@ impl<'d, T: Pin> Output<'d, T> { | |||
| 129 | cortex_m::interrupt::free(|_| unsafe { | 171 | cortex_m::interrupt::free(|_| unsafe { |
| 130 | let r = pin.block(); | 172 | let r = pin.block(); |
| 131 | let n = pin.pin() as usize; | 173 | let n = pin.pin() as usize; |
| 132 | r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING)); | 174 | #[cfg(gpio_v1)] |
| 133 | r.otyper().modify(|w| w.set_ot(n, vals::Ot::PUSHPULL)); | 175 | { |
| 134 | pin.set_speed(speed); | 176 | let crlh = if n < 8 { 0 } else { 1 }; |
| 135 | r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT)); | 177 | r.cr(crlh).modify(|w| w.set_cnf(n % 8, vals::Cnf::PUSHPULL)); |
| 178 | r.cr(crlh).modify(|w| w.set_mode(n % 8, speed.into())); | ||
| 179 | } | ||
| 180 | #[cfg(gpio_v2)] | ||
| 181 | { | ||
| 182 | r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING)); | ||
| 183 | r.otyper().modify(|w| w.set_ot(n, vals::Ot::PUSHPULL)); | ||
| 184 | pin.set_speed(speed); | ||
| 185 | r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT)); | ||
| 186 | } | ||
| 136 | }); | 187 | }); |
| 137 | 188 | ||
| 138 | Self { | 189 | Self { |
| @@ -147,8 +198,18 @@ impl<'d, T: Pin> Drop for Output<'d, T> { | |||
| 147 | cortex_m::interrupt::free(|_| unsafe { | 198 | cortex_m::interrupt::free(|_| unsafe { |
| 148 | let r = self.pin.block(); | 199 | let r = self.pin.block(); |
| 149 | let n = self.pin.pin() as usize; | 200 | let n = self.pin.pin() as usize; |
| 150 | r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING)); | 201 | #[cfg(gpio_v1)] |
| 151 | r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT)); | 202 | { |
| 203 | let crlh = if n < 8 { 0 } else { 1 }; | ||
| 204 | r.cr(crlh) | ||
| 205 | .modify(|w| w.set_cnf(n % 8, vals::Cnf::OPENDRAIN)); | ||
| 206 | r.cr(crlh).modify(|w| w.set_mode(n % 8, vals::Mode::INPUT)); | ||
| 207 | } | ||
| 208 | #[cfg(gpio_v2)] | ||
| 209 | { | ||
| 210 | r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING)); | ||
| 211 | r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT)); | ||
| 212 | } | ||
| 152 | }); | 213 | }); |
| 153 | } | 214 | } |
| 154 | } | 215 | } |
| @@ -207,10 +268,25 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> { | |||
| 207 | cortex_m::interrupt::free(|_| unsafe { | 268 | cortex_m::interrupt::free(|_| unsafe { |
| 208 | let r = pin.block(); | 269 | let r = pin.block(); |
| 209 | let n = pin.pin() as usize; | 270 | let n = pin.pin() as usize; |
| 210 | r.pupdr().modify(|w| w.set_pupdr(n, pull.into())); | 271 | #[cfg(gpio_v1)] |
| 211 | r.otyper().modify(|w| w.set_ot(n, vals::Ot::OPENDRAIN)); | 272 | { |
| 212 | pin.set_speed(speed); | 273 | let crlh = if n < 8 { 0 } else { 1 }; |
| 213 | r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT)); | 274 | match pull { |
| 275 | Pull::Up => r.bsrr().write(|w| w.set_bs(n, true)), | ||
| 276 | Pull::Down => r.bsrr().write(|w| w.set_br(n, true)), | ||
| 277 | Pull::None => {} | ||
| 278 | } | ||
| 279 | r.cr(crlh).modify(|w| w.set_mode(n % 8, speed.into())); | ||
| 280 | r.cr(crlh) | ||
| 281 | .modify(|w| w.set_cnf(n % 8, vals::Cnf::OPENDRAIN)); | ||
| 282 | } | ||
| 283 | #[cfg(gpio_v2)] | ||
| 284 | { | ||
| 285 | r.pupdr().modify(|w| w.set_pupdr(n, pull.into())); | ||
| 286 | r.otyper().modify(|w| w.set_ot(n, vals::Ot::OPENDRAIN)); | ||
| 287 | pin.set_speed(speed); | ||
| 288 | r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT)); | ||
| 289 | } | ||
| 214 | }); | 290 | }); |
| 215 | 291 | ||
| 216 | Self { | 292 | Self { |
| @@ -225,8 +301,18 @@ impl<'d, T: Pin> Drop for OutputOpenDrain<'d, T> { | |||
| 225 | cortex_m::interrupt::free(|_| unsafe { | 301 | cortex_m::interrupt::free(|_| unsafe { |
| 226 | let r = self.pin.block(); | 302 | let r = self.pin.block(); |
| 227 | let n = self.pin.pin() as usize; | 303 | let n = self.pin.pin() as usize; |
| 228 | r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING)); | 304 | #[cfg(gpio_v1)] |
| 229 | r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT)); | 305 | { |
| 306 | let crlh = if n < 8 { 0 } else { 1 }; | ||
| 307 | r.cr(crlh) | ||
| 308 | .modify(|w| w.set_cnf(n % 8, vals::Cnf::OPENDRAIN)); | ||
| 309 | r.cr(crlh).modify(|w| w.set_mode(n % 8, vals::Mode::INPUT)); | ||
| 310 | } | ||
| 311 | #[cfg(gpio_v2)] | ||
| 312 | { | ||
| 313 | r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING)); | ||
| 314 | r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT)); | ||
| 315 | } | ||
| 230 | }); | 316 | }); |
| 231 | } | 317 | } |
| 232 | } | 318 | } |
| @@ -307,6 +393,11 @@ pub(crate) mod sealed { | |||
| 307 | } | 393 | } |
| 308 | } | 394 | } |
| 309 | 395 | ||
| 396 | #[cfg(gpio_v1)] | ||
| 397 | unsafe fn set_as_af(&self, _af_num: u8, _af_type: OutputType) { | ||
| 398 | panic!("F1 alternate GPIO functions not supported yet!"); | ||
| 399 | } | ||
| 400 | #[cfg(gpio_v2)] | ||
| 310 | unsafe fn set_as_af(&self, af_num: u8, af_type: OutputType) { | 401 | unsafe fn set_as_af(&self, af_num: u8, af_type: OutputType) { |
| 311 | let pin = self._pin() as usize; | 402 | let pin = self._pin() as usize; |
| 312 | let block = self.block(); | 403 | let block = self.block(); |
| @@ -333,11 +424,23 @@ pub(crate) mod sealed { | |||
| 333 | unsafe fn set_as_analog(&self) { | 424 | unsafe fn set_as_analog(&self) { |
| 334 | let pin = self._pin() as usize; | 425 | let pin = self._pin() as usize; |
| 335 | let block = self.block(); | 426 | let block = self.block(); |
| 427 | #[cfg(gpio_v1)] | ||
| 428 | { | ||
| 429 | let crlh = if pin < 8 { 0 } else { 1 }; | ||
| 430 | block | ||
| 431 | .cr(crlh) | ||
| 432 | .modify(|w| w.set_cnf(pin % 8, vals::Cnf::PUSHPULL)); | ||
| 433 | block | ||
| 434 | .cr(crlh) | ||
| 435 | .modify(|w| w.set_mode(pin % 8, vals::Mode::INPUT)); | ||
| 436 | } | ||
| 437 | #[cfg(gpio_v2)] | ||
| 336 | block | 438 | block |
| 337 | .moder() | 439 | .moder() |
| 338 | .modify(|w| w.set_moder(pin, vals::Moder::ANALOG)); | 440 | .modify(|w| w.set_moder(pin, vals::Moder::ANALOG)); |
| 339 | } | 441 | } |
| 340 | 442 | ||
| 443 | #[cfg(gpio_v2)] | ||
| 341 | unsafe fn set_speed(&self, speed: Speed) { | 444 | unsafe fn set_speed(&self, speed: Speed) { |
| 342 | let pin = self._pin() as usize; | 445 | let pin = self._pin() as usize; |
| 343 | self.block() | 446 | self.block() |
diff --git a/embassy-stm32/src/i2c/mod.rs b/embassy-stm32/src/i2c/mod.rs index 523a0b83a..4af5051db 100644 --- a/embassy-stm32/src/i2c/mod.rs +++ b/embassy-stm32/src/i2c/mod.rs | |||
| @@ -96,6 +96,7 @@ crate::pac::interrupts!( | |||
| 96 | }; | 96 | }; |
| 97 | ); | 97 | ); |
| 98 | 98 | ||
| 99 | #[cfg(not(rcc_f1))] | ||
| 99 | macro_rules! impl_pin { | 100 | macro_rules! impl_pin { |
| 100 | ($inst:ident, $pin:ident, $signal:ident, $af:expr) => { | 101 | ($inst:ident, $pin:ident, $signal:ident, $af:expr) => { |
| 101 | impl $signal<peripherals::$inst> for peripherals::$pin {} | 102 | impl $signal<peripherals::$inst> for peripherals::$pin {} |
diff --git a/embassy-stm32/src/rcc/f1/mod.rs b/embassy-stm32/src/rcc/f1/mod.rs new file mode 100644 index 000000000..75367d421 --- /dev/null +++ b/embassy-stm32/src/rcc/f1/mod.rs | |||
| @@ -0,0 +1,214 @@ | |||
| 1 | use core::marker::PhantomData; | ||
| 2 | |||
| 3 | use embassy::util::Unborrow; | ||
| 4 | |||
| 5 | use crate::pac::flash::vals::Latency; | ||
| 6 | use crate::pac::{FLASH, RCC}; | ||
| 7 | use crate::peripherals; | ||
| 8 | use crate::time::Hertz; | ||
| 9 | |||
| 10 | use cast::u32; | ||
| 11 | |||
| 12 | use super::{set_freqs, Clocks}; | ||
| 13 | |||
| 14 | const HSI: u32 = 8_000_000; | ||
| 15 | |||
| 16 | /// Configuration of the clocks | ||
| 17 | /// | ||
| 18 | #[non_exhaustive] | ||
| 19 | #[derive(Default)] | ||
| 20 | pub struct Config { | ||
| 21 | pub hse: Option<Hertz>, | ||
| 22 | |||
| 23 | pub sys_ck: Option<Hertz>, | ||
| 24 | pub hclk: Option<Hertz>, | ||
| 25 | pub pclk1: Option<Hertz>, | ||
| 26 | pub pclk2: Option<Hertz>, | ||
| 27 | pub adcclk: Option<Hertz>, | ||
| 28 | } | ||
| 29 | |||
| 30 | pub struct Rcc<'d> { | ||
| 31 | inner: PhantomData<&'d ()>, | ||
| 32 | config: Config, | ||
| 33 | } | ||
| 34 | |||
| 35 | impl<'d> Rcc<'d> { | ||
| 36 | pub fn new(_rcc: impl Unborrow<Target = peripherals::RCC> + 'd, config: Config) -> Self { | ||
| 37 | Self { | ||
| 38 | inner: PhantomData, | ||
| 39 | config, | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | pub fn freeze(self) -> Clocks { | ||
| 44 | use crate::pac::rcc::vals::{Adcpre, Hpre, Pllmul, Pllsrc, Ppre1, Sw, Usbpre}; | ||
| 45 | |||
| 46 | let pllsrcclk = self.config.hse.map(|hse| hse.0).unwrap_or(HSI / 2); | ||
| 47 | let sysclk = self.config.sys_ck.map(|sys| sys.0).unwrap_or(pllsrcclk); | ||
| 48 | let pllmul = sysclk / pllsrcclk; | ||
| 49 | |||
| 50 | let (pllmul_bits, real_sysclk) = if pllmul == 1 { | ||
| 51 | (None, self.config.hse.map(|hse| hse.0).unwrap_or(HSI)) | ||
| 52 | } else { | ||
| 53 | let pllmul = core::cmp::min(core::cmp::max(pllmul, 1), 16); | ||
| 54 | (Some(pllmul as u8 - 2), pllsrcclk * pllmul) | ||
| 55 | }; | ||
| 56 | |||
| 57 | assert!(real_sysclk <= 72_000_000); | ||
| 58 | |||
| 59 | let hpre_bits = self | ||
| 60 | .config | ||
| 61 | .hclk | ||
| 62 | .map(|hclk| match real_sysclk / hclk.0 { | ||
| 63 | 0 => unreachable!(), | ||
| 64 | 1 => 0b0111, | ||
| 65 | 2 => 0b1000, | ||
| 66 | 3..=5 => 0b1001, | ||
| 67 | 6..=11 => 0b1010, | ||
| 68 | 12..=39 => 0b1011, | ||
| 69 | 40..=95 => 0b1100, | ||
| 70 | 96..=191 => 0b1101, | ||
| 71 | 192..=383 => 0b1110, | ||
| 72 | _ => 0b1111, | ||
| 73 | }) | ||
| 74 | .unwrap_or(0b0111); | ||
| 75 | |||
| 76 | let hclk = if hpre_bits >= 0b1100 { | ||
| 77 | real_sysclk / (1 << (hpre_bits - 0b0110)) | ||
| 78 | } else { | ||
| 79 | real_sysclk / (1 << (hpre_bits - 0b0111)) | ||
| 80 | }; | ||
| 81 | |||
| 82 | assert!(hclk <= 72_000_000); | ||
| 83 | |||
| 84 | let ppre1_bits = self | ||
| 85 | .config | ||
| 86 | .pclk1 | ||
| 87 | .map(|pclk1| match hclk / pclk1.0 { | ||
| 88 | 0 => unreachable!(), | ||
| 89 | 1 => 0b011, | ||
| 90 | 2 => 0b100, | ||
| 91 | 3..=5 => 0b101, | ||
| 92 | 6..=11 => 0b110, | ||
| 93 | _ => 0b111, | ||
| 94 | }) | ||
| 95 | .unwrap_or(0b011); | ||
| 96 | |||
| 97 | let ppre1: i32 = 1 << (ppre1_bits - 0b011); | ||
| 98 | let pclk1 = hclk / u32(ppre1).unwrap(); | ||
| 99 | let timer_mul1 = if ppre1 == 1 { 1 } else { 2 }; | ||
| 100 | |||
| 101 | assert!(pclk1 <= 36_000_000); | ||
| 102 | |||
| 103 | let ppre2_bits = self | ||
| 104 | .config | ||
| 105 | .pclk2 | ||
| 106 | .map(|pclk2| match hclk / pclk2.0 { | ||
| 107 | 0 => unreachable!(), | ||
| 108 | 1 => 0b011, | ||
| 109 | 2 => 0b100, | ||
| 110 | 3..=5 => 0b101, | ||
| 111 | 6..=11 => 0b110, | ||
| 112 | _ => 0b111, | ||
| 113 | }) | ||
| 114 | .unwrap_or(0b011); | ||
| 115 | |||
| 116 | let ppre2: i32 = 1 << (ppre2_bits - 0b011); | ||
| 117 | let pclk2 = hclk / u32(ppre2).unwrap(); | ||
| 118 | let timer_mul2 = if ppre2 == 1 { 1 } else { 2 }; | ||
| 119 | |||
| 120 | assert!(pclk2 <= 72_000_000); | ||
| 121 | |||
| 122 | // Only needed for stm32f103? | ||
| 123 | // NOTE(safety) Atomic write | ||
| 124 | unsafe { | ||
| 125 | FLASH.acr().write(|w| { | ||
| 126 | w.set_latency(if real_sysclk <= 24_000_000 { | ||
| 127 | Latency(0b000) | ||
| 128 | } else if real_sysclk <= 48_000_000 { | ||
| 129 | Latency(0b001) | ||
| 130 | } else { | ||
| 131 | Latency(0b010) | ||
| 132 | }); | ||
| 133 | }) | ||
| 134 | } | ||
| 135 | |||
| 136 | // the USB clock is only valid if an external crystal is used, the PLL is enabled, and the | ||
| 137 | // PLL output frequency is a supported one. | ||
| 138 | // usbpre == false: divide clock by 1.5, otherwise no division | ||
| 139 | let (usbpre, _usbclk_valid) = match (self.config.hse, pllmul_bits, real_sysclk) { | ||
| 140 | (Some(_), Some(_), 72_000_000) => (false, true), | ||
| 141 | (Some(_), Some(_), 48_000_000) => (true, true), | ||
| 142 | _ => (true, false), | ||
| 143 | }; | ||
| 144 | |||
| 145 | let apre_bits: u8 = self | ||
| 146 | .config | ||
| 147 | .adcclk | ||
| 148 | .map(|adcclk| match pclk2 / adcclk.0 { | ||
| 149 | 0..=2 => 0b00, | ||
| 150 | 3..=4 => 0b01, | ||
| 151 | 5..=7 => 0b10, | ||
| 152 | _ => 0b11, | ||
| 153 | }) | ||
| 154 | .unwrap_or(0b11); | ||
| 155 | |||
| 156 | let apre = (apre_bits + 1) << 1; | ||
| 157 | let adcclk = pclk2 / u32(apre); | ||
| 158 | |||
| 159 | assert!(adcclk <= 14_000_000); | ||
| 160 | |||
| 161 | unsafe { | ||
| 162 | if self.config.hse.is_some() { | ||
| 163 | // enable HSE and wait for it to be ready | ||
| 164 | RCC.cr().modify(|w| w.set_hseon(true)); | ||
| 165 | while !RCC.cr().read().hserdy() {} | ||
| 166 | } | ||
| 167 | |||
| 168 | if let Some(pllmul_bits) = pllmul_bits { | ||
| 169 | // enable PLL and wait for it to be ready | ||
| 170 | RCC.cfgr().modify(|w| { | ||
| 171 | w.set_pllmul(Pllmul(pllmul_bits)); | ||
| 172 | w.set_pllsrc(Pllsrc(self.config.hse.is_some() as u8)); | ||
| 173 | }); | ||
| 174 | |||
| 175 | RCC.cr().modify(|w| w.set_pllon(true)); | ||
| 176 | while !RCC.cr().read().pllrdy() {} | ||
| 177 | } | ||
| 178 | |||
| 179 | // Only needed for stm32f103? | ||
| 180 | RCC.cfgr().modify(|w| { | ||
| 181 | w.set_adcpre(Adcpre(apre_bits)); | ||
| 182 | w.set_ppre2(Ppre1(ppre2_bits)); | ||
| 183 | w.set_ppre1(Ppre1(ppre1_bits)); | ||
| 184 | w.set_hpre(Hpre(hpre_bits)); | ||
| 185 | w.set_usbpre(Usbpre(usbpre as u8)); | ||
| 186 | w.set_sw(Sw(if pllmul_bits.is_some() { | ||
| 187 | // PLL | ||
| 188 | 0b10 | ||
| 189 | } else if self.config.hse.is_some() { | ||
| 190 | // HSE | ||
| 191 | 0b1 | ||
| 192 | } else { | ||
| 193 | // HSI | ||
| 194 | 0b0 | ||
| 195 | })); | ||
| 196 | }); | ||
| 197 | } | ||
| 198 | |||
| 199 | Clocks { | ||
| 200 | sys: Hertz(real_sysclk), | ||
| 201 | apb1: Hertz(pclk1), | ||
| 202 | apb2: Hertz(pclk2), | ||
| 203 | apb1_tim: Hertz(pclk1 * timer_mul1), | ||
| 204 | apb2_tim: Hertz(pclk2 * timer_mul2), | ||
| 205 | ahb: Hertz(hclk), | ||
| 206 | } | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | pub unsafe fn init(config: Config) { | ||
| 211 | let rcc = Rcc::new(<peripherals::RCC as embassy::util::Steal>::steal(), config); | ||
| 212 | let clocks = rcc.freeze(); | ||
| 213 | set_freqs(clocks); | ||
| 214 | } | ||
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index d6b4bec5f..ef1d6a859 100644 --- a/embassy-stm32/src/rcc/mod.rs +++ b/embassy-stm32/src/rcc/mod.rs | |||
| @@ -27,7 +27,7 @@ pub struct Clocks { | |||
| 27 | #[cfg(rcc_wl5)] | 27 | #[cfg(rcc_wl5)] |
| 28 | pub apb3: Hertz, | 28 | pub apb3: Hertz, |
| 29 | 29 | ||
| 30 | #[cfg(any(rcc_l0, rcc_l1, rcc_f0, rcc_f0x0, rcc_g0))] | 30 | #[cfg(any(rcc_l0, rcc_l1, rcc_f0, rcc_f1, rcc_f0x0, rcc_g0))] |
| 31 | pub ahb: Hertz, | 31 | pub ahb: Hertz, |
| 32 | 32 | ||
| 33 | #[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))] |
| @@ -79,6 +79,9 @@ cfg_if::cfg_if! { | |||
| 79 | } else if #[cfg(rcc_l4)] { | 79 | } else if #[cfg(rcc_l4)] { |
| 80 | mod l4; | 80 | mod l4; |
| 81 | pub use l4::*; | 81 | pub use l4::*; |
| 82 | } else if #[cfg(rcc_f1)] { | ||
| 83 | mod f1; | ||
| 84 | pub use f1::*; | ||
| 82 | } else if #[cfg(rcc_f4)] { | 85 | } else if #[cfg(rcc_f4)] { |
| 83 | mod f4; | 86 | mod f4; |
| 84 | pub use f4::*; | 87 | pub use f4::*; |
diff --git a/embassy-stm32/src/usart/mod.rs b/embassy-stm32/src/usart/mod.rs index c1cdd8d73..e64f8d1d9 100644 --- a/embassy-stm32/src/usart/mod.rs +++ b/embassy-stm32/src/usart/mod.rs | |||
| @@ -127,6 +127,7 @@ crate::pac::interrupts!( | |||
| 127 | }; | 127 | }; |
| 128 | ); | 128 | ); |
| 129 | 129 | ||
| 130 | #[cfg(not(rcc_f1))] | ||
| 130 | macro_rules! impl_pin { | 131 | macro_rules! impl_pin { |
| 131 | ($inst:ident, $pin:ident, $signal:ident, $af:expr) => { | 132 | ($inst:ident, $pin:ident, $signal:ident, $af:expr) => { |
| 132 | impl sealed::$signal<peripherals::$inst> for peripherals::$pin { | 133 | impl sealed::$signal<peripherals::$inst> for peripherals::$pin { |
diff --git a/examples/stm32f1/.cargo/config.toml b/examples/stm32f1/.cargo/config.toml new file mode 100644 index 000000000..28df61383 --- /dev/null +++ b/examples/stm32f1/.cargo/config.toml | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
| 2 | # replace STM32F103C8 with your chip as listed in `probe-run --list-chips` | ||
| 3 | runner = "probe-run --chip STM32F103C8" | ||
| 4 | |||
| 5 | rustflags = [ | ||
| 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] | ||
| 18 | target = "thumbv7m-none-eabi" | ||
diff --git a/examples/stm32f1/Cargo.toml b/examples/stm32f1/Cargo.toml new file mode 100644 index 000000000..9b4e831ef --- /dev/null +++ b/examples/stm32f1/Cargo.toml | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | [package] | ||
| 2 | authors = ["Dario Nieuwenhuis <[email protected]>"] | ||
| 3 | edition = "2018" | ||
| 4 | name = "embassy-stm32f1-examples" | ||
| 5 | version = "0.1.0" | ||
| 6 | resolver = "2" | ||
| 7 | |||
| 8 | [features] | ||
| 9 | default = [ | ||
| 10 | "defmt-default", | ||
| 11 | ] | ||
| 12 | defmt-default = [] | ||
| 13 | defmt-trace = [] | ||
| 14 | defmt-debug = [] | ||
| 15 | defmt-info = [] | ||
| 16 | defmt-warn = [] | ||
| 17 | defmt-error = [] | ||
| 18 | |||
| 19 | [dependencies] | ||
| 20 | embassy = { version = "0.1.0", path = "../../embassy", features = ["defmt", "defmt-trace"] } | ||
| 21 | embassy-traits = { version = "0.1.0", path = "../../embassy-traits", features = ["defmt"] } | ||
| 22 | embassy-stm32 = { version = "0.1.0", path = "../../embassy-stm32", features = ["defmt", "defmt-trace", "stm32f103c8", "unstable-pac", "memory-x", "time-driver-tim2"] } | ||
| 23 | embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } | ||
| 24 | |||
| 25 | defmt = "0.2.3" | ||
| 26 | defmt-rtt = "0.2.0" | ||
| 27 | |||
| 28 | cortex-m = "0.7.3" | ||
| 29 | cortex-m-rt = "0.7.0" | ||
| 30 | embedded-hal = "0.2.6" | ||
| 31 | panic-probe = { version = "0.2.0", features = ["print-defmt"] } | ||
| 32 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | ||
| 33 | rtt-target = { version = "0.3.1", features = ["cortex-m"] } | ||
| 34 | heapless = { version = "0.7.5", default-features = false } | ||
| 35 | nb = "1.0.0" | ||
diff --git a/examples/stm32f1/src/bin/blinky.rs b/examples/stm32f1/src/bin/blinky.rs new file mode 100644 index 000000000..1e4f2deec --- /dev/null +++ b/examples/stm32f1/src/bin/blinky.rs | |||
| @@ -0,0 +1,29 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | #[path = "../example_common.rs"] | ||
| 6 | mod example_common; | ||
| 7 | use embassy::executor::Spawner; | ||
| 8 | use embassy::time::{Duration, Timer}; | ||
| 9 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 10 | use embassy_stm32::Peripherals; | ||
| 11 | use embedded_hal::digital::v2::OutputPin; | ||
| 12 | use example_common::*; | ||
| 13 | |||
| 14 | #[embassy::main] | ||
| 15 | async fn main(_spawner: Spawner, p: Peripherals) { | ||
| 16 | info!("Hello World!"); | ||
| 17 | |||
| 18 | let mut led = Output::new(p.PC13, Level::High, Speed::Low); | ||
| 19 | |||
| 20 | loop { | ||
| 21 | info!("high"); | ||
| 22 | unwrap!(led.set_high()); | ||
| 23 | Timer::after(Duration::from_millis(300)).await; | ||
| 24 | |||
| 25 | info!("low"); | ||
| 26 | unwrap!(led.set_low()); | ||
| 27 | Timer::after(Duration::from_millis(300)).await; | ||
| 28 | } | ||
| 29 | } | ||
diff --git a/examples/stm32f1/src/bin/hello.rs b/examples/stm32f1/src/bin/hello.rs new file mode 100644 index 000000000..efcb9a244 --- /dev/null +++ b/examples/stm32f1/src/bin/hello.rs | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | use defmt::info; | ||
| 6 | use embassy::executor::Spawner; | ||
| 7 | use embassy::time::{Duration, Timer}; | ||
| 8 | use embassy_stm32::time::Hertz; | ||
| 9 | use embassy_stm32::Config; | ||
| 10 | use embassy_stm32::Peripherals; | ||
| 11 | |||
| 12 | #[path = "../example_common.rs"] | ||
| 13 | mod example_common; | ||
| 14 | |||
| 15 | fn config() -> Config { | ||
| 16 | let mut config = Config::default(); | ||
| 17 | config.rcc.sys_ck = Some(Hertz(36_000_000)); | ||
| 18 | config | ||
| 19 | } | ||
| 20 | |||
| 21 | #[embassy::main(config = "config()")] | ||
| 22 | async fn main(_spawner: Spawner, _p: Peripherals) -> ! { | ||
| 23 | loop { | ||
| 24 | info!("Hello World!"); | ||
| 25 | Timer::after(Duration::from_secs(1)).await; | ||
| 26 | } | ||
| 27 | } | ||
diff --git a/examples/stm32f1/src/example_common.rs b/examples/stm32f1/src/example_common.rs new file mode 100644 index 000000000..54d633837 --- /dev/null +++ b/examples/stm32f1/src/example_common.rs | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | #![macro_use] | ||
| 2 | |||
| 3 | use defmt_rtt as _; // global logger | ||
| 4 | use panic_probe as _; | ||
| 5 | |||
| 6 | pub use defmt::*; | ||
| 7 | |||
| 8 | use core::sync::atomic::{AtomicUsize, Ordering}; | ||
| 9 | |||
| 10 | defmt::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-gen-features/src/lib.rs b/stm32-gen-features/src/lib.rs index 75eb7d756..426984cb0 100644 --- a/stm32-gen-features/src/lib.rs +++ b/stm32-gen-features/src/lib.rs | |||
| @@ -2,8 +2,9 @@ | |||
| 2 | 2 | ||
| 3 | use std::{iter::FilterMap, path::Path, slice::Iter}; | 3 | use std::{iter::FilterMap, path::Path, slice::Iter}; |
| 4 | 4 | ||
| 5 | const SUPPORTED_FAMILIES: [&str; 9] = [ | 5 | const SUPPORTED_FAMILIES: [&str; 10] = [ |
| 6 | "stm32f0", | 6 | "stm32f0", |
| 7 | "stm32f1", | ||
| 7 | "stm32f4", | 8 | "stm32f4", |
| 8 | "stm32g0", | 9 | "stm32g0", |
| 9 | "stm32l0", | 10 | "stm32l0", |
