Skip to content

Commit

Permalink
Update examples
Browse files Browse the repository at this point in the history
  • Loading branch information
ptpaterson committed Jan 6, 2024
1 parent 098ddce commit 3143b8c
Show file tree
Hide file tree
Showing 5 changed files with 248 additions and 61 deletions.
2 changes: 1 addition & 1 deletion esp32c3-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -147,4 +147,4 @@ required-features = ["direct-vectoring"]

[[example]]
name = "embassy_twai"
required-features = ["embassy", "async"]
required-features = ["embassy", "async", "embassy-executor-thread"]
49 changes: 40 additions & 9 deletions esp32c3-hal/examples/embassy_twai.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
// ! embassy twai
// !
// ! This is an example of running the embassy executor and asynchronously
// ! receiving and transmitting twai frames.
//! This example demonstrates use of the twai peripheral running the embassy
//! executor and asynchronously receiving and transmitting twai frames.
//!
//! The `receiver` task waits to receive a frame and puts it into a channel
//! which will be picked up by the `transmitter` task.
//!
//! The `transmitter` task waits for a channel to receive a frame and transmits
//! it.
//!
//! This example should work with another ESP board running the `twai` example
//! with `IS_SENDER` set to `true`.
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]

use embassy_executor::Spawner;
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, channel::Channel};
use embedded_can::{Frame, Id};
use esp32c3_hal::{
clock::ClockControl,
embassy,
Expand All @@ -19,24 +27,26 @@ use esp32c3_hal::{
IO,
};
use esp_backtrace as _;
use esp_println::println;
use static_cell::make_static;

type TwaiOutbox = Channel<NoopRawMutex, EspTwaiFrame, 16>;

#[embassy_executor::task]
async fn receiver(mut rx: TwaiRx<'static, TWAI0>, channel: &'static TwaiOutbox) -> ! {
loop {
// let frame = nb::block!(can.receive());
let frame = rx.receive_async().await;

match frame {
Ok(frame) => {
esp_println::println!("Received frame: {:?}", frame);
println!("Received a frame:");
print_frame(&frame);

// repeat the frame back
channel.send(frame).await;
}
Err(e) => {
esp_println::println!("Receive error: {:?}", e);
println!("Receive error: {:?}", e);
}
}
}
Expand All @@ -50,10 +60,11 @@ async fn transmitter(mut tx: TwaiTx<'static, TWAI0>, channel: &'static TwaiOutbo

match result {
Ok(()) => {
esp_println::println!("Transmitted frame: {:?}", frame);
println!("Transmitted a frame:");
print_frame(&frame);
}
Err(e) => {
esp_println::println!("Transmit error: {:?}", e);
println!("Transmit error: {:?}", e);
}
}
}
Expand Down Expand Up @@ -126,3 +137,23 @@ async fn main(spawner: Spawner) {
spawner.spawn(receiver(rx, channel)).ok();
spawner.spawn(transmitter(tx, channel)).ok();
}

fn print_frame(frame: &EspTwaiFrame) {
// Print different messages based on the frame id type.
match frame.id() {
Id::Standard(id) => {
println!("\tStandard Id: {:?}", id);
}
Id::Extended(id) => {
println!("\tExtended Id: {:?}", id);
}
}

// Print out the frame data or the requested data length code for a remote
// transmission request frame.
if frame.is_data_frame() {
println!("\tData: {:?}", frame.data());
} else {
println!("\tRemote Frame. Data Length Code: {}", frame.dlc());
}
}
104 changes: 82 additions & 22 deletions esp32c3-hal/examples/twai.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
//! This example demonstrates the use of the twai peripheral to send and receive
//! frames. When `IS_SENDER` is set to `true`, the node will send a frame
//! every `DELAY_MS` interval. When `IS_SENDER` is set to `false`, the node will
//! wait to receive a frame and repeat it back.
//!
//! When running this example on two ESP boards, `IS_SENDER` must be set to
//! `true` for at least one node. It is okay to have multiple senders.
#![no_std]
#![no_main]

const IS_SENDER: bool = true;
const DELAY_MS: u32 = 1000;

// Run this example with the eh1 feature enabled to use embedded-can instead of
// embedded-hal-0.2.7. embedded-can was split off from embedded-hal before it's
// upgrade to 1.0.0. cargo run --example twai --features eh1 --release
Expand All @@ -9,8 +20,15 @@ use embedded_can::{Frame, Id};
// Run this example without the eh1 flag to use the embedded-hal 0.2.7 CAN traits.
// cargo run --example twai --release
#[cfg(not(feature = "eh1"))]
use embedded_hal::can::{Frame, Id};
use esp32c3_hal::{clock::ClockControl, gpio::IO, peripherals::Peripherals, prelude::*, twai};
use embedded_hal::can::{Frame, Id, StandardId};
use esp32c3_hal::{
clock::ClockControl,
gpio::IO,
peripherals::Peripherals,
prelude::*,
twai::{self, EspTwaiError, EspTwaiFrame},
Delay,
};
use esp_backtrace as _;
use esp_println::println;
use nb::block;
Expand All @@ -23,6 +41,8 @@ fn main() -> ! {

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

let mut delay = Delay::new(&clocks);

// Use GPIO pins 2 and 3 to connect to the respective pins on the CAN
// transceiver.
let can_tx_pin = io.pins.gpio2;
Expand All @@ -45,42 +65,82 @@ fn main() -> ! {
// undesired messages. Note that due to how the hardware filters messages,
// standard ids and extended ids may both match a filter. Frame ids should
// be explicitly checked in the application instead of fully relying on
// these partial acceptance filters to exactly match. A filter that matches
// standard ids of an even value.
// these partial acceptance filters to exactly match.
// A filter that matches StandardId::ZERO.
const FILTER: twai::filter::SingleStandardFilter =
twai::filter::SingleStandardFilter::new(b"xxxxxxxxxx0", b"x", [b"xxxxxxxx", b"xxxxxxxx"]);
twai::filter::SingleStandardFilter::new(b"00000000000", b"x", [b"xxxxxxxx", b"xxxxxxxx"]);
can_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 counter: u32 = 0;

loop {
// Wait for a frame to be received.
let frame = block!(can.receive()).unwrap();
if IS_SENDER {
// If this is the sender-node, then send a frame every DELAY_MS inteval.

println!("Received a frame:");
// Send a frame to the other ESP
let frame = Frame::new(StandardId::ZERO, &counter.to_be_bytes()).unwrap();

// Print different messages based on the frame id type.
match frame.id() {
Id::Standard(id) => {
println!("\tStandard Id: {:?}", id);
// Check for BusOff error, and restart the peripheral if it occurs.
let transmit_result = block!(can.transmit(&frame));
if let Err(EspTwaiError::BusOff) = transmit_result {
println!("Transmit Error: BusOff. restarting...");
let config = can.stop();
can = config.start();
continue;
}
Id::Extended(id) => {
println!("\tExtended Id: {:?}", id);

println!("Transmitted a frame.");
print_frame(&frame);
counter += 1;

// Check for received frame, but do not block.
let receive_result = can.receive();
if let Ok(f) = receive_result {
println!("Received a frame:");
print_frame(&f);
}
}

// Print out the frame data or the requested data length code for a remote
// transmission request frame.
if frame.is_data_frame() {
println!("\tData: {:?}", frame.data());
delay.delay_ms(DELAY_MS);
} else {
println!("\tRemote Frame. Data Length Code: {}", frame.dlc());
// If this is the receiver-node, then wait for a frame to be received, then send
// it back

// Wait for a frame to be received.
let frame = block!(can.receive()).unwrap();

println!("Received a frame:");
print_frame(&frame);

// Transmit the frame back.
// We just received a frame, so chances of BusOff are low.
block!(can.transmit(&frame)).unwrap();

println!("Transmitted the frame back.");
}
}
}

fn print_frame(frame: &EspTwaiFrame) {
// Print different messages based on the frame id type.
match frame.id() {
Id::Standard(id) => {
println!("\tStandard Id: {:?}", id);
}
Id::Extended(id) => {
println!("\tExtended Id: {:?}", id);
}
}

// Transmit the frame back.
let _result = block!(can.transmit(&frame)).unwrap();
// Print out the frame data or the requested data length code for a remote
// transmission request frame.
if frame.is_data_frame() {
println!("\tData: {:?}", frame.data());
} else {
println!("\tRemote Frame. Data Length Code: {}", frame.dlc());
}
}
48 changes: 40 additions & 8 deletions esp32s3-hal/examples/embassy_twai.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
// ! embassy twai
// !
// ! This is an example of running the embassy executor and asynchronously
// ! receiving and transmitting twai frames.
//! This example demonstrates use of the twai peripheral running the embassy
//! executor and asynchronously receiving and transmitting twai frames.
//!
//! The `receiver` task waits to receive a frame and puts it into a channel
//! which will be picked up by the `transmitter` task.
//!
//! The `transmitter` task waits for a channel to receive a frame and transmits
//! it.
//!
//! This example should work with another ESP board running the `twai` example
//! with `IS_SENDER` set to `true`.
#![no_std]
#![no_main]
#![feature(type_alias_impl_trait)]

use embassy_executor::Spawner;
use embassy_sync::{blocking_mutex::raw::NoopRawMutex, channel::Channel};
use embedded_can::{Frame, Id};
use esp32s3_hal::{
clock::ClockControl,
embassy,
Expand All @@ -19,6 +27,7 @@ use esp32s3_hal::{
IO,
};
use esp_backtrace as _;
use esp_println::println;
use static_cell::make_static;

type TwaiOutbox = Channel<NoopRawMutex, EspTwaiFrame, 16>;
Expand All @@ -30,12 +39,14 @@ async fn receiver(mut rx: TwaiRx<'static, TWAI0>, channel: &'static TwaiOutbox)

match frame {
Ok(frame) => {
esp_println::println!("Received frame: {:?}", frame);
println!("Received a frame:");
print_frame(&frame);

// repeat the frame back
channel.send(frame).await;
}
Err(e) => {
esp_println::println!("Receive error: {:?}", e);
println!("Receive error: {:?}", e);
}
}
}
Expand All @@ -49,10 +60,11 @@ async fn transmitter(mut tx: TwaiTx<'static, TWAI0>, channel: &'static TwaiOutbo

match result {
Ok(()) => {
esp_println::println!("Transmitted frame: {:?}", frame);
println!("Transmitted a frame:");
print_frame(&frame);
}
Err(e) => {
esp_println::println!("Transmit error: {:?}", e);
println!("Transmit error: {:?}", e);
}
}
}
Expand Down Expand Up @@ -125,3 +137,23 @@ async fn main(spawner: Spawner) {
spawner.spawn(receiver(rx, channel)).ok();
spawner.spawn(transmitter(tx, channel)).ok();
}

fn print_frame(frame: &EspTwaiFrame) {
// Print different messages based on the frame id type.
match frame.id() {
Id::Standard(id) => {
println!("\tStandard Id: {:?}", id);
}
Id::Extended(id) => {
println!("\tExtended Id: {:?}", id);
}
}

// Print out the frame data or the requested data length code for a remote
// transmission request frame.
if frame.is_data_frame() {
println!("\tData: {:?}", frame.data());
} else {
println!("\tRemote Frame. Data Length Code: {}", frame.dlc());
}
}
Loading

0 comments on commit 3143b8c

Please sign in to comment.