From bd9589d0ce71a2aa41c9fdf439d6de6349a09d83 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 11 May 2021 03:04:59 +0200 Subject: [PATCH 01/10] nrf: add support for nrf52805, nrf52811, nrf52820 --- .github/workflows/rust.yml | 21 +- embassy-macros/src/lib.rs | 2 +- embassy-nrf-examples/Cargo.toml | 2 +- embassy-nrf-examples/src/bin/spim.rs | 9 +- embassy-nrf/Cargo.toml | 16 +- embassy-nrf/src/chips/nrf52805.rs | 182 ++++++++++++++++++ embassy-nrf/src/chips/nrf52810.rs | 183 ++++++++++++++++++ embassy-nrf/src/chips/nrf52811.rs | 184 ++++++++++++++++++ embassy-nrf/src/chips/nrf52820.rs | 185 ++++++++++++++++++ embassy-nrf/src/chips/nrf52832.rs | 202 +++++++++++++++++++ embassy-nrf/src/chips/nrf52833.rs | 244 +++++++++++++++++++++++ embassy-nrf/src/chips/nrf52840.rs | 251 ++++++++++++++++++++++++ embassy-nrf/src/gpio.rs | 70 +------ embassy-nrf/src/gpiote.rs | 16 +- embassy-nrf/src/interrupt.rs | 210 -------------------- embassy-nrf/src/lib.rs | 278 +++++---------------------- embassy-nrf/src/qspi.rs | 22 +-- embassy-nrf/src/spim.rs | 47 +++-- embassy-nrf/src/timer.rs | 34 ++-- embassy-nrf/src/uarte.rs | 26 ++- embassy-nrf/src/util.rs | 18 ++ 21 files changed, 1600 insertions(+), 602 deletions(-) create mode 100644 embassy-nrf/src/chips/nrf52805.rs create mode 100644 embassy-nrf/src/chips/nrf52810.rs create mode 100644 embassy-nrf/src/chips/nrf52811.rs create mode 100644 embassy-nrf/src/chips/nrf52820.rs create mode 100644 embassy-nrf/src/chips/nrf52832.rs create mode 100644 embassy-nrf/src/chips/nrf52833.rs create mode 100644 embassy-nrf/src/chips/nrf52840.rs delete mode 100644 embassy-nrf/src/interrupt.rs create mode 100644 embassy-nrf/src/util.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 8613f7e0d..cf70e2e5c 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -30,22 +30,31 @@ jobs: target: thumbv7em-none-eabi - package: embassy-nrf target: thumbv7em-none-eabi - features: 52810 + features: nrf52805 - package: embassy-nrf target: thumbv7em-none-eabi - features: 52832 + features: nrf52810 - package: embassy-nrf target: thumbv7em-none-eabi - features: 52833 + features: nrf52811 - package: embassy-nrf target: thumbv7em-none-eabi - features: 52840 + features: nrf52820 - package: embassy-nrf target: thumbv7em-none-eabi - features: 52840,log + features: nrf52832 - package: embassy-nrf target: thumbv7em-none-eabi - features: 52840,defmt + features: nrf52833 + - package: embassy-nrf + target: thumbv7em-none-eabi + features: nrf52840 + - package: embassy-nrf + target: thumbv7em-none-eabi + features: nrf52840,log + - package: embassy-nrf + target: thumbv7em-none-eabi + features: nrf52840,defmt - package: embassy-stm32-examples target: thumbv7em-none-eabi features: stm32f405 diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs index 64411f5b4..ce643ae89 100644 --- a/embassy-macros/src/lib.rs +++ b/embassy-macros/src/lib.rs @@ -130,7 +130,7 @@ pub fn interrupt_declare(item: TokenStream) -> TokenStream { let result = quote! { #[allow(non_camel_case_types)] pub struct #name_interrupt(()); - unsafe impl Interrupt for #name_interrupt { + unsafe impl ::embassy::interrupt::Interrupt for #name_interrupt { type Priority = crate::interrupt::Priority; fn number(&self) -> u16 { use cortex_m::interrupt::InterruptNumber; diff --git a/embassy-nrf-examples/Cargo.toml b/embassy-nrf-examples/Cargo.toml index 29614f133..4cec37522 100644 --- a/embassy-nrf-examples/Cargo.toml +++ b/embassy-nrf-examples/Cargo.toml @@ -19,7 +19,7 @@ defmt-error = [] [dependencies] embassy = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] } embassy-traits = { version = "0.1.0", path = "../embassy-traits", features = ["defmt"] } -embassy-nrf = { version = "0.1.0", path = "../embassy-nrf", features = ["defmt", "defmt-trace", "52840"] } +embassy-nrf = { version = "0.1.0", path = "../embassy-nrf", features = ["defmt", "defmt-trace", "nrf52840"] } defmt = "0.2.0" defmt-rtt = "0.2.0" diff --git a/embassy-nrf-examples/src/bin/spim.rs b/embassy-nrf-examples/src/bin/spim.rs index 27486374f..ccda75765 100644 --- a/embassy-nrf-examples/src/bin/spim.rs +++ b/embassy-nrf-examples/src/bin/spim.rs @@ -24,14 +24,11 @@ async fn main(spawner: Spawner) { let p = unsafe { Peripherals::steal() }; - let config = spim::Config { - frequency: spim::Frequency::M16, - mode: spim::MODE_0, - orc: 0x00, - }; + let mut config = spim::Config::default(); + config.frequency = spim::Frequency::M16; let irq = interrupt::take!(SPIM3); - let mut spim = spim::Spim::new(p.SPIM3, irq, p.P0_29, p.P0_28, p.P0_30, config); + let mut spim = spim::Spim::new(p.SPI3, irq, p.P0_29, p.P0_28, p.P0_30, config); let mut ncs = Output::new(p.P0_31, Level::High, OutputDrive::Standard); diff --git a/embassy-nrf/Cargo.toml b/embassy-nrf/Cargo.toml index f482f0493..07524fa2d 100644 --- a/embassy-nrf/Cargo.toml +++ b/embassy-nrf/Cargo.toml @@ -11,11 +11,13 @@ defmt-info = [ ] defmt-warn = [ ] defmt-error = [ ] -52810 = ["nrf52810-pac"] -52811 = ["nrf52811-pac"] -52832 = ["nrf52832-pac"] -52833 = ["nrf52833-pac"] -52840 = ["nrf52840-pac"] +nrf52805 = ["nrf52805-pac"] +nrf52810 = ["nrf52810-pac"] +nrf52811 = ["nrf52811-pac"] +nrf52820 = ["nrf52820-pac"] +nrf52832 = ["nrf52832-pac"] +nrf52833 = ["nrf52833-pac"] +nrf52840 = ["nrf52840-pac"] [dependencies] @@ -30,10 +32,12 @@ cortex-m = "0.7.1" embedded-hal = { version = "0.2.4" } embedded-dma = { version = "0.1.2" } futures = { version = "0.3.5", default-features = false } +critical-section = "0.2.1" +nrf52805-pac = { version = "0.1.0", optional = true, features = [ "rt" ], git = "https://github.com/Dirbaio/nrf52805-pac"} nrf52810-pac = { version = "0.9.0", optional = true, features = [ "rt" ]} nrf52811-pac = { version = "0.9.1", optional = true, features = [ "rt" ]} +nrf52820-pac = { version = "0.1.0", optional = true, features = [ "rt" ], git = "https://github.com/Dirbaio/nrf52820-pac"} nrf52832-pac = { version = "0.9.0", optional = true, features = [ "rt" ]} nrf52833-pac = { version = "0.9.0", optional = true, features = [ "rt" ]} nrf52840-pac = { version = "0.9.0", optional = true, features = [ "rt" ]} -critical-section = "0.2.1" diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs new file mode 100644 index 000000000..8b2ba7c00 --- /dev/null +++ b/embassy-nrf/src/chips/nrf52805.rs @@ -0,0 +1,182 @@ +pub use nrf52805_pac as pac; + +pub const EASY_DMA_SIZE: usize = (1 << 14) - 1; +pub const FORCE_COPY_BUFFER_SIZE: usize = 256; + +embassy_extras::peripherals! { + // RTC + RTC0, + RTC1, + + // UARTE + UARTE0, + + // SPI/TWI + TWI0, + SPI0, + + // SAADC + SAADC, + + // TIMER + TIMER0, + TIMER1, + TIMER2, + + // GPIOTE + GPIOTE, + GPIOTE_CH0, + GPIOTE_CH1, + GPIOTE_CH2, + GPIOTE_CH3, + GPIOTE_CH4, + GPIOTE_CH5, + GPIOTE_CH6, + GPIOTE_CH7, + + // PPI + PPI_CH0, + PPI_CH1, + PPI_CH2, + PPI_CH3, + PPI_CH4, + PPI_CH5, + PPI_CH6, + PPI_CH7, + PPI_CH8, + PPI_CH9, + PPI_CH10, + PPI_CH11, + PPI_CH12, + PPI_CH13, + PPI_CH14, + PPI_CH15, + PPI_CH16, + PPI_CH17, + PPI_CH18, + PPI_CH19, + PPI_CH20, + PPI_CH21, + PPI_CH22, + PPI_CH23, + PPI_CH24, + PPI_CH25, + PPI_CH26, + PPI_CH27, + PPI_CH28, + PPI_CH29, + PPI_CH30, + PPI_CH31, + + PPI_GROUP0, + PPI_GROUP1, + PPI_GROUP2, + PPI_GROUP3, + PPI_GROUP4, + PPI_GROUP5, + + // GPIO port 0 + P0_00, + P0_01, + P0_02, + P0_03, + P0_04, + P0_05, + P0_06, + P0_07, + P0_08, + P0_09, + P0_10, + P0_11, + P0_12, + P0_13, + P0_14, + P0_15, + P0_16, + P0_17, + P0_18, + P0_19, + P0_20, + P0_21, + P0_22, + P0_23, + P0_24, + P0_25, + P0_26, + P0_27, + P0_28, + P0_29, + P0_30, + P0_31, +} + +impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); + +impl_spim!(SPI0, SPIM0, SPIM0_SPIS0_SPI0); + +impl_twim!(TWI0, TWIM0, TWIM0_TWIS0_TWI0); + +impl_timer!(TIMER0, TIMER0, TIMER0); +impl_timer!(TIMER1, TIMER1, TIMER1); +impl_timer!(TIMER2, TIMER2, TIMER2); + +impl_pin!(P0_00, 0, 0); +impl_pin!(P0_01, 0, 1); +impl_pin!(P0_02, 0, 2); +impl_pin!(P0_03, 0, 3); +impl_pin!(P0_04, 0, 4); +impl_pin!(P0_05, 0, 5); +impl_pin!(P0_06, 0, 6); +impl_pin!(P0_07, 0, 7); +impl_pin!(P0_08, 0, 8); +impl_pin!(P0_09, 0, 9); +impl_pin!(P0_10, 0, 10); +impl_pin!(P0_11, 0, 11); +impl_pin!(P0_12, 0, 12); +impl_pin!(P0_13, 0, 13); +impl_pin!(P0_14, 0, 14); +impl_pin!(P0_15, 0, 15); +impl_pin!(P0_16, 0, 16); +impl_pin!(P0_17, 0, 17); +impl_pin!(P0_18, 0, 18); +impl_pin!(P0_19, 0, 19); +impl_pin!(P0_20, 0, 20); +impl_pin!(P0_21, 0, 21); +impl_pin!(P0_22, 0, 22); +impl_pin!(P0_23, 0, 23); +impl_pin!(P0_24, 0, 24); +impl_pin!(P0_25, 0, 25); +impl_pin!(P0_26, 0, 26); +impl_pin!(P0_27, 0, 27); +impl_pin!(P0_28, 0, 28); +impl_pin!(P0_29, 0, 29); +impl_pin!(P0_30, 0, 30); +impl_pin!(P0_31, 0, 31); + +pub mod irqs { + use embassy_macros::interrupt_declare as declare; + declare!(POWER_CLOCK); + declare!(RADIO); + declare!(UARTE0_UART0); + declare!(TWIM0_TWIS0_TWI0); + declare!(SPIM0_SPIS0_SPI0); + declare!(GPIOTE); + declare!(SAADC); + declare!(TIMER0); + declare!(TIMER1); + declare!(TIMER2); + declare!(RTC0); + declare!(TEMP); + declare!(RNG); + declare!(ECB); + declare!(CCM_AAR); + declare!(WDT); + declare!(RTC1); + declare!(QDEC); + declare!(SWI0_EGU0); + declare!(SWI1_EGU1); + declare!(SWI2); + declare!(SWI3); + declare!(SWI4); + declare!(SWI5); +} diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs new file mode 100644 index 000000000..7fe35b27f --- /dev/null +++ b/embassy-nrf/src/chips/nrf52810.rs @@ -0,0 +1,183 @@ +pub use nrf52810_pac as pac; + +pub const EASY_DMA_SIZE: usize = (1 << 10) - 1; +pub const FORCE_COPY_BUFFER_SIZE: usize = 256; + +embassy_extras::peripherals! { + // RTC + RTC0, + RTC1, + + // UARTE + UARTE0, + + // SPI/TWI + TWI0, + SPI0, + + // SAADC + SAADC, + + // TIMER + TIMER0, + TIMER1, + TIMER2, + + // GPIOTE + GPIOTE, + GPIOTE_CH0, + GPIOTE_CH1, + GPIOTE_CH2, + GPIOTE_CH3, + GPIOTE_CH4, + GPIOTE_CH5, + GPIOTE_CH6, + GPIOTE_CH7, + + // PPI + PPI_CH0, + PPI_CH1, + PPI_CH2, + PPI_CH3, + PPI_CH4, + PPI_CH5, + PPI_CH6, + PPI_CH7, + PPI_CH8, + PPI_CH9, + PPI_CH10, + PPI_CH11, + PPI_CH12, + PPI_CH13, + PPI_CH14, + PPI_CH15, + PPI_CH16, + PPI_CH17, + PPI_CH18, + PPI_CH19, + PPI_CH20, + PPI_CH21, + PPI_CH22, + PPI_CH23, + PPI_CH24, + PPI_CH25, + PPI_CH26, + PPI_CH27, + PPI_CH28, + PPI_CH29, + PPI_CH30, + PPI_CH31, + + PPI_GROUP0, + PPI_GROUP1, + PPI_GROUP2, + PPI_GROUP3, + PPI_GROUP4, + PPI_GROUP5, + + // GPIO port 0 + P0_00, + P0_01, + P0_02, + P0_03, + P0_04, + P0_05, + P0_06, + P0_07, + P0_08, + P0_09, + P0_10, + P0_11, + P0_12, + P0_13, + P0_14, + P0_15, + P0_16, + P0_17, + P0_18, + P0_19, + P0_20, + P0_21, + P0_22, + P0_23, + P0_24, + P0_25, + P0_26, + P0_27, + P0_28, + P0_29, + P0_30, + P0_31, +} + +impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); + +impl_spim!(SPI0, SPIM0, SPIM0_SPIS0_SPI0); + +impl_timer!(TIMER0, TIMER0, TIMER0); +impl_timer!(TIMER1, TIMER1, TIMER1); +impl_timer!(TIMER2, TIMER2, TIMER2); + +impl_pin!(P0_00, 0, 0); +impl_pin!(P0_01, 0, 1); +impl_pin!(P0_02, 0, 2); +impl_pin!(P0_03, 0, 3); +impl_pin!(P0_04, 0, 4); +impl_pin!(P0_05, 0, 5); +impl_pin!(P0_06, 0, 6); +impl_pin!(P0_07, 0, 7); +impl_pin!(P0_08, 0, 8); +impl_pin!(P0_09, 0, 9); +impl_pin!(P0_10, 0, 10); +impl_pin!(P0_11, 0, 11); +impl_pin!(P0_12, 0, 12); +impl_pin!(P0_13, 0, 13); +impl_pin!(P0_14, 0, 14); +impl_pin!(P0_15, 0, 15); +impl_pin!(P0_16, 0, 16); +impl_pin!(P0_17, 0, 17); +impl_pin!(P0_18, 0, 18); +impl_pin!(P0_19, 0, 19); +impl_pin!(P0_20, 0, 20); +impl_pin!(P0_21, 0, 21); +impl_pin!(P0_22, 0, 22); +impl_pin!(P0_23, 0, 23); +impl_pin!(P0_24, 0, 24); +impl_pin!(P0_25, 0, 25); +impl_pin!(P0_26, 0, 26); +impl_pin!(P0_27, 0, 27); +impl_pin!(P0_28, 0, 28); +impl_pin!(P0_29, 0, 29); +impl_pin!(P0_30, 0, 30); +impl_pin!(P0_31, 0, 31); + +pub mod irqs { + use embassy_macros::interrupt_declare as declare; + declare!(POWER_CLOCK); + declare!(RADIO); + declare!(UARTE0_UART0); + declare!(TWIM0_TWIS0_TWI0); + declare!(SPIM0_SPIS0_SPI0); + declare!(GPIOTE); + declare!(SAADC); + declare!(TIMER0); + declare!(TIMER1); + declare!(TIMER2); + declare!(RTC0); + declare!(TEMP); + declare!(RNG); + declare!(ECB); + declare!(CCM_AAR); + declare!(WDT); + declare!(RTC1); + declare!(QDEC); + declare!(COMP); + declare!(SWI0_EGU0); + declare!(SWI1_EGU1); + declare!(SWI2); + declare!(SWI3); + declare!(SWI4); + declare!(SWI5); + declare!(PWM0); + declare!(PDM); +} diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs new file mode 100644 index 000000000..e3f4f18ba --- /dev/null +++ b/embassy-nrf/src/chips/nrf52811.rs @@ -0,0 +1,184 @@ +pub use nrf52811_pac as pac; + +pub const EASY_DMA_SIZE: usize = (1 << 14) - 1; +pub const FORCE_COPY_BUFFER_SIZE: usize = 256; + +embassy_extras::peripherals! { + // RTC + RTC0, + RTC1, + + // UARTE + UARTE0, + + // SPI/TWI + TWISPI0, + SPI1, + + // SAADC + SAADC, + + // TIMER + TIMER0, + TIMER1, + TIMER2, + + // GPIOTE + GPIOTE, + GPIOTE_CH0, + GPIOTE_CH1, + GPIOTE_CH2, + GPIOTE_CH3, + GPIOTE_CH4, + GPIOTE_CH5, + GPIOTE_CH6, + GPIOTE_CH7, + + // PPI + PPI_CH0, + PPI_CH1, + PPI_CH2, + PPI_CH3, + PPI_CH4, + PPI_CH5, + PPI_CH6, + PPI_CH7, + PPI_CH8, + PPI_CH9, + PPI_CH10, + PPI_CH11, + PPI_CH12, + PPI_CH13, + PPI_CH14, + PPI_CH15, + PPI_CH16, + PPI_CH17, + PPI_CH18, + PPI_CH19, + PPI_CH20, + PPI_CH21, + PPI_CH22, + PPI_CH23, + PPI_CH24, + PPI_CH25, + PPI_CH26, + PPI_CH27, + PPI_CH28, + PPI_CH29, + PPI_CH30, + PPI_CH31, + + PPI_GROUP0, + PPI_GROUP1, + PPI_GROUP2, + PPI_GROUP3, + PPI_GROUP4, + PPI_GROUP5, + + // GPIO port 0 + P0_00, + P0_01, + P0_02, + P0_03, + P0_04, + P0_05, + P0_06, + P0_07, + P0_08, + P0_09, + P0_10, + P0_11, + P0_12, + P0_13, + P0_14, + P0_15, + P0_16, + P0_17, + P0_18, + P0_19, + P0_20, + P0_21, + P0_22, + P0_23, + P0_24, + P0_25, + P0_26, + P0_27, + P0_28, + P0_29, + P0_30, + P0_31, +} + +impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); + +impl_spim!(TWISPI0, SPIM0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0); +impl_spim!(SPI1, SPIM1, SPIM1_SPIS1_SPI1); + +impl_timer!(TIMER0, TIMER0, TIMER0); +impl_timer!(TIMER1, TIMER1, TIMER1); +impl_timer!(TIMER2, TIMER2, TIMER2); + +impl_pin!(P0_00, 0, 0); +impl_pin!(P0_01, 0, 1); +impl_pin!(P0_02, 0, 2); +impl_pin!(P0_03, 0, 3); +impl_pin!(P0_04, 0, 4); +impl_pin!(P0_05, 0, 5); +impl_pin!(P0_06, 0, 6); +impl_pin!(P0_07, 0, 7); +impl_pin!(P0_08, 0, 8); +impl_pin!(P0_09, 0, 9); +impl_pin!(P0_10, 0, 10); +impl_pin!(P0_11, 0, 11); +impl_pin!(P0_12, 0, 12); +impl_pin!(P0_13, 0, 13); +impl_pin!(P0_14, 0, 14); +impl_pin!(P0_15, 0, 15); +impl_pin!(P0_16, 0, 16); +impl_pin!(P0_17, 0, 17); +impl_pin!(P0_18, 0, 18); +impl_pin!(P0_19, 0, 19); +impl_pin!(P0_20, 0, 20); +impl_pin!(P0_21, 0, 21); +impl_pin!(P0_22, 0, 22); +impl_pin!(P0_23, 0, 23); +impl_pin!(P0_24, 0, 24); +impl_pin!(P0_25, 0, 25); +impl_pin!(P0_26, 0, 26); +impl_pin!(P0_27, 0, 27); +impl_pin!(P0_28, 0, 28); +impl_pin!(P0_29, 0, 29); +impl_pin!(P0_30, 0, 30); +impl_pin!(P0_31, 0, 31); + +pub mod irqs { + use embassy_macros::interrupt_declare as declare; + declare!(POWER_CLOCK); + declare!(RADIO); + declare!(UARTE0_UART0); + declare!(TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0); + declare!(SPIM1_SPIS1_SPI1); + declare!(GPIOTE); + declare!(SAADC); + declare!(TIMER0); + declare!(TIMER1); + declare!(TIMER2); + declare!(RTC0); + declare!(TEMP); + declare!(RNG); + declare!(ECB); + declare!(CCM_AAR); + declare!(WDT); + declare!(RTC1); + declare!(QDEC); + declare!(COMP); + declare!(SWI0_EGU0); + declare!(SWI1_EGU1); + declare!(SWI2); + declare!(SWI3); + declare!(SWI4); + declare!(SWI5); + declare!(PWM0); + declare!(PDM); +} diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs new file mode 100644 index 000000000..e367a7916 --- /dev/null +++ b/embassy-nrf/src/chips/nrf52820.rs @@ -0,0 +1,185 @@ +pub use nrf52820_pac as pac; + +pub const EASY_DMA_SIZE: usize = (1 << 15) - 1; +pub const FORCE_COPY_BUFFER_SIZE: usize = 512; + +embassy_extras::peripherals! { + // RTC + RTC0, + RTC1, + + // UARTE + UARTE0, + + // SPI/TWI + TWISPI0, + TWISPI1, + + // SAADC + SAADC, + + // TIMER + TIMER0, + TIMER1, + TIMER2, + TIMER3, + + // GPIOTE + GPIOTE, + GPIOTE_CH0, + GPIOTE_CH1, + GPIOTE_CH2, + GPIOTE_CH3, + GPIOTE_CH4, + GPIOTE_CH5, + GPIOTE_CH6, + GPIOTE_CH7, + + // PPI + PPI_CH0, + PPI_CH1, + PPI_CH2, + PPI_CH3, + PPI_CH4, + PPI_CH5, + PPI_CH6, + PPI_CH7, + PPI_CH8, + PPI_CH9, + PPI_CH10, + PPI_CH11, + PPI_CH12, + PPI_CH13, + PPI_CH14, + PPI_CH15, + PPI_CH16, + PPI_CH17, + PPI_CH18, + PPI_CH19, + PPI_CH20, + PPI_CH21, + PPI_CH22, + PPI_CH23, + PPI_CH24, + PPI_CH25, + PPI_CH26, + PPI_CH27, + PPI_CH28, + PPI_CH29, + PPI_CH30, + PPI_CH31, + + PPI_GROUP0, + PPI_GROUP1, + PPI_GROUP2, + PPI_GROUP3, + PPI_GROUP4, + PPI_GROUP5, + + // GPIO port 0 + P0_00, + P0_01, + P0_02, + P0_03, + P0_04, + P0_05, + P0_06, + P0_07, + P0_08, + P0_09, + P0_10, + P0_11, + P0_12, + P0_13, + P0_14, + P0_15, + P0_16, + P0_17, + P0_18, + P0_19, + P0_20, + P0_21, + P0_22, + P0_23, + P0_24, + P0_25, + P0_26, + P0_27, + P0_28, + P0_29, + P0_30, + P0_31, +} + +impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); + +impl_spim!(TWISPI0, SPIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); +impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); + +impl_timer!(TIMER0, TIMER0, TIMER0); +impl_timer!(TIMER1, TIMER1, TIMER1); +impl_timer!(TIMER2, TIMER2, TIMER2); +impl_timer!(TIMER3, TIMER3, TIMER3, extended); + +impl_pin!(P0_00, 0, 0); +impl_pin!(P0_01, 0, 1); +impl_pin!(P0_02, 0, 2); +impl_pin!(P0_03, 0, 3); +impl_pin!(P0_04, 0, 4); +impl_pin!(P0_05, 0, 5); +impl_pin!(P0_06, 0, 6); +impl_pin!(P0_07, 0, 7); +impl_pin!(P0_08, 0, 8); +impl_pin!(P0_09, 0, 9); +impl_pin!(P0_10, 0, 10); +impl_pin!(P0_11, 0, 11); +impl_pin!(P0_12, 0, 12); +impl_pin!(P0_13, 0, 13); +impl_pin!(P0_14, 0, 14); +impl_pin!(P0_15, 0, 15); +impl_pin!(P0_16, 0, 16); +impl_pin!(P0_17, 0, 17); +impl_pin!(P0_18, 0, 18); +impl_pin!(P0_19, 0, 19); +impl_pin!(P0_20, 0, 20); +impl_pin!(P0_21, 0, 21); +impl_pin!(P0_22, 0, 22); +impl_pin!(P0_23, 0, 23); +impl_pin!(P0_24, 0, 24); +impl_pin!(P0_25, 0, 25); +impl_pin!(P0_26, 0, 26); +impl_pin!(P0_27, 0, 27); +impl_pin!(P0_28, 0, 28); +impl_pin!(P0_29, 0, 29); +impl_pin!(P0_30, 0, 30); +impl_pin!(P0_31, 0, 31); + +pub mod irqs { + use embassy_macros::interrupt_declare as declare; + declare!(POWER_CLOCK); + declare!(RADIO); + declare!(UARTE0_UART0); + declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); + declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); + declare!(GPIOTE); + declare!(TIMER0); + declare!(TIMER1); + declare!(TIMER2); + declare!(RTC0); + declare!(TEMP); + declare!(RNG); + declare!(ECB); + declare!(CCM_AAR); + declare!(WDT); + declare!(RTC1); + declare!(QDEC); + declare!(COMP); + declare!(SWI0_EGU0); + declare!(SWI1_EGU1); + declare!(SWI2_EGU2); + declare!(SWI3_EGU3); + declare!(SWI4_EGU4); + declare!(SWI5_EGU5); + declare!(TIMER3); + declare!(USBD); +} diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs new file mode 100644 index 000000000..e0669d93e --- /dev/null +++ b/embassy-nrf/src/chips/nrf52832.rs @@ -0,0 +1,202 @@ +pub use nrf52832_pac as pac; + +pub const EASY_DMA_SIZE: usize = (1 << 8) - 1; +pub const FORCE_COPY_BUFFER_SIZE: usize = 255; + +embassy_extras::peripherals! { + // RTC + RTC0, + RTC1, + RTC2, + + // UARTE + UARTE0, + + // SPI/TWI + TWISPI0, + TWISPI1, + SPI2, + SPI3, + + // SAADC + SAADC, + + // TIMER + TIMER0, + TIMER1, + TIMER2, + TIMER3, + TIMER4, + + // GPIOTE + GPIOTE, + GPIOTE_CH0, + GPIOTE_CH1, + GPIOTE_CH2, + GPIOTE_CH3, + GPIOTE_CH4, + GPIOTE_CH5, + GPIOTE_CH6, + GPIOTE_CH7, + + // PPI + PPI_CH0, + PPI_CH1, + PPI_CH2, + PPI_CH3, + PPI_CH4, + PPI_CH5, + PPI_CH6, + PPI_CH7, + PPI_CH8, + PPI_CH9, + PPI_CH10, + PPI_CH11, + PPI_CH12, + PPI_CH13, + PPI_CH14, + PPI_CH15, + PPI_CH16, + PPI_CH17, + PPI_CH18, + PPI_CH19, + PPI_CH20, + PPI_CH21, + PPI_CH22, + PPI_CH23, + PPI_CH24, + PPI_CH25, + PPI_CH26, + PPI_CH27, + PPI_CH28, + PPI_CH29, + PPI_CH30, + PPI_CH31, + + PPI_GROUP0, + PPI_GROUP1, + PPI_GROUP2, + PPI_GROUP3, + PPI_GROUP4, + PPI_GROUP5, + + // GPIO port 0 + P0_00, + P0_01, + P0_02, + P0_03, + P0_04, + P0_05, + P0_06, + P0_07, + P0_08, + P0_09, + P0_10, + P0_11, + P0_12, + P0_13, + P0_14, + P0_15, + P0_16, + P0_17, + P0_18, + P0_19, + P0_20, + P0_21, + P0_22, + P0_23, + P0_24, + P0_25, + P0_26, + P0_27, + P0_28, + P0_29, + P0_30, + P0_31, +} + +impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); + +impl_spim!(TWISPI0, SPIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); +impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); +impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2); + +impl_timer!(TIMER0, TIMER0, TIMER0); +impl_timer!(TIMER1, TIMER1, TIMER1); +impl_timer!(TIMER2, TIMER2, TIMER2); +impl_timer!(TIMER3, TIMER3, TIMER3, extended); +impl_timer!(TIMER4, TIMER4, TIMER4, extended); + +impl_pin!(P0_00, 0, 0); +impl_pin!(P0_01, 0, 1); +impl_pin!(P0_02, 0, 2); +impl_pin!(P0_03, 0, 3); +impl_pin!(P0_04, 0, 4); +impl_pin!(P0_05, 0, 5); +impl_pin!(P0_06, 0, 6); +impl_pin!(P0_07, 0, 7); +impl_pin!(P0_08, 0, 8); +impl_pin!(P0_09, 0, 9); +impl_pin!(P0_10, 0, 10); +impl_pin!(P0_11, 0, 11); +impl_pin!(P0_12, 0, 12); +impl_pin!(P0_13, 0, 13); +impl_pin!(P0_14, 0, 14); +impl_pin!(P0_15, 0, 15); +impl_pin!(P0_16, 0, 16); +impl_pin!(P0_17, 0, 17); +impl_pin!(P0_18, 0, 18); +impl_pin!(P0_19, 0, 19); +impl_pin!(P0_20, 0, 20); +impl_pin!(P0_21, 0, 21); +impl_pin!(P0_22, 0, 22); +impl_pin!(P0_23, 0, 23); +impl_pin!(P0_24, 0, 24); +impl_pin!(P0_25, 0, 25); +impl_pin!(P0_26, 0, 26); +impl_pin!(P0_27, 0, 27); +impl_pin!(P0_28, 0, 28); +impl_pin!(P0_29, 0, 29); +impl_pin!(P0_30, 0, 30); +impl_pin!(P0_31, 0, 31); + +pub mod irqs { + use embassy_macros::interrupt_declare as declare; + declare!(POWER_CLOCK); + declare!(RADIO); + declare!(UARTE0_UART0); + declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); + declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); + declare!(NFCT); + declare!(GPIOTE); + declare!(SAADC); + declare!(TIMER0); + declare!(TIMER1); + declare!(TIMER2); + declare!(RTC0); + declare!(TEMP); + declare!(RNG); + declare!(ECB); + declare!(CCM_AAR); + declare!(WDT); + declare!(RTC1); + declare!(QDEC); + declare!(COMP_LPCOMP); + declare!(SWI0_EGU0); + declare!(SWI1_EGU1); + declare!(SWI2_EGU2); + declare!(SWI3_EGU3); + declare!(SWI4_EGU4); + declare!(SWI5_EGU5); + declare!(TIMER3); + declare!(TIMER4); + declare!(PWM0); + declare!(PDM); + declare!(MWU); + declare!(PWM1); + declare!(PWM2); + declare!(SPIM2_SPIS2_SPI2); + declare!(RTC2); + declare!(I2S); + declare!(FPU); +} diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs new file mode 100644 index 000000000..a0b434229 --- /dev/null +++ b/embassy-nrf/src/chips/nrf52833.rs @@ -0,0 +1,244 @@ +pub use nrf52833_pac as pac; + +pub const EASY_DMA_SIZE: usize = (1 << 16) - 1; +pub const FORCE_COPY_BUFFER_SIZE: usize = 512; + +embassy_extras::peripherals! { + // RTC + RTC0, + RTC1, + RTC2, + + // UARTE + UARTE0, + UARTE1, + + // SPI/TWI + TWISPI0, + TWISPI1, + SPI2, + SPI3, + + // SAADC + SAADC, + + // TIMER + TIMER0, + TIMER1, + TIMER2, + TIMER3, + TIMER4, + + // GPIOTE + GPIOTE, + GPIOTE_CH0, + GPIOTE_CH1, + GPIOTE_CH2, + GPIOTE_CH3, + GPIOTE_CH4, + GPIOTE_CH5, + GPIOTE_CH6, + GPIOTE_CH7, + + // PPI + PPI_CH0, + PPI_CH1, + PPI_CH2, + PPI_CH3, + PPI_CH4, + PPI_CH5, + PPI_CH6, + PPI_CH7, + PPI_CH8, + PPI_CH9, + PPI_CH10, + PPI_CH11, + PPI_CH12, + PPI_CH13, + PPI_CH14, + PPI_CH15, + PPI_CH16, + PPI_CH17, + PPI_CH18, + PPI_CH19, + PPI_CH20, + PPI_CH21, + PPI_CH22, + PPI_CH23, + PPI_CH24, + PPI_CH25, + PPI_CH26, + PPI_CH27, + PPI_CH28, + PPI_CH29, + PPI_CH30, + PPI_CH31, + + PPI_GROUP0, + PPI_GROUP1, + PPI_GROUP2, + PPI_GROUP3, + PPI_GROUP4, + PPI_GROUP5, + + // GPIO port 0 + P0_00, + P0_01, + P0_02, + P0_03, + P0_04, + P0_05, + P0_06, + P0_07, + P0_08, + P0_09, + P0_10, + P0_11, + P0_12, + P0_13, + P0_14, + P0_15, + P0_16, + P0_17, + P0_18, + P0_19, + P0_20, + P0_21, + P0_22, + P0_23, + P0_24, + P0_25, + P0_26, + P0_27, + P0_28, + P0_29, + P0_30, + P0_31, + + // GPIO port 1 + P1_00, + P1_01, + P1_02, + P1_03, + P1_04, + P1_05, + P1_06, + P1_07, + P1_08, + P1_09, + P1_10, + P1_11, + P1_12, + P1_13, + P1_14, + P1_15, +} + +impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); +impl_uarte!(UARTE1, UARTE1, UARTE1); + +impl_spim!(TWISPI0, SPIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); +impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); +impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2); +impl_spim!(SPI3, SPIM3, SPIM3); + +impl_timer!(TIMER0, TIMER0, TIMER0); +impl_timer!(TIMER1, TIMER1, TIMER1); +impl_timer!(TIMER2, TIMER2, TIMER2); +impl_timer!(TIMER3, TIMER3, TIMER3, extended); +impl_timer!(TIMER4, TIMER4, TIMER4, extended); + +impl_pin!(P0_00, 0, 0); +impl_pin!(P0_01, 0, 1); +impl_pin!(P0_02, 0, 2); +impl_pin!(P0_03, 0, 3); +impl_pin!(P0_04, 0, 4); +impl_pin!(P0_05, 0, 5); +impl_pin!(P0_06, 0, 6); +impl_pin!(P0_07, 0, 7); +impl_pin!(P0_08, 0, 8); +impl_pin!(P0_09, 0, 9); +impl_pin!(P0_10, 0, 10); +impl_pin!(P0_11, 0, 11); +impl_pin!(P0_12, 0, 12); +impl_pin!(P0_13, 0, 13); +impl_pin!(P0_14, 0, 14); +impl_pin!(P0_15, 0, 15); +impl_pin!(P0_16, 0, 16); +impl_pin!(P0_17, 0, 17); +impl_pin!(P0_18, 0, 18); +impl_pin!(P0_19, 0, 19); +impl_pin!(P0_20, 0, 20); +impl_pin!(P0_21, 0, 21); +impl_pin!(P0_22, 0, 22); +impl_pin!(P0_23, 0, 23); +impl_pin!(P0_24, 0, 24); +impl_pin!(P0_25, 0, 25); +impl_pin!(P0_26, 0, 26); +impl_pin!(P0_27, 0, 27); +impl_pin!(P0_28, 0, 28); +impl_pin!(P0_29, 0, 29); +impl_pin!(P0_30, 0, 30); +impl_pin!(P0_31, 0, 31); + +impl_pin!(P1_00, 1, 0); +impl_pin!(P1_01, 1, 1); +impl_pin!(P1_02, 1, 2); +impl_pin!(P1_03, 1, 3); +impl_pin!(P1_04, 1, 4); +impl_pin!(P1_05, 1, 5); +impl_pin!(P1_06, 1, 6); +impl_pin!(P1_07, 1, 7); +impl_pin!(P1_08, 1, 8); +impl_pin!(P1_09, 1, 9); +impl_pin!(P1_10, 1, 10); +impl_pin!(P1_11, 1, 11); +impl_pin!(P1_12, 1, 12); +impl_pin!(P1_13, 1, 13); +impl_pin!(P1_14, 1, 14); +impl_pin!(P1_15, 1, 15); + +pub mod irqs { + use embassy_macros::interrupt_declare as declare; + declare!(POWER_CLOCK); + declare!(RADIO); + declare!(UARTE0_UART0); + declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); + declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); + declare!(NFCT); + declare!(GPIOTE); + declare!(SAADC); + declare!(TIMER0); + declare!(TIMER1); + declare!(TIMER2); + declare!(RTC0); + declare!(TEMP); + declare!(RNG); + declare!(ECB); + declare!(CCM_AAR); + declare!(WDT); + declare!(RTC1); + declare!(QDEC); + declare!(COMP_LPCOMP); + declare!(SWI0_EGU0); + declare!(SWI1_EGU1); + declare!(SWI2_EGU2); + declare!(SWI3_EGU3); + declare!(SWI4_EGU4); + declare!(SWI5_EGU5); + declare!(TIMER3); + declare!(TIMER4); + declare!(PWM0); + declare!(PDM); + declare!(MWU); + declare!(PWM1); + declare!(PWM2); + declare!(SPIM2_SPIS2_SPI2); + declare!(RTC2); + declare!(I2S); + declare!(FPU); + declare!(USBD); + declare!(UARTE1); + declare!(PWM3); + declare!(SPIM3); +} diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs new file mode 100644 index 000000000..9a9f99201 --- /dev/null +++ b/embassy-nrf/src/chips/nrf52840.rs @@ -0,0 +1,251 @@ +pub use nrf52840_pac as pac; + +pub const EASY_DMA_SIZE: usize = (1 << 16) - 1; +pub const FORCE_COPY_BUFFER_SIZE: usize = 512; + +embassy_extras::peripherals! { + // RTC + RTC0, + RTC1, + RTC2, + + // QSPI + QSPI, + + // UARTE + UARTE0, + UARTE1, + + // SPI/TWI + TWISPI0, + TWISPI1, + SPI2, + SPI3, + + // SAADC + SAADC, + + // TIMER + TIMER0, + TIMER1, + TIMER2, + TIMER3, + TIMER4, + + // GPIOTE + GPIOTE, + GPIOTE_CH0, + GPIOTE_CH1, + GPIOTE_CH2, + GPIOTE_CH3, + GPIOTE_CH4, + GPIOTE_CH5, + GPIOTE_CH6, + GPIOTE_CH7, + + // PPI + PPI_CH0, + PPI_CH1, + PPI_CH2, + PPI_CH3, + PPI_CH4, + PPI_CH5, + PPI_CH6, + PPI_CH7, + PPI_CH8, + PPI_CH9, + PPI_CH10, + PPI_CH11, + PPI_CH12, + PPI_CH13, + PPI_CH14, + PPI_CH15, + PPI_CH16, + PPI_CH17, + PPI_CH18, + PPI_CH19, + PPI_CH20, + PPI_CH21, + PPI_CH22, + PPI_CH23, + PPI_CH24, + PPI_CH25, + PPI_CH26, + PPI_CH27, + PPI_CH28, + PPI_CH29, + PPI_CH30, + PPI_CH31, + + PPI_GROUP0, + PPI_GROUP1, + PPI_GROUP2, + PPI_GROUP3, + PPI_GROUP4, + PPI_GROUP5, + + // GPIO port 0 + P0_00, + P0_01, + P0_02, + P0_03, + P0_04, + P0_05, + P0_06, + P0_07, + P0_08, + P0_09, + P0_10, + P0_11, + P0_12, + P0_13, + P0_14, + P0_15, + P0_16, + P0_17, + P0_18, + P0_19, + P0_20, + P0_21, + P0_22, + P0_23, + P0_24, + P0_25, + P0_26, + P0_27, + P0_28, + P0_29, + P0_30, + P0_31, + + // GPIO port 1 + P1_00, + P1_01, + P1_02, + P1_03, + P1_04, + P1_05, + P1_06, + P1_07, + P1_08, + P1_09, + P1_10, + P1_11, + P1_12, + P1_13, + P1_14, + P1_15, +} + +impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); +impl_uarte!(UARTE1, UARTE1, UARTE1); + +impl_spim!(TWISPI0, SPIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); +impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); +impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2); +impl_spim!(SPI3, SPIM3, SPIM3); + +impl_timer!(TIMER0, TIMER0, TIMER0); +impl_timer!(TIMER1, TIMER1, TIMER1); +impl_timer!(TIMER2, TIMER2, TIMER2); +impl_timer!(TIMER3, TIMER3, TIMER3, extended); +impl_timer!(TIMER4, TIMER4, TIMER4, extended); + +impl_qspi!(QSPI, QSPI, QSPI); + +impl_pin!(P0_00, 0, 0); +impl_pin!(P0_01, 0, 1); +impl_pin!(P0_02, 0, 2); +impl_pin!(P0_03, 0, 3); +impl_pin!(P0_04, 0, 4); +impl_pin!(P0_05, 0, 5); +impl_pin!(P0_06, 0, 6); +impl_pin!(P0_07, 0, 7); +impl_pin!(P0_08, 0, 8); +impl_pin!(P0_09, 0, 9); +impl_pin!(P0_10, 0, 10); +impl_pin!(P0_11, 0, 11); +impl_pin!(P0_12, 0, 12); +impl_pin!(P0_13, 0, 13); +impl_pin!(P0_14, 0, 14); +impl_pin!(P0_15, 0, 15); +impl_pin!(P0_16, 0, 16); +impl_pin!(P0_17, 0, 17); +impl_pin!(P0_18, 0, 18); +impl_pin!(P0_19, 0, 19); +impl_pin!(P0_20, 0, 20); +impl_pin!(P0_21, 0, 21); +impl_pin!(P0_22, 0, 22); +impl_pin!(P0_23, 0, 23); +impl_pin!(P0_24, 0, 24); +impl_pin!(P0_25, 0, 25); +impl_pin!(P0_26, 0, 26); +impl_pin!(P0_27, 0, 27); +impl_pin!(P0_28, 0, 28); +impl_pin!(P0_29, 0, 29); +impl_pin!(P0_30, 0, 30); +impl_pin!(P0_31, 0, 31); + +impl_pin!(P1_00, 1, 0); +impl_pin!(P1_01, 1, 1); +impl_pin!(P1_02, 1, 2); +impl_pin!(P1_03, 1, 3); +impl_pin!(P1_04, 1, 4); +impl_pin!(P1_05, 1, 5); +impl_pin!(P1_06, 1, 6); +impl_pin!(P1_07, 1, 7); +impl_pin!(P1_08, 1, 8); +impl_pin!(P1_09, 1, 9); +impl_pin!(P1_10, 1, 10); +impl_pin!(P1_11, 1, 11); +impl_pin!(P1_12, 1, 12); +impl_pin!(P1_13, 1, 13); +impl_pin!(P1_14, 1, 14); +impl_pin!(P1_15, 1, 15); + +pub mod irqs { + use embassy_macros::interrupt_declare as declare; + declare!(POWER_CLOCK); + declare!(RADIO); + declare!(UARTE0_UART0); + declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); + declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); + declare!(NFCT); + declare!(GPIOTE); + declare!(SAADC); + declare!(TIMER0); + declare!(TIMER1); + declare!(TIMER2); + declare!(RTC0); + declare!(TEMP); + declare!(RNG); + declare!(ECB); + declare!(CCM_AAR); + declare!(WDT); + declare!(RTC1); + declare!(QDEC); + declare!(COMP_LPCOMP); + declare!(SWI0_EGU0); + declare!(SWI1_EGU1); + declare!(SWI2_EGU2); + declare!(SWI3_EGU3); + declare!(SWI4_EGU4); + declare!(SWI5_EGU5); + declare!(TIMER3); + declare!(TIMER4); + declare!(PWM0); + declare!(PDM); + declare!(MWU); + declare!(PWM1); + declare!(PWM2); + declare!(SPIM2_SPIS2_SPI2); + declare!(RTC2); + declare!(I2S); + declare!(FPU); + declare!(USBD); + declare!(UARTE1); + declare!(QSPI); + declare!(CRYPTOCELL); + declare!(PWM3); + declare!(SPIM3); +} diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index 14ac61822..2cdb685d3 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs @@ -1,3 +1,5 @@ +#![macro_use] + use core::convert::Infallible; use core::hint::unreachable_unchecked; use core::marker::PhantomData; @@ -18,7 +20,7 @@ pub enum Port { Port0, /// Port 1, only available on some nRF52 MCUs. - #[cfg(any(feature = "52833", feature = "52840"))] + #[cfg(any(feature = "nrf52833", feature = "nrf52840"))] Port1, } @@ -281,12 +283,12 @@ pub(crate) mod sealed { #[inline] fn _pin(&self) -> u8 { - #[cfg(any(feature = "52833", feature = "52840"))] + #[cfg(any(feature = "nrf52833", feature = "nrf52840"))] { self.pin_port() % 32 } - #[cfg(not(any(feature = "52833", feature = "52840")))] + #[cfg(not(any(feature = "nrf52833", feature = "nrf52840")))] { self.pin_port() } @@ -297,7 +299,7 @@ pub(crate) mod sealed { unsafe { match self.pin_port() / 32 { 0 => &*pac::P0::ptr(), - #[cfg(any(feature = "52833", feature = "52840"))] + #[cfg(any(feature = "nrf52833", feature = "nrf52840"))] 1 => &*pac::P1::ptr(), _ => unreachable_unchecked(), } @@ -341,7 +343,7 @@ pub trait Pin: sealed::Pin + Sized { fn port(&self) -> Port { match self.pin_port() / 32 { 0 => Port::Port0, - #[cfg(any(feature = "52833", feature = "52840"))] + #[cfg(any(feature = "nrf52833", feature = "nrf52840"))] 1 => Port::Port1, _ => unsafe { unreachable_unchecked() }, } @@ -488,8 +490,8 @@ impl OptionalPin for NoPin { macro_rules! impl_pin { ($type:ident, $port_num:expr, $pin_num:expr) => { - impl Pin for peripherals::$type {} - impl sealed::Pin for peripherals::$type { + impl crate::gpio::Pin for peripherals::$type {} + impl crate::gpio::sealed::Pin for peripherals::$type { #[inline] fn pin_port(&self) -> u8 { $port_num * 32 + $pin_num @@ -497,57 +499,3 @@ macro_rules! impl_pin { } }; } - -impl_pin!(P0_00, 0, 0); -impl_pin!(P0_01, 0, 1); -impl_pin!(P0_02, 0, 2); -impl_pin!(P0_03, 0, 3); -impl_pin!(P0_04, 0, 4); -impl_pin!(P0_05, 0, 5); -impl_pin!(P0_06, 0, 6); -impl_pin!(P0_07, 0, 7); -impl_pin!(P0_08, 0, 8); -impl_pin!(P0_09, 0, 9); -impl_pin!(P0_10, 0, 10); -impl_pin!(P0_11, 0, 11); -impl_pin!(P0_12, 0, 12); -impl_pin!(P0_13, 0, 13); -impl_pin!(P0_14, 0, 14); -impl_pin!(P0_15, 0, 15); -impl_pin!(P0_16, 0, 16); -impl_pin!(P0_17, 0, 17); -impl_pin!(P0_18, 0, 18); -impl_pin!(P0_19, 0, 19); -impl_pin!(P0_20, 0, 20); -impl_pin!(P0_21, 0, 21); -impl_pin!(P0_22, 0, 22); -impl_pin!(P0_23, 0, 23); -impl_pin!(P0_24, 0, 24); -impl_pin!(P0_25, 0, 25); -impl_pin!(P0_26, 0, 26); -impl_pin!(P0_27, 0, 27); -impl_pin!(P0_28, 0, 28); -impl_pin!(P0_29, 0, 29); -impl_pin!(P0_30, 0, 30); -impl_pin!(P0_31, 0, 31); - -#[cfg(any(feature = "52833", feature = "52840"))] -mod _p1 { - use super::*; - impl_pin!(P1_00, 1, 0); - impl_pin!(P1_01, 1, 1); - impl_pin!(P1_02, 1, 2); - impl_pin!(P1_03, 1, 3); - impl_pin!(P1_04, 1, 4); - impl_pin!(P1_05, 1, 5); - impl_pin!(P1_06, 1, 6); - impl_pin!(P1_07, 1, 7); - impl_pin!(P1_08, 1, 8); - impl_pin!(P1_09, 1, 9); - impl_pin!(P1_10, 1, 10); - impl_pin!(P1_11, 1, 11); - impl_pin!(P1_12, 1, 12); - impl_pin!(P1_13, 1, 13); - impl_pin!(P1_14, 1, 14); - impl_pin!(P1_15, 1, 15); -} diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index fbd8c093c..bfa5ba68b 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs @@ -17,9 +17,9 @@ use crate::{interrupt, peripherals}; pub const CHANNEL_COUNT: usize = 8; -#[cfg(any(feature = "52833", feature = "52840"))] +#[cfg(any(feature = "nrf52833", feature = "nrf52840"))] pub const PIN_COUNT: usize = 48; -#[cfg(not(any(feature = "52833", feature = "52840")))] +#[cfg(not(any(feature = "nrf52833", feature = "nrf52840")))] pub const PIN_COUNT: usize = 32; const NEW_AW: AtomicWaker = AtomicWaker::new(); @@ -49,9 +49,9 @@ pub struct Initialized { } pub fn initialize(_gpiote: peripherals::GPIOTE, irq: interrupt::GPIOTE) -> Initialized { - #[cfg(any(feature = "52833", feature = "52840"))] + #[cfg(any(feature = "nrf52833", feature = "nrf52840"))] let ports = unsafe { &[&*pac::P0::ptr(), &*pac::P1::ptr()] }; - #[cfg(not(any(feature = "52833", feature = "52840")))] + #[cfg(not(any(feature = "nrf52833", feature = "nrf52840")))] let ports = unsafe { &[&*pac::P0::ptr()] }; for &p in ports { @@ -85,9 +85,9 @@ unsafe fn on_irq(_ctx: *mut ()) { if g.events_port.read().bits() != 0 { g.events_port.write(|w| w); - #[cfg(any(feature = "52833", feature = "52840"))] + #[cfg(any(feature = "nrf52833", feature = "nrf52840"))] let ports = &[&*pac::P0::ptr(), &*pac::P1::ptr()]; - #[cfg(not(any(feature = "52833", feature = "52840")))] + #[cfg(not(any(feature = "nrf52833", feature = "nrf52840")))] let ports = &[&*pac::P0::ptr()]; for (port, &p) in ports.iter().enumerate() { @@ -149,7 +149,7 @@ impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> { InputChannelPolarity::None => w.mode().event().polarity().none(), InputChannelPolarity::Toggle => w.mode().event().polarity().toggle(), }; - #[cfg(any(feature = "52833", feature = "52840"))] + #[cfg(any(feature = "nrf52833", feature = "nrf52840"))] w.port().bit(match pin.pin.port() { Port::Port0 => false, Port::Port1 => true, @@ -237,7 +237,7 @@ impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> { OutputChannelPolarity::Clear => w.polarity().hi_to_lo(), OutputChannelPolarity::Toggle => w.polarity().toggle(), }; - #[cfg(any(feature = "52833", feature = "52840"))] + #[cfg(any(feature = "nrf52833", feature = "nrf52840"))] w.port().bit(match pin.pin.port() { Port::Port0 => false, Port::Port1 => true, diff --git a/embassy-nrf/src/interrupt.rs b/embassy-nrf/src/interrupt.rs deleted file mode 100644 index a29861977..000000000 --- a/embassy-nrf/src/interrupt.rs +++ /dev/null @@ -1,210 +0,0 @@ -//! Interrupt management -//! -//! This module implements an API for managing interrupts compatible with -//! nrf_softdevice::interrupt. Intended for switching between the two at compile-time. - -// Re-exports -pub use embassy::interrupt::{declare, take, Interrupt}; -pub use embassy_extras::interrupt::Priority3 as Priority; - -#[cfg(feature = "52810")] -mod irqs { - use super::*; - declare!(POWER_CLOCK); - declare!(RADIO); - declare!(UARTE0_UART0); - declare!(TWIM0_TWIS0_TWI0); - declare!(SPIM0_SPIS0_SPI0); - declare!(GPIOTE); - declare!(SAADC); - declare!(TIMER0); - declare!(TIMER1); - declare!(TIMER2); - declare!(RTC0); - declare!(TEMP); - declare!(RNG); - declare!(ECB); - declare!(CCM_AAR); - declare!(WDT); - declare!(RTC1); - declare!(QDEC); - declare!(COMP); - declare!(SWI0_EGU0); - declare!(SWI1_EGU1); - declare!(SWI2); - declare!(SWI3); - declare!(SWI4); - declare!(SWI5); - declare!(PWM0); - declare!(PDM); -} - -#[cfg(feature = "52811")] -mod irqs { - use super::*; - declare!(POWER_CLOCK); - declare!(RADIO); - declare!(UARTE0_UART0); - declare!(TWIM0_TWIS0_TWI0_SPIM1_SPIS1_SPI1); - declare!(SPIM0_SPIS0_SPI0); - declare!(GPIOTE); - declare!(SAADC); - declare!(TIMER0); - declare!(TIMER1); - declare!(TIMER2); - declare!(RTC0); - declare!(TEMP); - declare!(RNG); - declare!(ECB); - declare!(CCM_AAR); - declare!(WDT); - declare!(RTC1); - declare!(QDEC); - declare!(COMP); - declare!(SWI0_EGU0); - declare!(SWI1_EGU1); - declare!(SWI2); - declare!(SWI3); - declare!(SWI4); - declare!(SWI5); - declare!(PWM0); - declare!(PDM); -} - -#[cfg(feature = "52832")] -mod irqs { - use super::*; - declare!(POWER_CLOCK); - declare!(RADIO); - declare!(UARTE0_UART0); - declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); - declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); - declare!(NFCT); - declare!(GPIOTE); - declare!(SAADC); - declare!(TIMER0); - declare!(TIMER1); - declare!(TIMER2); - declare!(RTC0); - declare!(TEMP); - declare!(RNG); - declare!(ECB); - declare!(CCM_AAR); - declare!(WDT); - declare!(RTC1); - declare!(QDEC); - declare!(COMP_LPCOMP); - declare!(SWI0_EGU0); - declare!(SWI1_EGU1); - declare!(SWI2_EGU2); - declare!(SWI3_EGU3); - declare!(SWI4_EGU4); - declare!(SWI5_EGU5); - declare!(TIMER3); - declare!(TIMER4); - declare!(PWM0); - declare!(PDM); - declare!(MWU); - declare!(PWM1); - declare!(PWM2); - declare!(SPIM2_SPIS2_SPI2); - declare!(RTC2); - declare!(I2S); - declare!(FPU); -} - -#[cfg(feature = "52833")] -mod irqs { - use super::*; - declare!(POWER_CLOCK); - declare!(RADIO); - declare!(UARTE0_UART0); - declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); - declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); - declare!(NFCT); - declare!(GPIOTE); - declare!(SAADC); - declare!(TIMER0); - declare!(TIMER1); - declare!(TIMER2); - declare!(RTC0); - declare!(TEMP); - declare!(RNG); - declare!(ECB); - declare!(CCM_AAR); - declare!(WDT); - declare!(RTC1); - declare!(QDEC); - declare!(COMP_LPCOMP); - declare!(SWI0_EGU0); - declare!(SWI1_EGU1); - declare!(SWI2_EGU2); - declare!(SWI3_EGU3); - declare!(SWI4_EGU4); - declare!(SWI5_EGU5); - declare!(TIMER3); - declare!(TIMER4); - declare!(PWM0); - declare!(PDM); - declare!(MWU); - declare!(PWM1); - declare!(PWM2); - declare!(SPIM2_SPIS2_SPI2); - declare!(RTC2); - declare!(I2S); - declare!(FPU); - declare!(USBD); - declare!(UARTE1); - declare!(PWM3); - declare!(SPIM3); -} - -#[cfg(feature = "52840")] -mod irqs { - use super::*; - declare!(POWER_CLOCK); - declare!(RADIO); - declare!(UARTE0_UART0); - declare!(SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); - declare!(SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); - declare!(NFCT); - declare!(GPIOTE); - declare!(SAADC); - declare!(TIMER0); - declare!(TIMER1); - declare!(TIMER2); - declare!(RTC0); - declare!(TEMP); - declare!(RNG); - declare!(ECB); - declare!(CCM_AAR); - declare!(WDT); - declare!(RTC1); - declare!(QDEC); - declare!(COMP_LPCOMP); - declare!(SWI0_EGU0); - declare!(SWI1_EGU1); - declare!(SWI2_EGU2); - declare!(SWI3_EGU3); - declare!(SWI4_EGU4); - declare!(SWI5_EGU5); - declare!(TIMER3); - declare!(TIMER4); - declare!(PWM0); - declare!(PDM); - declare!(MWU); - declare!(PWM1); - declare!(PWM2); - declare!(SPIM2_SPIS2_SPI2); - declare!(RTC2); - declare!(I2S); - declare!(FPU); - declare!(USBD); - declare!(UARTE1); - declare!(QSPI); - declare!(CRYPTOCELL); - declare!(PWM3); - declare!(SPIM3); -} - -pub use irqs::*; diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 33d764fba..066bf5f6f 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -7,257 +7,67 @@ #![allow(incomplete_features)] #[cfg(not(any( - feature = "52810", - feature = "52811", - feature = "52832", - feature = "52833", - feature = "52840", + feature = "nrf51", + feature = "nrf52805", + feature = "nrf52810", + feature = "nrf52811", + feature = "nrf52820", + feature = "nrf52832", + feature = "nrf52833", + feature = "nrf52840", + feature = "nrf5340-app", + feature = "nrf5340-net", + feature = "nrf9160", )))] -compile_error!("No chip feature activated. You must activate exactly one of the following features: 52810, 52811, 52832, 52833, 52840"); - -#[cfg(any( - all(feature = "52810", feature = "52811"), - all(feature = "52810", feature = "52832"), - all(feature = "52810", feature = "52833"), - all(feature = "52810", feature = "52840"), - all(feature = "52811", feature = "52832"), - all(feature = "52811", feature = "52833"), - all(feature = "52811", feature = "52840"), - all(feature = "52832", feature = "52833"), - all(feature = "52832", feature = "52840"), - all(feature = "52833", feature = "52840"), -))] -compile_error!("Multile chip features activated. You must activate exactly one of the following features: 52810, 52811, 52832, 52833, 52840"); - -#[cfg(feature = "52810")] -pub use nrf52810_pac as pac; -#[cfg(feature = "52811")] -pub use nrf52811_pac as pac; -#[cfg(feature = "52832")] -pub use nrf52832_pac as pac; -#[cfg(feature = "52833")] -pub use nrf52833_pac as pac; -#[cfg(feature = "52840")] -pub use nrf52840_pac as pac; - -/// Length of Nordic EasyDMA differs for MCUs -#[cfg(any( - feature = "52810", - feature = "52811", - feature = "52832", - feature = "51" -))] -pub mod target_constants { - // NRF52832 8 bits1..0xFF - pub const EASY_DMA_SIZE: usize = 255; - // Easy DMA can only read from data ram - pub const SRAM_LOWER: usize = 0x2000_0000; - pub const SRAM_UPPER: usize = 0x3000_0000; -} -#[cfg(any(feature = "52840", feature = "52833", feature = "9160"))] -pub mod target_constants { - // NRF52840 and NRF9160 16 bits 1..0xFFFF - pub const EASY_DMA_SIZE: usize = 65535; - // Limits for Easy DMA - it can only read from data ram - pub const SRAM_LOWER: usize = 0x2000_0000; - pub const SRAM_UPPER: usize = 0x3000_0000; -} - -/// Does this slice reside entirely within RAM? -pub(crate) fn slice_in_ram(slice: &[u8]) -> bool { - let ptr = slice.as_ptr() as usize; - ptr >= target_constants::SRAM_LOWER && (ptr + slice.len()) < target_constants::SRAM_UPPER -} - -/// Return an error if slice is not in RAM. -#[cfg(not(feature = "51"))] -pub(crate) fn slice_in_ram_or(slice: &[u8], err: T) -> Result<(), T> { - if slice.len() == 0 || slice_in_ram(slice) { - Ok(()) - } else { - Err(err) - } -} +compile_error!("No chip feature activated. You must activate exactly one of the following features: nrf52810, nrf52811, nrf52832, nrf52833, nrf52840"); // This mod MUST go first, so that the others see its macros. pub(crate) mod fmt; +pub(crate) mod util; pub mod buffered_uarte; pub mod gpio; pub mod gpiote; -pub mod interrupt; pub mod ppi; -#[cfg(feature = "52840")] +#[cfg(feature = "nrf52840")] pub mod qspi; pub mod rtc; +#[cfg(not(feature = "nrf52820"))] pub mod saadc; pub mod spim; pub mod system; pub mod timer; pub mod uarte; -embassy_extras::peripherals! { - // RTC - RTC0, - RTC1, - #[cfg(any(feature = "52832", feature = "52833", feature = "52840"))] - RTC2, +// This mod MUST go last, so that it sees all the `impl_foo!` macros +#[cfg(feature = "nrf52805")] +#[path = "chips/nrf52805.rs"] +mod chip; +#[cfg(feature = "nrf52810")] +#[path = "chips/nrf52810.rs"] +mod chip; +#[cfg(feature = "nrf52811")] +#[path = "chips/nrf52811.rs"] +mod chip; +#[cfg(feature = "nrf52820")] +#[path = "chips/nrf52820.rs"] +mod chip; +#[cfg(feature = "nrf52832")] +#[path = "chips/nrf52832.rs"] +mod chip; +#[cfg(feature = "nrf52833")] +#[path = "chips/nrf52833.rs"] +mod chip; +#[cfg(feature = "nrf52840")] +#[path = "chips/nrf52840.rs"] +mod chip; - // QSPI - #[cfg(feature = "52840")] - QSPI, +pub(crate) use chip::pac; +pub use chip::{peripherals, Peripherals}; - // UARTE - UARTE0, - #[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] - UARTE1, - - // SPIM - // TODO this is actually shared with SPI, SPIM, SPIS, TWI, TWIS, TWIS. - // When they're all implemented, they should be only one peripheral here. - SPIM0, - #[cfg(any(feature = "52832", feature = "52833", feature = "52840"))] - SPIM1, - #[cfg(any(feature = "52832", feature = "52833", feature = "52840"))] - SPIM2, - #[cfg(any(feature = "52833", feature = "52840"))] - SPIM3, - - // SAADC - SAADC, - - // TIMER - TIMER0, - TIMER1, - TIMER2, - #[cfg(any(feature = "52832", feature = "52833", feature = "52840"))] - TIMER3, - #[cfg(any(feature = "52832", feature = "52833", feature = "52840"))] - TIMER4, - - // GPIOTE - GPIOTE, - GPIOTE_CH0, - GPIOTE_CH1, - GPIOTE_CH2, - GPIOTE_CH3, - GPIOTE_CH4, - GPIOTE_CH5, - GPIOTE_CH6, - GPIOTE_CH7, - - // PPI - PPI_CH0, - PPI_CH1, - PPI_CH2, - PPI_CH3, - PPI_CH4, - PPI_CH5, - PPI_CH6, - PPI_CH7, - PPI_CH8, - PPI_CH9, - PPI_CH10, - PPI_CH11, - PPI_CH12, - PPI_CH13, - PPI_CH14, - PPI_CH15, - #[cfg(not(feature = "51"))] - PPI_CH16, - #[cfg(not(feature = "51"))] - PPI_CH17, - #[cfg(not(feature = "51"))] - PPI_CH18, - #[cfg(not(feature = "51"))] - PPI_CH19, - PPI_CH20, - PPI_CH21, - PPI_CH22, - PPI_CH23, - PPI_CH24, - PPI_CH25, - PPI_CH26, - PPI_CH27, - PPI_CH28, - PPI_CH29, - PPI_CH30, - PPI_CH31, - - PPI_GROUP0, - PPI_GROUP1, - PPI_GROUP2, - PPI_GROUP3, - #[cfg(not(feature = "51"))] - PPI_GROUP4, - #[cfg(not(feature = "51"))] - PPI_GROUP5, - - // GPIO port 0 - P0_00, - P0_01, - P0_02, - P0_03, - P0_04, - P0_05, - P0_06, - P0_07, - P0_08, - P0_09, - P0_10, - P0_11, - P0_12, - P0_13, - P0_14, - P0_15, - P0_16, - P0_17, - P0_18, - P0_19, - P0_20, - P0_21, - P0_22, - P0_23, - P0_24, - P0_25, - P0_26, - P0_27, - P0_28, - P0_29, - P0_30, - P0_31, - - // GPIO port 1 - #[cfg(any(feature = "52833", feature = "52840"))] - P1_00, - #[cfg(any(feature = "52833", feature = "52840"))] - P1_01, - #[cfg(any(feature = "52833", feature = "52840"))] - P1_02, - #[cfg(any(feature = "52833", feature = "52840"))] - P1_03, - #[cfg(any(feature = "52833", feature = "52840"))] - P1_04, - #[cfg(any(feature = "52833", feature = "52840"))] - P1_05, - #[cfg(any(feature = "52833", feature = "52840"))] - P1_06, - #[cfg(any(feature = "52833", feature = "52840"))] - P1_07, - #[cfg(any(feature = "52833", feature = "52840"))] - P1_08, - #[cfg(any(feature = "52833", feature = "52840"))] - P1_09, - #[cfg(any(feature = "52833", feature = "52840"))] - P1_10, - #[cfg(any(feature = "52833", feature = "52840"))] - P1_11, - #[cfg(any(feature = "52833", feature = "52840"))] - P1_12, - #[cfg(any(feature = "52833", feature = "52840"))] - P1_13, - #[cfg(any(feature = "52833", feature = "52840"))] - P1_14, - #[cfg(any(feature = "52833", feature = "52840"))] - P1_15, +pub mod interrupt { + pub use crate::chip::irqs::*; + pub use cortex_m::interrupt::{CriticalSection, Mutex}; + pub use embassy::interrupt::{declare, take, Interrupt}; + pub use embassy_extras::interrupt::Priority3 as Priority; } diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index f683138d6..d75070220 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs @@ -1,3 +1,5 @@ +#![macro_use] + use core::future::Future; use core::marker::PhantomData; use core::task::Poll; @@ -361,7 +363,7 @@ impl<'d, T: Instance> Flash for Qspi<'d, T> { } } -mod sealed { +pub(crate) mod sealed { use super::*; pub struct State { @@ -385,21 +387,19 @@ pub trait Instance: sealed::Instance + 'static { type Interrupt: Interrupt; } -macro_rules! impl_instance { - ($type:ident, $irq:ident) => { - impl sealed::Instance for peripherals::$type { +macro_rules! impl_qspi { + ($type:ident, $pac_type:ident, $irq:ident) => { + impl crate::qspi::sealed::Instance for peripherals::$type { fn regs() -> &'static pac::qspi::RegisterBlock { - unsafe { &*pac::$type::ptr() } + unsafe { &*pac::$pac_type::ptr() } } - fn state() -> &'static sealed::State { - static STATE: sealed::State = sealed::State::new(); + fn state() -> &'static crate::qspi::sealed::State { + static STATE: crate::qspi::sealed::State = crate::qspi::sealed::State::new(); &STATE } } - impl Instance for peripherals::$type { - type Interrupt = interrupt::$irq; + impl crate::qspi::Instance for peripherals::$type { + type Interrupt = crate::interrupt::$irq; } }; } - -impl_instance!(QSPI, QSPI); diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index 3370e1243..1fb3d441b 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs @@ -1,3 +1,5 @@ +#![macro_use] + use core::future::Future; use core::marker::PhantomData; use core::sync::atomic::{compiler_fence, Ordering}; @@ -12,7 +14,7 @@ use traits::spi::FullDuplex; use crate::gpio::sealed::Pin as _; use crate::gpio::{OptionalPin, Pin as GpioPin}; use crate::interrupt::{self, Interrupt}; -use crate::{pac, peripherals, slice_in_ram_or}; +use crate::{pac, peripherals, util::slice_in_ram_or}; pub use embedded_hal::spi::{Mode, Phase, Polarity, MODE_0, MODE_1, MODE_2, MODE_3}; pub use pac::spim0::frequency::FREQUENCY_A as Frequency; @@ -33,12 +35,23 @@ pub struct Spim<'d, T: Instance> { phantom: PhantomData<&'d mut T>, } +#[non_exhaustive] pub struct Config { pub frequency: Frequency, pub mode: Mode, pub orc: u8, } +impl Default for Config { + fn default() -> Self { + Self { + frequency: Frequency::M1, + mode: MODE_0, + orc: 0x00, + } + } +} + impl<'d, T: Instance> Spim<'d, T> { pub fn new( spim: impl Unborrow + 'd, @@ -315,7 +328,7 @@ impl<'d, T: Instance> embedded_hal::blocking::spi::Write for Spim<'d, T> { } } -mod sealed { +pub(crate) mod sealed { use super::*; pub struct State { @@ -340,33 +353,19 @@ pub trait Instance: sealed::Instance + 'static { type Interrupt: Interrupt; } -macro_rules! impl_instance { - ($type:ident, $irq:ident) => { - impl sealed::Instance for peripherals::$type { +macro_rules! impl_spim { + ($type:ident, $pac_type:ident, $irq:ident) => { + impl crate::spim::sealed::Instance for peripherals::$type { fn regs() -> &'static pac::spim0::RegisterBlock { - unsafe { &*pac::$type::ptr() } + unsafe { &*pac::$pac_type::ptr() } } - fn state() -> &'static sealed::State { - static STATE: sealed::State = sealed::State::new(); + fn state() -> &'static crate::spim::sealed::State { + static STATE: crate::spim::sealed::State = crate::spim::sealed::State::new(); &STATE } } - impl Instance for peripherals::$type { - type Interrupt = interrupt::$irq; + impl crate::spim::Instance for peripherals::$type { + type Interrupt = crate::interrupt::$irq; } }; } - -#[cfg(feature = "52810")] -impl_instance!(SPIM0, SPIM0_SPIS0_SPI0); -#[cfg(not(feature = "52810"))] -impl_instance!(SPIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); - -#[cfg(any(feature = "52832", feature = "52833", feature = "52840"))] -impl_instance!(SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); - -#[cfg(any(feature = "52832", feature = "52833", feature = "52840"))] -impl_instance!(SPIM2, SPIM2_SPIS2_SPI2); - -#[cfg(any(feature = "52833", feature = "52840"))] -impl_instance!(SPIM3, SPIM3); diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs index d74e3cfad..69d620b48 100644 --- a/embassy-nrf/src/timer.rs +++ b/embassy-nrf/src/timer.rs @@ -1,8 +1,10 @@ +#![macro_use] + use embassy::interrupt::Interrupt; -use crate::{interrupt, pac, peripherals}; +use crate::pac; -mod sealed { +pub(crate) mod sealed { use super::*; pub trait Instance { @@ -16,28 +18,20 @@ pub trait Instance: sealed::Instance + 'static { } pub trait ExtendedInstance: Instance + sealed::ExtendedInstance {} -macro_rules! impl_instance { - ($type:ident, $irq:ident) => { - impl sealed::Instance for peripherals::$type { +macro_rules! impl_timer { + ($type:ident, $pac_type:ident, $irq:ident) => { + impl crate::timer::sealed::Instance for peripherals::$type { fn regs(&self) -> &pac::timer0::RegisterBlock { - unsafe { &*(pac::$type::ptr() as *const pac::timer0::RegisterBlock) } + unsafe { &*(pac::$pac_type::ptr() as *const pac::timer0::RegisterBlock) } } } - impl Instance for peripherals::$type { - type Interrupt = interrupt::$irq; + impl crate::timer::Instance for peripherals::$type { + type Interrupt = crate::interrupt::$irq; } }; - ($type:ident, $irq:ident, extended) => { - impl_instance!($type, $irq); - impl sealed::ExtendedInstance for peripherals::$type {} - impl ExtendedInstance for peripherals::$type {} + ($type:ident, $pac_type:ident, $irq:ident, extended) => { + impl_timer!($type, $pac_type, $irq); + impl crate::timer::sealed::ExtendedInstance for peripherals::$type {} + impl crate::timer::ExtendedInstance for peripherals::$type {} }; } - -impl_instance!(TIMER0, TIMER0); -impl_instance!(TIMER1, TIMER1); -impl_instance!(TIMER2, TIMER2); -#[cfg(any(feature = "52832", feature = "52833", feature = "52840"))] -impl_instance!(TIMER3, TIMER3, extended); -#[cfg(any(feature = "52832", feature = "52833", feature = "52840"))] -impl_instance!(TIMER4, TIMER4, extended); diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 04907fb56..7581f7a8b 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs @@ -1,3 +1,5 @@ +#![macro_use] + //! Async UART use core::future::Future; @@ -10,6 +12,7 @@ use embassy::util::{AtomicWaker, OnDrop, Unborrow}; use embassy_extras::unborrow; use futures::future::poll_fn; +use crate::chip::EASY_DMA_SIZE; use crate::fmt::{assert, panic, *}; use crate::gpio::sealed::Pin as _; use crate::gpio::{OptionalPin as GpioOptionalPin, Pin as GpioPin}; @@ -18,7 +21,6 @@ use crate::interrupt::Interrupt; use crate::pac; use crate::peripherals; use crate::ppi::{AnyConfigurableChannel, ConfigurableChannel, Event, Ppi, Task}; -use crate::target_constants::EASY_DMA_SIZE; use crate::timer::Instance as TimerInstance; // Re-export SVD variants to allow user to directly set values. @@ -445,7 +447,7 @@ impl<'d, U: Instance, T: TimerInstance> Write for UarteWithIdle<'d, U, T> { } } -mod sealed { +pub(crate) mod sealed { use super::*; pub struct State { @@ -471,23 +473,19 @@ pub trait Instance: sealed::Instance + 'static { type Interrupt: Interrupt; } -macro_rules! impl_instance { - ($type:ident, $irq:ident) => { - impl sealed::Instance for peripherals::$type { +macro_rules! impl_uarte { + ($type:ident, $pac_type:ident, $irq:ident) => { + impl crate::uarte::sealed::Instance for peripherals::$type { fn regs() -> &'static pac::uarte0::RegisterBlock { - unsafe { &*pac::$type::ptr() } + unsafe { &*pac::$pac_type::ptr() } } - fn state() -> &'static sealed::State { - static STATE: sealed::State = sealed::State::new(); + fn state() -> &'static crate::uarte::sealed::State { + static STATE: crate::uarte::sealed::State = crate::uarte::sealed::State::new(); &STATE } } - impl Instance for peripherals::$type { - type Interrupt = interrupt::$irq; + impl crate::uarte::Instance for peripherals::$type { + type Interrupt = crate::interrupt::$irq; } }; } - -impl_instance!(UARTE0, UARTE0_UART0); -#[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] -impl_instance!(UARTE1, UARTE1); diff --git a/embassy-nrf/src/util.rs b/embassy-nrf/src/util.rs new file mode 100644 index 000000000..7c3974eeb --- /dev/null +++ b/embassy-nrf/src/util.rs @@ -0,0 +1,18 @@ +const SRAM_LOWER: usize = 0x2000_0000; +const SRAM_UPPER: usize = 0x3000_0000; + +/// Does this slice reside entirely within RAM? +pub(crate) fn slice_in_ram(slice: &[u8]) -> bool { + let ptr = slice.as_ptr() as usize; + ptr >= SRAM_LOWER && (ptr + slice.len()) < SRAM_UPPER +} + +/// Return an error if slice is not in RAM. +#[cfg(not(feature = "51"))] +pub(crate) fn slice_in_ram_or(slice: &[u8], err: T) -> Result<(), T> { + if slice.len() == 0 || slice_in_ram(slice) { + Ok(()) + } else { + Err(err) + } +} From eb4571dc4ce46ef7d2689de881077a9d3c6bcc27 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Tue, 11 May 2021 03:07:37 +0200 Subject: [PATCH 02/10] nrf: add blocking TWIM --- embassy-nrf/src/chips/nrf52810.rs | 2 + embassy-nrf/src/chips/nrf52811.rs | 2 + embassy-nrf/src/chips/nrf52820.rs | 3 + embassy-nrf/src/chips/nrf52832.rs | 3 + embassy-nrf/src/chips/nrf52833.rs | 3 + embassy-nrf/src/chips/nrf52840.rs | 3 + embassy-nrf/src/lib.rs | 1 + embassy-nrf/src/twim.rs | 531 ++++++++++++++++++++++++++++++ 8 files changed, 548 insertions(+) create mode 100644 embassy-nrf/src/twim.rs diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs index 7fe35b27f..9f3ed9cf3 100644 --- a/embassy-nrf/src/chips/nrf52810.rs +++ b/embassy-nrf/src/chips/nrf52810.rs @@ -114,6 +114,8 @@ impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); impl_spim!(SPI0, SPIM0, SPIM0_SPIS0_SPI0); +impl_twim!(TWI0, TWIM0, TWIM0_TWIS0_TWI0); + impl_timer!(TIMER0, TIMER0, TIMER0); impl_timer!(TIMER1, TIMER1, TIMER1); impl_timer!(TIMER2, TIMER2, TIMER2); diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs index e3f4f18ba..6728f6a41 100644 --- a/embassy-nrf/src/chips/nrf52811.rs +++ b/embassy-nrf/src/chips/nrf52811.rs @@ -115,6 +115,8 @@ impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); impl_spim!(TWISPI0, SPIM0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0); impl_spim!(SPI1, SPIM1, SPIM1_SPIS1_SPI1); +impl_twim!(TWISPI0, TWIM0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0); + impl_timer!(TIMER0, TIMER0, TIMER0); impl_timer!(TIMER1, TIMER1, TIMER1); impl_timer!(TIMER2, TIMER2, TIMER2); diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs index e367a7916..2f9eb5f53 100644 --- a/embassy-nrf/src/chips/nrf52820.rs +++ b/embassy-nrf/src/chips/nrf52820.rs @@ -116,6 +116,9 @@ impl_uarte!(UARTE0, UARTE0, UARTE0_UART0); impl_spim!(TWISPI0, SPIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); +impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); +impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); + impl_timer!(TIMER0, TIMER0, TIMER0); impl_timer!(TIMER1, TIMER1, TIMER1); impl_timer!(TIMER2, TIMER2, TIMER2); diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs index e0669d93e..015bc51f8 100644 --- a/embassy-nrf/src/chips/nrf52832.rs +++ b/embassy-nrf/src/chips/nrf52832.rs @@ -121,6 +121,9 @@ impl_spim!(TWISPI0, SPIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2); +impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); +impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); + impl_timer!(TIMER0, TIMER0, TIMER0); impl_timer!(TIMER1, TIMER1, TIMER1); impl_timer!(TIMER2, TIMER2, TIMER2); diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs index a0b434229..404883934 100644 --- a/embassy-nrf/src/chips/nrf52833.rs +++ b/embassy-nrf/src/chips/nrf52833.rs @@ -142,6 +142,9 @@ impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2); impl_spim!(SPI3, SPIM3, SPIM3); +impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); +impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); + impl_timer!(TIMER0, TIMER0, TIMER0); impl_timer!(TIMER1, TIMER1, TIMER1); impl_timer!(TIMER2, TIMER2, TIMER2); diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs index 9a9f99201..26dfc7e8f 100644 --- a/embassy-nrf/src/chips/nrf52840.rs +++ b/embassy-nrf/src/chips/nrf52840.rs @@ -145,6 +145,9 @@ impl_spim!(TWISPI1, SPIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2); impl_spim!(SPI3, SPIM3, SPIM3); +impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); +impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); + impl_timer!(TIMER0, TIMER0, TIMER0); impl_timer!(TIMER1, TIMER1, TIMER1); impl_timer!(TIMER2, TIMER2, TIMER2); diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 066bf5f6f..2b35fdd6a 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -37,6 +37,7 @@ pub mod saadc; pub mod spim; pub mod system; pub mod timer; +pub mod twim; pub mod uarte; // This mod MUST go last, so that it sees all the `impl_foo!` macros diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs new file mode 100644 index 000000000..cbaf97dff --- /dev/null +++ b/embassy-nrf/src/twim.rs @@ -0,0 +1,531 @@ +#![macro_use] + +//! HAL interface to the TWIM peripheral. +//! +//! See product specification: +//! +//! - nRF52832: Section 33 +//! - nRF52840: Section 6.31 +use core::marker::PhantomData; +use core::sync::atomic::{compiler_fence, Ordering::SeqCst}; +use embassy::interrupt::{Interrupt, InterruptExt}; +use embassy::util::{AtomicWaker, Unborrow}; +use embassy_extras::unborrow; + +use crate::chip::{EASY_DMA_SIZE, FORCE_COPY_BUFFER_SIZE}; +use crate::fmt::*; +use crate::gpio::Pin as GpioPin; +use crate::pac; +use crate::util::{slice_in_ram, slice_in_ram_or}; + +pub enum Frequency { + #[doc = "26738688: 100 kbps"] + K100 = 26738688, + #[doc = "67108864: 250 kbps"] + K250 = 67108864, + #[doc = "104857600: 400 kbps"] + K400 = 104857600, +} + +#[non_exhaustive] +pub struct Config { + pub frequency: Frequency, +} + +impl Default for Config { + fn default() -> Self { + Self { + frequency: Frequency::K100, + } + } +} + +/// Interface to a TWIM instance. +pub struct Twim<'d, T: Instance> { + peri: T, + irq: T::Interrupt, + phantom: PhantomData<&'d mut T>, +} + +impl<'d, T: Instance> Twim<'d, T> { + pub fn new( + twim: impl Unborrow + 'd, + irq: impl Unborrow + 'd, + sda: impl Unborrow + 'd, + scl: impl Unborrow + 'd, + config: Config, + ) -> Self { + unborrow!(twim, irq, sda, scl); + + let r = T::regs(); + + // Configure pins + sda.conf().write(|w| { + w.dir().input(); + w.input().connect(); + w.pull().pullup(); + w.drive().s0d1(); + w + }); + scl.conf().write(|w| { + w.dir().input(); + w.input().connect(); + w.pull().pullup(); + w.drive().s0d1(); + w + }); + + // Select pins. + r.psel.sda.write(|w| unsafe { w.bits(sda.psel_bits()) }); + r.psel.scl.write(|w| unsafe { w.bits(scl.psel_bits()) }); + + // Enable TWIM instance. + r.enable.write(|w| w.enable().enabled()); + + // Configure frequency. + r.frequency + .write(|w| unsafe { w.frequency().bits(config.frequency as u32) }); + + // Disable all events interrupts + r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); + + irq.set_handler(Self::on_interrupt); + irq.unpend(); + irq.enable(); + + Self { + peri: twim, + irq, + phantom: PhantomData, + } + } + + fn on_interrupt(_: *mut ()) { + let r = T::regs(); + let s = T::state(); + + if r.events_stopped.read().bits() != 0 { + s.end_waker.wake(); + r.intenclr.write(|w| w.stopped().clear()); + } + if r.events_error.read().bits() != 0 { + s.end_waker.wake(); + r.intenclr.write(|w| w.error().clear()); + } + } + + /// Set TX buffer, checking that it is in RAM and has suitable length. + unsafe fn set_tx_buffer(&mut self, buffer: &[u8]) -> Result<(), Error> { + slice_in_ram_or(buffer, Error::DMABufferNotInDataMemory)?; + + if buffer.len() == 0 { + return Err(Error::TxBufferZeroLength); + } + if buffer.len() > EASY_DMA_SIZE { + return Err(Error::TxBufferTooLong); + } + + let r = T::regs(); + + r.txd.ptr.write(|w| + // We're giving the register a pointer to the stack. Since we're + // waiting for the I2C transaction to end before this stack pointer + // becomes invalid, there's nothing wrong here. + // + // The PTR field is a full 32 bits wide and accepts the full range + // of values. + w.ptr().bits(buffer.as_ptr() as u32)); + r.txd.maxcnt.write(|w| + // We're giving it the length of the buffer, so no danger of + // accessing invalid memory. We have verified that the length of the + // buffer fits in an `u8`, so the cast to `u8` is also fine. + // + // The MAXCNT field is 8 bits wide and accepts the full range of + // values. + w.maxcnt().bits(buffer.len() as _)); + + Ok(()) + } + + /// Set RX buffer, checking that it has suitable length. + unsafe fn set_rx_buffer(&mut self, buffer: &mut [u8]) -> Result<(), Error> { + // NOTE: RAM slice check is not necessary, as a mutable + // slice can only be built from data located in RAM. + + if buffer.len() == 0 { + return Err(Error::RxBufferZeroLength); + } + if buffer.len() > EASY_DMA_SIZE { + return Err(Error::RxBufferTooLong); + } + + let r = T::regs(); + + r.rxd.ptr.write(|w| + // We're giving the register a pointer to the stack. Since we're + // waiting for the I2C transaction to end before this stack pointer + // becomes invalid, there's nothing wrong here. + // + // The PTR field is a full 32 bits wide and accepts the full range + // of values. + w.ptr().bits(buffer.as_mut_ptr() as u32)); + r.rxd.maxcnt.write(|w| + // We're giving it the length of the buffer, so no danger of + // accessing invalid memory. We have verified that the length of the + // buffer fits in an `u8`, so the cast to the type of maxcnt + // is also fine. + // + // Note that that nrf52840 maxcnt is a wider + // type than a u8, so we use a `_` cast rather than a `u8` cast. + // The MAXCNT field is thus at least 8 bits wide and accepts the + // full range of values that fit in a `u8`. + w.maxcnt().bits(buffer.len() as _)); + + Ok(()) + } + + fn clear_errorsrc(&mut self) { + let r = T::regs(); + r.errorsrc + .write(|w| w.anack().bit(true).dnack().bit(true).overrun().bit(true)); + } + + /// Get Error instance, if any occurred. + fn read_errorsrc(&self) -> Result<(), Error> { + let r = T::regs(); + + let err = r.errorsrc.read(); + if err.anack().is_received() { + return Err(Error::AddressNack); + } + if err.dnack().is_received() { + return Err(Error::DataNack); + } + if err.overrun().is_received() { + return Err(Error::DataNack); + } + Ok(()) + } + + /// Wait for stop or error + fn wait(&mut self) { + let r = T::regs(); + loop { + if r.events_stopped.read().bits() != 0 { + r.events_stopped.reset(); + break; + } + if r.events_error.read().bits() != 0 { + r.events_error.reset(); + r.tasks_stop.write(|w| unsafe { w.bits(1) }); + } + } + } + + /// Write to an I2C slave. + /// + /// The buffer must have a length of at most 255 bytes on the nRF52832 + /// and at most 65535 bytes on the nRF52840. + pub fn write(&mut self, address: u8, buffer: &[u8]) -> Result<(), Error> { + let r = T::regs(); + + // Conservative compiler fence to prevent optimizations that do not + // take in to account actions by DMA. The fence has been placed here, + // before any DMA action has started. + compiler_fence(SeqCst); + + r.address.write(|w| unsafe { w.address().bits(address) }); + + // Set up the DMA write. + unsafe { self.set_tx_buffer(buffer)? }; + + // Clear events + r.events_stopped.reset(); + r.events_error.reset(); + r.events_lasttx.reset(); + self.clear_errorsrc(); + + // Start write operation. + r.shorts.write(|w| w.lasttx_stop().enabled()); + r.tasks_starttx.write(|w| + // `1` is a valid value to write to task registers. + unsafe { w.bits(1) }); + + self.wait(); + + // Conservative compiler fence to prevent optimizations that do not + // take in to account actions by DMA. The fence has been placed here, + // after all possible DMA actions have completed. + compiler_fence(SeqCst); + + self.read_errorsrc()?; + + if r.txd.amount.read().bits() != buffer.len() as u32 { + return Err(Error::Transmit); + } + + Ok(()) + } + + /// Read from an I2C slave. + /// + /// The buffer must have a length of at most 255 bytes on the nRF52832 + /// and at most 65535 bytes on the nRF52840. + pub fn read(&mut self, address: u8, buffer: &mut [u8]) -> Result<(), Error> { + let r = T::regs(); + + // Conservative compiler fence to prevent optimizations that do not + // take in to account actions by DMA. The fence has been placed here, + // before any DMA action has started. + compiler_fence(SeqCst); + + r.address.write(|w| unsafe { w.address().bits(address) }); + + // Set up the DMA read. + unsafe { self.set_rx_buffer(buffer)? }; + + // Clear events + r.events_stopped.reset(); + r.events_error.reset(); + self.clear_errorsrc(); + + // Start read operation. + r.shorts.write(|w| w.lastrx_stop().enabled()); + r.tasks_startrx.write(|w| + // `1` is a valid value to write to task registers. + unsafe { w.bits(1) }); + + self.wait(); + + // Conservative compiler fence to prevent optimizations that do not + // take in to account actions by DMA. The fence has been placed here, + // after all possible DMA actions have completed. + compiler_fence(SeqCst); + + self.read_errorsrc()?; + + if r.rxd.amount.read().bits() != buffer.len() as u32 { + return Err(Error::Receive); + } + + Ok(()) + } + + /// Write data to an I2C slave, then read data from the slave without + /// triggering a stop condition between the two. + /// + /// The buffers must have a length of at most 255 bytes on the nRF52832 + /// and at most 65535 bytes on the nRF52840. + pub fn write_then_read( + &mut self, + address: u8, + wr_buffer: &[u8], + rd_buffer: &mut [u8], + ) -> Result<(), Error> { + let r = T::regs(); + + // Conservative compiler fence to prevent optimizations that do not + // take in to account actions by DMA. The fence has been placed here, + // before any DMA action has started. + compiler_fence(SeqCst); + + r.address.write(|w| unsafe { w.address().bits(address) }); + + // Set up DMA buffers. + unsafe { + self.set_tx_buffer(wr_buffer)?; + self.set_rx_buffer(rd_buffer)?; + } + + // Clear events + r.events_stopped.reset(); + r.events_error.reset(); + self.clear_errorsrc(); + + // Start write+read operation. + r.shorts.write(|w| { + w.lasttx_startrx().enabled(); + w.lastrx_stop().enabled(); + w + }); + // `1` is a valid value to write to task registers. + r.tasks_starttx.write(|w| unsafe { w.bits(1) }); + + self.wait(); + + // Conservative compiler fence to prevent optimizations that do not + // take in to account actions by DMA. The fence has been placed here, + // after all possible DMA actions have completed. + compiler_fence(SeqCst); + + self.read_errorsrc()?; + + let bad_write = r.txd.amount.read().bits() != wr_buffer.len() as u32; + let bad_read = r.rxd.amount.read().bits() != rd_buffer.len() as u32; + + if bad_write { + return Err(Error::Transmit); + } + + if bad_read { + return Err(Error::Receive); + } + + Ok(()) + } + + /// Copy data into RAM and write to an I2C slave. + /// + /// The write buffer must have a length of at most 255 bytes on the nRF52832 + /// and at most 1024 bytes on the nRF52840. + pub fn copy_write(&mut self, address: u8, wr_buffer: &[u8]) -> Result<(), Error> { + if wr_buffer.len() > FORCE_COPY_BUFFER_SIZE { + return Err(Error::TxBufferTooLong); + } + + // Copy to RAM + let wr_ram_buffer = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()]; + wr_ram_buffer.copy_from_slice(wr_buffer); + + self.write(address, wr_ram_buffer) + } + + /// Copy data into RAM and write to an I2C slave, then read data from the slave without + /// triggering a stop condition between the two. + /// + /// The write buffer must have a length of at most 255 bytes on the nRF52832 + /// and at most 1024 bytes on the nRF52840. + /// + /// The read buffer must have a length of at most 255 bytes on the nRF52832 + /// and at most 65535 bytes on the nRF52840. + pub fn copy_write_then_read( + &mut self, + address: u8, + wr_buffer: &[u8], + rd_buffer: &mut [u8], + ) -> Result<(), Error> { + if wr_buffer.len() > FORCE_COPY_BUFFER_SIZE { + return Err(Error::TxBufferTooLong); + } + + // Copy to RAM + let wr_ram_buffer = &mut [0; FORCE_COPY_BUFFER_SIZE][..wr_buffer.len()]; + wr_ram_buffer.copy_from_slice(wr_buffer); + + self.write_then_read(address, wr_ram_buffer, rd_buffer) + } +} + +impl<'a, T: Instance> Drop for Twim<'a, T> { + fn drop(&mut self) { + info!("twim drop"); + + // TODO when implementing async here, check for abort + + // disable! + let r = T::regs(); + r.enable.write(|w| w.enable().disabled()); + + info!("uarte drop: done"); + + // TODO: disable pins + } +} + +impl<'a, T: Instance> embedded_hal::blocking::i2c::Write for Twim<'a, T> { + type Error = Error; + + fn write<'w>(&mut self, addr: u8, bytes: &'w [u8]) -> Result<(), Error> { + if slice_in_ram(bytes) { + self.write(addr, bytes) + } else { + let buf = &mut [0; FORCE_COPY_BUFFER_SIZE][..]; + for chunk in bytes.chunks(FORCE_COPY_BUFFER_SIZE) { + buf[..chunk.len()].copy_from_slice(chunk); + self.write(addr, &buf[..chunk.len()])?; + } + Ok(()) + } + } +} + +impl<'a, T: Instance> embedded_hal::blocking::i2c::Read for Twim<'a, T> { + type Error = Error; + + fn read<'w>(&mut self, addr: u8, bytes: &'w mut [u8]) -> Result<(), Error> { + self.read(addr, bytes) + } +} + +impl<'a, T: Instance> embedded_hal::blocking::i2c::WriteRead for Twim<'a, T> { + type Error = Error; + + fn write_read<'w>( + &mut self, + addr: u8, + bytes: &'w [u8], + buffer: &'w mut [u8], + ) -> Result<(), Error> { + if slice_in_ram(bytes) { + self.write_then_read(addr, bytes, buffer) + } else { + self.copy_write_then_read(addr, bytes, buffer) + } + } +} + +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum Error { + TxBufferTooLong, + RxBufferTooLong, + TxBufferZeroLength, + RxBufferZeroLength, + Transmit, + Receive, + DMABufferNotInDataMemory, + AddressNack, + DataNack, + Overrun, +} + +pub(crate) mod sealed { + use super::*; + + pub struct State { + pub end_waker: AtomicWaker, + } + + impl State { + pub const fn new() -> Self { + Self { + end_waker: AtomicWaker::new(), + } + } + } + + pub trait Instance { + fn regs() -> &'static pac::twim0::RegisterBlock; + fn state() -> &'static State; + } +} + +pub trait Instance: sealed::Instance + 'static { + type Interrupt: Interrupt; +} + +macro_rules! impl_twim { + ($type:ident, $pac_type:ident, $irq:ident) => { + impl crate::twim::sealed::Instance for peripherals::$type { + fn regs() -> &'static pac::twim0::RegisterBlock { + unsafe { &*pac::$pac_type::ptr() } + } + fn state() -> &'static crate::twim::sealed::State { + static STATE: crate::twim::sealed::State = crate::twim::sealed::State::new(); + &STATE + } + } + impl crate::twim::Instance for peripherals::$type { + type Interrupt = crate::interrupt::$irq; + } + }; +} From 92be72e0e3917782aade44e5b4cdbebb2dbab46e Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 12 May 2021 01:00:43 +0200 Subject: [PATCH 03/10] Add `#[interrupt]` macro to register static interrupts. --- embassy-macros/src/lib.rs | 73 ++++++++++++++++++++++++++++++++++++--- embassy-nrf/src/lib.rs | 1 + 2 files changed, 69 insertions(+), 5 deletions(-) diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs index ce643ae89..590289f94 100644 --- a/embassy-macros/src/lib.rs +++ b/embassy-macros/src/lib.rs @@ -3,9 +3,13 @@ extern crate proc_macro; use darling::FromMeta; -use proc_macro::{Span, TokenStream}; +use proc_macro::TokenStream; +use proc_macro2::Span; use quote::{format_ident, quote}; +use std::iter; use syn::spanned::Spanned; +use syn::{parse, Type, Visibility}; +use syn::{ItemFn, ReturnType}; mod path; @@ -58,10 +62,9 @@ pub fn task(args: TokenStream, item: TokenStream) -> TokenStream { fail = true; } if pool_size < 1 { - Span::call_site() - .error("pool_size must be 1 or greater") - .emit(); - fail = true + return parse::Error::new(Span::call_site(), "pool_size must be 1 or greater") + .to_compile_error() + .into(); } let mut arg_names: syn::punctuated::Punctuated = @@ -120,6 +123,66 @@ pub fn task(args: TokenStream, item: TokenStream) -> TokenStream { result.into() } +#[proc_macro_attribute] +pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream { + let mut f: ItemFn = syn::parse(input).expect("`#[interrupt]` must be applied to a function"); + + if !args.is_empty() { + return parse::Error::new(Span::call_site(), "This attribute accepts no arguments") + .to_compile_error() + .into(); + } + + let fspan = f.span(); + let ident = f.sig.ident.clone(); + let ident_s = ident.to_string(); + + // XXX should we blacklist other attributes? + + let valid_signature = f.sig.constness.is_none() + && f.vis == Visibility::Inherited + && f.sig.abi.is_none() + && f.sig.inputs.is_empty() + && f.sig.generics.params.is_empty() + && f.sig.generics.where_clause.is_none() + && f.sig.variadic.is_none() + && match f.sig.output { + ReturnType::Default => true, + ReturnType::Type(_, ref ty) => match **ty { + Type::Tuple(ref tuple) => tuple.elems.is_empty(), + Type::Never(..) => true, + _ => false, + }, + }; + + if !valid_signature { + return parse::Error::new( + fspan, + "`#[interrupt]` handlers must have signature `[unsafe] fn() [-> !]`", + ) + .to_compile_error() + .into(); + } + + f.block.stmts = iter::once( + syn::parse2(quote! {{ + // Check that this interrupt actually exists + let __irq_exists_check: interrupt::#ident; + }}) + .unwrap(), + ) + .chain(f.block.stmts) + .collect(); + + quote!( + #[doc(hidden)] + #[export_name = #ident_s] + #[allow(non_snake_case)] + #f + ) + .into() +} + #[proc_macro] pub fn interrupt_declare(item: TokenStream) -> TokenStream { let name = syn::parse_macro_input!(item as syn::Ident); diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 2b35fdd6a..4349bf39f 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -72,3 +72,4 @@ pub mod interrupt { pub use embassy::interrupt::{declare, take, Interrupt}; pub use embassy_extras::interrupt::Priority3 as Priority; } +pub use embassy_macros::interrupt; From 97b01f1c4799a66bc2af596bfc5138ccf919a6de Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 12 May 2021 01:01:08 +0200 Subject: [PATCH 04/10] nrf/gpiote: initialize automatically --- .../src/bin/gpiote_channel.rs | 5 --- embassy-nrf-examples/src/bin/gpiote_port.rs | 13 +++--- embassy-nrf-examples/src/bin/ppi.rs | 7 ---- embassy-nrf/src/chips/nrf52805.rs | 1 - embassy-nrf/src/chips/nrf52810.rs | 1 - embassy-nrf/src/chips/nrf52811.rs | 1 - embassy-nrf/src/chips/nrf52820.rs | 1 - embassy-nrf/src/chips/nrf52832.rs | 1 - embassy-nrf/src/chips/nrf52833.rs | 1 - embassy-nrf/src/chips/nrf52840.rs | 1 - embassy-nrf/src/gpiote.rs | 41 ++++++------------- embassy-nrf/src/system.rs | 3 ++ 12 files changed, 21 insertions(+), 55 deletions(-) diff --git a/embassy-nrf-examples/src/bin/gpiote_channel.rs b/embassy-nrf-examples/src/bin/gpiote_channel.rs index 9e653192b..ee670acd5 100644 --- a/embassy-nrf-examples/src/bin/gpiote_channel.rs +++ b/embassy-nrf-examples/src/bin/gpiote_channel.rs @@ -18,30 +18,25 @@ use embassy_nrf::{interrupt, Peripherals}; #[embassy::main] async fn main(spawner: Spawner) { let p = Peripherals::take().unwrap(); - let g = gpiote::initialize(p.GPIOTE, interrupt::take!(GPIOTE)); info!("Starting!"); let ch1 = InputChannel::new( - g, p.GPIOTE_CH0, Input::new(p.P0_11, Pull::Up), InputChannelPolarity::HiToLo, ); let ch2 = InputChannel::new( - g, p.GPIOTE_CH1, Input::new(p.P0_12, Pull::Up), InputChannelPolarity::LoToHi, ); let ch3 = InputChannel::new( - g, p.GPIOTE_CH2, Input::new(p.P0_24, Pull::Up), InputChannelPolarity::Toggle, ); let ch4 = InputChannel::new( - g, p.GPIOTE_CH3, Input::new(p.P0_25, Pull::Up), InputChannelPolarity::Toggle, diff --git a/embassy-nrf-examples/src/bin/gpiote_port.rs b/embassy-nrf-examples/src/bin/gpiote_port.rs index 386806dfc..717d3398b 100644 --- a/embassy-nrf-examples/src/bin/gpiote_port.rs +++ b/embassy-nrf-examples/src/bin/gpiote_port.rs @@ -8,12 +8,11 @@ #[path = "../example_common.rs"] mod example_common; -use core::pin::Pin; use defmt::panic; use embassy::executor::Spawner; use embassy::traits::gpio::{WaitForHigh, WaitForLow}; use embassy_nrf::gpio::{AnyPin, Input, Pin as _, Pull}; -use embassy_nrf::gpiote::{self, PortInput}; +use embassy_nrf::gpiote::PortInput; use embassy_nrf::interrupt; use embassy_nrf::Peripherals; use example_common::*; @@ -32,12 +31,12 @@ async fn button_task(n: usize, mut pin: PortInput<'static, AnyPin>) { async fn main(spawner: Spawner) { let p = Peripherals::take().unwrap(); - let g = gpiote::initialize(p.GPIOTE, interrupt::take!(GPIOTE)); + info!("Starting!"); - let btn1 = PortInput::new(g, Input::new(p.P0_11.degrade(), Pull::Up)); - let btn2 = PortInput::new(g, Input::new(p.P0_12.degrade(), Pull::Up)); - let btn3 = PortInput::new(g, Input::new(p.P0_24.degrade(), Pull::Up)); - let btn4 = PortInput::new(g, Input::new(p.P0_25.degrade(), Pull::Up)); + let btn1 = PortInput::new(Input::new(p.P0_11.degrade(), Pull::Up)); + let btn2 = PortInput::new(Input::new(p.P0_12.degrade(), Pull::Up)); + let btn3 = PortInput::new(Input::new(p.P0_24.degrade(), Pull::Up)); + let btn4 = PortInput::new(Input::new(p.P0_25.degrade(), Pull::Up)); spawner.spawn(button_task(1, btn1)).unwrap(); spawner.spawn(button_task(2, btn2)).unwrap(); diff --git a/embassy-nrf-examples/src/bin/ppi.rs b/embassy-nrf-examples/src/bin/ppi.rs index aeda76f21..3c39e032e 100644 --- a/embassy-nrf-examples/src/bin/ppi.rs +++ b/embassy-nrf-examples/src/bin/ppi.rs @@ -21,44 +21,37 @@ use gpiote::{OutputChannel, OutputChannelPolarity}; #[embassy::main] async fn main(spawner: Spawner) { let p = Peripherals::take().unwrap(); - let g = gpiote::initialize(p.GPIOTE, interrupt::take!(GPIOTE)); info!("Starting!"); let button1 = InputChannel::new( - g, p.GPIOTE_CH0, Input::new(p.P0_11, Pull::Up), InputChannelPolarity::HiToLo, ); let button2 = InputChannel::new( - g, p.GPIOTE_CH1, Input::new(p.P0_12, Pull::Up), InputChannelPolarity::HiToLo, ); let button3 = InputChannel::new( - g, p.GPIOTE_CH2, Input::new(p.P0_24, Pull::Up), InputChannelPolarity::HiToLo, ); let button4 = InputChannel::new( - g, p.GPIOTE_CH3, Input::new(p.P0_25, Pull::Up), InputChannelPolarity::HiToLo, ); let led1 = OutputChannel::new( - g, p.GPIOTE_CH4, Output::new(p.P0_13, Level::Low, OutputDrive::Standard), OutputChannelPolarity::Toggle, ); let led2 = OutputChannel::new( - g, p.GPIOTE_CH5, Output::new(p.P0_14, Level::Low, OutputDrive::Standard), OutputChannelPolarity::Toggle, diff --git a/embassy-nrf/src/chips/nrf52805.rs b/embassy-nrf/src/chips/nrf52805.rs index 8b2ba7c00..272cabc06 100644 --- a/embassy-nrf/src/chips/nrf52805.rs +++ b/embassy-nrf/src/chips/nrf52805.rs @@ -24,7 +24,6 @@ embassy_extras::peripherals! { TIMER2, // GPIOTE - GPIOTE, GPIOTE_CH0, GPIOTE_CH1, GPIOTE_CH2, diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs index 9f3ed9cf3..2e77a2fad 100644 --- a/embassy-nrf/src/chips/nrf52810.rs +++ b/embassy-nrf/src/chips/nrf52810.rs @@ -24,7 +24,6 @@ embassy_extras::peripherals! { TIMER2, // GPIOTE - GPIOTE, GPIOTE_CH0, GPIOTE_CH1, GPIOTE_CH2, diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs index 6728f6a41..b3ad5817a 100644 --- a/embassy-nrf/src/chips/nrf52811.rs +++ b/embassy-nrf/src/chips/nrf52811.rs @@ -24,7 +24,6 @@ embassy_extras::peripherals! { TIMER2, // GPIOTE - GPIOTE, GPIOTE_CH0, GPIOTE_CH1, GPIOTE_CH2, diff --git a/embassy-nrf/src/chips/nrf52820.rs b/embassy-nrf/src/chips/nrf52820.rs index 2f9eb5f53..d0a8b9e9a 100644 --- a/embassy-nrf/src/chips/nrf52820.rs +++ b/embassy-nrf/src/chips/nrf52820.rs @@ -25,7 +25,6 @@ embassy_extras::peripherals! { TIMER3, // GPIOTE - GPIOTE, GPIOTE_CH0, GPIOTE_CH1, GPIOTE_CH2, diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs index 015bc51f8..ed94430e4 100644 --- a/embassy-nrf/src/chips/nrf52832.rs +++ b/embassy-nrf/src/chips/nrf52832.rs @@ -29,7 +29,6 @@ embassy_extras::peripherals! { TIMER4, // GPIOTE - GPIOTE, GPIOTE_CH0, GPIOTE_CH1, GPIOTE_CH2, diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs index 404883934..080157d69 100644 --- a/embassy-nrf/src/chips/nrf52833.rs +++ b/embassy-nrf/src/chips/nrf52833.rs @@ -30,7 +30,6 @@ embassy_extras::peripherals! { TIMER4, // GPIOTE - GPIOTE, GPIOTE_CH0, GPIOTE_CH1, GPIOTE_CH2, diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs index 26dfc7e8f..06b508d89 100644 --- a/embassy-nrf/src/chips/nrf52840.rs +++ b/embassy-nrf/src/chips/nrf52840.rs @@ -33,7 +33,6 @@ embassy_extras::peripherals! { TIMER4, // GPIOTE - GPIOTE, GPIOTE_CH0, GPIOTE_CH1, GPIOTE_CH2, diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index bfa5ba68b..f322c1694 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs @@ -2,7 +2,7 @@ use core::convert::Infallible; use core::future::Future; use core::marker::PhantomData; use core::task::{Context, Poll}; -use embassy::interrupt::InterruptExt; +use embassy::interrupt::{Interrupt, InterruptExt}; use embassy::traits::gpio::{WaitForAnyEdge, WaitForHigh, WaitForLow}; use embassy::util::AtomicWaker; use embassy_extras::impl_unborrow; @@ -40,15 +40,7 @@ pub enum OutputChannelPolarity { Toggle, } -/// Token indicating GPIOTE has been correctly initialized. -/// -/// This is not an owned singleton, it is Copy. Drivers that make use of GPIOTE require it. -#[derive(Clone, Copy)] -pub struct Initialized { - _private: (), -} - -pub fn initialize(_gpiote: peripherals::GPIOTE, irq: interrupt::GPIOTE) -> Initialized { +pub(crate) fn init() { #[cfg(any(feature = "nrf52833", feature = "nrf52840"))] let ports = unsafe { &[&*pac::P0::ptr(), &*pac::P1::ptr()] }; #[cfg(not(any(feature = "nrf52833", feature = "nrf52840")))] @@ -62,17 +54,18 @@ pub fn initialize(_gpiote: peripherals::GPIOTE, irq: interrupt::GPIOTE) -> Initi } // Enable interrupts - let g = unsafe { &*pac::GPIOTE::ptr() }; - g.events_port.write(|w| w); - g.intenset.write(|w| w.port().set()); - irq.set_handler(on_irq); + + let irq = unsafe { interrupt::GPIOTE::steal() }; irq.unpend(); irq.enable(); - Initialized { _private: () } + let g = unsafe { &*pac::GPIOTE::ptr() }; + g.events_port.write(|w| w); + g.intenset.write(|w| w.port().set()); } -unsafe fn on_irq(_ctx: *mut ()) { +#[interrupt] +unsafe fn GPIOTE() { let g = &*pac::GPIOTE::ptr(); for i in 0..CHANNEL_COUNT { @@ -133,12 +126,7 @@ impl<'d, C: Channel, T: GpioPin> Drop for InputChannel<'d, C, T> { } impl<'d, C: Channel, T: GpioPin> InputChannel<'d, C, T> { - pub fn new( - _init: Initialized, - ch: C, - pin: Input<'d, T>, - polarity: InputChannelPolarity, - ) -> Self { + pub fn new(ch: C, pin: Input<'d, T>, polarity: InputChannelPolarity) -> Self { let g = unsafe { &*pac::GPIOTE::ptr() }; let num = ch.number(); @@ -217,12 +205,7 @@ impl<'d, C: Channel, T: GpioPin> Drop for OutputChannel<'d, C, T> { } impl<'d, C: Channel, T: GpioPin> OutputChannel<'d, C, T> { - pub fn new( - _init: Initialized, - ch: C, - pin: Output<'d, T>, - polarity: OutputChannelPolarity, - ) -> Self { + pub fn new(ch: C, pin: Output<'d, T>, polarity: OutputChannelPolarity) -> Self { let g = unsafe { &*pac::GPIOTE::ptr() }; let num = ch.number(); @@ -297,7 +280,7 @@ pub struct PortInput<'d, T: GpioPin> { impl<'d, T: GpioPin> Unpin for PortInput<'d, T> {} impl<'d, T: GpioPin> PortInput<'d, T> { - pub fn new(_init: Initialized, pin: Input<'d, T>) -> Self { + pub fn new(pin: Input<'d, T>) -> Self { Self { pin } } } diff --git a/embassy-nrf/src/system.rs b/embassy-nrf/src/system.rs index 5d36e66fa..e358d2c38 100644 --- a/embassy-nrf/src/system.rs +++ b/embassy-nrf/src/system.rs @@ -73,4 +73,7 @@ pub unsafe fn configure(config: Config) { r.events_lfclkstarted.write(|w| unsafe { w.bits(0) }); r.tasks_lfclkstart.write(|w| unsafe { w.bits(1) }); while r.events_lfclkstarted.read().bits() == 0 {} + + // Init GPIOTE + crate::gpiote::init(); } From bfc7f52e6dd7b5ad12fa1f09483fa60f2732ae0c Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Mon, 17 May 2021 00:57:32 +0200 Subject: [PATCH 05/10] Remove stm32. stm32 developemnt continues in the `stm32-neo` branch for now. --- .github/workflows/rust.yml | 18 - embassy-macros/Cargo.toml | 1 - embassy-macros/src/chip/stm32.rs | 28 - embassy-macros/src/lib.rs | 6 +- embassy-stm32-examples/.cargo/config.toml | 28 - embassy-stm32-examples/Cargo.toml | 53 - embassy-stm32-examples/build.rs | 31 - embassy-stm32-examples/memory.x | 5 - embassy-stm32-examples/src/bin/can.rs | 57 - embassy-stm32-examples/src/bin/exti.rs | 57 - embassy-stm32-examples/src/bin/hello.rs | 42 - embassy-stm32-examples/src/bin/rtc_async.rs | 40 - embassy-stm32-examples/src/bin/serial.rs | 80 -- embassy-stm32-examples/src/bin/usb_serial.rs | 119 -- embassy-stm32-examples/src/example_common.rs | 17 - embassy-stm32/Cargo.toml | 53 - embassy-stm32/src/can.rs | 120 -- embassy-stm32/src/exti.rs | 790 ------------- embassy-stm32/src/f4/mod.rs | 4 - embassy-stm32/src/f4/rtc.rs | 505 --------- embassy-stm32/src/f4/serial.rs | 357 ------ embassy-stm32/src/f4/spi.rs | 492 --------- embassy-stm32/src/f4/system.rs | 61 - embassy-stm32/src/fmt.rs | 114 -- embassy-stm32/src/interrupt.rs | 1042 ------------------ embassy-stm32/src/l0/mod.rs | 2 - embassy-stm32/src/l0/rtc.rs | 372 ------- embassy-stm32/src/l0/system.rs | 17 - embassy-stm32/src/lib.rs | 478 -------- 29 files changed, 1 insertion(+), 4988 deletions(-) delete mode 100644 embassy-macros/src/chip/stm32.rs delete mode 100644 embassy-stm32-examples/.cargo/config.toml delete mode 100644 embassy-stm32-examples/Cargo.toml delete mode 100644 embassy-stm32-examples/build.rs delete mode 100644 embassy-stm32-examples/memory.x delete mode 100644 embassy-stm32-examples/src/bin/can.rs delete mode 100644 embassy-stm32-examples/src/bin/exti.rs delete mode 100644 embassy-stm32-examples/src/bin/hello.rs delete mode 100644 embassy-stm32-examples/src/bin/rtc_async.rs delete mode 100644 embassy-stm32-examples/src/bin/serial.rs delete mode 100644 embassy-stm32-examples/src/bin/usb_serial.rs delete mode 100644 embassy-stm32-examples/src/example_common.rs delete mode 100644 embassy-stm32/Cargo.toml delete mode 100644 embassy-stm32/src/can.rs delete mode 100644 embassy-stm32/src/exti.rs delete mode 100644 embassy-stm32/src/f4/mod.rs delete mode 100644 embassy-stm32/src/f4/rtc.rs delete mode 100644 embassy-stm32/src/f4/serial.rs delete mode 100644 embassy-stm32/src/f4/spi.rs delete mode 100644 embassy-stm32/src/f4/system.rs delete mode 100644 embassy-stm32/src/fmt.rs delete mode 100644 embassy-stm32/src/interrupt.rs delete mode 100644 embassy-stm32/src/l0/mod.rs delete mode 100644 embassy-stm32/src/l0/rtc.rs delete mode 100644 embassy-stm32/src/l0/system.rs delete mode 100644 embassy-stm32/src/lib.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index cf70e2e5c..97c668aca 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -55,24 +55,6 @@ jobs: - package: embassy-nrf target: thumbv7em-none-eabi features: nrf52840,defmt - - package: embassy-stm32-examples - target: thumbv7em-none-eabi - features: stm32f405 - - package: embassy-stm32 - target: thumbv7em-none-eabi - features: stm32f405 - - package: embassy-stm32 - target: thumbv7em-none-eabi - features: stm32f446 - - package: embassy-stm32 - target: thumbv7em-none-eabi - features: stm32f405,defmt - - package: embassy-stm32 - target: thumbv6m-none-eabi - features: stm32l0x2 - - package: embassy-stm32 - target: thumbv6m-none-eabi - features: stm32l0x2,defmt - package: embassy-rp-examples target: thumbv6m-none-eabi diff --git a/embassy-macros/Cargo.toml b/embassy-macros/Cargo.toml index 6da2a5868..265a0c083 100644 --- a/embassy-macros/Cargo.toml +++ b/embassy-macros/Cargo.toml @@ -14,7 +14,6 @@ proc-macro2 = "1.0.24" proc-macro = true [features] -stm32 = [] nrf = [] rp = [] std = [] diff --git a/embassy-macros/src/chip/stm32.rs b/embassy-macros/src/chip/stm32.rs deleted file mode 100644 index 3f299650c..000000000 --- a/embassy-macros/src/chip/stm32.rs +++ /dev/null @@ -1,28 +0,0 @@ -use crate::path::ModulePrefix; -use proc_macro2::TokenStream; -use quote::quote; - -pub fn generate(embassy_prefix: &ModulePrefix, config: syn::Expr) -> TokenStream { - let embassy_path = embassy_prefix.append("embassy").path(); - let embassy_stm32_path = embassy_prefix.append("embassy_stm32").path(); - - quote!( - use #embassy_stm32_path::{rtc, interrupt, Peripherals, pac, hal::rcc::RccExt, hal::time::U32Ext}; - - unsafe { #embassy_stm32_path::system::configure(#config) }; - - let (dp, clocks) = Peripherals::take().unwrap(); - - let mut rtc = rtc::RTC::new(dp.TIM2, interrupt::take!(TIM2), clocks); - let rtc = unsafe { make_static(&mut rtc) }; - rtc.start(); - let mut alarm = rtc.alarm1(); - - unsafe { #embassy_path::time::set_clock(rtc) }; - - let alarm = unsafe { make_static(&mut alarm) }; - executor.set_alarm(alarm); - - unsafe { Peripherals::set_peripherals(clocks) }; - ) -} diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs index 590289f94..d91549ca7 100644 --- a/embassy-macros/src/lib.rs +++ b/embassy-macros/src/lib.rs @@ -267,10 +267,6 @@ pub fn interrupt_take(item: TokenStream) -> TokenStream { #[path = "chip/nrf.rs"] mod chip; -#[cfg(feature = "stm32")] -#[path = "chip/stm32.rs"] -mod chip; - #[cfg(feature = "rp")] #[path = "chip/rp.rs"] mod chip; @@ -284,7 +280,7 @@ struct MainArgs { config: Option, } -#[cfg(any(feature = "nrf", feature = "stm32", feature = "rp"))] +#[cfg(any(feature = "nrf", feature = "rp"))] #[proc_macro_attribute] pub fn main(args: TokenStream, item: TokenStream) -> TokenStream { let macro_args = syn::parse_macro_input!(args as syn::AttributeArgs); diff --git a/embassy-stm32-examples/.cargo/config.toml b/embassy-stm32-examples/.cargo/config.toml deleted file mode 100644 index 3ccca879d..000000000 --- a/embassy-stm32-examples/.cargo/config.toml +++ /dev/null @@ -1,28 +0,0 @@ -[target.'cfg(all(target_arch = "arm", target_os = "none"))'] -runner = "probe-run --chip STM32F401CCUx" - -rustflags = [ - # LLD (shipped with the Rust toolchain) is used as the default linker - "-C", "link-arg=--nmagic", - "-C", "link-arg=-Tlink.x", - "-C", "link-arg=-Tdefmt.x", - - # if you run into problems with LLD switch to the GNU linker by commenting out - # this line - # "-C", "linker=arm-none-eabi-ld", - - # if you need to link to pre-compiled C libraries provided by a C toolchain - # use GCC as the linker by commenting out both lines above and then - # uncommenting the three lines below - # "-C", "linker=arm-none-eabi-gcc", - # "-C", "link-arg=-Wl,-Tlink.x", - # "-C", "link-arg=-nostartfiles", - - # Code-size optimizations. - "-Z", "trap-unreachable=no", - "-C", "inline-threshold=5", - "-C", "no-vectorize-loops", -] - -[build] -target = "thumbv7em-none-eabi" diff --git a/embassy-stm32-examples/Cargo.toml b/embassy-stm32-examples/Cargo.toml deleted file mode 100644 index bdb1ca84a..000000000 --- a/embassy-stm32-examples/Cargo.toml +++ /dev/null @@ -1,53 +0,0 @@ -[package] -authors = ["Dario Nieuwenhuis "] -edition = "2018" -name = "embassy-stm32f4-examples" -version = "0.1.0" - -[features] -default = [ - "defmt-default", -] -defmt-default = [] -defmt-trace = [] -defmt-debug = [] -defmt-info = [] -defmt-warn = [] -defmt-error = [] - -stm32f401 = ["embassy-stm32/stm32f401"] -stm32f405 = ["embassy-stm32/stm32f405"] -stm32f407 = ["embassy-stm32/stm32f407"] -stm32f410 = ["embassy-stm32/stm32f410"] -stm32f411 = ["embassy-stm32/stm32f411"] -stm32f412 = ["embassy-stm32/stm32f412"] -stm32f413 = ["embassy-stm32/stm32f413"] -stm32f415 = ["embassy-stm32/stm32f405"] -stm32f417 = ["embassy-stm32/stm32f407"] -stm32f423 = ["embassy-stm32/stm32f413"] -stm32f427 = ["embassy-stm32/stm32f427"] -stm32f429 = ["embassy-stm32/stm32f429"] -stm32f437 = ["embassy-stm32/stm32f427"] -stm32f439 = ["embassy-stm32/stm32f429"] -stm32f446 = ["embassy-stm32/stm32f446"] -stm32f469 = ["embassy-stm32/stm32f469"] -stm32f479 = ["embassy-stm32/stm32f469"] - - -[dependencies] -embassy = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] } -embassy-traits = { version = "0.1.0", path = "../embassy-traits", features = ["defmt"] } -embassy-stm32 = { version = "0.1.0", path = "../embassy-stm32" } -embassy-extras = {version = "0.1.0", path = "../embassy-extras" } - -defmt = "0.2.0" -defmt-rtt = "0.2.0" - -cortex-m = "0.7.1" -cortex-m-rt = "0.6.13" -embedded-hal = { version = "0.2.4" } -panic-probe = { version = "0.2.0", features = ["print-defmt"] } -futures = { version = "0.3.8", default-features = false, features = ["async-await"] } -rtt-target = { version = "0.3", features = ["cortex-m"] } -bxcan = "0.5.0" -usb-device = "0.2.7" diff --git a/embassy-stm32-examples/build.rs b/embassy-stm32-examples/build.rs deleted file mode 100644 index d534cc3df..000000000 --- a/embassy-stm32-examples/build.rs +++ /dev/null @@ -1,31 +0,0 @@ -//! This build script copies the `memory.x` file from the crate root into -//! a directory where the linker can always find it at build time. -//! For many projects this is optional, as the linker always searches the -//! project root directory -- wherever `Cargo.toml` is. However, if you -//! are using a workspace or have a more complicated build setup, this -//! build script becomes required. Additionally, by requesting that -//! Cargo re-run the build script whenever `memory.x` is changed, -//! updating `memory.x` ensures a rebuild of the application with the -//! new memory settings. - -use std::env; -use std::fs::File; -use std::io::Write; -use std::path::PathBuf; - -fn main() { - // Put `memory.x` in our output directory and ensure it's - // on the linker search path. - let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); - File::create(out.join("memory.x")) - .unwrap() - .write_all(include_bytes!("memory.x")) - .unwrap(); - println!("cargo:rustc-link-search={}", out.display()); - - // By default, Cargo will re-run a build script whenever - // any file in the project changes. By specifying `memory.x` - // here, we ensure the build script is only re-run when - // `memory.x` is changed. - println!("cargo:rerun-if-changed=memory.x"); -} diff --git a/embassy-stm32-examples/memory.x b/embassy-stm32-examples/memory.x deleted file mode 100644 index efa700b8a..000000000 --- a/embassy-stm32-examples/memory.x +++ /dev/null @@ -1,5 +0,0 @@ -MEMORY -{ - FLASH : ORIGIN = 0x08000000, LENGTH = 64K - RAM : ORIGIN = 0x20000000, LENGTH = 32K -} diff --git a/embassy-stm32-examples/src/bin/can.rs b/embassy-stm32-examples/src/bin/can.rs deleted file mode 100644 index 72272212e..000000000 --- a/embassy-stm32-examples/src/bin/can.rs +++ /dev/null @@ -1,57 +0,0 @@ -#![no_std] -#![no_main] -#![feature(trait_alias)] -#![feature(type_alias_impl_trait)] -#![feature(min_type_alias_impl_trait)] -#![feature(impl_trait_in_bindings)] - -#[path = "../example_common.rs"] -mod example_common; -use example_common::{panic, *}; - -use bxcan::filter::Mask32; -use cortex_m_rt::entry; -use embassy::executor::Executor; -use embassy::util::Forever; -use embassy_stm32::hal::prelude::*; -use embassy_stm32::hal::{can::Can, stm32}; -use embassy_stm32::{can, interrupt}; - -#[embassy::task] -async fn run(dp: stm32::Peripherals, _cp: cortex_m::Peripherals) { - let gpioa = dp.GPIOA.split(); - - let rx = gpioa.pa11.into_alternate_af9(); - let tx = gpioa.pa12.into_alternate_af9(); - let mut can = bxcan::Can::new(Can::new(dp.CAN1, (tx, rx))); - - // APB1 (PCLK1): 24MHz, Bit rate: 20kBit/s, Sample Point 87.5% - // Value was calculated with http://www.bittiming.can-wiki.info/ - can.modify_config().set_bit_timing(0x001c_004a); - // Configure filters so that can frames can be received. - can.modify_filters().enable_bank(0, Mask32::accept_all()); - - let mut can = can::Can::new(can, interrupt::take!(CAN1_TX), interrupt::take!(CAN1_RX0)); - - let _frame = can.receive().await; -} - -static EXECUTOR: Forever = Forever::new(); - -#[entry] -fn main() -> ! { - let dp = stm32::Peripherals::take().unwrap(); - let cp = cortex_m::peripheral::Peripherals::take().unwrap(); - - dp.DBGMCU.cr.modify(|_, w| { - w.dbg_sleep().set_bit(); - w.dbg_standby().set_bit(); - w.dbg_stop().set_bit() - }); - dp.RCC.ahb1enr.modify(|_, w| w.dma1en().enabled()); - - let executor = EXECUTOR.put(Executor::new()); - executor.run(|spawner| { - unwrap!(spawner.spawn(run(dp, cp))); - }); -} diff --git a/embassy-stm32-examples/src/bin/exti.rs b/embassy-stm32-examples/src/bin/exti.rs deleted file mode 100644 index e13b23bac..000000000 --- a/embassy-stm32-examples/src/bin/exti.rs +++ /dev/null @@ -1,57 +0,0 @@ -#![no_std] -#![no_main] -#![feature(trait_alias)] -#![feature(min_type_alias_impl_trait)] -#![feature(impl_trait_in_bindings)] -#![feature(type_alias_impl_trait)] - -#[path = "../example_common.rs"] -mod example_common; -use example_common::{panic, *}; - -use cortex_m_rt::entry; -use embassy::executor::Executor; -use embassy::traits::gpio::*; -use embassy::util::Forever; -use embassy_stm32::exti::ExtiPin; -use embassy_stm32::hal::prelude::*; -use embassy_stm32::interrupt; -use embassy_stm32::pac as stm32; -use futures::pin_mut; - -#[embassy::task] -async fn run(dp: stm32::Peripherals, _cp: cortex_m::Peripherals) { - let gpioa = dp.GPIOA.split(); - - let button = gpioa.pa0.into_pull_up_input(); - let mut syscfg = dp.SYSCFG.constrain(); - - let mut pin = ExtiPin::new(button, interrupt::take!(EXTI0), &mut syscfg); - - info!("Starting loop"); - - loop { - pin.wait_for_rising_edge().await; - info!("edge detected!"); - } -} - -static EXECUTOR: Forever = Forever::new(); - -#[entry] -fn main() -> ! { - let dp = stm32::Peripherals::take().unwrap(); - let cp = cortex_m::peripheral::Peripherals::take().unwrap(); - - dp.DBGMCU.cr.modify(|_, w| { - w.dbg_sleep().set_bit(); - w.dbg_standby().set_bit(); - w.dbg_stop().set_bit() - }); - dp.RCC.ahb1enr.modify(|_, w| w.dma1en().enabled()); - - let executor = EXECUTOR.put(Executor::new()); - executor.run(|spawner| { - unwrap!(spawner.spawn(run(dp, cp))); - }); -} diff --git a/embassy-stm32-examples/src/bin/hello.rs b/embassy-stm32-examples/src/bin/hello.rs deleted file mode 100644 index b851482d4..000000000 --- a/embassy-stm32-examples/src/bin/hello.rs +++ /dev/null @@ -1,42 +0,0 @@ -#![no_std] -#![no_main] -#![feature(trait_alias)] -#![feature(min_type_alias_impl_trait)] -#![feature(impl_trait_in_bindings)] -#![feature(type_alias_impl_trait)] - -#[path = "../example_common.rs"] -mod example_common; -use example_common::*; - -use cortex_m_rt::entry; -use embassy_stm32::hal::prelude::*; - -#[entry] -fn main() -> ! { - info!("Hello World!"); - - let p = embassy_stm32::pac::Peripherals::take().unwrap(); - - p.DBGMCU.cr.modify(|_, w| { - w.dbg_sleep().set_bit(); - w.dbg_standby().set_bit(); - w.dbg_stop().set_bit() - }); - p.RCC.ahb1enr.modify(|_, w| w.dma1en().enabled()); - - let gpioa = p.GPIOA.split(); - let gpioc = p.GPIOC.split(); - - let mut led = gpioc.pc13.into_push_pull_output(); - let button = gpioa.pa0.into_pull_up_input(); - led.set_low().unwrap(); - - loop { - if button.is_high().unwrap() { - led.set_low().unwrap(); - } else { - led.set_high().unwrap(); - } - } -} diff --git a/embassy-stm32-examples/src/bin/rtc_async.rs b/embassy-stm32-examples/src/bin/rtc_async.rs deleted file mode 100644 index b780c3c10..000000000 --- a/embassy-stm32-examples/src/bin/rtc_async.rs +++ /dev/null @@ -1,40 +0,0 @@ -#![no_std] -#![no_main] -#![feature(min_type_alias_impl_trait)] -#![feature(impl_trait_in_bindings)] -#![feature(type_alias_impl_trait)] - -#[path = "../example_common.rs"] -mod example_common; -use example_common::*; - -use defmt::panic; -use embassy; - -use embassy::executor::Spawner; -use embassy::time::{Duration, Timer}; -use embassy_stm32; -use embassy_stm32::hal; - -#[embassy::task] -async fn run1() { - loop { - info!("BIG INFREQUENT TICK"); - Timer::after(Duration::from_ticks(32768 * 2 as u64)).await; - } -} - -#[embassy::task] -async fn run2() { - loop { - info!("tick"); - Timer::after(Duration::from_ticks(13000 as u64)).await; - } -} - -#[embassy::main(config = "embassy_stm32::system::Config::new().use_hse(16)")] -async fn main(spawner: Spawner) { - let (dp, clocks) = embassy_stm32::Peripherals::take().unwrap(); - - spawner.spawn(run1()).unwrap(); -} diff --git a/embassy-stm32-examples/src/bin/serial.rs b/embassy-stm32-examples/src/bin/serial.rs deleted file mode 100644 index c48ba746b..000000000 --- a/embassy-stm32-examples/src/bin/serial.rs +++ /dev/null @@ -1,80 +0,0 @@ -#![no_std] -#![no_main] -#![feature(trait_alias)] -#![feature(min_type_alias_impl_trait)] -#![feature(impl_trait_in_bindings)] -#![feature(type_alias_impl_trait)] - -#[path = "../example_common.rs"] -mod example_common; -use example_common::{panic, *}; - -use cortex_m::singleton; -use cortex_m_rt::entry; -use embassy::executor::{Executor, Spawner}; -use embassy::traits::uart::{Read, ReadUntilIdle, Write}; -use embassy::util::Forever; -use embassy_stm32::hal::dma::StreamsTuple; -use embassy_stm32::hal::prelude::*; -use embassy_stm32::hal::serial::config::Config; -use embassy_stm32::interrupt; -use embassy_stm32::pac as stm32; -use embassy_stm32::serial; -use futures::pin_mut; - -#[embassy::main(config = "embassy_stm32::system::Config::new().use_hse(16).sysclk(48).pclk1(24)")] -async fn main(spawner: Spawner) { - let (dp, clocks) = embassy_stm32::Peripherals::take().unwrap(); - let cp = cortex_m::peripheral::Peripherals::take().unwrap(); - - dp.DBGMCU.cr.modify(|_, w| { - w.dbg_sleep().set_bit(); - w.dbg_standby().set_bit(); - w.dbg_stop().set_bit() - }); - - // https://gist.github.com/thalesfragoso/a07340c5df6eee3b04c42fdc69ecdcb1 - let gpioa = dp.GPIOA.split(); - let streams = StreamsTuple::new(dp.DMA2); - - let _serial = unsafe { - serial::Serial::new( - dp.USART1, - (streams.7, streams.2), - ( - gpioa.pa9.into_alternate_af7(), - gpioa.pa10.into_alternate_af7(), - ), - interrupt::take!(DMA2_STREAM7), - interrupt::take!(DMA2_STREAM2), - interrupt::take!(USART1), - Config::default().baudrate(9600.bps()), - clocks, - ) - }; - - let streams = StreamsTuple::new(dp.DMA1); - - let mut serial = unsafe { - serial::Serial::new( - dp.USART2, - (streams.6, streams.5), - ( - gpioa.pa2.into_alternate_af7(), - gpioa.pa3.into_alternate_af7(), - ), - interrupt::take!(DMA1_STREAM6), - interrupt::take!(DMA1_STREAM5), - interrupt::take!(USART2), - Config::default().baudrate(9600.bps()), - clocks, - ) - }; - pin_mut!(serial); - - let buf = singleton!(: [u8; 30] = [0; 30]).unwrap(); - - buf[5] = 0x01; - serial.as_mut().write(buf).await.unwrap(); - serial.as_mut().read_until_idle(buf).await.unwrap(); -} diff --git a/embassy-stm32-examples/src/bin/usb_serial.rs b/embassy-stm32-examples/src/bin/usb_serial.rs deleted file mode 100644 index 38656b979..000000000 --- a/embassy-stm32-examples/src/bin/usb_serial.rs +++ /dev/null @@ -1,119 +0,0 @@ -#![no_std] -#![no_main] -#![feature(type_alias_impl_trait)] -#![feature(min_type_alias_impl_trait)] -#![feature(impl_trait_in_bindings)] - -#[path = "../example_common.rs"] -mod example_common; -use example_common::*; - -use cortex_m_rt::entry; -use defmt::panic; -use embassy::executor::{Executor, Spawner}; -use embassy::interrupt::InterruptExt; -use embassy::io::{AsyncBufReadExt, AsyncWriteExt}; -use embassy::time::{Duration, Timer}; -use embassy::util::Forever; -use embassy_extras::usb::usb_serial::UsbSerial; -use embassy_extras::usb::Usb; -use embassy_stm32::hal::otg_fs::{UsbBus, USB}; -use embassy_stm32::hal::prelude::*; -use embassy_stm32::{interrupt, pac, rtc}; -use futures::future::{select, Either}; -use futures::pin_mut; -use usb_device::bus::UsbBusAllocator; -use usb_device::prelude::*; - -#[embassy::task] -async fn run1(bus: &'static mut UsbBusAllocator>) { - info!("Async task"); - - let mut read_buf = [0u8; 128]; - let mut write_buf = [0u8; 128]; - let serial = UsbSerial::new(bus, &mut read_buf, &mut write_buf); - - let device = UsbDeviceBuilder::new(bus, UsbVidPid(0x16c0, 0x27dd)) - .manufacturer("Fake company") - .product("Serial port") - .serial_number("TEST") - .device_class(0x02) - .build(); - - let irq = interrupt::take!(OTG_FS); - irq.set_priority(interrupt::Priority::P3); - - let usb = Usb::new(device, serial, irq); - pin_mut!(usb); - usb.as_mut().start(); - - let (mut read_interface, mut write_interface) = usb.as_ref().take_serial_0(); - - let mut buf = [0u8; 64]; - loop { - let mut n = 0; - let left = { - let recv_fut = async { - loop { - let byte = unwrap!(read_interface.read_byte().await); - unwrap!(write_interface.write_byte(byte).await); - buf[n] = byte; - - n += 1; - if byte == b'\n' || byte == b'\r' || n == buf.len() { - break; - } - } - }; - pin_mut!(recv_fut); - - let timeout = Timer::after(Duration::from_ticks(32768 * 10)); - - match select(recv_fut, timeout).await { - Either::Left(_) => true, - Either::Right(_) => false, - } - }; - - if left { - for c in buf[..n].iter_mut() { - if 0x61 <= *c && *c <= 0x7a { - *c &= !0x20; - } - } - unwrap!(write_interface.write_byte(b'\n').await); - unwrap!(write_interface.write_all(&buf[..n]).await); - unwrap!(write_interface.write_byte(b'\n').await); - } else { - unwrap!(write_interface.write_all(b"\r\nSend something\r\n").await); - } - } -} - -static USB_BUS: Forever>> = Forever::new(); - -#[embassy::main( - config = "embassy_stm32::system::Config::new().use_hse(25).sysclk(48).require_pll48clk()" -)] -async fn main(spawner: Spawner) -> ! { - static mut EP_MEMORY: [u32; 1024] = [0; 1024]; - - info!("Hello World!"); - - let (p, clocks) = embassy_stm32::Peripherals::take().unwrap(); - - let gpioa = p.GPIOA.split(); - let usb = USB { - usb_global: p.OTG_FS_GLOBAL, - usb_device: p.OTG_FS_DEVICE, - usb_pwrclk: p.OTG_FS_PWRCLK, - pin_dm: gpioa.pa11.into_alternate_af10(), - pin_dp: gpioa.pa12.into_alternate_af10(), - hclk: clocks.hclk(), - }; - // Rust analyzer isn't recognizing the static ref magic `cortex-m` does - #[allow(unused_unsafe)] - let usb_bus = USB_BUS.put(UsbBus::new(usb, unsafe { &mut EP_MEMORY })); - - spawner.spawn(run1(usb_bus)).unwrap(); -} diff --git a/embassy-stm32-examples/src/example_common.rs b/embassy-stm32-examples/src/example_common.rs deleted file mode 100644 index 54d633837..000000000 --- a/embassy-stm32-examples/src/example_common.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![macro_use] - -use defmt_rtt as _; // global logger -use panic_probe as _; - -pub use defmt::*; - -use core::sync::atomic::{AtomicUsize, Ordering}; - -defmt::timestamp! {"{=u64}", { - static COUNT: AtomicUsize = AtomicUsize::new(0); - // NOTE(no-CAS) `timestamps` runs with interrupts disabled - let n = COUNT.load(Ordering::Relaxed); - COUNT.store(n + 1, Ordering::Relaxed); - n as u64 - } -} diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml deleted file mode 100644 index 1eeb2d21d..000000000 --- a/embassy-stm32/Cargo.toml +++ /dev/null @@ -1,53 +0,0 @@ -[package] -name = "embassy-stm32" -version = "0.1.0" -authors = ["Dario Nieuwenhuis "] -edition = "2018" - -[features] -defmt-trace = [ ] -defmt-debug = [ ] -defmt-info = [ ] -defmt-warn = [ ] -defmt-error = [ ] - -stm32f401 = ["stm32f4xx-hal/stm32f401"] -stm32f405 = ["stm32f4xx-hal/stm32f405"] -stm32f407 = ["stm32f4xx-hal/stm32f407"] -stm32f410 = ["stm32f4xx-hal/stm32f410"] -stm32f411 = ["stm32f4xx-hal/stm32f411"] -stm32f412 = ["stm32f4xx-hal/stm32f412"] -stm32f413 = ["stm32f4xx-hal/stm32f413"] -stm32f415 = ["stm32f4xx-hal/stm32f405"] -stm32f417 = ["stm32f4xx-hal/stm32f407"] -stm32f423 = ["stm32f4xx-hal/stm32f413"] -stm32f427 = ["stm32f4xx-hal/stm32f427"] -stm32f429 = ["stm32f4xx-hal/stm32f429"] -stm32f437 = ["stm32f4xx-hal/stm32f427"] -stm32f439 = ["stm32f4xx-hal/stm32f429"] -stm32f446 = ["stm32f4xx-hal/stm32f446"] -stm32f469 = ["stm32f4xx-hal/stm32f469"] -stm32f479 = ["stm32f4xx-hal/stm32f469"] - -stm32l0x1 = ["stm32l0xx-hal/stm32l0x1"] -stm32l0x2 = ["stm32l0xx-hal/stm32l0x2"] -stm32l0x3 = ["stm32l0xx-hal/stm32l0x3"] - -[dependencies] -embassy = { version = "0.1.0", path = "../embassy" } -embassy-macros = { version = "0.1.0", path = "../embassy-macros", features = ["stm32"]} -embassy-extras = {version = "0.1.0", path = "../embassy-extras" } - -atomic-polyfill = "0.1.1" -critical-section = "0.2.1" -defmt = { version = "0.2.0", optional = true } -log = { version = "0.4.11", optional = true } -cortex-m-rt = "0.6.13" -cortex-m = "0.7.1" -embedded-hal = { version = "0.2.4" } -embedded-dma = { version = "0.1.2" } -bxcan = "0.5.0" -nb = "*" -stm32f4xx-hal = { version = "0.9.0", features = ["rt", "can", "usb_fs"], optional = true } -stm32l0xx-hal = { version = "0.7.0", features = ["rt"], optional = true } -futures = { version = "0.3.5", default-features = false, features = ["async-await"] } diff --git a/embassy-stm32/src/can.rs b/embassy-stm32/src/can.rs deleted file mode 100644 index f97e900ea..000000000 --- a/embassy-stm32/src/can.rs +++ /dev/null @@ -1,120 +0,0 @@ -//! Async low power Serial. -//! -//! The peripheral is autmatically enabled and disabled as required to save power. -//! Lowest power consumption can only be guaranteed if the send receive futures -//! are dropped correctly (e.g. not using `mem::forget()`). - -use bxcan; -use bxcan::Interrupts; -use core::future::Future; -use embassy::interrupt::Interrupt; -use embassy::util::InterruptFuture; -use nb; -use nb::block; - -use crate::interrupt; - -/// Interface to the Serial peripheral -pub struct Can { - can: bxcan::Can, - tx_int: T::TInterrupt, - rx_int: T::RInterrupt, -} - -impl Can { - pub fn new(mut can: bxcan::Can, tx_int: T::TInterrupt, rx_int: T::RInterrupt) -> Self { - // Sync to the bus and start normal operation. - can.enable_interrupts( - Interrupts::TRANSMIT_MAILBOX_EMPTY | Interrupts::FIFO0_MESSAGE_PENDING, - ); - block!(can.enable()).unwrap(); - - Can { - can: can, - tx_int: tx_int, - rx_int: rx_int, - } - } - - /// Sends can frame. - /// - /// This method async-blocks until the frame is transmitted. - pub fn transmit<'a>(&'a mut self, frame: &'a bxcan::Frame) -> impl Future + 'a { - async move { - let fut = InterruptFuture::new(&mut self.tx_int); - // Infallible - self.can.transmit(frame).unwrap(); - - fut.await; - } - } - - /// Receive can frame. - /// - /// This method async-blocks until the frame is received. - pub fn receive<'a>(&'a mut self) -> impl Future + 'a { - async move { - let mut frame: Option; - - loop { - let fut = InterruptFuture::new(&mut self.rx_int); - frame = match self.can.receive() { - Ok(frame) => Some(frame), - Err(nb::Error::WouldBlock) => None, - Err(nb::Error::Other(_)) => None, // Ignore overrun errors. - }; - if frame.is_some() { - break; - } - fut.await; - } - - frame.unwrap() - } - } -} - -mod private { - pub trait Sealed {} -} - -pub trait Instance: bxcan::Instance + private::Sealed { - type TInterrupt: Interrupt; - type RInterrupt: Interrupt; -} - -macro_rules! can { - ($($can:ident => ($tint:ident, $rint:ident),)+) => { - $( - impl private::Sealed for crate::hal::can::Can {} - impl Instance for crate::hal::can::Can { - type TInterrupt = interrupt::$tint; - type RInterrupt = interrupt::$rint; - } - )+ - } -} - -#[cfg(any( - feature = "stm32f401", - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f410", - feature = "stm32f411", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479", -))] -can! { - CAN1 => (CAN1_TX, CAN1_RX0), - CAN2 => (CAN2_TX, CAN2_RX0), -} diff --git a/embassy-stm32/src/exti.rs b/embassy-stm32/src/exti.rs deleted file mode 100644 index 3d83c2d53..000000000 --- a/embassy-stm32/src/exti.rs +++ /dev/null @@ -1,790 +0,0 @@ -use core::future::Future; -use core::mem; -use cortex_m; - -use crate::hal::gpio; - -#[cfg(any( - feature = "stm32f401", - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f410", - feature = "stm32f411", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479", -))] -use crate::hal::syscfg::SysCfg; - -#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] -use crate::hal::syscfg::SYSCFG as SysCfg; - -use embassy::traits::gpio::{ - WaitForAnyEdge, WaitForFallingEdge, WaitForHigh, WaitForLow, WaitForRisingEdge, -}; -use embassy::util::InterruptFuture; - -use embedded_hal::digital::v2 as digital; - -use crate::interrupt; - -pub struct ExtiPin { - pin: T, - interrupt: T::Interrupt, -} - -impl ExtiPin { - pub fn new(mut pin: T, interrupt: T::Interrupt, syscfg: &mut SysCfg) -> Self { - critical_section::with(|_| { - pin.make_source(syscfg); - }); - - Self { pin, interrupt } - } -} - -impl digital::OutputPin for ExtiPin { - type Error = T::Error; - - fn set_low(&mut self) -> Result<(), Self::Error> { - self.pin.set_low() - } - - fn set_high(&mut self) -> Result<(), Self::Error> { - self.pin.set_high() - } -} - -impl digital::StatefulOutputPin for ExtiPin { - fn is_set_low(&self) -> Result { - self.pin.is_set_low() - } - - fn is_set_high(&self) -> Result { - self.pin.is_set_high() - } -} - -impl digital::ToggleableOutputPin for ExtiPin { - type Error = T::Error; - - fn toggle(&mut self) -> Result<(), Self::Error> { - self.pin.toggle() - } -} - -impl digital::InputPin for ExtiPin { - type Error = T::Error; - - fn is_high(&self) -> Result { - self.pin.is_high() - } - - fn is_low(&self) -> Result { - self.pin.is_low() - } -} - -impl ExtiPin { - fn wait_for_state<'a>(&'a mut self, state: bool) -> impl Future + 'a { - async move { - let fut = InterruptFuture::new(&mut self.interrupt); - let pin = &mut self.pin; - critical_section::with(|_| { - pin.trigger_edge(if state { - EdgeOption::Rising - } else { - EdgeOption::Falling - }); - }); - - if (state && self.pin.is_high().unwrap_or(false)) - || (!state && self.pin.is_low().unwrap_or(false)) - { - return; - } - - fut.await; - - self.pin.clear_pending_bit(); - } - } -} - -impl ExtiPin { - fn wait_for_edge<'a>(&'a mut self, state: EdgeOption) -> impl Future + 'a { - self.pin.clear_pending_bit(); - async move { - let fut = InterruptFuture::new(&mut self.interrupt); - let pin = &mut self.pin; - critical_section::with(|_| { - pin.trigger_edge(state); - }); - - fut.await; - - self.pin.clear_pending_bit(); - } - } -} - -impl WaitForHigh for ExtiPin { - type Future<'a> = impl Future + 'a; - - fn wait_for_high<'a>(&'a mut self) -> Self::Future<'a> { - self.wait_for_state(true) - } -} - -impl WaitForLow for ExtiPin { - type Future<'a> = impl Future + 'a; - - fn wait_for_low<'a>(&'a mut self) -> Self::Future<'a> { - self.wait_for_state(false) - } -} - -/* - Irq Handler Description - EXTI0_IRQn EXTI0_IRQHandler Handler for pins connected to line 0 - EXTI1_IRQn EXTI1_IRQHandler Handler for pins connected to line 1 - EXTI2_IRQn EXTI2_IRQHandler Handler for pins connected to line 2 - EXTI3_IRQn EXTI3_IRQHandler Handler for pins connected to line 3 - EXTI4_IRQn EXTI4_IRQHandler Handler for pins connected to line 4 - EXTI9_5_IRQn EXTI9_5_IRQHandler Handler for pins connected to line 5 to 9 - EXTI15_10_IRQn EXTI15_10_IRQHandler Handler for pins connected to line 10 to 15 -*/ - -impl WaitForRisingEdge for ExtiPin { - type Future<'a> = impl Future + 'a; - - fn wait_for_rising_edge<'a>(&'a mut self) -> Self::Future<'a> { - self.wait_for_edge(EdgeOption::Rising) - } -} - -impl WaitForFallingEdge for ExtiPin { - type Future<'a> = impl Future + 'a; - - fn wait_for_falling_edge<'a>(&'a mut self) -> Self::Future<'a> { - self.wait_for_edge(EdgeOption::Falling) - } -} - -impl WaitForAnyEdge for ExtiPin { - type Future<'a> = impl Future + 'a; - - fn wait_for_any_edge<'a>(&'a mut self) -> Self::Future<'a> { - self.wait_for_edge(EdgeOption::RisingFalling) - } -} - -mod private { - pub trait Sealed {} -} - -#[derive(Copy, Clone)] -pub enum EdgeOption { - Rising, - Falling, - RisingFalling, -} - -pub trait WithInterrupt: private::Sealed { - type Interrupt: interrupt::Interrupt; -} - -pub trait Instance: WithInterrupt { - fn make_source(&mut self, syscfg: &mut SysCfg); - fn clear_pending_bit(&mut self); - fn trigger_edge(&mut self, edge: EdgeOption); -} - -macro_rules! exti { - ($set:ident, [ - $($INT:ident => $pin:ident,)+ - ]) => { - $( - impl private::Sealed for gpio::$set::$pin {} - impl WithInterrupt for gpio::$set::$pin { - type Interrupt = interrupt::$INT; - } - - #[cfg(any( - feature = "stm32f401", - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f410", - feature = "stm32f411", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479", - ))] - impl Instance for gpio::$set::$pin> { - fn make_source(&mut self, syscfg: &mut SysCfg) { - use crate::hal::gpio::ExtiPin; - self.make_interrupt_source(syscfg); - } - - fn clear_pending_bit(&mut self) { - use crate::hal::{gpio::Edge, gpio::ExtiPin, syscfg::SysCfg}; - - self.clear_interrupt_pending_bit(); - } - - fn trigger_edge(&mut self, edge: EdgeOption) { - use crate::hal::{gpio::Edge, gpio::ExtiPin, syscfg::SysCfg}; - use crate::pac::EXTI; - let mut exti: EXTI = unsafe { mem::transmute(()) }; - let edge = match edge { - EdgeOption::Falling => Edge::FALLING, - EdgeOption::Rising => Edge::RISING, - EdgeOption::RisingFalling => Edge::RISING_FALLING, - }; - self.trigger_on_edge(&mut exti, edge); - self.enable_interrupt(&mut exti); - } - } - - #[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] - impl Instance for gpio::$set::$pin { - fn make_source(&mut self, syscfg: &mut SysCfg) {} - - fn clear_pending_bit(&mut self) { - use crate::hal::{ - exti::{Exti, ExtiLine, GpioLine, TriggerEdge}, - syscfg::SYSCFG, - }; - - Exti::unpend(GpioLine::from_raw_line(self.pin_number()).unwrap()); - } - - fn trigger_edge(&mut self, edge: EdgeOption) { - use crate::hal::{ - exti::{Exti, ExtiLine, GpioLine, TriggerEdge}, - syscfg::SYSCFG, - }; - - use crate::pac::EXTI; - - let edge = match edge { - EdgeOption::Falling => TriggerEdge::Falling, - EdgeOption::Rising => TriggerEdge::Rising, - EdgeOption::RisingFalling => TriggerEdge::Both, - }; - - let exti: EXTI = unsafe { mem::transmute(()) }; - let mut exti = Exti::new(exti); - let port = self.port(); - let mut syscfg: SYSCFG = unsafe { mem::transmute(()) }; - let line = GpioLine::from_raw_line(self.pin_number()).unwrap(); - exti.listen_gpio(&mut syscfg, port, line, edge); - } - } - )+ - }; -} - -#[cfg(any( - feature = "stm32f401", - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f410", - feature = "stm32f411", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479" -))] -exti!(gpioa, [ - EXTI0 => PA0, - EXTI1 => PA1, - EXTI2 => PA2, - EXTI3 => PA3, - EXTI4 => PA4, - EXTI9_5 => PA5, - EXTI9_5 => PA6, - EXTI9_5 => PA7, - EXTI9_5 => PA8, - EXTI9_5 => PA9, - EXTI15_10 => PA10, - EXTI15_10 => PA11, - EXTI15_10 => PA12, - EXTI15_10 => PA13, - EXTI15_10 => PA14, - EXTI15_10 => PA15, -]); - -#[cfg(any( - feature = "stm32f401", - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f410", - feature = "stm32f411", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479" -))] -exti!(gpiob, [ - EXTI0 => PB0, - EXTI1 => PB1, - EXTI2 => PB2, - EXTI3 => PB3, - EXTI4 => PB4, - EXTI9_5 => PB5, - EXTI9_5 => PB6, - EXTI9_5 => PB7, - EXTI9_5 => PB8, - EXTI9_5 => PB9, - EXTI15_10 => PB10, - EXTI15_10 => PB11, - EXTI15_10 => PB12, - EXTI15_10 => PB13, - EXTI15_10 => PB14, - EXTI15_10 => PB15, -]); - -#[cfg(any( - feature = "stm32f401", - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f410", - feature = "stm32f411", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479" -))] -exti!(gpioc, [ - EXTI0 => PC0, - EXTI1 => PC1, - EXTI2 => PC2, - EXTI3 => PC3, - EXTI4 => PC4, - EXTI9_5 => PC5, - EXTI9_5 => PC6, - EXTI9_5 => PC7, - EXTI9_5 => PC8, - EXTI9_5 => PC9, - EXTI15_10 => PC10, - EXTI15_10 => PC11, - EXTI15_10 => PC12, - EXTI15_10 => PC13, - EXTI15_10 => PC14, - EXTI15_10 => PC15, -]); - -#[cfg(any( - feature = "stm32f401", - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f411", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479" -))] -exti!(gpiod, [ - EXTI0 => PD0, - EXTI1 => PD1, - EXTI2 => PD2, - EXTI3 => PD3, - EXTI4 => PD4, - EXTI9_5 => PD5, - EXTI9_5 => PD6, - EXTI9_5 => PD7, - EXTI9_5 => PD8, - EXTI9_5 => PD9, - EXTI15_10 => PD10, - EXTI15_10 => PD11, - EXTI15_10 => PD12, - EXTI15_10 => PD13, - EXTI15_10 => PD14, - EXTI15_10 => PD15, -]); - -#[cfg(any( - feature = "stm32f401", - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f411", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479" -))] -exti!(gpioe, [ - EXTI0 => PE0, - EXTI1 => PE1, - EXTI2 => PE2, - EXTI3 => PE3, - EXTI4 => PE4, - EXTI9_5 => PE5, - EXTI9_5 => PE6, - EXTI9_5 => PE7, - EXTI9_5 => PE8, - EXTI9_5 => PE9, - EXTI15_10 => PE10, - EXTI15_10 => PE11, - EXTI15_10 => PE12, - EXTI15_10 => PE13, - EXTI15_10 => PE14, - EXTI15_10 => PE15, -]); - -#[cfg(any( - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479" -))] -exti!(gpiof, [ - EXTI0 => PF0, - EXTI1 => PF1, - EXTI2 => PF2, - EXTI3 => PF3, - EXTI4 => PF4, - EXTI9_5 => PF5, - EXTI9_5 => PF6, - EXTI9_5 => PF7, - EXTI9_5 => PF8, - EXTI9_5 => PF9, - EXTI15_10 => PF10, - EXTI15_10 => PF11, - EXTI15_10 => PF12, - EXTI15_10 => PF13, - EXTI15_10 => PF14, - EXTI15_10 => PF15, -]); - -#[cfg(any( - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479" -))] -exti!(gpiog, [ - EXTI0 => PG0, - EXTI1 => PG1, - EXTI2 => PG2, - EXTI3 => PG3, - EXTI4 => PG4, - EXTI9_5 => PG5, - EXTI9_5 => PG6, - EXTI9_5 => PG7, - EXTI9_5 => PG8, - EXTI9_5 => PG9, - EXTI15_10 => PG10, - EXTI15_10 => PG11, - EXTI15_10 => PG12, - EXTI15_10 => PG13, - EXTI15_10 => PG14, - EXTI15_10 => PG15, -]); - -#[cfg(any( - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f410", - feature = "stm32f411", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479" -))] -exti!(gpioh, [ - EXTI0 => PH0, - EXTI1 => PH1, - EXTI2 => PH2, - EXTI3 => PH3, - EXTI4 => PH4, - EXTI9_5 => PH5, - EXTI9_5 => PH6, - EXTI9_5 => PH7, - EXTI9_5 => PH8, - EXTI9_5 => PH9, - EXTI15_10 => PH10, - EXTI15_10 => PH11, - EXTI15_10 => PH12, - EXTI15_10 => PH13, - EXTI15_10 => PH14, - EXTI15_10 => PH15, -]); - -#[cfg(any(feature = "stm32f401"))] -exti!(gpioh, [ - EXTI0 => PH0, - EXTI1 => PH1, -]); - -#[cfg(any( - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f469", - feature = "stm32f479" -))] -exti!(gpioi, [ - EXTI0 => PI0, - EXTI1 => PI1, - EXTI2 => PI2, - EXTI3 => PI3, - EXTI4 => PI4, - EXTI9_5 => PI5, - EXTI9_5 => PI6, - EXTI9_5 => PI7, - EXTI9_5 => PI8, - EXTI9_5 => PI9, - EXTI15_10 => PI10, - EXTI15_10 => PI11, - EXTI15_10 => PI12, - EXTI15_10 => PI13, - EXTI15_10 => PI14, - EXTI15_10 => PI15, -]); - -#[cfg(any( - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f469", - feature = "stm32f479" -))] -exti!(gpioj, [ - EXTI0 => PJ0, - EXTI1 => PJ1, - EXTI2 => PJ2, - EXTI3 => PJ3, - EXTI4 => PJ4, - EXTI9_5 => PJ5, - EXTI9_5 => PJ6, - EXTI9_5 => PJ7, - EXTI9_5 => PJ8, - EXTI9_5 => PJ9, - EXTI15_10 => PJ10, - EXTI15_10 => PJ11, - EXTI15_10 => PJ12, - EXTI15_10 => PJ13, - EXTI15_10 => PJ14, - EXTI15_10 => PJ15, -]); - -#[cfg(any( - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f469", - feature = "stm32f479" -))] -exti!(gpiok, [ - EXTI0 => PK0, - EXTI1 => PK1, - EXTI2 => PK2, - EXTI3 => PK3, - EXTI4 => PK4, - EXTI9_5 => PK5, - EXTI9_5 => PK6, - EXTI9_5 => PK7, -]); - -#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] -exti!(gpioa, [ - EXTI0_1 => PA0, - EXTI0_1 => PA1, - EXTI2_3 => PA2, - EXTI2_3 => PA3, - EXTI4_15 => PA4, - EXTI4_15 => PA5, - EXTI4_15 => PA6, - EXTI4_15 => PA7, - EXTI4_15 => PA8, - EXTI4_15 => PA9, - EXTI4_15 => PA10, - EXTI4_15 => PA11, - EXTI4_15 => PA12, - EXTI4_15 => PA13, - EXTI4_15 => PA14, - EXTI4_15 => PA15, -]); - -#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] -exti!(gpiob, [ - EXTI0_1 => PB0, - EXTI0_1 => PB1, - EXTI2_3 => PB2, - EXTI2_3 => PB3, - EXTI4_15 => PB4, - EXTI4_15 => PB5, - EXTI4_15 => PB6, - EXTI4_15 => PB7, - EXTI4_15 => PB8, - EXTI4_15 => PB9, - EXTI4_15 => PB10, - EXTI4_15 => PB11, - EXTI4_15 => PB12, - EXTI4_15 => PB13, - EXTI4_15 => PB14, - EXTI4_15 => PB15, -]); - -#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] -exti!(gpioc, [ - EXTI0_1 => PC0, - EXTI0_1 => PC1, - EXTI2_3 => PC2, - EXTI2_3 => PC3, - EXTI4_15 => PC4, - EXTI4_15 => PC5, - EXTI4_15 => PC6, - EXTI4_15 => PC7, - EXTI4_15 => PC8, - EXTI4_15 => PC9, - EXTI4_15 => PC10, - EXTI4_15 => PC11, - EXTI4_15 => PC12, - EXTI4_15 => PC13, - EXTI4_15 => PC14, - EXTI4_15 => PC15, -]); - -#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] -exti!(gpiod, [ - EXTI0_1 => PD0, - EXTI0_1 => PD1, - EXTI2_3 => PD2, - EXTI2_3 => PD3, - EXTI4_15 => PD4, - EXTI4_15 => PD5, - EXTI4_15 => PD6, - EXTI4_15 => PD7, - EXTI4_15 => PD8, - EXTI4_15 => PD9, - EXTI4_15 => PD10, - EXTI4_15 => PD11, - EXTI4_15 => PD12, - EXTI4_15 => PD13, - EXTI4_15 => PD14, - EXTI4_15 => PD15, -]); - -#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] -exti!(gpioe, [ - EXTI0_1 => PE0, - EXTI0_1 => PE1, - EXTI2_3 => PE2, - EXTI2_3 => PE3, - EXTI4_15 => PE4, - EXTI4_15 => PE5, - EXTI4_15 => PE6, - EXTI4_15 => PE7, - EXTI4_15 => PE8, - EXTI4_15 => PE9, - EXTI4_15 => PE10, - EXTI4_15 => PE11, - EXTI4_15 => PE12, - EXTI4_15 => PE13, - EXTI4_15 => PE14, - EXTI4_15 => PE15, -]); - -#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] -exti!(gpioh, [ - EXTI0_1 => PH0, - EXTI0_1 => PH1, - EXTI4_15 => PH9, - EXTI4_15 => PH10, -]); diff --git a/embassy-stm32/src/f4/mod.rs b/embassy-stm32/src/f4/mod.rs deleted file mode 100644 index 9549b3ed6..000000000 --- a/embassy-stm32/src/f4/mod.rs +++ /dev/null @@ -1,4 +0,0 @@ -pub mod rtc; -pub mod serial; -pub mod spi; -pub mod system; diff --git a/embassy-stm32/src/f4/rtc.rs b/embassy-stm32/src/f4/rtc.rs deleted file mode 100644 index df7a82d87..000000000 --- a/embassy-stm32/src/f4/rtc.rs +++ /dev/null @@ -1,505 +0,0 @@ -use crate::hal::bb; -use crate::hal::rcc::Clocks; -use core::cell::Cell; -use core::convert::TryInto; -use core::sync::atomic::{compiler_fence, AtomicU32, Ordering}; -use critical_section::CriticalSection; -use embassy::interrupt::InterruptExt; -use embassy::time::{Clock, TICKS_PER_SECOND}; -use embassy::util::CriticalSectionMutex as Mutex; - -use crate::interrupt; -use crate::interrupt::Interrupt; - -// RTC timekeeping works with something we call "periods", which are time intervals -// of 2^15 ticks. The RTC counter value is 16 bits, so one "overflow cycle" is 2 periods. -// -// A `period` count is maintained in parallel to the RTC hardware `counter`, like this: -// - `period` and `counter` start at 0 -// - `period` is incremented on overflow (at counter value 0) -// - `period` is incremented "midway" between overflows (at counter value 0x8000) -// -// Therefore, when `period` is even, counter is in 0..0x7FFF. When odd, counter is in 0x8000..0xFFFF -// This allows for now() to return the correct value even if it races an overflow. -// -// To get `now()`, `period` is read first, then `counter` is read. If the counter value matches -// the expected range for the `period` parity, we're done. If it doesn't, this means that -// a new period start has raced us between reading `period` and `counter`, so we assume the `counter` value -// corresponds to the next period. -// -// `period` is a 32bit integer, so It overflows on 2^32 * 2^15 / 32768 seconds of uptime, which is 136 years. -fn calc_now(period: u32, counter: u16) -> u64 { - ((period as u64) << 15) + ((counter as u32 ^ ((period & 1) << 15)) as u64) -} - -struct AlarmState { - timestamp: Cell, - callback: Cell>, -} - -impl AlarmState { - fn new() -> Self { - Self { - timestamp: Cell::new(u64::MAX), - callback: Cell::new(None), - } - } -} - -// TODO: This is sometimes wasteful, try to find a better way -const ALARM_COUNT: usize = 3; - -/// RTC timer that can be used by the executor and to set alarms. -/// -/// It can work with Timers 2, 3, 4, 5, 9 and 12. Timers 9 and 12 only have one alarm available, -/// while the others have three each. -/// This timer works internally with a unit of 2^15 ticks, which means that if a call to -/// [`embassy::time::Clock::now`] is blocked for that amount of ticks the returned value will be -/// wrong (an old value). The current default tick rate is 32768 ticks per second. -pub struct RTC { - rtc: T, - irq: T::Interrupt, - - /// Number of 2^23 periods elapsed since boot. - period: AtomicU32, - - /// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled. - alarms: Mutex<[AlarmState; ALARM_COUNT]>, - - clocks: Clocks, -} - -impl RTC { - pub fn new(rtc: T, irq: T::Interrupt, clocks: Clocks) -> Self { - Self { - rtc, - irq, - period: AtomicU32::new(0), - alarms: Mutex::new([AlarmState::new(), AlarmState::new(), AlarmState::new()]), - clocks, - } - } - - pub fn start(&'static self) { - self.rtc.enable_clock(); - self.rtc.stop_and_reset(); - - let multiplier = if T::ppre(&self.clocks) == 1 { 1 } else { 2 }; - let freq = T::pclk(&self.clocks) * multiplier; - let psc = freq / TICKS_PER_SECOND as u32 - 1; - let psc: u16 = psc.try_into().unwrap(); - - self.rtc.set_psc_arr(psc, u16::MAX); - // Mid-way point - self.rtc.set_compare(0, 0x8000); - self.rtc.set_compare_interrupt(0, true); - - self.irq.set_handler(|ptr| unsafe { - let this = &*(ptr as *const () as *const Self); - this.on_interrupt(); - }); - self.irq.set_handler_context(self as *const _ as *mut _); - self.irq.unpend(); - self.irq.enable(); - - self.rtc.start(); - } - - fn on_interrupt(&self) { - if self.rtc.overflow_interrupt_status() { - self.rtc.overflow_clear_flag(); - self.next_period(); - } - - // Half overflow - if self.rtc.compare_interrupt_status(0) { - self.rtc.compare_clear_flag(0); - self.next_period(); - } - - for n in 1..=ALARM_COUNT { - if self.rtc.compare_interrupt_status(n) { - self.rtc.compare_clear_flag(n); - critical_section::with(|cs| self.trigger_alarm(n, cs)); - } - } - } - - fn next_period(&self) { - critical_section::with(|cs| { - let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; - let t = (period as u64) << 15; - - for n in 1..=ALARM_COUNT { - let alarm = &self.alarms.borrow(cs)[n - 1]; - let at = alarm.timestamp.get(); - - let diff = at - t; - if diff < 0xc000 { - self.rtc.set_compare(n, at as u16); - self.rtc.set_compare_interrupt(n, true); - } - } - }) - } - - fn trigger_alarm(&self, n: usize, cs: CriticalSection) { - self.rtc.set_compare_interrupt(n, false); - - let alarm = &self.alarms.borrow(cs)[n - 1]; - alarm.timestamp.set(u64::MAX); - - // Call after clearing alarm, so the callback can set another alarm. - if let Some((f, ctx)) = alarm.callback.get() { - f(ctx); - } - } - - fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) { - critical_section::with(|cs| { - let alarm = &self.alarms.borrow(cs)[n - 1]; - alarm.callback.set(Some((callback, ctx))); - }) - } - - fn set_alarm(&self, n: usize, timestamp: u64) { - critical_section::with(|cs| { - let alarm = &self.alarms.borrow(cs)[n - 1]; - alarm.timestamp.set(timestamp); - - let t = self.now(); - if timestamp <= t { - self.trigger_alarm(n, cs); - return; - } - - let diff = timestamp - t; - if diff < 0xc000 { - let safe_timestamp = timestamp.max(t + 3); - self.rtc.set_compare(n, safe_timestamp as u16); - self.rtc.set_compare_interrupt(n, true); - } else { - self.rtc.set_compare_interrupt(n, false); - } - }) - } - - pub fn alarm1(&'static self) -> Alarm { - Alarm { n: 1, rtc: self } - } - pub fn alarm2(&'static self) -> Option> { - if T::REAL_ALARM_COUNT >= 2 { - Some(Alarm { n: 2, rtc: self }) - } else { - None - } - } - pub fn alarm3(&'static self) -> Option> { - if T::REAL_ALARM_COUNT >= 3 { - Some(Alarm { n: 3, rtc: self }) - } else { - None - } - } -} - -impl embassy::time::Clock for RTC { - fn now(&self) -> u64 { - let period = self.period.load(Ordering::Relaxed); - compiler_fence(Ordering::Acquire); - let counter = self.rtc.counter(); - calc_now(period, counter) - } -} - -pub struct Alarm { - n: usize, - rtc: &'static RTC, -} - -impl embassy::time::Alarm for Alarm { - fn set_callback(&self, callback: fn(*mut ()), ctx: *mut ()) { - self.rtc.set_alarm_callback(self.n, callback, ctx); - } - - fn set(&self, timestamp: u64) { - self.rtc.set_alarm(self.n, timestamp); - } - - fn clear(&self) { - self.rtc.set_alarm(self.n, u64::MAX); - } -} - -mod sealed { - pub trait Sealed {} -} - -pub trait Instance: sealed::Sealed + Sized + 'static { - type Interrupt: Interrupt; - const REAL_ALARM_COUNT: usize; - - fn enable_clock(&self); - fn set_compare(&self, n: usize, value: u16); - fn set_compare_interrupt(&self, n: usize, enable: bool); - fn compare_interrupt_status(&self, n: usize) -> bool; - fn compare_clear_flag(&self, n: usize); - fn overflow_interrupt_status(&self) -> bool; - fn overflow_clear_flag(&self); - // This method should ensure that the values are really updated before returning - fn set_psc_arr(&self, psc: u16, arr: u16); - fn stop_and_reset(&self); - fn start(&self); - fn counter(&self) -> u16; - fn ppre(clocks: &Clocks) -> u8; - fn pclk(clocks: &Clocks) -> u32; -} - -#[allow(unused_macros)] -macro_rules! impl_timer { - ($module:ident: ($TYPE:ident, $INT:ident, $apbenr:ident, $enrbit:expr, $apbrstr:ident, $rstrbit:expr, $ppre:ident, $pclk: ident), 3) => { - mod $module { - use super::*; - use crate::hal::pac::{$TYPE, RCC}; - - impl sealed::Sealed for $TYPE {} - - impl Instance for $TYPE { - type Interrupt = interrupt::$INT; - const REAL_ALARM_COUNT: usize = 3; - - fn enable_clock(&self) { - // NOTE(unsafe) It will only be used for atomic operations - unsafe { - let rcc = &*RCC::ptr(); - - bb::set(&rcc.$apbenr, $enrbit); - bb::set(&rcc.$apbrstr, $rstrbit); - bb::clear(&rcc.$apbrstr, $rstrbit); - } - } - - fn set_compare(&self, n: usize, value: u16) { - // NOTE(unsafe) these registers accept all the range of u16 values - match n { - 0 => self.ccr1.write(|w| unsafe { w.bits(value.into()) }), - 1 => self.ccr2.write(|w| unsafe { w.bits(value.into()) }), - 2 => self.ccr3.write(|w| unsafe { w.bits(value.into()) }), - 3 => self.ccr4.write(|w| unsafe { w.bits(value.into()) }), - _ => {} - } - } - - fn set_compare_interrupt(&self, n: usize, enable: bool) { - if n > 3 { - return; - } - let bit = n as u8 + 1; - unsafe { - if enable { - bb::set(&self.dier, bit); - } else { - bb::clear(&self.dier, bit); - } - } - } - - fn compare_interrupt_status(&self, n: usize) -> bool { - let status = self.sr.read(); - match n { - 0 => status.cc1if().bit_is_set(), - 1 => status.cc2if().bit_is_set(), - 2 => status.cc3if().bit_is_set(), - 3 => status.cc4if().bit_is_set(), - _ => false, - } - } - - fn compare_clear_flag(&self, n: usize) { - if n > 3 { - return; - } - let bit = n as u8 + 1; - unsafe { - bb::clear(&self.sr, bit); - } - } - - fn overflow_interrupt_status(&self) -> bool { - self.sr.read().uif().bit_is_set() - } - - fn overflow_clear_flag(&self) { - unsafe { - bb::clear(&self.sr, 0); - } - } - - fn set_psc_arr(&self, psc: u16, arr: u16) { - // NOTE(unsafe) All u16 values are valid - self.psc.write(|w| unsafe { w.bits(psc.into()) }); - self.arr.write(|w| unsafe { w.bits(arr.into()) }); - - unsafe { - // Set URS, generate update, clear URS - bb::set(&self.cr1, 2); - self.egr.write(|w| w.ug().set_bit()); - bb::clear(&self.cr1, 2); - } - } - - fn stop_and_reset(&self) { - unsafe { - bb::clear(&self.cr1, 0); - } - self.cnt.reset(); - } - - fn start(&self) { - unsafe { bb::set(&self.cr1, 0) } - } - - fn counter(&self) -> u16 { - self.cnt.read().bits() as u16 - } - - fn ppre(clocks: &Clocks) -> u8 { - clocks.$ppre() - } - - fn pclk(clocks: &Clocks) -> u32 { - clocks.$pclk().0 - } - } - } - }; - - ($module:ident: ($TYPE:ident, $INT:ident, $apbenr:ident, $enrbit:expr, $apbrstr:ident, $rstrbit:expr, $ppre:ident, $pclk: ident), 1) => { - mod $module { - use super::*; - use crate::hal::pac::{$TYPE, RCC}; - - impl sealed::Sealed for $TYPE {} - - impl Instance for $TYPE { - type Interrupt = interrupt::$INT; - const REAL_ALARM_COUNT: usize = 1; - - fn enable_clock(&self) { - // NOTE(unsafe) It will only be used for atomic operations - unsafe { - let rcc = &*RCC::ptr(); - - bb::set(&rcc.$apbenr, $enrbit); - bb::set(&rcc.$apbrstr, $rstrbit); - bb::clear(&rcc.$apbrstr, $rstrbit); - } - } - - fn set_compare(&self, n: usize, value: u16) { - // NOTE(unsafe) these registers accept all the range of u16 values - match n { - 0 => self.ccr1.write(|w| unsafe { w.bits(value.into()) }), - 1 => self.ccr2.write(|w| unsafe { w.bits(value.into()) }), - _ => {} - } - } - - fn set_compare_interrupt(&self, n: usize, enable: bool) { - if n > 1 { - return; - } - let bit = n as u8 + 1; - unsafe { - if enable { - bb::set(&self.dier, bit); - } else { - bb::clear(&self.dier, bit); - } - } - } - - fn compare_interrupt_status(&self, n: usize) -> bool { - let status = self.sr.read(); - match n { - 0 => status.cc1if().bit_is_set(), - 1 => status.cc2if().bit_is_set(), - _ => false, - } - } - - fn compare_clear_flag(&self, n: usize) { - if n > 1 { - return; - } - let bit = n as u8 + 1; - unsafe { - bb::clear(&self.sr, bit); - } - } - - fn overflow_interrupt_status(&self) -> bool { - self.sr.read().uif().bit_is_set() - } - - fn overflow_clear_flag(&self) { - unsafe { - bb::clear(&self.sr, 0); - } - } - - fn set_psc_arr(&self, psc: u16, arr: u16) { - // NOTE(unsafe) All u16 values are valid - self.psc.write(|w| unsafe { w.bits(psc.into()) }); - self.arr.write(|w| unsafe { w.bits(arr.into()) }); - - unsafe { - // Set URS, generate update, clear URS - bb::set(&self.cr1, 2); - self.egr.write(|w| w.ug().set_bit()); - bb::clear(&self.cr1, 2); - } - } - - fn stop_and_reset(&self) { - unsafe { - bb::clear(&self.cr1, 0); - } - self.cnt.reset(); - } - - fn start(&self) { - unsafe { bb::set(&self.cr1, 0) } - } - - fn counter(&self) -> u16 { - self.cnt.read().bits() as u16 - } - - fn ppre(clocks: &Clocks) -> u8 { - clocks.$ppre() - } - - fn pclk(clocks: &Clocks) -> u32 { - clocks.$pclk().0 - } - } - } - }; -} - -#[cfg(not(feature = "stm32f410"))] -impl_timer!(tim2: (TIM2, TIM2, apb1enr, 0, apb1rstr, 0, ppre1, pclk1), 3); - -#[cfg(not(feature = "stm32f410"))] -impl_timer!(tim3: (TIM3, TIM3, apb1enr, 1, apb1rstr, 1, ppre1, pclk1), 3); - -#[cfg(not(feature = "stm32f410"))] -impl_timer!(tim4: (TIM4, TIM4, apb1enr, 2, apb1rstr, 2, ppre1, pclk1), 3); - -impl_timer!(tim5: (TIM5, TIM5, apb1enr, 3, apb1rstr, 3, ppre1, pclk1), 3); - -impl_timer!(tim9: (TIM9, TIM1_BRK_TIM9, apb2enr, 16, apb2rstr, 16, ppre2, pclk2), 1); - -#[cfg(not(any(feature = "stm32f401", feature = "stm32f410", feature = "stm32f411")))] -impl_timer!(tim12: (TIM12, TIM8_BRK_TIM12, apb1enr, 6, apb1rstr, 6, ppre1, pclk1), 1); diff --git a/embassy-stm32/src/f4/serial.rs b/embassy-stm32/src/f4/serial.rs deleted file mode 100644 index 78aaa8944..000000000 --- a/embassy-stm32/src/f4/serial.rs +++ /dev/null @@ -1,357 +0,0 @@ -//! Async Serial. - -use core::future::Future; -use core::marker::PhantomData; -use embassy::interrupt::Interrupt; -use embassy::traits::uart::{Error, Read, ReadUntilIdle, Write}; -use embassy::util::InterruptFuture; -use futures::{select_biased, FutureExt}; - -use crate::hal::{ - dma, - dma::config::DmaConfig, - dma::traits::{Channel, DMASet, PeriAddress, Stream}, - dma::{MemoryToPeripheral, PeripheralToMemory, Transfer}, - rcc::Clocks, - serial, - serial::config::{Config as SerialConfig, DmaConfig as SerialDmaConfig}, - serial::{Event as SerialEvent, Pins}, -}; -use crate::interrupt; -use crate::pac; - -/// Interface to the Serial peripheral -pub struct Serial< - USART: PeriAddress + WithInterrupt, - TSTREAM: Stream + WithInterrupt, - RSTREAM: Stream + WithInterrupt, - CHANNEL: Channel, -> { - tx_stream: Option, - rx_stream: Option, - usart: Option, - tx_int: TSTREAM::Interrupt, - rx_int: RSTREAM::Interrupt, - usart_int: USART::Interrupt, - channel: PhantomData, -} - -// static mut INSTANCE: *const Serial, Stream2> = ptr::null_mut(); - -impl Serial -where - USART: serial::Instance - + PeriAddress - + DMASet - + DMASet - + WithInterrupt, - TSTREAM: Stream + WithInterrupt, - RSTREAM: Stream + WithInterrupt, - CHANNEL: Channel, -{ - // Leaking futures is forbidden! - pub unsafe fn new( - usart: USART, - streams: (TSTREAM, RSTREAM), - pins: PINS, - tx_int: TSTREAM::Interrupt, - rx_int: RSTREAM::Interrupt, - usart_int: USART::Interrupt, - mut config: SerialConfig, - clocks: Clocks, - ) -> Self - where - PINS: Pins, - { - config.dma = SerialDmaConfig::TxRx; - - let (usart, _) = serial::Serial::new(usart, pins, config, clocks) - .unwrap() - .release(); - - let (tx_stream, rx_stream) = streams; - - Serial { - tx_stream: Some(tx_stream), - rx_stream: Some(rx_stream), - usart: Some(usart), - tx_int: tx_int, - rx_int: rx_int, - usart_int: usart_int, - channel: PhantomData, - } - } -} - -impl Read for Serial -where - USART: serial::Instance - + PeriAddress - + DMASet - + DMASet - + WithInterrupt - + 'static, - TSTREAM: Stream + WithInterrupt + 'static, - RSTREAM: Stream + WithInterrupt + 'static, - CHANNEL: Channel + 'static, -{ - type ReadFuture<'a> = impl Future> + 'a; - - /// Receives serial data. - /// - /// The future is pending until the buffer is completely filled. - fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { - let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) }; - - async move { - let rx_stream = self.rx_stream.take().unwrap(); - let usart = self.usart.take().unwrap(); - - let mut rx_transfer = Transfer::init( - rx_stream, - usart, - static_buf, - None, - DmaConfig::default() - .transfer_complete_interrupt(true) - .memory_increment(true) - .double_buffer(false), - ); - - let fut = InterruptFuture::new(&mut self.rx_int); - rx_transfer.start(|_usart| {}); - fut.await; - - let (rx_stream, usart, _, _) = rx_transfer.free(); - self.rx_stream.replace(rx_stream); - self.usart.replace(usart); - - Ok(()) - } - } -} - -impl Write for Serial -where - USART: serial::Instance - + PeriAddress - + DMASet - + DMASet - + WithInterrupt - + 'static, - TSTREAM: Stream + WithInterrupt + 'static, - RSTREAM: Stream + WithInterrupt + 'static, - CHANNEL: Channel + 'static, -{ - type WriteFuture<'a> = impl Future> + 'a; - - /// Sends serial data. - fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { - #[allow(mutable_transmutes)] - let static_buf = unsafe { core::mem::transmute::<&'a [u8], &'static mut [u8]>(buf) }; - - async move { - let tx_stream = self.tx_stream.take().unwrap(); - let usart = self.usart.take().unwrap(); - - let mut tx_transfer = Transfer::init( - tx_stream, - usart, - static_buf, - None, - DmaConfig::default() - .transfer_complete_interrupt(true) - .memory_increment(true) - .double_buffer(false), - ); - - let fut = InterruptFuture::new(&mut self.tx_int); - - tx_transfer.start(|_usart| {}); - fut.await; - - let (tx_stream, usart, _buf, _) = tx_transfer.free(); - - self.tx_stream.replace(tx_stream); - self.usart.replace(usart); - - Ok(()) - } - } -} - -impl ReadUntilIdle for Serial -where - USART: serial::Instance - + PeriAddress - + DMASet - + DMASet - + WithInterrupt - + 'static, - TSTREAM: Stream + WithInterrupt + 'static, - RSTREAM: Stream + WithInterrupt + 'static, - CHANNEL: Channel + 'static, -{ - type ReadUntilIdleFuture<'a> = impl Future> + 'a; - - /// Receives serial data. - /// - /// The future is pending until either the buffer is completely full, or the RX line falls idle after receiving some data. - /// - /// Returns the number of bytes read. - fn read_until_idle<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadUntilIdleFuture<'a> { - let static_buf = unsafe { core::mem::transmute::<&'a mut [u8], &'static mut [u8]>(buf) }; - - async move { - let rx_stream = self.rx_stream.take().unwrap(); - let usart = self.usart.take().unwrap(); - - unsafe { - /* __HAL_UART_ENABLE_IT(&uart->UartHandle, UART_IT_IDLE); */ - (*USART::ptr()).cr1.modify(|_, w| w.idleie().set_bit()); - - /* __HAL_UART_CLEAR_IDLEFLAG(&uart->UartHandle); */ - (*USART::ptr()).sr.read(); - (*USART::ptr()).dr.read(); - }; - - let mut rx_transfer = Transfer::init( - rx_stream, - usart, - static_buf, - None, - DmaConfig::default() - .transfer_complete_interrupt(true) - .memory_increment(true) - .double_buffer(false), - ); - - let total_bytes = RSTREAM::get_number_of_transfers() as usize; - - let fut = InterruptFuture::new(&mut self.rx_int); - let fut_idle = InterruptFuture::new(&mut self.usart_int); - - rx_transfer.start(|_usart| {}); - - futures::future::select(fut, fut_idle).await; - - let (rx_stream, usart, _, _) = rx_transfer.free(); - - let remaining_bytes = RSTREAM::get_number_of_transfers() as usize; - - unsafe { - (*USART::ptr()).cr1.modify(|_, w| w.idleie().clear_bit()); - } - self.rx_stream.replace(rx_stream); - self.usart.replace(usart); - - Ok(total_bytes - remaining_bytes) - } - } -} - -mod private { - pub trait Sealed {} -} - -pub trait WithInterrupt: private::Sealed { - type Interrupt: Interrupt; -} - -macro_rules! dma { - ($($PER:ident => ($dma:ident, $stream:ident),)+) => { - $( - impl private::Sealed for dma::$stream {} - impl WithInterrupt for dma::$stream { - type Interrupt = interrupt::$PER; - } - )+ - } - } - -macro_rules! usart { - ($($PER:ident => ($usart:ident),)+) => { - $( - impl private::Sealed for pac::$usart {} - impl WithInterrupt for pac::$usart { - type Interrupt = interrupt::$PER; - } - )+ - } -} - -dma! { - DMA2_STREAM0 => (DMA2, Stream0), - DMA2_STREAM1 => (DMA2, Stream1), - DMA2_STREAM2 => (DMA2, Stream2), - DMA2_STREAM3 => (DMA2, Stream3), - DMA2_STREAM4 => (DMA2, Stream4), - DMA2_STREAM5 => (DMA2, Stream5), - DMA2_STREAM6 => (DMA2, Stream6), - DMA2_STREAM7 => (DMA2, Stream7), - DMA1_STREAM0 => (DMA1, Stream0), - DMA1_STREAM1 => (DMA1, Stream1), - DMA1_STREAM2 => (DMA1, Stream2), - DMA1_STREAM3 => (DMA1, Stream3), - DMA1_STREAM4 => (DMA1, Stream4), - DMA1_STREAM5 => (DMA1, Stream5), - DMA1_STREAM6 => (DMA1, Stream6), -} - -#[cfg(any(feature = "stm32f401", feature = "stm32f410", feature = "stm32f411",))] -usart! { - USART1 => (USART1), - USART2 => (USART2), - USART6 => (USART6), -} - -#[cfg(any(feature = "stm32f405", feature = "stm32f407"))] -usart! { - USART1 => (USART1), - USART2 => (USART2), - USART3 => (USART3), - USART6 => (USART6), - - UART4 => (UART4), - UART5 => (UART5), -} - -#[cfg(feature = "stm32f412")] -usart! { - USART1 => (USART1), - USART2 => (USART2), - USART3 => (USART3), - USART6 => (USART6), -} - -#[cfg(feature = "stm32f413")] -usart! { - USART1 => (USART1), - USART2 => (USART2), - USART3 => (USART3), - USART6 => (USART6), - USART7 => (USART7), - USART8 => (USART8), - - UART5 => (UART5), - UART9 => (UART9), - UART10 => (UART10), -} - -#[cfg(any( - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f446", - feature = "stm32f469" -))] -usart! { - USART1 => (USART1), - USART2 => (USART2), - USART3 => (USART3), - USART6 => (USART6), - - UART4 => (UART4), - UART5 => (UART5), -// UART7 => (UART7), -// UART8 => (UART8), -} diff --git a/embassy-stm32/src/f4/spi.rs b/embassy-stm32/src/f4/spi.rs deleted file mode 100644 index d02c78106..000000000 --- a/embassy-stm32/src/f4/spi.rs +++ /dev/null @@ -1,492 +0,0 @@ -//! Async SPI - -use embassy::time; - -use core::{future::Future, marker::PhantomData, mem, ops::Deref, pin::Pin, ptr}; -use embassy::{interrupt::Interrupt, traits::spi::FullDuplex, util::InterruptFuture}; -use nb; - -pub use crate::hal::spi::{Mode, Phase, Polarity}; -use crate::hal::{ - bb, dma, - dma::config::DmaConfig, - dma::traits::{Channel, DMASet, PeriAddress, Stream}, - dma::{MemoryToPeripheral, PeripheralToMemory, Transfer}, - rcc::Clocks, - spi::Pins, - time::Hertz, -}; -use crate::interrupt; -use crate::pac; -use futures::future; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[cfg_attr(feature = "defmt", derive(defmt::Format))] -#[non_exhaustive] -pub enum Error { - TxBufferTooLong, - RxBufferTooLong, - Overrun, - ModeFault, - Crc, -} - -fn read_sr(spi: &T) -> nb::Result { - let sr = spi.sr.read(); - Err(if sr.ovr().bit_is_set() { - nb::Error::Other(Error::Overrun) - } else if sr.modf().bit_is_set() { - nb::Error::Other(Error::ModeFault) - } else if sr.crcerr().bit_is_set() { - nb::Error::Other(Error::Crc) - } else if sr.rxne().bit_is_set() { - // NOTE(read_volatile) read only 1 byte (the svd2rust API only allows - // reading a half-word) - return Ok(unsafe { ptr::read_volatile(&spi.dr as *const _ as *const u8) }); - } else { - nb::Error::WouldBlock - }) -} - -fn write_sr(spi: &T, byte: u8) -> nb::Result<(), Error> { - let sr = spi.sr.read(); - Err(if sr.ovr().bit_is_set() { - // Read from the DR to clear the OVR bit - let _ = spi.dr.read(); - nb::Error::Other(Error::Overrun) - } else if sr.modf().bit_is_set() { - // Write to CR1 to clear MODF - spi.cr1.modify(|_r, w| w); - nb::Error::Other(Error::ModeFault) - } else if sr.crcerr().bit_is_set() { - // Clear the CRCERR bit - spi.sr.modify(|_r, w| { - w.crcerr().clear_bit(); - w - }); - nb::Error::Other(Error::Crc) - } else if sr.txe().bit_is_set() { - // NOTE(write_volatile) see note above - unsafe { ptr::write_volatile(&spi.dr as *const _ as *mut u8, byte) } - return Ok(()); - } else { - nb::Error::WouldBlock - }) -} - -/// Interface to the Serial peripheral -pub struct Spi< - SPI: PeriAddress + WithInterrupt, - TSTREAM: Stream + WithInterrupt, - RSTREAM: Stream + WithInterrupt, - CHANNEL: Channel, -> { - tx_stream: Option, - rx_stream: Option, - spi: Option, - tx_int: TSTREAM::Interrupt, - rx_int: RSTREAM::Interrupt, - spi_int: SPI::Interrupt, - channel: PhantomData, -} - -impl Spi -where - SPI: Instance - + PeriAddress - + DMASet - + DMASet - + WithInterrupt, - TSTREAM: Stream + WithInterrupt, - RSTREAM: Stream + WithInterrupt, - CHANNEL: Channel, -{ - // Leaking futures is forbidden! - pub unsafe fn new( - spi: SPI, - streams: (TSTREAM, RSTREAM), - pins: PINS, - tx_int: TSTREAM::Interrupt, - rx_int: RSTREAM::Interrupt, - spi_int: SPI::Interrupt, - mode: Mode, - freq: Hertz, - clocks: Clocks, - ) -> Self - where - PINS: Pins, - { - let (tx_stream, rx_stream) = streams; - - // let spi1: crate::pac::SPI1 = unsafe { mem::transmute(()) }; - // let mut hspi = crate::hal::spi::Spi::spi1( - // spi1, - // ( - // crate::hal::spi::NoSck, - // crate::hal::spi::NoMiso, - // crate::hal::spi::NoMosi, - // ), - // mode, - // freq, - // clocks, - // ); - - unsafe { SPI::enable_clock() }; - - let clock = SPI::clock_speed(clocks); - - // disable SS output - // spi.cr2 - // .write(|w| w.ssoe().clear_bit().rxdmaen().set_bit().txdmaen().set_bit()); - spi.cr2.write(|w| w.ssoe().clear_bit()); - - let br = match clock.0 / freq.0 { - 0 => unreachable!(), - 1..=2 => 0b000, - 3..=5 => 0b001, - 6..=11 => 0b010, - 12..=23 => 0b011, - 24..=47 => 0b100, - 48..=95 => 0b101, - 96..=191 => 0b110, - _ => 0b111, - }; - - // mstr: master configuration - // lsbfirst: MSB first - // ssm: enable software slave management (NSS pin free for other uses) - // ssi: set nss high = master mode - // dff: 8 bit frames - // bidimode: 2-line unidirectional - // spe: enable the SPI bus - spi.cr1.write(|w| { - w.cpha() - .bit(mode.phase == Phase::CaptureOnSecondTransition) - .cpol() - .bit(mode.polarity == Polarity::IdleHigh) - .mstr() - .set_bit() - .br() - .bits(br) - .lsbfirst() - .clear_bit() - .ssm() - .set_bit() - .ssi() - .set_bit() - .rxonly() - .clear_bit() - .dff() - .clear_bit() - .bidimode() - .clear_bit() - .spe() - .set_bit() - }); - - Self { - tx_stream: Some(tx_stream), - rx_stream: Some(rx_stream), - spi: Some(spi), - tx_int: tx_int, - rx_int: rx_int, - spi_int: spi_int, - channel: PhantomData, - } - } -} - -impl FullDuplex for Spi -where - SPI: Instance - + PeriAddress - + DMASet - + DMASet - + WithInterrupt - + 'static, - TSTREAM: Stream + WithInterrupt + 'static, - RSTREAM: Stream + WithInterrupt + 'static, - CHANNEL: Channel + 'static, -{ - type Error = Error; - - type WriteFuture<'a> = impl Future> + 'a; - type ReadFuture<'a> = impl Future> + 'a; - type WriteReadFuture<'a> = impl Future> + 'a; - - fn read<'a>(&'a mut self, buf: &'a mut [u8]) -> Self::ReadFuture<'a> { - #[allow(mutable_transmutes)] - let static_buf: &'static mut [u8] = unsafe { mem::transmute(buf) }; - - async move { - let rx_stream = self.rx_stream.take().unwrap(); - let spi = self.spi.take().unwrap(); - - spi.cr2.modify(|_, w| w.errie().set_bit()); - - let mut rx_transfer = Transfer::init( - rx_stream, - spi, - static_buf, - None, - DmaConfig::default() - .transfer_complete_interrupt(true) - .memory_increment(true) - .double_buffer(false), - ); - - let fut = InterruptFuture::new(&mut self.rx_int); - let fut_err = InterruptFuture::new(&mut self.spi_int); - - rx_transfer.start(|_spi| {}); - future::select(fut, fut_err).await; - - let (rx_stream, spi, _buf, _) = rx_transfer.free(); - - spi.cr2.modify(|_, w| w.errie().clear_bit()); - self.rx_stream.replace(rx_stream); - self.spi.replace(spi); - - Ok(()) - } - } - - fn write<'a>(&'a mut self, buf: &'a [u8]) -> Self::WriteFuture<'a> { - #[allow(mutable_transmutes)] - let static_buf: &'static mut [u8] = unsafe { mem::transmute(buf) }; - - async move { - let tx_stream = self.tx_stream.take().unwrap(); - let spi = self.spi.take().unwrap(); - - spi.cr2 - .modify(|_, w| w.errie().set_bit().txeie().set_bit().rxneie().set_bit()); - - // let mut tx_transfer = Transfer::init( - // tx_stream, - // spi, - // static_buf, - // None, - // DmaConfig::default() - // .transfer_complete_interrupt(true) - // .memory_increment(true) - // .double_buffer(false), - // ); - // - // let fut = InterruptFuture::new(&mut self.tx_int); - // - // tx_transfer.start(|_spi| {}); - // fut.await; - - // let (tx_stream, spi, _buf, _) = tx_transfer.free(); - - for i in 0..(static_buf.len() - 1) { - let byte = static_buf[i]; - loop { - match write_sr(&spi, byte) { - Ok(()) => break, - _ => {} - } - InterruptFuture::new(&mut self.spi_int).await; - } - } - - spi.cr2.modify(|_, w| { - w.errie() - .clear_bit() - .txeie() - .clear_bit() - .rxneie() - .clear_bit() - }); - self.tx_stream.replace(tx_stream); - self.spi.replace(spi); - - Ok(()) - } - } - - fn read_write<'a>( - &'a mut self, - read_buf: &'a mut [u8], - write_buf: &'a [u8], - ) -> Self::WriteReadFuture<'a> { - #[allow(mutable_transmutes)] - let write_static_buf: &'static mut [u8] = unsafe { mem::transmute(write_buf) }; - let read_static_buf: &'static mut [u8] = unsafe { mem::transmute(read_buf) }; - - async move { - let tx_stream = self.tx_stream.take().unwrap(); - let rx_stream = self.rx_stream.take().unwrap(); - let spi_tx = self.spi.take().unwrap(); - let spi_rx: SPI = unsafe { mem::transmute_copy(&spi_tx) }; - - spi_rx - .cr2 - .modify(|_, w| w.errie().set_bit().txeie().set_bit().rxneie().set_bit()); - - // let mut tx_transfer = Transfer::init( - // tx_stream, - // spi_tx, - // write_static_buf, - // None, - // DmaConfig::default() - // .transfer_complete_interrupt(true) - // .memory_increment(true) - // .double_buffer(false), - // ); - // - // let mut rx_transfer = Transfer::init( - // rx_stream, - // spi_rx, - // read_static_buf, - // None, - // DmaConfig::default() - // .transfer_complete_interrupt(true) - // .memory_increment(true) - // .double_buffer(false), - // ); - // - // let tx_fut = InterruptFuture::new(&mut self.tx_int); - // let rx_fut = InterruptFuture::new(&mut self.rx_int); - // let rx_fut_err = InterruptFuture::new(&mut self.spi_int); - // - // rx_transfer.start(|_spi| {}); - // tx_transfer.start(|_spi| {}); - // - // time::Timer::after(time::Duration::from_millis(500)).await; - // - // // tx_fut.await; - // // future::select(rx_fut, rx_fut_err).await; - // - // let (rx_stream, spi_rx, _buf, _) = rx_transfer.free(); - // let (tx_stream, _, _buf, _) = tx_transfer.free(); - - for i in 0..(read_static_buf.len() - 1) { - let byte = write_static_buf[i]; - loop { - let fut = InterruptFuture::new(&mut self.spi_int); - match write_sr(&spi_tx, byte) { - Ok(()) => break, - _ => {} - } - fut.await; - } - - loop { - let fut = InterruptFuture::new(&mut self.spi_int); - match read_sr(&spi_tx) { - Ok(byte) => { - read_static_buf[i] = byte; - break; - } - _ => {} - } - fut.await; - } - } - - spi_rx.cr2.modify(|_, w| { - w.errie() - .clear_bit() - .txeie() - .clear_bit() - .rxneie() - .clear_bit() - }); - self.rx_stream.replace(rx_stream); - self.tx_stream.replace(tx_stream); - self.spi.replace(spi_rx); - - Ok(()) - } - } -} - -mod private { - pub trait Sealed {} -} - -pub trait WithInterrupt: private::Sealed { - type Interrupt: Interrupt; -} - -pub trait Instance: Deref + private::Sealed { - unsafe fn enable_clock(); - fn clock_speed(clocks: Clocks) -> Hertz; -} - -macro_rules! dma { - ($($PER:ident => ($dma:ident, $stream:ident),)+) => { - $( - impl private::Sealed for dma::$stream {} - impl WithInterrupt for dma::$stream { - type Interrupt = interrupt::$PER; - } - )+ - } - } - -macro_rules! spi { - ($($PER:ident => ($SPI:ident, $pclkX:ident, $apbXenr:ident, $en:expr),)+) => { - $( - impl private::Sealed for pac::$SPI {} - impl Instance for pac::$SPI { - unsafe fn enable_clock() { - const EN_BIT: u8 = $en; - // NOTE(unsafe) self reference will only be used for atomic writes with no side effects. - let rcc = &(*pac::RCC::ptr()); - // Enable clock. - bb::set(&rcc.$apbXenr, EN_BIT); - // Stall the pipeline to work around erratum 2.1.13 (DM00037591) - cortex_m::asm::dsb(); - } - - fn clock_speed(clocks: Clocks) -> Hertz { - clocks.$pclkX() - } - } - impl WithInterrupt for pac::$SPI { - type Interrupt = interrupt::$PER; - } - )+ - } -} - -dma! { - DMA2_STREAM0 => (DMA2, Stream0), - DMA2_STREAM1 => (DMA2, Stream1), - DMA2_STREAM2 => (DMA2, Stream2), - DMA2_STREAM3 => (DMA2, Stream3), - DMA2_STREAM4 => (DMA2, Stream4), - DMA2_STREAM5 => (DMA2, Stream5), - DMA2_STREAM6 => (DMA2, Stream6), - DMA2_STREAM7 => (DMA2, Stream7), - DMA1_STREAM0 => (DMA1, Stream0), - DMA1_STREAM1 => (DMA1, Stream1), - DMA1_STREAM2 => (DMA1, Stream2), - DMA1_STREAM3 => (DMA1, Stream3), - DMA1_STREAM4 => (DMA1, Stream4), - DMA1_STREAM5 => (DMA1, Stream5), - DMA1_STREAM6 => (DMA1, Stream6), -} - -#[cfg(any( - feature = "stm32f401", - feature = "stm32f410", - feature = "stm32f411", - feature = "stm32f446", -))] -spi! { - SPI1 => (SPI1, pclk2, apb2enr, 12), - SPI2 => (SPI2, pclk1, apb2enr, 14), -// SPI6 => (SPI6, pclk2, apb2enr, 21), - SPI4 => (SPI3, pclk2, apb2enr, 13), -// SPI5 => (SPI3, pclk2, apb2enr, 20), -} - -#[cfg(any(feature = "stm32f405", feature = "stm32f407"))] -spi! { - SPI1 => (SPI1, pclk2, apb2enr, 12), - SPI3 => (SPI3, pclk1, apb2enr, 15), -} diff --git a/embassy-stm32/src/f4/system.rs b/embassy-stm32/src/f4/system.rs deleted file mode 100644 index fb739272a..000000000 --- a/embassy-stm32/src/f4/system.rs +++ /dev/null @@ -1,61 +0,0 @@ -use crate::{hal::prelude::*, pac, Peripherals}; - -#[derive(Default)] -pub struct Config { - pub use_hse: Option, - pub sysclk: Option, - pub pclk1: Option, - pub require_pll48clk: bool, -} - -impl Config { - pub fn new() -> Self { - Default::default() - } - - pub fn use_hse(mut self, freq: u32) -> Self { - self.use_hse = Some(freq); - self - } - - pub fn sysclk(mut self, freq: u32) -> Self { - self.sysclk = Some(freq); - self - } - - pub fn pclk1(mut self, freq: u32) -> Self { - self.pclk1 = Some(freq); - self - } - - pub fn require_pll48clk(mut self) -> Self { - self.require_pll48clk = true; - self - } -} - -/// safety: must only call once. -pub unsafe fn configure(config: Config) { - let dp = pac::Peripherals::take().unwrap(); - let mut cfgr = dp.RCC.constrain().cfgr; - - if let Some(hz) = config.use_hse { - cfgr = cfgr.use_hse(hz.mhz()); - }; - - if let Some(hz) = config.sysclk { - cfgr = cfgr.sysclk(hz.mhz()); - }; - - if let Some(hz) = config.pclk1 { - cfgr = cfgr.pclk1(hz.mhz()); - }; - - if config.require_pll48clk { - cfgr = cfgr.require_pll48clk(); - }; - - let clocks = cfgr.freeze(); - - unsafe { Peripherals::set_peripherals(clocks) }; -} diff --git a/embassy-stm32/src/fmt.rs b/embassy-stm32/src/fmt.rs deleted file mode 100644 index 160642ccd..000000000 --- a/embassy-stm32/src/fmt.rs +++ /dev/null @@ -1,114 +0,0 @@ -#![macro_use] -#![allow(clippy::module_inception)] -#![allow(unused)] - -#[cfg(all(feature = "defmt", feature = "log"))] -compile_error!("You may not enable both `defmt` and `log` features."); - -pub use fmt::*; - -#[cfg(feature = "defmt")] -mod fmt { - pub use defmt::{ - assert, assert_eq, assert_ne, debug, debug_assert, debug_assert_eq, debug_assert_ne, error, - info, panic, todo, trace, unreachable, unwrap, warn, - }; -} - -#[cfg(feature = "log")] -mod fmt { - pub use core::{ - assert, assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, panic, todo, - unreachable, - }; - pub use log::{debug, error, info, trace, warn}; -} - -#[cfg(not(any(feature = "defmt", feature = "log")))] -mod fmt { - #![macro_use] - - pub use core::{ - assert, assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, panic, todo, - unreachable, - }; - - macro_rules! trace { - ($($msg:expr),+ $(,)?) => { - () - }; - } - - macro_rules! debug { - ($($msg:expr),+ $(,)?) => { - () - }; - } - - macro_rules! info { - ($($msg:expr),+ $(,)?) => { - () - }; - } - - macro_rules! warn { - ($($msg:expr),+ $(,)?) => { - () - }; - } - - macro_rules! error { - ($($msg:expr),+ $(,)?) => { - () - }; - } -} - -#[cfg(not(feature = "defmt"))] -macro_rules! unwrap { - ($arg:expr) => { - match $crate::fmt::Try::into_result($arg) { - ::core::result::Result::Ok(t) => t, - ::core::result::Result::Err(e) => { - ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); - } - } - }; - ($arg:expr, $($msg:expr),+ $(,)? ) => { - match $crate::fmt::Try::into_result($arg) { - ::core::result::Result::Ok(t) => t, - ::core::result::Result::Err(e) => { - ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); - } - } - } -} - -#[derive(Debug, Copy, Clone, Eq, PartialEq)] -pub struct NoneError; - -pub trait Try { - type Ok; - type Error; - fn into_result(self) -> Result; -} - -impl Try for Option { - type Ok = T; - type Error = NoneError; - - #[inline] - fn into_result(self) -> Result { - self.ok_or(NoneError) - } -} - -impl Try for Result { - type Ok = T; - type Error = E; - - #[inline] - fn into_result(self) -> Self { - self - } -} diff --git a/embassy-stm32/src/interrupt.rs b/embassy-stm32/src/interrupt.rs deleted file mode 100644 index 76dea28f6..000000000 --- a/embassy-stm32/src/interrupt.rs +++ /dev/null @@ -1,1042 +0,0 @@ -//! Interrupt management -//! -//! This module implements an API for managing interrupts compatible with -//! nrf_softdevice::interrupt. Intended for switching between the two at compile-time. - -// Re-exports -pub use embassy::interrupt::{declare, take, Interrupt}; -pub use embassy_extras::interrupt::Priority4 as Priority; - -#[cfg(feature = "stm32f401")] -mod irqs { - use super::*; - declare!(PVD); - declare!(TAMP_STAMP); - declare!(RTC_WKUP); - declare!(FLASH); - declare!(RCC); - declare!(EXTI0); - declare!(EXTI1); - declare!(EXTI2); - declare!(EXTI3); - declare!(EXTI4); - declare!(DMA1_STREAM0); - declare!(DMA1_STREAM1); - declare!(DMA1_STREAM2); - declare!(DMA1_STREAM3); - declare!(DMA1_STREAM4); - declare!(DMA1_STREAM5); - declare!(DMA1_STREAM6); - declare!(ADC); - declare!(EXTI9_5); - declare!(TIM1_BRK_TIM9); - declare!(TIM1_UP_TIM10); - declare!(TIM1_TRG_COM_TIM11); - declare!(TIM1_CC); - declare!(TIM2); - declare!(TIM3); - declare!(TIM4); - declare!(I2C1_EV); - declare!(I2C1_ER); - declare!(I2C2_EV); - declare!(I2C2_ER); - declare!(SPI1); - declare!(SPI2); - declare!(USART1); - declare!(USART2); - declare!(EXTI15_10); - declare!(RTC_ALARM); - declare!(OTG_FS_WKUP); - declare!(DMA1_STREAM7); - declare!(SDIO); - declare!(TIM5); - declare!(SPI3); - declare!(DMA2_STREAM0); - declare!(DMA2_STREAM1); - declare!(DMA2_STREAM2); - declare!(DMA2_STREAM3); - declare!(DMA2_STREAM4); - declare!(OTG_FS); - declare!(DMA2_STREAM5); - declare!(DMA2_STREAM6); - declare!(DMA2_STREAM7); - declare!(USART6); - declare!(I2C3_EV); - declare!(I2C3_ER); - declare!(FPU); - declare!(SPI4); -} - -#[cfg(feature = "stm32f405")] -mod irqs { - use super::*; - declare!(WWDG); - declare!(PVD); - declare!(TAMP_STAMP); - declare!(RTC_WKUP); - // declare!(FLASH); - declare!(RCC); - declare!(EXTI0); - declare!(EXTI1); - declare!(EXTI2); - declare!(EXTI3); - declare!(EXTI4); - declare!(DMA1_STREAM0); - declare!(DMA1_STREAM1); - declare!(DMA1_STREAM2); - declare!(DMA1_STREAM3); - declare!(DMA1_STREAM4); - declare!(DMA1_STREAM5); - declare!(DMA1_STREAM6); - declare!(ADC); - declare!(CAN1_TX); - declare!(CAN1_RX0); - declare!(CAN1_RX1); - declare!(CAN1_SCE); - declare!(EXTI9_5); - declare!(TIM1_BRK_TIM9); - declare!(TIM1_UP_TIM10); - declare!(TIM1_TRG_COM_TIM11); - declare!(TIM1_CC); - declare!(TIM2); - declare!(TIM3); - declare!(TIM4); - declare!(I2C1_EV); - declare!(I2C1_ER); - declare!(I2C2_EV); - declare!(I2C2_ER); - declare!(SPI1); - declare!(SPI2); - declare!(USART1); - declare!(USART2); - declare!(USART3); - declare!(EXTI15_10); - declare!(RTC_ALARM); - declare!(OTG_FS_WKUP); - declare!(TIM8_BRK_TIM12); - declare!(TIM8_UP_TIM13); - declare!(TIM8_TRG_COM_TIM14); - declare!(TIM8_CC); - declare!(DMA1_STREAM7); - // declare!(FMC); - declare!(SDIO); - declare!(TIM5); - declare!(SPI3); - declare!(UART4); - declare!(UART5); - declare!(TIM6_DAC); - declare!(TIM7); - declare!(DMA2_STREAM0); - declare!(DMA2_STREAM1); - declare!(DMA2_STREAM2); - declare!(DMA2_STREAM3); - declare!(DMA2_STREAM4); - declare!(ETH); - declare!(ETH_WKUP); - declare!(CAN2_TX); - declare!(CAN2_RX0); - declare!(CAN2_RX1); - declare!(CAN2_SCE); - declare!(OTG_FS); - declare!(DMA2_STREAM5); - declare!(DMA2_STREAM6); - declare!(DMA2_STREAM7); - declare!(USART6); - declare!(I2C3_EV); - declare!(I2C3_ER); - declare!(OTG_HS_EP1_OUT); - declare!(OTG_HS_EP1_IN); - declare!(OTG_HS_WKUP); - declare!(OTG_HS); - declare!(DCMI); - declare!(CRYP); - declare!(HASH_RNG); - declare!(FPU); - // declare!(UART7); - // declare!(UART8); - // declare!(SPI4); - // declare!(SPI5); - // declare!(SPI6); - // declare!(SAI1); - // declare!(LCD_TFT); - // declare!(LCD_TFT_1); - // declare!(DMA2D); -} - -#[cfg(feature = "stm32f407")] -mod irqs { - use super::*; - - declare!(WWDG); - declare!(PVD); - declare!(TAMP_STAMP); - declare!(RTC_WKUP); - declare!(RCC); - declare!(EXTI0); - declare!(EXTI1); - declare!(EXTI2); - declare!(EXTI3); - declare!(EXTI4); - declare!(DMA1_STREAM0); - declare!(DMA1_STREAM1); - declare!(DMA1_STREAM2); - declare!(DMA1_STREAM3); - declare!(DMA1_STREAM4); - declare!(DMA1_STREAM5); - declare!(DMA1_STREAM6); - declare!(ADC); - declare!(CAN1_TX); - declare!(CAN1_RX0); - declare!(CAN1_RX1); - declare!(CAN1_SCE); - declare!(EXTI9_5); - declare!(TIM1_BRK_TIM9); - declare!(TIM1_UP_TIM10); - declare!(TIM1_TRG_COM_TIM11); - declare!(TIM1_CC); - declare!(TIM2); - declare!(TIM3); - declare!(TIM4); - declare!(I2C1_EV); - declare!(I2C1_ER); - declare!(I2C2_EV); - declare!(I2C2_ER); - declare!(SPI1); - declare!(SPI2); - declare!(USART1); - declare!(USART2); - declare!(USART3); - declare!(EXTI15_10); - declare!(RTC_ALARM); - declare!(OTG_FS_WKUP); - declare!(TIM8_BRK_TIM12); - declare!(TIM8_UP_TIM13); - declare!(TIM8_TRG_COM_TIM14); - declare!(TIM8_CC); - declare!(DMA1_STREAM7); - declare!(FSMC); - declare!(SDIO); - declare!(TIM5); - declare!(SPI3); - declare!(UART4); - declare!(UART5); - declare!(TIM6_DAC); - declare!(TIM7); - declare!(DMA2_STREAM0); - declare!(DMA2_STREAM1); - declare!(DMA2_STREAM2); - declare!(DMA2_STREAM3); - declare!(DMA2_STREAM4); - declare!(ETH); - declare!(ETH_WKUP); - declare!(CAN2_TX); - declare!(CAN2_RX0); - declare!(CAN2_RX1); - declare!(CAN2_SCE); - declare!(OTG_FS); - declare!(DMA2_STREAM5); - declare!(DMA2_STREAM6); - declare!(DMA2_STREAM7); - declare!(USART6); - declare!(I2C3_EV); - declare!(I2C3_ER); - declare!(OTG_HS_EP1_OUT); - declare!(OTG_HS_EP1_IN); - declare!(OTG_HS_WKUP); - declare!(OTG_HS); - declare!(DCMI); - declare!(CRYP); - declare!(HASH_RNG); - declare!(FPU); - declare!(LCD_TFT); - declare!(LCD_TFT_1); -} - -#[cfg(feature = "stm32f410")] -mod irqs { - use super::*; - - declare!(WWDG); - declare!(PVD); - declare!(TAMP_STAMP); - declare!(RTC_WKUP); - declare!(FLASH); - declare!(RCC); - declare!(EXTI0); - declare!(EXTI1); - declare!(EXTI2); - declare!(EXTI3); - declare!(EXTI4); - declare!(DMA1_STREAM0); - declare!(DMA1_STREAM1); - declare!(DMA1_STREAM2); - declare!(DMA1_STREAM3); - declare!(DMA1_STREAM4); - declare!(DMA1_STREAM5); - declare!(DMA1_STREAM6); - declare!(ADC); - declare!(EXTI9_5); - declare!(TIM1_BRK_TIM9); - declare!(PWM1_UP); - declare!(TIM1_TRG_COM_TIM11); - declare!(TIM1_CC); - declare!(I2C1_EV); - declare!(I2C1_ER); - declare!(I2C2_EV); - declare!(I2C2_ER); - declare!(SPI1); - declare!(SPI2); - declare!(USART1); - declare!(USART2); - declare!(EXTI15_10); - declare!(RTC_ALARM); - declare!(DMA1_STREAM7); - declare!(TIM5); - declare!(TIM6_DAC1); - declare!(DMA2_STREAM0); - declare!(DMA2_STREAM1); - declare!(DMA2_STREAM2); - declare!(DMA2_STREAM3); - declare!(DMA2_STREAM4); - declare!(EXTI19); - declare!(DMA2_STREAM5); - declare!(DMA2_STREAM6); - declare!(DMA2_STREAM7); - declare!(USART6); - declare!(EXTI20); - declare!(RNG); - declare!(FPU); - declare!(SPI5); - declare!(I2C4_EV); - declare!(I2C4_ER); - declare!(LPTIM1); -} - -#[cfg(feature = "stm32f411")] -mod irqs { - use super::*; - - declare!(WWDG); - declare!(PVD); - declare!(TAMP_STAMP); - declare!(RTC_WKUP); - declare!(FLASH); - declare!(RCC); - declare!(EXTI0); - declare!(EXTI1); - declare!(EXTI2); - declare!(EXTI3); - declare!(EXTI4); - declare!(DMA1_STREAM0); - declare!(DMA1_STREAM1); - declare!(DMA1_STREAM2); - declare!(DMA1_STREAM3); - declare!(DMA1_STREAM4); - declare!(DMA1_STREAM5); - declare!(DMA1_STREAM6); - declare!(ADC); - declare!(EXTI9_5); - declare!(TIM1_BRK_TIM9); - declare!(TIM1_UP_TIM10); - declare!(TIM1_TRG_COM_TIM11); - declare!(TIM1_CC); - declare!(TIM2); - declare!(TIM3); - declare!(TIM4); - declare!(I2C1_EV); - declare!(I2C1_ER); - declare!(I2C2_EV); - declare!(I2C2_ER); - declare!(SPI1); - declare!(SPI2); - declare!(USART1); - declare!(USART2); - declare!(EXTI15_10); - declare!(RTC_ALARM); - declare!(OTG_FS_WKUP); - declare!(DMA1_STREAM7); - declare!(SDIO); - declare!(TIM5); - declare!(SPI3); - declare!(DMA2_STREAM0); - declare!(DMA2_STREAM1); - declare!(DMA2_STREAM2); - declare!(DMA2_STREAM3); - declare!(DMA2_STREAM4); - declare!(OTG_FS); - declare!(DMA2_STREAM5); - declare!(DMA2_STREAM6); - declare!(DMA2_STREAM7); - declare!(USART6); - declare!(I2C3_EV); - declare!(I2C3_ER); - declare!(FPU); - declare!(SPI4); - declare!(SPI5); -} - -#[cfg(feature = "stm32f412")] -mod irqs { - use super::*; - - declare!(WWDG); - declare!(PVD); - declare!(TAMP_STAMP); - declare!(RTC_WKUP); - declare!(FLASH); - declare!(RCC); - declare!(EXTI0); - declare!(EXTI1); - declare!(EXTI2); - declare!(EXTI3); - declare!(EXTI4); - declare!(DMA1_STREAM0); - declare!(DMA1_STREAM1); - declare!(DMA1_STREAM2); - declare!(DMA1_STREAM3); - declare!(DMA1_STREAM4); - declare!(DMA1_STREAM5); - declare!(DMA1_STREAM6); - declare!(ADC); - declare!(CAN1_TX); - declare!(CAN1_RX0); - declare!(CAN1_RX1); - declare!(CAN1_SCE); - declare!(EXTI9_5); - declare!(TIM1_BRK_TIM9); - declare!(TIM1_UP_TIM10); - declare!(TIM1_TRG_COM_TIM11); - declare!(TIM1_CC); - declare!(TIM2); - declare!(TIM3); - declare!(TIM4); - declare!(I2C1_EV); - declare!(I2C1_ER); - declare!(I2C2_EV); - declare!(I2C2_ER); - declare!(SPI1); - declare!(SPI2); - declare!(USART1); - declare!(USART2); - declare!(USART3); - declare!(EXTI15_10); - declare!(RTC_ALARM); - declare!(OTG_FS_WKUP); - declare!(TIM12); - declare!(TIM13); - declare!(TIM14); - declare!(TIM8_CC); - declare!(DMA1_STREAM7); - declare!(FSMC); - declare!(SDIO); - declare!(TIM5); - declare!(SPI3); - declare!(TIM6_DACUNDER); - declare!(TIM7); - declare!(DMA2_STREAM0); - declare!(DMA2_STREAM1); - declare!(DMA2_STREAM2); - declare!(DMA2_STREAM3); - declare!(DMA2_STREAM4); - declare!(DFSDM1_FLT0); - declare!(DFSDM1_FLT1); - declare!(CAN2_TX); - declare!(CAN2_RX0); - declare!(CAN2_RX1); - declare!(CAN2_SCE); - declare!(OTG_FS); - declare!(DMA2_STREAM5); - declare!(DMA2_STREAM6); - declare!(DMA2_STREAM7); - declare!(USART6); - declare!(I2C3_EV); - declare!(I2C3_ER); - declare!(HASH_RNG); - declare!(FPU); - declare!(SPI4); - declare!(SPI5); - declare!(QUAD_SPI); - declare!(I2CFMP1_EVENT); - declare!(I2CFMP1_ERROR); -} - -#[cfg(feature = "stm32f413")] -mod irqs { - use super::*; - - declare!(PVD); - declare!(TAMP_STAMP); - declare!(RTC_WKUP); - declare!(FLASH); - declare!(RCC); - declare!(EXTI0); - declare!(EXTI1); - declare!(EXTI2); - declare!(EXTI3); - declare!(EXTI4); - declare!(DMA1_STREAM0); - declare!(DMA1_STREAM1); - declare!(DMA1_STREAM2); - declare!(DMA1_STREAM3); - declare!(DMA1_STREAM4); - declare!(DMA1_STREAM5); - declare!(DMA1_STREAM6); - declare!(ADC); - declare!(CAN1_TX); - declare!(CAN1_RX0); - declare!(CAN1_RX1); - declare!(CAN1_SCE); - declare!(EXTI9_5); - declare!(TIM1_BRK_TIM9); - declare!(TIM1_UP_TIM10); - declare!(TIM1_TRG_COM_TIM11); - declare!(TIM1_CC); - declare!(TIM2); - declare!(TIM3); - declare!(TIM4); - declare!(I2C1_EVT); - declare!(I2C1_ERR); - declare!(I2C2_EVT); - declare!(I2C2_ERR); - declare!(SPI1); - declare!(SPI2); - declare!(USART1); - declare!(USART2); - declare!(USART3); - declare!(EXTI15_10); - declare!(EXTI17_RTC_ALARM); - declare!(TIM8_BRK_TIM12); - declare!(TIM8_UP_TIM13); - declare!(TIM8_TRG_COM_TIM14); - declare!(TIM8_CC); - declare!(DMA1_STREAM7); - declare!(FSMC); - declare!(SDIO); - declare!(TIM5); - declare!(SPI3); - declare!(USART4); - declare!(UART5); - declare!(TIM6_GLB_IT_DAC1_DAC2); - declare!(TIM7); - declare!(DMA2_STREAM0); - declare!(DMA2_STREAM1); - declare!(DMA2_STREAM2); - declare!(DMA2_STREAM3); - declare!(DMA2_STREAM4); - declare!(DFSDM1_FLT0); - declare!(DFSDM1_FLT1); - declare!(CAN2_TX); - declare!(CAN2_RX0); - declare!(CAN2_RX1); - declare!(CAN2_SCE); - declare!(OTG_FS); - declare!(DMA2_STREAM5); - declare!(DMA2_STREAM6); - declare!(DMA2_STREAM7); - declare!(USART6); - declare!(I2C3_EV); - declare!(I2C3_ER); - declare!(CAN3_TX); - declare!(CAN3_RX0); - declare!(CAN3_RX1); - declare!(CAN3_SCE); - declare!(CRYPTO); - declare!(RNG); - declare!(FPU); - declare!(USART7); - declare!(USART8); - declare!(SPI4); - declare!(SPI5); - declare!(SAI1); - declare!(UART9); - declare!(UART10); - declare!(QUADSPI); - declare!(I2CFMP1EVENT); - declare!(I2CFMP1ERROR); - declare!(LPTIM1_OR_IT_EIT_23); - declare!(DFSDM2_FILTER1); - declare!(DFSDM2_FILTER2); - declare!(DFSDM2_FILTER3); - declare!(DFSDM2_FILTER4); -} - -#[cfg(feature = "stm32f427")] -mod irqs { - use super::*; - - declare!(WWDG); - declare!(PVD); - declare!(TAMP_STAMP); - declare!(RTC_WKUP); - declare!(FLASH); - declare!(RCC); - declare!(EXTI0); - declare!(EXTI1); - declare!(EXTI2); - declare!(EXTI3); - declare!(EXTI4); - declare!(DMA1_STREAM0); - declare!(DMA1_STREAM1); - declare!(DMA1_STREAM2); - declare!(DMA1_STREAM3); - declare!(DMA1_STREAM4); - declare!(DMA1_STREAM5); - declare!(DMA1_STREAM6); - declare!(ADC); - declare!(CAN1_TX); - declare!(CAN1_RX0); - declare!(CAN1_RX1); - declare!(CAN1_SCE); - declare!(EXTI9_5); - declare!(TIM1_BRK_TIM9); - declare!(TIM1_UP_TIM10); - declare!(TIM1_TRG_COM_TIM11); - declare!(TIM1_CC); - declare!(TIM2); - declare!(TIM3); - declare!(TIM4); - declare!(I2C1_EV); - declare!(I2C1_ER); - declare!(I2C2_EV); - declare!(I2C2_ER); - declare!(SPI1); - declare!(SPI2); - declare!(USART1); - declare!(USART2); - declare!(USART3); - declare!(EXTI15_10); - declare!(RTC_ALARM); - declare!(OTG_FS_WKUP); - declare!(TIM8_BRK_TIM12); - declare!(TIM8_UP_TIM13); - declare!(TIM8_TRG_COM_TIM14); - declare!(TIM8_CC); - declare!(DMA1_STREAM7); - declare!(FMC); - declare!(SDIO); - declare!(TIM5); - declare!(SPI3); - declare!(UART4); - declare!(UART5); - declare!(TIM6_DAC); - declare!(TIM7); - declare!(DMA2_STREAM0); - declare!(DMA2_STREAM1); - declare!(DMA2_STREAM2); - declare!(DMA2_STREAM3); - declare!(DMA2_STREAM4); - declare!(ETH); - declare!(ETH_WKUP); - declare!(CAN2_TX); - declare!(CAN2_RX0); - declare!(CAN2_RX1); - declare!(CAN2_SCE); - declare!(OTG_FS); - declare!(DMA2_STREAM5); - declare!(DMA2_STREAM6); - declare!(DMA2_STREAM7); - declare!(USART6); - declare!(I2C3_EV); - declare!(I2C3_ER); - declare!(OTG_HS_EP1_OUT); - declare!(OTG_HS_EP1_IN); - declare!(OTG_HS_WKUP); - declare!(OTG_HS); - declare!(DCMI); - declare!(CRYP); - declare!(HASH_RNG); - declare!(FPU); - declare!(UART7); - declare!(UART8); - declare!(SPI4); - declare!(SPI5); - declare!(SPI6); - declare!(LCD_TFT); - declare!(LCD_TFT_1); -} - -#[cfg(feature = "stm32f429")] -mod irqs { - use super::*; - - declare!(WWDG); - declare!(PVD); - declare!(TAMP_STAMP); - declare!(RTC_WKUP); - declare!(FLASH); - declare!(RCC); - declare!(EXTI0); - declare!(EXTI1); - declare!(EXTI2); - declare!(EXTI3); - declare!(EXTI4); - declare!(DMA1_STREAM0); - declare!(DMA1_STREAM1); - declare!(DMA1_STREAM2); - declare!(DMA1_STREAM3); - declare!(DMA1_STREAM4); - declare!(DMA1_STREAM5); - declare!(DMA1_STREAM6); - declare!(ADC); - declare!(CAN1_TX); - declare!(CAN1_RX0); - declare!(CAN1_RX1); - declare!(CAN1_SCE); - declare!(EXTI9_5); - declare!(TIM1_BRK_TIM9); - declare!(TIM1_UP_TIM10); - declare!(TIM1_TRG_COM_TIM11); - declare!(TIM1_CC); - declare!(TIM2); - declare!(TIM3); - declare!(TIM4); - declare!(I2C1_EV); - declare!(I2C1_ER); - declare!(I2C2_EV); - declare!(I2C2_ER); - declare!(SPI1); - declare!(SPI2); - declare!(USART1); - declare!(USART2); - declare!(USART3); - declare!(EXTI15_10); - declare!(RTC_ALARM); - declare!(OTG_FS_WKUP); - declare!(TIM8_BRK_TIM12); - declare!(TIM8_UP_TIM13); - declare!(TIM8_TRG_COM_TIM14); - declare!(TIM8_CC); - declare!(DMA1_STREAM7); - declare!(FMC); - declare!(SDIO); - declare!(TIM5); - declare!(SPI3); - declare!(UART4); - declare!(UART5); - declare!(TIM6_DAC); - declare!(TIM7); - declare!(DMA2_STREAM0); - declare!(DMA2_STREAM1); - declare!(DMA2_STREAM2); - declare!(DMA2_STREAM3); - declare!(DMA2_STREAM4); - declare!(ETH); - declare!(ETH_WKUP); - declare!(CAN2_TX); - declare!(CAN2_RX0); - declare!(CAN2_RX1); - declare!(CAN2_SCE); - declare!(OTG_FS); - declare!(DMA2_STREAM5); - declare!(DMA2_STREAM6); - declare!(DMA2_STREAM7); - declare!(USART6); - declare!(I2C3_EV); - declare!(I2C3_ER); - declare!(OTG_HS_EP1_OUT); - declare!(OTG_HS_EP1_IN); - declare!(OTG_HS_WKUP); - declare!(OTG_HS); - declare!(DCMI); - declare!(CRYP); - declare!(HASH_RNG); - declare!(FPU); - declare!(UART7); - declare!(UART8); - declare!(SPI4); - declare!(SPI5); - declare!(SPI6); - declare!(SAI1); - declare!(LCD_TFT); - declare!(LCD_TFT_1); - declare!(DMA2D); -} - -#[cfg(feature = "stm32f446")] -mod irqs { - use super::*; - - declare!(WWDG); - declare!(TAMP_STAMP); - declare!(RTC_WKUP); - declare!(FLASH); - declare!(RCC); - declare!(EXTI0); - declare!(EXTI1); - declare!(EXTI2); - declare!(EXTI3); - declare!(EXTI4); - declare!(DMA1_STREAM0); - declare!(DMA1_STREAM1); - declare!(DMA1_STREAM2); - declare!(DMA1_STREAM3); - declare!(DMA1_STREAM4); - declare!(DMA1_STREAM5); - declare!(DMA1_STREAM6); - declare!(ADC); - declare!(CAN1_TX); - declare!(CAN1_RX0); - declare!(CAN1_RX1); - declare!(CAN1_SCE); - declare!(EXTI9_5); - declare!(TIM1_BRK_TIM9); - declare!(TIM1_UP_TIM10); - declare!(TIM1_TRG_COM_TIM11); - declare!(TIM1_CC); - declare!(TIM2); - declare!(TIM3); - declare!(TIM4); - declare!(I2C1_EV); - declare!(I2C1_ER); - declare!(I2C2_EV); - declare!(I2C2_ER); - declare!(SPI1); - declare!(SPI2); - declare!(USART1); - declare!(USART2); - declare!(USART3); - declare!(EXTI15_10); - declare!(RTC_ALARM); - declare!(OTG_FS_WKUP); - declare!(TIM8_BRK_TIM12); - declare!(TIM8_UP_TIM13); - declare!(TIM8_TRG_COM_TIM14); - declare!(TIM8_CC); - declare!(DMA1_STREAM7); - declare!(FMC); - // declare!(SDIO); - declare!(TIM5); - declare!(SPI3); - declare!(UART4); - declare!(UART5); - declare!(TIM6_DAC); - declare!(TIM7); - declare!(DMA2_STREAM0); - declare!(DMA2_STREAM1); - declare!(DMA2_STREAM2); - declare!(DMA2_STREAM3); - declare!(DMA2_STREAM4); - declare!(ETH); - declare!(ETH_WKUP); - declare!(CAN2_TX); - declare!(CAN2_RX0); - declare!(CAN2_RX1); - declare!(CAN2_SCE); - declare!(OTG_FS); - declare!(DMA2_STREAM5); - declare!(DMA2_STREAM6); - declare!(DMA2_STREAM7); - declare!(USART6); - declare!(I2C3_EV); - declare!(I2C3_ER); - declare!(DCMI); - declare!(FPU); - declare!(UART7); - declare!(UART8); - declare!(SPI4); - declare!(LCD_TFT); - declare!(LCD_TFT_1); -} - -#[cfg(feature = "stm32f469")] -mod irqs { - use super::*; - - declare!(WWDG); - declare!(PVD); - declare!(TAMP_STAMP); - declare!(RTC_WKUP); - declare!(FLASH); - declare!(RCC); - declare!(EXTI0); - declare!(EXTI1); - declare!(EXTI2); - declare!(EXTI3); - declare!(EXTI4); - declare!(DMA1_STREAM0); - declare!(DMA1_STREAM1); - declare!(DMA1_STREAM2); - declare!(DMA1_STREAM3); - declare!(DMA1_STREAM4); - declare!(DMA1_STREAM5); - declare!(DMA1_STREAM6); - declare!(ADC); - declare!(CAN1_TX); - declare!(CAN1_RX0); - declare!(CAN1_RX1); - declare!(CAN1_SCE); - declare!(EXTI9_5); - declare!(TIM1_BRK_TIM9); - declare!(TIM1_UP_TIM10); - declare!(TIM1_TRG_COM_TIM11); - declare!(TIM1_CC); - declare!(TIM2); - declare!(TIM3); - declare!(TIM4); - declare!(I2C1_EV); - declare!(I2C1_ER); - declare!(I2C2_EV); - declare!(I2C2_ER); - declare!(SPI1); - declare!(SPI2); - declare!(USART1); - declare!(USART2); - declare!(USART3); - declare!(EXTI15_10); - declare!(RTC_ALARM); - declare!(OTG_FS_WKUP); - declare!(TIM8_BRK_TIM12); - declare!(TIM8_UP_TIM13); - declare!(TIM8_TRG_COM_TIM14); - declare!(TIM8_CC); - declare!(DMA1_STREAM7); - declare!(FMC); - declare!(SDIO); - declare!(TIM5); - declare!(SPI3); - declare!(UART4); - declare!(UART5); - declare!(TIM6_DAC); - declare!(TIM7); - declare!(DMA2_STREAM0); - declare!(DMA2_STREAM1); - declare!(DMA2_STREAM2); - declare!(DMA2_STREAM3); - declare!(DMA2_STREAM4); - declare!(ETH); - declare!(ETH_WKUP); - declare!(CAN2_TX); - declare!(CAN2_RX0); - declare!(CAN2_RX1); - declare!(CAN2_SCE); - declare!(OTG_FS); - declare!(DMA2_STREAM5); - declare!(DMA2_STREAM6); - declare!(DMA2_STREAM7); - declare!(USART6); - declare!(I2C3_EV); - declare!(I2C3_ER); - declare!(OTG_HS_EP1_OUT); - declare!(OTG_HS_EP1_IN); - declare!(OTG_HS_WKUP); - declare!(OTG_HS); - declare!(DCMI); - declare!(CRYP); - declare!(HASH_RNG); - declare!(FPU); - declare!(UART7); - declare!(UART8); - declare!(SPI4); - declare!(SPI5); - declare!(SPI6); - declare!(SAI1); - declare!(LCD_TFT); - declare!(LCD_TFT_1); - declare!(DMA2D); - declare!(QUADSPI); - declare!(DSIHOST); -} - -#[cfg(feature = "stm32l0x1")] -mod irqs { - use super::*; - declare!(WWDG); - declare!(PVD); - declare!(RTC); - declare!(FLASH); - declare!(RCC); - declare!(EXTI0_1); - declare!(EXTI2_3); - declare!(EXTI4_15); - declare!(DMA1_CHANNEL1); - declare!(DMA1_CHANNEL2_3); - declare!(DMA1_CHANNEL4_7); - declare!(ADC_COMP); - declare!(LPTIM1); - declare!(USART4_USART5); - declare!(TIM2); - declare!(TIM3); - declare!(TIM6); - declare!(TIM7); - declare!(TIM21); - declare!(I2C3); - declare!(TIM22); - declare!(I2C1); - declare!(I2C2); - declare!(SPI1); - declare!(SPI2); - declare!(USART1); - declare!(USART2); - declare!(AES_RNG_LPUART1); -} - -#[cfg(feature = "stm32l0x2")] -mod irqs { - use super::*; - declare!(WWDG); - declare!(PVD); - declare!(RTC); - declare!(RCC); - declare!(EXTI0_1); - declare!(EXTI2_3); - declare!(EXTI4_15); - declare!(TSC); - declare!(DMA1_CHANNEL1); - declare!(DMA1_CHANNEL2_3); - declare!(DMA1_CHANNEL4_7); - declare!(ADC_COMP); - declare!(LPTIM1); - declare!(USART4_USART5); - declare!(TIM2); - declare!(TIM3); - declare!(TIM6_DAC); - declare!(TIM7); - declare!(TIM21); - declare!(I2C3); - declare!(TIM22); - declare!(I2C1); - declare!(I2C2); - declare!(SPI1); - declare!(SPI2); - declare!(USART1); - declare!(USART2); - declare!(AES_RNG_LPUART1); - declare!(USB); -} - -#[cfg(feature = "stm32l0x3")] -mod irqs { - use super::*; - declare!(WWDG); - declare!(PVD); - declare!(RTC); - declare!(RCC); - declare!(EXTI0_1); - declare!(EXTI2_3); - declare!(EXTI4_15); - declare!(TSC); - declare!(DMA1_CHANNEL1); - declare!(DMA1_CHANNEL2_3); - declare!(DMA1_CHANNEL4_7); - declare!(ADC_COMP); - declare!(LPTIM1); - declare!(USART4_USART5); - declare!(TIM2); - declare!(TIM3); - declare!(TIM6_DAC); - declare!(TIM7); - declare!(TIM21); - declare!(I2C3); - declare!(TIM22); - declare!(I2C1); - declare!(I2C2); - declare!(SPI1); - declare!(SPI2); - declare!(USART1); - declare!(USART2); - declare!(AES_RNG_LPUART1); - declare!(LCD); - declare!(USB); -} - -pub use irqs::*; diff --git a/embassy-stm32/src/l0/mod.rs b/embassy-stm32/src/l0/mod.rs deleted file mode 100644 index 53b44fe2d..000000000 --- a/embassy-stm32/src/l0/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod rtc; -pub mod system; diff --git a/embassy-stm32/src/l0/rtc.rs b/embassy-stm32/src/l0/rtc.rs deleted file mode 100644 index fa5011d3a..000000000 --- a/embassy-stm32/src/l0/rtc.rs +++ /dev/null @@ -1,372 +0,0 @@ -use crate::hal::rcc::Clocks; -use atomic_polyfill::{compiler_fence, AtomicU32, Ordering}; -use core::cell::Cell; -use core::convert::TryInto; -use critical_section::CriticalSection; -use embassy::interrupt::InterruptExt; -use embassy::time::{Clock, TICKS_PER_SECOND}; -use embassy::util::CriticalSectionMutex as Mutex; - -use crate::interrupt; -use crate::interrupt::Interrupt; - -// RTC timekeeping works with something we call "periods", which are time intervals -// of 2^15 ticks. The RTC counter value is 16 bits, so one "overflow cycle" is 2 periods. -// -// A `period` count is maintained in parallel to the RTC hardware `counter`, like this: -// - `period` and `counter` start at 0 -// - `period` is incremented on overflow (at counter value 0) -// - `period` is incremented "midway" between overflows (at counter value 0x8000) -// -// Therefore, when `period` is even, counter is in 0..0x7FFF. When odd, counter is in 0x8000..0xFFFF -// This allows for now() to return the correct value even if it races an overflow. -// -// To get `now()`, `period` is read first, then `counter` is read. If the counter value matches -// the expected range for the `period` parity, we're done. If it doesn't, this means that -// a new period start has raced us between reading `period` and `counter`, so we assume the `counter` value -// corresponds to the next period. -// -// `period` is a 32bit integer, so It overflows on 2^32 * 2^15 / 32768 seconds of uptime, which is 136 years. -fn calc_now(period: u32, counter: u16) -> u64 { - ((period as u64) << 15) + ((counter as u32 ^ ((period & 1) << 15)) as u64) -} - -struct AlarmState { - timestamp: Cell, - callback: Cell>, -} - -impl AlarmState { - fn new() -> Self { - Self { - timestamp: Cell::new(u64::MAX), - callback: Cell::new(None), - } - } -} - -// TODO: This is sometimes wasteful, try to find a better way -const ALARM_COUNT: usize = 3; - -/// RTC timer that can be used by the executor and to set alarms. -/// -/// It can work with Timers 2 and 3. - -/// This timer works internally with a unit of 2^15 ticks, which means that if a call to -/// [`embassy::time::Clock::now`] is blocked for that amount of ticks the returned value will be -/// wrong (an old value). The current default tick rate is 32768 ticks per second. -pub struct RTC { - rtc: T, - irq: T::Interrupt, - - /// Number of 2^23 periods elapsed since boot. - period: AtomicU32, - - /// Timestamp at which to fire alarm. u64::MAX if no alarm is scheduled. - alarms: Mutex<[AlarmState; ALARM_COUNT]>, - - clocks: Clocks, -} - -impl RTC { - pub fn new(rtc: T, irq: T::Interrupt, clocks: Clocks) -> Self { - Self { - rtc, - irq, - period: AtomicU32::new(0), - alarms: Mutex::new([AlarmState::new(), AlarmState::new(), AlarmState::new()]), - clocks, - } - } - - pub fn start(&'static self) { - self.rtc.enable_clock(); - self.rtc.stop_and_reset(); - - let freq = T::pclk(&self.clocks); - let psc = freq / TICKS_PER_SECOND as u32 - 1; - let psc: u16 = psc.try_into().unwrap(); - - self.rtc.set_psc_arr(psc, u16::MAX); - // Mid-way point - self.rtc.set_compare(0, 0x8000); - self.rtc.set_compare_interrupt(0, true); - - self.irq.set_handler(|ptr| unsafe { - let this = &*(ptr as *const () as *const Self); - this.on_interrupt(); - }); - self.irq.set_handler_context(self as *const _ as *mut _); - self.irq.unpend(); - self.irq.enable(); - - self.rtc.start(); - } - - fn on_interrupt(&self) { - if self.rtc.overflow_interrupt_status() { - self.rtc.overflow_clear_flag(); - self.next_period(); - } - - // Half overflow - if self.rtc.compare_interrupt_status(0) { - self.rtc.compare_clear_flag(0); - self.next_period(); - } - - for n in 1..=ALARM_COUNT { - if self.rtc.compare_interrupt_status(n) { - self.rtc.compare_clear_flag(n); - critical_section::with(|cs| self.trigger_alarm(n, cs)); - } - } - } - - fn next_period(&self) { - critical_section::with(|cs| { - let period = self.period.fetch_add(1, Ordering::Relaxed) + 1; - let t = (period as u64) << 15; - - for n in 1..=ALARM_COUNT { - let alarm = &self.alarms.borrow(cs)[n - 1]; - let at = alarm.timestamp.get(); - - let diff = at - t; - if diff < 0xc000 { - self.rtc.set_compare(n, at as u16); - self.rtc.set_compare_interrupt(n, true); - } - } - }) - } - - fn trigger_alarm(&self, n: usize, cs: CriticalSection) { - self.rtc.set_compare_interrupt(n, false); - - let alarm = &self.alarms.borrow(cs)[n - 1]; - alarm.timestamp.set(u64::MAX); - - // Call after clearing alarm, so the callback can set another alarm. - if let Some((f, ctx)) = alarm.callback.get() { - f(ctx); - } - } - - fn set_alarm_callback(&self, n: usize, callback: fn(*mut ()), ctx: *mut ()) { - critical_section::with(|cs| { - let alarm = &self.alarms.borrow(cs)[n - 1]; - alarm.callback.set(Some((callback, ctx))); - }) - } - - fn set_alarm(&self, n: usize, timestamp: u64) { - critical_section::with(|cs| { - let alarm = &self.alarms.borrow(cs)[n - 1]; - alarm.timestamp.set(timestamp); - - let t = self.now(); - if timestamp <= t { - self.trigger_alarm(n, cs); - return; - } - - let diff = timestamp - t; - if diff < 0xc000 { - let safe_timestamp = timestamp.max(t + 3); - self.rtc.set_compare(n, safe_timestamp as u16); - self.rtc.set_compare_interrupt(n, true); - } else { - self.rtc.set_compare_interrupt(n, false); - } - }); - } - - pub fn alarm1(&'static self) -> Alarm { - Alarm { n: 1, rtc: self } - } - pub fn alarm2(&'static self) -> Option> { - if T::REAL_ALARM_COUNT >= 2 { - Some(Alarm { n: 2, rtc: self }) - } else { - None - } - } - pub fn alarm3(&'static self) -> Option> { - if T::REAL_ALARM_COUNT >= 3 { - Some(Alarm { n: 3, rtc: self }) - } else { - None - } - } -} - -impl embassy::time::Clock for RTC { - fn now(&self) -> u64 { - let period = self.period.load(Ordering::Relaxed); - compiler_fence(Ordering::Acquire); - let counter = self.rtc.counter(); - calc_now(period, counter) - } -} - -pub struct Alarm { - n: usize, - rtc: &'static RTC, -} - -impl embassy::time::Alarm for Alarm { - fn set_callback(&self, callback: fn(*mut ()), ctx: *mut ()) { - self.rtc.set_alarm_callback(self.n, callback, ctx); - } - - fn set(&self, timestamp: u64) { - self.rtc.set_alarm(self.n, timestamp); - } - - fn clear(&self) { - self.rtc.set_alarm(self.n, u64::MAX); - } -} - -mod sealed { - pub trait Sealed {} -} - -pub trait Instance: sealed::Sealed + Sized + 'static { - type Interrupt: Interrupt; - const REAL_ALARM_COUNT: usize; - - fn enable_clock(&self); - fn set_compare(&self, n: usize, value: u16); - fn set_compare_interrupt(&self, n: usize, enable: bool); - fn compare_interrupt_status(&self, n: usize) -> bool; - fn compare_clear_flag(&self, n: usize); - fn overflow_interrupt_status(&self) -> bool; - fn overflow_clear_flag(&self); - // This method should ensure that the values are really updated before returning - fn set_psc_arr(&self, psc: u16, arr: u16); - fn stop_and_reset(&self); - fn start(&self); - fn counter(&self) -> u16; - fn pclk(clocks: &Clocks) -> u32; -} - -#[allow(unused_macros)] -macro_rules! impl_timer { - ($module:ident: ($TYPE:ident, $INT:ident, $timXen:ident, $timXrst:ident, $apbenr:ident, $apbrstr:ident, $pclk: ident)) => { - mod $module { - use super::*; - use crate::hal::pac::{$TYPE, RCC}; - - impl sealed::Sealed for $TYPE {} - - impl Instance for $TYPE { - type Interrupt = interrupt::$INT; - const REAL_ALARM_COUNT: usize = 3; - - fn enable_clock(&self) { - // NOTE(unsafe) It will only be used for atomic operations - unsafe { - let rcc = &*RCC::ptr(); - - rcc.$apbenr.modify(|_, w| w.$timXen().set_bit()); - rcc.$apbrstr.modify(|_, w| w.$timXrst().set_bit()); - rcc.$apbrstr.modify(|_, w| w.$timXrst().clear_bit()); - } - } - - fn set_compare(&self, n: usize, value: u16) { - // NOTE(unsafe) these registers accept all the range of u16 values - match n { - 0 => self.ccr1.write(|w| unsafe { w.bits(value.into()) }), - 1 => self.ccr2.write(|w| unsafe { w.bits(value.into()) }), - 2 => self.ccr3.write(|w| unsafe { w.bits(value.into()) }), - 3 => self.ccr4.write(|w| unsafe { w.bits(value.into()) }), - _ => {} - } - } - - fn set_compare_interrupt(&self, n: usize, enable: bool) { - if n > 3 { - return; - } - let bit = n as u8 + 1; - unsafe { - if enable { - self.dier.modify(|r, w| w.bits(r.bits() | (1 << bit))); - } else { - self.dier.modify(|r, w| w.bits(r.bits() & !(1 << bit))); - } - } - } - - fn compare_interrupt_status(&self, n: usize) -> bool { - let status = self.sr.read(); - match n { - 0 => status.cc1if().bit_is_set(), - 1 => status.cc2if().bit_is_set(), - 2 => status.cc3if().bit_is_set(), - 3 => status.cc4if().bit_is_set(), - _ => false, - } - } - - fn compare_clear_flag(&self, n: usize) { - if n > 3 { - return; - } - let bit = n as u8 + 1; - unsafe { - self.sr.modify(|r, w| w.bits(r.bits() & !(1 << bit))); - } - } - - fn overflow_interrupt_status(&self) -> bool { - self.sr.read().uif().bit_is_set() - } - - fn overflow_clear_flag(&self) { - unsafe { - self.sr.modify(|_, w| w.uif().clear_bit()); - } - } - - fn set_psc_arr(&self, psc: u16, arr: u16) { - // NOTE(unsafe) All u16 values are valid - self.psc.write(|w| unsafe { w.bits(psc.into()) }); - self.arr.write(|w| unsafe { w.bits(arr.into()) }); - - unsafe { - // Set URS, generate update, clear URS - self.cr1.modify(|_, w| w.urs().set_bit()); - self.egr.write(|w| w.ug().set_bit()); - self.cr1.modify(|_, w| w.urs().clear_bit()); - } - } - - fn stop_and_reset(&self) { - unsafe { - self.cr1.modify(|_, w| w.cen().clear_bit()); - } - self.cnt.reset(); - } - - fn start(&self) { - self.cr1.modify(|_, w| w.cen().set_bit()); - } - - fn counter(&self) -> u16 { - self.cnt.read().bits() as u16 - } - - fn pclk(clocks: &Clocks) -> u32 { - clocks.$pclk().0 - } - } - } - }; -} - -impl_timer!(tim2: (TIM2, TIM2, tim2en, tim2rst, apb1enr, apb1rstr, apb1_tim_clk)); -impl_timer!(tim3: (TIM3, TIM3, tim3en, tim3rst, apb1enr, apb1rstr, apb1_tim_clk)); diff --git a/embassy-stm32/src/l0/system.rs b/embassy-stm32/src/l0/system.rs deleted file mode 100644 index 00e417d4b..000000000 --- a/embassy-stm32/src/l0/system.rs +++ /dev/null @@ -1,17 +0,0 @@ -use crate::{hal, pac, Peripherals}; - -pub use hal::{ - prelude::*, - rcc::{Clocks, Config}, -}; - -/// safety: must only call once. -pub unsafe fn configure(config: Config) { - let dp = pac::Peripherals::take().unwrap(); - - let rcc = dp.RCC.freeze(config); - - let clocks = rcc.clocks; - - unsafe { Peripherals::set_peripherals(clocks) }; -} diff --git a/embassy-stm32/src/lib.rs b/embassy-stm32/src/lib.rs deleted file mode 100644 index 2fd9f1d3d..000000000 --- a/embassy-stm32/src/lib.rs +++ /dev/null @@ -1,478 +0,0 @@ -#![no_std] -#![feature(generic_associated_types)] -#![feature(asm)] -#![feature(min_type_alias_impl_trait)] -#![feature(impl_trait_in_bindings)] -#![feature(type_alias_impl_trait)] -#![allow(incomplete_features)] - -#[cfg(any( - feature = "stm32f401", - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f410", - feature = "stm32f411", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479", -))] -mod f4; - -#[cfg(any( - feature = "stm32f401", - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479", -))] -pub use {stm32f4xx_hal as hal, stm32f4xx_hal::stm32 as pac}; - -#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] -pub use {stm32l0xx_hal as hal, stm32l0xx_hal::pac}; - -#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] -mod l0; - -#[cfg(any(feature = "stm32l0x1", feature = "stm32l0x2", feature = "stm32l0x3",))] -pub use l0::{rtc, system}; - -pub mod fmt; - -pub mod exti; -pub mod interrupt; - -#[cfg(any( - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479", -))] -pub mod can; - -#[cfg(any( - feature = "stm32f401", - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479", -))] -pub use f4::{rtc, serial, spi, system}; - -#[cfg(any( - feature = "stm32f401", - feature = "stm32f405", - feature = "stm32f407", - feature = "stm32f410", - feature = "stm32f411", - feature = "stm32f412", - feature = "stm32f413", - feature = "stm32f415", - feature = "stm32f417", - feature = "stm32f423", - feature = "stm32f427", - feature = "stm32f429", - feature = "stm32f437", - feature = "stm32f439", - feature = "stm32f446", - feature = "stm32f469", - feature = "stm32f479", -))] -unsafe impl embassy_extras::usb::USBInterrupt for interrupt::OTG_FS {} - -use core::option::Option; -use hal::prelude::*; -use hal::rcc::Clocks; - -#[cfg(feature = "stm32f401")] -embassy_extras::std_peripherals! { - ADC_COMMON, - ADC1, - CRC, - DBGMCU, - EXTI, - FLASH, - IWDG, - OTG_FS_DEVICE, - OTG_FS_GLOBAL, - OTG_FS_HOST, - OTG_FS_PWRCLK, - PWR, - //RCC, - RTC, - SDIO, - SYSCFG, - TIM1, - TIM8, - TIM10, - TIM11, - TIM2, - //TIM3, - TIM4, - TIM5, - TIM9, - USART1, - USART2, - USART6, - WWDG, - DMA2, - DMA1, - GPIOH, - GPIOE, - GPIOD, - GPIOC, - GPIOB, - GPIOA, - I2C3, - I2C2, - I2C1, - I2S2EXT, - I2S3EXT, - SPI1, - SPI2, - SPI3, - SPI4, - FPU, - STK, - NVIC_STIR, - FPU_CPACR, - SCB_ACTRL, -} - -#[cfg(feature = "stm32f446")] -embassy_extras::std_peripherals! { - DCMI, - FMC, - DBGMCU, - DMA2, - DMA1, -// RCC, - GPIOH, - GPIOG, - GPIOF, - GPIOE, - GPIOD, - GPIOC, - GPIOB, - GPIOA, - SYSCFG, - SPI1, - SPI2, - SPI3, - SPI4, - ADC1, - ADC2, - ADC3, - USART6, - USART1, - USART2, - USART3, - DAC, - I2C3, - I2C2, - I2C1, - IWDG, - WWDG, - RTC, - UART4, - UART5, - ADC_COMMON, - TIM1, - TIM2, - TIM8, -// TIM3, - TIM4, - TIM5, - TIM9, - TIM12, - TIM10, - TIM13, - TIM14, - TIM11, - TIM6, - TIM7, - CRC, - OTG_FS_GLOBAL, - OTG_FS_HOST, - OTG_FS_DEVICE, - OTG_FS_PWRCLK, - CAN1, - CAN2, - FLASH, - EXTI, - OTG_HS_GLOBAL, - OTG_HS_HOST, - OTG_HS_DEVICE, - OTG_HS_PWRCLK, - SAI1, - SAI2, - PWR, - QUADSPI, - SPDIFRX, -// SDMMC, - HDMI_CEC, - FPU, - STK, - NVIC_STIR, - FPU_CPACR, - SCB_ACTRL, -} - -#[cfg(feature = "stm32f405")] -embassy_extras::std_peripherals! { - RNG, - DCMI, - FSMC, - DBGMCU, - DMA2, - DMA1, -// RCC, - GPIOI, - GPIOH, - GPIOG, - GPIOF, - GPIOE, - GPIOD, - GPIOC, - GPIOJ, - GPIOK, - GPIOB, - GPIOA, - SYSCFG, - SPI1, - SPI2, - SPI3, - I2S2EXT, - I2S3EXT, - SPI4, - SPI5, - SPI6, - SDIO, - ADC1, - ADC2, - ADC3, - USART6, - USART1, - USART2, - USART3, - DAC, - PWR, - I2C3, - I2C2, - I2C1, - IWDG, - WWDG, - RTC, - UART4, - UART5, - UART7, - UART8, - ADC_COMMON, - TIM1, - TIM8, - TIM2, -// TIM3, - TIM4, - TIM5, - TIM9, - TIM12, - TIM10, - TIM13, - TIM14, - TIM11, - TIM6, - TIM7, - ETHERNET_MAC, - ETHERNET_MMC, - ETHERNET_PTP, - ETHERNET_DMA, - CRC, - OTG_FS_GLOBAL, - OTG_FS_HOST, - OTG_FS_DEVICE, - OTG_FS_PWRCLK, - CAN1, - CAN2, - FLASH, - EXTI, - OTG_HS_GLOBAL, - OTG_HS_HOST, - OTG_HS_DEVICE, - OTG_HS_PWRCLK, - SAI1, - LTDC, - HASH, - CRYP, - FPU, - STK, - NVIC_STIR, - FPU_CPACR, - SCB_ACTRL, -} - -#[cfg(feature = "stm32f407")] -embassy_extras::std_peripherals! { - RNG, - DCMI, - FSMC, - DBGMCU, - DMA2, - DMA1, -// RCC, - GPIOI, - GPIOH, - GPIOG, - GPIOF, - GPIOE, - GPIOD, - GPIOC, - GPIOJ, - GPIOK, - GPIOB, - GPIOA, - SYSCFG, - SPI1, - SPI2, - SPI3, - I2S2EXT, - I2S3EXT, - SPI4, - SPI5, - SPI6, - SDIO, - ADC1, - ADC2, - ADC3, - USART6, - USART1, - USART2, - USART3, - DAC, - PWR, - I2C3, - I2C2, - I2C1, - IWDG, - WWDG, - RTC, - UART4, - UART5, - UART7, - UART8, - ADC_COMMON, - TIM1, - TIM8, - TIM2, -// TIM3, - TIM4, - TIM5, - TIM9, - TIM12, - TIM10, - TIM13, - TIM14, - TIM11, - TIM6, - TIM7, - ETHERNET_MAC, - ETHERNET_MMC, - ETHERNET_PTP, - ETHERNET_DMA, - CRC, - OTG_FS_GLOBAL, - OTG_FS_HOST, - OTG_FS_DEVICE, - OTG_FS_PWRCLK, - CAN1, - CAN2, - FLASH, - EXTI, - OTG_HS_GLOBAL, - OTG_HS_HOST, - OTG_HS_DEVICE, - OTG_HS_PWRCLK, - SAI1, - LTDC, - HASH, - CRYP, - FPU, - STK, - NVIC_STIR, - FPU_CPACR, - SCB_ACTRL, -} - -#[cfg(feature = "stm32l0x2")] -embassy_extras::std_peripherals! { - SPI1, - SPI2, - USART1, - USART2, - USART4, - USART5, - I2C1, - I2C2, - I2C3, - RNG, - TIM2, - TIM3, - TIM6, - TIM7, - TIM21, - TIM22, - DAC, - RTC, - PWR, - CRC, - GPIOA, - GPIOB, - GPIOC, - GPIOD, - GPIOE, - GPIOH, - SYSCFG, - DMA1, - EXTI, - ADC, - IWDG, - WWDG, - DBG, -} From 0310e4d458b86df31f1765104eb3aa9a6ee09bfc Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 12 May 2021 01:57:01 +0200 Subject: [PATCH 06/10] Add `init` fn. Initializes hw and returns Peripherals. --- embassy-extras/src/macros.rs | 13 +-- embassy-macros/src/chip/nrf.rs | 2 +- embassy-macros/src/chip/rp.rs | 2 +- embassy-macros/src/lib.rs | 6 +- embassy-nrf-examples/src/bin/blinky.rs | 3 +- embassy-nrf-examples/src/bin/buffered_uart.rs | 4 +- .../src/bin/executor_fairness_test.rs | 4 +- .../src/bin/gpiote_channel.rs | 6 +- embassy-nrf-examples/src/bin/gpiote_port.rs | 4 +- embassy-nrf-examples/src/bin/multiprio.rs | 3 +- embassy-nrf-examples/src/bin/ppi.rs | 4 +- embassy-nrf-examples/src/bin/qspi.rs | 4 +- embassy-nrf-examples/src/bin/raw_spawn.rs | 3 +- embassy-nrf-examples/src/bin/spim.rs | 4 +- embassy-nrf-examples/src/bin/timer.rs | 3 +- embassy-nrf-examples/src/bin/uart.rs | 32 +----- embassy-nrf-examples/src/bin/uart_idle.rs | 4 +- embassy-nrf/src/lib.rs | 86 ++++++++++++++- embassy-nrf/src/system.rs | 79 -------------- embassy-rp-examples/src/bin/blinky.rs | 4 +- embassy-rp-examples/src/bin/button.rs | 4 +- embassy-rp-examples/src/bin/uart.rs | 4 +- embassy-rp/src/lib.rs | 103 +++++++++++++++++- embassy-rp/src/system.rs | 94 ---------------- 24 files changed, 217 insertions(+), 258 deletions(-) delete mode 100644 embassy-nrf/src/system.rs delete mode 100644 embassy-rp/src/system.rs diff --git a/embassy-extras/src/macros.rs b/embassy-extras/src/macros.rs index 860c0795a..fba752619 100644 --- a/embassy-extras/src/macros.rs +++ b/embassy-extras/src/macros.rs @@ -46,18 +46,17 @@ macro_rules! peripherals { impl Peripherals { ///Returns all the peripherals *once* #[inline] - pub fn take() -> Option { + pub(crate) fn take() -> Self { #[no_mangle] static mut _EMBASSY_DEVICE_PERIPHERALS: bool = false; - critical_section::with(|_| { - if unsafe { _EMBASSY_DEVICE_PERIPHERALS } { - None - } else { - unsafe { _EMBASSY_DEVICE_PERIPHERALS = true }; - Some(unsafe { ::steal() }) + critical_section::with(|_| unsafe { + if _EMBASSY_DEVICE_PERIPHERALS { + panic!("init called more than once!") } + _EMBASSY_DEVICE_PERIPHERALS = true; + ::steal() }) } } diff --git a/embassy-macros/src/chip/nrf.rs b/embassy-macros/src/chip/nrf.rs index aba4c004f..503a8ba5a 100644 --- a/embassy-macros/src/chip/nrf.rs +++ b/embassy-macros/src/chip/nrf.rs @@ -9,7 +9,7 @@ pub fn generate(embassy_prefix: &ModulePrefix, config: syn::Expr) -> TokenStream quote!( use #embassy_nrf_path::{interrupt, peripherals, rtc}; - unsafe { #embassy_nrf_path::system::configure(#config) }; + let p = #embassy_nrf_path::init(#config); let mut rtc = rtc::RTC::new(unsafe { ::steal() }, interrupt::take!(RTC1)); let rtc = unsafe { make_static(&mut rtc) }; diff --git a/embassy-macros/src/chip/rp.rs b/embassy-macros/src/chip/rp.rs index 33863de86..04211f8f3 100644 --- a/embassy-macros/src/chip/rp.rs +++ b/embassy-macros/src/chip/rp.rs @@ -7,6 +7,6 @@ pub fn generate(embassy_prefix: &ModulePrefix, config: syn::Expr) -> TokenStream quote!( use #embassy_rp_path::{interrupt, peripherals}; - unsafe { #embassy_rp_path::system::configure(#config) }; + let p = #embassy_rp_path::init(#config); ) } diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs index d91549ca7..dc234cd6d 100644 --- a/embassy-macros/src/lib.rs +++ b/embassy-macros/src/lib.rs @@ -315,12 +315,12 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream { let args = task_fn.sig.inputs.clone(); - if args.len() != 1 { + if args.len() != 2 { task_fn .sig .span() .unwrap() - .error("main function must have one argument") + .error("main function must have 2 arguments") .emit(); fail = true; } @@ -364,7 +364,7 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream { #chip_setup executor.run(|spawner| { - spawner.spawn(__embassy_main(spawner)).unwrap(); + spawner.spawn(__embassy_main(spawner, p)).unwrap(); }) } diff --git a/embassy-nrf-examples/src/bin/blinky.rs b/embassy-nrf-examples/src/bin/blinky.rs index 4cb09bee7..e6fc854b5 100644 --- a/embassy-nrf-examples/src/bin/blinky.rs +++ b/embassy-nrf-examples/src/bin/blinky.rs @@ -17,8 +17,7 @@ use embassy_nrf::Peripherals; use embedded_hal::digital::v2::OutputPin; #[embassy::main] -async fn main(spawner: Spawner) { - let p = Peripherals::take().unwrap(); +async fn main(spawner: Spawner, p: Peripherals) { let mut led = Output::new(p.P0_13, Level::Low, OutputDrive::Standard); loop { diff --git a/embassy-nrf-examples/src/bin/buffered_uart.rs b/embassy-nrf-examples/src/bin/buffered_uart.rs index 8f5d9fb2e..b3a621c6b 100644 --- a/embassy-nrf-examples/src/bin/buffered_uart.rs +++ b/embassy-nrf-examples/src/bin/buffered_uart.rs @@ -17,9 +17,7 @@ use example_common::*; use futures::pin_mut; #[embassy::main] -async fn main(spawner: Spawner) { - let p = Peripherals::take().unwrap(); - +async fn main(spawner: Spawner, p: Peripherals) { let mut config = uarte::Config::default(); config.parity = uarte::Parity::EXCLUDED; config.baudrate = uarte::Baudrate::BAUD115200; diff --git a/embassy-nrf-examples/src/bin/executor_fairness_test.rs b/embassy-nrf-examples/src/bin/executor_fairness_test.rs index 3ea74316e..ca9bcc1e6 100644 --- a/embassy-nrf-examples/src/bin/executor_fairness_test.rs +++ b/embassy-nrf-examples/src/bin/executor_fairness_test.rs @@ -13,7 +13,7 @@ use core::task::Poll; use defmt::panic; use embassy::executor::Spawner; use embassy::time::{Duration, Instant, Timer}; -use embassy_nrf::interrupt; +use embassy_nrf::{interrupt, Peripherals}; #[embassy::task] async fn run1() { @@ -40,7 +40,7 @@ async fn run3() { } #[embassy::main] -async fn main(spawner: Spawner) { +async fn main(spawner: Spawner, p: Peripherals) { unwrap!(spawner.spawn(run1())); unwrap!(spawner.spawn(run2())); unwrap!(spawner.spawn(run3())); diff --git a/embassy-nrf-examples/src/bin/gpiote_channel.rs b/embassy-nrf-examples/src/bin/gpiote_channel.rs index ee670acd5..d52ed7767 100644 --- a/embassy-nrf-examples/src/bin/gpiote_channel.rs +++ b/embassy-nrf-examples/src/bin/gpiote_channel.rs @@ -12,13 +12,11 @@ use example_common::*; use defmt::panic; use embassy::executor::Spawner; use embassy_nrf::gpio::{Input, Pull}; -use embassy_nrf::gpiote::{self, InputChannel, InputChannelPolarity}; +use embassy_nrf::gpiote::{InputChannel, InputChannelPolarity}; use embassy_nrf::{interrupt, Peripherals}; #[embassy::main] -async fn main(spawner: Spawner) { - let p = Peripherals::take().unwrap(); - +async fn main(spawner: Spawner, p: Peripherals) { info!("Starting!"); let ch1 = InputChannel::new( diff --git a/embassy-nrf-examples/src/bin/gpiote_port.rs b/embassy-nrf-examples/src/bin/gpiote_port.rs index 717d3398b..4a7951cd3 100644 --- a/embassy-nrf-examples/src/bin/gpiote_port.rs +++ b/embassy-nrf-examples/src/bin/gpiote_port.rs @@ -28,9 +28,7 @@ async fn button_task(n: usize, mut pin: PortInput<'static, AnyPin>) { } #[embassy::main] -async fn main(spawner: Spawner) { - let p = Peripherals::take().unwrap(); - +async fn main(spawner: Spawner, p: Peripherals) { info!("Starting!"); let btn1 = PortInput::new(Input::new(p.P0_11.degrade(), Pull::Up)); diff --git a/embassy-nrf-examples/src/bin/multiprio.rs b/embassy-nrf-examples/src/bin/multiprio.rs index 9ed5c1368..79fa029b3 100644 --- a/embassy-nrf-examples/src/bin/multiprio.rs +++ b/embassy-nrf-examples/src/bin/multiprio.rs @@ -126,9 +126,8 @@ static EXECUTOR_LOW: Forever = Forever::new(); fn main() -> ! { info!("Hello World!"); - let p = unwrap!(embassy_nrf::Peripherals::take()); + let p = embassy_nrf::init(Default::default()); - unsafe { embassy_nrf::system::configure(Default::default()) }; let rtc = RTC.put(rtc::RTC::new(p.RTC1, interrupt::take!(RTC1))); rtc.start(); unsafe { embassy::time::set_clock(rtc) }; diff --git a/embassy-nrf-examples/src/bin/ppi.rs b/embassy-nrf-examples/src/bin/ppi.rs index 3c39e032e..47782ed29 100644 --- a/embassy-nrf-examples/src/bin/ppi.rs +++ b/embassy-nrf-examples/src/bin/ppi.rs @@ -19,9 +19,7 @@ use embassy_nrf::{interrupt, Peripherals}; use gpiote::{OutputChannel, OutputChannelPolarity}; #[embassy::main] -async fn main(spawner: Spawner) { - let p = Peripherals::take().unwrap(); - +async fn main(spawner: Spawner, p: Peripherals) { info!("Starting!"); let button1 = InputChannel::new( diff --git a/embassy-nrf-examples/src/bin/qspi.rs b/embassy-nrf-examples/src/bin/qspi.rs index 28cde6e51..3dc027f6f 100644 --- a/embassy-nrf-examples/src/bin/qspi.rs +++ b/embassy-nrf-examples/src/bin/qspi.rs @@ -23,9 +23,7 @@ const PAGE_SIZE: usize = 4096; struct AlignedBuf([u8; 4096]); #[embassy::main] -async fn main(spawner: Spawner) { - let p = Peripherals::take().unwrap(); - +async fn main(spawner: Spawner, p: Peripherals) { let csn = p.P0_17; let sck = p.P0_19; let io0 = p.P0_20; diff --git a/embassy-nrf-examples/src/bin/raw_spawn.rs b/embassy-nrf-examples/src/bin/raw_spawn.rs index f8e021d9b..78de7b100 100644 --- a/embassy-nrf-examples/src/bin/raw_spawn.rs +++ b/embassy-nrf-examples/src/bin/raw_spawn.rs @@ -37,9 +37,8 @@ static EXECUTOR: Forever = Forever::new(); fn main() -> ! { info!("Hello World!"); - let p = unwrap!(embassy_nrf::Peripherals::take()); + let p = embassy_nrf::init(Default::default()); - unsafe { embassy_nrf::system::configure(Default::default()) }; let rtc = RTC.put(rtc::RTC::new(p.RTC1, interrupt::take!(RTC1))); rtc.start(); unsafe { embassy::time::set_clock(rtc) }; diff --git a/embassy-nrf-examples/src/bin/spim.rs b/embassy-nrf-examples/src/bin/spim.rs index ccda75765..df921fc86 100644 --- a/embassy-nrf-examples/src/bin/spim.rs +++ b/embassy-nrf-examples/src/bin/spim.rs @@ -19,11 +19,9 @@ use embedded_hal::digital::v2::*; use example_common::*; #[embassy::main] -async fn main(spawner: Spawner) { +async fn main(spawner: Spawner, p: Peripherals) { info!("running!"); - let p = unsafe { Peripherals::steal() }; - let mut config = spim::Config::default(); config.frequency = spim::Frequency::M16; diff --git a/embassy-nrf-examples/src/bin/timer.rs b/embassy-nrf-examples/src/bin/timer.rs index a2b717bc1..ffbbb7841 100644 --- a/embassy-nrf-examples/src/bin/timer.rs +++ b/embassy-nrf-examples/src/bin/timer.rs @@ -7,6 +7,7 @@ #[path = "../example_common.rs"] mod example_common; +use embassy_nrf::Peripherals; use example_common::*; use defmt::panic; @@ -30,7 +31,7 @@ async fn run2() { } #[embassy::main] -async fn main(spawner: Spawner) { +async fn main(spawner: Spawner, p: Peripherals) { unwrap!(spawner.spawn(run1())); unwrap!(spawner.spawn(run2())); } diff --git a/embassy-nrf-examples/src/bin/uart.rs b/embassy-nrf-examples/src/bin/uart.rs index 23fc89312..9a0e65d3e 100644 --- a/embassy-nrf-examples/src/bin/uart.rs +++ b/embassy-nrf-examples/src/bin/uart.rs @@ -17,9 +17,7 @@ use embassy_nrf::gpio::NoPin; use embassy_nrf::{interrupt, uarte, Peripherals}; #[embassy::main] -async fn main(spawner: Spawner) { - let p = unsafe { Peripherals::steal() }; - +async fn main(spawner: Spawner, p: Peripherals) { let mut config = uarte::Config::default(); config.parity = uarte::Parity::EXCLUDED; config.baudrate = uarte::Baudrate::BAUD115200; @@ -42,33 +40,5 @@ async fn main(spawner: Spawner) { unwrap!(uart.read(&mut buf).await); info!("writing..."); unwrap!(uart.write(&buf).await); - - /* - // `receive()` doesn't return until the buffer has been completely filled with - // incoming data, which in this case is 8 bytes. - // - // This example shows how to use `select` to run an uart receive concurrently with a - // 1 second timer, effectively adding a timeout to the receive operation. - let recv_fut = uart.read(&mut buf); - let timer_fut = Timer::after(Duration::from_millis(1000)); - let received_len = match select(recv_fut, timer_fut).await { - // recv_fut completed first, so we've received `buf_len` bytes. - Either::Left(_) => buf_len, - // timer_fut completed first. `select` gives us back the future that didn't complete, which - // is `recv_fut` in this case, so we can do further stuff with it. - // - // The recv_fut would stop the uart read automatically when dropped. However, we want to know how - // many bytes have been received, so we have to "gracefully stop" it with `.stop()`. - Either::Right((_, recv_fut)) => recv_fut.stop().await, - }; - let received = &mut buf[..received_len]; - - if !received.is_empty() { - info!("read done, got {}", received); - - // Echo back received data - unwrap!(uart.write(received).await); - } - */ } } diff --git a/embassy-nrf-examples/src/bin/uart_idle.rs b/embassy-nrf-examples/src/bin/uart_idle.rs index 54d524ae5..a97c65933 100644 --- a/embassy-nrf-examples/src/bin/uart_idle.rs +++ b/embassy-nrf-examples/src/bin/uart_idle.rs @@ -18,9 +18,7 @@ use embassy_nrf::gpio::NoPin; use embassy_nrf::{interrupt, uarte, Peripherals}; #[embassy::main] -async fn main(spawner: Spawner) { - let p = unsafe { Peripherals::steal() }; - +async fn main(spawner: Spawner, p: Peripherals) { let mut config = uarte::Config::default(); config.parity = uarte::Parity::EXCLUDED; config.baudrate = uarte::Baudrate::BAUD115200; diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 4349bf39f..6ab9cbb27 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -35,7 +35,6 @@ pub mod rtc; #[cfg(not(feature = "nrf52820"))] pub mod saadc; pub mod spim; -pub mod system; pub mod timer; pub mod twim; pub mod uarte; @@ -73,3 +72,88 @@ pub mod interrupt { pub use embassy_extras::interrupt::Priority3 as Priority; } pub use embassy_macros::interrupt; + +pub mod config { + pub enum HfclkSource { + Internal, + ExternalXtal, + } + + pub enum LfclkSource { + InternalRC, + Synthesized, + ExternalXtal, + ExternalLowSwing, + ExternalFullSwing, + } + + #[non_exhaustive] + pub struct Config { + pub hfclk_source: HfclkSource, + pub lfclk_source: LfclkSource, + } + + impl Default for Config { + fn default() -> Self { + Self { + // There are hobby nrf52 boards out there without external XTALs... + // Default everything to internal so it Just Works. User can enable external + // xtals if they know they have them. + hfclk_source: HfclkSource::Internal, + lfclk_source: LfclkSource::InternalRC, + } + } + } +} + +pub fn init(config: config::Config) -> Peripherals { + // Do this first, so that it panics if user is calling `init` a second time + // before doing anything important. + let peripherals = Peripherals::take(); + + let r = unsafe { &*pac::CLOCK::ptr() }; + + // Start HFCLK. + match config.hfclk_source { + config::HfclkSource::Internal => {} + config::HfclkSource::ExternalXtal => { + // Datasheet says this is likely to take 0.36ms + r.events_hfclkstarted.write(|w| unsafe { w.bits(0) }); + r.tasks_hfclkstart.write(|w| unsafe { w.bits(1) }); + while r.events_hfclkstarted.read().bits() == 0 {} + } + } + + // Configure LFCLK. + match config.lfclk_source { + config::LfclkSource::InternalRC => r.lfclksrc.write(|w| w.src().rc()), + config::LfclkSource::Synthesized => r.lfclksrc.write(|w| w.src().synth()), + + config::LfclkSource::ExternalXtal => r.lfclksrc.write(|w| w.src().xtal()), + + config::LfclkSource::ExternalLowSwing => r.lfclksrc.write(|w| { + w.src().xtal(); + w.external().enabled(); + w.bypass().disabled(); + w + }), + config::LfclkSource::ExternalFullSwing => r.lfclksrc.write(|w| { + w.src().xtal(); + w.external().enabled(); + w.bypass().enabled(); + w + }), + } + + // Start LFCLK. + // Datasheet says this could take 100us from synth source + // 600us from rc source, 0.25s from an external source. + r.events_lfclkstarted.write(|w| unsafe { w.bits(0) }); + r.tasks_lfclkstart.write(|w| unsafe { w.bits(1) }); + while r.events_lfclkstarted.read().bits() == 0 {} + + // Init GPIOTE + crate::gpiote::init(); + + peripherals +} diff --git a/embassy-nrf/src/system.rs b/embassy-nrf/src/system.rs deleted file mode 100644 index e358d2c38..000000000 --- a/embassy-nrf/src/system.rs +++ /dev/null @@ -1,79 +0,0 @@ -use crate::pac; - -pub enum HfclkSource { - Internal, - ExternalXtal, -} - -pub enum LfclkSource { - InternalRC, - Synthesized, - ExternalXtal, - ExternalLowSwing, - ExternalFullSwing, -} - -#[non_exhaustive] -pub struct Config { - pub hfclk_source: HfclkSource, - pub lfclk_source: LfclkSource, -} - -impl Default for Config { - fn default() -> Self { - Self { - // There are hobby nrf52 boards out there without external XTALs... - // Default everything to internal so it Just Works. User can enable external - // xtals if they know they have them. - hfclk_source: HfclkSource::Internal, - lfclk_source: LfclkSource::InternalRC, - } - } -} - -/// safety: must only call once. -pub unsafe fn configure(config: Config) { - let r = &*pac::CLOCK::ptr(); - - // Start HFCLK. - match config.hfclk_source { - HfclkSource::Internal => {} - HfclkSource::ExternalXtal => { - // Datasheet says this is likely to take 0.36ms - r.events_hfclkstarted.write(|w| unsafe { w.bits(0) }); - r.tasks_hfclkstart.write(|w| unsafe { w.bits(1) }); - while r.events_hfclkstarted.read().bits() == 0 {} - } - } - - // Configure LFCLK. - match config.lfclk_source { - LfclkSource::InternalRC => r.lfclksrc.write(|w| w.src().rc()), - LfclkSource::Synthesized => r.lfclksrc.write(|w| w.src().synth()), - - LfclkSource::ExternalXtal => r.lfclksrc.write(move |w| w.src().xtal()), - - LfclkSource::ExternalLowSwing => r.lfclksrc.write(move |w| { - w.src().xtal(); - w.external().enabled(); - w.bypass().disabled(); - w - }), - LfclkSource::ExternalFullSwing => r.lfclksrc.write(move |w| { - w.src().xtal(); - w.external().enabled(); - w.bypass().enabled(); - w - }), - } - - // Start LFCLK. - // Datasheet says this could take 100us from synth source - // 600us from rc source, 0.25s from an external source. - r.events_lfclkstarted.write(|w| unsafe { w.bits(0) }); - r.tasks_lfclkstart.write(|w| unsafe { w.bits(1) }); - while r.events_lfclkstarted.read().bits() == 0 {} - - // Init GPIOTE - crate::gpiote::init(); -} diff --git a/embassy-rp-examples/src/bin/blinky.rs b/embassy-rp-examples/src/bin/blinky.rs index 34e3cafc3..e42999912 100644 --- a/embassy-rp-examples/src/bin/blinky.rs +++ b/embassy-rp-examples/src/bin/blinky.rs @@ -16,9 +16,7 @@ use embedded_hal::digital::v2::OutputPin; use gpio::{Level, Output}; #[embassy::main] -async fn main(_spawner: Spawner) { - let p = unwrap!(Peripherals::take()); - +async fn main(_spawner: Spawner, p: Peripherals) { let mut led = Output::new(p.PIN_25, Level::Low); loop { diff --git a/embassy-rp-examples/src/bin/button.rs b/embassy-rp-examples/src/bin/button.rs index 77d4c57a9..007d07a36 100644 --- a/embassy-rp-examples/src/bin/button.rs +++ b/embassy-rp-examples/src/bin/button.rs @@ -16,9 +16,7 @@ use embassy_rp::Peripherals; use embedded_hal::digital::v2::{InputPin, OutputPin}; #[embassy::main] -async fn main(_spawner: Spawner) { - let p = unwrap!(Peripherals::take()); - +async fn main(_spawner: Spawner, p: Peripherals) { let button = Input::new(p.PIN_28, Pull::Up); let mut led = Output::new(p.PIN_25, Level::Low); diff --git a/embassy-rp-examples/src/bin/uart.rs b/embassy-rp-examples/src/bin/uart.rs index cd72d5312..82bd4cb6a 100644 --- a/embassy-rp-examples/src/bin/uart.rs +++ b/embassy-rp-examples/src/bin/uart.rs @@ -14,9 +14,7 @@ use embassy::executor::Spawner; use embassy_rp::{uart, Peripherals}; #[embassy::main] -async fn main(_spanwer: Spawner) { - let p = unwrap!(Peripherals::take()); - +async fn main(_spawner: Spawner, p: Peripherals) { let config = uart::Config::default(); let mut uart = uart::Uart::new(p.UART0, p.PIN_0, p.PIN_1, p.PIN_2, p.PIN_3, config); uart.send("Hello World!\r\n".as_bytes()); diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index f64464d13..f1a045987 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -15,7 +15,6 @@ pub mod dma; pub mod gpio; pub mod pll; pub mod resets; -pub mod system; pub mod uart; embassy_extras::peripherals! { @@ -72,3 +71,105 @@ embassy_extras::peripherals! { DMA_CH10, DMA_CH11, } + +#[link_section = ".boot2"] +#[used] +static BOOT2: [u8; 256] = *include_bytes!("boot2.bin"); + +pub mod config { + #[non_exhaustive] + pub struct Config {} + + impl Default for Config { + fn default() -> Self { + Self {} + } + } +} + +pub fn init(config: config::Config) -> Peripherals { + // Do this first, so that it panics if user is calling `init` a second time + // before doing anything important. + let peripherals = Peripherals::take(); + + // Now reset all the peripherals, except QSPI and XIP (we're using those + // to execute from external flash!) + + let resets = resets::Resets::new(); + + // Reset everything except: + // - QSPI (we're using it to run this code!) + // - PLLs (it may be suicide if that's what's clocking us) + let mut peris = resets::ALL_PERIPHERALS; + peris.set_io_qspi(false); + peris.set_pads_qspi(false); + peris.set_pll_sys(false); + peris.set_pll_usb(false); + resets.reset(peris); + + let mut peris = resets::ALL_PERIPHERALS; + peris.set_adc(false); + peris.set_rtc(false); + peris.set_spi0(false); + peris.set_spi1(false); + peris.set_uart0(false); + peris.set_uart1(false); + peris.set_usbctrl(false); + resets.unreset_wait(peris); + + unsafe { + // xosc 12 mhz + pac::WATCHDOG.tick().write(|w| { + w.set_cycles(XOSC_MHZ as u16); + w.set_enable(true); + }); + + pac::CLOCKS + .clk_sys_resus_ctrl() + .write_value(pac::clocks::regs::ClkSysResusCtrl(0)); + + // Enable XOSC + // TODO extract to HAL module + const XOSC_MHZ: u32 = 12; + pac::XOSC + .ctrl() + .write(|w| w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ)); + + let startup_delay = (((XOSC_MHZ * 1_000_000) / 1000) + 128) / 256; + pac::XOSC + .startup() + .write(|w| w.set_delay(startup_delay as u16)); + pac::XOSC.ctrl().write(|w| { + w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ); + w.set_enable(pac::xosc::vals::CtrlEnable::ENABLE); + }); + while !pac::XOSC.status().read().stable() {} + + // Before we touch PLLs, switch sys and ref cleanly away from their aux sources. + pac::CLOCKS + .clk_sys_ctrl() + .modify(|w| w.set_src(pac::clocks::vals::ClkSysCtrlSrc::CLK_REF)); + while pac::CLOCKS.clk_sys_selected().read() != 1 {} + pac::CLOCKS + .clk_ref_ctrl() + .modify(|w| w.set_src(pac::clocks::vals::ClkRefCtrlSrc::ROSC_CLKSRC_PH)); + while pac::CLOCKS.clk_ref_selected().read() != 1 {} + + let mut peris = resets::Peripherals(0); + peris.set_pll_sys(true); + peris.set_pll_usb(true); + resets.reset(peris); + resets.unreset_wait(peris); + + pll::PLL::new(pll::PllSys).configure(1, 1500_000_000, 6, 2); + pll::PLL::new(pll::PllUsb).configure(1, 480_000_000, 5, 2); + + // Activate peripheral clock and take external oscillator as input + pac::CLOCKS.clk_peri_ctrl().write(|w| { + w.set_enable(true); + w.set_auxsrc(pac::clocks::vals::ClkPeriCtrlAuxsrc::XOSC_CLKSRC); + }); + } + + peripherals +} diff --git a/embassy-rp/src/system.rs b/embassy-rp/src/system.rs deleted file mode 100644 index ba1396433..000000000 --- a/embassy-rp/src/system.rs +++ /dev/null @@ -1,94 +0,0 @@ -use crate::{pac, pll, resets}; - -#[link_section = ".boot2"] -#[used] -pub static BOOT2: [u8; 256] = *include_bytes!("boot2.bin"); - -#[non_exhaustive] -pub struct Config {} - -impl Default for Config { - fn default() -> Self { - Self {} - } -} - -/// safety: must only call once. -pub unsafe fn configure(_config: Config) { - // Now reset all the peripherals, except QSPI and XIP (we're using those - // to execute from external flash!) - - let resets = resets::Resets::new(); - - // Reset everything except: - // - QSPI (we're using it to run this code!) - // - PLLs (it may be suicide if that's what's clocking us) - let mut peris = resets::ALL_PERIPHERALS; - peris.set_io_qspi(false); - peris.set_pads_qspi(false); - peris.set_pll_sys(false); - peris.set_pll_usb(false); - resets.reset(peris); - - let mut peris = resets::ALL_PERIPHERALS; - peris.set_adc(false); - peris.set_rtc(false); - peris.set_spi0(false); - peris.set_spi1(false); - peris.set_uart0(false); - peris.set_uart1(false); - peris.set_usbctrl(false); - resets.unreset_wait(peris); - - // xosc 12 mhz - pac::WATCHDOG.tick().write(|w| { - w.set_cycles(XOSC_MHZ as u16); - w.set_enable(true); - }); - - pac::CLOCKS - .clk_sys_resus_ctrl() - .write_value(pac::clocks::regs::ClkSysResusCtrl(0)); - - // Enable XOSC - // TODO extract to HAL module - const XOSC_MHZ: u32 = 12; - pac::XOSC - .ctrl() - .write(|w| w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ)); - - let startup_delay = (((XOSC_MHZ * 1_000_000) / 1000) + 128) / 256; - pac::XOSC - .startup() - .write(|w| w.set_delay(startup_delay as u16)); - pac::XOSC.ctrl().write(|w| { - w.set_freq_range(pac::xosc::vals::CtrlFreqRange::_1_15MHZ); - w.set_enable(pac::xosc::vals::CtrlEnable::ENABLE); - }); - while !pac::XOSC.status().read().stable() {} - - // Before we touch PLLs, switch sys and ref cleanly away from their aux sources. - pac::CLOCKS - .clk_sys_ctrl() - .modify(|w| w.set_src(pac::clocks::vals::ClkSysCtrlSrc::CLK_REF)); - while pac::CLOCKS.clk_sys_selected().read() != 1 {} - pac::CLOCKS - .clk_ref_ctrl() - .modify(|w| w.set_src(pac::clocks::vals::ClkRefCtrlSrc::ROSC_CLKSRC_PH)); - while pac::CLOCKS.clk_ref_selected().read() != 1 {} - - let mut peris = resets::Peripherals(0); - peris.set_pll_sys(true); - peris.set_pll_usb(true); - resets.reset(peris); - resets.unreset_wait(peris); - - pll::PLL::new(pll::PllSys).configure(1, 1500_000_000, 6, 2); - pll::PLL::new(pll::PllUsb).configure(1, 480_000_000, 5, 2); - - // Activate peripheral clock and take external oscillator as input - pac::CLOCKS.clk_peri_ctrl().write(|w| { - w.set_enable(true); - w.set_auxsrc(pac::clocks::vals::ClkPeriCtrlAuxsrc::XOSC_CLKSRC); - }); -} From f9bcf6df6b6797c35941e64d1f67ca6ede74d30a Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Wed, 12 May 2021 04:56:11 +0200 Subject: [PATCH 07/10] nrf: add PWM --- embassy-nrf-examples/src/bin/pwm.rs | 104 +++++++++++++ embassy-nrf/src/chips/nrf52810.rs | 5 + embassy-nrf/src/chips/nrf52811.rs | 5 + embassy-nrf/src/chips/nrf52832.rs | 9 ++ embassy-nrf/src/chips/nrf52833.rs | 11 ++ embassy-nrf/src/chips/nrf52840.rs | 11 ++ embassy-nrf/src/lib.rs | 2 + embassy-nrf/src/pwm.rs | 219 ++++++++++++++++++++++++++++ 8 files changed, 366 insertions(+) create mode 100644 embassy-nrf-examples/src/bin/pwm.rs create mode 100644 embassy-nrf/src/pwm.rs diff --git a/embassy-nrf-examples/src/bin/pwm.rs b/embassy-nrf-examples/src/bin/pwm.rs new file mode 100644 index 000000000..6efcf22d2 --- /dev/null +++ b/embassy-nrf-examples/src/bin/pwm.rs @@ -0,0 +1,104 @@ +#![no_std] +#![no_main] +#![feature(min_type_alias_impl_trait)] +#![feature(impl_trait_in_bindings)] +#![feature(type_alias_impl_trait)] +#![allow(incomplete_features)] + +#[path = "../example_common.rs"] +mod example_common; +use defmt::{panic, *}; +use embassy::executor::Spawner; +use embassy::time::{Duration, Timer}; +use embassy_nrf::pwm::{Prescaler, Pwm}; +use embassy_nrf::{interrupt, Peripherals}; + +// for i in range(1024): print(int((math.sin(i/512*math.pi)*0.4+0.5)**2*32767), ', ', end='') +static DUTY: [u16; 1024] = [ + 8191, 8272, 8353, 8434, 8516, 8598, 8681, 8764, 8847, 8931, 9015, 9099, 9184, 9269, 9354, 9440, + 9526, 9613, 9700, 9787, 9874, 9962, 10050, 10139, 10227, 10316, 10406, 10495, 10585, 10675, + 10766, 10857, 10948, 11039, 11131, 11223, 11315, 11407, 11500, 11592, 11685, 11779, 11872, + 11966, 12060, 12154, 12248, 12343, 12438, 12533, 12628, 12723, 12818, 12914, 13010, 13106, + 13202, 13298, 13394, 13491, 13587, 13684, 13781, 13878, 13975, 14072, 14169, 14266, 14364, + 14461, 14558, 14656, 14754, 14851, 14949, 15046, 15144, 15242, 15339, 15437, 15535, 15632, + 15730, 15828, 15925, 16023, 16120, 16218, 16315, 16412, 16510, 16607, 16704, 16801, 16898, + 16995, 17091, 17188, 17284, 17380, 17477, 17572, 17668, 17764, 17859, 17955, 18050, 18145, + 18239, 18334, 18428, 18522, 18616, 18710, 18803, 18896, 18989, 19082, 19174, 19266, 19358, + 19449, 19540, 19631, 19722, 19812, 19902, 19991, 20081, 20169, 20258, 20346, 20434, 20521, + 20608, 20695, 20781, 20867, 20952, 21037, 21122, 21206, 21290, 21373, 21456, 21538, 21620, + 21701, 21782, 21863, 21943, 22022, 22101, 22179, 22257, 22335, 22412, 22488, 22564, 22639, + 22714, 22788, 22861, 22934, 23007, 23079, 23150, 23220, 23290, 23360, 23429, 23497, 23564, + 23631, 23698, 23763, 23828, 23892, 23956, 24019, 24081, 24143, 24204, 24264, 24324, 24383, + 24441, 24499, 24555, 24611, 24667, 24721, 24775, 24828, 24881, 24933, 24983, 25034, 25083, + 25132, 25180, 25227, 25273, 25319, 25363, 25407, 25451, 25493, 25535, 25575, 25615, 25655, + 25693, 25731, 25767, 25803, 25838, 25873, 25906, 25939, 25971, 26002, 26032, 26061, 26089, + 26117, 26144, 26170, 26195, 26219, 26242, 26264, 26286, 26307, 26327, 26346, 26364, 26381, + 26397, 26413, 26427, 26441, 26454, 26466, 26477, 26487, 26496, 26505, 26512, 26519, 26525, + 26530, 26534, 26537, 26539, 26540, 26541, 26540, 26539, 26537, 26534, 26530, 26525, 26519, + 26512, 26505, 26496, 26487, 26477, 26466, 26454, 26441, 26427, 26413, 26397, 26381, 26364, + 26346, 26327, 26307, 26286, 26264, 26242, 26219, 26195, 26170, 26144, 26117, 26089, 26061, + 26032, 26002, 25971, 25939, 25906, 25873, 25838, 25803, 25767, 25731, 25693, 25655, 25615, + 25575, 25535, 25493, 25451, 25407, 25363, 25319, 25273, 25227, 25180, 25132, 25083, 25034, + 24983, 24933, 24881, 24828, 24775, 24721, 24667, 24611, 24555, 24499, 24441, 24383, 24324, + 24264, 24204, 24143, 24081, 24019, 23956, 23892, 23828, 23763, 23698, 23631, 23564, 23497, + 23429, 23360, 23290, 23220, 23150, 23079, 23007, 22934, 22861, 22788, 22714, 22639, 22564, + 22488, 22412, 22335, 22257, 22179, 22101, 22022, 21943, 21863, 21782, 21701, 21620, 21538, + 21456, 21373, 21290, 21206, 21122, 21037, 20952, 20867, 20781, 20695, 20608, 20521, 20434, + 20346, 20258, 20169, 20081, 19991, 19902, 19812, 19722, 19631, 19540, 19449, 19358, 19266, + 19174, 19082, 18989, 18896, 18803, 18710, 18616, 18522, 18428, 18334, 18239, 18145, 18050, + 17955, 17859, 17764, 17668, 17572, 17477, 17380, 17284, 17188, 17091, 16995, 16898, 16801, + 16704, 16607, 16510, 16412, 16315, 16218, 16120, 16023, 15925, 15828, 15730, 15632, 15535, + 15437, 15339, 15242, 15144, 15046, 14949, 14851, 14754, 14656, 14558, 14461, 14364, 14266, + 14169, 14072, 13975, 13878, 13781, 13684, 13587, 13491, 13394, 13298, 13202, 13106, 13010, + 12914, 12818, 12723, 12628, 12533, 12438, 12343, 12248, 12154, 12060, 11966, 11872, 11779, + 11685, 11592, 11500, 11407, 11315, 11223, 11131, 11039, 10948, 10857, 10766, 10675, 10585, + 10495, 10406, 10316, 10227, 10139, 10050, 9962, 9874, 9787, 9700, 9613, 9526, 9440, 9354, 9269, + 9184, 9099, 9015, 8931, 8847, 8764, 8681, 8598, 8516, 8434, 8353, 8272, 8191, 8111, 8031, 7952, + 7873, 7794, 7716, 7638, 7561, 7484, 7407, 7331, 7255, 7180, 7105, 7031, 6957, 6883, 6810, 6738, + 6665, 6594, 6522, 6451, 6381, 6311, 6241, 6172, 6104, 6036, 5968, 5901, 5834, 5767, 5702, 5636, + 5571, 5507, 5443, 5379, 5316, 5253, 5191, 5130, 5068, 5008, 4947, 4888, 4828, 4769, 4711, 4653, + 4596, 4539, 4482, 4426, 4371, 4316, 4261, 4207, 4153, 4100, 4047, 3995, 3943, 3892, 3841, 3791, + 3741, 3691, 3642, 3594, 3546, 3498, 3451, 3404, 3358, 3312, 3267, 3222, 3178, 3134, 3090, 3047, + 3005, 2962, 2921, 2879, 2839, 2798, 2758, 2719, 2680, 2641, 2603, 2565, 2528, 2491, 2454, 2418, + 2382, 2347, 2312, 2278, 2244, 2210, 2177, 2144, 2112, 2080, 2048, 2017, 1986, 1956, 1926, 1896, + 1867, 1838, 1810, 1781, 1754, 1726, 1699, 1673, 1646, 1620, 1595, 1570, 1545, 1520, 1496, 1472, + 1449, 1426, 1403, 1380, 1358, 1336, 1315, 1294, 1273, 1252, 1232, 1212, 1192, 1173, 1154, 1135, + 1117, 1099, 1081, 1063, 1046, 1029, 1012, 996, 980, 964, 948, 933, 918, 903, 888, 874, 860, + 846, 833, 819, 806, 793, 781, 768, 756, 744, 733, 721, 710, 699, 688, 677, 667, 657, 647, 637, + 627, 618, 609, 599, 591, 582, 574, 565, 557, 549, 541, 534, 526, 519, 512, 505, 498, 492, 485, + 479, 473, 467, 461, 455, 450, 444, 439, 434, 429, 424, 419, 415, 410, 406, 402, 398, 394, 390, + 386, 383, 379, 376, 373, 370, 367, 364, 361, 359, 356, 354, 351, 349, 347, 345, 343, 342, 340, + 338, 337, 336, 334, 333, 332, 331, 330, 330, 329, 328, 328, 328, 327, 327, 327, 327, 327, 328, + 328, 328, 329, 330, 330, 331, 332, 333, 334, 336, 337, 338, 340, 342, 343, 345, 347, 349, 351, + 354, 356, 359, 361, 364, 367, 370, 373, 376, 379, 383, 386, 390, 394, 398, 402, 406, 410, 415, + 419, 424, 429, 434, 439, 444, 450, 455, 461, 467, 473, 479, 485, 492, 498, 505, 512, 519, 526, + 534, 541, 549, 557, 565, 574, 582, 591, 599, 609, 618, 627, 637, 647, 657, 667, 677, 688, 699, + 710, 721, 733, 744, 756, 768, 781, 793, 806, 819, 833, 846, 860, 874, 888, 903, 918, 933, 948, + 964, 980, 996, 1012, 1029, 1046, 1063, 1081, 1099, 1117, 1135, 1154, 1173, 1192, 1212, 1232, + 1252, 1273, 1294, 1315, 1336, 1358, 1380, 1403, 1426, 1449, 1472, 1496, 1520, 1545, 1570, 1595, + 1620, 1646, 1673, 1699, 1726, 1754, 1781, 1810, 1838, 1867, 1896, 1926, 1956, 1986, 2017, 2048, + 2080, 2112, 2144, 2177, 2210, 2244, 2278, 2312, 2347, 2382, 2418, 2454, 2491, 2528, 2565, 2603, + 2641, 2680, 2719, 2758, 2798, 2839, 2879, 2921, 2962, 3005, 3047, 3090, 3134, 3178, 3222, 3267, + 3312, 3358, 3404, 3451, 3498, 3546, 3594, 3642, 3691, 3741, 3791, 3841, 3892, 3943, 3995, 4047, + 4100, 4153, 4207, 4261, 4316, 4371, 4426, 4482, 4539, 4596, 4653, 4711, 4769, 4828, 4888, 4947, + 5008, 5068, 5130, 5191, 5253, 5316, 5379, 5443, 5507, 5571, 5636, 5702, 5767, 5834, 5901, 5968, + 6036, 6104, 6172, 6241, 6311, 6381, 6451, 6522, 6594, 6665, 6738, 6810, 6883, 6957, 7031, 7105, + 7180, 7255, 7331, 7407, 7484, 7561, 7638, 7716, 7794, 7873, 7952, 8031, 8111, +]; + +#[embassy::main] +async fn main(spawner: Spawner, p: Peripherals) { + let pwm = Pwm::new(p.PWM0, p.P0_13, p.P0_14, p.P0_16, p.P0_15); + pwm.set_prescaler(Prescaler::Div1); + info!("pwm initialized!"); + + let mut i = 0; + loop { + i += 1; + pwm.set_duty(0, DUTY[i % 1024]); + pwm.set_duty(1, DUTY[(i + 256) % 1024]); + pwm.set_duty(2, DUTY[(i + 512) % 1024]); + pwm.set_duty(3, DUTY[(i + 768) % 1024]); + Timer::after(Duration::from_millis(3)).await; + } +} diff --git a/embassy-nrf/src/chips/nrf52810.rs b/embassy-nrf/src/chips/nrf52810.rs index 2e77a2fad..9e9f80090 100644 --- a/embassy-nrf/src/chips/nrf52810.rs +++ b/embassy-nrf/src/chips/nrf52810.rs @@ -18,6 +18,9 @@ embassy_extras::peripherals! { // SAADC SAADC, + // PWM + PWM0, + // TIMER TIMER0, TIMER1, @@ -115,6 +118,8 @@ impl_spim!(SPI0, SPIM0, SPIM0_SPIS0_SPI0); impl_twim!(TWI0, TWIM0, TWIM0_TWIS0_TWI0); +impl_pwm!(PWM0, PWM0, PWM0); + impl_timer!(TIMER0, TIMER0, TIMER0); impl_timer!(TIMER1, TIMER1, TIMER1); impl_timer!(TIMER2, TIMER2, TIMER2); diff --git a/embassy-nrf/src/chips/nrf52811.rs b/embassy-nrf/src/chips/nrf52811.rs index b3ad5817a..a9ef0ed19 100644 --- a/embassy-nrf/src/chips/nrf52811.rs +++ b/embassy-nrf/src/chips/nrf52811.rs @@ -18,6 +18,9 @@ embassy_extras::peripherals! { // SAADC SAADC, + // PWM + PWM0, + // TIMER TIMER0, TIMER1, @@ -116,6 +119,8 @@ impl_spim!(SPI1, SPIM1, SPIM1_SPIS1_SPI1); impl_twim!(TWISPI0, TWIM0, TWIM0_TWIS0_TWI0_SPIM0_SPIS0_SPI0); +impl_pwm!(PWM0, PWM0, PWM0); + impl_timer!(TIMER0, TIMER0, TIMER0); impl_timer!(TIMER1, TIMER1, TIMER1); impl_timer!(TIMER2, TIMER2, TIMER2); diff --git a/embassy-nrf/src/chips/nrf52832.rs b/embassy-nrf/src/chips/nrf52832.rs index ed94430e4..4e57f2fa4 100644 --- a/embassy-nrf/src/chips/nrf52832.rs +++ b/embassy-nrf/src/chips/nrf52832.rs @@ -21,6 +21,11 @@ embassy_extras::peripherals! { // SAADC SAADC, + // PWM + PWM0, + PWM1, + PWM2, + // TIMER TIMER0, TIMER1, @@ -123,6 +128,10 @@ impl_spim!(SPI2, SPIM2, SPIM2_SPIS2_SPI2); impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); +impl_pwm!(PWM0, PWM0, PWM0); +impl_pwm!(PWM1, PWM1, PWM1); +impl_pwm!(PWM2, PWM2, PWM2); + impl_timer!(TIMER0, TIMER0, TIMER0); impl_timer!(TIMER1, TIMER1, TIMER1); impl_timer!(TIMER2, TIMER2, TIMER2); diff --git a/embassy-nrf/src/chips/nrf52833.rs b/embassy-nrf/src/chips/nrf52833.rs index 080157d69..30b0ab007 100644 --- a/embassy-nrf/src/chips/nrf52833.rs +++ b/embassy-nrf/src/chips/nrf52833.rs @@ -22,6 +22,12 @@ embassy_extras::peripherals! { // SAADC SAADC, + // PWM + PWM0, + PWM1, + PWM2, + PWM3, + // TIMER TIMER0, TIMER1, @@ -144,6 +150,11 @@ impl_spim!(SPI3, SPIM3, SPIM3); impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); +impl_pwm!(PWM0, PWM0, PWM0); +impl_pwm!(PWM1, PWM1, PWM1); +impl_pwm!(PWM2, PWM2, PWM2); +impl_pwm!(PWM3, PWM3, PWM3); + impl_timer!(TIMER0, TIMER0, TIMER0); impl_timer!(TIMER1, TIMER1, TIMER1); impl_timer!(TIMER2, TIMER2, TIMER2); diff --git a/embassy-nrf/src/chips/nrf52840.rs b/embassy-nrf/src/chips/nrf52840.rs index 06b508d89..0b6c3f68e 100644 --- a/embassy-nrf/src/chips/nrf52840.rs +++ b/embassy-nrf/src/chips/nrf52840.rs @@ -25,6 +25,12 @@ embassy_extras::peripherals! { // SAADC SAADC, + // PWM + PWM0, + PWM1, + PWM2, + PWM3, + // TIMER TIMER0, TIMER1, @@ -147,6 +153,11 @@ impl_spim!(SPI3, SPIM3, SPIM3); impl_twim!(TWISPI0, TWIM0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0); impl_twim!(TWISPI1, TWIM1, SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1); +impl_pwm!(PWM0, PWM0, PWM0); +impl_pwm!(PWM1, PWM1, PWM1); +impl_pwm!(PWM2, PWM2, PWM2); +impl_pwm!(PWM3, PWM3, PWM3); + impl_timer!(TIMER0, TIMER0, TIMER0); impl_timer!(TIMER1, TIMER1, TIMER1); impl_timer!(TIMER2, TIMER2, TIMER2); diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index 6ab9cbb27..1c496be19 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -29,6 +29,8 @@ pub mod buffered_uarte; pub mod gpio; pub mod gpiote; pub mod ppi; +#[cfg(not(any(feature = "nrf52805", feature = "nrf52820")))] +pub mod pwm; #[cfg(feature = "nrf52840")] pub mod qspi; pub mod rtc; diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs new file mode 100644 index 000000000..b79c4bc37 --- /dev/null +++ b/embassy-nrf/src/pwm.rs @@ -0,0 +1,219 @@ +#![macro_use] + +use core::cell::UnsafeCell; +use core::marker::PhantomData; +use core::sync::atomic::{compiler_fence, Ordering}; +use embassy::util::Unborrow; +use embassy_extras::unborrow; + +use crate::fmt::{assert, panic, unreachable, *}; +use crate::gpio::sealed::Pin as _; +use crate::gpio::OptionalPin as GpioOptionalPin; +use crate::interrupt::Interrupt; +use crate::pac; + +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum Prescaler { + Div1, + Div2, + Div4, + Div8, + Div16, + Div32, + Div64, + Div128, +} + +/// Interface to the UARTE peripheral +pub struct Pwm<'d, T: Instance> { + peri: T, + phantom: PhantomData<&'d mut T>, +} + +impl<'d, T: Instance> Pwm<'d, T> { + /// Creates the interface to a UARTE instance. + /// Sets the baud rate, parity and assigns the pins to the UARTE peripheral. + /// + /// # Safety + /// + /// The returned API is safe unless you use `mem::forget` (or similar safe mechanisms) + /// on stack allocated buffers which which have been passed to [`send()`](Pwm::send) + /// or [`receive`](Pwm::receive). + #[allow(unused_unsafe)] + pub fn new( + pwm: impl Unborrow + 'd, + ch0: impl Unborrow + 'd, + ch1: impl Unborrow + 'd, + ch2: impl Unborrow + 'd, + ch3: impl Unborrow + 'd, + ) -> Self { + unborrow!(pwm, ch0, ch1, ch2, ch3); + + let r = T::regs(); + let s = T::state(); + + if let Some(pin) = ch0.pin_mut() { + pin.set_high(); + pin.conf().write(|w| w.dir().output()); + } + if let Some(pin) = ch1.pin_mut() { + pin.set_high(); + pin.conf().write(|w| w.dir().output()); + } + if let Some(pin) = ch2.pin_mut() { + pin.set_high(); + pin.conf().write(|w| w.dir().output()); + } + if let Some(pin) = ch3.pin_mut() { + pin.set_high(); + pin.conf().write(|w| w.dir().output()); + } + r.psel.out[0].write(|w| unsafe { w.bits(ch0.psel_bits()) }); + r.psel.out[1].write(|w| unsafe { w.bits(ch1.psel_bits()) }); + r.psel.out[2].write(|w| unsafe { w.bits(ch2.psel_bits()) }); + r.psel.out[3].write(|w| unsafe { w.bits(ch3.psel_bits()) }); + + // Disable all interrupts + r.intenclr.write(|w| unsafe { w.bits(0xFFFF_FFFF) }); + + // Enable + r.enable.write(|w| w.enable().enabled()); + + r.seq0 + .ptr + .write(|w| unsafe { w.bits(&s.duty as *const _ as u32) }); + r.seq0.cnt.write(|w| unsafe { w.bits(4) }); + r.seq0.refresh.write(|w| unsafe { w.bits(32) }); + r.seq0.enddelay.write(|w| unsafe { w.bits(0) }); + + r.decoder.write(|w| { + w.load().individual(); + w.mode().refresh_count() + }); + r.mode.write(|w| w.updown().up()); + r.prescaler.write(|w| w.prescaler().div_1()); + r.countertop + .write(|w| unsafe { w.countertop().bits(32767) }); + r.loop_.write(|w| w.cnt().disabled()); + + Self { + peri: pwm, + phantom: PhantomData, + } + } + + /// Sets duty cycle (15 bit) for a PWM channel. + pub fn set_duty(&self, channel: usize, duty: u16) { + let s = T::state(); + unsafe { (*s.duty.get())[channel] = duty & 0x7FFF }; + + compiler_fence(Ordering::SeqCst); + T::regs().tasks_seqstart[0].write(|w| unsafe { w.bits(1) }); + } + + /// Sets the PWM clock prescaler. + #[inline(always)] + pub fn set_prescaler(&self, div: Prescaler) { + T::regs().prescaler.write(|w| w.prescaler().bits(div as u8)); + } + + /// Sets the PWM clock prescaler. + #[inline(always)] + pub fn prescaler(&self) -> Prescaler { + match T::regs().prescaler.read().prescaler().bits() { + 0 => Prescaler::Div1, + 1 => Prescaler::Div2, + 2 => Prescaler::Div4, + 3 => Prescaler::Div8, + 4 => Prescaler::Div16, + 5 => Prescaler::Div32, + 6 => Prescaler::Div64, + 7 => Prescaler::Div128, + _ => unreachable!(), + } + } + + /// Sets the maximum duty cycle value. + #[inline(always)] + pub fn set_max_duty(&self, duty: u16) { + T::regs() + .countertop + .write(|w| unsafe { w.countertop().bits(duty.min(32767u16)) }); + } + + /// Returns the maximum duty cycle value. + #[inline(always)] + pub fn max_duty(&self) -> u16 { + T::regs().countertop.read().countertop().bits() + } + + /// Sets the PWM output frequency. + #[inline(always)] + pub fn set_period(&self, freq: u32) { + let clk = 16_000_000u32 >> (self.prescaler() as u8); + let duty = clk / freq; + self.set_max_duty(duty.min(32767) as u16); + } + + /// Returns the PWM output frequency. + #[inline(always)] + pub fn period(&self) -> u32 { + let clk = 16_000_000u32 >> (self.prescaler() as u8); + let max_duty = self.max_duty() as u32; + clk / max_duty + } +} + +impl<'a, T: Instance> Drop for Pwm<'a, T> { + fn drop(&mut self) { + let r = T::regs(); + r.enable.write(|w| w.enable().disabled()); + + info!("pwm drop: done"); + + // TODO: disable pins + } +} + +pub(crate) mod sealed { + use super::*; + + pub struct State { + pub duty: UnsafeCell<[u16; 4]>, + } + unsafe impl Sync for State {} + + impl State { + pub const fn new() -> Self { + Self { + duty: UnsafeCell::new([0; 4]), + } + } + } + + pub trait Instance { + fn regs() -> &'static pac::pwm0::RegisterBlock; + fn state() -> &'static State; + } +} + +pub trait Instance: sealed::Instance + 'static { + type Interrupt: Interrupt; +} + +macro_rules! impl_pwm { + ($type:ident, $pac_type:ident, $irq:ident) => { + impl crate::pwm::sealed::Instance for peripherals::$type { + fn regs() -> &'static pac::pwm0::RegisterBlock { + unsafe { &*pac::$pac_type::ptr() } + } + fn state() -> &'static crate::pwm::sealed::State { + static STATE: crate::pwm::sealed::State = crate::pwm::sealed::State::new(); + &STATE + } + } + impl crate::pwm::Instance for peripherals::$type { + type Interrupt = crate::interrupt::$irq; + } + }; +} From 88f664b434fd062faee923129d8814ef9c16036d Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 15 May 2021 00:02:35 +0200 Subject: [PATCH 08/10] nrf/pwm: set initial value to Low, according to the PS --- embassy-nrf/src/pwm.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index b79c4bc37..ec589e8d1 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs @@ -53,19 +53,19 @@ impl<'d, T: Instance> Pwm<'d, T> { let s = T::state(); if let Some(pin) = ch0.pin_mut() { - pin.set_high(); + pin.set_low(); pin.conf().write(|w| w.dir().output()); } if let Some(pin) = ch1.pin_mut() { - pin.set_high(); + pin.set_low(); pin.conf().write(|w| w.dir().output()); } if let Some(pin) = ch2.pin_mut() { - pin.set_high(); + pin.set_low(); pin.conf().write(|w| w.dir().output()); } if let Some(pin) = ch3.pin_mut() { - pin.set_high(); + pin.set_low(); pin.conf().write(|w| w.dir().output()); } r.psel.out[0].write(|w| unsafe { w.bits(ch0.psel_bits()) }); From 8394603ea6c76b29d1cb14f706e048eebbd933c3 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 15 May 2021 00:02:50 +0200 Subject: [PATCH 09/10] nrf/pwm: add enable/disable --- embassy-nrf/src/pwm.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index ec589e8d1..4f500d722 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs @@ -102,6 +102,20 @@ impl<'d, T: Instance> Pwm<'d, T> { } } + /// Enables the PWM generator. + #[inline(always)] + pub fn enable(&self) { + let r = T::regs(); + r.enable.write(|w| w.enable().enabled()); + } + + /// Disables the PWM generator. + #[inline(always)] + pub fn disable(&self) { + let r = T::regs(); + r.enable.write(|w| w.enable().disabled()); + } + /// Sets duty cycle (15 bit) for a PWM channel. pub fn set_duty(&self, channel: usize, duty: u16) { let s = T::state(); From a5ad79927ecaa9d6cd7bd96e015b66afa9201d84 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sat, 15 May 2021 00:05:32 +0200 Subject: [PATCH 10/10] nrf: add `Unborrow` bound to all instance traits --- embassy-nrf/src/gpio.rs | 4 ++-- embassy-nrf/src/pwm.rs | 2 +- embassy-nrf/src/qspi.rs | 2 +- embassy-nrf/src/rtc.rs | 4 ++-- embassy-nrf/src/spim.rs | 2 +- embassy-nrf/src/timer.rs | 3 ++- embassy-nrf/src/twim.rs | 2 +- embassy-nrf/src/uarte.rs | 2 +- 8 files changed, 11 insertions(+), 10 deletions(-) diff --git a/embassy-nrf/src/gpio.rs b/embassy-nrf/src/gpio.rs index 2cdb685d3..fed1ae049 100644 --- a/embassy-nrf/src/gpio.rs +++ b/embassy-nrf/src/gpio.rs @@ -331,7 +331,7 @@ pub(crate) mod sealed { pub trait OptionalPin {} } -pub trait Pin: sealed::Pin + Sized { +pub trait Pin: Unborrow + sealed::Pin + Sized { /// Number of the pin within the port (0..31) #[inline] fn pin(&self) -> u8 { @@ -435,7 +435,7 @@ fn init_output(pin: &T, drive: OutputDrive) { // ==================== -pub trait OptionalPin: sealed::OptionalPin + Sized { +pub trait OptionalPin: Unborrow + sealed::OptionalPin + Sized { type Pin: Pin; fn pin(&self) -> Option<&Self::Pin>; fn pin_mut(&mut self) -> Option<&mut Self::Pin>; diff --git a/embassy-nrf/src/pwm.rs b/embassy-nrf/src/pwm.rs index 4f500d722..34c31e3bb 100644 --- a/embassy-nrf/src/pwm.rs +++ b/embassy-nrf/src/pwm.rs @@ -211,7 +211,7 @@ pub(crate) mod sealed { } } -pub trait Instance: sealed::Instance + 'static { +pub trait Instance: Unborrow + sealed::Instance + 'static { type Interrupt: Interrupt; } diff --git a/embassy-nrf/src/qspi.rs b/embassy-nrf/src/qspi.rs index d75070220..db6b653e7 100644 --- a/embassy-nrf/src/qspi.rs +++ b/embassy-nrf/src/qspi.rs @@ -383,7 +383,7 @@ pub(crate) mod sealed { } } -pub trait Instance: sealed::Instance + 'static { +pub trait Instance: Unborrow + sealed::Instance + 'static { type Interrupt: Interrupt; } diff --git a/embassy-nrf/src/rtc.rs b/embassy-nrf/src/rtc.rs index dc0e3ceb6..99b6c099d 100644 --- a/embassy-nrf/src/rtc.rs +++ b/embassy-nrf/src/rtc.rs @@ -3,7 +3,7 @@ use core::sync::atomic::{compiler_fence, AtomicU32, Ordering}; use critical_section::CriticalSection; use embassy::interrupt::InterruptExt; use embassy::time::Clock; -use embassy::util::CriticalSectionMutex as Mutex; +use embassy::util::{CriticalSectionMutex as Mutex, Unborrow}; use crate::interrupt::Interrupt; use crate::pac; @@ -283,7 +283,7 @@ macro_rules! impl_instance { } /// Implemented by all RTC instances. -pub trait Instance: sealed::Instance + 'static { +pub trait Instance: Unborrow + sealed::Instance + 'static { /// The interrupt associated with this RTC instance. type Interrupt: Interrupt; } diff --git a/embassy-nrf/src/spim.rs b/embassy-nrf/src/spim.rs index 1fb3d441b..0703836b9 100644 --- a/embassy-nrf/src/spim.rs +++ b/embassy-nrf/src/spim.rs @@ -349,7 +349,7 @@ pub(crate) mod sealed { } } -pub trait Instance: sealed::Instance + 'static { +pub trait Instance: Unborrow + sealed::Instance + 'static { type Interrupt: Interrupt; } diff --git a/embassy-nrf/src/timer.rs b/embassy-nrf/src/timer.rs index 69d620b48..2490bfd93 100644 --- a/embassy-nrf/src/timer.rs +++ b/embassy-nrf/src/timer.rs @@ -1,6 +1,7 @@ #![macro_use] use embassy::interrupt::Interrupt; +use embassy::util::Unborrow; use crate::pac; @@ -13,7 +14,7 @@ pub(crate) mod sealed { pub trait ExtendedInstance {} } -pub trait Instance: sealed::Instance + 'static { +pub trait Instance: Unborrow + sealed::Instance + 'static { type Interrupt: Interrupt; } pub trait ExtendedInstance: Instance + sealed::ExtendedInstance {} diff --git a/embassy-nrf/src/twim.rs b/embassy-nrf/src/twim.rs index cbaf97dff..3e0fbc3d0 100644 --- a/embassy-nrf/src/twim.rs +++ b/embassy-nrf/src/twim.rs @@ -509,7 +509,7 @@ pub(crate) mod sealed { } } -pub trait Instance: sealed::Instance + 'static { +pub trait Instance: Unborrow + sealed::Instance + 'static { type Interrupt: Interrupt; } diff --git a/embassy-nrf/src/uarte.rs b/embassy-nrf/src/uarte.rs index 7581f7a8b..494110bee 100644 --- a/embassy-nrf/src/uarte.rs +++ b/embassy-nrf/src/uarte.rs @@ -469,7 +469,7 @@ pub(crate) mod sealed { } } -pub trait Instance: sealed::Instance + 'static { +pub trait Instance: Unborrow + sealed::Instance + 'static { type Interrupt: Interrupt; }