H2: enable TWAI, enable delay test (#2199)

* Add TWAI support for H2

* Enable delay test on h2

* Also enable example

* Changelog

* De-CAN the example
This commit is contained in:
Dániel Buga 2024-09-20 09:04:52 +02:00 committed by GitHub
parent 5de267ab09
commit d5afeeddc8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 71 additions and 41 deletions

View File

@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added APIs to allow connecting signals through the GPIO matrix. (#2128)
- Implement `TryFrom<u32>` for `ledc::timer::config::Duty` (#1984)
- Expose `RtcClock::get_xtal_freq` and `RtcClock::get_slow_freq` publically for all chips (#2183)
- TWAI support for ESP32-H2 (#2199)
### Changed

View File

@ -662,8 +662,8 @@ impl BaudRate {
/// Convert the BaudRate into the timings that the peripheral needs.
// See: https://github.com/espressif/esp-idf/tree/master/components/hal/include/hal/twai_types.h
const fn timing(self) -> TimingConfig {
#[allow(unused_mut)]
let mut timing = match self {
#[cfg(not(esp32h2))]
let timing = match self {
Self::B125K => TimingConfig {
baud_rate_prescaler: 32,
sync_jump_width: 3,
@ -695,11 +695,45 @@ impl BaudRate {
Self::Custom(timing_config) => timing_config,
};
#[cfg(esp32h2)]
let timing = match self {
Self::B125K => TimingConfig {
baud_rate_prescaler: 8,
sync_jump_width: 3,
tseg_1: 23,
tseg_2: 8,
triple_sample: false,
},
Self::B250K => TimingConfig {
baud_rate_prescaler: 8,
sync_jump_width: 3,
tseg_1: 11,
tseg_2: 4,
triple_sample: false,
},
Self::B500K => TimingConfig {
baud_rate_prescaler: 4,
sync_jump_width: 3,
tseg_1: 11,
tseg_2: 4,
triple_sample: false,
},
Self::B1000K => TimingConfig {
baud_rate_prescaler: 2,
sync_jump_width: 3,
tseg_1: 11,
tseg_2: 4,
triple_sample: false,
},
Self::Custom(timing_config) => timing_config,
};
// clock source on ESP32-C6 is xtal (40MHz)
#[cfg(esp32c6)]
{
// clock source on ESP32-C6 is xtal (40MHz)
timing.baud_rate_prescaler /= 2;
}
let timing = TimingConfig {
baud_rate_prescaler: timing.baud_rate_prescaler / 2,
..timing
};
timing
}
@ -802,7 +836,7 @@ where
fn set_baud_rate(&mut self, baud_rate: BaudRate) {
// TWAI is clocked from the APB_CLK according to Table 6-4 [ESP32C3 Reference Manual](https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf)
// Included timings are all for 80MHz so assert that we are running at 80MHz.
#[cfg(not(esp32c6))]
#[cfg(not(any(esp32h2, esp32c6)))]
{
let apb_clock = crate::clock::Clocks::get().apb_clock;
assert!(apb_clock == fugit::HertzU32::MHz(80));
@ -820,22 +854,17 @@ where
let tseg_2 = timing.tseg_2 - 1;
let triple_sample = timing.triple_sample;
#[cfg(esp32)]
let prescale = prescale as u8;
// Set up the prescaler and sync jump width.
T::register_block()
.bus_timing_0()
.modify(|_, w| unsafe { w.baud_presc().bits(prescale).sync_jump_width().bits(sjw) });
T::register_block().bus_timing_0().modify(|_, w| unsafe {
w.baud_presc().bits(prescale as _);
w.sync_jump_width().bits(sjw)
});
// Set up the time segment 1, time segment 2, and triple sample.
T::register_block().bus_timing_1().modify(|_, w| unsafe {
w.time_seg1()
.bits(tseg_1)
.time_seg2()
.bits(tseg_2)
.time_samp()
.bit(triple_sample)
w.time_seg1().bits(tseg_1);
w.time_seg2().bits(tseg_2);
w.time_samp().bit(triple_sample)
});
}
@ -1510,7 +1539,7 @@ impl Instance for crate::peripherals::TWAI0 {
#[cfg(any(esp32, esp32c3, esp32s2, esp32s3))]
impl OperationInstance for crate::peripherals::TWAI0 {}
#[cfg(esp32c6)]
#[cfg(any(esp32h2, esp32c6))]
impl Instance for crate::peripherals::TWAI0 {
const SYSTEM_PERIPHERAL: system::Peripheral = system::Peripheral::Twai0;
const NUMBER: usize = 0;
@ -1554,7 +1583,7 @@ impl Instance for crate::peripherals::TWAI0 {
}
}
#[cfg(esp32c6)]
#[cfg(any(esp32h2, esp32c6))]
impl OperationInstance for crate::peripherals::TWAI0 {}
#[cfg(esp32c6)]
@ -1641,7 +1670,7 @@ mod asynch {
}
}
const NUM_TWAI: usize = 2;
const NUM_TWAI: usize = 1 + cfg!(twai1) as usize;
#[allow(clippy::declare_interior_mutable_const)]
const NEW_STATE: TwaiAsyncState = TwaiAsyncState::new();
pub(crate) static TWAI_STATE: [TwaiAsyncState; NUM_TWAI] = [NEW_STATE; NUM_TWAI];
@ -1768,7 +1797,7 @@ mod asynch {
}
}
#[cfg(esp32c6)]
#[cfg(any(esp32h2, esp32c6))]
#[handler]
pub(super) fn twai0() {
let register_block = TWAI0::register_block();

View File

@ -54,7 +54,7 @@ peripherals = [
"timg0",
"timg1",
"trace0",
# "twai0",
"twai0",
"uart0",
"uart1",
"uhci0",

View File

@ -1,6 +1,6 @@
//! This example sends a CAN message to another ESP and receives it back.
//! This example sends a TWAI message to another ESP and receives it back.
//!
//! This example works without CAN Transceivers by:
//! This example works without TWAI transceivers by:
//! * setting the tx pins to open drain
//! * connecting all rx and tx pins together
//! * adding a pull-up to the signal pins
@ -17,7 +17,7 @@
//! In case you want to use `self-testing`, get rid of everything related to the aforementioned `IS_FIRST_SENDER`
//! and follow the advice in the comments related to this mode.
//% CHIPS: esp32c3 esp32c6 esp32s2 esp32s3
//% CHIPS: esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
#![no_std]
#![no_main]
@ -39,11 +39,11 @@ fn main() -> ! {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let can_tx_pin = io.pins.gpio0;
let can_rx_pin = io.pins.gpio2;
let tx_pin = io.pins.gpio0;
let rx_pin = io.pins.gpio2;
// The speed of the CAN bus.
const CAN_BAUDRATE: twai::BaudRate = twai::BaudRate::B1000K;
const TWAI_BAUDRATE: twai::BaudRate = twai::BaudRate::B1000K;
// !!! Use `new` when using a transceiver. `new_no_transceiver` sets TX to open-drain
// Self-testing also works using the regular `new` function.
@ -51,11 +51,11 @@ fn main() -> ! {
// Begin configuring the TWAI peripheral. The peripheral is in a reset like
// state that prevents transmission but allows configuration.
// For self-testing use `SelfTest` mode of the TWAI peripheral.
let mut can_config = twai::TwaiConfiguration::new_no_transceiver(
let mut twai_config = twai::TwaiConfiguration::new_no_transceiver(
peripherals.TWAI0,
can_rx_pin,
can_tx_pin,
CAN_BAUDRATE,
rx_pin,
tx_pin,
TWAI_BAUDRATE,
TwaiMode::Normal,
);
@ -67,12 +67,12 @@ fn main() -> ! {
// A filter that matches StandardId::ZERO.
const FILTER: SingleStandardFilter =
SingleStandardFilter::new(b"00000000000", b"x", [b"xxxxxxxx", b"xxxxxxxx"]);
can_config.set_filter(FILTER);
twai_config.set_filter(FILTER);
// Start the peripheral. This locks the configuration settings of the peripheral
// and puts it into operation mode, allowing packets to be sent and
// received.
let mut can = can_config.start();
let mut can = twai_config.start();
if IS_FIRST_SENDER {
// Send a frame to the other ESP

View File

@ -1,6 +1,6 @@
//! Delay Test
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32s2 esp32s3
//% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
#![no_std]
#![no_main]

View File

@ -1,6 +1,6 @@
//! TWAI test
//% CHIPS: esp32c3 esp32c6 esp32s2 esp32s3
//% CHIPS: esp32c3 esp32c6 esp32h2 esp32s2 esp32s3
#![no_std]
#![no_main]
@ -33,12 +33,12 @@ mod tests {
let io = Io::new(peripherals.GPIO, peripherals.IO_MUX);
let (can_tx_pin, can_rx_pin) = hil_test::common_test_pins!(io);
let (tx_pin, rx_pin) = hil_test::common_test_pins!(io);
let mut config = twai::TwaiConfiguration::new(
peripherals.TWAI0,
can_rx_pin,
can_tx_pin,
rx_pin,
tx_pin,
twai::BaudRate::B1000K,
TwaiMode::SelfTest,
);