ETM improvements (#2427)

* ETM simplifications

* Work with GPIO signals

* Fix changelog
This commit is contained in:
Dániel Buga 2024-11-05 14:39:19 +01:00 committed by GitHub
parent 665fb0e278
commit eabb6fb1c6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 267 additions and 310 deletions

View File

@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `gpio::Output::peripheral_input()` (#2418)
- `{Uart, UartRx, UartTx}::apply_config()` (#2449)
- `{Uart, UartRx, UartTx}` now implement `embassy_embedded_hal::SetConfig` (#2449)
- GPIO ETM tasks and events now accept `InputSignal` and `OutputSignal` (#2427)
### Changed
@ -78,6 +79,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Most of the async-specific constructors (`new_async`, `new_async_no_transceiver`) have been removed. (#2430)
- The `configure_for_async` DMA functions have been removed (#2430)
- The `Uart::{change_baud, change_stop_bits}` functions have been removed (#2449)
- `gpio::{Input, Output, OutputOpenDrain, Flex, GpioPin}::{peripheral_input, into_peripheral_output}` have been removed. (#2418)
- The `GpioEtm` prefix has been removed from `gpio::etm` types (#2427)
- The `TimerEtm` prefix has been removed from `timer::timg::etm` types (#2427)
- The `SysTimerEtm` prefix has been removed from `timer::systimer::etm` types (#2427)
- The `GpioEtmEventRising`, `GpioEtmEventFalling`, `GpioEtmEventAny` types have been replaced with `Event` (#2427)
- The `TaskSet`, `TaskClear`, `TaskToggle` types have been replaced with `Task` (#2427)
## [0.21.1]

View File

@ -231,6 +231,14 @@ The previous signal function have been replaced by `split`. This change affects
`into_peripheral_output`, `split` (for output pins only) and `peripheral_input` have been added to
the GPIO drivers (`Input`, `Output`, `OutputOpenDrain` and `Flex`) instead.
## ETM changes
- The types are no longer prefixed with `GpioEtm`, `TimerEtm` or `SysTimerEtm`. You can still use
import aliasses in case you need to differentiate due to name collisions
(e.g. `use esp_hal::gpio::etm::Event as GpioEtmEvent`).
- The old task and event types have been replaced by `Task` and `Event`.
- GPIO tasks and events are no longer generic.
## Changes to peripheral configuration
### The `uart::config` module has been removed
@ -243,4 +251,4 @@ The module's contents have been moved into `uart`.
```
If you work with multiple configurable peripherals, you may want to import the `uart` module and
refer to the `Config` struct as `uart::Config`.
refer to the `Config` struct as `uart::Config`.

View File

@ -24,10 +24,8 @@
//! ```rust, no_run
#![doc = crate::before_snippet!()]
//! # use esp_hal::gpio::Io;
//! # use esp_hal::gpio::etm::GpioEtmChannels;
//! # use esp_hal::gpio::etm::{Channels, InputConfig, OutputConfig};
//! # use esp_hal::etm::Etm;
//! # use esp_hal::gpio::etm::GpioEtmInputConfig;
//! # use esp_hal::gpio::etm::GpioEtmOutputConfig;
//! # use esp_hal::gpio::Pull;
//! # use esp_hal::gpio::Level;
//!
@ -36,18 +34,18 @@
//! let button = io.pins.gpio9;
//!
//! // setup ETM
//! let gpio_ext = GpioEtmChannels::new(peripherals.GPIO_SD);
//! let gpio_ext = Channels::new(peripherals.GPIO_SD);
//! let led_task = gpio_ext.channel0_task.toggle(
//! &mut led,
//! GpioEtmOutputConfig {
//! open_drain: false,
//! pull: Pull::None,
//! initial_state: Level::Low,
//! },
//! &mut led,
//! OutputConfig {
//! open_drain: false,
//! pull: Pull::None,
//! initial_state: Level::Low,
//! },
//! );
//! let button_event = gpio_ext
//! .channel0_event
//! .falling_edge(button, GpioEtmInputConfig { pull: Pull::Down });
//! .falling_edge(button, InputConfig { pull: Pull::Down });
//!
//! let etm = Etm::new(peripherals.SOC_ETM);
//! let channel0 = etm.channel0;

View File

@ -26,21 +26,21 @@
//! ```rust, no_run
#![doc = crate::before_snippet!()]
//! # use esp_hal::gpio::Io;
//! # use esp_hal::gpio::etm::GpioEtmChannels;
//! # use esp_hal::gpio::etm::Channels;
//! # use esp_hal::etm::Etm;
//! # use esp_hal::gpio::etm::GpioEtmInputConfig;
//! # use esp_hal::gpio::etm::GpioEtmOutputConfig;
//! # use esp_hal::gpio::etm::InputConfig;
//! # use esp_hal::gpio::etm::OutputConfig;
//! # use esp_hal::gpio::Pull;
//! # use esp_hal::gpio::Level;
//!
//! #
//! # let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
//! # let mut led = io.pins.gpio1;
//! # let button = io.pins.gpio9;
//!
//! let gpio_ext = GpioEtmChannels::new(peripherals.GPIO_SD);
//! let gpio_ext = Channels::new(peripherals.GPIO_SD);
//! let led_task = gpio_ext.channel0_task.toggle(
//! &mut led,
//! GpioEtmOutputConfig {
//! OutputConfig {
//! open_drain: false,
//! pull: Pull::None,
//! initial_state: Level::Low,
@ -48,77 +48,84 @@
//! );
//! let button_event = gpio_ext
//! .channel0_event
//! .falling_edge(button, GpioEtmInputConfig { pull: Pull::Down });
//! .falling_edge(button, InputConfig { pull: Pull::Down });
//! # }
//! ```
use core::marker::PhantomData;
use crate::{
gpio::{Level, Pull},
gpio::{
interconnect::{InputSignal, OutputSignal},
Level,
Pull,
},
peripheral::{Peripheral, PeripheralRef},
peripherals::GPIO_SD,
private,
};
/// All the GPIO ETM channels
#[non_exhaustive]
pub struct GpioEtmChannels<'d> {
_gpio_sd: PeripheralRef<'d, crate::peripherals::GPIO_SD>,
pub struct Channels<'d> {
_gpio_sd: PeripheralRef<'d, GPIO_SD>,
/// Task channel 0 for triggering GPIO tasks.
pub channel0_task: GpioEtmTaskChannel<0>,
pub channel0_task: TaskChannel<0>,
/// Event channel 0 for handling GPIO events.
pub channel0_event: GpioEtmEventChannel<0>,
pub channel0_event: EventChannel<0>,
/// Task channel 1 for triggering GPIO tasks.
pub channel1_task: GpioEtmTaskChannel<1>,
pub channel1_task: TaskChannel<1>,
/// Event channel 1 for handling GPIO events.
pub channel1_event: GpioEtmEventChannel<1>,
pub channel1_event: EventChannel<1>,
/// Task channel 2 for triggering GPIO tasks.
pub channel2_task: GpioEtmTaskChannel<2>,
pub channel2_task: TaskChannel<2>,
/// Event channel 2 for handling GPIO events.
pub channel2_event: GpioEtmEventChannel<2>,
pub channel2_event: EventChannel<2>,
/// Task channel 3 for triggering GPIO tasks.
pub channel3_task: GpioEtmTaskChannel<3>,
pub channel3_task: TaskChannel<3>,
/// Event channel 3 for handling GPIO events.
pub channel3_event: GpioEtmEventChannel<3>,
pub channel3_event: EventChannel<3>,
/// Task channel 4 for triggering GPIO tasks.
pub channel4_task: GpioEtmTaskChannel<4>,
pub channel4_task: TaskChannel<4>,
/// Event channel 4 for handling GPIO events.
pub channel4_event: GpioEtmEventChannel<4>,
pub channel4_event: EventChannel<4>,
/// Task channel 5 for triggering GPIO tasks.
pub channel5_task: GpioEtmTaskChannel<5>,
pub channel5_task: TaskChannel<5>,
/// Event channel 5 for handling GPIO events.
pub channel5_event: GpioEtmEventChannel<5>,
pub channel5_event: EventChannel<5>,
/// Task channel 6 for triggering GPIO tasks.
pub channel6_task: GpioEtmTaskChannel<6>,
pub channel6_task: TaskChannel<6>,
/// Event channel 6 for handling GPIO events.
pub channel6_event: GpioEtmEventChannel<6>,
pub channel6_event: EventChannel<6>,
/// Task channel 7 for triggering GPIO tasks.
pub channel7_task: GpioEtmTaskChannel<7>,
pub channel7_task: TaskChannel<7>,
/// Event channel 7 for handling GPIO events.
pub channel7_event: GpioEtmEventChannel<7>,
pub channel7_event: EventChannel<7>,
}
impl<'d> GpioEtmChannels<'d> {
impl<'d> Channels<'d> {
/// Create a new instance
pub fn new(peripheral: impl Peripheral<P = crate::peripherals::GPIO_SD> + 'd) -> Self {
pub fn new(peripheral: impl Peripheral<P = GPIO_SD> + 'd) -> Self {
crate::into_ref!(peripheral);
Self {
_gpio_sd: peripheral,
channel0_task: GpioEtmTaskChannel {},
channel0_event: GpioEtmEventChannel {},
channel1_task: GpioEtmTaskChannel {},
channel1_event: GpioEtmEventChannel {},
channel2_task: GpioEtmTaskChannel {},
channel2_event: GpioEtmEventChannel {},
channel3_task: GpioEtmTaskChannel {},
channel3_event: GpioEtmEventChannel {},
channel4_task: GpioEtmTaskChannel {},
channel4_event: GpioEtmEventChannel {},
channel5_task: GpioEtmTaskChannel {},
channel5_event: GpioEtmEventChannel {},
channel6_task: GpioEtmTaskChannel {},
channel6_event: GpioEtmEventChannel {},
channel7_task: GpioEtmTaskChannel {},
channel7_event: GpioEtmEventChannel {},
channel0_task: TaskChannel {},
channel0_event: EventChannel {},
channel1_task: TaskChannel {},
channel1_event: EventChannel {},
channel2_task: TaskChannel {},
channel2_event: EventChannel {},
channel3_task: TaskChannel {},
channel3_event: EventChannel {},
channel4_task: TaskChannel {},
channel4_event: EventChannel {},
channel5_task: TaskChannel {},
channel5_event: EventChannel {},
channel6_task: TaskChannel {},
channel6_event: EventChannel {},
channel7_task: TaskChannel {},
channel7_event: EventChannel {},
}
}
}
@ -126,143 +133,102 @@ impl<'d> GpioEtmChannels<'d> {
/// Configuration for an ETM controlled GPIO input pin
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct GpioEtmInputConfig {
pub struct InputConfig {
/// Configuration for the internal pull-up resistors
pub pull: Pull,
}
impl Default for GpioEtmInputConfig {
impl Default for InputConfig {
fn default() -> Self {
Self { pull: Pull::None }
}
}
/// An ETM controlled GPIO event
pub struct GpioEtmEventChannel<const C: u8> {}
pub struct EventChannel<const C: u8> {}
impl<const C: u8> GpioEtmEventChannel<C> {
impl<const C: u8> EventChannel<C> {
/// Trigger at rising edge
pub fn rising_edge<'d, PIN>(
pub fn rising_edge<'d>(
self,
pin: impl Peripheral<P = PIN> + 'd,
pin_config: GpioEtmInputConfig,
) -> GpioEtmEventChannelRising<'d, PIN, C>
where
PIN: super::InputPin,
{
crate::into_ref!(pin);
pin.init_input(pin_config.pull, private::Internal);
enable_event_channel(C, pin.number());
GpioEtmEventChannelRising { _pin: pin }
pin: impl Peripheral<P = impl Into<InputSignal>> + 'd,
pin_config: InputConfig,
) -> Event<'d> {
self.into_event(pin, pin_config, EventKind::Rising)
}
/// Trigger at falling edge
pub fn falling_edge<'d, PIN>(
pub fn falling_edge<'d>(
self,
pin: impl Peripheral<P = PIN> + 'd,
pin_config: GpioEtmInputConfig,
) -> GpioEtmEventChannelFalling<'d, PIN, C>
where
PIN: super::InputPin,
{
crate::into_ref!(pin);
pin.init_input(pin_config.pull, private::Internal);
enable_event_channel(C, pin.number());
GpioEtmEventChannelFalling { _pin: pin }
pin: impl Peripheral<P = impl Into<InputSignal>> + 'd,
pin_config: InputConfig,
) -> Event<'d> {
self.into_event(pin, pin_config, EventKind::Falling)
}
/// Trigger at any edge
pub fn any_edge<'d, PIN>(
pub fn any_edge<'d>(
self,
pin: impl Peripheral<P = PIN> + 'd,
pin_config: GpioEtmInputConfig,
) -> GpioEtmEventChannelAny<'d, PIN, C>
where
PIN: super::InputPin,
{
crate::into_ref!(pin);
pin: impl Peripheral<P = impl Into<InputSignal>> + 'd,
pin_config: InputConfig,
) -> Event<'d> {
self.into_event(pin, pin_config, EventKind::Any)
}
fn into_event<'d>(
self,
pin: impl Peripheral<P = impl Into<InputSignal>> + 'd,
pin_config: InputConfig,
kind: EventKind,
) -> Event<'d> {
crate::into_mapped_ref!(pin);
pin.init_input(pin_config.pull, private::Internal);
enable_event_channel(C, pin.number());
GpioEtmEventChannelAny { _pin: pin }
Event {
id: kind.id() + C,
_pin: PhantomData,
}
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
enum EventKind {
Rising,
Falling,
Any,
}
impl EventKind {
fn id(&self) -> u8 {
match self {
EventKind::Rising => 1,
EventKind::Falling => 9,
EventKind::Any => 17,
}
}
}
/// Event for rising edge
#[non_exhaustive]
pub struct GpioEtmEventChannelRising<'d, PIN, const C: u8>
where
PIN: super::Pin,
{
_pin: PeripheralRef<'d, PIN>,
pub struct Event<'d> {
_pin: PhantomData<&'d mut ()>,
id: u8,
}
impl<PIN, const C: u8> private::Sealed for GpioEtmEventChannelRising<'_, PIN, C> where
PIN: super::Pin
{
}
impl private::Sealed for Event<'_> {}
impl<PIN, const C: u8> crate::etm::EtmEvent for GpioEtmEventChannelRising<'_, PIN, C>
where
PIN: super::Pin,
{
impl crate::etm::EtmEvent for Event<'_> {
fn id(&self) -> u8 {
1 + C
}
}
/// Event for falling edge
#[non_exhaustive]
pub struct GpioEtmEventChannelFalling<'d, PIN, const C: u8>
where
PIN: super::Pin,
{
_pin: PeripheralRef<'d, PIN>,
}
impl<PIN, const C: u8> private::Sealed for GpioEtmEventChannelFalling<'_, PIN, C> where
PIN: super::Pin
{
}
impl<PIN, const C: u8> crate::etm::EtmEvent for GpioEtmEventChannelFalling<'_, PIN, C>
where
PIN: super::Pin,
{
fn id(&self) -> u8 {
9 + C
}
}
/// Event for any edge
#[non_exhaustive]
pub struct GpioEtmEventChannelAny<'d, PIN, const C: u8>
where
PIN: super::Pin,
{
_pin: PeripheralRef<'d, PIN>,
}
impl<PIN, const C: u8> private::Sealed for GpioEtmEventChannelAny<'_, PIN, C> where PIN: super::Pin {}
impl<PIN, const C: u8> crate::etm::EtmEvent for GpioEtmEventChannelAny<'_, PIN, C>
where
PIN: super::Pin,
{
fn id(&self) -> u8 {
17 + C
self.id
}
}
/// Configuration for an ETM controlled GPIO output pin
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct GpioEtmOutputConfig {
pub struct OutputConfig {
/// Set to open-drain output
pub open_drain: bool,
/// Only used when open-drain
@ -271,7 +237,7 @@ pub struct GpioEtmOutputConfig {
pub initial_state: Level,
}
impl Default for GpioEtmOutputConfig {
impl Default for OutputConfig {
fn default() -> Self {
Self {
open_drain: false,
@ -282,70 +248,48 @@ impl Default for GpioEtmOutputConfig {
}
/// An ETM controlled GPIO task
pub struct GpioEtmTaskChannel<const C: u8> {}
pub struct TaskChannel<const C: u8> {}
impl<const C: u8> GpioEtmTaskChannel<C> {
impl<const C: u8> TaskChannel<C> {
// In theory we could have multiple pins assigned to the same task. Not sure how
// useful that would be. If we want to support it, the easiest would be
// to offer additional functions like `set2`, `set3` etc. where the
// number is the pin-count
/// Task to set a high level
pub fn set<'d, PIN>(
pub fn set<'d>(
self,
pin: impl Peripheral<P = PIN> + 'd,
pin_config: GpioEtmOutputConfig,
) -> GpioEtmTaskSet<'d, PIN, C>
where
PIN: super::OutputPin,
{
crate::into_ref!(pin);
pin.set_output_high(pin_config.initial_state.into(), private::Internal);
if pin_config.open_drain {
pin.pull_direction(pin_config.pull, private::Internal);
pin.set_to_open_drain_output(private::Internal);
} else {
pin.set_to_push_pull_output(private::Internal);
}
enable_task_channel(C, pin.number());
GpioEtmTaskSet { _pin: pin }
pin: impl Peripheral<P = impl Into<OutputSignal>> + 'd,
pin_config: OutputConfig,
) -> Task<'d> {
self.into_task(pin, pin_config, TaskKind::Set)
}
/// Task to set a low level
pub fn clear<'d, PIN>(
pub fn clear<'d>(
self,
pin: impl Peripheral<P = PIN> + 'd,
pin_config: GpioEtmOutputConfig,
) -> GpioEtmTaskClear<'d, PIN, C>
where
PIN: super::OutputPin,
{
crate::into_ref!(pin);
pin.set_output_high(pin_config.initial_state.into(), private::Internal);
if pin_config.open_drain {
pin.pull_direction(pin_config.pull, private::Internal);
pin.set_to_open_drain_output(private::Internal);
} else {
pin.set_to_push_pull_output(private::Internal);
}
enable_task_channel(C, pin.number());
GpioEtmTaskClear { _pin: pin }
pin: impl Peripheral<P = impl Into<OutputSignal>> + 'd,
pin_config: OutputConfig,
) -> Task<'d> {
self.into_task(pin, pin_config, TaskKind::Clear)
}
/// Task to toggle the level
pub fn toggle<'d, PIN>(
pub fn toggle<'d>(
self,
pin: impl Peripheral<P = PIN> + 'd,
pin_config: GpioEtmOutputConfig,
) -> GpioEtmTaskToggle<'d, PIN, C>
where
PIN: super::OutputPin,
{
crate::into_ref!(pin);
pin: impl Peripheral<P = impl Into<OutputSignal>> + 'd,
pin_config: OutputConfig,
) -> Task<'d> {
self.into_task(pin, pin_config, TaskKind::Toggle)
}
fn into_task<'d>(
self,
pin: impl Peripheral<P = impl Into<OutputSignal>> + 'd,
pin_config: OutputConfig,
kind: TaskKind,
) -> Task<'d> {
crate::into_mapped_ref!(pin);
pin.set_output_high(pin_config.initial_state.into(), private::Internal);
if pin_config.open_drain {
@ -356,66 +300,47 @@ impl<const C: u8> GpioEtmTaskChannel<C> {
}
enable_task_channel(C, pin.number());
GpioEtmTaskToggle { _pin: pin }
Task {
id: kind.id() + C,
_pin: PhantomData,
}
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
enum TaskKind {
Set,
Clear,
Toggle,
}
impl TaskKind {
fn id(&self) -> u8 {
match self {
TaskKind::Set => 1,
TaskKind::Clear => 9,
TaskKind::Toggle => 17,
}
}
}
/// Task for set operation
#[non_exhaustive]
pub struct GpioEtmTaskSet<'d, PIN, const C: u8>
where
PIN: super::Pin,
{
_pin: PeripheralRef<'d, PIN>,
pub struct Task<'d> {
_pin: PhantomData<&'d mut ()>,
id: u8,
}
impl<PIN, const C: u8> private::Sealed for GpioEtmTaskSet<'_, PIN, C> where PIN: super::Pin {}
impl private::Sealed for Task<'_> {}
impl<PIN, const C: u8> crate::etm::EtmTask for GpioEtmTaskSet<'_, PIN, C>
where
PIN: super::Pin,
{
impl crate::etm::EtmTask for Task<'_> {
fn id(&self) -> u8 {
1 + C
}
}
/// Task for clear operation
#[non_exhaustive]
pub struct GpioEtmTaskClear<'d, PIN, const C: u8> {
_pin: PeripheralRef<'d, PIN>,
}
impl<PIN, const C: u8> private::Sealed for GpioEtmTaskClear<'_, PIN, C> where PIN: super::Pin {}
impl<PIN, const C: u8> crate::etm::EtmTask for GpioEtmTaskClear<'_, PIN, C>
where
PIN: super::Pin,
{
fn id(&self) -> u8 {
9 + C
}
}
/// Task for toggle operation
#[non_exhaustive]
pub struct GpioEtmTaskToggle<'d, PIN, const C: u8> {
_pin: PeripheralRef<'d, PIN>,
}
impl<PIN, const C: u8> private::Sealed for GpioEtmTaskToggle<'_, PIN, C> where PIN: super::Pin {}
impl<PIN, const C: u8> crate::etm::EtmTask for GpioEtmTaskToggle<'_, PIN, C>
where
PIN: super::Pin,
{
fn id(&self) -> u8 {
17 + C
self.id
}
}
fn enable_task_channel(channel: u8, pin: u8) {
let gpio_sd = unsafe { crate::peripherals::GPIO_SD::steal() };
let gpio_sd = unsafe { GPIO_SD::steal() };
let ptr = unsafe { gpio_sd.etm_task_p0_cfg().as_ptr().add(pin as usize / 4) };
let shift = 8 * (pin as usize % 4);
// bit 0 = en, bit 1-3 = channel
@ -427,7 +352,7 @@ fn enable_task_channel(channel: u8, pin: u8) {
}
fn enable_event_channel(channel: u8, pin: u8) {
let gpio_sd = unsafe { crate::peripherals::GPIO_SD::steal() };
let gpio_sd = unsafe { GPIO_SD::steal() };
gpio_sd
.etm_event_ch_cfg(channel as usize)
.modify(|_, w| w.event_en().clear_bit());

View File

@ -60,6 +60,15 @@ pub struct InputSignal {
is_inverted: bool,
}
impl<P> From<P> for InputSignal
where
P: InputPin,
{
fn from(input: P) -> Self {
Self::new(input.degrade())
}
}
impl Clone for InputSignal {
fn clone(&self) -> Self {
Self {
@ -87,6 +96,11 @@ impl InputSignal {
}
}
/// Returns the GPIO number of the underlying pin.
pub fn number(&self) -> u8 {
self.pin.number()
}
/// Returns the current signal level.
pub fn get_level(&self) -> Level {
self.is_input_high(private::Internal).into()
@ -120,9 +134,7 @@ impl InputSignal {
w.in_sel().bits(input)
});
}
}
impl InputSignal {
/// Connect the pin to a peripheral input signal.
///
/// Since there can only be one input signal connected to a peripheral at a
@ -191,6 +203,15 @@ pub struct OutputSignal {
is_inverted: bool,
}
impl<P> From<P> for OutputSignal
where
P: OutputPin,
{
fn from(input: P) -> Self {
Self::new(input.degrade())
}
}
impl Peripheral for OutputSignal {
type P = Self;
@ -212,6 +233,11 @@ impl OutputSignal {
}
}
/// Returns the GPIO number of the underlying pin.
pub fn number(&self) -> u8 {
self.pin.number()
}
/// Inverts the peripheral's output signal.
///
/// Calling this function multiple times toggles the setting.
@ -268,9 +294,7 @@ impl OutputSignal {
w.oen_inv_sel().bit(invert_enable)
});
}
}
impl OutputSignal {
/// Connect the pin to a peripheral input signal.
///
/// Since there can only be one signal connected to a peripheral input at a
@ -434,9 +458,7 @@ where
P: InputPin,
{
fn from(input: P) -> Self {
Self(InputConnectionInner::Input(InputSignal::new(
input.degrade(),
)))
Self(InputConnectionInner::Input(InputSignal::from(input)))
}
}
@ -527,9 +549,7 @@ where
P: OutputPin,
{
fn from(input: P) -> Self {
Self(OutputConnectionInner::Output(OutputSignal::new(
input.degrade(),
)))
Self(OutputConnectionInner::Output(OutputSignal::from(input)))
}
}

View File

@ -1104,27 +1104,25 @@ pub mod etm {
//! ## Example
//! ```rust, no_run
#![doc = crate::before_snippet!()]
//! # use esp_hal::timer::systimer::{etm::SysTimerEtmEvent, SystemTimer};
//! # use esp_hal::timer::systimer::{etm::Event, SystemTimer};
//! # use fugit::ExtU32;
//! let syst = SystemTimer::new(peripherals.SYSTIMER);
//! let syst_alarms = syst.split();
//! let mut alarm0 = syst_alarms.alarm0.into_periodic();
//! alarm0.set_period(1u32.secs());
//!
//! let timer_event = SysTimerEtmEvent::new(&mut alarm0);
//! let timer_event = Event::new(&mut alarm0);
//! # }
//! ```
use super::*;
/// An ETM controlled SYSTIMER event
pub struct SysTimerEtmEvent<'a, 'd, M, DM: crate::Mode, COMP, UNIT> {
pub struct Event<'a, 'd, M, DM: crate::Mode, COMP, UNIT> {
alarm: &'a mut Alarm<'d, M, DM, COMP, UNIT>,
}
impl<'a, 'd, M, DM: crate::Mode, COMP: Comparator, UNIT: Unit>
SysTimerEtmEvent<'a, 'd, M, DM, COMP, UNIT>
{
impl<'a, 'd, M, DM: crate::Mode, COMP: Comparator, UNIT: Unit> Event<'a, 'd, M, DM, COMP, UNIT> {
/// Creates an ETM event from the given [Alarm]
pub fn new(alarm: &'a mut Alarm<'d, M, DM, COMP, UNIT>) -> Self {
Self { alarm }
@ -1138,12 +1136,12 @@ pub mod etm {
}
impl<M, DM: crate::Mode, COMP: Comparator, UNIT: Unit> crate::private::Sealed
for SysTimerEtmEvent<'_, '_, M, DM, COMP, UNIT>
for Event<'_, '_, M, DM, COMP, UNIT>
{
}
impl<M, DM: crate::Mode, COMP: Comparator, UNIT: Unit> crate::etm::EtmEvent
for SysTimerEtmEvent<'_, '_, M, DM, COMP, UNIT>
for Event<'_, '_, M, DM, COMP, UNIT>
{
fn id(&self) -> u8 {
50 + self.alarm.comparator.channel()

View File

@ -1349,87 +1349,87 @@ pub mod etm {
use crate::etm::{EtmEvent, EtmTask};
/// Event Task Matrix event for a timer.
pub struct TimerEtmEvent {
pub struct Event {
id: u8,
}
/// Event Task Matrix task for a timer.
pub struct TimerEtmTask {
pub struct Task {
id: u8,
}
impl EtmEvent for TimerEtmEvent {
impl EtmEvent for Event {
fn id(&self) -> u8 {
self.id
}
}
impl Sealed for TimerEtmEvent {}
impl Sealed for Event {}
impl EtmTask for TimerEtmTask {
impl EtmTask for Task {
fn id(&self) -> u8 {
self.id
}
}
impl Sealed for TimerEtmTask {}
impl Sealed for Task {}
/// General purpose timer ETM events.
pub trait TimerEtmEvents<TG> {
pub trait Events<TG> {
/// ETM event triggered on alarm
fn on_alarm(&self) -> TimerEtmEvent;
fn on_alarm(&self) -> Event;
}
/// General purpose timer ETM tasks
pub trait TimerEtmTasks<TG> {
pub trait Tasks<TG> {
/// ETM task to start the counter
fn cnt_start(&self) -> TimerEtmTask;
fn cnt_start(&self) -> Task;
/// ETM task to start the alarm
fn cnt_stop(&self) -> TimerEtmTask;
fn cnt_stop(&self) -> Task;
/// ETM task to stop the counter
fn cnt_reload(&self) -> TimerEtmTask;
fn cnt_reload(&self) -> Task;
/// ETM task to reload the counter
fn cnt_cap(&self) -> TimerEtmTask;
fn cnt_cap(&self) -> Task;
/// ETM task to load the counter with the value stored when the last
/// `now()` was called
fn alarm_start(&self) -> TimerEtmTask;
fn alarm_start(&self) -> Task;
}
impl<TG> TimerEtmEvents<TG> for Timer0<TG>
impl<TG> Events<TG> for Timer0<TG>
where
TG: TimerGroupInstance,
{
fn on_alarm(&self) -> TimerEtmEvent {
TimerEtmEvent { id: 48 + TG::id() }
fn on_alarm(&self) -> Event {
Event { id: 48 + TG::id() }
}
}
impl<TG> TimerEtmTasks<TG> for Timer0<TG>
impl<TG> Tasks<TG> for Timer0<TG>
where
TG: TimerGroupInstance,
{
fn cnt_start(&self) -> TimerEtmTask {
TimerEtmTask { id: 88 + TG::id() }
fn cnt_start(&self) -> Task {
Task { id: 88 + TG::id() }
}
fn alarm_start(&self) -> TimerEtmTask {
TimerEtmTask { id: 90 + TG::id() }
fn alarm_start(&self) -> Task {
Task { id: 90 + TG::id() }
}
fn cnt_stop(&self) -> TimerEtmTask {
TimerEtmTask { id: 92 + TG::id() }
fn cnt_stop(&self) -> Task {
Task { id: 92 + TG::id() }
}
fn cnt_reload(&self) -> TimerEtmTask {
TimerEtmTask { id: 94 + TG::id() }
fn cnt_reload(&self) -> Task {
Task { id: 94 + TG::id() }
}
fn cnt_cap(&self) -> TimerEtmTask {
TimerEtmTask { id: 96 + TG::id() }
fn cnt_cap(&self) -> Task {
Task { id: 96 + TG::id() }
}
}
}

View File

@ -12,13 +12,13 @@ use esp_backtrace as _;
use esp_hal::{
etm::Etm,
gpio::{
etm::{GpioEtmChannels, GpioEtmOutputConfig},
etm::{Channels, OutputConfig},
Io,
Level,
Pull,
},
prelude::*,
timer::systimer::{etm::SysTimerEtmEvent, Periodic, SystemTimer},
timer::systimer::{etm::Event, Periodic, SystemTimer},
};
use fugit::ExtU32;
@ -35,17 +35,17 @@ fn main() -> ! {
let mut led = io.pins.gpio1;
// setup ETM
let gpio_ext = GpioEtmChannels::new(peripherals.GPIO_SD);
let gpio_ext = Channels::new(peripherals.GPIO_SD);
let led_task = gpio_ext.channel0_task.toggle(
&mut led,
GpioEtmOutputConfig {
OutputConfig {
open_drain: false,
pull: Pull::None,
initial_state: Level::High,
},
);
let timer_event = SysTimerEtmEvent::new(&mut alarm0);
let timer_event = Event::new(&mut alarm0);
let etm = Etm::new(peripherals.SOC_ETM);
let channel0 = etm.channel0;

View File

@ -12,7 +12,7 @@ use esp_backtrace as _;
use esp_hal::{
etm::Etm,
gpio::{
etm::{GpioEtmChannels, GpioEtmInputConfig, GpioEtmOutputConfig},
etm::{Channels, InputConfig, OutputConfig},
Io,
Level,
Output,
@ -26,16 +26,17 @@ fn main() -> ! {
let peripherals = esp_hal::init(esp_hal::Config::default());
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let mut led = Output::new(io.pins.gpio1, Level::Low);
let button = io.pins.gpio9;
led.set_high();
// setup ETM
let gpio_ext = GpioEtmChannels::new(peripherals.GPIO_SD);
let gpio_ext = Channels::new(peripherals.GPIO_SD);
let led_task = gpio_ext.channel0_task.toggle(
&mut led,
GpioEtmOutputConfig {
led,
OutputConfig {
open_drain: false,
pull: Pull::None,
initial_state: Level::Low,
@ -43,7 +44,7 @@ fn main() -> ! {
);
let button_event = gpio_ext
.channel0_event
.falling_edge(button, GpioEtmInputConfig { pull: Pull::Down });
.falling_edge(button, InputConfig { pull: Pull::Down });
let etm = Etm::new(peripherals.SOC_ETM);
let channel0 = etm.channel0;

View File

@ -1,5 +1,5 @@
//! This shows how to use the general purpose timers ETM tasks and events
//! Notice you need to import the traits esp_hal::timer::etm::{TimerEtmEvents, TimerEtmTasks}
//! Notice you need to import the traits esp_hal::timer::etm::{Events, Tasks}
//% CHIPS: esp32c6 esp32h2
@ -16,7 +16,7 @@ use esp_hal::{
peripherals::TIMG0,
prelude::*,
timer::timg::{
etm::{TimerEtmEvents, TimerEtmTasks},
etm::{Events, Tasks},
Timer,
Timer0,
TimerGroup,