Add some miscellaneous examples for the ESP32-H2 (#548)

* Add some miscellaneous examples for the ESP32-H2

* Update the CHANGELOG
This commit is contained in:
Jesse Braham 2023-05-17 07:13:47 -07:00 committed by GitHub
parent 3be64df304
commit 661a9de5eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 428 additions and 14 deletions

View File

@ -224,10 +224,10 @@ jobs:
run: cd esp32h2-hal/ && cargo +nightly check --examples --features=eh1,ufmt
- name: check esp32h2-hal (async, i2c)
run: cd esp32h2-hal/ && cargo check --example=embassy_i2c --features=embassy,embassy-time-systick,async
# - name: check esp32h2-hal (async, systick)
# run: cd esp32h2-hal/ && cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-systick
# - name: check esp32h2-hal (async, timg0)
# run: cd esp32h2-hal/ && cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-timg0
- name: check esp32h2-hal (async, systick)
run: cd esp32h2-hal/ && cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-systick
- name: check esp32h2-hal (async, timg0)
run: cd esp32h2-hal/ && cargo +nightly check --example=embassy_hello_world --features=embassy,embassy-time-timg0
# - name: check esp32h2-hal (async, gpio)
# run: cd esp32h2-hal/ && cargo +nightly check --example=embassy_wait --features=embassy,embassy-time-systick,async
# - name: check esp32h2-hal (async, spi)
@ -440,7 +440,7 @@ jobs:
uses: dangoslen/changelog-enforcer@v3
with:
changeLogPath: CHANGELOG.md
skipLabels: 'skip-changelog'
missingUpdateErrorMessage: 'Please add a changelog entry in the CHANGELOG.md file.'
skipLabels: "skip-changelog"
missingUpdateErrorMessage: "Please add a changelog entry in the CHANGELOG.md file."
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -24,21 +24,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Add LEDC hardware fade support
- Added support for multicore async GPIO (#542)
- Add initial support for MCPWM in ESP32-H2 (#544)
- Add some miscellaneous examples for the ESP32-H2 (#548)
### Fixed
- DMA is supported for SPI3 on ESP32-S3 (#507)
- `change_bus_frequency` is now available on `SpiDma` (#529)
- Fixed a bug where a GPIO interrupt could erroneously fire again causing the next `await` on that pin to instantly return `Poll::Ok` (#537)
- Fixed a bug where a GPIO interrupt could erroneously fire again causing the next `await` on that pin to instantly return `Poll::Ok` (#537)
- Set `vecbase` on core 1 (ESP32, ESP32-S3) (#536)
- ESP32-S3: Move PSRAM related function to RAM (#546)
### Changed
- Improve examples documentation (#533)
### Breaking
- As part of the refactoring in #537, the public GPIO type has changed.
- As part of the refactoring in #537, the public GPIO type has changed.
## [0.9.0] - 2023-05-02

View File

@ -55,7 +55,7 @@ esp32 = { version = "0.23.0", features = ["critical-section"], optional = true
esp32c2 = { version = "0.11.0", features = ["critical-section"], optional = true }
esp32c3 = { version = "0.14.0", features = ["critical-section"], optional = true }
esp32c6 = { version = "0.4.0", features = ["critical-section"], optional = true }
esp32h2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "5828519", package = "esp32h2", features = ["critical-section"], optional = true }
esp32h2 = { git = "https://github.com/esp-rs/esp-pacs", rev = "ff70333", package = "esp32h2", features = ["critical-section"], optional = true }
esp32s2 = { version = "0.14.0", features = ["critical-section"], optional = true }
esp32s3 = { version = "0.18.0", features = ["critical-section"], optional = true }

View File

@ -56,7 +56,7 @@ peripherals = [
"uart0",
"uart1",
# "uhci0",
# "usb_device",
"usb_device",
# Additional peripherals defined by us (the developers):
"adc",

View File

@ -58,6 +58,6 @@ crate::peripherals! {
UART0 => true,
UART1 => true,
// UHCI0 => true,
// USB_DEVICE => true,
USB_DEVICE => true,
RADIO => false,
}

View File

@ -138,7 +138,7 @@ impl<T, const CHANNEL: u8> Alarm<T, CHANNEL> {
#[cfg(esp32s2)]
systimer.step.write(|w| w.timer_xtal_step().bits(0x1)); // run at XTAL freq, not 80 * XTAL freq
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))]
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
{
tconf.write(|w| w.target0_timer_unit_sel().clear_bit()); // default, use unit 0
systimer
@ -148,7 +148,7 @@ impl<T, const CHANNEL: u8> Alarm<T, CHANNEL> {
conf(tconf, hi, lo);
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))]
#[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))]
{
match CHANNEL {
0 => {

View File

@ -61,6 +61,10 @@ embassy = ["esp-hal-common/embassy"]
embassy-time-systick = ["esp-hal-common/embassy-time-systick", "embassy-time/tick-hz-16_000_000"]
embassy-time-timg0 = ["esp-hal-common/embassy-time-timg0", "embassy-time/tick-hz-1_000_000"]
[[example]]
name = "embassy_hello_world"
required-features = ["embassy"]
[[example]]
name = "embassy_i2c"
required-features = ["embassy", "async", "embassy-time-systick"]
required-features = ["embassy", "async", "embassy-time-systick"]

View File

@ -0,0 +1,89 @@
//! This shows how to configure UART
//! You can short the TX and RX pin and see it reads what was written.
//! Additionally you can connect a logic analzyer to TX and see how the changes
//! of the configuration change the output signal.
#![no_std]
#![no_main]
use esp32h2_hal::{
clock::ClockControl,
peripherals::Peripherals,
prelude::*,
timer::TimerGroup,
uart::{
config::{Config, DataBits, Parity, StopBits},
TxRxPins,
},
Rtc,
Uart,
IO,
};
use esp_backtrace as _;
use esp_println::println;
use nb::block;
#[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 timer0 = timer_group0.timer0;
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;
rtc.swd.disable();
rtc.rwdt.disable();
wdt0.disable();
wdt1.disable();
let config = Config {
baudrate: 115200,
data_bits: DataBits::DataBits8,
parity: Parity::ParityNone,
stop_bits: StopBits::STOP1,
};
let io = IO::new(peripherals.GPIO, peripherals.IO_MUX);
let pins = TxRxPins::new_tx_rx(
io.pins.gpio1.into_push_pull_output(),
io.pins.gpio2.into_floating_input(),
);
let mut serial1 = Uart::new_with_config(
peripherals.UART1,
Some(config),
Some(pins),
&clocks,
&mut system.peripheral_clock_control,
);
timer0.start(250u64.millis());
println!("Start");
loop {
serial1.write(0x42).ok();
let read = block!(serial1.read());
match read {
Ok(read) => println!("Read {:02x}", read),
Err(err) => println!("Error {:?}", err),
}
block!(timer0.wait()).unwrap();
}
}

View File

@ -0,0 +1,82 @@
//! embassy hello world
//!
//! This is an example of running the embassy executor with multiple tasks
//! concurrently.
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]
use embassy_executor::Executor;
use embassy_time::{Duration, Timer};
use esp32h2_hal::{
clock::ClockControl,
embassy,
peripherals::Peripherals,
prelude::*,
timer::TimerGroup,
Rtc,
};
use esp_backtrace as _;
use static_cell::StaticCell;
#[embassy_executor::task]
async fn run1() {
loop {
esp_println::println!("Hello world from embassy using esp-hal-async!");
Timer::after(Duration::from_millis(1_000)).await;
}
}
#[embassy_executor::task]
async fn run2() {
loop {
esp_println::println!("Bing!");
Timer::after(Duration::from_millis(5_000)).await;
}
}
static EXECUTOR: StaticCell<Executor> = StaticCell::new();
#[entry]
fn main() -> ! {
esp_println::println!("Init!");
let peripherals = Peripherals::take();
let mut system = peripherals.PCR.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
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();
#[cfg(feature = "embassy-time-systick")]
embassy::init(
&clocks,
esp32h2_hal::systimer::SystemTimer::new(peripherals.SYSTIMER),
);
#[cfg(feature = "embassy-time-timg0")]
embassy::init(&clocks, timer_group0.timer0);
let executor = EXECUTOR.init(Executor::new());
executor.run(|spawner| {
spawner.spawn(run1()).ok();
spawner.spawn(run2()).ok();
});
}

View File

@ -0,0 +1,138 @@
//! This shows how to use the SYSTIMER peripheral including interrupts.
//! It's an additional timer besides the TIMG peripherals.
#![no_std]
#![no_main]
use core::cell::RefCell;
use critical_section::Mutex;
use esp32h2_hal::{
clock::ClockControl,
interrupt,
interrupt::Priority,
peripherals::{self, Peripherals},
prelude::*,
systimer::{Alarm, Periodic, SystemTimer, Target},
timer::TimerGroup,
Delay,
Rtc,
};
use esp_backtrace as _;
use esp_println::println;
static ALARM0: Mutex<RefCell<Option<Alarm<Periodic, 0>>>> = Mutex::new(RefCell::new(None));
static ALARM1: Mutex<RefCell<Option<Alarm<Target, 1>>>> = Mutex::new(RefCell::new(None));
static ALARM2: Mutex<RefCell<Option<Alarm<Target, 2>>>> = Mutex::new(RefCell::new(None));
#[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 syst = SystemTimer::new(peripherals.SYSTIMER);
println!("SYSTIMER Current value = {}", SystemTimer::now());
let alarm0 = syst.alarm0.into_periodic();
alarm0.set_period(1u32.Hz());
alarm0.clear_interrupt();
alarm0.interrupt_enable(true);
let alarm1 = syst.alarm1;
alarm1.set_target(SystemTimer::now() + (SystemTimer::TICKS_PER_SECOND * 2));
alarm1.interrupt_enable(true);
let alarm2 = syst.alarm2;
alarm2.set_target(SystemTimer::now() + (SystemTimer::TICKS_PER_SECOND * 3));
alarm2.interrupt_enable(true);
critical_section::with(|cs| {
ALARM0.borrow_ref_mut(cs).replace(alarm0);
ALARM1.borrow_ref_mut(cs).replace(alarm1);
ALARM2.borrow_ref_mut(cs).replace(alarm2);
});
interrupt::enable(
peripherals::Interrupt::SYSTIMER_TARGET0,
Priority::Priority1,
)
.unwrap();
interrupt::enable(
peripherals::Interrupt::SYSTIMER_TARGET1,
Priority::Priority2,
)
.unwrap();
interrupt::enable(
peripherals::Interrupt::SYSTIMER_TARGET2,
Priority::Priority2,
)
.unwrap();
// Initialize the Delay peripheral, and use it to toggle the LED state in a
// loop.
let mut delay = Delay::new(&clocks);
loop {
delay.delay_ms(10000u32);
}
}
#[interrupt]
fn SYSTIMER_TARGET0() {
println!("Interrupt lvl1 (alarm0)");
critical_section::with(|cs| {
ALARM0
.borrow_ref_mut(cs)
.as_mut()
.unwrap()
.clear_interrupt()
});
}
#[interrupt]
fn SYSTIMER_TARGET1() {
println!("Interrupt lvl2 (alarm1)");
critical_section::with(|cs| {
ALARM1
.borrow_ref_mut(cs)
.as_mut()
.unwrap()
.clear_interrupt()
});
}
#[interrupt]
fn SYSTIMER_TARGET2() {
println!("Interrupt lvl2 (alarm2)");
critical_section::with(|cs| {
ALARM2
.borrow_ref_mut(cs)
.as_mut()
.unwrap()
.clear_interrupt()
});
}

View File

@ -0,0 +1,99 @@
//! This shows how to output text via USB Serial/JTAG.
//! You need to connect via the Serial/JTAG interface to see any output.
//! Most dev-kits use a USB-UART-bridge - in that case you won't see any output.
#![no_std]
#![no_main]
use core::{cell::RefCell, fmt::Write};
use critical_section::Mutex;
use esp32h2_hal::{
clock::ClockControl,
interrupt,
peripherals::{self, Peripherals},
prelude::*,
riscv,
timer::TimerGroup,
Cpu,
Rtc,
UsbSerialJtag,
};
use esp_backtrace as _;
use nb::block;
static USB_SERIAL: Mutex<RefCell<Option<UsbSerialJtag>>> = Mutex::new(RefCell::new(None));
#[entry]
fn main() -> ! {
let peripherals = Peripherals::take();
let mut system = peripherals.PCR.split();
let clocks = ClockControl::boot_defaults(system.clock_control).freeze();
let mut rtc = Rtc::new(peripherals.LP_CLKRST);
let timer_group0 = TimerGroup::new(
peripherals.TIMG0,
&clocks,
&mut system.peripheral_clock_control,
);
let mut timer0 = timer_group0.timer0;
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 mut usb_serial =
UsbSerialJtag::new(peripherals.USB_DEVICE, &mut system.peripheral_clock_control);
usb_serial.listen_rx_packet_recv_interrupt();
timer0.start(1u64.secs());
critical_section::with(|cs| USB_SERIAL.borrow_ref_mut(cs).replace(usb_serial));
interrupt::enable(peripherals::Interrupt::USB, interrupt::Priority::Priority1).unwrap();
interrupt::set_kind(
Cpu::ProCpu,
interrupt::CpuInterrupt::Interrupt1,
interrupt::InterruptKind::Edge,
);
unsafe {
riscv::interrupt::enable();
}
loop {
critical_section::with(|cs| {
writeln!(
USB_SERIAL.borrow_ref_mut(cs).as_mut().unwrap(),
"Hello world!"
)
.ok();
});
block!(timer0.wait()).unwrap();
}
}
#[interrupt]
fn USB() {
critical_section::with(|cs| {
let mut usb_serial = USB_SERIAL.borrow_ref_mut(cs);
let usb_serial = usb_serial.as_mut().unwrap();
writeln!(usb_serial, "USB serial interrupt").unwrap();
while let nb::Result::Ok(c) = usb_serial.read_byte() {
writeln!(usb_serial, "Read byte: {:02x}", c).unwrap();
}
usb_serial.reset_rx_packet_recv_interrupt();
});
}