diff options
| -rw-r--r-- | embassy-nxp/CHANGELOG.md | 2 | ||||
| -rw-r--r-- | embassy-nxp/Cargo.toml | 13 | ||||
| -rw-r--r-- | embassy-nxp/src/chips/lpc55.rs | 2 | ||||
| -rw-r--r-- | embassy-nxp/src/gpio.rs | 2 | ||||
| -rw-r--r-- | embassy-nxp/src/gpio/lpc55.rs | 360 | ||||
| -rw-r--r-- | embassy-nxp/src/lib.rs | 10 | ||||
| -rw-r--r-- | embassy-nxp/src/pint.rs | 97 | ||||
| -rw-r--r-- | embassy-nxp/src/time_driver/rtc.rs | 76 | ||||
| -rw-r--r-- | embassy-nxp/src/usart.rs | 3 | ||||
| -rw-r--r-- | embassy-nxp/src/usart/lpc55.rs | 884 | ||||
| -rw-r--r-- | examples/lpc55s69/Cargo.toml | 2 |
11 files changed, 462 insertions, 989 deletions
diff --git a/embassy-nxp/CHANGELOG.md b/embassy-nxp/CHANGELOG.md index 7042ad14c..ab97c4185 100644 --- a/embassy-nxp/CHANGELOG.md +++ b/embassy-nxp/CHANGELOG.md | |||
| @@ -7,5 +7,5 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 | |||
| 7 | 7 | ||
| 8 | <!-- next-header --> | 8 | <!-- next-header --> |
| 9 | ## Unreleased - ReleaseDate | 9 | ## Unreleased - ReleaseDate |
| 10 | 10 | - Moved NXP LPC55S69 from `lpc55-pac` to `nxp-pac` | |
| 11 | - First release with changelog. | 11 | - First release with changelog. |
diff --git a/embassy-nxp/Cargo.toml b/embassy-nxp/Cargo.toml index ab0bfbfd7..455915f29 100644 --- a/embassy-nxp/Cargo.toml +++ b/embassy-nxp/Cargo.toml | |||
| @@ -7,7 +7,7 @@ publish = false | |||
| 7 | 7 | ||
| 8 | [package.metadata.embassy] | 8 | [package.metadata.embassy] |
| 9 | build = [ | 9 | build = [ |
| 10 | {target = "thumbv8m.main-none-eabihf", features = ["defmt", "lpc55"]}, | 10 | {target = "thumbv8m.main-none-eabihf", features = ["defmt", "lpc55-core0"]}, |
| 11 | {target = "thumbv7em-none-eabihf", features = ["defmt", "mimxrt1011", "rt", "time-driver-pit"]}, | 11 | {target = "thumbv7em-none-eabihf", features = ["defmt", "mimxrt1011", "rt", "time-driver-pit"]}, |
| 12 | {target = "thumbv7em-none-eabihf", features = ["defmt", "mimxrt1062", "rt", "time-driver-pit"]}, | 12 | {target = "thumbv7em-none-eabihf", features = ["defmt", "mimxrt1062", "rt", "time-driver-pit"]}, |
| 13 | ] | 13 | ] |
| @@ -18,7 +18,7 @@ src_base_git = "https://github.com/embassy-rs/embassy/blob/$COMMIT/embassy-nxp/s | |||
| 18 | features = ["defmt", "unstable-pac" ] # TODO: Add time-driver-any, as both lpc55 and mimxrt1xxx use different drivers. | 18 | features = ["defmt", "unstable-pac" ] # TODO: Add time-driver-any, as both lpc55 and mimxrt1xxx use different drivers. |
| 19 | 19 | ||
| 20 | flavors = [ | 20 | flavors = [ |
| 21 | { regex_feature = "lpc55", target = "thumbv8m.main-none-eabihf" }, | 21 | { regex_feature = "lpc55-core0", target = "thumbv8m.main-none-eabihf" }, |
| 22 | { regex_feature = "mimxrt.*", target = "thumbv7em-none-eabihf" }, | 22 | { regex_feature = "mimxrt.*", target = "thumbv7em-none-eabihf" }, |
| 23 | ] | 23 | ] |
| 24 | 24 | ||
| @@ -36,21 +36,20 @@ embassy-time-queue-utils = { version = "0.3.0", path = "../embassy-time-queue-ut | |||
| 36 | embedded-io = "0.6.1" | 36 | embedded-io = "0.6.1" |
| 37 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } | 37 | embedded-hal-02 = { package = "embedded-hal", version = "0.2.6", features = ["unproven"] } |
| 38 | ## Chip dependencies | 38 | ## Chip dependencies |
| 39 | lpc55-pac = { version = "0.5.0", optional = true } | 39 | nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/i509VCB/nxp-pac", rev = "b736e3038254d593024aaa1a5a7b1f95a5728538"} |
| 40 | nxp-pac = { version = "0.1.0", optional = true, git = "https://github.com/i509VCB/nxp-pac", rev = "be4dd0936c20d5897364a381b1d95a99514c1e7e" } | ||
| 41 | 40 | ||
| 42 | imxrt-rt = { version = "0.1.7", optional = true, features = ["device"] } | 41 | imxrt-rt = { version = "0.1.7", optional = true, features = ["device"] } |
| 43 | 42 | ||
| 44 | [build-dependencies] | 43 | [build-dependencies] |
| 45 | cfg_aliases = "0.2.1" | 44 | cfg_aliases = "0.2.1" |
| 46 | nxp-pac = { version = "0.1.0", git = "https://github.com/i509VCB/nxp-pac", rev = "be4dd0936c20d5897364a381b1d95a99514c1e7e", features = ["metadata"], optional = true } | 45 | nxp-pac = { version = "0.1.0", git = "https://github.com/i509VCB/nxp-pac", rev = "b736e3038254d593024aaa1a5a7b1f95a5728538", features = ["metadata"], optional = true } |
| 47 | proc-macro2 = "1.0.95" | 46 | proc-macro2 = "1.0.95" |
| 48 | quote = "1.0.15" | 47 | quote = "1.0.15" |
| 49 | 48 | ||
| 50 | [features] | 49 | [features] |
| 51 | default = ["rt"] | 50 | default = ["rt"] |
| 52 | # Enable PACs as optional dependencies, since some chip families will use different pac crates (temporarily). | 51 | # Enable PACs as optional dependencies, since some chip families will use different pac crates (temporarily). |
| 53 | rt = ["lpc55-pac?/rt", "nxp-pac?/rt"] | 52 | rt = ["nxp-pac?/rt"] |
| 54 | 53 | ||
| 55 | ## Enable [defmt support](https://docs.rs/defmt) and enables `defmt` debug-log messages and formatting in embassy drivers. | 54 | ## Enable [defmt support](https://docs.rs/defmt) and enables `defmt` debug-log messages and formatting in embassy drivers. |
| 56 | defmt = ["dep:defmt", "embassy-hal-internal/defmt", "embassy-sync/defmt"] | 55 | defmt = ["dep:defmt", "embassy-hal-internal/defmt", "embassy-sync/defmt"] |
| @@ -79,6 +78,6 @@ _rt1xxx = [] | |||
| 79 | _time_driver = ["dep:embassy-time-driver", "dep:embassy-time-queue-utils"] | 78 | _time_driver = ["dep:embassy-time-driver", "dep:embassy-time-queue-utils"] |
| 80 | 79 | ||
| 81 | #! ### Chip selection features | 80 | #! ### Chip selection features |
| 82 | lpc55 = ["dep:lpc55-pac"] | 81 | lpc55-core0 = ["nxp-pac/lpc55s69_cm33_core0"] |
| 83 | mimxrt1011 = ["nxp-pac/mimxrt1011", "_rt1xxx", "dep:imxrt-rt"] | 82 | mimxrt1011 = ["nxp-pac/mimxrt1011", "_rt1xxx", "dep:imxrt-rt"] |
| 84 | mimxrt1062 = ["nxp-pac/mimxrt1062", "_rt1xxx", "dep:imxrt-rt"] | 83 | mimxrt1062 = ["nxp-pac/mimxrt1062", "_rt1xxx", "dep:imxrt-rt"] |
diff --git a/embassy-nxp/src/chips/lpc55.rs b/embassy-nxp/src/chips/lpc55.rs index e168ced00..711bff3e7 100644 --- a/embassy-nxp/src/chips/lpc55.rs +++ b/embassy-nxp/src/chips/lpc55.rs | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | pub use lpc55_pac as pac; | 1 | pub use nxp_pac as pac; |
| 2 | 2 | ||
| 3 | embassy_hal_internal::peripherals! { | 3 | embassy_hal_internal::peripherals! { |
| 4 | // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other | 4 | // External pins. These are not only GPIOs, they are multi-purpose pins and can be used by other |
diff --git a/embassy-nxp/src/gpio.rs b/embassy-nxp/src/gpio.rs index 3049cc12d..717b38d96 100644 --- a/embassy-nxp/src/gpio.rs +++ b/embassy-nxp/src/gpio.rs | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | //! General purpose input/output (GPIO) driver. | 1 | //! General purpose input/output (GPIO) driver. |
| 2 | #![macro_use] | 2 | #![macro_use] |
| 3 | 3 | ||
| 4 | #[cfg_attr(feature = "lpc55", path = "./gpio/lpc55.rs")] | 4 | #[cfg_attr(feature = "lpc55-core0", path = "./gpio/lpc55.rs")] |
| 5 | #[cfg_attr(rt1xxx, path = "./gpio/rt1xxx.rs")] | 5 | #[cfg_attr(rt1xxx, path = "./gpio/rt1xxx.rs")] |
| 6 | mod inner; | 6 | mod inner; |
| 7 | pub use inner::*; | 7 | pub use inner::*; |
diff --git a/embassy-nxp/src/gpio/lpc55.rs b/embassy-nxp/src/gpio/lpc55.rs index 8f407bb3a..36ea99d21 100644 --- a/embassy-nxp/src/gpio/lpc55.rs +++ b/embassy-nxp/src/gpio/lpc55.rs | |||
| @@ -1,12 +1,17 @@ | |||
| 1 | use embassy_hal_internal::{impl_peripheral, PeripheralType}; | 1 | use embassy_hal_internal::{impl_peripheral, PeripheralType}; |
| 2 | 2 | ||
| 3 | use crate::pac::iocon::vals::{PioDigimode, PioMode}; | ||
| 4 | use crate::pac::{GPIO, IOCON, SYSCON}; | ||
| 3 | use crate::{peripherals, Peri}; | 5 | use crate::{peripherals, Peri}; |
| 4 | 6 | ||
| 5 | pub(crate) fn init() { | 7 | pub(crate) fn init() { |
| 6 | // Enable clocks for GPIO, PINT, and IOCON | 8 | // Enable clocks for GPIO, PINT, and IOCON |
| 7 | syscon_reg() | 9 | SYSCON.ahbclkctrl0().modify(|w| { |
| 8 | .ahbclkctrl0 | 10 | w.set_gpio0(true); |
| 9 | .modify(|_, w| w.gpio0().enable().gpio1().enable().mux().enable().iocon().enable()); | 11 | w.set_gpio1(true); |
| 12 | w.set_mux(true); | ||
| 13 | w.set_iocon(true); | ||
| 14 | }); | ||
| 10 | info!("GPIO initialized"); | 15 | info!("GPIO initialized"); |
| 11 | } | 16 | } |
| 12 | 17 | ||
| @@ -59,21 +64,24 @@ impl<'d> Output<'d> { | |||
| 59 | } | 64 | } |
| 60 | 65 | ||
| 61 | pub fn set_high(&mut self) { | 66 | pub fn set_high(&mut self) { |
| 62 | gpio_reg().set[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) | 67 | GPIO.set(self.pin.pin_bank() as usize) |
| 68 | .write(|w| w.set_setp(self.pin.bit())); | ||
| 63 | } | 69 | } |
| 64 | 70 | ||
| 65 | pub fn set_low(&mut self) { | 71 | pub fn set_low(&mut self) { |
| 66 | gpio_reg().clr[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) | 72 | GPIO.clr(self.pin.pin_bank() as usize) |
| 73 | .write(|w| w.set_clrp(self.pin.bit())); | ||
| 67 | } | 74 | } |
| 68 | 75 | ||
| 69 | pub fn toggle(&mut self) { | 76 | pub fn toggle(&mut self) { |
| 70 | gpio_reg().not[self.pin.pin_bank() as usize].write(|w| unsafe { w.bits(self.pin.bit()) }) | 77 | GPIO.not(self.pin.pin_bank() as usize) |
| 78 | .write(|w| w.set_notp(self.pin.bit())); | ||
| 71 | } | 79 | } |
| 72 | 80 | ||
| 73 | /// Get the current output level of the pin. Note that the value returned by this function is | 81 | /// Get the current output level of the pin. Note that the value returned by this function is |
| 74 | /// the voltage level reported by the pin, not the value set by the output driver. | 82 | /// the voltage level reported by the pin, not the value set by the output driver. |
| 75 | pub fn level(&self) -> Level { | 83 | pub fn level(&self) -> Level { |
| 76 | let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits(); | 84 | let bits = GPIO.pin(self.pin.pin_bank() as usize).read().port(); |
| 77 | if bits & self.pin.bit() != 0 { | 85 | if bits & self.pin.bit() != 0 { |
| 78 | Level::High | 86 | Level::High |
| 79 | } else { | 87 | } else { |
| @@ -101,18 +109,18 @@ impl<'d> Input<'d> { | |||
| 101 | 109 | ||
| 102 | /// Set the pull configuration for the pin. To disable the pull, use [Pull::None]. | 110 | /// Set the pull configuration for the pin. To disable the pull, use [Pull::None]. |
| 103 | pub fn set_pull(&mut self, pull: Pull) { | 111 | pub fn set_pull(&mut self, pull: Pull) { |
| 104 | match_iocon!(register, iocon_reg(), self.pin.pin_bank(), self.pin.pin_number(), { | 112 | match_iocon!(register, self.pin.pin_bank(), self.pin.pin_number(), { |
| 105 | register.modify(|_, w| match pull { | 113 | register.modify(|w| match pull { |
| 106 | Pull::None => w.mode().inactive(), | 114 | Pull::None => w.set_mode(PioMode::INACTIVE), |
| 107 | Pull::Up => w.mode().pull_up(), | 115 | Pull::Up => w.set_mode(PioMode::PULL_UP), |
| 108 | Pull::Down => w.mode().pull_down(), | 116 | Pull::Down => w.set_mode(PioMode::PULL_DOWN), |
| 109 | }); | 117 | }); |
| 110 | }); | 118 | }); |
| 111 | } | 119 | } |
| 112 | 120 | ||
| 113 | /// Get the current input level of the pin. | 121 | /// Get the current input level of the pin. |
| 114 | pub fn read(&self) -> Level { | 122 | pub fn read(&self) -> Level { |
| 115 | let bits = gpio_reg().pin[self.pin.pin_bank() as usize].read().bits(); | 123 | let bits = GPIO.pin(self.pin.pin_bank() as usize).read().port(); |
| 116 | if bits & self.pin.bit() != 0 { | 124 | if bits & self.pin.bit() != 0 { |
| 117 | Level::High | 125 | Level::High |
| 118 | } else { | 126 | } else { |
| @@ -188,8 +196,8 @@ impl<'d> Flex<'d> { | |||
| 188 | /// Set the pin to digital mode. This is required for using a pin as a GPIO pin. The default | 196 | /// Set the pin to digital mode. This is required for using a pin as a GPIO pin. The default |
| 189 | /// setting for pins is (usually) non-digital. | 197 | /// setting for pins is (usually) non-digital. |
| 190 | fn set_as_digital(&mut self) { | 198 | fn set_as_digital(&mut self) { |
| 191 | match_iocon!(register, iocon_reg(), self.pin_bank(), self.pin_number(), { | 199 | match_iocon!(register, self.pin_bank(), self.pin_number(), { |
| 192 | register.modify(|_, w| w.digimode().digital()); | 200 | register.modify(|w| w.set_digimode(PioDigimode::DIGITAL)); |
| 193 | }); | 201 | }); |
| 194 | } | 202 | } |
| 195 | 203 | ||
| @@ -197,12 +205,14 @@ impl<'d> Flex<'d> { | |||
| 197 | /// function handles itself. | 205 | /// function handles itself. |
| 198 | pub fn set_as_output(&mut self) { | 206 | pub fn set_as_output(&mut self) { |
| 199 | self.set_as_digital(); | 207 | self.set_as_digital(); |
| 200 | gpio_reg().dirset[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirsetp().bits(self.bit()) }) | 208 | GPIO.dirset(self.pin.pin_bank() as usize) |
| 209 | .write(|w| w.set_dirsetp(self.bit())) | ||
| 201 | } | 210 | } |
| 202 | 211 | ||
| 203 | pub fn set_as_input(&mut self) { | 212 | pub fn set_as_input(&mut self) { |
| 204 | self.set_as_digital(); | 213 | self.set_as_digital(); |
| 205 | gpio_reg().dirclr[self.pin.pin_bank() as usize].write(|w| unsafe { w.dirclrp().bits(self.bit()) }) | 214 | GPIO.dirclr(self.pin.pin_bank() as usize) |
| 215 | .write(|w| w.set_dirclrp(self.bit())) | ||
| 206 | } | 216 | } |
| 207 | } | 217 | } |
| 208 | 218 | ||
| @@ -262,52 +272,6 @@ impl SealedPin for AnyPin { | |||
| 262 | } | 272 | } |
| 263 | } | 273 | } |
| 264 | 274 | ||
| 265 | /// Get the GPIO register block. This is used to configure all GPIO pins. | ||
| 266 | /// | ||
| 267 | /// # Safety | ||
| 268 | /// Due to the type system of peripherals, access to the settings of a single pin is possible only | ||
| 269 | /// by a single thread at a time. Read/Write operations on a single registers are NOT atomic. You | ||
| 270 | /// must ensure that the GPIO registers are not accessed concurrently by multiple threads. | ||
| 271 | pub(crate) fn gpio_reg() -> &'static lpc55_pac::gpio::RegisterBlock { | ||
| 272 | unsafe { &*lpc55_pac::GPIO::ptr() } | ||
| 273 | } | ||
| 274 | |||
| 275 | /// Get the IOCON register block. | ||
| 276 | /// | ||
| 277 | /// # Safety | ||
| 278 | /// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO | ||
| 279 | /// registers are not accessed concurrently by multiple threads. | ||
| 280 | pub(crate) fn iocon_reg() -> &'static lpc55_pac::iocon::RegisterBlock { | ||
| 281 | unsafe { &*lpc55_pac::IOCON::ptr() } | ||
| 282 | } | ||
| 283 | |||
| 284 | /// Get the INPUTMUX register block. | ||
| 285 | /// | ||
| 286 | /// # Safety | ||
| 287 | /// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO | ||
| 288 | /// registers are not accessed concurrently by multiple threads. | ||
| 289 | pub(crate) fn inputmux_reg() -> &'static lpc55_pac::inputmux::RegisterBlock { | ||
| 290 | unsafe { &*lpc55_pac::INPUTMUX::ptr() } | ||
| 291 | } | ||
| 292 | |||
| 293 | /// Get the SYSCON register block. | ||
| 294 | /// | ||
| 295 | /// # Safety | ||
| 296 | /// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO | ||
| 297 | /// registers are not accessed concurrently by multiple threads. | ||
| 298 | pub(crate) fn syscon_reg() -> &'static lpc55_pac::syscon::RegisterBlock { | ||
| 299 | unsafe { &*lpc55_pac::SYSCON::ptr() } | ||
| 300 | } | ||
| 301 | |||
| 302 | /// Get the PINT register block. | ||
| 303 | /// | ||
| 304 | /// # Safety | ||
| 305 | /// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO | ||
| 306 | /// registers are not accessed concurrently by multiple threads. | ||
| 307 | pub(crate) fn pint_reg() -> &'static lpc55_pac::pint::RegisterBlock { | ||
| 308 | unsafe { &*lpc55_pac::PINT::ptr() } | ||
| 309 | } | ||
| 310 | |||
| 311 | /// Match the pin bank and number of a pin to the corresponding IOCON register. | 275 | /// Match the pin bank and number of a pin to the corresponding IOCON register. |
| 312 | /// | 276 | /// |
| 313 | /// # Example | 277 | /// # Example |
| @@ -316,270 +280,26 @@ pub(crate) fn pint_reg() -> &'static lpc55_pac::pint::RegisterBlock { | |||
| 316 | /// use embassy_nxp::pac_utils::{iocon_reg, match_iocon}; | 280 | /// use embassy_nxp::pac_utils::{iocon_reg, match_iocon}; |
| 317 | /// | 281 | /// |
| 318 | /// // Make pin PIO1_6 digital and set it to pull-down mode. | 282 | /// // Make pin PIO1_6 digital and set it to pull-down mode. |
| 319 | /// match_iocon!(register, iocon_reg(), Bank::Bank1, 6, { | 283 | /// match_iocon!(register, Bank::Bank1, 6, { |
| 320 | /// register.modify(|_, w| w.mode().pull_down().digimode().digital()); | 284 | /// register.modify(|w|{ |
| 285 | /// w.set_mode(PioMode::PULL_DOWN); | ||
| 286 | /// w.set_digimode(PioDigimode::DIGITAL); | ||
| 287 | /// | ||
| 288 | /// } | ||
| 321 | /// }); | 289 | /// }); |
| 322 | /// ``` | 290 | /// ``` |
| 323 | macro_rules! match_iocon { | 291 | macro_rules! match_iocon { |
| 324 | ($register:ident, $iocon_register:expr, $pin_bank:expr, $pin_number:expr, $action:expr) => { | 292 | ($register:ident, $pin_bank:expr, $pin_number:expr, $action:expr) => { |
| 325 | match ($pin_bank, $pin_number) { | 293 | match $pin_bank { |
| 326 | (Bank::Bank0, 0) => { | 294 | Bank::Bank0 => { |
| 327 | let $register = &($iocon_register).pio0_0; | 295 | let $register = IOCON.pio0($pin_number as usize); |
| 328 | $action; | ||
| 329 | } | ||
| 330 | (Bank::Bank0, 1) => { | ||
| 331 | let $register = &($iocon_register).pio0_1; | ||
| 332 | $action; | ||
| 333 | } | ||
| 334 | (Bank::Bank0, 2) => { | ||
| 335 | let $register = &($iocon_register).pio0_2; | ||
| 336 | $action; | ||
| 337 | } | ||
| 338 | (Bank::Bank0, 3) => { | ||
| 339 | let $register = &($iocon_register).pio0_3; | ||
| 340 | $action; | ||
| 341 | } | ||
| 342 | (Bank::Bank0, 4) => { | ||
| 343 | let $register = &($iocon_register).pio0_4; | ||
| 344 | $action; | ||
| 345 | } | ||
| 346 | (Bank::Bank0, 5) => { | ||
| 347 | let $register = &($iocon_register).pio0_5; | ||
| 348 | $action; | ||
| 349 | } | ||
| 350 | (Bank::Bank0, 6) => { | ||
| 351 | let $register = &($iocon_register).pio0_6; | ||
| 352 | $action; | ||
| 353 | } | ||
| 354 | (Bank::Bank0, 7) => { | ||
| 355 | let $register = &($iocon_register).pio0_7; | ||
| 356 | $action; | ||
| 357 | } | ||
| 358 | (Bank::Bank0, 8) => { | ||
| 359 | let $register = &($iocon_register).pio0_8; | ||
| 360 | $action; | ||
| 361 | } | ||
| 362 | (Bank::Bank0, 9) => { | ||
| 363 | let $register = &($iocon_register).pio0_9; | ||
| 364 | $action; | ||
| 365 | } | ||
| 366 | (Bank::Bank0, 10) => { | ||
| 367 | let $register = &($iocon_register).pio0_10; | ||
| 368 | $action; | 296 | $action; |
| 369 | } | 297 | } |
| 370 | (Bank::Bank0, 11) => { | 298 | |
| 371 | let $register = &($iocon_register).pio0_11; | 299 | Bank::Bank1 => { |
| 372 | $action; | 300 | let $register = IOCON.pio1($pin_number as usize); |
| 373 | } | ||
| 374 | (Bank::Bank0, 12) => { | ||
| 375 | let $register = &($iocon_register).pio0_12; | ||
| 376 | $action; | ||
| 377 | } | ||
| 378 | (Bank::Bank0, 13) => { | ||
| 379 | let $register = &($iocon_register).pio0_13; | ||
| 380 | $action; | ||
| 381 | } | ||
| 382 | (Bank::Bank0, 14) => { | ||
| 383 | let $register = &($iocon_register).pio0_14; | ||
| 384 | $action; | ||
| 385 | } | ||
| 386 | (Bank::Bank0, 15) => { | ||
| 387 | let $register = &($iocon_register).pio0_15; | ||
| 388 | $action; | ||
| 389 | } | ||
| 390 | (Bank::Bank0, 16) => { | ||
| 391 | let $register = &($iocon_register).pio0_16; | ||
| 392 | $action; | ||
| 393 | } | ||
| 394 | (Bank::Bank0, 17) => { | ||
| 395 | let $register = &($iocon_register).pio0_17; | ||
| 396 | $action; | ||
| 397 | } | ||
| 398 | (Bank::Bank0, 18) => { | ||
| 399 | let $register = &($iocon_register).pio0_18; | ||
| 400 | $action; | ||
| 401 | } | ||
| 402 | (Bank::Bank0, 19) => { | ||
| 403 | let $register = &($iocon_register).pio0_19; | ||
| 404 | $action; | ||
| 405 | } | ||
| 406 | (Bank::Bank0, 20) => { | ||
| 407 | let $register = &($iocon_register).pio0_20; | ||
| 408 | $action; | ||
| 409 | } | ||
| 410 | (Bank::Bank0, 21) => { | ||
| 411 | let $register = &($iocon_register).pio0_21; | ||
| 412 | $action; | ||
| 413 | } | ||
| 414 | (Bank::Bank0, 22) => { | ||
| 415 | let $register = &($iocon_register).pio0_22; | ||
| 416 | $action; | ||
| 417 | } | ||
| 418 | (Bank::Bank0, 23) => { | ||
| 419 | let $register = &($iocon_register).pio0_23; | ||
| 420 | $action; | ||
| 421 | } | ||
| 422 | (Bank::Bank0, 24) => { | ||
| 423 | let $register = &($iocon_register).pio0_24; | ||
| 424 | $action; | ||
| 425 | } | ||
| 426 | (Bank::Bank0, 25) => { | ||
| 427 | let $register = &($iocon_register).pio0_25; | ||
| 428 | $action; | ||
| 429 | } | ||
| 430 | (Bank::Bank0, 26) => { | ||
| 431 | let $register = &($iocon_register).pio0_26; | ||
| 432 | $action; | ||
| 433 | } | ||
| 434 | (Bank::Bank0, 27) => { | ||
| 435 | let $register = &($iocon_register).pio0_27; | ||
| 436 | $action; | ||
| 437 | } | ||
| 438 | (Bank::Bank0, 28) => { | ||
| 439 | let $register = &($iocon_register).pio0_28; | ||
| 440 | $action; | ||
| 441 | } | ||
| 442 | (Bank::Bank0, 29) => { | ||
| 443 | let $register = &($iocon_register).pio0_29; | ||
| 444 | $action; | ||
| 445 | } | ||
| 446 | (Bank::Bank0, 30) => { | ||
| 447 | let $register = &($iocon_register).pio0_30; | ||
| 448 | $action; | ||
| 449 | } | ||
| 450 | (Bank::Bank0, 31) => { | ||
| 451 | let $register = &($iocon_register).pio0_31; | ||
| 452 | $action; | ||
| 453 | } | ||
| 454 | (Bank::Bank1, 0) => { | ||
| 455 | let $register = &($iocon_register).pio1_0; | ||
| 456 | $action; | ||
| 457 | } | ||
| 458 | (Bank::Bank1, 1) => { | ||
| 459 | let $register = &($iocon_register).pio1_1; | ||
| 460 | $action; | ||
| 461 | } | ||
| 462 | (Bank::Bank1, 2) => { | ||
| 463 | let $register = &($iocon_register).pio1_2; | ||
| 464 | $action; | ||
| 465 | } | ||
| 466 | (Bank::Bank1, 3) => { | ||
| 467 | let $register = &($iocon_register).pio1_3; | ||
| 468 | $action; | ||
| 469 | } | ||
| 470 | (Bank::Bank1, 4) => { | ||
| 471 | let $register = &($iocon_register).pio1_4; | ||
| 472 | $action; | ||
| 473 | } | ||
| 474 | (Bank::Bank1, 5) => { | ||
| 475 | let $register = &($iocon_register).pio1_5; | ||
| 476 | $action; | ||
| 477 | } | ||
| 478 | (Bank::Bank1, 6) => { | ||
| 479 | let $register = &($iocon_register).pio1_6; | ||
| 480 | $action; | ||
| 481 | } | ||
| 482 | (Bank::Bank1, 7) => { | ||
| 483 | let $register = &($iocon_register).pio1_7; | ||
| 484 | $action; | ||
| 485 | } | ||
| 486 | (Bank::Bank1, 8) => { | ||
| 487 | let $register = &($iocon_register).pio1_8; | ||
| 488 | $action; | ||
| 489 | } | ||
| 490 | (Bank::Bank1, 9) => { | ||
| 491 | let $register = &($iocon_register).pio1_9; | ||
| 492 | $action; | ||
| 493 | } | ||
| 494 | (Bank::Bank1, 10) => { | ||
| 495 | let $register = &($iocon_register).pio1_10; | ||
| 496 | $action; | ||
| 497 | } | ||
| 498 | (Bank::Bank1, 11) => { | ||
| 499 | let $register = &($iocon_register).pio1_11; | ||
| 500 | $action; | ||
| 501 | } | ||
| 502 | (Bank::Bank1, 12) => { | ||
| 503 | let $register = &($iocon_register).pio1_12; | ||
| 504 | $action; | ||
| 505 | } | ||
| 506 | (Bank::Bank1, 13) => { | ||
| 507 | let $register = &($iocon_register).pio1_13; | ||
| 508 | $action; | ||
| 509 | } | ||
| 510 | (Bank::Bank1, 14) => { | ||
| 511 | let $register = &($iocon_register).pio1_14; | ||
| 512 | $action; | ||
| 513 | } | ||
| 514 | (Bank::Bank1, 15) => { | ||
| 515 | let $register = &($iocon_register).pio1_15; | ||
| 516 | $action; | ||
| 517 | } | ||
| 518 | (Bank::Bank1, 16) => { | ||
| 519 | let $register = &($iocon_register).pio1_16; | ||
| 520 | $action; | ||
| 521 | } | ||
| 522 | (Bank::Bank1, 17) => { | ||
| 523 | let $register = &($iocon_register).pio1_17; | ||
| 524 | $action; | ||
| 525 | } | ||
| 526 | (Bank::Bank1, 18) => { | ||
| 527 | let $register = &($iocon_register).pio1_18; | ||
| 528 | $action; | ||
| 529 | } | ||
| 530 | (Bank::Bank1, 19) => { | ||
| 531 | let $register = &($iocon_register).pio1_19; | ||
| 532 | $action; | ||
| 533 | } | ||
| 534 | (Bank::Bank1, 20) => { | ||
| 535 | let $register = &($iocon_register).pio1_20; | ||
| 536 | $action; | ||
| 537 | } | ||
| 538 | (Bank::Bank1, 21) => { | ||
| 539 | let $register = &($iocon_register).pio1_21; | ||
| 540 | $action; | ||
| 541 | } | ||
| 542 | (Bank::Bank1, 22) => { | ||
| 543 | let $register = &($iocon_register).pio1_22; | ||
| 544 | $action; | ||
| 545 | } | ||
| 546 | (Bank::Bank1, 23) => { | ||
| 547 | let $register = &($iocon_register).pio1_23; | ||
| 548 | $action; | ||
| 549 | } | ||
| 550 | (Bank::Bank1, 24) => { | ||
| 551 | let $register = &($iocon_register).pio1_24; | ||
| 552 | $action; | ||
| 553 | } | ||
| 554 | (Bank::Bank1, 25) => { | ||
| 555 | let $register = &($iocon_register).pio1_25; | ||
| 556 | $action; | ||
| 557 | } | ||
| 558 | (Bank::Bank1, 26) => { | ||
| 559 | let $register = &($iocon_register).pio1_26; | ||
| 560 | $action; | ||
| 561 | } | ||
| 562 | (Bank::Bank1, 27) => { | ||
| 563 | let $register = &($iocon_register).pio1_27; | ||
| 564 | $action; | ||
| 565 | } | ||
| 566 | (Bank::Bank1, 28) => { | ||
| 567 | let $register = &($iocon_register).pio1_28; | ||
| 568 | $action; | ||
| 569 | } | ||
| 570 | (Bank::Bank1, 29) => { | ||
| 571 | let $register = &($iocon_register).pio1_29; | ||
| 572 | $action; | ||
| 573 | } | ||
| 574 | (Bank::Bank1, 30) => { | ||
| 575 | let $register = &($iocon_register).pio1_30; | ||
| 576 | $action; | ||
| 577 | } | ||
| 578 | (Bank::Bank1, 31) => { | ||
| 579 | let $register = &($iocon_register).pio1_31; | ||
| 580 | $action; | 301 | $action; |
| 581 | } | 302 | } |
| 582 | _ => unreachable!(), | ||
| 583 | } | 303 | } |
| 584 | }; | 304 | }; |
| 585 | } | 305 | } |
diff --git a/embassy-nxp/src/lib.rs b/embassy-nxp/src/lib.rs index 3fcb14b7e..74142a10b 100644 --- a/embassy-nxp/src/lib.rs +++ b/embassy-nxp/src/lib.rs | |||
| @@ -4,9 +4,9 @@ | |||
| 4 | pub(crate) mod fmt; | 4 | pub(crate) mod fmt; |
| 5 | 5 | ||
| 6 | pub mod gpio; | 6 | pub mod gpio; |
| 7 | #[cfg(feature = "lpc55")] | 7 | #[cfg(feature = "lpc55-core0")] |
| 8 | pub mod pint; | 8 | pub mod pint; |
| 9 | #[cfg(feature = "lpc55")] | 9 | #[cfg(feature = "lpc55-core0")] |
| 10 | pub mod usart; | 10 | pub mod usart; |
| 11 | 11 | ||
| 12 | #[cfg(feature = "_time_driver")] | 12 | #[cfg(feature = "_time_driver")] |
| @@ -15,7 +15,7 @@ pub mod usart; | |||
| 15 | mod time_driver; | 15 | mod time_driver; |
| 16 | 16 | ||
| 17 | // This mod MUST go last, so that it sees all the `impl_foo!` macros | 17 | // This mod MUST go last, so that it sees all the `impl_foo!` macros |
| 18 | #[cfg_attr(feature = "lpc55", path = "chips/lpc55.rs")] | 18 | #[cfg_attr(feature = "lpc55-core0", path = "chips/lpc55.rs")] |
| 19 | #[cfg_attr(feature = "mimxrt1011", path = "chips/mimxrt1011.rs")] | 19 | #[cfg_attr(feature = "mimxrt1011", path = "chips/mimxrt1011.rs")] |
| 20 | #[cfg_attr(feature = "mimxrt1062", path = "chips/mimxrt1062.rs")] | 20 | #[cfg_attr(feature = "mimxrt1062", path = "chips/mimxrt1062.rs")] |
| 21 | mod chip; | 21 | mod chip; |
| @@ -83,10 +83,10 @@ pub fn init(_config: config::Config) -> Peripherals { | |||
| 83 | pac::CCM.ccgr6().modify(|v| v.set_cg0(1)); | 83 | pac::CCM.ccgr6().modify(|v| v.set_cg0(1)); |
| 84 | } | 84 | } |
| 85 | 85 | ||
| 86 | #[cfg(any(feature = "lpc55", rt1xxx))] | 86 | #[cfg(any(feature = "lpc55-core0", rt1xxx))] |
| 87 | gpio::init(); | 87 | gpio::init(); |
| 88 | 88 | ||
| 89 | #[cfg(feature = "lpc55")] | 89 | #[cfg(feature = "lpc55-core0")] |
| 90 | pint::init(); | 90 | pint::init(); |
| 91 | 91 | ||
| 92 | #[cfg(feature = "_time_driver")] | 92 | #[cfg(feature = "_time_driver")] |
diff --git a/embassy-nxp/src/pint.rs b/embassy-nxp/src/pint.rs index ff414b4e6..e594aaa6a 100644 --- a/embassy-nxp/src/pint.rs +++ b/embassy-nxp/src/pint.rs | |||
| @@ -5,10 +5,11 @@ use core::pin::Pin as FuturePin; | |||
| 5 | use core::task::{Context, Poll}; | 5 | use core::task::{Context, Poll}; |
| 6 | 6 | ||
| 7 | use critical_section::Mutex; | 7 | use critical_section::Mutex; |
| 8 | use embassy_hal_internal::interrupt::InterruptExt; | ||
| 8 | use embassy_sync::waitqueue::AtomicWaker; | 9 | use embassy_sync::waitqueue::AtomicWaker; |
| 9 | 10 | ||
| 10 | use crate::gpio::{self, inputmux_reg, pint_reg, syscon_reg, AnyPin, Level, SealedPin}; | 11 | use crate::gpio::{self, AnyPin, Level, SealedPin}; |
| 11 | use crate::pac::interrupt; | 12 | use crate::pac::{interrupt, INPUTMUX, PINT, SYSCON}; |
| 12 | use crate::Peri; | 13 | use crate::Peri; |
| 13 | 14 | ||
| 14 | struct PinInterrupt { | 15 | struct PinInterrupt { |
| @@ -88,18 +89,18 @@ enum InterruptOn { | |||
| 88 | } | 89 | } |
| 89 | 90 | ||
| 90 | pub(crate) fn init() { | 91 | pub(crate) fn init() { |
| 91 | syscon_reg().ahbclkctrl0.modify(|_, w| w.pint().enable()); | 92 | SYSCON.ahbclkctrl0().modify(|w| w.set_pint(true)); |
| 92 | 93 | ||
| 93 | // Enable interrupts | 94 | // Enable interrupts |
| 94 | unsafe { | 95 | unsafe { |
| 95 | crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT0); | 96 | interrupt::PIN_INT0.enable(); |
| 96 | crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT1); | 97 | interrupt::PIN_INT1.enable(); |
| 97 | crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT2); | 98 | interrupt::PIN_INT2.enable(); |
| 98 | crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT3); | 99 | interrupt::PIN_INT3.enable(); |
| 99 | crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT4); | 100 | interrupt::PIN_INT4.enable(); |
| 100 | crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT5); | 101 | interrupt::PIN_INT5.enable(); |
| 101 | crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT6); | 102 | interrupt::PIN_INT6.enable(); |
| 102 | crate::pac::NVIC::unmask(crate::pac::Interrupt::PIN_INT7); | 103 | interrupt::PIN_INT7.enable(); |
| 103 | }; | 104 | }; |
| 104 | 105 | ||
| 105 | info!("Pin interrupts initialized"); | 106 | info!("Pin interrupts initialized"); |
| @@ -119,24 +120,19 @@ impl<'d> InputFuture<'d> { | |||
| 119 | let interrupt_number = next_available_interrupt()?; | 120 | let interrupt_number = next_available_interrupt()?; |
| 120 | 121 | ||
| 121 | // Clear interrupt, just in case | 122 | // Clear interrupt, just in case |
| 122 | pint_reg() | 123 | PINT.rise().write(|w| w.set_rdet(1 << interrupt_number)); |
| 123 | .rise | 124 | PINT.fall().write(|w| w.set_fdet(1 << interrupt_number)); |
| 124 | .write(|w| unsafe { w.rdet().bits(1 << interrupt_number) }); | ||
| 125 | pint_reg() | ||
| 126 | .fall | ||
| 127 | .write(|w| unsafe { w.fdet().bits(1 << interrupt_number) }); | ||
| 128 | 125 | ||
| 129 | // Enable input multiplexing on pin interrupt register 0 for pin (32*bank + pin_number) | 126 | // Enable input multiplexing on pin interrupt register 0 for pin (32*bank + pin_number) |
| 130 | inputmux_reg().pintsel[interrupt_number] | 127 | INPUTMUX |
| 131 | .write(|w| unsafe { w.intpin().bits(32 * pin.pin_bank() as u8 + pin.pin_number()) }); | 128 | .pintsel(interrupt_number as usize) |
| 129 | .write(|w| w.set_intpin(32 * pin.pin_bank() as u8 + pin.pin_number())); | ||
| 132 | 130 | ||
| 133 | match interrupt_on { | 131 | match interrupt_on { |
| 134 | InterruptOn::Level(level) => { | 132 | InterruptOn::Level(level) => { |
| 135 | // Set pin interrupt register to edge sensitive or level sensitive | 133 | // Set pin interrupt register to edge sensitive or level sensitive |
| 136 | // 0 = edge sensitive, 1 = level sensitive | 134 | // 0 = edge sensitive, 1 = level sensitive |
| 137 | pint_reg() | 135 | PINT.isel().modify(|w| w.set_pmode(w.pmode() | (1 << interrupt_number))); |
| 138 | .isel | ||
| 139 | .modify(|r, w| unsafe { w.bits(r.bits() | (1 << interrupt_number)) }); | ||
| 140 | 136 | ||
| 141 | // Enable level interrupt. | 137 | // Enable level interrupt. |
| 142 | // | 138 | // |
| @@ -144,63 +140,44 @@ impl<'d> InputFuture<'d> { | |||
| 144 | // is activated. | 140 | // is activated. |
| 145 | 141 | ||
| 146 | // 0 = no-op, 1 = enable | 142 | // 0 = no-op, 1 = enable |
| 147 | pint_reg() | 143 | PINT.sienr().write(|w| w.set_setenrl(1 << interrupt_number)); |
| 148 | .sienr | ||
| 149 | .write(|w| unsafe { w.setenrl().bits(1 << interrupt_number) }); | ||
| 150 | 144 | ||
| 151 | // Set active level | 145 | // Set active level |
| 152 | match level { | 146 | match level { |
| 153 | Level::Low => { | 147 | Level::Low => { |
| 154 | // 0 = no-op, 1 = select LOW | 148 | // 0 = no-op, 1 = select LOW |
| 155 | pint_reg() | 149 | PINT.cienf().write(|w| w.set_cenaf(1 << interrupt_number)); |
| 156 | .cienf | ||
| 157 | .write(|w| unsafe { w.cenaf().bits(1 << interrupt_number) }); | ||
| 158 | } | 150 | } |
| 159 | Level::High => { | 151 | Level::High => { |
| 160 | // 0 = no-op, 1 = select HIGH | 152 | // 0 = no-op, 1 = select HIGH |
| 161 | pint_reg() | 153 | PINT.sienf().write(|w| w.set_setenaf(1 << interrupt_number)); |
| 162 | .sienf | ||
| 163 | .write(|w| unsafe { w.setenaf().bits(1 << interrupt_number) }); | ||
| 164 | } | 154 | } |
| 165 | } | 155 | } |
| 166 | } | 156 | } |
| 167 | InterruptOn::Edge(edge) => { | 157 | InterruptOn::Edge(edge) => { |
| 168 | // Set pin interrupt register to edge sensitive or level sensitive | 158 | // Set pin interrupt register to edge sensitive or level sensitive |
| 169 | // 0 = edge sensitive, 1 = level sensitive | 159 | // 0 = edge sensitive, 1 = level sensitive |
| 170 | pint_reg() | 160 | PINT.isel() |
| 171 | .isel | 161 | .modify(|w| w.set_pmode(w.pmode() & !(1 << interrupt_number))); |
| 172 | .modify(|r, w| unsafe { w.bits(r.bits() & !(1 << interrupt_number)) }); | ||
| 173 | 162 | ||
| 174 | // Enable rising/falling edge detection | 163 | // Enable rising/falling edge detection |
| 175 | match edge { | 164 | match edge { |
| 176 | Edge::Rising => { | 165 | Edge::Rising => { |
| 177 | // 0 = no-op, 1 = enable rising edge | 166 | // 0 = no-op, 1 = enable rising edge |
| 178 | pint_reg() | 167 | PINT.sienr().write(|w| w.set_setenrl(1 << interrupt_number)); |
| 179 | .sienr | ||
| 180 | .write(|w| unsafe { w.setenrl().bits(1 << interrupt_number) }); | ||
| 181 | // 0 = no-op, 1 = disable falling edge | 168 | // 0 = no-op, 1 = disable falling edge |
| 182 | pint_reg() | 169 | PINT.cienf().write(|w| w.set_cenaf(1 << interrupt_number)); |
| 183 | .cienf | ||
| 184 | .write(|w| unsafe { w.cenaf().bits(1 << interrupt_number) }); | ||
| 185 | } | 170 | } |
| 186 | Edge::Falling => { | 171 | Edge::Falling => { |
| 187 | // 0 = no-op, 1 = enable falling edge | 172 | // 0 = no-op, 1 = enable falling edge |
| 188 | pint_reg() | 173 | PINT.sienf().write(|w| w.set_setenaf(1 << interrupt_number)); |
| 189 | .sienf | ||
| 190 | .write(|w| unsafe { w.setenaf().bits(1 << interrupt_number) }); | ||
| 191 | // 0 = no-op, 1 = disable rising edge | 174 | // 0 = no-op, 1 = disable rising edge |
| 192 | pint_reg() | 175 | PINT.cienr().write(|w| w.set_cenrl(1 << interrupt_number)); |
| 193 | .cienr | ||
| 194 | .write(|w| unsafe { w.cenrl().bits(1 << interrupt_number) }); | ||
| 195 | } | 176 | } |
| 196 | Edge::Both => { | 177 | Edge::Both => { |
| 197 | // 0 = no-op, 1 = enable | 178 | // 0 = no-op, 1 = enable |
| 198 | pint_reg() | 179 | PINT.sienr().write(|w| w.set_setenrl(1 << interrupt_number)); |
| 199 | .sienr | 180 | PINT.sienf().write(|w| w.set_setenaf(1 << interrupt_number)); |
| 200 | .write(|w| unsafe { w.setenrl().bits(1 << interrupt_number) }); | ||
| 201 | pint_reg() | ||
| 202 | .sienf | ||
| 203 | .write(|w| unsafe { w.setenaf().bits(1 << interrupt_number) }); | ||
| 204 | } | 181 | } |
| 205 | } | 182 | } |
| 206 | } | 183 | } |
| @@ -239,12 +216,8 @@ impl<'d> Drop for InputFuture<'d> { | |||
| 239 | 216 | ||
| 240 | // Disable pin interrupt | 217 | // Disable pin interrupt |
| 241 | // 0 = no-op, 1 = disable | 218 | // 0 = no-op, 1 = disable |
| 242 | pint_reg() | 219 | PINT.cienr().write(|w| w.set_cenrl(1 << interrupt_number)); |
| 243 | .cienr | 220 | PINT.cienf().write(|w| w.set_cenaf(1 << interrupt_number)); |
| 244 | .write(|w| unsafe { w.cenrl().bits(1 << interrupt_number) }); | ||
| 245 | pint_reg() | ||
| 246 | .cienf | ||
| 247 | .write(|w| unsafe { w.cenaf().bits(1 << interrupt_number) }); | ||
| 248 | 221 | ||
| 249 | critical_section::with(|cs| { | 222 | critical_section::with(|cs| { |
| 250 | let mut pin_interrupts = PIN_INTERRUPTS.borrow(cs).borrow_mut(); | 223 | let mut pin_interrupts = PIN_INTERRUPTS.borrow(cs).borrow_mut(); |
| @@ -277,12 +250,8 @@ impl<'d> Future for InputFuture<'d> { | |||
| 277 | } | 250 | } |
| 278 | 251 | ||
| 279 | fn handle_interrupt(interrupt_number: usize) { | 252 | fn handle_interrupt(interrupt_number: usize) { |
| 280 | pint_reg() | 253 | PINT.rise().write(|w| w.set_rdet(1 << interrupt_number)); |
| 281 | .rise | 254 | PINT.fall().write(|w| w.set_fdet(1 << interrupt_number)); |
| 282 | .write(|w| unsafe { w.rdet().bits(1 << interrupt_number) }); | ||
| 283 | pint_reg() | ||
| 284 | .fall | ||
| 285 | .write(|w| unsafe { w.fdet().bits(1 << interrupt_number) }); | ||
| 286 | 255 | ||
| 287 | critical_section::with(|cs| { | 256 | critical_section::with(|cs| { |
| 288 | let mut pin_interrupts = PIN_INTERRUPTS.borrow(cs).borrow_mut(); | 257 | let mut pin_interrupts = PIN_INTERRUPTS.borrow(cs).borrow_mut(); |
diff --git a/embassy-nxp/src/time_driver/rtc.rs b/embassy-nxp/src/time_driver/rtc.rs index 94272e9c2..fb6de6a5e 100644 --- a/embassy-nxp/src/time_driver/rtc.rs +++ b/embassy-nxp/src/time_driver/rtc.rs | |||
| @@ -6,7 +6,9 @@ use embassy_hal_internal::interrupt::{InterruptExt, Priority}; | |||
| 6 | use embassy_sync::blocking_mutex::CriticalSectionMutex as Mutex; | 6 | use embassy_sync::blocking_mutex::CriticalSectionMutex as Mutex; |
| 7 | use embassy_time_driver::{time_driver_impl, Driver}; | 7 | use embassy_time_driver::{time_driver_impl, Driver}; |
| 8 | use embassy_time_queue_utils::Queue; | 8 | use embassy_time_queue_utils::Queue; |
| 9 | use lpc55_pac::{interrupt, PMC, RTC, SYSCON}; | 9 | |
| 10 | use crate::pac::{interrupt, pmc, rtc, PMC, RTC, SYSCON}; | ||
| 11 | |||
| 10 | struct AlarmState { | 12 | struct AlarmState { |
| 11 | timestamp: Cell<u64>, | 13 | timestamp: Cell<u64>, |
| 12 | } | 14 | } |
| @@ -32,33 +34,32 @@ time_driver_impl!(static DRIVER: RtcDriver = RtcDriver { | |||
| 32 | }); | 34 | }); |
| 33 | impl RtcDriver { | 35 | impl RtcDriver { |
| 34 | fn init(&'static self) { | 36 | fn init(&'static self) { |
| 35 | let syscon = unsafe { &*SYSCON::ptr() }; | 37 | let syscon = SYSCON; |
| 36 | let pmc = unsafe { &*PMC::ptr() }; | 38 | let pmc = PMC; |
| 37 | let rtc = unsafe { &*RTC::ptr() }; | 39 | let rtc = RTC; |
| 38 | 40 | ||
| 39 | syscon.ahbclkctrl0.modify(|_, w| w.rtc().enable()); | 41 | syscon.ahbclkctrl0().modify(|w| w.set_rtc(true)); |
| 40 | 42 | ||
| 41 | // By default the RTC enters software reset. If for some reason it is | 43 | // By default the RTC enters software reset. If for some reason it is |
| 42 | // not in reset, we enter and them promptly leave.q | 44 | // not in reset, we enter and them promptly leave.q |
| 43 | rtc.ctrl.modify(|_, w| w.swreset().set_bit()); | 45 | rtc.ctrl().modify(|w| w.set_swreset(true)); |
| 44 | rtc.ctrl.modify(|_, w| w.swreset().clear_bit()); | 46 | rtc.ctrl().modify(|w| w.set_swreset(false)); |
| 45 | 47 | ||
| 46 | // Select clock source - either XTAL or FRO | 48 | // Select clock source - either XTAL or FRO |
| 47 | // pmc.rtcosc32k.write(|w| w.sel().xtal32k()); | 49 | // pmc.rtcosc32k().write(|w| w.set_sel(pmc::vals::Sel::XTAL32K)); |
| 48 | pmc.rtcosc32k.write(|w| w.sel().fro32k()); | 50 | pmc.rtcosc32k().write(|w| w.set_sel(pmc::vals::Sel::FRO32K)); |
| 49 | 51 | ||
| 50 | // Start the RTC peripheral | 52 | // Start the RTC peripheral |
| 51 | rtc.ctrl.modify(|_, w| w.rtc_osc_pd().power_up()); | 53 | rtc.ctrl().modify(|w| w.set_rtc_osc_pd(rtc::vals::RtcOscPd::POWER_UP)); |
| 52 | |||
| 53 | // rtc.ctrl.modify(|_, w| w.rtc_en().clear_bit()); // EXTRA | ||
| 54 | 54 | ||
| 55 | //reset/clear(?) counter | 55 | //reset/clear(?) counter |
| 56 | rtc.count.reset(); | 56 | rtc.count().modify(|w| w.set_val(0)); |
| 57 | //en rtc main counter | 57 | //en rtc main counter |
| 58 | rtc.ctrl.modify(|_, w| w.rtc_en().set_bit()); | 58 | rtc.ctrl().modify(|w| w.set_rtc_en(true)); |
| 59 | rtc.ctrl.modify(|_, w| w.rtc1khz_en().set_bit()); | 59 | rtc.ctrl().modify(|w| w.set_rtc1khz_en(true)); |
| 60 | // subsec counter enable | 60 | // subsec counter enable |
| 61 | rtc.ctrl.modify(|_, w| w.rtc_subsec_ena().set_bit()); | 61 | rtc.ctrl() |
| 62 | .modify(|w| w.set_rtc_subsec_ena(rtc::vals::RtcSubsecEna::POWER_UP)); | ||
| 62 | 63 | ||
| 63 | // enable irq | 64 | // enable irq |
| 64 | unsafe { | 65 | unsafe { |
| @@ -68,7 +69,7 @@ impl RtcDriver { | |||
| 68 | } | 69 | } |
| 69 | 70 | ||
| 70 | fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool { | 71 | fn set_alarm(&self, cs: CriticalSection, timestamp: u64) -> bool { |
| 71 | let rtc = unsafe { &*RTC::ptr() }; | 72 | let rtc = RTC; |
| 72 | let alarm = &self.alarms.borrow(cs); | 73 | let alarm = &self.alarms.borrow(cs); |
| 73 | alarm.timestamp.set(timestamp); | 74 | alarm.timestamp.set(timestamp); |
| 74 | let now = self.now(); | 75 | let now = self.now(); |
| @@ -83,33 +84,38 @@ impl RtcDriver { | |||
| 83 | let sec = (diff / 32768) as u32; | 84 | let sec = (diff / 32768) as u32; |
| 84 | let subsec = (diff % 32768) as u32; | 85 | let subsec = (diff % 32768) as u32; |
| 85 | 86 | ||
| 86 | let current_sec = rtc.count.read().val().bits(); | 87 | let current_sec = rtc.count().read().val(); |
| 87 | let target_sec = current_sec.wrapping_add(sec as u32); | 88 | let target_sec = current_sec.wrapping_add(sec as u32); |
| 88 | 89 | ||
| 89 | rtc.match_.write(|w| unsafe { w.matval().bits(target_sec) }); | 90 | rtc.match_().write(|w| w.set_matval(target_sec)); |
| 90 | rtc.wake.write(|w| unsafe { | 91 | rtc.wake().write(|w| { |
| 91 | let ms = (subsec * 1000) / 32768; | 92 | let ms = (subsec * 1000) / 32768; |
| 92 | w.val().bits(ms as u16) | 93 | w.set_val(ms as u16) |
| 93 | }); | 94 | }); |
| 95 | |||
| 94 | if subsec > 0 { | 96 | if subsec > 0 { |
| 95 | let ms = (subsec * 1000) / 32768; | 97 | let ms = (subsec * 1000) / 32768; |
| 96 | rtc.wake.write(|w| unsafe { w.val().bits(ms as u16) }); | 98 | rtc.wake().write(|w| w.set_val(ms as u16)); |
| 97 | } | 99 | } |
| 98 | rtc.ctrl.modify(|_, w| w.alarm1hz().clear_bit().wake1khz().clear_bit()); | 100 | |
| 101 | rtc.ctrl().modify(|w| { | ||
| 102 | w.set_alarm1hz(false); | ||
| 103 | w.set_wake1khz(rtc::vals::Wake1khz::RUN) | ||
| 104 | }); | ||
| 99 | true | 105 | true |
| 100 | } | 106 | } |
| 101 | 107 | ||
| 102 | fn on_interrupt(&self) { | 108 | fn on_interrupt(&self) { |
| 103 | critical_section::with(|cs| { | 109 | critical_section::with(|cs| { |
| 104 | let rtc = unsafe { &*RTC::ptr() }; | 110 | let rtc = RTC; |
| 105 | let flags = rtc.ctrl.read(); | 111 | let flags = rtc.ctrl().read(); |
| 106 | if flags.alarm1hz().bit_is_clear() { | 112 | if flags.alarm1hz() == false { |
| 107 | rtc.ctrl.modify(|_, w| w.alarm1hz().set_bit()); | 113 | rtc.ctrl().modify(|w| w.set_alarm1hz(true)); |
| 108 | self.trigger_alarm(cs); | 114 | self.trigger_alarm(cs); |
| 109 | } | 115 | } |
| 110 | 116 | ||
| 111 | if flags.wake1khz().bit_is_clear() { | 117 | if flags.wake1khz() == rtc::vals::Wake1khz::RUN { |
| 112 | rtc.ctrl.modify(|_, w| w.wake1khz().set_bit()); | 118 | rtc.ctrl().modify(|w| w.set_wake1khz(rtc::vals::Wake1khz::TIMEOUT)); |
| 113 | self.trigger_alarm(cs); | 119 | self.trigger_alarm(cs); |
| 114 | } | 120 | } |
| 115 | }); | 121 | }); |
| @@ -135,13 +141,13 @@ impl RtcDriver { | |||
| 135 | 141 | ||
| 136 | impl Driver for RtcDriver { | 142 | impl Driver for RtcDriver { |
| 137 | fn now(&self) -> u64 { | 143 | fn now(&self) -> u64 { |
| 138 | let rtc = unsafe { &*RTC::ptr() }; | 144 | let rtc = RTC; |
| 139 | 145 | ||
| 140 | loop { | 146 | loop { |
| 141 | let sec1 = rtc.count.read().val().bits() as u64; | 147 | let sec1 = rtc.count().read().val() as u64; |
| 142 | let sub1 = rtc.subsec.read().subsec().bits() as u64; | 148 | let sub1 = rtc.subsec().read().subsec() as u64; |
| 143 | let sec2 = rtc.count.read().val().bits() as u64; | 149 | let sec2 = rtc.count().read().val() as u64; |
| 144 | let sub2 = rtc.subsec.read().subsec().bits() as u64; | 150 | let sub2 = rtc.subsec().read().subsec() as u64; |
| 145 | 151 | ||
| 146 | if sec1 == sec2 && sub1 == sub2 { | 152 | if sec1 == sec2 && sub1 == sub2 { |
| 147 | return sec1 * 32768 + sub1; | 153 | return sec1 * 32768 + sub1; |
| @@ -162,7 +168,7 @@ impl Driver for RtcDriver { | |||
| 162 | }) | 168 | }) |
| 163 | } | 169 | } |
| 164 | } | 170 | } |
| 165 | #[cortex_m_rt::interrupt] | 171 | #[interrupt] |
| 166 | fn RTC() { | 172 | fn RTC() { |
| 167 | DRIVER.on_interrupt(); | 173 | DRIVER.on_interrupt(); |
| 168 | } | 174 | } |
diff --git a/embassy-nxp/src/usart.rs b/embassy-nxp/src/usart.rs index 009c251e2..1d8886f24 100644 --- a/embassy-nxp/src/usart.rs +++ b/embassy-nxp/src/usart.rs | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | //! Universal Synchronous/Asynchronous Receiver/Transmitter (USART) driver. | 1 | //! Universal Synchronous/Asynchronous Receiver/Transmitter (USART) driver. |
| 2 | #![macro_use] | ||
| 3 | 2 | ||
| 4 | #[cfg_attr(feature = "lpc55", path = "./usart/lpc55.rs")] | 3 | #[cfg_attr(feature = "lpc55-core0", path = "./usart/lpc55.rs")] |
| 5 | mod inner; | 4 | mod inner; |
| 6 | pub use inner::*; | 5 | pub use inner::*; |
diff --git a/embassy-nxp/src/usart/lpc55.rs b/embassy-nxp/src/usart/lpc55.rs index 3f7456a2e..428b80c4b 100644 --- a/embassy-nxp/src/usart/lpc55.rs +++ b/embassy-nxp/src/usart/lpc55.rs | |||
| @@ -2,9 +2,12 @@ use core::marker::PhantomData; | |||
| 2 | 2 | ||
| 3 | use embassy_hal_internal::{Peri, PeripheralType}; | 3 | use embassy_hal_internal::{Peri, PeripheralType}; |
| 4 | use embedded_io::{self, ErrorKind}; | 4 | use embedded_io::{self, ErrorKind}; |
| 5 | pub use sealed::SealedInstance; | ||
| 6 | 5 | ||
| 7 | use crate::gpio::AnyPin; | 6 | use crate::gpio::{match_iocon, AnyPin, Bank, SealedPin}; |
| 7 | use crate::pac::flexcomm::Flexcomm as FlexcommReg; | ||
| 8 | use crate::pac::iocon::vals::PioFunc; | ||
| 9 | use crate::pac::usart::Usart as UsartReg; | ||
| 10 | use crate::pac::*; | ||
| 8 | use crate::{Blocking, Mode}; | 11 | use crate::{Blocking, Mode}; |
| 9 | 12 | ||
| 10 | /// Serial error | 13 | /// Serial error |
| @@ -47,16 +50,6 @@ pub enum DataBits { | |||
| 47 | DataBits9, | 50 | DataBits9, |
| 48 | } | 51 | } |
| 49 | 52 | ||
| 50 | impl DataBits { | ||
| 51 | fn bits(&self) -> u8 { | ||
| 52 | match self { | ||
| 53 | Self::DataBits7 => 0b00, | ||
| 54 | Self::DataBits8 => 0b01, | ||
| 55 | Self::DataBits9 => 0b10, | ||
| 56 | } | ||
| 57 | } | ||
| 58 | } | ||
| 59 | |||
| 60 | /// Parity bit. | 53 | /// Parity bit. |
| 61 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] | 54 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] |
| 62 | pub enum Parity { | 55 | pub enum Parity { |
| @@ -68,16 +61,6 @@ pub enum Parity { | |||
| 68 | ParityOdd, | 61 | ParityOdd, |
| 69 | } | 62 | } |
| 70 | 63 | ||
| 71 | impl Parity { | ||
| 72 | fn bits(&self) -> u8 { | ||
| 73 | match self { | ||
| 74 | Self::ParityNone => 0b00, | ||
| 75 | Self::ParityEven => 0b10, | ||
| 76 | Self::ParityOdd => 0b11, | ||
| 77 | } | ||
| 78 | } | ||
| 79 | } | ||
| 80 | |||
| 81 | /// Stop bits. | 64 | /// Stop bits. |
| 82 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] | 65 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] |
| 83 | pub enum StopBits { | 66 | pub enum StopBits { |
| @@ -87,15 +70,6 @@ pub enum StopBits { | |||
| 87 | Stop2, | 70 | Stop2, |
| 88 | } | 71 | } |
| 89 | 72 | ||
| 90 | impl StopBits { | ||
| 91 | fn bits(&self) -> bool { | ||
| 92 | return match self { | ||
| 93 | Self::Stop1 => false, | ||
| 94 | Self::Stop2 => true, | ||
| 95 | }; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | /// UART config. | 73 | /// UART config. |
| 100 | #[non_exhaustive] | 74 | #[non_exhaustive] |
| 101 | #[derive(Clone, Debug)] | 75 | #[derive(Clone, Debug)] |
| @@ -117,7 +91,7 @@ pub struct Config { | |||
| 117 | impl Default for Config { | 91 | impl Default for Config { |
| 118 | fn default() -> Self { | 92 | fn default() -> Self { |
| 119 | Self { | 93 | Self { |
| 120 | baudrate: 9600, | 94 | baudrate: 115200, |
| 121 | data_bits: DataBits::DataBits8, | 95 | data_bits: DataBits::DataBits8, |
| 122 | stop_bits: StopBits::Stop1, | 96 | stop_bits: StopBits::Stop1, |
| 123 | parity: Parity::ParityNone, | 97 | parity: Parity::ParityNone, |
| @@ -131,59 +105,72 @@ impl Default for Config { | |||
| 131 | /// 'd: the lifetime marker ensuring correct borrow checking for peripherals used at compile time | 105 | /// 'd: the lifetime marker ensuring correct borrow checking for peripherals used at compile time |
| 132 | /// T: the peripheral instance type allowing usage of peripheral specific registers | 106 | /// T: the peripheral instance type allowing usage of peripheral specific registers |
| 133 | /// M: the operating mode of USART peripheral | 107 | /// M: the operating mode of USART peripheral |
| 134 | pub struct Usart<'d, T: Instance, M: Mode> { | 108 | pub struct Usart<'d, M: Mode> { |
| 135 | tx: UsartTx<'d, T, M>, | 109 | tx: UsartTx<'d, M>, |
| 136 | rx: UsartRx<'d, T, M>, | 110 | rx: UsartRx<'d, M>, |
| 137 | } | 111 | } |
| 138 | 112 | ||
| 139 | pub struct UsartTx<'d, T: Instance, M: Mode> { | 113 | pub struct UsartTx<'d, M: Mode> { |
| 140 | phantom: PhantomData<(&'d (), T, M)>, | 114 | info: &'static Info, |
| 115 | phantom: PhantomData<(&'d (), M)>, | ||
| 141 | } | 116 | } |
| 142 | 117 | ||
| 143 | pub struct UsartRx<'d, T: Instance, M: Mode> { | 118 | pub struct UsartRx<'d, M: Mode> { |
| 144 | phantom: PhantomData<(&'d (), T, M)>, | 119 | info: &'static Info, |
| 120 | phantom: PhantomData<(&'d (), M)>, | ||
| 145 | } | 121 | } |
| 146 | 122 | ||
| 147 | impl<'d, T: Instance, M: Mode> UsartTx<'d, T, M> { | 123 | impl<'d, M: Mode> UsartTx<'d, M> { |
| 148 | pub fn new(_usart: Peri<'d, T>, tx: Peri<'d, impl TxPin<T>>, config: Config) -> Self { | 124 | pub fn new<T: Instance>(_usart: Peri<'d, T>, tx: Peri<'d, impl TxPin<T>>, config: Config) -> Self { |
| 149 | Usart::<T, M>::init(Some(tx.into()), None, config); | 125 | Usart::<M>::init::<T>(Some(tx.into()), None, config); |
| 150 | Self::new_inner() | 126 | Self::new_inner(T::info()) |
| 151 | } | 127 | } |
| 152 | 128 | ||
| 153 | #[inline] | 129 | #[inline] |
| 154 | fn new_inner() -> Self { | 130 | fn new_inner(info: &'static Info) -> Self { |
| 155 | Self { phantom: PhantomData } | 131 | Self { |
| 132 | info, | ||
| 133 | phantom: PhantomData, | ||
| 134 | } | ||
| 156 | } | 135 | } |
| 157 | 136 | ||
| 158 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { | 137 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 159 | T::blocking_write(buffer) | 138 | for &b in buffer { |
| 139 | while !(self.info.usart_reg.fifostat().read().txnotfull()) {} | ||
| 140 | self.info.usart_reg.fifowr().write(|w| w.set_txdata(b as u16)); | ||
| 141 | } | ||
| 142 | Ok(()) | ||
| 160 | } | 143 | } |
| 161 | 144 | ||
| 162 | pub fn blocking_flush(&mut self) -> Result<(), Error> { | 145 | pub fn blocking_flush(&mut self) -> Result<(), Error> { |
| 163 | T::blocking_flush() | 146 | while !(self.info.usart_reg.fifostat().read().txempty()) {} |
| 147 | Ok(()) | ||
| 164 | } | 148 | } |
| 165 | 149 | ||
| 166 | pub fn tx_busy(&self) -> bool { | 150 | pub fn tx_busy(&self) -> bool { |
| 167 | T::tx_busy() | 151 | !(self.info.usart_reg.fifostat().read().txempty()) |
| 168 | } | 152 | } |
| 169 | } | 153 | } |
| 170 | 154 | ||
| 171 | impl<'d, T: Instance> UsartTx<'d, T, Blocking> { | 155 | impl<'d> UsartTx<'d, Blocking> { |
| 172 | pub fn new_blocking(_usart: Peri<'d, T>, tx: Peri<'d, impl TxPin<T>>, config: Config) -> Self { | 156 | pub fn new_blocking<T: Instance>(_usart: Peri<'d, T>, tx: Peri<'d, impl TxPin<T>>, config: Config) -> Self { |
| 173 | Usart::<T, Blocking>::init(Some(tx.into()), None, config); | 157 | Usart::<Blocking>::init::<T>(Some(tx.into()), None, config); |
| 174 | Self::new_inner() | 158 | Self::new_inner(T::info()) |
| 175 | } | 159 | } |
| 176 | } | 160 | } |
| 177 | 161 | ||
| 178 | impl<'d, T: Instance, M: Mode> UsartRx<'d, T, M> { | 162 | impl<'d, M: Mode> UsartRx<'d, M> { |
| 179 | pub fn new(_usart: Peri<'d, T>, rx: Peri<'d, impl RxPin<T>>, config: Config) -> Self { | 163 | pub fn new<T: Instance>(_usart: Peri<'d, T>, rx: Peri<'d, impl RxPin<T>>, config: Config) -> Self { |
| 180 | Usart::<T, M>::init(None, Some(rx.into()), config); | 164 | Usart::<M>::init::<T>(None, Some(rx.into()), config); |
| 181 | Self::new_inner() | 165 | Self::new_inner(T::info()) |
| 182 | } | 166 | } |
| 183 | 167 | ||
| 184 | #[inline] | 168 | #[inline] |
| 185 | fn new_inner() -> Self { | 169 | fn new_inner(info: &'static Info) -> Self { |
| 186 | Self { phantom: PhantomData } | 170 | Self { |
| 171 | info, | ||
| 172 | phantom: PhantomData, | ||
| 173 | } | ||
| 187 | } | 174 | } |
| 188 | 175 | ||
| 189 | pub fn blocking_read(&mut self, mut buffer: &mut [u8]) -> Result<(), Error> { | 176 | pub fn blocking_read(&mut self, mut buffer: &mut [u8]) -> Result<(), Error> { |
| @@ -201,19 +188,35 @@ impl<'d, T: Instance, M: Mode> UsartRx<'d, T, M> { | |||
| 201 | /// - Ok(n) -> read n bytes | 188 | /// - Ok(n) -> read n bytes |
| 202 | /// - Err(n, Error) -> read n-1 bytes, but encountered an error while reading nth byte | 189 | /// - Err(n, Error) -> read n-1 bytes, but encountered an error while reading nth byte |
| 203 | fn drain_fifo(&mut self, buffer: &mut [u8]) -> Result<usize, (usize, Error)> { | 190 | fn drain_fifo(&mut self, buffer: &mut [u8]) -> Result<usize, (usize, Error)> { |
| 204 | T::drain_fifo(buffer) | 191 | for (i, b) in buffer.iter_mut().enumerate() { |
| 192 | while !(self.info.usart_reg.fifostat().read().rxnotempty()) {} | ||
| 193 | if self.info.usart_reg.fifostat().read().rxerr() { | ||
| 194 | return Err((i, Error::Overrun)); | ||
| 195 | } else if self.info.usart_reg.fifordnopop().read().parityerr() { | ||
| 196 | return Err((i, Error::Parity)); | ||
| 197 | } else if self.info.usart_reg.fifordnopop().read().framerr() { | ||
| 198 | return Err((i, Error::Framing)); | ||
| 199 | } else if self.info.usart_reg.fifordnopop().read().rxnoise() { | ||
| 200 | return Err((i, Error::Noise)); | ||
| 201 | } else if self.info.usart_reg.intstat().read().deltarxbrk() { | ||
| 202 | return Err((i, Error::Break)); | ||
| 203 | } | ||
| 204 | let dr = self.info.usart_reg.fiford().read().rxdata() as u8; | ||
| 205 | *b = dr; | ||
| 206 | } | ||
| 207 | Ok(buffer.len()) | ||
| 205 | } | 208 | } |
| 206 | } | 209 | } |
| 207 | 210 | ||
| 208 | impl<'d, T: Instance> UsartRx<'d, T, Blocking> { | 211 | impl<'d> UsartRx<'d, Blocking> { |
| 209 | pub fn new_blocking(_usart: Peri<'d, T>, rx: Peri<'d, impl RxPin<T>>, config: Config) -> Self { | 212 | pub fn new_blocking<T: Instance>(_usart: Peri<'d, T>, rx: Peri<'d, impl RxPin<T>>, config: Config) -> Self { |
| 210 | Usart::<T, Blocking>::init(None, Some(rx.into()), config); | 213 | Usart::<Blocking>::init::<T>(None, Some(rx.into()), config); |
| 211 | Self::new_inner() | 214 | Self::new_inner(T::info()) |
| 212 | } | 215 | } |
| 213 | } | 216 | } |
| 214 | 217 | ||
| 215 | impl<'d, T: Instance> Usart<'d, T, Blocking> { | 218 | impl<'d> Usart<'d, Blocking> { |
| 216 | pub fn new_blocking( | 219 | pub fn new_blocking<T: Instance>( |
| 217 | usart: Peri<'d, T>, | 220 | usart: Peri<'d, T>, |
| 218 | tx: Peri<'d, impl TxPin<T>>, | 221 | tx: Peri<'d, impl TxPin<T>>, |
| 219 | rx: Peri<'d, impl RxPin<T>>, | 222 | rx: Peri<'d, impl RxPin<T>>, |
| @@ -223,29 +226,70 @@ impl<'d, T: Instance> Usart<'d, T, Blocking> { | |||
| 223 | } | 226 | } |
| 224 | } | 227 | } |
| 225 | 228 | ||
| 226 | impl<'d, T: Instance, M: Mode> Usart<'d, T, M> { | 229 | impl<'d, M: Mode> Usart<'d, M> { |
| 227 | fn new_inner(_usart: Peri<'d, T>, mut tx: Peri<'d, AnyPin>, mut rx: Peri<'d, AnyPin>, config: Config) -> Self { | 230 | fn new_inner<T: Instance>( |
| 228 | Self::init(Some(tx.reborrow()), Some(rx.reborrow()), config); | 231 | _usart: Peri<'d, T>, |
| 232 | mut tx: Peri<'d, AnyPin>, | ||
| 233 | mut rx: Peri<'d, AnyPin>, | ||
| 234 | config: Config, | ||
| 235 | ) -> Self { | ||
| 236 | Self::init::<T>(Some(tx.reborrow()), Some(rx.reborrow()), config); | ||
| 229 | Self { | 237 | Self { |
| 230 | tx: UsartTx::new_inner(), | 238 | tx: UsartTx::new_inner(T::info()), |
| 231 | rx: UsartRx::new_inner(), | 239 | rx: UsartRx::new_inner(T::info()), |
| 232 | } | 240 | } |
| 233 | } | 241 | } |
| 234 | 242 | ||
| 235 | fn init(_tx: Option<Peri<'_, AnyPin>>, _rx: Option<Peri<'_, AnyPin>>, config: Config) { | 243 | fn init<T: Instance>(tx: Option<Peri<'_, AnyPin>>, rx: Option<Peri<'_, AnyPin>>, config: Config) { |
| 236 | T::enable_clock(); | 244 | Self::configure_flexcomm(T::info().fc_reg, T::instance_number()); |
| 237 | T::reset_flexcomm(); | 245 | Self::configure_clock::<T>(&config); |
| 238 | let source_clock: u32 = T::select_clock(config.baudrate); | 246 | Self::pin_config::<T>(tx, rx); |
| 239 | T::configure_flexcomm(); | 247 | Self::configure_usart(T::info(), &config); |
| 240 | T::tx_pin_config(); | ||
| 241 | T::rx_pin_config(); | ||
| 242 | Self::set_baudrate(source_clock, config.baudrate); | ||
| 243 | T::configure_usart(config); | ||
| 244 | T::disable_dma(); | ||
| 245 | T::enable_usart(); | ||
| 246 | } | 248 | } |
| 247 | 249 | ||
| 248 | fn set_baudrate(source_clock: u32, baudrate: u32) { | 250 | fn configure_clock<T: Instance>(config: &Config) { |
| 251 | // Select source clock | ||
| 252 | |||
| 253 | // Adaptive clock choice based on baud rate | ||
| 254 | // To get the desired baud rate, it is essential to choose the clock bigger than baud rate so that it can be 'chiseled' | ||
| 255 | // There are two types of dividers: integer divider (baud rate generator register and oversample selection value) | ||
| 256 | // and fractional divider (fractional rate divider). | ||
| 257 | |||
| 258 | // By default, oversampling rate is 16 which is an industry standard. | ||
| 259 | // That means 16 clocks are used to deliver the byte to recipient. | ||
| 260 | // In this way the probability of getting correct bytes instead of noise directly increases as oversampling increases as well. | ||
| 261 | |||
| 262 | // Minimum and maximum values were computed taking these formulas into account: | ||
| 263 | // For minimum value, MULT = 0, BRGVAL = 0 | ||
| 264 | // For maximum value, MULT = 255, BRGVAL = 255 | ||
| 265 | // Flexcomm Interface function clock = (clock selected via FCCLKSEL) / (1 + MULT / DIV) | ||
| 266 | // By default, OSRVAL = 15 (see above) | ||
| 267 | // Baud rate = [FCLK / (OSRVAL+1)] / (BRGVAL + 1) | ||
| 268 | let source_clock = match config.baudrate { | ||
| 269 | 750_001..=6_000_000 => { | ||
| 270 | SYSCON | ||
| 271 | .fcclksel(T::instance_number()) | ||
| 272 | .modify(|w| w.set_sel(syscon::vals::FcclkselSel::ENUM_0X3)); // 96 MHz | ||
| 273 | 96_000_000 | ||
| 274 | } | ||
| 275 | 1501..=750_000 => { | ||
| 276 | SYSCON | ||
| 277 | .fcclksel(T::instance_number()) | ||
| 278 | .modify(|w| w.set_sel(syscon::vals::FcclkselSel::ENUM_0X2)); // 12 MHz | ||
| 279 | 12_000_000 | ||
| 280 | } | ||
| 281 | 121..=1500 => { | ||
| 282 | SYSCON | ||
| 283 | .fcclksel(T::instance_number()) | ||
| 284 | .modify(|w| w.set_sel(syscon::vals::FcclkselSel::ENUM_0X4)); // 1 MHz | ||
| 285 | 1_000_000 | ||
| 286 | } | ||
| 287 | _ => { | ||
| 288 | panic!("{} baudrate is not permitted in this mode", config.baudrate); | ||
| 289 | } | ||
| 290 | }; | ||
| 291 | // Calculate MULT and BRG values based on baudrate | ||
| 292 | |||
| 249 | // There are two types of dividers: integer divider (baud rate generator register and oversample selection value) | 293 | // There are two types of dividers: integer divider (baud rate generator register and oversample selection value) |
| 250 | // and fractional divider (fractional rate divider). | 294 | // and fractional divider (fractional rate divider). |
| 251 | // For oversampling, the default is industry standard 16x oversampling, i.e. OSRVAL = 15 | 295 | // For oversampling, the default is industry standard 16x oversampling, i.e. OSRVAL = 15 |
| @@ -274,14 +318,167 @@ impl<'d, T: Instance, M: Mode> Usart<'d, T, M> { | |||
| 274 | // Secondly, MULT is calculated to ultimately 'chisel' the clock to get the baud rate. | 318 | // Secondly, MULT is calculated to ultimately 'chisel' the clock to get the baud rate. |
| 275 | // The deduced formulas are written below. | 319 | // The deduced formulas are written below. |
| 276 | 320 | ||
| 277 | let brg_value = (source_clock / (16 * baudrate)).min(255); | 321 | let brg_value = (source_clock / (16 * config.baudrate)).min(255); |
| 278 | let raw_clock = source_clock / (16 * brg_value); | 322 | let raw_clock = source_clock / (16 * brg_value); |
| 279 | let mult_value = ((raw_clock * 256 / baudrate) - 256).min(255); | 323 | let mult_value = ((raw_clock * 256 / config.baudrate) - 256).min(255); |
| 280 | T::set_baudrate(mult_value as u8, brg_value as u8); | 324 | |
| 325 | // Write values to the registers | ||
| 326 | |||
| 327 | // FCLK = (clock selected via FCCLKSEL) / (1+ MULT / DIV) | ||
| 328 | // Remark: To use the fractional baud rate generator, 0xFF must be wirtten to the DIV value | ||
| 329 | // to yield a denominator vale of 256. All other values are not supported | ||
| 330 | SYSCON.flexfrgctrl(T::instance_number()).modify(|w| { | ||
| 331 | w.set_div(0xFF); | ||
| 332 | w.set_mult(mult_value as u8); | ||
| 333 | }); | ||
| 334 | |||
| 335 | // Baud rate = [FCLK / (OSRVAL+1)] / (BRGVAL + 1) | ||
| 336 | // By default, oversampling is 16x, i.e. OSRVAL = 15 | ||
| 337 | |||
| 338 | // Typical industry standard USARTs use a 16x oversample clock to transmit and receive | ||
| 339 | // asynchronous data. This is the number of BRG clocks used for one data bit. The | ||
| 340 | // Oversample Select Register (OSR) allows this USART to use a 16x down to a 5x | ||
| 341 | // oversample clock. There is no oversampling in synchronous modes. | ||
| 342 | T::info() | ||
| 343 | .usart_reg | ||
| 344 | .brg() | ||
| 345 | .modify(|w| w.set_brgval((brg_value - 1) as u16)); | ||
| 346 | } | ||
| 347 | |||
| 348 | fn pin_config<T: Instance>(tx: Option<Peri<'_, AnyPin>>, rx: Option<Peri<'_, AnyPin>>) { | ||
| 349 | if let Some(tx_pin) = tx { | ||
| 350 | match_iocon!(register, tx_pin.pin_bank(), tx_pin.pin_number(), { | ||
| 351 | register.modify(|w| { | ||
| 352 | w.set_func(T::tx_pin_func()); | ||
| 353 | w.set_mode(iocon::vals::PioMode::INACTIVE); | ||
| 354 | w.set_slew(iocon::vals::PioSlew::STANDARD); | ||
| 355 | w.set_invert(false); | ||
| 356 | w.set_digimode(iocon::vals::PioDigimode::DIGITAL); | ||
| 357 | w.set_od(iocon::vals::PioOd::NORMAL); | ||
| 358 | }); | ||
| 359 | }) | ||
| 360 | } | ||
| 361 | |||
| 362 | if let Some(rx_pin) = rx { | ||
| 363 | match_iocon!(register, rx_pin.pin_bank(), rx_pin.pin_number(), { | ||
| 364 | register.modify(|w| { | ||
| 365 | w.set_func(T::rx_pin_func()); | ||
| 366 | w.set_mode(iocon::vals::PioMode::INACTIVE); | ||
| 367 | w.set_slew(iocon::vals::PioSlew::STANDARD); | ||
| 368 | w.set_invert(false); | ||
| 369 | w.set_digimode(iocon::vals::PioDigimode::DIGITAL); | ||
| 370 | w.set_od(iocon::vals::PioOd::NORMAL); | ||
| 371 | }); | ||
| 372 | }) | ||
| 373 | }; | ||
| 374 | } | ||
| 375 | |||
| 376 | fn configure_flexcomm(flexcomm_register: crate::pac::flexcomm::Flexcomm, instance_number: usize) { | ||
| 377 | critical_section::with(|_cs| { | ||
| 378 | if !(SYSCON.ahbclkctrl0().read().iocon()) { | ||
| 379 | SYSCON.ahbclkctrl0().modify(|w| w.set_iocon(true)); | ||
| 380 | } | ||
| 381 | }); | ||
| 382 | critical_section::with(|_cs| { | ||
| 383 | if !(SYSCON.ahbclkctrl1().read().fc(instance_number)) { | ||
| 384 | SYSCON.ahbclkctrl1().modify(|w| w.set_fc(instance_number, true)); | ||
| 385 | } | ||
| 386 | }); | ||
| 387 | SYSCON | ||
| 388 | .presetctrl1() | ||
| 389 | .modify(|w| w.set_fc_rst(instance_number, syscon::vals::FcRst::ASSERTED)); | ||
| 390 | SYSCON | ||
| 391 | .presetctrl1() | ||
| 392 | .modify(|w| w.set_fc_rst(instance_number, syscon::vals::FcRst::RELEASED)); | ||
| 393 | flexcomm_register | ||
| 394 | .pselid() | ||
| 395 | .modify(|w| w.set_persel(flexcomm::vals::Persel::USART)); | ||
| 396 | } | ||
| 397 | |||
| 398 | fn configure_usart(info: &'static Info, config: &Config) { | ||
| 399 | let registers = info.usart_reg; | ||
| 400 | // See section 34.6.1 | ||
| 401 | registers.cfg().modify(|w| { | ||
| 402 | // LIN break mode enable | ||
| 403 | // Disabled. Break detect and generate is configured for normal operation. | ||
| 404 | w.set_linmode(false); | ||
| 405 | //CTS Enable. Determines whether CTS is used for flow control. CTS can be from the | ||
| 406 | //input pin, or from the USART’s own RTS if loopback mode is enabled. | ||
| 407 | // No flow control. The transmitter does not receive any automatic flow control signal. | ||
| 408 | w.set_ctsen(false); | ||
| 409 | // Selects synchronous or asynchronous operation. | ||
| 410 | w.set_syncen(usart::vals::Syncen::ASYNCHRONOUS_MODE); | ||
| 411 | // Selects the clock polarity and sampling edge of received data in synchronous mode. | ||
| 412 | w.set_clkpol(usart::vals::Clkpol::RISING_EDGE); | ||
| 413 | // Synchronous mode Master select. | ||
| 414 | // When synchronous mode is enabled, the USART is a master. | ||
| 415 | w.set_syncmst(usart::vals::Syncmst::MASTER); | ||
| 416 | // Selects data loopback mode | ||
| 417 | w.set_loop_(usart::vals::Loop::NORMAL); | ||
| 418 | // Output Enable Turnaround time enable for RS-485 operation. | ||
| 419 | // Disabled. If selected by OESEL, the Output Enable signal deasserted at the end of | ||
| 420 | // the last stop bit of a transmission. | ||
| 421 | w.set_oeta(false); | ||
| 422 | // Output enable select. | ||
| 423 | // Standard. The RTS signal is used as the standard flow control function. | ||
| 424 | w.set_oesel(usart::vals::Oesel::STANDARD); | ||
| 425 | // Automatic address matching enable. | ||
| 426 | // Disabled. When addressing is enabled by ADDRDET, address matching is done by | ||
| 427 | // software. This provides the possibility of versatile addressing (e.g. respond to more | ||
| 428 | // than one address) | ||
| 429 | w.set_autoaddr(false); | ||
| 430 | // Output enable polarity. | ||
| 431 | // Low. If selected by OESEL, the output enable is active low. | ||
| 432 | w.set_oepol(usart::vals::Oepol::LOW); | ||
| 433 | }); | ||
| 434 | |||
| 435 | // Configurations based on the config written by a user | ||
| 436 | registers.cfg().modify(|w| { | ||
| 437 | w.set_datalen(match config.data_bits { | ||
| 438 | DataBits::DataBits7 => usart::vals::Datalen::BIT_7, | ||
| 439 | DataBits::DataBits8 => usart::vals::Datalen::BIT_8, | ||
| 440 | DataBits::DataBits9 => usart::vals::Datalen::BIT_9, | ||
| 441 | }); | ||
| 442 | w.set_paritysel(match config.parity { | ||
| 443 | Parity::ParityNone => usart::vals::Paritysel::NO_PARITY, | ||
| 444 | Parity::ParityEven => usart::vals::Paritysel::EVEN_PARITY, | ||
| 445 | Parity::ParityOdd => usart::vals::Paritysel::ODD_PARITY, | ||
| 446 | }); | ||
| 447 | w.set_stoplen(match config.stop_bits { | ||
| 448 | StopBits::Stop1 => usart::vals::Stoplen::BIT_1, | ||
| 449 | StopBits::Stop2 => usart::vals::Stoplen::BITS_2, | ||
| 450 | }); | ||
| 451 | w.set_rxpol(match config.invert_rx { | ||
| 452 | false => usart::vals::Rxpol::STANDARD, | ||
| 453 | true => usart::vals::Rxpol::INVERTED, | ||
| 454 | }); | ||
| 455 | w.set_txpol(match config.invert_tx { | ||
| 456 | false => usart::vals::Txpol::STANDARD, | ||
| 457 | true => usart::vals::Txpol::INVERTED, | ||
| 458 | }); | ||
| 459 | }); | ||
| 460 | |||
| 461 | // DMA-related settings | ||
| 462 | registers.fifocfg().modify(|w| { | ||
| 463 | w.set_dmatx(false); | ||
| 464 | w.set_dmatx(false); | ||
| 465 | }); | ||
| 466 | |||
| 467 | // Enabling USART | ||
| 468 | registers.fifocfg().modify(|w| { | ||
| 469 | w.set_enabletx(true); | ||
| 470 | w.set_enablerx(true); | ||
| 471 | }); | ||
| 472 | registers.cfg().modify(|w| w.set_enable(true)); | ||
| 473 | |||
| 474 | // Drain RX FIFO in case it still has some unrelevant data | ||
| 475 | while registers.fifostat().read().rxnotempty() { | ||
| 476 | let _ = registers.fiford().read().0; | ||
| 477 | } | ||
| 281 | } | 478 | } |
| 282 | } | 479 | } |
| 283 | 480 | ||
| 284 | impl<'d, T: Instance, M: Mode> Usart<'d, T, M> { | 481 | impl<'d, M: Mode> Usart<'d, M> { |
| 285 | /// Transmit the provided buffer blocking execution until done. | 482 | /// Transmit the provided buffer blocking execution until done. |
| 286 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { | 483 | pub fn blocking_write(&mut self, buffer: &[u8]) -> Result<(), Error> { |
| 287 | self.tx.blocking_write(buffer) | 484 | self.tx.blocking_write(buffer) |
| @@ -304,19 +501,19 @@ impl<'d, T: Instance, M: Mode> Usart<'d, T, M> { | |||
| 304 | 501 | ||
| 305 | /// Split the Usart into a transmitter and receiver, which is particularly | 502 | /// Split the Usart into a transmitter and receiver, which is particularly |
| 306 | /// useful when having two tasks correlating to transmitting and receiving. | 503 | /// useful when having two tasks correlating to transmitting and receiving. |
| 307 | pub fn split(self) -> (UsartTx<'d, T, M>, UsartRx<'d, T, M>) { | 504 | pub fn split(self) -> (UsartTx<'d, M>, UsartRx<'d, M>) { |
| 308 | (self.tx, self.rx) | 505 | (self.tx, self.rx) |
| 309 | } | 506 | } |
| 310 | 507 | ||
| 311 | /// Split the Usart into a transmitter and receiver by mutable reference, | 508 | /// Split the Usart into a transmitter and receiver by mutable reference, |
| 312 | /// which is particularly useful when having two tasks correlating to | 509 | /// which is particularly useful when having two tasks correlating to |
| 313 | /// transmitting and receiving. | 510 | /// transmitting and receiving. |
| 314 | pub fn split_ref(&mut self) -> (&mut UsartTx<'d, T, M>, &mut UsartRx<'d, T, M>) { | 511 | pub fn split_ref(&mut self) -> (&mut UsartTx<'d, M>, &mut UsartRx<'d, M>) { |
| 315 | (&mut self.tx, &mut self.rx) | 512 | (&mut self.tx, &mut self.rx) |
| 316 | } | 513 | } |
| 317 | } | 514 | } |
| 318 | 515 | ||
| 319 | impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UsartTx<'d, T, M> { | 516 | impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for UsartTx<'d, M> { |
| 320 | type Error = Error; | 517 | type Error = Error; |
| 321 | 518 | ||
| 322 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | 519 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { |
| @@ -328,7 +525,7 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for | |||
| 328 | } | 525 | } |
| 329 | } | 526 | } |
| 330 | 527 | ||
| 331 | impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Usart<'d, T, M> { | 528 | impl<'d, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for Usart<'d, M> { |
| 332 | type Error = Error; | 529 | type Error = Error; |
| 333 | 530 | ||
| 334 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { | 531 | fn bwrite_all(&mut self, buffer: &[u8]) -> Result<(), Self::Error> { |
| @@ -340,11 +537,11 @@ impl<'d, T: Instance, M: Mode> embedded_hal_02::blocking::serial::Write<u8> for | |||
| 340 | } | 537 | } |
| 341 | } | 538 | } |
| 342 | 539 | ||
| 343 | impl<'d, T: Instance> embedded_io::ErrorType for UsartTx<'d, T, Blocking> { | 540 | impl<'d> embedded_io::ErrorType for UsartTx<'d, Blocking> { |
| 344 | type Error = Error; | 541 | type Error = Error; |
| 345 | } | 542 | } |
| 346 | 543 | ||
| 347 | impl<'d, T: Instance> embedded_io::Write for UsartTx<'d, T, Blocking> { | 544 | impl<'d> embedded_io::Write for UsartTx<'d, Blocking> { |
| 348 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 545 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 349 | self.blocking_write(buf).map(|_| buf.len()) | 546 | self.blocking_write(buf).map(|_| buf.len()) |
| 350 | } | 547 | } |
| @@ -354,21 +551,21 @@ impl<'d, T: Instance> embedded_io::Write for UsartTx<'d, T, Blocking> { | |||
| 354 | } | 551 | } |
| 355 | } | 552 | } |
| 356 | 553 | ||
| 357 | impl<'d, T: Instance> embedded_io::ErrorType for UsartRx<'d, T, Blocking> { | 554 | impl<'d> embedded_io::ErrorType for UsartRx<'d, Blocking> { |
| 358 | type Error = Error; | 555 | type Error = Error; |
| 359 | } | 556 | } |
| 360 | 557 | ||
| 361 | impl<'d, T: Instance> embedded_io::Read for UsartRx<'d, T, Blocking> { | 558 | impl<'d> embedded_io::Read for UsartRx<'d, Blocking> { |
| 362 | fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { | 559 | fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { |
| 363 | self.blocking_read(buf).map(|_| buf.len()) | 560 | self.blocking_read(buf).map(|_| buf.len()) |
| 364 | } | 561 | } |
| 365 | } | 562 | } |
| 366 | 563 | ||
| 367 | impl<'d, T: Instance> embedded_io::ErrorType for Usart<'d, T, Blocking> { | 564 | impl<'d> embedded_io::ErrorType for Usart<'d, Blocking> { |
| 368 | type Error = Error; | 565 | type Error = Error; |
| 369 | } | 566 | } |
| 370 | 567 | ||
| 371 | impl<'d, T: Instance> embedded_io::Write for Usart<'d, T, Blocking> { | 568 | impl<'d> embedded_io::Write for Usart<'d, Blocking> { |
| 372 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { | 569 | fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> { |
| 373 | self.blocking_write(buf).map(|_| buf.len()) | 570 | self.blocking_write(buf).map(|_| buf.len()) |
| 374 | } | 571 | } |
| @@ -378,468 +575,69 @@ impl<'d, T: Instance> embedded_io::Write for Usart<'d, T, Blocking> { | |||
| 378 | } | 575 | } |
| 379 | } | 576 | } |
| 380 | 577 | ||
| 381 | impl<'d, T: Instance> embedded_io::Read for Usart<'d, T, Blocking> { | 578 | impl<'d> embedded_io::Read for Usart<'d, Blocking> { |
| 382 | fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { | 579 | fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> { |
| 383 | self.blocking_read(buf).map(|_| buf.len()) | 580 | self.blocking_read(buf).map(|_| buf.len()) |
| 384 | } | 581 | } |
| 385 | } | 582 | } |
| 386 | 583 | ||
| 387 | type UsartRegBlock = crate::pac::usart0::RegisterBlock; | 584 | struct Info { |
| 388 | 585 | usart_reg: UsartReg, | |
| 389 | mod sealed { | 586 | fc_reg: FlexcommReg, |
| 390 | use crate::usart::inner::UsartRegBlock; | 587 | } |
| 391 | use crate::usart::{Config, Error}; | ||
| 392 | pub trait SealedInstance { | ||
| 393 | fn usart_reg() -> &'static UsartRegBlock; | ||
| 394 | fn enable_clock(); | ||
| 395 | fn select_clock(baudrate: u32) -> u32; | ||
| 396 | fn configure_flexcomm(); | ||
| 397 | fn set_baudrate(mult_value: u8, brg_value: u8); | ||
| 398 | fn reset_flexcomm(); | ||
| 399 | fn tx_pin_config(); | ||
| 400 | fn rx_pin_config(); | ||
| 401 | |||
| 402 | fn configure_usart(config: Config) { | ||
| 403 | // See section 34.6.1 | ||
| 404 | Self::usart_reg().cfg.modify(|_, w| { | ||
| 405 | // LIN break mode enable | ||
| 406 | w.linmode() | ||
| 407 | // Disabled. Break detect and generate is configured for normal operation. | ||
| 408 | .disabled() | ||
| 409 | //CTS Enable. Determines whether CTS is used for flow control. CTS can be from the | ||
| 410 | //input pin, or from the USART’s own RTS if loopback mode is enabled. | ||
| 411 | .ctsen() | ||
| 412 | // No flow control. The transmitter does not receive any automatic flow control signal. | ||
| 413 | .disabled() | ||
| 414 | // Selects synchronous or asynchronous operation. | ||
| 415 | .syncen() | ||
| 416 | .asynchronous_mode() | ||
| 417 | // Selects the clock polarity and sampling edge of received data in synchronous mode. | ||
| 418 | .clkpol() | ||
| 419 | .rising_edge() | ||
| 420 | // Synchronous mode Master select. | ||
| 421 | .syncmst() | ||
| 422 | // When synchronous mode is enabled, the USART is a master. | ||
| 423 | .master() | ||
| 424 | // Selects data loopback mode | ||
| 425 | .loop_() | ||
| 426 | // Normal operation | ||
| 427 | .normal() | ||
| 428 | // Output Enable Turnaround time enable for RS-485 operation. | ||
| 429 | .oeta() | ||
| 430 | // Disabled. If selected by OESEL, the Output Enable signal deasserted at the end of | ||
| 431 | // the last stop bit of a transmission. | ||
| 432 | .disabled() | ||
| 433 | // Output enable select. | ||
| 434 | .oesel() | ||
| 435 | // Standard. The RTS signal is used as the standard flow control function. | ||
| 436 | .standard() | ||
| 437 | // Automatic address matching enable. | ||
| 438 | .autoaddr() | ||
| 439 | // Disabled. When addressing is enabled by ADDRDET, address matching is done by | ||
| 440 | // software. This provides the possibility of versatile addressing (e.g. respond to more | ||
| 441 | // than one address) | ||
| 442 | .disabled() | ||
| 443 | // Output enable polarity. | ||
| 444 | .oepol() | ||
| 445 | // Low. If selected by OESEL, the output enable is active low. | ||
| 446 | .low() | ||
| 447 | }); | ||
| 448 | 588 | ||
| 449 | Self::usart_reg().cfg.modify(|_, w| unsafe { | 589 | trait SealedInstance { |
| 450 | w.datalen() | 590 | fn info() -> &'static Info; |
| 451 | .bits(config.data_bits.bits()) | 591 | fn instance_number() -> usize; |
| 452 | .paritysel() | 592 | fn tx_pin_func() -> PioFunc; |
| 453 | .bits(config.parity.bits()) | 593 | fn rx_pin_func() -> PioFunc; |
| 454 | .stoplen() | ||
| 455 | .bit(config.stop_bits.bits()) | ||
| 456 | .rxpol() | ||
| 457 | .bit(config.invert_rx) | ||
| 458 | .txpol() | ||
| 459 | .bit(config.invert_tx) | ||
| 460 | }); | ||
| 461 | } | ||
| 462 | fn disable_dma() { | ||
| 463 | Self::usart_reg() | ||
| 464 | .fifocfg | ||
| 465 | .modify(|_, w| w.dmatx().disabled().dmarx().disabled()); | ||
| 466 | } | ||
| 467 | fn enable_usart() { | ||
| 468 | Self::usart_reg() | ||
| 469 | .fifocfg | ||
| 470 | .modify(|_, w| w.enabletx().enabled().enablerx().enabled()); | ||
| 471 | Self::usart_reg().cfg.modify(|_, w| w.enable().enabled()); | ||
| 472 | while Self::usart_reg().fifostat.read().rxnotempty().bit_is_set() { | ||
| 473 | let _ = Self::usart_reg().fiford.read().bits(); | ||
| 474 | } | ||
| 475 | } | ||
| 476 | fn blocking_write(buffer: &[u8]) -> Result<(), Error> { | ||
| 477 | for &b in buffer { | ||
| 478 | while Self::usart_reg().fifostat.read().txnotfull().bit_is_clear() {} | ||
| 479 | Self::usart_reg() | ||
| 480 | .fifowr | ||
| 481 | .modify(|_, w| unsafe { w.txdata().bits(b as u16) }); | ||
| 482 | } | ||
| 483 | Ok(()) | ||
| 484 | } | ||
| 485 | fn blocking_flush() -> Result<(), Error> { | ||
| 486 | while Self::usart_reg().fifostat.read().txempty().bit_is_clear() {} | ||
| 487 | Ok(()) | ||
| 488 | } | ||
| 489 | fn tx_busy() -> bool { | ||
| 490 | Self::usart_reg().fifostat.read().txempty().bit_is_clear() | ||
| 491 | } | ||
| 492 | fn drain_fifo(buffer: &mut [u8]) -> Result<usize, (usize, Error)> { | ||
| 493 | for (i, b) in buffer.iter_mut().enumerate() { | ||
| 494 | while Self::usart_reg().fifostat.read().rxnotempty().bit_is_clear() {} | ||
| 495 | |||
| 496 | if Self::usart_reg().fifostat.read().rxerr().bit_is_set() { | ||
| 497 | return Err((i, Error::Overrun)); | ||
| 498 | } else if Self::usart_reg().fifordnopop.read().parityerr().bit_is_set() { | ||
| 499 | return Err((i, Error::Parity)); | ||
| 500 | } else if Self::usart_reg().fifordnopop.read().framerr().bit_is_set() { | ||
| 501 | return Err((i, Error::Framing)); | ||
| 502 | } else if Self::usart_reg().fifordnopop.read().rxnoise().bit_is_set() { | ||
| 503 | return Err((i, Error::Noise)); | ||
| 504 | } else if Self::usart_reg().intstat.read().deltarxbrk().bit_is_set() { | ||
| 505 | return Err((i, Error::Break)); | ||
| 506 | } | ||
| 507 | let dr = Self::usart_reg().fiford.read().bits() as u8; | ||
| 508 | *b = dr; | ||
| 509 | } | ||
| 510 | Ok(buffer.len()) | ||
| 511 | } | ||
| 512 | } | ||
| 513 | } | 594 | } |
| 514 | 595 | ||
| 515 | /// UART instance. | 596 | /// UART instance. |
| 516 | #[allow(private_bounds)] | 597 | #[allow(private_bounds)] |
| 517 | pub trait Instance: sealed::SealedInstance + PeripheralType {} | 598 | pub trait Instance: SealedInstance + PeripheralType {} |
| 518 | 599 | ||
| 519 | #[macro_export] | ||
| 520 | macro_rules! impl_instance { | 600 | macro_rules! impl_instance { |
| 521 | ( | 601 | ($inst:ident, $fc:ident, $tx_pin:ident, $rx_pin:ident, $fc_num:expr) => { |
| 522 | $inst:ident, | 602 | impl $crate::usart::inner::SealedInstance for $crate::peripherals::$inst { |
| 523 | usart_peripheral: $USARTX:ident, | 603 | fn info() -> &'static Info { |
| 524 | usart_crate: $usartX:ident, | 604 | static INFO: Info = Info { |
| 525 | 605 | usart_reg: crate::pac::$inst, | |
| 526 | flexcomm: { | 606 | fc_reg: crate::pac::$fc, |
| 527 | field: $FLEXCOMM_FIELD:ident, | ||
| 528 | clock_field: $FLEXCOMM_CLK_FIELD:ident | ||
| 529 | }, | ||
| 530 | |||
| 531 | reset: { | ||
| 532 | bit: $RESET_BIT:ident | ||
| 533 | }, | ||
| 534 | |||
| 535 | clock: { | ||
| 536 | sel_field: $CLKSEL_FIELD:ident, | ||
| 537 | frg_field: $FRG_FIELD:ident | ||
| 538 | }, | ||
| 539 | |||
| 540 | pins: { | ||
| 541 | tx: $TX_IOCON:ident => $TX_FUNC:expr, | ||
| 542 | rx: $RX_IOCON:ident => $RX_FUNC:expr | ||
| 543 | } | ||
| 544 | |||
| 545 | ) => { | ||
| 546 | impl $crate::usart::SealedInstance for $crate::peripherals::$inst { | ||
| 547 | fn usart_reg() -> &'static UsartRegBlock { | ||
| 548 | unsafe { &*$crate::pac::$USARTX::ptr() } | ||
| 549 | } | ||
| 550 | |||
| 551 | fn enable_clock() { | ||
| 552 | critical_section::with(|_cs| { | ||
| 553 | if syscon_reg().ahbclkctrl0.read().iocon().is_disable() { | ||
| 554 | syscon_reg().ahbclkctrl0.modify(|_, w| w.iocon().enable()); | ||
| 555 | } | ||
| 556 | if syscon_reg().ahbclkctrl1.read().$FLEXCOMM_CLK_FIELD().is_disable() { | ||
| 557 | syscon_reg() | ||
| 558 | .ahbclkctrl1 | ||
| 559 | .modify(|_, w| w.$FLEXCOMM_CLK_FIELD().enable()); | ||
| 560 | } | ||
| 561 | }); | ||
| 562 | } | ||
| 563 | |||
| 564 | fn configure_flexcomm() { | ||
| 565 | let flexcomm = unsafe { &*$crate::pac::$FLEXCOMM_FIELD::ptr() }; | ||
| 566 | flexcomm.pselid.modify(|_, w| w.persel().usart()); | ||
| 567 | } | ||
| 568 | |||
| 569 | fn reset_flexcomm() { | ||
| 570 | syscon_reg().presetctrl1.modify(|_, w| w.$RESET_BIT().set_bit()); | ||
| 571 | syscon_reg().presetctrl1.modify(|_, w| w.$RESET_BIT().clear_bit()); | ||
| 572 | } | ||
| 573 | |||
| 574 | fn select_clock(baudrate: u32) -> u32 { | ||
| 575 | // Adaptive clock choice based on baud rate | ||
| 576 | // To get the desired baud rate, it is essential to choose the clock bigger than baud rate so that it can be 'chiseled' | ||
| 577 | // There are two types of dividers: integer divider (baud rate generator register and oversample selection value) | ||
| 578 | // and fractional divider (fractional rate divider). | ||
| 579 | |||
| 580 | // By default, oversampling rate is 16 which is an industry standard. | ||
| 581 | // That means 16 clocks are used to deliver the byte to recipient. | ||
| 582 | // In this way the probability of getting correct bytes instead of noise directly increases as oversampling increases as well. | ||
| 583 | |||
| 584 | // Minimum and maximum values were computed taking these formulas into account: | ||
| 585 | // For minimum value, MULT = 0, BRGVAL = 0 | ||
| 586 | // For maximum value, MULT = 255, BRGVAL = 255 | ||
| 587 | // Flexcomm Interface function clock = (clock selected via FCCLKSEL) / (1 + MULT / DIV) | ||
| 588 | // By default, OSRVAL = 15 (see above) | ||
| 589 | // Baud rate = [FCLK / (OSRVAL+1)] / (BRGVAL + 1) | ||
| 590 | return match baudrate { | ||
| 591 | 750_001..=6000000 => { | ||
| 592 | syscon_reg().$CLKSEL_FIELD().write(|w| w.sel().enum_0x3()); // 96 MHz | ||
| 593 | 96_000_000 | ||
| 594 | } | ||
| 595 | 1501..=750_000 => { | ||
| 596 | syscon_reg().$CLKSEL_FIELD().write(|w| w.sel().enum_0x2()); // 12 MHz | ||
| 597 | 12_000_000 | ||
| 598 | } | ||
| 599 | 121..=1500 => { | ||
| 600 | syscon_reg().$CLKSEL_FIELD().write(|w| w.sel().enum_0x4()); // 1 MHz | ||
| 601 | 1_000_000 | ||
| 602 | } | ||
| 603 | _ => { | ||
| 604 | panic!("{} baudrate is not permitted in this mode", baudrate); | ||
| 605 | } | ||
| 606 | }; | 607 | }; |
| 608 | &INFO | ||
| 607 | } | 609 | } |
| 608 | 610 | #[inline] | |
| 609 | fn set_baudrate(mult_value: u8, brg_value: u8) { | 611 | fn instance_number() -> usize { |
| 610 | // FCLK = (clock selected via FCCLKSEL) / (1+ MULT / DIV) | 612 | $fc_num |
| 611 | // Remark: To use the fractional baud rate generator, 0xFF must be wirtten to the DIV value | ||
| 612 | // to yield a denominator vale of 256. All other values are not supported | ||
| 613 | syscon_reg() | ||
| 614 | .$FRG_FIELD() | ||
| 615 | .modify(|_, w| unsafe { w.div().bits(0xFF).mult().bits(mult_value as u8) }); | ||
| 616 | |||
| 617 | // Baud rate = [FCLK / (OSRVAL+1)] / (BRGVAL + 1) | ||
| 618 | // By default, oversampling is 16x, i.e. OSRVAL = 15 | ||
| 619 | |||
| 620 | // Typical industry standard USARTs use a 16x oversample clock to transmit and receive | ||
| 621 | // asynchronous data. This is the number of BRG clocks used for one data bit. The | ||
| 622 | // Oversample Select Register (OSR) allows this USART to use a 16x down to a 5x | ||
| 623 | // oversample clock. There is no oversampling in synchronous modes. | ||
| 624 | Self::usart_reg() | ||
| 625 | .brg | ||
| 626 | .modify(|_, w| unsafe { w.brgval().bits((brg_value - 1) as u16) }); | ||
| 627 | } | 613 | } |
| 628 | 614 | #[inline] | |
| 629 | fn tx_pin_config() { | 615 | fn tx_pin_func() -> PioFunc { |
| 630 | iocon_reg().$TX_IOCON.modify(|_, w| unsafe { | 616 | PioFunc::$tx_pin |
| 631 | w.func() | ||
| 632 | .bits($TX_FUNC) | ||
| 633 | .digimode() | ||
| 634 | .digital() | ||
| 635 | .slew() | ||
| 636 | .standard() | ||
| 637 | .mode() | ||
| 638 | .inactive() | ||
| 639 | .invert() | ||
| 640 | .disabled() | ||
| 641 | .od() | ||
| 642 | .normal() | ||
| 643 | }); | ||
| 644 | } | 617 | } |
| 645 | 618 | #[inline] | |
| 646 | fn rx_pin_config() { | 619 | fn rx_pin_func() -> PioFunc { |
| 647 | iocon_reg().$RX_IOCON.modify(|_, w| unsafe { | 620 | PioFunc::$rx_pin |
| 648 | w.func() | ||
| 649 | .bits($RX_FUNC) | ||
| 650 | .digimode() | ||
| 651 | .digital() | ||
| 652 | .slew() | ||
| 653 | .standard() | ||
| 654 | .mode() | ||
| 655 | .inactive() | ||
| 656 | .invert() | ||
| 657 | .disabled() | ||
| 658 | .od() | ||
| 659 | .normal() | ||
| 660 | }); | ||
| 661 | } | 621 | } |
| 662 | } | 622 | } |
| 663 | |||
| 664 | impl $crate::usart::Instance for $crate::peripherals::$inst {} | 623 | impl $crate::usart::Instance for $crate::peripherals::$inst {} |
| 665 | }; | 624 | }; |
| 666 | } | 625 | } |
| 667 | 626 | ||
| 668 | impl_instance!(USART0, usart_peripheral: USART0, usart_crate: usart0, | 627 | impl_instance!(USART0, FLEXCOMM0, ALT1, ALT1, 0); |
| 669 | flexcomm: { | 628 | impl_instance!(USART1, FLEXCOMM1, ALT2, ALT2, 1); |
| 670 | field: FLEXCOMM0, | 629 | impl_instance!(USART2, FLEXCOMM2, ALT1, ALT1, 2); |
| 671 | clock_field: fc0 | 630 | impl_instance!(USART3, FLEXCOMM3, ALT1, ALT1, 3); |
| 672 | }, | 631 | impl_instance!(USART4, FLEXCOMM4, ALT1, ALT2, 4); |
| 673 | 632 | impl_instance!(USART5, FLEXCOMM5, ALT3, ALT3, 5); | |
| 674 | reset: { | 633 | impl_instance!(USART6, FLEXCOMM6, ALT2, ALT2, 6); |
| 675 | bit: fc0_rst | 634 | impl_instance!(USART7, FLEXCOMM7, ALT7, ALT7, 7); |
| 676 | }, | ||
| 677 | |||
| 678 | clock: { | ||
| 679 | sel_field: fcclksel0, | ||
| 680 | frg_field: flexfrg0ctrl | ||
| 681 | }, | ||
| 682 | |||
| 683 | pins: { | ||
| 684 | tx: pio1_6 => 1, | ||
| 685 | rx: pio1_5 => 1 | ||
| 686 | } | ||
| 687 | ); | ||
| 688 | |||
| 689 | impl_instance!(USART1, usart_peripheral: USART1, usart_crate: usart1, | ||
| 690 | flexcomm: { | ||
| 691 | field: FLEXCOMM1, | ||
| 692 | clock_field: fc1 | ||
| 693 | }, | ||
| 694 | |||
| 695 | reset: { | ||
| 696 | bit: fc1_rst | ||
| 697 | }, | ||
| 698 | |||
| 699 | clock: { | ||
| 700 | sel_field: fcclksel1, | ||
| 701 | frg_field: flexfrg1ctrl | ||
| 702 | }, | ||
| 703 | |||
| 704 | pins: { | ||
| 705 | tx: pio1_11 => 2, | ||
| 706 | rx: pio1_10 => 2 | ||
| 707 | } | ||
| 708 | ); | ||
| 709 | |||
| 710 | impl_instance!(USART2, usart_peripheral: USART2, usart_crate: usart2, | ||
| 711 | flexcomm: { | ||
| 712 | field: FLEXCOMM2, | ||
| 713 | clock_field: fc2 | ||
| 714 | }, | ||
| 715 | |||
| 716 | reset: { | ||
| 717 | bit: fc2_rst | ||
| 718 | }, | ||
| 719 | |||
| 720 | clock: { | ||
| 721 | sel_field: fcclksel2, | ||
| 722 | frg_field: flexfrg2ctrl | ||
| 723 | }, | ||
| 724 | |||
| 725 | pins: { | ||
| 726 | tx: pio0_27 => 1, | ||
| 727 | rx: pio1_24 => 1 | ||
| 728 | } | ||
| 729 | ); | ||
| 730 | |||
| 731 | impl_instance!(USART3, usart_peripheral: USART3, usart_crate: usart3, | ||
| 732 | flexcomm: { | ||
| 733 | field: FLEXCOMM3, | ||
| 734 | clock_field: fc3 | ||
| 735 | }, | ||
| 736 | |||
| 737 | reset: { | ||
| 738 | bit: fc3_rst | ||
| 739 | }, | ||
| 740 | |||
| 741 | clock: { | ||
| 742 | sel_field: fcclksel3, | ||
| 743 | frg_field: flexfrg3ctrl | ||
| 744 | }, | ||
| 745 | |||
| 746 | pins: { | ||
| 747 | tx: pio0_2 => 1, | ||
| 748 | rx: pio0_3 => 1 | ||
| 749 | } | ||
| 750 | ); | ||
| 751 | |||
| 752 | impl_instance!(USART4, usart_peripheral: USART4, usart_crate: usart4, | ||
| 753 | flexcomm: { | ||
| 754 | field: FLEXCOMM4, | ||
| 755 | clock_field: fc4 | ||
| 756 | }, | ||
| 757 | |||
| 758 | reset: { | ||
| 759 | bit: fc4_rst | ||
| 760 | }, | ||
| 761 | |||
| 762 | clock: { | ||
| 763 | sel_field: fcclksel4, | ||
| 764 | frg_field: flexfrg4ctrl | ||
| 765 | }, | ||
| 766 | |||
| 767 | pins: { | ||
| 768 | tx: pio0_16 => 1, | ||
| 769 | rx: pio0_5 => 2 | ||
| 770 | } | ||
| 771 | ); | ||
| 772 | |||
| 773 | impl_instance!(USART5, usart_peripheral: USART5, usart_crate: usart5, | ||
| 774 | flexcomm: { | ||
| 775 | field: FLEXCOMM5, | ||
| 776 | clock_field: fc5 | ||
| 777 | }, | ||
| 778 | |||
| 779 | reset: { | ||
| 780 | bit: fc5_rst | ||
| 781 | }, | ||
| 782 | |||
| 783 | clock: { | ||
| 784 | sel_field: fcclksel5, | ||
| 785 | frg_field: flexfrg5ctrl | ||
| 786 | }, | ||
| 787 | |||
| 788 | pins: { | ||
| 789 | tx: pio0_9 => 3, | ||
| 790 | rx: pio0_8 => 3 | ||
| 791 | } | ||
| 792 | ); | ||
| 793 | |||
| 794 | impl_instance!(USART6, usart_peripheral: USART6, usart_crate: usart6, | ||
| 795 | flexcomm: { | ||
| 796 | field: FLEXCOMM6, | ||
| 797 | clock_field: fc6 | ||
| 798 | }, | ||
| 799 | |||
| 800 | reset: { | ||
| 801 | bit: fc6_rst | ||
| 802 | }, | ||
| 803 | |||
| 804 | clock: { | ||
| 805 | sel_field: fcclksel6, | ||
| 806 | frg_field: flexfrg6ctrl | ||
| 807 | }, | ||
| 808 | |||
| 809 | pins: { | ||
| 810 | tx: pio1_16 => 2, | ||
| 811 | rx: pio1_13 => 2 | ||
| 812 | } | ||
| 813 | ); | ||
| 814 | |||
| 815 | impl_instance!(USART7, usart_peripheral: USART7, usart_crate: usart7, | ||
| 816 | flexcomm: { | ||
| 817 | field: FLEXCOMM7, | ||
| 818 | clock_field: fc7 | ||
| 819 | }, | ||
| 820 | |||
| 821 | reset: { | ||
| 822 | bit: fc7_rst | ||
| 823 | }, | ||
| 824 | |||
| 825 | clock: { | ||
| 826 | sel_field: fcclksel7, | ||
| 827 | frg_field: flexfrg7ctrl | ||
| 828 | }, | ||
| 829 | |||
| 830 | pins: { | ||
| 831 | tx: pio0_19 => 7, | ||
| 832 | rx: pio0_20 => 7 | ||
| 833 | } | ||
| 834 | ); | ||
| 835 | 635 | ||
| 836 | /// Trait for TX pins. | 636 | /// Trait for TX pins. |
| 837 | pub trait TxPin<T: Instance>: crate::gpio::Pin {} | 637 | pub trait TxPin<T: Instance>: crate::gpio::Pin {} |
| 838 | /// Trait for RX pins. | 638 | /// Trait for RX pins. |
| 839 | pub trait RxPin<T: Instance>: crate::gpio::Pin {} | 639 | pub trait RxPin<T: Instance>: crate::gpio::Pin {} |
| 840 | 640 | ||
| 841 | // TODO: Add RTS, CTS and CLK pin traits | ||
| 842 | |||
| 843 | macro_rules! impl_pin { | 641 | macro_rules! impl_pin { |
| 844 | ($pin:ident, $instance:ident, Tx) => { | 642 | ($pin:ident, $instance:ident, Tx) => { |
| 845 | impl TxPin<crate::peripherals::$instance> for crate::peripherals::$pin {} | 643 | impl TxPin<crate::peripherals::$instance> for crate::peripherals::$pin {} |
| @@ -849,37 +647,19 @@ macro_rules! impl_pin { | |||
| 849 | }; | 647 | }; |
| 850 | } | 648 | } |
| 851 | 649 | ||
| 852 | impl_pin!(PIO1_5, USART0, Rx); | ||
| 853 | impl_pin!(PIO1_6, USART0, Tx); | 650 | impl_pin!(PIO1_6, USART0, Tx); |
| 854 | impl_pin!(PIO1_10, USART1, Rx); | 651 | impl_pin!(PIO1_5, USART0, Rx); |
| 855 | impl_pin!(PIO1_11, USART1, Tx); | 652 | impl_pin!(PIO1_11, USART1, Tx); |
| 653 | impl_pin!(PIO1_10, USART1, Rx); | ||
| 856 | impl_pin!(PIO0_27, USART2, Tx); | 654 | impl_pin!(PIO0_27, USART2, Tx); |
| 857 | impl_pin!(PIO1_24, USART2, Rx); | 655 | impl_pin!(PIO1_24, USART2, Rx); |
| 858 | impl_pin!(PIO0_2, USART3, Tx); | 656 | impl_pin!(PIO0_2, USART3, Tx); |
| 859 | impl_pin!(PIO0_3, USART3, Rx); | 657 | impl_pin!(PIO0_3, USART3, Rx); |
| 860 | impl_pin!(PIO0_16, USART4, Tx); | 658 | impl_pin!(PIO0_16, USART4, Tx); |
| 861 | impl_pin!(PIO0_5, USART4, Rx); | 659 | impl_pin!(PIO0_5, USART4, Rx); |
| 862 | impl_pin!(PIO0_8, USART5, Rx); | ||
| 863 | impl_pin!(PIO0_9, USART5, Tx); | 660 | impl_pin!(PIO0_9, USART5, Tx); |
| 661 | impl_pin!(PIO0_8, USART5, Rx); | ||
| 864 | impl_pin!(PIO1_16, USART6, Tx); | 662 | impl_pin!(PIO1_16, USART6, Tx); |
| 865 | impl_pin!(PIO1_13, USART6, Rx); | 663 | impl_pin!(PIO1_13, USART6, Rx); |
| 866 | impl_pin!(PIO0_20, USART7, Rx); | ||
| 867 | impl_pin!(PIO0_19, USART7, Tx); | 664 | impl_pin!(PIO0_19, USART7, Tx); |
| 868 | 665 | impl_pin!(PIO0_20, USART7, Rx); | |
| 869 | /// Get the SYSCON register block. | ||
| 870 | /// | ||
| 871 | /// # Safety | ||
| 872 | /// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO | ||
| 873 | /// registers are not accessed concurrently by multiple threads. | ||
| 874 | pub(crate) fn syscon_reg() -> &'static crate::pac::syscon::RegisterBlock { | ||
| 875 | unsafe { &*crate::pac::SYSCON::ptr() } | ||
| 876 | } | ||
| 877 | |||
| 878 | /// Get the IOCON register block. | ||
| 879 | /// | ||
| 880 | /// # Safety | ||
| 881 | /// Read/Write operations on a single registers are NOT atomic. You must ensure that the GPIO | ||
| 882 | /// registers are not accessed concurrently by multiple threads. | ||
| 883 | pub(crate) fn iocon_reg() -> &'static crate::pac::iocon::RegisterBlock { | ||
| 884 | unsafe { &*crate::pac::IOCON::ptr() } | ||
| 885 | } | ||
diff --git a/examples/lpc55s69/Cargo.toml b/examples/lpc55s69/Cargo.toml index 79b27f269..579748595 100644 --- a/examples/lpc55s69/Cargo.toml +++ b/examples/lpc55s69/Cargo.toml | |||
| @@ -7,7 +7,7 @@ license = "MIT OR Apache-2.0" | |||
| 7 | publish = false | 7 | publish = false |
| 8 | 8 | ||
| 9 | [dependencies] | 9 | [dependencies] |
| 10 | embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["lpc55", "rt", "defmt", "time-driver-rtc"] } | 10 | embassy-nxp = { version = "0.1.0", path = "../../embassy-nxp", features = ["lpc55-core0", "rt", "defmt", "time-driver-rtc"] } |
| 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } | 11 | embassy-executor = { version = "0.9.0", path = "../../embassy-executor", features = ["arch-cortex-m", "executor-thread", "executor-interrupt"] } |
| 12 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } | 12 | embassy-sync = { version = "0.7.2", path = "../../embassy-sync", features = ["defmt"] } |
| 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768"] } | 13 | embassy-time = { version = "0.5.0", path = "../../embassy-time", features = ["defmt", "tick-hz-32_768"] } |
