Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Implement Copy and Eq for EspTwaiError (#540)
- Add LEDC hardware fade support
- Added support for multicore async GPIO (#542)
- Add initial support for MCPWM in ESP32-H2 (#544)

### Fixed

Expand Down
2 changes: 1 addition & 1 deletion esp-hal-common/devices/esp32h2.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ peripherals = [
# "lp_peri",
# "lp_timer",
"lp_wdt",
# "mcpwm0",
"mcpwm0",
# "mem_monitor",
# "modem_lpcon",
# "modem_syscon",
Expand Down
20 changes: 20 additions & 0 deletions esp-hal-common/src/mcpwm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,22 @@ impl<'d, PWM: PwmPeripheral> MCPWM<'d, PWM> {
// TODO: Add other clock sources
}

#[cfg(esp32h2)]
{
unsafe { &*crate::peripherals::PCR::PTR }
.pwm_clk_conf
.modify(|_, w| unsafe {
w.pwm_div_num()
.variant(peripheral_clock.prescaler)
.pwm_clkm_en()
.set_bit()
.pwm_clkm_sel()
.bits(0)
});

// TODO: Add other clock sources
}

Self {
_inner: peripheral,
timer0: Timer::new(),
Expand Down Expand Up @@ -169,6 +185,8 @@ impl<'a> PeripheralClockConfig<'a> {
let source_clock = clocks.crypto_clock;
#[cfg(esp32s3)]
let source_clock = clocks.crypto_pwm_clock;
#[cfg(esp32h2)]
let source_clock = clocks.xtal_clock;

Self {
frequency: source_clock / (prescaler as u32 + 1),
Expand Down Expand Up @@ -201,6 +219,8 @@ impl<'a> PeripheralClockConfig<'a> {
let source_clock = clocks.crypto_clock;
#[cfg(esp32s3)]
let source_clock = clocks.crypto_pwm_clock;
#[cfg(esp32h2)]
let source_clock = clocks.xtal_clock;

if target_freq.raw() == 0 || target_freq > source_clock {
return Err(FrequencyError);
Expand Down
4 changes: 2 additions & 2 deletions esp-hal-common/src/mcpwm/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
}

/// Set how a new timestamp syncs with the timer
#[cfg(esp32c6)]
#[cfg(any(esp32c6, esp32h2))]
pub fn set_update_method(&mut self, update_method: PwmUpdateMethod) {
// SAFETY:
// We only write to our GENx_x_UPMETHOD register
Expand Down Expand Up @@ -300,7 +300,7 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool>
/// Write a new timestamp.
/// The written value will take effect according to the set
/// [`PwmUpdateMethod`].
#[cfg(esp32c6)]
#[cfg(any(esp32c6, esp32h2))]
pub fn set_timestamp(&mut self, value: u16) {
// SAFETY:
// We only write to our GENx_TSTMP_x register
Expand Down
12 changes: 6 additions & 6 deletions esp-hal-common/src/soc/esp32h2/gpio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,12 @@ pub enum OutputSignal {
GPIO_SD1 = 84,
GPIO_SD2 = 85,
GPIO_SD3 = 86,
PWM0_OUT0A = 87,
PWM0_OUT0B = 88,
PWM0_OUT1A = 89,
PWM0_OUT1B = 90,
PWM0_OUT2A = 91,
PWM0_OUT2B = 92,
PWM0_0A = 87,
PWM0_0B = 88,
PWM0_1A = 89,
PWM0_1B = 90,
PWM0_2A = 91,
PWM0_2B = 92,
SIG_IN_FUNC97 = 97,
SIG_IN_FUNC98 = 98,
SIG_IN_FUNC99 = 99,
Expand Down
2 changes: 1 addition & 1 deletion esp-hal-common/src/soc/esp32h2/peripherals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ crate::peripherals! {
// LP_PERI => true,
// LP_TIMER => true,
LP_WDT => true,
// MCPWM0 => true,
MCPWM0 => true,
// MEM_MONITOR => true,
// MODEM_LPCON => true,
// MODEM_SYSCON => true,
Expand Down
79 changes: 79 additions & 0 deletions esp32h2-hal/examples/mcpwm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//! Uses timer0 and operator0 of the MCPWM0
//!
//! to output a 50% duty
//! signal at 16 kHz.
//!
//! The signal will be output to the pin assigned to `pin`. (GPIO4)

#![no_std]
#![no_main]

use esp32h2_hal::{
clock::ClockControl,
gpio::IO,
mcpwm::{operator::PwmPinConfig, timer::PwmWorkingMode, PeripheralClockConfig, MCPWM},
peripherals::Peripherals,
prelude::*,
timer::TimerGroup,
Rtc,
};
use esp_backtrace as _;

#[entry]
fn main() -> ! {
let peripherals = Peripherals::take();
let mut system = peripherals.PCR.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();

// Disable the watchdog timers. For the ESP32-H2, this includes the Super WDT,
// and the TIMG WDTs.
let mut rtc = Rtc::new(peripherals.LP_CLKRST);
let timer_group0 = TimerGroup::new(
peripherals.TIMG0,
&clocks,
&mut system.peripheral_clock_control,
);
let mut wdt0 = timer_group0.wdt;
let timer_group1 = TimerGroup::new(
peripherals.TIMG1,
&clocks,
&mut system.peripheral_clock_control,
);
let mut wdt1 = timer_group1.wdt;

// Disable watchdog timers
rtc.swd.disable();
rtc.rwdt.disable();
wdt0.disable();
wdt1.disable();

let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
let pin = io.pins.gpio4;

// initialize peripheral
let clock_cfg = PeripheralClockConfig::with_frequency(&clocks, 32u32.MHz()).unwrap();
let mut mcpwm = MCPWM::new(
peripherals.MCPWM0,
clock_cfg,
&mut system.peripheral_clock_control,
);

// connect operator0 to timer0
mcpwm.operator0.set_timer(&mcpwm.timer0);
// connect operator0 to pin
let mut pwm_pin = mcpwm
.operator0
.with_pin_a(pin, PwmPinConfig::UP_ACTIVE_HIGH);

// start timer with timestamp values in the range of 0..=99 and a frequency of
// 20 kHz
let timer_clock_cfg = clock_cfg
.timer_clock_with_frequency(99, PwmWorkingMode::Increase, 20u32.kHz())
.unwrap();
mcpwm.timer0.start(timer_clock_cfg);

// pin will be high 50% of the time
pwm_pin.set_timestamp(50);

loop {}
}