diff options
| author | Ulf Lilleengen <[email protected]> | 2021-09-21 13:42:27 +0200 |
|---|---|---|
| committer | Ulf Lilleengen <[email protected]> | 2021-09-21 14:50:23 +0200 |
| commit | c79485c286d96ca7b1d0bdeb7360488b838a841e (patch) | |
| tree | 58415adb5d9dbdb1a31ab8f9b4b6cc3cb727c986 | |
| parent | 14aa4265db25adb75fdcaf66798a878ae789bf9c (diff) | |
Support for STM32L1
* Add RCC
* Fix more issues with dash in chip names
* Update stm32-data version
* Add blinky and spi example
| -rw-r--r-- | .github/workflows/rust.yml | 5 | ||||
| -rw-r--r-- | embassy-stm32/Cargo.toml | 87 | ||||
| -rw-r--r-- | embassy-stm32/build.rs | 25 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/l1/mod.rs | 235 | ||||
| -rw-r--r-- | embassy-stm32/src/rcc/mod.rs | 5 | ||||
| -rw-r--r-- | examples/stm32l1/.cargo/config.toml | 18 | ||||
| -rw-r--r-- | examples/stm32l1/Cargo.toml | 35 | ||||
| -rw-r--r-- | examples/stm32l1/build.rs | 31 | ||||
| -rw-r--r-- | examples/stm32l1/memory.x | 5 | ||||
| -rw-r--r-- | examples/stm32l1/src/bin/blinky.rs | 30 | ||||
| -rw-r--r-- | examples/stm32l1/src/bin/spi.rs | 43 | ||||
| -rw-r--r-- | examples/stm32l1/src/example_common.rs | 17 | ||||
| -rw-r--r-- | examples/stm32l4/.cargo/config.toml | 3 | ||||
| -rw-r--r-- | rust-toolchain.toml | 2 | ||||
| m--------- | stm32-data | 0 | ||||
| -rw-r--r-- | stm32-gen-features/src/lib.rs | 3 | ||||
| -rw-r--r-- | stm32-metapac-gen/src/assets/build.rs | 11 | ||||
| -rw-r--r-- | stm32-metapac-gen/src/lib.rs | 2 | ||||
| -rw-r--r-- | stm32-metapac/build.rs | 11 |
19 files changed, 558 insertions, 10 deletions
diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 79a5ad796..5cdf75d7b 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml | |||
| @@ -78,6 +78,9 @@ jobs: | |||
| 78 | - package: embassy-stm32 | 78 | - package: embassy-stm32 |
| 79 | target: thumbv6m-none-eabi | 79 | target: thumbv6m-none-eabi |
| 80 | features: stm32l072cz,defmt | 80 | features: stm32l072cz,defmt |
| 81 | - package: embassy-stm32 | ||
| 82 | target: thumbv7m-none-eabi | ||
| 83 | features: stm32l151cb-a,defmt | ||
| 81 | - package: examples/stm32f4 | 84 | - package: examples/stm32f4 |
| 82 | target: thumbv7em-none-eabi | 85 | target: thumbv7em-none-eabi |
| 83 | - package: examples/stm32l4 | 86 | - package: examples/stm32l4 |
| @@ -86,6 +89,8 @@ jobs: | |||
| 86 | target: thumbv7em-none-eabi | 89 | target: thumbv7em-none-eabi |
| 87 | - package: examples/stm32l0 | 90 | - package: examples/stm32l0 |
| 88 | target: thumbv6m-none-eabi | 91 | target: thumbv6m-none-eabi |
| 92 | - package: examples/stm32l1 | ||
| 93 | target: thumbv7m-none-eabi | ||
| 89 | - package: examples/stm32wb55 | 94 | - package: examples/stm32wb55 |
| 90 | target: thumbv7em-none-eabihf | 95 | target: thumbv7em-none-eabihf |
| 91 | - package: examples/stm32wl55 | 96 | - package: examples/stm32wl55 |
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index dec336588..3e91040f0 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -625,6 +625,93 @@ stm32l083rz = [ "stm32-metapac/stm32l083rz" ] | |||
| 625 | stm32l083v8 = [ "stm32-metapac/stm32l083v8" ] | 625 | stm32l083v8 = [ "stm32-metapac/stm32l083v8" ] |
| 626 | stm32l083vb = [ "stm32-metapac/stm32l083vb" ] | 626 | stm32l083vb = [ "stm32-metapac/stm32l083vb" ] |
| 627 | stm32l083vz = [ "stm32-metapac/stm32l083vz" ] | 627 | stm32l083vz = [ "stm32-metapac/stm32l083vz" ] |
| 628 | stm32l100c6-a = [ "stm32-metapac/stm32l100c6-a" ] | ||
| 629 | stm32l100c6 = [ "stm32-metapac/stm32l100c6" ] | ||
| 630 | stm32l100r8-a = [ "stm32-metapac/stm32l100r8-a" ] | ||
| 631 | stm32l100r8 = [ "stm32-metapac/stm32l100r8" ] | ||
| 632 | stm32l100rb-a = [ "stm32-metapac/stm32l100rb-a" ] | ||
| 633 | stm32l100rb = [ "stm32-metapac/stm32l100rb" ] | ||
| 634 | stm32l100rc = [ "stm32-metapac/stm32l100rc" ] | ||
| 635 | stm32l151c6-a = [ "stm32-metapac/stm32l151c6-a" ] | ||
| 636 | stm32l151c6 = [ "stm32-metapac/stm32l151c6" ] | ||
| 637 | stm32l151c8-a = [ "stm32-metapac/stm32l151c8-a" ] | ||
| 638 | stm32l151c8 = [ "stm32-metapac/stm32l151c8" ] | ||
| 639 | stm32l151cb-a = [ "stm32-metapac/stm32l151cb-a" ] | ||
| 640 | stm32l151cb = [ "stm32-metapac/stm32l151cb" ] | ||
| 641 | stm32l151cc = [ "stm32-metapac/stm32l151cc" ] | ||
| 642 | stm32l151qc = [ "stm32-metapac/stm32l151qc" ] | ||
| 643 | stm32l151qd = [ "stm32-metapac/stm32l151qd" ] | ||
| 644 | stm32l151qe = [ "stm32-metapac/stm32l151qe" ] | ||
| 645 | stm32l151r6-a = [ "stm32-metapac/stm32l151r6-a" ] | ||
| 646 | stm32l151r6 = [ "stm32-metapac/stm32l151r6" ] | ||
| 647 | stm32l151r8-a = [ "stm32-metapac/stm32l151r8-a" ] | ||
| 648 | stm32l151r8 = [ "stm32-metapac/stm32l151r8" ] | ||
| 649 | stm32l151rb-a = [ "stm32-metapac/stm32l151rb-a" ] | ||
| 650 | stm32l151rb = [ "stm32-metapac/stm32l151rb" ] | ||
| 651 | stm32l151rc-a = [ "stm32-metapac/stm32l151rc-a" ] | ||
| 652 | stm32l151rc = [ "stm32-metapac/stm32l151rc" ] | ||
| 653 | stm32l151rd = [ "stm32-metapac/stm32l151rd" ] | ||
| 654 | stm32l151re = [ "stm32-metapac/stm32l151re" ] | ||
| 655 | stm32l151uc = [ "stm32-metapac/stm32l151uc" ] | ||
| 656 | stm32l151v8-a = [ "stm32-metapac/stm32l151v8-a" ] | ||
| 657 | stm32l151v8 = [ "stm32-metapac/stm32l151v8" ] | ||
| 658 | stm32l151vb-a = [ "stm32-metapac/stm32l151vb-a" ] | ||
| 659 | stm32l151vb = [ "stm32-metapac/stm32l151vb" ] | ||
| 660 | stm32l151vc-a = [ "stm32-metapac/stm32l151vc-a" ] | ||
| 661 | stm32l151vc = [ "stm32-metapac/stm32l151vc" ] | ||
| 662 | stm32l151vd-x = [ "stm32-metapac/stm32l151vd-x" ] | ||
| 663 | stm32l151vd = [ "stm32-metapac/stm32l151vd" ] | ||
| 664 | stm32l151ve = [ "stm32-metapac/stm32l151ve" ] | ||
| 665 | stm32l151zc = [ "stm32-metapac/stm32l151zc" ] | ||
| 666 | stm32l151zd = [ "stm32-metapac/stm32l151zd" ] | ||
| 667 | stm32l151ze = [ "stm32-metapac/stm32l151ze" ] | ||
| 668 | stm32l152c6-a = [ "stm32-metapac/stm32l152c6-a" ] | ||
| 669 | stm32l152c6 = [ "stm32-metapac/stm32l152c6" ] | ||
| 670 | stm32l152c8-a = [ "stm32-metapac/stm32l152c8-a" ] | ||
| 671 | stm32l152c8 = [ "stm32-metapac/stm32l152c8" ] | ||
| 672 | stm32l152cb-a = [ "stm32-metapac/stm32l152cb-a" ] | ||
| 673 | stm32l152cb = [ "stm32-metapac/stm32l152cb" ] | ||
| 674 | stm32l152cc = [ "stm32-metapac/stm32l152cc" ] | ||
| 675 | stm32l152qc = [ "stm32-metapac/stm32l152qc" ] | ||
| 676 | stm32l152qd = [ "stm32-metapac/stm32l152qd" ] | ||
| 677 | stm32l152qe = [ "stm32-metapac/stm32l152qe" ] | ||
| 678 | stm32l152r6-a = [ "stm32-metapac/stm32l152r6-a" ] | ||
| 679 | stm32l152r6 = [ "stm32-metapac/stm32l152r6" ] | ||
| 680 | stm32l152r8-a = [ "stm32-metapac/stm32l152r8-a" ] | ||
| 681 | stm32l152r8 = [ "stm32-metapac/stm32l152r8" ] | ||
| 682 | stm32l152rb-a = [ "stm32-metapac/stm32l152rb-a" ] | ||
| 683 | stm32l152rb = [ "stm32-metapac/stm32l152rb" ] | ||
| 684 | stm32l152rc-a = [ "stm32-metapac/stm32l152rc-a" ] | ||
| 685 | stm32l152rc = [ "stm32-metapac/stm32l152rc" ] | ||
| 686 | stm32l152rd = [ "stm32-metapac/stm32l152rd" ] | ||
| 687 | stm32l152re = [ "stm32-metapac/stm32l152re" ] | ||
| 688 | stm32l152uc = [ "stm32-metapac/stm32l152uc" ] | ||
| 689 | stm32l152v8-a = [ "stm32-metapac/stm32l152v8-a" ] | ||
| 690 | stm32l152v8 = [ "stm32-metapac/stm32l152v8" ] | ||
| 691 | stm32l152vb-a = [ "stm32-metapac/stm32l152vb-a" ] | ||
| 692 | stm32l152vb = [ "stm32-metapac/stm32l152vb" ] | ||
| 693 | stm32l152vc-a = [ "stm32-metapac/stm32l152vc-a" ] | ||
| 694 | stm32l152vc = [ "stm32-metapac/stm32l152vc" ] | ||
| 695 | stm32l152vd-x = [ "stm32-metapac/stm32l152vd-x" ] | ||
| 696 | stm32l152vd = [ "stm32-metapac/stm32l152vd" ] | ||
| 697 | stm32l152ve = [ "stm32-metapac/stm32l152ve" ] | ||
| 698 | stm32l152zc = [ "stm32-metapac/stm32l152zc" ] | ||
| 699 | stm32l152zd = [ "stm32-metapac/stm32l152zd" ] | ||
| 700 | stm32l152ze = [ "stm32-metapac/stm32l152ze" ] | ||
| 701 | stm32l162qc = [ "stm32-metapac/stm32l162qc" ] | ||
| 702 | stm32l162qd = [ "stm32-metapac/stm32l162qd" ] | ||
| 703 | stm32l162rc-a = [ "stm32-metapac/stm32l162rc-a" ] | ||
| 704 | stm32l162rc = [ "stm32-metapac/stm32l162rc" ] | ||
| 705 | stm32l162rd = [ "stm32-metapac/stm32l162rd" ] | ||
| 706 | stm32l162re = [ "stm32-metapac/stm32l162re" ] | ||
| 707 | stm32l162vc-a = [ "stm32-metapac/stm32l162vc-a" ] | ||
| 708 | stm32l162vc = [ "stm32-metapac/stm32l162vc" ] | ||
| 709 | stm32l162vd-x = [ "stm32-metapac/stm32l162vd-x" ] | ||
| 710 | stm32l162vd = [ "stm32-metapac/stm32l162vd" ] | ||
| 711 | stm32l162ve = [ "stm32-metapac/stm32l162ve" ] | ||
| 712 | stm32l162zc = [ "stm32-metapac/stm32l162zc" ] | ||
| 713 | stm32l162zd = [ "stm32-metapac/stm32l162zd" ] | ||
| 714 | stm32l162ze = [ "stm32-metapac/stm32l162ze" ] | ||
| 628 | stm32l412c8 = [ "stm32-metapac/stm32l412c8" ] | 715 | stm32l412c8 = [ "stm32-metapac/stm32l412c8" ] |
| 629 | stm32l412cb = [ "stm32-metapac/stm32l412cb" ] | 716 | stm32l412cb = [ "stm32-metapac/stm32l412cb" ] |
| 630 | stm32l412k8 = [ "stm32-metapac/stm32l412k8" ] | 717 | stm32l412k8 = [ "stm32-metapac/stm32l412k8" ] |
diff --git a/embassy-stm32/build.rs b/embassy-stm32/build.rs index 8bb78a6f2..32115f9a8 100644 --- a/embassy-stm32/build.rs +++ b/embassy-stm32/build.rs | |||
| @@ -85,13 +85,28 @@ fn main() { | |||
| 85 | }; | 85 | }; |
| 86 | ); | 86 | ); |
| 87 | 87 | ||
| 88 | let mut chip_and_core = chip_name.split('_'); | 88 | let mut s = chip_name.split('_'); |
| 89 | let chip = chip_and_core.next().expect("Unexpected stm32xx feature"); | 89 | let mut chip_name: String = s.next().unwrap().to_string(); |
| 90 | let core_name = if let Some(c) = s.next() { | ||
| 91 | if !c.starts_with("CM") { | ||
| 92 | chip_name.push('_'); | ||
| 93 | chip_name.push_str(c); | ||
| 94 | None | ||
| 95 | } else { | ||
| 96 | Some(c) | ||
| 97 | } | ||
| 98 | } else { | ||
| 99 | None | ||
| 100 | }; | ||
| 90 | 101 | ||
| 91 | if let Some(core) = chip_and_core.next() { | 102 | if let Some(core) = core_name { |
| 92 | println!("cargo:rustc-cfg={}_{}", &chip[..(chip.len() - 2)], core); | 103 | println!( |
| 104 | "cargo:rustc-cfg={}_{}", | ||
| 105 | &chip_name[..chip_name.len() - 2], | ||
| 106 | core | ||
| 107 | ); | ||
| 93 | } else { | 108 | } else { |
| 94 | println!("cargo:rustc-cfg={}", &chip[..(chip.len() - 2)]); | 109 | println!("cargo:rustc-cfg={}", &chip_name[..chip_name.len() - 2]); |
| 95 | } | 110 | } |
| 96 | 111 | ||
| 97 | println!("cargo:rerun-if-changed=build.rs"); | 112 | println!("cargo:rerun-if-changed=build.rs"); |
diff --git a/embassy-stm32/src/rcc/l1/mod.rs b/embassy-stm32/src/rcc/l1/mod.rs new file mode 100644 index 000000000..25b5609c4 --- /dev/null +++ b/embassy-stm32/src/rcc/l1/mod.rs | |||
| @@ -0,0 +1,235 @@ | |||
| 1 | pub use super::types::*; | ||
| 2 | use crate::pac; | ||
| 3 | use crate::peripherals::{self, RCC}; | ||
| 4 | use crate::rcc::{get_freqs, set_freqs, Clocks}; | ||
| 5 | use crate::time::Hertz; | ||
| 6 | use crate::time::U32Ext; | ||
| 7 | use core::marker::PhantomData; | ||
| 8 | use embassy::util::Unborrow; | ||
| 9 | use embassy_hal_common::unborrow; | ||
| 10 | use pac::rcc::vals::{Hpre, Ppre, Sw}; | ||
| 11 | |||
| 12 | /// Most of clock setup is copied from rcc/l0 | ||
| 13 | |||
| 14 | /// HSI speed | ||
| 15 | pub const HSI_FREQ: u32 = 16_000_000; | ||
| 16 | |||
| 17 | /// System clock mux source | ||
| 18 | #[derive(Clone, Copy)] | ||
| 19 | pub enum ClockSrc { | ||
| 20 | MSI(MSIRange), | ||
| 21 | HSE(Hertz), | ||
| 22 | HSI, | ||
| 23 | } | ||
| 24 | |||
| 25 | impl Into<Ppre> for APBPrescaler { | ||
| 26 | fn into(self) -> Ppre { | ||
| 27 | match self { | ||
| 28 | APBPrescaler::NotDivided => Ppre::DIV1, | ||
| 29 | APBPrescaler::Div2 => Ppre::DIV2, | ||
| 30 | APBPrescaler::Div4 => Ppre::DIV4, | ||
| 31 | APBPrescaler::Div8 => Ppre::DIV8, | ||
| 32 | APBPrescaler::Div16 => Ppre::DIV16, | ||
| 33 | } | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | impl Into<Hpre> for AHBPrescaler { | ||
| 38 | fn into(self) -> Hpre { | ||
| 39 | match self { | ||
| 40 | AHBPrescaler::NotDivided => Hpre::DIV1, | ||
| 41 | AHBPrescaler::Div2 => Hpre::DIV2, | ||
| 42 | AHBPrescaler::Div4 => Hpre::DIV4, | ||
| 43 | AHBPrescaler::Div8 => Hpre::DIV8, | ||
| 44 | AHBPrescaler::Div16 => Hpre::DIV16, | ||
| 45 | AHBPrescaler::Div64 => Hpre::DIV64, | ||
| 46 | AHBPrescaler::Div128 => Hpre::DIV128, | ||
| 47 | AHBPrescaler::Div256 => Hpre::DIV256, | ||
| 48 | AHBPrescaler::Div512 => Hpre::DIV512, | ||
| 49 | } | ||
| 50 | } | ||
| 51 | } | ||
| 52 | |||
| 53 | impl Into<u8> for MSIRange { | ||
| 54 | fn into(self) -> u8 { | ||
| 55 | match self { | ||
| 56 | MSIRange::Range0 => 0b000, | ||
| 57 | MSIRange::Range1 => 0b001, | ||
| 58 | MSIRange::Range2 => 0b010, | ||
| 59 | MSIRange::Range3 => 0b011, | ||
| 60 | MSIRange::Range4 => 0b100, | ||
| 61 | MSIRange::Range5 => 0b101, | ||
| 62 | MSIRange::Range6 => 0b110, | ||
| 63 | } | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | /// Clocks configutation | ||
| 68 | pub struct Config { | ||
| 69 | mux: ClockSrc, | ||
| 70 | ahb_pre: AHBPrescaler, | ||
| 71 | apb1_pre: APBPrescaler, | ||
| 72 | apb2_pre: APBPrescaler, | ||
| 73 | } | ||
| 74 | |||
| 75 | impl Default for Config { | ||
| 76 | #[inline] | ||
| 77 | fn default() -> Config { | ||
| 78 | Config { | ||
| 79 | mux: ClockSrc::MSI(MSIRange::default()), | ||
| 80 | ahb_pre: AHBPrescaler::NotDivided, | ||
| 81 | apb1_pre: APBPrescaler::NotDivided, | ||
| 82 | apb2_pre: APBPrescaler::NotDivided, | ||
| 83 | } | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | impl Config { | ||
| 88 | #[inline] | ||
| 89 | pub fn clock_src(mut self, mux: ClockSrc) -> Self { | ||
| 90 | self.mux = mux; | ||
| 91 | self | ||
| 92 | } | ||
| 93 | |||
| 94 | #[inline] | ||
| 95 | pub fn ahb_pre(mut self, pre: AHBPrescaler) -> Self { | ||
| 96 | self.ahb_pre = pre; | ||
| 97 | self | ||
| 98 | } | ||
| 99 | |||
| 100 | #[inline] | ||
| 101 | pub fn apb1_pre(mut self, pre: APBPrescaler) -> Self { | ||
| 102 | self.apb1_pre = pre; | ||
| 103 | self | ||
| 104 | } | ||
| 105 | |||
| 106 | #[inline] | ||
| 107 | pub fn apb2_pre(mut self, pre: APBPrescaler) -> Self { | ||
| 108 | self.apb2_pre = pre; | ||
| 109 | self | ||
| 110 | } | ||
| 111 | } | ||
| 112 | |||
| 113 | /// RCC peripheral | ||
| 114 | pub struct Rcc<'d> { | ||
| 115 | _rb: peripherals::RCC, | ||
| 116 | phantom: PhantomData<&'d mut peripherals::RCC>, | ||
| 117 | } | ||
| 118 | |||
| 119 | impl<'d> Rcc<'d> { | ||
| 120 | pub fn new(rcc: impl Unborrow<Target = peripherals::RCC> + 'd) -> Self { | ||
| 121 | unborrow!(rcc); | ||
| 122 | Self { | ||
| 123 | _rb: rcc, | ||
| 124 | phantom: PhantomData, | ||
| 125 | } | ||
| 126 | } | ||
| 127 | |||
| 128 | // Safety: RCC init must have been called | ||
| 129 | pub fn clocks(&self) -> &'static Clocks { | ||
| 130 | unsafe { get_freqs() } | ||
| 131 | } | ||
| 132 | } | ||
| 133 | |||
| 134 | /// Extension trait that freezes the `RCC` peripheral with provided clocks configuration | ||
| 135 | pub trait RccExt { | ||
| 136 | fn freeze(self, config: Config) -> Clocks; | ||
| 137 | } | ||
| 138 | |||
| 139 | impl RccExt for RCC { | ||
| 140 | // `cfgr` is almost always a constant, so make sure it can be constant-propagated properly by | ||
| 141 | // marking this function and all `Config` constructors and setters as `#[inline]`. | ||
| 142 | // This saves ~900 Bytes for the `pwr.rs` example. | ||
| 143 | #[inline] | ||
| 144 | fn freeze(self, cfgr: Config) -> Clocks { | ||
| 145 | let rcc = pac::RCC; | ||
| 146 | let (sys_clk, sw) = match cfgr.mux { | ||
| 147 | ClockSrc::MSI(range) => { | ||
| 148 | // Set MSI range | ||
| 149 | unsafe { | ||
| 150 | rcc.icscr().write(|w| w.set_msirange(range.into())); | ||
| 151 | } | ||
| 152 | |||
| 153 | // Enable MSI | ||
| 154 | unsafe { | ||
| 155 | rcc.cr().write(|w| w.set_msion(true)); | ||
| 156 | while !rcc.cr().read().msirdy() {} | ||
| 157 | } | ||
| 158 | |||
| 159 | let freq = 32_768 * (1 << (range as u8 + 1)); | ||
| 160 | (freq, Sw::MSI) | ||
| 161 | } | ||
| 162 | ClockSrc::HSI => { | ||
| 163 | // Enable HSI | ||
| 164 | unsafe { | ||
| 165 | rcc.cr().write(|w| w.set_hsion(true)); | ||
| 166 | while !rcc.cr().read().hsirdy() {} | ||
| 167 | } | ||
| 168 | |||
| 169 | (HSI_FREQ, Sw::HSI) | ||
| 170 | } | ||
| 171 | ClockSrc::HSE(freq) => { | ||
| 172 | // Enable HSE | ||
| 173 | unsafe { | ||
| 174 | rcc.cr().write(|w| w.set_hseon(true)); | ||
| 175 | while !rcc.cr().read().hserdy() {} | ||
| 176 | } | ||
| 177 | |||
| 178 | (freq.0, Sw::HSE) | ||
| 179 | } | ||
| 180 | }; | ||
| 181 | |||
| 182 | unsafe { | ||
| 183 | rcc.cfgr().modify(|w| { | ||
| 184 | w.set_sw(sw.into()); | ||
| 185 | w.set_hpre(cfgr.ahb_pre.into()); | ||
| 186 | w.set_ppre1(cfgr.apb1_pre.into()); | ||
| 187 | w.set_ppre2(cfgr.apb2_pre.into()); | ||
| 188 | }); | ||
| 189 | } | ||
| 190 | |||
| 191 | let ahb_freq: u32 = match cfgr.ahb_pre { | ||
| 192 | AHBPrescaler::NotDivided => sys_clk, | ||
| 193 | pre => { | ||
| 194 | let pre: Hpre = pre.into(); | ||
| 195 | let pre = 1 << (pre.0 as u32 - 7); | ||
| 196 | sys_clk / pre | ||
| 197 | } | ||
| 198 | }; | ||
| 199 | |||
| 200 | let (apb1_freq, apb1_tim_freq) = match cfgr.apb1_pre { | ||
| 201 | APBPrescaler::NotDivided => (ahb_freq, ahb_freq), | ||
| 202 | pre => { | ||
| 203 | let pre: Ppre = pre.into(); | ||
| 204 | let pre: u8 = 1 << (pre.0 - 3); | ||
| 205 | let freq = ahb_freq / pre as u32; | ||
| 206 | (freq, freq * 2) | ||
| 207 | } | ||
| 208 | }; | ||
| 209 | |||
| 210 | let (apb2_freq, apb2_tim_freq) = match cfgr.apb2_pre { | ||
| 211 | APBPrescaler::NotDivided => (ahb_freq, ahb_freq), | ||
| 212 | pre => { | ||
| 213 | let pre: Ppre = pre.into(); | ||
| 214 | let pre: u8 = 1 << (pre.0 - 3); | ||
| 215 | let freq = ahb_freq / (1 << (pre as u8 - 3)); | ||
| 216 | (freq, freq * 2) | ||
| 217 | } | ||
| 218 | }; | ||
| 219 | |||
| 220 | Clocks { | ||
| 221 | sys: sys_clk.hz(), | ||
| 222 | ahb: ahb_freq.hz(), | ||
| 223 | apb1: apb1_freq.hz(), | ||
| 224 | apb2: apb2_freq.hz(), | ||
| 225 | apb1_tim: apb1_tim_freq.hz(), | ||
| 226 | apb2_tim: apb2_tim_freq.hz(), | ||
| 227 | } | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | pub unsafe fn init(config: Config) { | ||
| 232 | let r = <peripherals::RCC as embassy::util::Steal>::steal(); | ||
| 233 | let clocks = r.freeze(config); | ||
| 234 | set_freqs(clocks); | ||
| 235 | } | ||
diff --git a/embassy-stm32/src/rcc/mod.rs b/embassy-stm32/src/rcc/mod.rs index 791b86c0d..d6b4bec5f 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_f0, rcc_f0x0, rcc_g0))] | 30 | #[cfg(any(rcc_l0, rcc_l1, rcc_f0, 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))] |
| @@ -73,6 +73,9 @@ cfg_if::cfg_if! { | |||
| 73 | } else if #[cfg(rcc_l0)] { | 73 | } else if #[cfg(rcc_l0)] { |
| 74 | mod l0; | 74 | mod l0; |
| 75 | pub use l0::*; | 75 | pub use l0::*; |
| 76 | } else if #[cfg(rcc_l1)] { | ||
| 77 | mod l1; | ||
| 78 | pub use l1::*; | ||
| 76 | } else if #[cfg(rcc_l4)] { | 79 | } else if #[cfg(rcc_l4)] { |
| 77 | mod l4; | 80 | mod l4; |
| 78 | pub use l4::*; | 81 | pub use l4::*; |
diff --git a/examples/stm32l1/.cargo/config.toml b/examples/stm32l1/.cargo/config.toml new file mode 100644 index 000000000..e0d2bddf0 --- /dev/null +++ b/examples/stm32l1/.cargo/config.toml | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | ||
| 2 | # replace your chip as listed in `probe-run --list-chips` | ||
| 3 | runner = "probe-run --chip STM32L151CBxxA" | ||
| 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/stm32l1/Cargo.toml b/examples/stm32l1/Cargo.toml new file mode 100644 index 000000000..e4dd7186a --- /dev/null +++ b/examples/stm32l1/Cargo.toml | |||
| @@ -0,0 +1,35 @@ | |||
| 1 | [package] | ||
| 2 | authors = ["Dario Nieuwenhuis <[email protected]>", "Ulf Lilleengen <[email protected]>"] | ||
| 3 | edition = "2018" | ||
| 4 | name = "embassy-stm32l1-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", "stm32l151cb-a", "time-driver-tim2", "memory-x"] } | ||
| 23 | embassy-hal-common = {version = "0.1.0", path = "../../embassy-hal-common" } | ||
| 24 | embassy-macros = { path = "../../embassy-macros" } | ||
| 25 | |||
| 26 | defmt = "0.2.3" | ||
| 27 | defmt-rtt = "0.2.0" | ||
| 28 | |||
| 29 | cortex-m = "0.7.3" | ||
| 30 | cortex-m-rt = "0.7.0" | ||
| 31 | embedded-hal = "0.2.6" | ||
| 32 | panic-probe = { version = "0.2.0", features = ["print-defmt"] } | ||
| 33 | futures = { version = "0.3.17", default-features = false, features = ["async-await"] } | ||
| 34 | rtt-target = { version = "0.3.1", features = ["cortex-m"] } | ||
| 35 | heapless = { version = "0.7.5", default-features = false } | ||
diff --git a/examples/stm32l1/build.rs b/examples/stm32l1/build.rs new file mode 100644 index 000000000..d534cc3df --- /dev/null +++ b/examples/stm32l1/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 | |||
| 11 | use std::env; | ||
| 12 | use std::fs::File; | ||
| 13 | use std::io::Write; | ||
| 14 | use std::path::PathBuf; | ||
| 15 | |||
| 16 | fn 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/stm32l1/memory.x b/examples/stm32l1/memory.x new file mode 100644 index 000000000..c94d395c8 --- /dev/null +++ b/examples/stm32l1/memory.x | |||
| @@ -0,0 +1,5 @@ | |||
| 1 | MEMORY | ||
| 2 | { | ||
| 3 | FLASH : ORIGIN = 0x08000000, LENGTH = 128K | ||
| 4 | RAM : ORIGIN = 0x20000000, LENGTH = 32K | ||
| 5 | } | ||
diff --git a/examples/stm32l1/src/bin/blinky.rs b/examples/stm32l1/src/bin/blinky.rs new file mode 100644 index 000000000..deabdddba --- /dev/null +++ b/examples/stm32l1/src/bin/blinky.rs | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | #[path = "../example_common.rs"] | ||
| 6 | mod example_common; | ||
| 7 | |||
| 8 | use embassy::executor::Spawner; | ||
| 9 | use embassy::time::{Duration, Timer}; | ||
| 10 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 11 | use embassy_stm32::Peripherals; | ||
| 12 | use embedded_hal::digital::v2::OutputPin; | ||
| 13 | use example_common::*; | ||
| 14 | |||
| 15 | #[embassy::main] | ||
| 16 | async fn main(_spawner: Spawner, p: Peripherals) { | ||
| 17 | info!("Hello World!"); | ||
| 18 | |||
| 19 | let mut led = Output::new(p.PA12, Level::High, Speed::Low); | ||
| 20 | |||
| 21 | loop { | ||
| 22 | info!("high"); | ||
| 23 | unwrap!(led.set_high()); | ||
| 24 | Timer::after(Duration::from_millis(1000)).await; | ||
| 25 | |||
| 26 | info!("low"); | ||
| 27 | unwrap!(led.set_low()); | ||
| 28 | Timer::after(Duration::from_millis(1000)).await; | ||
| 29 | } | ||
| 30 | } | ||
diff --git a/examples/stm32l1/src/bin/spi.rs b/examples/stm32l1/src/bin/spi.rs new file mode 100644 index 000000000..3cfbe3fc4 --- /dev/null +++ b/examples/stm32l1/src/bin/spi.rs | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(type_alias_impl_trait)] | ||
| 4 | |||
| 5 | #[path = "../example_common.rs"] | ||
| 6 | mod example_common; | ||
| 7 | |||
| 8 | use embassy::executor::Spawner; | ||
| 9 | use embassy_stm32::gpio::{Level, Output, Speed}; | ||
| 10 | use embedded_hal::digital::v2::OutputPin; | ||
| 11 | use example_common::*; | ||
| 12 | |||
| 13 | use embassy_stm32::dma::NoDma; | ||
| 14 | use embassy_stm32::spi::{Config, Spi}; | ||
| 15 | use embassy_stm32::time::Hertz; | ||
| 16 | use embassy_stm32::Peripherals; | ||
| 17 | use embedded_hal::blocking::spi::Transfer; | ||
| 18 | |||
| 19 | #[embassy::main] | ||
| 20 | async fn main(_spawner: Spawner, p: Peripherals) { | ||
| 21 | info!("Hello World, folks!"); | ||
| 22 | |||
| 23 | let mut spi = Spi::new( | ||
| 24 | p.SPI1, | ||
| 25 | p.PA5, | ||
| 26 | p.PA7, | ||
| 27 | p.PA6, | ||
| 28 | NoDma, | ||
| 29 | NoDma, | ||
| 30 | Hertz(1_000_000), | ||
| 31 | Config::default(), | ||
| 32 | ); | ||
| 33 | |||
| 34 | let mut cs = Output::new(p.PA4, Level::High, Speed::VeryHigh); | ||
| 35 | |||
| 36 | loop { | ||
| 37 | let mut buf = [0x0Au8; 4]; | ||
| 38 | unwrap!(cs.set_low()); | ||
| 39 | unwrap!(spi.transfer(&mut buf)); | ||
| 40 | unwrap!(cs.set_high()); | ||
| 41 | info!("xfer {=[u8]:x}", buf); | ||
| 42 | } | ||
| 43 | } | ||
diff --git a/examples/stm32l1/src/example_common.rs b/examples/stm32l1/src/example_common.rs new file mode 100644 index 000000000..54d633837 --- /dev/null +++ b/examples/stm32l1/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/examples/stm32l4/.cargo/config.toml b/examples/stm32l4/.cargo/config.toml index 38dd98d1e..b157e3aeb 100644 --- a/examples/stm32l4/.cargo/config.toml +++ b/examples/stm32l4/.cargo/config.toml | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] | 1 | [target.'cfg(all(target_arch = "arm", target_os = "none"))'] |
| 2 | # replace STM32F429ZITx with your chip as listed in `probe-run --list-chips` | 2 | # replace STM32F429ZITx with your chip as listed in `probe-run --list-chips` |
| 3 | runner = "probe-run --chip STM32L4S5VI" | 3 | #runner = "probe-run --chip STM32L475VGT6" |
| 4 | runner = "probe-run --chip STM32L475VG" | ||
| 4 | 5 | ||
| 5 | rustflags = [ | 6 | rustflags = [ |
| 6 | # LLD (shipped with the Rust toolchain) is used as the default linker | 7 | # LLD (shipped with the Rust toolchain) is used as the default linker |
diff --git a/rust-toolchain.toml b/rust-toolchain.toml index d7ad907fd..8f3473433 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml | |||
| @@ -3,4 +3,4 @@ | |||
| 3 | [toolchain] | 3 | [toolchain] |
| 4 | channel = "nightly-2021-08-18" | 4 | channel = "nightly-2021-08-18" |
| 5 | components = [ "rust-src", "rustfmt" ] | 5 | components = [ "rust-src", "rustfmt" ] |
| 6 | targets = [ "thumbv7em-none-eabi", "thumbv6m-none-eabi", "thumbv7em-none-eabihf", "wasm32-unknown-unknown" ] | 6 | targets = [ "thumbv7em-none-eabi", "thumbv7m-none-eabi", "thumbv6m-none-eabi", "thumbv7em-none-eabihf", "wasm32-unknown-unknown" ] |
diff --git a/stm32-data b/stm32-data | |||
| Subproject 3fb217ad3eebe2d8808b8af4d04ce051c69ecb7 | Subproject 7f5f8e7c641d74a0e97e2d84bac61b7c6c267a7 | ||
diff --git a/stm32-gen-features/src/lib.rs b/stm32-gen-features/src/lib.rs index 597d78b07..75eb7d756 100644 --- a/stm32-gen-features/src/lib.rs +++ b/stm32-gen-features/src/lib.rs | |||
| @@ -2,11 +2,12 @@ | |||
| 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; 8] = [ | 5 | const SUPPORTED_FAMILIES: [&str; 9] = [ |
| 6 | "stm32f0", | 6 | "stm32f0", |
| 7 | "stm32f4", | 7 | "stm32f4", |
| 8 | "stm32g0", | 8 | "stm32g0", |
| 9 | "stm32l0", | 9 | "stm32l0", |
| 10 | "stm32l1", | ||
| 10 | "stm32l4", | 11 | "stm32l4", |
| 11 | "stm32h7", | 12 | "stm32h7", |
| 12 | "stm32wb55", | 13 | "stm32wb55", |
diff --git a/stm32-metapac-gen/src/assets/build.rs b/stm32-metapac-gen/src/assets/build.rs index 4110fe485..1c9411151 100644 --- a/stm32-metapac-gen/src/assets/build.rs +++ b/stm32-metapac-gen/src/assets/build.rs | |||
| @@ -9,6 +9,17 @@ fn main() { | |||
| 9 | .unwrap() | 9 | .unwrap() |
| 10 | .to_ascii_lowercase(); | 10 | .to_ascii_lowercase(); |
| 11 | 11 | ||
| 12 | let mut s = chip_name.split('_'); | ||
| 13 | let mut chip_name: String = s.next().unwrap().to_string(); | ||
| 14 | if let Some(c) = s.next() { | ||
| 15 | if !c.starts_with("CM") { | ||
| 16 | chip_name.push('-'); | ||
| 17 | } else { | ||
| 18 | chip_name.push('_'); | ||
| 19 | } | ||
| 20 | chip_name.push_str(c); | ||
| 21 | } | ||
| 22 | |||
| 12 | #[cfg(feature = "memory-x")] | 23 | #[cfg(feature = "memory-x")] |
| 13 | println!("cargo:rustc-link-search=src/chips/{}/memory_x/", _chip_name); | 24 | println!("cargo:rustc-link-search=src/chips/{}/memory_x/", _chip_name); |
| 14 | 25 | ||
diff --git a/stm32-metapac-gen/src/lib.rs b/stm32-metapac-gen/src/lib.rs index 3bfd5297f..5c0f1d00c 100644 --- a/stm32-metapac-gen/src/lib.rs +++ b/stm32-metapac-gen/src/lib.rs | |||
| @@ -218,7 +218,7 @@ pub fn gen(options: Options) { | |||
| 218 | let core_name: Option<&str> = if let Some(c) = s.next() { | 218 | let core_name: Option<&str> = if let Some(c) = s.next() { |
| 219 | if !c.starts_with("CM") { | 219 | if !c.starts_with("CM") { |
| 220 | println!("Core not detected, adding as variant"); | 220 | println!("Core not detected, adding as variant"); |
| 221 | chip_name.push_str("-"); | 221 | chip_name.push('-'); |
| 222 | chip_name.push_str(c); | 222 | chip_name.push_str(c); |
| 223 | None | 223 | None |
| 224 | } else { | 224 | } else { |
diff --git a/stm32-metapac/build.rs b/stm32-metapac/build.rs index ca964c9ec..d840d8fe0 100644 --- a/stm32-metapac/build.rs +++ b/stm32-metapac/build.rs | |||
| @@ -22,6 +22,17 @@ fn main() { | |||
| 22 | chips: vec![chip_name.clone()], | 22 | chips: vec![chip_name.clone()], |
| 23 | }); | 23 | }); |
| 24 | 24 | ||
| 25 | let mut s = chip_name.split('_'); | ||
| 26 | let mut chip_name: String = s.next().unwrap().to_string(); | ||
| 27 | if let Some(c) = s.next() { | ||
| 28 | if !c.starts_with("CM") { | ||
| 29 | chip_name.push('-'); | ||
| 30 | } else { | ||
| 31 | chip_name.push('_'); | ||
| 32 | } | ||
| 33 | chip_name.push_str(c); | ||
| 34 | } | ||
| 35 | |||
| 25 | println!( | 36 | println!( |
| 26 | "cargo:rustc-link-search={}/src/chips/{}", | 37 | "cargo:rustc-link-search={}/src/chips/{}", |
| 27 | out_dir.display(), | 38 | out_dir.display(), |
