diff options
| -rw-r--r-- | embassy-stm32/src/gpio.rs | 97 |
1 files changed, 34 insertions, 63 deletions
diff --git a/embassy-stm32/src/gpio.rs b/embassy-stm32/src/gpio.rs index 6c989b52e..81969c4c2 100644 --- a/embassy-stm32/src/gpio.rs +++ b/embassy-stm32/src/gpio.rs | |||
| @@ -93,6 +93,32 @@ impl<'d, T: Pin> Flex<'d, T> { | |||
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | #[inline] | 95 | #[inline] |
| 96 | fn set_as_input_output(&mut self,speed: Speed, pull : Pull) { | ||
| 97 | critical_section::with(|_| unsafe { | ||
| 98 | let r = self.pin.block(); | ||
| 99 | let n = self.pin.pin() as usize; | ||
| 100 | #[cfg(gpio_v1)] | ||
| 101 | { | ||
| 102 | let crlh = if n < 8 { 0 } else { 1 }; | ||
| 103 | match pull { | ||
| 104 | Pull::Up => r.bsrr().write(|w| w.set_bs(n, true)), | ||
| 105 | Pull::Down => r.bsrr().write(|w| w.set_br(n, true)), | ||
| 106 | Pull::None => {} | ||
| 107 | } | ||
| 108 | r.cr(crlh).modify(|w| w.set_mode(n % 8, speed.into())); | ||
| 109 | r.cr(crlh).modify(|w| w.set_cnf_out(n % 8, vals::CnfOut::OPENDRAIN)); | ||
| 110 | } | ||
| 111 | #[cfg(gpio_v2)] | ||
| 112 | { | ||
| 113 | r.pupdr().modify(|w| w.set_pupdr(n, pull.into())); | ||
| 114 | r.otyper().modify(|w| w.set_ot(n, vals::Ot::OPENDRAIN)); | ||
| 115 | pin.set_speed(speed); | ||
| 116 | r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT)); | ||
| 117 | } | ||
| 118 | }); | ||
| 119 | } | ||
| 120 | |||
| 121 | #[inline] | ||
| 96 | pub fn is_high(&self) -> bool { | 122 | pub fn is_high(&self) -> bool { |
| 97 | !self.is_low() | 123 | !self.is_low() |
| 98 | } | 124 | } |
| @@ -304,58 +330,31 @@ impl<'d, T: Pin> Output<'d, T> { | |||
| 304 | 330 | ||
| 305 | /// GPIO output open-drain driver. | 331 | /// GPIO output open-drain driver. |
| 306 | pub struct OutputOpenDrain<'d, T: Pin> { | 332 | pub struct OutputOpenDrain<'d, T: Pin> { |
| 307 | pub(crate) pin: T, | 333 | pub(crate) pin: Flex<'d, T> |
| 308 | phantom: PhantomData<&'d mut T>, | ||
| 309 | } | 334 | } |
| 310 | 335 | ||
| 311 | impl<'d, T: Pin> OutputOpenDrain<'d, T> { | 336 | impl<'d, T: Pin> OutputOpenDrain<'d, T> { |
| 312 | #[inline] | 337 | #[inline] |
| 313 | pub fn new(pin: impl Unborrow<Target = T> + 'd, initial_output: Level, speed: Speed, pull: Pull) -> Self { | 338 | pub fn new(pin: impl Unborrow<Target = T> + 'd, initial_output: Level, speed: Speed, pull: Pull) -> Self { |
| 314 | unborrow!(pin); | 339 | let mut pin = Flex::new(pin); |
| 315 | 340 | ||
| 316 | match initial_output { | 341 | match initial_output { |
| 317 | Level::High => pin.set_high(), | 342 | Level::High => pin.set_high(), |
| 318 | Level::Low => pin.set_low(), | 343 | Level::Low => pin.set_low(), |
| 319 | } | 344 | } |
| 320 | 345 | ||
| 321 | critical_section::with(|_| unsafe { | 346 | pin.set_as_input_output(speed, pull); |
| 322 | let r = pin.block(); | 347 | Self { pin } |
| 323 | let n = pin.pin() as usize; | ||
| 324 | #[cfg(gpio_v1)] | ||
| 325 | { | ||
| 326 | let crlh = if n < 8 { 0 } else { 1 }; | ||
| 327 | match pull { | ||
| 328 | Pull::Up => r.bsrr().write(|w| w.set_bs(n, true)), | ||
| 329 | Pull::Down => r.bsrr().write(|w| w.set_br(n, true)), | ||
| 330 | Pull::None => {} | ||
| 331 | } | ||
| 332 | r.cr(crlh).modify(|w| w.set_mode(n % 8, speed.into())); | ||
| 333 | r.cr(crlh).modify(|w| w.set_cnf_out(n % 8, vals::CnfOut::OPENDRAIN)); | ||
| 334 | } | ||
| 335 | #[cfg(gpio_v2)] | ||
| 336 | { | ||
| 337 | r.pupdr().modify(|w| w.set_pupdr(n, pull.into())); | ||
| 338 | r.otyper().modify(|w| w.set_ot(n, vals::Ot::OPENDRAIN)); | ||
| 339 | pin.set_speed(speed); | ||
| 340 | r.moder().modify(|w| w.set_moder(n, vals::Moder::OUTPUT)); | ||
| 341 | } | ||
| 342 | }); | ||
| 343 | |||
| 344 | Self { | ||
| 345 | pin, | ||
| 346 | phantom: PhantomData, | ||
| 347 | } | ||
| 348 | } | 348 | } |
| 349 | 349 | ||
| 350 | #[inline] | 350 | #[inline] |
| 351 | pub fn is_high(&self) -> bool { | 351 | pub fn is_high(&self) -> bool { |
| 352 | !self.is_low() | 352 | !self.pin.is_low() |
| 353 | } | 353 | } |
| 354 | 354 | ||
| 355 | #[inline] | 355 | #[inline] |
| 356 | pub fn is_low(&self) -> bool { | 356 | pub fn is_low(&self) -> bool { |
| 357 | let state = unsafe { self.pin.block().idr().read().idr(self.pin.pin() as _) }; | 357 | self.pin.is_low() |
| 358 | state == vals::Idr::LOW | ||
| 359 | } | 358 | } |
| 360 | 359 | ||
| 361 | /// Set the output as high. | 360 | /// Set the output as high. |
| @@ -379,41 +378,13 @@ impl<'d, T: Pin> OutputOpenDrain<'d, T> { | |||
| 379 | /// Is the output pin set as low? | 378 | /// Is the output pin set as low? |
| 380 | #[inline] | 379 | #[inline] |
| 381 | pub fn is_set_low(&self) -> bool { | 380 | pub fn is_set_low(&self) -> bool { |
| 382 | let state = unsafe { self.pin.block().odr().read().odr(self.pin.pin() as _) }; | 381 | self.pin.is_set_low() |
| 383 | state == vals::Odr::LOW | ||
| 384 | } | 382 | } |
| 385 | 383 | ||
| 386 | /// Toggle pin output | 384 | /// Toggle pin output |
| 387 | #[inline] | 385 | #[inline] |
| 388 | pub fn toggle(&mut self) { | 386 | pub fn toggle(&mut self) { |
| 389 | if self.is_set_low() { | 387 | self.pin.toggle() |
| 390 | self.set_high() | ||
| 391 | } else { | ||
| 392 | self.set_low() | ||
| 393 | } | ||
| 394 | } | ||
| 395 | } | ||
| 396 | |||
| 397 | impl<'d, T: Pin> Drop for OutputOpenDrain<'d, T> { | ||
| 398 | #[inline] | ||
| 399 | fn drop(&mut self) { | ||
| 400 | critical_section::with(|_| unsafe { | ||
| 401 | let r = self.pin.block(); | ||
| 402 | let n = self.pin.pin() as usize; | ||
| 403 | #[cfg(gpio_v1)] | ||
| 404 | { | ||
| 405 | let crlh = if n < 8 { 0 } else { 1 }; | ||
| 406 | r.cr(crlh).modify(|w| { | ||
| 407 | w.set_mode(n % 8, vals::Mode::INPUT); | ||
| 408 | w.set_cnf_in(n % 8, vals::CnfIn::FLOATING); | ||
| 409 | }); | ||
| 410 | } | ||
| 411 | #[cfg(gpio_v2)] | ||
| 412 | { | ||
| 413 | r.pupdr().modify(|w| w.set_pupdr(n, vals::Pupdr::FLOATING)); | ||
| 414 | r.moder().modify(|w| w.set_moder(n, vals::Moder::INPUT)); | ||
| 415 | } | ||
| 416 | }); | ||
| 417 | } | 388 | } |
| 418 | } | 389 | } |
| 419 | 390 | ||
