diff options
| -rw-r--r-- | Cargo.toml | 2 | ||||
| -rw-r--r-- | embassy-stm32f4-examples/Cargo.toml | 39 | ||||
| -rw-r--r-- | embassy-stm32f4-examples/src/serial.rs | 64 | ||||
| -rw-r--r-- | embassy-stm32f4/Cargo.toml | 43 | ||||
| -rw-r--r-- | embassy-stm32f4/src/fmt.rs | 118 | ||||
| -rw-r--r-- | embassy-stm32f4/src/interrupt.rs | 193 | ||||
| -rw-r--r-- | embassy-stm32f4/src/lib.rs | 317 | ||||
| -rw-r--r-- | embassy-stm32f4/src/serial.rs | 224 |
8 files changed, 1000 insertions, 0 deletions
diff --git a/Cargo.toml b/Cargo.toml index 5ba9ba7d3..3e036b610 100644 --- a/Cargo.toml +++ b/Cargo.toml | |||
| @@ -3,7 +3,9 @@ | |||
| 3 | members = [ | 3 | members = [ |
| 4 | "embassy", | 4 | "embassy", |
| 5 | "embassy-nrf", | 5 | "embassy-nrf", |
| 6 | "embassy-stm32f4", | ||
| 6 | "embassy-nrf-examples", | 7 | "embassy-nrf-examples", |
| 8 | "embassy-stm32f4-examples", | ||
| 7 | "embassy-macros", | 9 | "embassy-macros", |
| 8 | ] | 10 | ] |
| 9 | 11 | ||
diff --git a/embassy-stm32f4-examples/Cargo.toml b/embassy-stm32f4-examples/Cargo.toml new file mode 100644 index 000000000..6502a77a5 --- /dev/null +++ b/embassy-stm32f4-examples/Cargo.toml | |||
| @@ -0,0 +1,39 @@ | |||
| 1 | [package] | ||
| 2 | authors = ["Dario Nieuwenhuis <[email protected]>"] | ||
| 3 | edition = "2018" | ||
| 4 | name = "embassy-stm32f4-examples" | ||
| 5 | version = "0.1.0" | ||
| 6 | |||
| 7 | [features] | ||
| 8 | default = [ | ||
| 9 | "defmt-default", | ||
| 10 | ] | ||
| 11 | defmt-default = [] | ||
| 12 | defmt-trace = [] | ||
| 13 | defmt-debug = [] | ||
| 14 | defmt-info = [] | ||
| 15 | defmt-warn = [] | ||
| 16 | defmt-error = [] | ||
| 17 | |||
| 18 | |||
| 19 | [dependencies] | ||
| 20 | embassy = { version = "0.1.0", path = "../embassy", features = ["defmt", "defmt-trace"] } | ||
| 21 | embassy-stm32f4 = { version = "*", path = "../embassy-stm32f4", features = ["stm32f405"] } | ||
| 22 | |||
| 23 | defmt = "0.1.3" | ||
| 24 | defmt-rtt = "0.1.0" | ||
| 25 | |||
| 26 | cortex-m = { version = "0.6.3" } | ||
| 27 | cortex-m-rt = "0.6.13" | ||
| 28 | embedded-hal = { version = "0.2.4" } | ||
| 29 | panic-probe = "0.1.0" | ||
| 30 | stm32f4xx-hal = { version = "0.8.3", features = ["rt", "stm32f405"], git = "https://github.com/stm32-rs/stm32f4xx-hal.git"} | ||
| 31 | futures = { version = "0.3.8", default-features = false, features = ["async-await"] } | ||
| 32 | cortex-m-rtic = "0.5" | ||
| 33 | rtt-target = { version = "0.3", features = ["cortex-m"] } | ||
| 34 | |||
| 35 | |||
| 36 | |||
| 37 | [[bin]] | ||
| 38 | name = "serial" | ||
| 39 | path = "src/serial.rs" \ No newline at end of file | ||
diff --git a/embassy-stm32f4-examples/src/serial.rs b/embassy-stm32f4-examples/src/serial.rs new file mode 100644 index 000000000..baed2e525 --- /dev/null +++ b/embassy-stm32f4-examples/src/serial.rs | |||
| @@ -0,0 +1,64 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![no_main] | ||
| 3 | #![feature(trait_alias)] | ||
| 4 | #![feature(type_alias_impl_trait)] | ||
| 5 | |||
| 6 | // extern crate panic_halt; | ||
| 7 | |||
| 8 | use cortex_m::singleton; | ||
| 9 | use cortex_m_rt::entry; | ||
| 10 | use embassy::executor::{task, Executor}; | ||
| 11 | use embassy::util::Forever; | ||
| 12 | use embassy_stm32f4::interrupt; | ||
| 13 | use embassy_stm32f4::serial; | ||
| 14 | use stm32f4xx_hal::stm32; | ||
| 15 | use stm32f4xx_hal::{prelude::*, serial::config}; | ||
| 16 | |||
| 17 | #[task] | ||
| 18 | async fn run(dp: stm32::Peripherals, cp: cortex_m::Peripherals) { | ||
| 19 | // https://gist.github.com/thalesfragoso/a07340c5df6eee3b04c42fdc69ecdcb1 | ||
| 20 | let gpioa = dp.GPIOA.split(); | ||
| 21 | let rcc = dp.RCC.constrain(); | ||
| 22 | |||
| 23 | let clocks = rcc | ||
| 24 | .cfgr | ||
| 25 | .use_hse(16.mhz()) | ||
| 26 | .sysclk(48.mhz()) | ||
| 27 | .pclk1(24.mhz()) | ||
| 28 | .freeze(); | ||
| 29 | |||
| 30 | let mut serial = serial::Serial::new( | ||
| 31 | gpioa.pa9.into_alternate_af7(), | ||
| 32 | gpioa.pa10.into_alternate_af7(), | ||
| 33 | interrupt::take!(DMA2_STREAM7), | ||
| 34 | interrupt::take!(DMA2_STREAM2), | ||
| 35 | interrupt::take!(USART1), | ||
| 36 | dp.DMA2, | ||
| 37 | dp.USART1, | ||
| 38 | config::Parity::ParityNone, | ||
| 39 | 9600.bps(), | ||
| 40 | clocks, | ||
| 41 | ); | ||
| 42 | |||
| 43 | let buf = singleton!(: [u8; 30] = [0; 30]).unwrap(); | ||
| 44 | |||
| 45 | buf[5] = 0x01; | ||
| 46 | |||
| 47 | serial.send(buf).await; | ||
| 48 | } | ||
| 49 | |||
| 50 | static EXECUTOR: Forever<Executor> = Forever::new(); | ||
| 51 | |||
| 52 | #[entry] | ||
| 53 | fn main() -> ! { | ||
| 54 | let dp = stm32::Peripherals::take().unwrap(); | ||
| 55 | let cp = cortex_m::peripheral::Peripherals::take().unwrap(); | ||
| 56 | |||
| 57 | let executor = EXECUTOR.put(Executor::new(cortex_m::asm::sev)); | ||
| 58 | executor.spawn(run(dp, cp)); | ||
| 59 | |||
| 60 | loop { | ||
| 61 | executor.run(); | ||
| 62 | cortex_m::asm::wfe(); | ||
| 63 | } | ||
| 64 | } | ||
diff --git a/embassy-stm32f4/Cargo.toml b/embassy-stm32f4/Cargo.toml new file mode 100644 index 000000000..44cf3db9d --- /dev/null +++ b/embassy-stm32f4/Cargo.toml | |||
| @@ -0,0 +1,43 @@ | |||
| 1 | [package] | ||
| 2 | name = "embassy-stm32f4" | ||
| 3 | version = "0.1.0" | ||
| 4 | authors = ["Dario Nieuwenhuis <[email protected]>"] | ||
| 5 | edition = "2018" | ||
| 6 | |||
| 7 | [features] | ||
| 8 | defmt-trace = [ ] | ||
| 9 | defmt-debug = [ ] | ||
| 10 | defmt-info = [ ] | ||
| 11 | defmt-warn = [ ] | ||
| 12 | defmt-error = [ ] | ||
| 13 | |||
| 14 | stm32f401 = ["stm32f4xx-hal/stm32f401"] | ||
| 15 | stm32f405 = ["stm32f4xx-hal/stm32f405"] | ||
| 16 | stm32f407 = ["stm32f4xx-hal/stm32f407"] | ||
| 17 | stm32f410 = ["stm32f4xx-hal/stm32f410"] | ||
| 18 | stm32f411 = ["stm32f4xx-hal/stm32f411"] | ||
| 19 | stm32f412 = ["stm32f4xx-hal/stm32f412"] | ||
| 20 | stm32f413 = ["stm32f4xx-hal/stm32f413"] | ||
| 21 | stm32f415 = ["stm32f4xx-hal/stm32f405"] | ||
| 22 | stm32f417 = ["stm32f4xx-hal/stm32f407"] | ||
| 23 | stm32f423 = ["stm32f4xx-hal/stm32f413"] | ||
| 24 | stm32f427 = ["stm32f4xx-hal/stm32f427"] | ||
| 25 | stm32f429 = ["stm32f4xx-hal/stm32f429"] | ||
| 26 | stm32f437 = ["stm32f4xx-hal/stm32f427"] | ||
| 27 | stm32f439 = ["stm32f4xx-hal/stm32f429"] | ||
| 28 | stm32f446 = ["stm32f4xx-hal/stm32f446"] | ||
| 29 | stm32f469 = ["stm32f4xx-hal/stm32f469"] | ||
| 30 | stm32f479 = ["stm32f4xx-hal/stm32f469"] | ||
| 31 | |||
| 32 | default = ["stm32f405"] | ||
| 33 | |||
| 34 | [dependencies] | ||
| 35 | embassy = { version = "0.1.0", path = "../embassy" } | ||
| 36 | |||
| 37 | defmt = { version = "0.1.3", optional = true } | ||
| 38 | log = { version = "0.4.11", optional = true } | ||
| 39 | cortex-m-rt = "0.6.13" | ||
| 40 | cortex-m = { version = "0.6.4" } | ||
| 41 | embedded-hal = { version = "0.2.4" } | ||
| 42 | embedded-dma = { version = "0.1.2" } | ||
| 43 | stm32f4xx-hal = { version = "0.8.3", features = ["rt"], git = "https://github.com/stm32-rs/stm32f4xx-hal.git"} | ||
diff --git a/embassy-stm32f4/src/fmt.rs b/embassy-stm32f4/src/fmt.rs new file mode 100644 index 000000000..4da69766c --- /dev/null +++ b/embassy-stm32f4/src/fmt.rs | |||
| @@ -0,0 +1,118 @@ | |||
| 1 | #![macro_use] | ||
| 2 | |||
| 3 | #[cfg(all(feature = "defmt", feature = "log"))] | ||
| 4 | compile_error!("You may not enable both `defmt` and `log` features."); | ||
| 5 | |||
| 6 | pub use fmt::*; | ||
| 7 | |||
| 8 | #[cfg(feature = "defmt")] | ||
| 9 | mod fmt { | ||
| 10 | pub use defmt::{ | ||
| 11 | assert, assert_eq, assert_ne, debug, debug_assert, debug_assert_eq, debug_assert_ne, error, | ||
| 12 | info, panic, todo, trace, unreachable, unwrap, warn, | ||
| 13 | }; | ||
| 14 | } | ||
| 15 | |||
| 16 | #[cfg(feature = "log")] | ||
| 17 | mod fmt { | ||
| 18 | pub use core::{ | ||
| 19 | assert, assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, panic, todo, | ||
| 20 | unreachable, | ||
| 21 | }; | ||
| 22 | pub use log::{debug, error, info, trace, warn}; | ||
| 23 | } | ||
| 24 | |||
| 25 | #[cfg(not(any(feature = "defmt", feature = "log")))] | ||
| 26 | mod fmt { | ||
| 27 | #![macro_use] | ||
| 28 | |||
| 29 | pub use core::{ | ||
| 30 | assert, assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, panic, todo, | ||
| 31 | unreachable, | ||
| 32 | }; | ||
| 33 | |||
| 34 | #[macro_export] | ||
| 35 | macro_rules! trace { | ||
| 36 | ($($msg:expr),+ $(,)?) => { | ||
| 37 | () | ||
| 38 | }; | ||
| 39 | } | ||
| 40 | |||
| 41 | #[macro_export] | ||
| 42 | macro_rules! debug { | ||
| 43 | ($($msg:expr),+ $(,)?) => { | ||
| 44 | () | ||
| 45 | }; | ||
| 46 | } | ||
| 47 | |||
| 48 | #[macro_export] | ||
| 49 | macro_rules! info { | ||
| 50 | ($($msg:expr),+ $(,)?) => { | ||
| 51 | () | ||
| 52 | }; | ||
| 53 | } | ||
| 54 | |||
| 55 | #[macro_export] | ||
| 56 | macro_rules! warn { | ||
| 57 | ($($msg:expr),+ $(,)?) => { | ||
| 58 | () | ||
| 59 | }; | ||
| 60 | } | ||
| 61 | |||
| 62 | #[macro_export] | ||
| 63 | macro_rules! error { | ||
| 64 | ($($msg:expr),+ $(,)?) => { | ||
| 65 | () | ||
| 66 | }; | ||
| 67 | } | ||
| 68 | } | ||
| 69 | |||
| 70 | #[cfg(not(feature = "defmt"))] | ||
| 71 | #[macro_export] | ||
| 72 | macro_rules! unwrap { | ||
| 73 | ($arg:expr) => { | ||
| 74 | match $crate::fmt::Try::into_result($arg) { | ||
| 75 | ::core::result::Result::Ok(t) => t, | ||
| 76 | ::core::result::Result::Err(e) => { | ||
| 77 | ::core::panic!("unwrap of `{}` failed: {:?}", ::core::stringify!($arg), e); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | }; | ||
| 81 | ($arg:expr, $($msg:expr),+ $(,)? ) => { | ||
| 82 | match $crate::fmt::Try::into_result($arg) { | ||
| 83 | ::core::result::Result::Ok(t) => t, | ||
| 84 | ::core::result::Result::Err(e) => { | ||
| 85 | ::core::panic!("unwrap of `{}` failed: {}: {:?}", ::core::stringify!($arg), ::core::format_args!($($msg,)*), e); | ||
| 86 | } | ||
| 87 | } | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||
| 92 | pub struct NoneError; | ||
| 93 | |||
| 94 | pub trait Try { | ||
| 95 | type Ok; | ||
| 96 | type Error; | ||
| 97 | fn into_result(self) -> Result<Self::Ok, Self::Error>; | ||
| 98 | } | ||
| 99 | |||
| 100 | impl<T> Try for Option<T> { | ||
| 101 | type Ok = T; | ||
| 102 | type Error = NoneError; | ||
| 103 | |||
| 104 | #[inline] | ||
| 105 | fn into_result(self) -> Result<T, NoneError> { | ||
| 106 | self.ok_or(NoneError) | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | impl<T, E> Try for Result<T, E> { | ||
| 111 | type Ok = T; | ||
| 112 | type Error = E; | ||
| 113 | |||
| 114 | #[inline] | ||
| 115 | fn into_result(self) -> Self { | ||
| 116 | self | ||
| 117 | } | ||
| 118 | } | ||
diff --git a/embassy-stm32f4/src/interrupt.rs b/embassy-stm32f4/src/interrupt.rs new file mode 100644 index 000000000..502d666ee --- /dev/null +++ b/embassy-stm32f4/src/interrupt.rs | |||
| @@ -0,0 +1,193 @@ | |||
| 1 | //! Interrupt management | ||
| 2 | //! | ||
| 3 | //! This module implements an API for managing interrupts compatible with | ||
| 4 | //! nrf_softdevice::interrupt. Intended for switching between the two at compile-time. | ||
| 5 | |||
| 6 | use core::sync::atomic::{compiler_fence, Ordering}; | ||
| 7 | |||
| 8 | use crate::pac::NVIC_PRIO_BITS; | ||
| 9 | |||
| 10 | // Re-exports | ||
| 11 | pub use crate::pac::Interrupt; | ||
| 12 | pub use crate::pac::Interrupt::*; // needed for cortex-m-rt #[interrupt] | ||
| 13 | pub use cortex_m::interrupt::{CriticalSection, Mutex}; | ||
| 14 | pub use embassy::interrupt::{declare, take, OwnedInterrupt}; | ||
| 15 | |||
| 16 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)] | ||
| 17 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] | ||
| 18 | #[repr(u8)] | ||
| 19 | pub enum Priority { | ||
| 20 | Level0 = 0, | ||
| 21 | Level1 = 1, | ||
| 22 | Level2 = 2, | ||
| 23 | Level3 = 3, | ||
| 24 | Level4 = 4, | ||
| 25 | Level5 = 5, | ||
| 26 | Level6 = 6, | ||
| 27 | Level7 = 7, | ||
| 28 | Level8 = 8, | ||
| 29 | Level9 = 9, | ||
| 30 | Level10 = 10, | ||
| 31 | Level11 = 11, | ||
| 32 | Level12 = 12, | ||
| 33 | Level13 = 13, | ||
| 34 | Level14 = 14, | ||
| 35 | Level15 = 15, | ||
| 36 | } | ||
| 37 | |||
| 38 | impl From<u8> for Priority { | ||
| 39 | fn from(priority: u8) -> Self { | ||
| 40 | match priority >> (8 - NVIC_PRIO_BITS) { | ||
| 41 | 0 => Self::Level0, | ||
| 42 | 1 => Self::Level1, | ||
| 43 | 2 => Self::Level2, | ||
| 44 | 3 => Self::Level3, | ||
| 45 | 4 => Self::Level4, | ||
| 46 | 5 => Self::Level5, | ||
| 47 | 6 => Self::Level6, | ||
| 48 | 7 => Self::Level7, | ||
| 49 | 8 => Self::Level8, | ||
| 50 | 9 => Self::Level9, | ||
| 51 | 10 => Self::Level10, | ||
| 52 | 11 => Self::Level11, | ||
| 53 | 12 => Self::Level12, | ||
| 54 | 13 => Self::Level13, | ||
| 55 | 14 => Self::Level14, | ||
| 56 | 15 => Self::Level15, | ||
| 57 | _ => unreachable!(), | ||
| 58 | } | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | impl From<Priority> for u8 { | ||
| 63 | fn from(p: Priority) -> Self { | ||
| 64 | (p as u8) << (8 - NVIC_PRIO_BITS) | ||
| 65 | } | ||
| 66 | } | ||
| 67 | |||
| 68 | #[inline] | ||
| 69 | pub fn free<F, R>(f: F) -> R | ||
| 70 | where | ||
| 71 | F: FnOnce(&CriticalSection) -> R, | ||
| 72 | { | ||
| 73 | unsafe { | ||
| 74 | // TODO: assert that we're in privileged level | ||
| 75 | // Needed because disabling irqs in non-privileged level is a noop, which would break safety. | ||
| 76 | |||
| 77 | let primask: u32; | ||
| 78 | asm!("mrs {}, PRIMASK", out(reg) primask); | ||
| 79 | |||
| 80 | asm!("cpsid i"); | ||
| 81 | |||
| 82 | // Prevent compiler from reordering operations inside/outside the critical section. | ||
| 83 | compiler_fence(Ordering::SeqCst); | ||
| 84 | |||
| 85 | let r = f(&CriticalSection::new()); | ||
| 86 | |||
| 87 | compiler_fence(Ordering::SeqCst); | ||
| 88 | |||
| 89 | if primask & 1 == 0 { | ||
| 90 | asm!("cpsie i"); | ||
| 91 | } | ||
| 92 | |||
| 93 | r | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | #[cfg(feature = "stm32f405")] | ||
| 98 | mod irqs { | ||
| 99 | use super::*; | ||
| 100 | declare!(WWDG); | ||
| 101 | declare!(PVD); | ||
| 102 | declare!(TAMP_STAMP); | ||
| 103 | declare!(RTC_WKUP); | ||
| 104 | // declare!(FLASH); | ||
| 105 | declare!(RCC); | ||
| 106 | declare!(EXTI0); | ||
| 107 | declare!(EXTI1); | ||
| 108 | declare!(EXTI2); | ||
| 109 | declare!(EXTI3); | ||
| 110 | declare!(EXTI4); | ||
| 111 | declare!(DMA1_STREAM0); | ||
| 112 | declare!(DMA1_STREAM1); | ||
| 113 | declare!(DMA1_STREAM2); | ||
| 114 | declare!(DMA1_STREAM3); | ||
| 115 | declare!(DMA1_STREAM4); | ||
| 116 | declare!(DMA1_STREAM5); | ||
| 117 | declare!(DMA1_STREAM6); | ||
| 118 | declare!(ADC); | ||
| 119 | declare!(CAN1_TX); | ||
| 120 | declare!(CAN1_RX0); | ||
| 121 | declare!(CAN1_RX1); | ||
| 122 | declare!(CAN1_SCE); | ||
| 123 | declare!(EXTI9_5); | ||
| 124 | declare!(TIM1_BRK_TIM9); | ||
| 125 | declare!(TIM1_UP_TIM10); | ||
| 126 | declare!(TIM1_TRG_COM_TIM11); | ||
| 127 | declare!(TIM1_CC); | ||
| 128 | declare!(TIM2); | ||
| 129 | declare!(TIM3); | ||
| 130 | declare!(TIM4); | ||
| 131 | declare!(I2C1_EV); | ||
| 132 | declare!(I2C1_ER); | ||
| 133 | declare!(I2C2_EV); | ||
| 134 | declare!(I2C2_ER); | ||
| 135 | declare!(SPI1); | ||
| 136 | declare!(SPI2); | ||
| 137 | declare!(USART1); | ||
| 138 | declare!(USART2); | ||
| 139 | declare!(USART3); | ||
| 140 | declare!(EXTI15_10); | ||
| 141 | declare!(RTC_ALARM); | ||
| 142 | declare!(OTG_FS_WKUP); | ||
| 143 | declare!(TIM8_BRK_TIM12); | ||
| 144 | declare!(TIM8_UP_TIM13); | ||
| 145 | declare!(TIM8_TRG_COM_TIM14); | ||
| 146 | declare!(TIM8_CC); | ||
| 147 | declare!(DMA1_STREAM7); | ||
| 148 | // declare!(FMC); | ||
| 149 | declare!(SDIO); | ||
| 150 | declare!(TIM5); | ||
| 151 | declare!(SPI3); | ||
| 152 | declare!(UART4); | ||
| 153 | declare!(UART5); | ||
| 154 | declare!(TIM6_DAC); | ||
| 155 | declare!(TIM7); | ||
| 156 | declare!(DMA2_STREAM0); | ||
| 157 | declare!(DMA2_STREAM1); | ||
| 158 | declare!(DMA2_STREAM2); | ||
| 159 | declare!(DMA2_STREAM3); | ||
| 160 | declare!(DMA2_STREAM4); | ||
| 161 | declare!(ETH); | ||
| 162 | declare!(ETH_WKUP); | ||
| 163 | declare!(CAN2_TX); | ||
| 164 | declare!(CAN2_RX0); | ||
| 165 | declare!(CAN2_RX1); | ||
| 166 | declare!(CAN2_SCE); | ||
| 167 | declare!(OTG_FS); | ||
| 168 | declare!(DMA2_STREAM5); | ||
| 169 | declare!(DMA2_STREAM6); | ||
| 170 | declare!(DMA2_STREAM7); | ||
| 171 | declare!(USART6); | ||
| 172 | declare!(I2C3_EV); | ||
| 173 | declare!(I2C3_ER); | ||
| 174 | declare!(OTG_HS_EP1_OUT); | ||
| 175 | declare!(OTG_HS_EP1_IN); | ||
| 176 | declare!(OTG_HS_WKUP); | ||
| 177 | declare!(OTG_HS); | ||
| 178 | declare!(DCMI); | ||
| 179 | declare!(CRYP); | ||
| 180 | declare!(HASH_RNG); | ||
| 181 | declare!(FPU); | ||
| 182 | // declare!(UART7); | ||
| 183 | // declare!(UART8); | ||
| 184 | // declare!(SPI4); | ||
| 185 | // declare!(SPI5); | ||
| 186 | // declare!(SPI6); | ||
| 187 | // declare!(SAI1); | ||
| 188 | declare!(LCD_TFT); | ||
| 189 | declare!(LCD_TFT_1); | ||
| 190 | // declare!(DMA2D); | ||
| 191 | } | ||
| 192 | |||
| 193 | pub use irqs::*; | ||
diff --git a/embassy-stm32f4/src/lib.rs b/embassy-stm32f4/src/lib.rs new file mode 100644 index 000000000..0f4a70bba --- /dev/null +++ b/embassy-stm32f4/src/lib.rs | |||
| @@ -0,0 +1,317 @@ | |||
| 1 | #![no_std] | ||
| 2 | #![feature(generic_associated_types)] | ||
| 3 | #![feature(asm)] | ||
| 4 | #![feature(type_alias_impl_trait)] | ||
| 5 | #![feature(let_chains)] | ||
| 6 | |||
| 7 | #[cfg(not(any( | ||
| 8 | feature = "stm32f401", | ||
| 9 | feature = "stm32f405", | ||
| 10 | feature = "stm32f407", | ||
| 11 | feature = "stm32f410", | ||
| 12 | feature = "stm32f411", | ||
| 13 | feature = "stm32f412", | ||
| 14 | feature = "stm32f413", | ||
| 15 | feature = "stm32f415", | ||
| 16 | feature = "stm32f417", | ||
| 17 | feature = "stm32f423", | ||
| 18 | feature = "stm32f427", | ||
| 19 | feature = "stm32f429", | ||
| 20 | feature = "stm32f437", | ||
| 21 | feature = "stm32f439", | ||
| 22 | feature = "stm32f446", | ||
| 23 | feature = "stm32f469", | ||
| 24 | feature = "stm32f479", | ||
| 25 | )))] | ||
| 26 | compile_error!( | ||
| 27 | "No chip feature activated. You must activate exactly one of the following features: " | ||
| 28 | ); | ||
| 29 | |||
| 30 | #[cfg(any( | ||
| 31 | all(feature = "stm32f401", feature = "stm32f405"), | ||
| 32 | all(feature = "stm32f401", feature = "stm32f407"), | ||
| 33 | all(feature = "stm32f401", feature = "stm32f410"), | ||
| 34 | all(feature = "stm32f401", feature = "stm32f411"), | ||
| 35 | all(feature = "stm32f401", feature = "stm32f412"), | ||
| 36 | all(feature = "stm32f401", feature = "stm32f413"), | ||
| 37 | all(feature = "stm32f401", feature = "stm32f415"), | ||
| 38 | all(feature = "stm32f401", feature = "stm32f417"), | ||
| 39 | all(feature = "stm32f401", feature = "stm32f423"), | ||
| 40 | all(feature = "stm32f401", feature = "stm32f427"), | ||
| 41 | all(feature = "stm32f401", feature = "stm32f429"), | ||
| 42 | all(feature = "stm32f401", feature = "stm32f437"), | ||
| 43 | all(feature = "stm32f401", feature = "stm32f439"), | ||
| 44 | all(feature = "stm32f401", feature = "stm32f446"), | ||
| 45 | all(feature = "stm32f401", feature = "stm32f469"), | ||
| 46 | all(feature = "stm32f401", feature = "stm32f479"), | ||
| 47 | all(feature = "stm32f405", feature = "stm32f401"), | ||
| 48 | all(feature = "stm32f405", feature = "stm32f407"), | ||
| 49 | all(feature = "stm32f405", feature = "stm32f410"), | ||
| 50 | all(feature = "stm32f405", feature = "stm32f411"), | ||
| 51 | all(feature = "stm32f405", feature = "stm32f412"), | ||
| 52 | all(feature = "stm32f405", feature = "stm32f413"), | ||
| 53 | all(feature = "stm32f405", feature = "stm32f415"), | ||
| 54 | all(feature = "stm32f405", feature = "stm32f417"), | ||
| 55 | all(feature = "stm32f405", feature = "stm32f423"), | ||
| 56 | all(feature = "stm32f405", feature = "stm32f427"), | ||
| 57 | all(feature = "stm32f405", feature = "stm32f429"), | ||
| 58 | all(feature = "stm32f405", feature = "stm32f437"), | ||
| 59 | all(feature = "stm32f405", feature = "stm32f439"), | ||
| 60 | all(feature = "stm32f405", feature = "stm32f446"), | ||
| 61 | all(feature = "stm32f405", feature = "stm32f469"), | ||
| 62 | all(feature = "stm32f405", feature = "stm32f479"), | ||
| 63 | all(feature = "stm32f407", feature = "stm32f401"), | ||
| 64 | all(feature = "stm32f407", feature = "stm32f405"), | ||
| 65 | all(feature = "stm32f407", feature = "stm32f410"), | ||
| 66 | all(feature = "stm32f407", feature = "stm32f411"), | ||
| 67 | all(feature = "stm32f407", feature = "stm32f412"), | ||
| 68 | all(feature = "stm32f407", feature = "stm32f413"), | ||
| 69 | all(feature = "stm32f407", feature = "stm32f415"), | ||
| 70 | all(feature = "stm32f407", feature = "stm32f417"), | ||
| 71 | all(feature = "stm32f407", feature = "stm32f423"), | ||
| 72 | all(feature = "stm32f407", feature = "stm32f427"), | ||
| 73 | all(feature = "stm32f407", feature = "stm32f429"), | ||
| 74 | all(feature = "stm32f407", feature = "stm32f437"), | ||
| 75 | all(feature = "stm32f407", feature = "stm32f439"), | ||
| 76 | all(feature = "stm32f407", feature = "stm32f446"), | ||
| 77 | all(feature = "stm32f407", feature = "stm32f469"), | ||
| 78 | all(feature = "stm32f407", feature = "stm32f479"), | ||
| 79 | all(feature = "stm32f410", feature = "stm32f401"), | ||
| 80 | all(feature = "stm32f410", feature = "stm32f405"), | ||
| 81 | all(feature = "stm32f410", feature = "stm32f407"), | ||
| 82 | all(feature = "stm32f410", feature = "stm32f411"), | ||
| 83 | all(feature = "stm32f410", feature = "stm32f412"), | ||
| 84 | all(feature = "stm32f410", feature = "stm32f413"), | ||
| 85 | all(feature = "stm32f410", feature = "stm32f415"), | ||
| 86 | all(feature = "stm32f410", feature = "stm32f417"), | ||
| 87 | all(feature = "stm32f410", feature = "stm32f423"), | ||
| 88 | all(feature = "stm32f410", feature = "stm32f427"), | ||
| 89 | all(feature = "stm32f410", feature = "stm32f429"), | ||
| 90 | all(feature = "stm32f410", feature = "stm32f437"), | ||
| 91 | all(feature = "stm32f410", feature = "stm32f439"), | ||
| 92 | all(feature = "stm32f410", feature = "stm32f446"), | ||
| 93 | all(feature = "stm32f410", feature = "stm32f469"), | ||
| 94 | all(feature = "stm32f410", feature = "stm32f479"), | ||
| 95 | all(feature = "stm32f411", feature = "stm32f401"), | ||
| 96 | all(feature = "stm32f411", feature = "stm32f405"), | ||
| 97 | all(feature = "stm32f411", feature = "stm32f407"), | ||
| 98 | all(feature = "stm32f411", feature = "stm32f410"), | ||
| 99 | all(feature = "stm32f411", feature = "stm32f412"), | ||
| 100 | all(feature = "stm32f411", feature = "stm32f413"), | ||
| 101 | all(feature = "stm32f411", feature = "stm32f415"), | ||
| 102 | all(feature = "stm32f411", feature = "stm32f417"), | ||
| 103 | all(feature = "stm32f411", feature = "stm32f423"), | ||
| 104 | all(feature = "stm32f411", feature = "stm32f427"), | ||
| 105 | all(feature = "stm32f411", feature = "stm32f429"), | ||
| 106 | all(feature = "stm32f411", feature = "stm32f437"), | ||
| 107 | all(feature = "stm32f411", feature = "stm32f439"), | ||
| 108 | all(feature = "stm32f411", feature = "stm32f446"), | ||
| 109 | all(feature = "stm32f411", feature = "stm32f469"), | ||
| 110 | all(feature = "stm32f411", feature = "stm32f479"), | ||
| 111 | all(feature = "stm32f412", feature = "stm32f401"), | ||
| 112 | all(feature = "stm32f412", feature = "stm32f405"), | ||
| 113 | all(feature = "stm32f412", feature = "stm32f407"), | ||
| 114 | all(feature = "stm32f412", feature = "stm32f410"), | ||
| 115 | all(feature = "stm32f412", feature = "stm32f411"), | ||
| 116 | all(feature = "stm32f412", feature = "stm32f413"), | ||
| 117 | all(feature = "stm32f412", feature = "stm32f415"), | ||
| 118 | all(feature = "stm32f412", feature = "stm32f417"), | ||
| 119 | all(feature = "stm32f412", feature = "stm32f423"), | ||
| 120 | all(feature = "stm32f412", feature = "stm32f427"), | ||
| 121 | all(feature = "stm32f412", feature = "stm32f429"), | ||
| 122 | all(feature = "stm32f412", feature = "stm32f437"), | ||
| 123 | all(feature = "stm32f412", feature = "stm32f439"), | ||
| 124 | all(feature = "stm32f412", feature = "stm32f446"), | ||
| 125 | all(feature = "stm32f412", feature = "stm32f469"), | ||
| 126 | all(feature = "stm32f412", feature = "stm32f479"), | ||
| 127 | all(feature = "stm32f413", feature = "stm32f401"), | ||
| 128 | all(feature = "stm32f413", feature = "stm32f405"), | ||
| 129 | all(feature = "stm32f413", feature = "stm32f407"), | ||
| 130 | all(feature = "stm32f413", feature = "stm32f410"), | ||
| 131 | all(feature = "stm32f413", feature = "stm32f411"), | ||
| 132 | all(feature = "stm32f413", feature = "stm32f412"), | ||
| 133 | all(feature = "stm32f413", feature = "stm32f415"), | ||
| 134 | all(feature = "stm32f413", feature = "stm32f417"), | ||
| 135 | all(feature = "stm32f413", feature = "stm32f423"), | ||
| 136 | all(feature = "stm32f413", feature = "stm32f427"), | ||
| 137 | all(feature = "stm32f413", feature = "stm32f429"), | ||
| 138 | all(feature = "stm32f413", feature = "stm32f437"), | ||
| 139 | all(feature = "stm32f413", feature = "stm32f439"), | ||
| 140 | all(feature = "stm32f413", feature = "stm32f446"), | ||
| 141 | all(feature = "stm32f413", feature = "stm32f469"), | ||
| 142 | all(feature = "stm32f413", feature = "stm32f479"), | ||
| 143 | all(feature = "stm32f415", feature = "stm32f401"), | ||
| 144 | all(feature = "stm32f415", feature = "stm32f405"), | ||
| 145 | all(feature = "stm32f415", feature = "stm32f407"), | ||
| 146 | all(feature = "stm32f415", feature = "stm32f410"), | ||
| 147 | all(feature = "stm32f415", feature = "stm32f411"), | ||
| 148 | all(feature = "stm32f415", feature = "stm32f412"), | ||
| 149 | all(feature = "stm32f415", feature = "stm32f413"), | ||
| 150 | all(feature = "stm32f415", feature = "stm32f417"), | ||
| 151 | all(feature = "stm32f415", feature = "stm32f423"), | ||
| 152 | all(feature = "stm32f415", feature = "stm32f427"), | ||
| 153 | all(feature = "stm32f415", feature = "stm32f429"), | ||
| 154 | all(feature = "stm32f415", feature = "stm32f437"), | ||
| 155 | all(feature = "stm32f415", feature = "stm32f439"), | ||
| 156 | all(feature = "stm32f415", feature = "stm32f446"), | ||
| 157 | all(feature = "stm32f415", feature = "stm32f469"), | ||
| 158 | all(feature = "stm32f415", feature = "stm32f479"), | ||
| 159 | all(feature = "stm32f417", feature = "stm32f401"), | ||
| 160 | all(feature = "stm32f417", feature = "stm32f405"), | ||
| 161 | all(feature = "stm32f417", feature = "stm32f407"), | ||
| 162 | all(feature = "stm32f417", feature = "stm32f410"), | ||
| 163 | all(feature = "stm32f417", feature = "stm32f411"), | ||
| 164 | all(feature = "stm32f417", feature = "stm32f412"), | ||
| 165 | all(feature = "stm32f417", feature = "stm32f413"), | ||
| 166 | all(feature = "stm32f417", feature = "stm32f415"), | ||
| 167 | all(feature = "stm32f417", feature = "stm32f423"), | ||
| 168 | all(feature = "stm32f417", feature = "stm32f427"), | ||
| 169 | all(feature = "stm32f417", feature = "stm32f429"), | ||
| 170 | all(feature = "stm32f417", feature = "stm32f437"), | ||
| 171 | all(feature = "stm32f417", feature = "stm32f439"), | ||
| 172 | all(feature = "stm32f417", feature = "stm32f446"), | ||
| 173 | all(feature = "stm32f417", feature = "stm32f469"), | ||
| 174 | all(feature = "stm32f417", feature = "stm32f479"), | ||
| 175 | all(feature = "stm32f423", feature = "stm32f401"), | ||
| 176 | all(feature = "stm32f423", feature = "stm32f405"), | ||
| 177 | all(feature = "stm32f423", feature = "stm32f407"), | ||
| 178 | all(feature = "stm32f423", feature = "stm32f410"), | ||
| 179 | all(feature = "stm32f423", feature = "stm32f411"), | ||
| 180 | all(feature = "stm32f423", feature = "stm32f412"), | ||
| 181 | all(feature = "stm32f423", feature = "stm32f413"), | ||
| 182 | all(feature = "stm32f423", feature = "stm32f415"), | ||
| 183 | all(feature = "stm32f423", feature = "stm32f417"), | ||
| 184 | all(feature = "stm32f423", feature = "stm32f427"), | ||
| 185 | all(feature = "stm32f423", feature = "stm32f429"), | ||
| 186 | all(feature = "stm32f423", feature = "stm32f437"), | ||
| 187 | all(feature = "stm32f423", feature = "stm32f439"), | ||
| 188 | all(feature = "stm32f423", feature = "stm32f446"), | ||
| 189 | all(feature = "stm32f423", feature = "stm32f469"), | ||
| 190 | all(feature = "stm32f423", feature = "stm32f479"), | ||
| 191 | all(feature = "stm32f427", feature = "stm32f401"), | ||
| 192 | all(feature = "stm32f427", feature = "stm32f405"), | ||
| 193 | all(feature = "stm32f427", feature = "stm32f407"), | ||
| 194 | all(feature = "stm32f427", feature = "stm32f410"), | ||
| 195 | all(feature = "stm32f427", feature = "stm32f411"), | ||
| 196 | all(feature = "stm32f427", feature = "stm32f412"), | ||
| 197 | all(feature = "stm32f427", feature = "stm32f413"), | ||
| 198 | all(feature = "stm32f427", feature = "stm32f415"), | ||
| 199 | all(feature = "stm32f427", feature = "stm32f417"), | ||
| 200 | all(feature = "stm32f427", feature = "stm32f423"), | ||
| 201 | all(feature = "stm32f427", feature = "stm32f429"), | ||
| 202 | all(feature = "stm32f427", feature = "stm32f437"), | ||
| 203 | all(feature = "stm32f427", feature = "stm32f439"), | ||
| 204 | all(feature = "stm32f427", feature = "stm32f446"), | ||
| 205 | all(feature = "stm32f427", feature = "stm32f469"), | ||
| 206 | all(feature = "stm32f427", feature = "stm32f479"), | ||
| 207 | all(feature = "stm32f429", feature = "stm32f401"), | ||
| 208 | all(feature = "stm32f429", feature = "stm32f405"), | ||
| 209 | all(feature = "stm32f429", feature = "stm32f407"), | ||
| 210 | all(feature = "stm32f429", feature = "stm32f410"), | ||
| 211 | all(feature = "stm32f429", feature = "stm32f411"), | ||
| 212 | all(feature = "stm32f429", feature = "stm32f412"), | ||
| 213 | all(feature = "stm32f429", feature = "stm32f413"), | ||
| 214 | all(feature = "stm32f429", feature = "stm32f415"), | ||
| 215 | all(feature = "stm32f429", feature = "stm32f417"), | ||
| 216 | all(feature = "stm32f429", feature = "stm32f423"), | ||
| 217 | all(feature = "stm32f429", feature = "stm32f427"), | ||
| 218 | all(feature = "stm32f429", feature = "stm32f437"), | ||
| 219 | all(feature = "stm32f429", feature = "stm32f439"), | ||
| 220 | all(feature = "stm32f429", feature = "stm32f446"), | ||
| 221 | all(feature = "stm32f429", feature = "stm32f469"), | ||
| 222 | all(feature = "stm32f429", feature = "stm32f479"), | ||
| 223 | all(feature = "stm32f437", feature = "stm32f401"), | ||
| 224 | all(feature = "stm32f437", feature = "stm32f405"), | ||
| 225 | all(feature = "stm32f437", feature = "stm32f407"), | ||
| 226 | all(feature = "stm32f437", feature = "stm32f410"), | ||
| 227 | all(feature = "stm32f437", feature = "stm32f411"), | ||
| 228 | all(feature = "stm32f437", feature = "stm32f412"), | ||
| 229 | all(feature = "stm32f437", feature = "stm32f413"), | ||
| 230 | all(feature = "stm32f437", feature = "stm32f415"), | ||
| 231 | all(feature = "stm32f437", feature = "stm32f417"), | ||
| 232 | all(feature = "stm32f437", feature = "stm32f423"), | ||
| 233 | all(feature = "stm32f437", feature = "stm32f427"), | ||
| 234 | all(feature = "stm32f437", feature = "stm32f429"), | ||
| 235 | all(feature = "stm32f437", feature = "stm32f439"), | ||
| 236 | all(feature = "stm32f437", feature = "stm32f446"), | ||
| 237 | all(feature = "stm32f437", feature = "stm32f469"), | ||
| 238 | all(feature = "stm32f437", feature = "stm32f479"), | ||
| 239 | all(feature = "stm32f439", feature = "stm32f401"), | ||
| 240 | all(feature = "stm32f439", feature = "stm32f405"), | ||
| 241 | all(feature = "stm32f439", feature = "stm32f407"), | ||
| 242 | all(feature = "stm32f439", feature = "stm32f410"), | ||
| 243 | all(feature = "stm32f439", feature = "stm32f411"), | ||
| 244 | all(feature = "stm32f439", feature = "stm32f412"), | ||
| 245 | all(feature = "stm32f439", feature = "stm32f413"), | ||
| 246 | all(feature = "stm32f439", feature = "stm32f415"), | ||
| 247 | all(feature = "stm32f439", feature = "stm32f417"), | ||
| 248 | all(feature = "stm32f439", feature = "stm32f423"), | ||
| 249 | all(feature = "stm32f439", feature = "stm32f427"), | ||
| 250 | all(feature = "stm32f439", feature = "stm32f429"), | ||
| 251 | all(feature = "stm32f439", feature = "stm32f437"), | ||
| 252 | all(feature = "stm32f439", feature = "stm32f446"), | ||
| 253 | all(feature = "stm32f439", feature = "stm32f469"), | ||
| 254 | all(feature = "stm32f439", feature = "stm32f479"), | ||
| 255 | all(feature = "stm32f446", feature = "stm32f401"), | ||
| 256 | all(feature = "stm32f446", feature = "stm32f405"), | ||
| 257 | all(feature = "stm32f446", feature = "stm32f407"), | ||
| 258 | all(feature = "stm32f446", feature = "stm32f410"), | ||
| 259 | all(feature = "stm32f446", feature = "stm32f411"), | ||
| 260 | all(feature = "stm32f446", feature = "stm32f412"), | ||
| 261 | all(feature = "stm32f446", feature = "stm32f413"), | ||
| 262 | all(feature = "stm32f446", feature = "stm32f415"), | ||
| 263 | all(feature = "stm32f446", feature = "stm32f417"), | ||
| 264 | all(feature = "stm32f446", feature = "stm32f423"), | ||
| 265 | all(feature = "stm32f446", feature = "stm32f427"), | ||
| 266 | all(feature = "stm32f446", feature = "stm32f429"), | ||
| 267 | all(feature = "stm32f446", feature = "stm32f437"), | ||
| 268 | all(feature = "stm32f446", feature = "stm32f439"), | ||
| 269 | all(feature = "stm32f446", feature = "stm32f469"), | ||
| 270 | all(feature = "stm32f446", feature = "stm32f479"), | ||
| 271 | all(feature = "stm32f469", feature = "stm32f401"), | ||
| 272 | all(feature = "stm32f469", feature = "stm32f405"), | ||
| 273 | all(feature = "stm32f469", feature = "stm32f407"), | ||
| 274 | all(feature = "stm32f469", feature = "stm32f410"), | ||
| 275 | all(feature = "stm32f469", feature = "stm32f411"), | ||
| 276 | all(feature = "stm32f469", feature = "stm32f412"), | ||
| 277 | all(feature = "stm32f469", feature = "stm32f413"), | ||
| 278 | all(feature = "stm32f469", feature = "stm32f415"), | ||
| 279 | all(feature = "stm32f469", feature = "stm32f417"), | ||
| 280 | all(feature = "stm32f469", feature = "stm32f423"), | ||
| 281 | all(feature = "stm32f469", feature = "stm32f427"), | ||
| 282 | all(feature = "stm32f469", feature = "stm32f429"), | ||
| 283 | all(feature = "stm32f469", feature = "stm32f437"), | ||
| 284 | all(feature = "stm32f469", feature = "stm32f439"), | ||
| 285 | all(feature = "stm32f469", feature = "stm32f446"), | ||
| 286 | all(feature = "stm32f469", feature = "stm32f479"), | ||
| 287 | all(feature = "stm32f479", feature = "stm32f401"), | ||
| 288 | all(feature = "stm32f479", feature = "stm32f405"), | ||
| 289 | all(feature = "stm32f479", feature = "stm32f407"), | ||
| 290 | all(feature = "stm32f479", feature = "stm32f410"), | ||
| 291 | all(feature = "stm32f479", feature = "stm32f411"), | ||
| 292 | all(feature = "stm32f479", feature = "stm32f412"), | ||
| 293 | all(feature = "stm32f479", feature = "stm32f413"), | ||
| 294 | all(feature = "stm32f479", feature = "stm32f415"), | ||
| 295 | all(feature = "stm32f479", feature = "stm32f417"), | ||
| 296 | all(feature = "stm32f479", feature = "stm32f423"), | ||
| 297 | all(feature = "stm32f479", feature = "stm32f427"), | ||
| 298 | all(feature = "stm32f479", feature = "stm32f429"), | ||
| 299 | all(feature = "stm32f479", feature = "stm32f437"), | ||
| 300 | all(feature = "stm32f479", feature = "stm32f439"), | ||
| 301 | all(feature = "stm32f479", feature = "stm32f446"), | ||
| 302 | all(feature = "stm32f479", feature = "stm32f469"), | ||
| 303 | ))] | ||
| 304 | compile_error!( | ||
| 305 | "Multile chip features activated. You must activate exactly one of the following features: " | ||
| 306 | ); | ||
| 307 | |||
| 308 | pub use stm32f4xx_hal as hal; | ||
| 309 | pub use stm32f4xx_hal::stm32 as pac; | ||
| 310 | |||
| 311 | // This mod MUST go first, so that the others see its macros. | ||
| 312 | pub(crate) mod fmt; | ||
| 313 | |||
| 314 | pub mod interrupt; | ||
| 315 | pub mod serial; | ||
| 316 | |||
| 317 | pub use cortex_m_rt::interrupt; | ||
diff --git a/embassy-stm32f4/src/serial.rs b/embassy-stm32f4/src/serial.rs new file mode 100644 index 000000000..cc55ef325 --- /dev/null +++ b/embassy-stm32f4/src/serial.rs | |||
| @@ -0,0 +1,224 @@ | |||
| 1 | //! Async low power Serial. | ||
| 2 | //! | ||
| 3 | //! The peripheral is autmatically enabled and disabled as required to save power. | ||
| 4 | //! Lowest power consumption can only be guaranteed if the send receive futures | ||
| 5 | //! are dropped correctly (e.g. not using `mem::forget()`). | ||
| 6 | |||
| 7 | use core::future::Future; | ||
| 8 | use core::ptr; | ||
| 9 | use core::sync::atomic::{self, Ordering}; | ||
| 10 | use core::task::{Context, Poll}; | ||
| 11 | |||
| 12 | use embassy::interrupt::OwnedInterrupt; | ||
| 13 | use embassy::util::Signal; | ||
| 14 | use embedded_dma::{StaticReadBuffer, StaticWriteBuffer, WriteBuffer}; | ||
| 15 | |||
| 16 | use crate::hal::dma::config::DmaConfig; | ||
| 17 | use crate::hal::dma::traits::{PeriAddress, Stream}; | ||
| 18 | use crate::hal::dma::{ | ||
| 19 | Channel4, MemoryToPeripheral, PeripheralToMemory, Stream2, Stream7, StreamsTuple, Transfer, | ||
| 20 | }; | ||
| 21 | use crate::hal::gpio::gpioa::{PA10, PA9}; | ||
| 22 | use crate::hal::gpio::{Alternate, AF7}; | ||
| 23 | use crate::hal::prelude::*; | ||
| 24 | use crate::hal::rcc::Clocks; | ||
| 25 | use crate::hal::serial::config::{ | ||
| 26 | Config as SerialConfig, DmaConfig as SerialDmaConfig, Parity, StopBits, WordLength, | ||
| 27 | }; | ||
| 28 | use crate::hal::serial::{Event as SerialEvent, Serial as HalSerial}; | ||
| 29 | use crate::hal::time::Bps; | ||
| 30 | |||
| 31 | use crate::interrupt; | ||
| 32 | |||
| 33 | use crate::pac::Interrupt; | ||
| 34 | use crate::pac::{DMA2, USART1}; | ||
| 35 | |||
| 36 | /// Interface to the Serial peripheral | ||
| 37 | pub struct Serial<USART: PeriAddress<MemSize = u8>, TSTREAM: Stream, RSTREAM: Stream> { | ||
| 38 | tx_stream: Option<TSTREAM>, | ||
| 39 | rx_stream: Option<RSTREAM>, | ||
| 40 | usart: Option<USART>, | ||
| 41 | tx_int: interrupt::DMA2_STREAM7Interrupt, | ||
| 42 | rx_int: interrupt::DMA2_STREAM2Interrupt, | ||
| 43 | usart_int: interrupt::USART1Interrupt, | ||
| 44 | } | ||
| 45 | |||
| 46 | struct State { | ||
| 47 | tx_int: Signal<()>, | ||
| 48 | rx_int: Signal<()>, | ||
| 49 | } | ||
| 50 | |||
| 51 | static STATE: State = State { | ||
| 52 | tx_int: Signal::new(), | ||
| 53 | rx_int: Signal::new(), | ||
| 54 | }; | ||
| 55 | |||
| 56 | static mut INSTANCE: *const Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> = ptr::null_mut(); | ||
| 57 | |||
| 58 | impl Serial<USART1, Stream7<DMA2>, Stream2<DMA2>> { | ||
| 59 | pub fn new( | ||
| 60 | txd: PA9<Alternate<AF7>>, | ||
| 61 | rxd: PA10<Alternate<AF7>>, | ||
| 62 | tx_int: interrupt::DMA2_STREAM7Interrupt, | ||
| 63 | rx_int: interrupt::DMA2_STREAM2Interrupt, | ||
| 64 | usart_int: interrupt::USART1Interrupt, | ||
| 65 | dma: DMA2, | ||
| 66 | usart: USART1, | ||
| 67 | parity: Parity, | ||
| 68 | baudrate: Bps, | ||
| 69 | clocks: Clocks, | ||
| 70 | ) -> Self { | ||
| 71 | let mut serial = HalSerial::usart1( | ||
| 72 | usart, | ||
| 73 | (txd, rxd), | ||
| 74 | SerialConfig { | ||
| 75 | baudrate: baudrate, | ||
| 76 | wordlength: WordLength::DataBits8, | ||
| 77 | parity: Parity::ParityNone, | ||
| 78 | stopbits: StopBits::STOP1, | ||
| 79 | dma: SerialDmaConfig::TxRx, | ||
| 80 | }, | ||
| 81 | clocks, | ||
| 82 | ) | ||
| 83 | .unwrap(); | ||
| 84 | |||
| 85 | serial.listen(SerialEvent::Idle); | ||
| 86 | // serial.listen(SerialEvent::Txe); | ||
| 87 | |||
| 88 | let (usart, _) = serial.release(); | ||
| 89 | |||
| 90 | // Register ISR | ||
| 91 | tx_int.set_handler(Self::on_tx_irq); | ||
| 92 | rx_int.set_handler(Self::on_rx_irq); | ||
| 93 | usart_int.set_handler(Self::on_rx_irq); | ||
| 94 | // usart_int.unpend(); | ||
| 95 | // usart_int.enable(); | ||
| 96 | |||
| 97 | let streams = StreamsTuple::new(dma); | ||
| 98 | |||
| 99 | Serial { | ||
| 100 | tx_stream: Some(streams.7), | ||
| 101 | rx_stream: Some(streams.2), | ||
| 102 | usart: Some(usart), | ||
| 103 | tx_int: tx_int, | ||
| 104 | rx_int: rx_int, | ||
| 105 | usart_int: usart_int, | ||
| 106 | } | ||
| 107 | } | ||
| 108 | |||
| 109 | unsafe fn on_tx_irq() { | ||
| 110 | let s = &(*INSTANCE); | ||
| 111 | |||
| 112 | s.tx_int.disable(); | ||
| 113 | |||
| 114 | STATE.tx_int.signal(()); | ||
| 115 | } | ||
| 116 | |||
| 117 | unsafe fn on_rx_irq() { | ||
| 118 | let s = &(*INSTANCE); | ||
| 119 | |||
| 120 | atomic::compiler_fence(Ordering::Acquire); | ||
| 121 | s.rx_int.disable(); | ||
| 122 | s.usart_int.disable(); | ||
| 123 | atomic::compiler_fence(Ordering::Release); | ||
| 124 | |||
| 125 | STATE.rx_int.signal(()); | ||
| 126 | } | ||
| 127 | |||
| 128 | unsafe fn on_usart_irq() { | ||
| 129 | let s = &(*INSTANCE); | ||
| 130 | |||
| 131 | atomic::compiler_fence(Ordering::Acquire); | ||
| 132 | s.rx_int.disable(); | ||
| 133 | s.usart_int.disable(); | ||
| 134 | atomic::compiler_fence(Ordering::Release); | ||
| 135 | |||
| 136 | STATE.rx_int.signal(()); | ||
| 137 | } | ||
| 138 | |||
| 139 | /// Sends serial data. | ||
| 140 | /// | ||
| 141 | /// `tx_buffer` is marked as static as per `embedded-dma` requirements. | ||
| 142 | /// It it safe to use a buffer with a non static lifetime if memory is not | ||
| 143 | /// reused until the future has finished. | ||
| 144 | pub fn send<'a, B: 'a>(&'a mut self, tx_buffer: B) -> impl Future<Output = ()> + 'a | ||
| 145 | where | ||
| 146 | B: StaticWriteBuffer<Word = u8>, | ||
| 147 | { | ||
| 148 | unsafe { INSTANCE = self }; | ||
| 149 | |||
| 150 | let tx_stream = self.tx_stream.take().unwrap(); | ||
| 151 | let usart = self.usart.take().unwrap(); | ||
| 152 | STATE.tx_int.reset(); | ||
| 153 | |||
| 154 | async move { | ||
| 155 | let mut tx_transfer = Transfer::init( | ||
| 156 | tx_stream, | ||
| 157 | usart, | ||
| 158 | tx_buffer, | ||
| 159 | None, | ||
| 160 | DmaConfig::default() | ||
| 161 | .transfer_complete_interrupt(true) | ||
| 162 | .memory_increment(true) | ||
| 163 | .double_buffer(false), | ||
| 164 | ); | ||
| 165 | |||
| 166 | self.tx_int.unpend(); | ||
| 167 | self.tx_int.enable(); | ||
| 168 | tx_transfer.start(|_usart| {}); | ||
| 169 | |||
| 170 | STATE.tx_int.wait().await; | ||
| 171 | |||
| 172 | let (tx_stream, usart, _buf, _) = tx_transfer.free(); | ||
| 173 | self.tx_stream.replace(tx_stream); | ||
| 174 | self.usart.replace(usart); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | /// Receives serial data. | ||
| 179 | /// | ||
| 180 | /// The future is pending until the buffer is completely filled. | ||
| 181 | /// A common pattern is to use [`stop()`](ReceiveFuture::stop) to cancel | ||
| 182 | /// unfinished transfers after a timeout to prevent lockup when no more data | ||
| 183 | /// is incoming. | ||
| 184 | /// | ||
| 185 | /// `rx_buffer` is marked as static as per `embedded-dma` requirements. | ||
| 186 | /// It it safe to use a buffer with a non static lifetime if memory is not | ||
| 187 | /// reused until the future has finished. | ||
| 188 | pub fn receive<'a, B: 'a>(&'a mut self, rx_buffer: B) -> impl Future<Output = B> + 'a | ||
| 189 | where | ||
| 190 | B: StaticWriteBuffer<Word = u8> + Unpin, | ||
| 191 | { | ||
| 192 | unsafe { INSTANCE = self }; | ||
| 193 | |||
| 194 | let rx_stream = self.rx_stream.take().unwrap(); | ||
| 195 | let usart = self.usart.take().unwrap(); | ||
| 196 | STATE.rx_int.reset(); | ||
| 197 | |||
| 198 | async move { | ||
| 199 | let mut rx_transfer = Transfer::init( | ||
| 200 | rx_stream, | ||
| 201 | usart, | ||
| 202 | rx_buffer, | ||
| 203 | None, | ||
| 204 | DmaConfig::default() | ||
| 205 | .transfer_complete_interrupt(true) | ||
| 206 | .memory_increment(true) | ||
| 207 | .double_buffer(false), | ||
| 208 | ); | ||
| 209 | |||
| 210 | self.rx_int.unpend(); | ||
| 211 | self.rx_int.enable(); | ||
| 212 | |||
| 213 | rx_transfer.start(|_usart| {}); | ||
| 214 | |||
| 215 | STATE.rx_int.wait().await; | ||
| 216 | |||
| 217 | let (rx_stream, usart, buf, _) = rx_transfer.free(); | ||
| 218 | self.rx_stream.replace(rx_stream); | ||
| 219 | self.usart.replace(usart); | ||
| 220 | |||
| 221 | buf | ||
| 222 | } | ||
| 223 | } | ||
| 224 | } | ||
