Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make RMT TX larger than one block work on ESP32-C3 and ESP32-S3 #143

Merged
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
28 changes: 17 additions & 11 deletions esp-hal-common/src/pulse_control.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@
//! // Create pulse sequence
//! let mut seq = [PulseCode {
//! level1: true,
//! length1: 1,
//! length1: 10u32.nanos(),
//! level2: false,
//! length2: 9,
//! length2: 90u32.nanos(),
//! }; 288];
//!
//! // Send sequence
Expand Down Expand Up @@ -284,13 +284,6 @@ macro_rules! channel_instance {
// Configure memory block size
w.mem_size()
.bits(1)
// Set config bit
.conf_update()
.set_bit()
// Enable wrap mode (this is enabled globally for
// the ESP32 and ESP32-S2)
.mem_tx_wrap_en()
.set_bit()
});
}
else {
Expand Down Expand Up @@ -588,7 +581,7 @@ macro_rules! output_channel {
self.write_sequence(&mut sequence_iter, CHANNEL_RAM_SIZE);
} else {
// Write whole sequence to FIFO RAM
self.write_sequence(&mut sequence_iter, CHANNEL_RAM_SIZE - 1);
self.write_sequence(&mut sequence_iter, CHANNEL_RAM_SIZE);
}

// Clear the relevant interrupts
Expand Down Expand Up @@ -639,6 +632,19 @@ macro_rules! output_channel {
}
}

// always enable tx wrap
#[cfg(any(feature = "esp32c3", feature = "esp32s3"))]
unsafe { &*RMT::PTR }.ch_tx_conf0[$num].modify(|_, w| {
w.mem_tx_wrap_en()
.set_bit()
});

// apply configuration updates
#[cfg(any(feature = "esp32c3", feature = "esp32s3"))]
unsafe { &*RMT::PTR }.ch_tx_conf0[$num].modify(|_, w| {
w.conf_update()
.set_bit()
});

// Depending on the variant, other registers have to be used here
cfg_if::cfg_if! {
Expand Down Expand Up @@ -929,7 +935,7 @@ macro_rules! rmt {
self.reg.int_ena.write(|w| unsafe { w.bits(0) });

// Clear all interrupts
self.reg.int_clr.write(|w| unsafe { w.bits(0) });
self.reg.int_clr.write(|w| unsafe { w.bits(0xffffffff) });

Ok(())
}
Expand Down
78 changes: 78 additions & 0 deletions esp32-hal/examples/pulse_control.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
//! This demos basic usage of RMT / PulseControl
//! Use a logic analyzer to see the generated pulses.
//! The correct output is only achieved when running in release mode.

#![no_std]
#![no_main]

use esp32_hal::{
clock::ClockControl,
gpio::IO,
pac::Peripherals,
prelude::*,
pulse_control::{OutputChannel, PulseCode, RepeatMode},
timer::TimerGroup,
PulseControl,
Rtc,
};
use panic_halt as _;
use xtensa_lx_rt::entry;

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

let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let mut wdt = timer_group0.wdt;
let mut rtc = Rtc::new(peripherals.RTC_CNTL);

// Disable MWDT and RWDT (Watchdog) flash boot protection
wdt.disable();
rtc.rwdt.disable();

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

// Configure RMT peripheral globally
let pulse = PulseControl::new(peripherals.RMT, &mut system.peripheral_clock_control).unwrap();

let mut rmt_channel0 = pulse.channel0;

rmt_channel0
.set_idle_output_level(false)
.set_carrier_modulation(false)
.set_channel_divider(1)
.set_idle_output(true);

// Assign GPIO pin where pulses should be sent to
rmt_channel0.assign_pin(io.pins.gpio4);

// Create pulse sequence
let mut seq = [PulseCode {
level1: true,
length1: 0u32.nanos(),
level2: false,
length2: 0u32.nanos(),
}; 128];

// -1 to make sure that the last element is a transmission end marker (i.e.
// lenght 0)
for i in 0..(seq.len() - 1) {
seq[i] = PulseCode {
level1: true,
length1: (10u32 * (i as u32 + 1u32)).nanos(),
level2: false,
length2: 60u32.nanos(),
};
}

esp_println::println!("Start");

loop {
// Send sequence
rmt_channel0
.send_pulse_sequence(RepeatMode::SingleShot, &seq)
.unwrap();
}
}
93 changes: 93 additions & 0 deletions esp32c3-hal/examples/pulse_control.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
//! This demos basic usage of RMT / PulseControl
//! Use a logic analyzer to see the generated pulses.
//! The correct output is only achieved when running in release mode.

#![no_std]
#![no_main]

use esp32c3_hal::{
clock::ClockControl,
gpio::IO,
pac::Peripherals,
prelude::*,
pulse_control::{ClockSource, OutputChannel, PulseCode, RepeatMode},
system::SystemExt,
timer::TimerGroup,
PulseControl,
Rtc,
};
use panic_halt as _;
use riscv_rt::entry;

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

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

rtc.swd.disable();
rtc.rwdt.disable();
wdt0.disable();
wdt1.disable();

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

// Configure RMT peripheral globally
let pulse = PulseControl::new(
peripherals.RMT,
&mut system.peripheral_clock_control,
ClockSource::APB,
0,
0,
0,
)
.unwrap();

let mut rmt_channel0 = pulse.channel0;

// Set up channel
rmt_channel0
.set_idle_output_level(false)
.set_carrier_modulation(false)
.set_channel_divider(1)
.set_idle_output(true);

// Assign GPIO pin where pulses should be sent to
rmt_channel0.assign_pin(io.pins.gpio4);

// Create pulse sequence
let mut seq = [PulseCode {
level1: true,
length1: 0u32.nanos(),
level2: false,
length2: 0u32.nanos(),
}; 128];

// -1 to make sure that the last element is a transmission end marker (i.e.
// lenght 0)
for i in 0..(seq.len() - 1) {
seq[i] = PulseCode {
level1: true,
length1: (10u32 * (i as u32 + 1u32)).nanos(),
level2: false,
length2: 60u32.nanos(),
};
}

esp_println::println!("Start");

loop {
// Send sequence
rmt_channel0
.send_pulse_sequence(RepeatMode::SingleShot, &seq)
.unwrap();
}
}
10 changes: 5 additions & 5 deletions esp32c3-hal/examples/rtc_watchdog.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
//! This demos the RTC Watchdog Timer (RWDT).
//! The RWDT is initially configured to trigger an interrupt after a given timeout.
//! Then, upon expiration, the RWDT is restarted and then reconfigured to reset both the main
//! system and the RTC.
//! The RWDT is initially configured to trigger an interrupt after a given
//! timeout. Then, upon expiration, the RWDT is restarted and then reconfigured
//! to reset both the main system and the RTC.

#![no_std]
#![no_main]

use core::cell::RefCell;

use bare_metal::Mutex;

use esp32c3_hal::{
clock::ClockControl,
interrupt,
pac::{self, Peripherals},
prelude::*,
Rtc, Rwdt,
Rtc,
Rwdt,
};
use panic_halt as _;
use riscv_rt::entry;
Expand Down
7 changes: 6 additions & 1 deletion esp32c3-hal/examples/watchdog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
use core::fmt::Write;

use esp32c3_hal::{
clock::ClockControl, pac::Peripherals, prelude::*, timer::TimerGroup, Rtc, Serial,
clock::ClockControl,
pac::Peripherals,
prelude::*,
timer::TimerGroup,
Rtc,
Serial,
};
use nb::block;
use panic_halt as _;
Expand Down
25 changes: 23 additions & 2 deletions esp32c3-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,29 @@ use core::arch::global_asm;

pub use embedded_hal as ehal;
pub use esp_hal_common::{
clock, efuse, gpio as gpio_types, i2c, interrupt, ledc, macros, pac, prelude, pulse_control,
serial, spi, system, systimer, timer, utils, Cpu, Delay, PulseControl, Rng, Rtc, Rwdt, Serial,
clock,
efuse,
gpio as gpio_types,
i2c,
interrupt,
ledc,
macros,
pac,
prelude,
pulse_control,
serial,
spi,
system,
systimer,
timer,
utils,
Cpu,
Delay,
PulseControl,
Rng,
Rtc,
Rwdt,
Serial,
UsbSerialJtag,
};
#[cfg(feature = "direct-boot")]
Expand Down
79 changes: 79 additions & 0 deletions esp32s2-hal/examples/pulse_control.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
//! This demos basic usage of RMT / PulseControl
//! Use a logic analyzer to see the generated pulses.
//! The correct output is only achieved when running in release mode.

#![no_std]
#![no_main]

use esp32s2_hal::{
clock::ClockControl,
gpio::IO,
pac::Peripherals,
prelude::*,
pulse_control::{OutputChannel, PulseCode, RepeatMode},
timer::TimerGroup,
PulseControl,
Rtc,
};
use panic_halt as _;
use xtensa_lx_rt::entry;

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

let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks);
let mut wdt = timer_group0.wdt;
let mut rtc = Rtc::new(peripherals.RTC_CNTL);

// Disable MWDT and RWDT (Watchdog) flash boot protection
wdt.disable();
rtc.rwdt.disable();

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

// Configure RMT peripheral globally
let pulse = PulseControl::new(peripherals.RMT, &mut system.peripheral_clock_control).unwrap();

let mut rmt_channel0 = pulse.channel0;

// Set up channel
rmt_channel0
.set_idle_output_level(false)
.set_carrier_modulation(false)
.set_channel_divider(1)
.set_idle_output(true);

// Assign GPIO pin where pulses should be sent to
rmt_channel0.assign_pin(io.pins.gpio4);

// Create pulse sequence
let mut seq = [PulseCode {
level1: true,
length1: 0u32.nanos(),
level2: false,
length2: 0u32.nanos(),
}; 128];

// -1 to make sure that the last element is a transmission end marker (i.e.
// lenght 0)
for i in 0..(seq.len() - 1) {
seq[i] = PulseCode {
level1: true,
length1: (10u32 * (i as u32 + 1u32)).nanos(),
level2: false,
length2: 60u32.nanos(),
};
}

esp_println::println!("Start");

loop {
// Send sequence
rmt_channel0
.send_pulse_sequence(RepeatMode::SingleShot, &seq)
.unwrap();
}
}
Loading