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

Add the esp-ieee802154 package to the repository #1554

Merged
merged 2 commits into from
May 15, 2024
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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ exclude = [
"esp-hal",
"esp-hal-procmacros",
"esp-hal-smartled",
"esp-ieee802154",
"esp-lp-hal",
"esp-metadata",
"esp-riscv-rt",
Expand Down
31 changes: 31 additions & 0 deletions esp-ieee802154/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[package]
name = "esp-ieee802154"
version = "0.1.0"
edition = "2021"
rust-version = "1.76.0"
description = "Low-level IEEE 802.15.4 driver for the ESP32-C6 and ESP32-H2"
repository = "https://github.com/esp-rs/esp-hal"
license = "MIT OR Apache-2.0"

[package.metadata.docs.rs]
default-target = "riscv32imac-unknown-none-elf"
features = ["esp32c6"]

[lib]
bench = false
test = false

[dependencies]
byte = "0.2.7"
critical-section = "1.1.2"
esp-hal = { version = "0.17.0", path = "../esp-hal" }
esp-wifi-sys = { git = "https://github.com/esp-rs/esp-wifi", rev = "2ceb4b3" }
heapless = "0.8.0"
ieee802154 = "0.6.1"
log = "0.4.21"
vcell = "0.1.3"

[features]
default = []
esp32c6 = ["esp-hal/esp32c6", "esp-wifi-sys/esp32c6"]
esp32h2 = ["esp-hal/esp32h2", "esp-wifi-sys/esp32h2"]
35 changes: 35 additions & 0 deletions esp-ieee802154/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# esp-ieee802154

[![Crates.io](https://img.shields.io/crates/v/esp-ieee802154?color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-ieee802154)
[![docs.rs](https://img.shields.io/docsrs/esp-ieee802154?color=C96329&logo=rust&style=flat-square)](https://docs.rs/esp-ieee802154)
![MSRV](https://img.shields.io/badge/MSRV-1.76-blue?labelColor=1C2C2E&style=flat-square)
![Crates.io](https://img.shields.io/crates/l/esp-ieee802154?style=flat-square)
[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&labelColor=1C2C2E&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org)

Low-level [IEEE 802.15.4] driver for the ESP32-C6 and ESP32-H2.

Implements the PHY/MAC layers of the IEEE802.15.4 protocol stack, and supports sending and receiving of raw frames.

[IEEE 802.15.4]: https://en.wikipedia.org/wiki/IEEE_802.15.4

## [Documentation](https://docs.rs/crate/esp-ieee802154)

## Minimum Supported Rust Version (MSRV)

This crate is guaranteed to compile on stable Rust 1.76 and up. It _might_
compile with older versions but that may change in any new patch release.

## License

Licensed under either of:

- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT)

at your option.

### Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in
the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without
any additional terms or conditions.
6 changes: 6 additions & 0 deletions esp-ieee802154/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
use std::{env, path::PathBuf};

fn main() {
let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
println!("cargo:rustc-link-search={}", out.display());
}
130 changes: 130 additions & 0 deletions esp-ieee802154/src/compat/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
use core::{ffi::VaListImpl, fmt::Write};

use log::info;

use self::str_buf::StrBuf;

mod str_buf;

#[no_mangle]
pub unsafe extern "C" fn phy_printf(format: *const u8, args: ...) {
syslog(format, args);
}

#[no_mangle]
pub unsafe extern "C" fn rtc_printf(format: *const u8, args: ...) {
syslog(format, args);
}

#[no_mangle]
pub unsafe extern "C" fn coexist_printf(format: *const u8, args: ...) {
syslog(format, args);
}

pub unsafe extern "C" fn syslog(format: *const u8, args: VaListImpl) {
let mut buf = [0u8; 512];
vsnprintf(&mut buf as *mut u8, 511, format, args);
let res_str = StrBuf::from(&buf as *const u8);
info!("{}", res_str.as_str_ref());
}

pub(crate) unsafe fn vsnprintf(
MabezDev marked this conversation as resolved.
Show resolved Hide resolved
dst: *mut u8,
_n: u32,
format: *const u8,
mut args: VaListImpl,
) -> i32 {
let fmt_str_ptr = format;

let mut res_str = StrBuf::new();

let strbuf = StrBuf::from(fmt_str_ptr);
let s = strbuf.as_str_ref();

let mut format_char = ' ';
let mut is_long = false;
let mut found = false;
for c in s.chars() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this ascii or utf-8? If ascii then better to use bytes instead of chars.

if !found {
if c == '%' {
found = true;
}

if !found {
res_str.append_char(c);
}
} else if c.is_numeric() || c == '-' || c == 'l' {
if c == 'l' {
is_long = true;
}
// ignore
} else {
// a format char
format_char = c;
}

if found && format_char != ' ' {
// have to format an arg
match format_char {
'd' => {
if is_long {
let v = args.arg::<i64>();
write!(res_str, "{}", v).ok();
} else {
let v = args.arg::<i32>();
write!(res_str, "{}", v).ok();
}
}

'u' => {
let v = args.arg::<u32>();
write!(res_str, "{}", v).ok();
}

'p' => {
let v = args.arg::<u32>();
write!(res_str, "0x{:x}", v).ok();
}

'X' => {
let v = args.arg::<u32>();
write!(res_str, "{:02x}", (v & 0xff000000) >> 24).ok();
}

'x' => {
let v = args.arg::<u32>();
write!(res_str, "{:02x}", v).ok();
}

's' => {
let v = args.arg::<u32>() as *const u8;
let vbuf = StrBuf::from(v);
write!(res_str, "{}", vbuf.as_str_ref()).ok();
}

'c' => {
let v = args.arg::<u8>();
if v != 0 {
write!(res_str, "{}", v as char).ok();
}
}

_ => {
write!(res_str, "<UNKNOWN{}>", format_char).ok();
}
}

format_char = ' ';
found = false;
is_long = false;
}
}
let mut idx = 0;
res_str.as_str_ref().chars().for_each(|c| {
*(dst.offset(idx)) = c as u8;
idx += 1;
});
*(dst.offset(idx)) = 0;

idx as i32
}
58 changes: 58 additions & 0 deletions esp-ieee802154/src/compat/str_buf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
use core::fmt::Write;

pub struct StrBuf {
buffer: [u8; 512],
len: usize,
}

impl StrBuf {
pub fn new() -> StrBuf {
StrBuf {
buffer: [0u8; 512],
len: 0,
}
}

pub unsafe fn from(c_str: *const u8) -> StrBuf {
let mut res = StrBuf {
buffer: [0u8; 512],
len: 0,
};

let mut idx: usize = 0;
while *(c_str.add(idx)) != 0 {
res.buffer[idx] = *(c_str.add(idx));
idx += 1;
}

res.len = idx;
res
}

pub fn append(&mut self, s: &str) {
let mut idx: usize = self.len;
s.chars().for_each(|c| {
self.buffer[idx] = c as u8;
idx += 1;
});
self.len = idx;
}

pub fn append_char(&mut self, c: char) {
let mut idx: usize = self.len;
self.buffer[idx] = c as u8;
idx += 1;
self.len = idx;
}

pub unsafe fn as_str_ref(&self) -> &str {
core::str::from_utf8_unchecked(&self.buffer[..self.len])
}
}

impl Write for StrBuf {
fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
self.append(s);
Ok(())
}
}
45 changes: 45 additions & 0 deletions esp-ieee802154/src/frame.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use heapless::Vec;
use ieee802154::mac::{FrameContent, Header};

pub(crate) const FRAME_SIZE: usize = 129;
pub(crate) const FRAME_VERSION_1: u8 = 0x10; // IEEE 802.15.4 - 2006 & 2011
pub(crate) const FRAME_VERSION_2: u8 = 0x20; // IEEE 802.15.4 - 2015

const FRAME_AR_OFFSET: usize = 1;
const FRAME_AR_BIT: u8 = 0x20;
const FRAME_VERSION_OFFSET: usize = 2;
const FRAME_VERSION_MASK: u8 = 0x30;

/// IEEE 802.15.4 MAC frame
#[derive(Debug, Clone)]
pub struct Frame {
/// Header
pub header: Header,
/// Content
pub content: FrameContent,
/// Payload
pub payload: Vec<u8, FRAME_SIZE>,
/// This is a 2-byte CRC checksum
pub footer: [u8; 2],
}

/// IEEE 802.15.4 MAC frame which has been received
#[derive(Debug, Clone)]
pub struct ReceivedFrame {
/// Frame
pub frame: Frame,
/// Receiver channel
pub channel: u8,
/// Received Signal Strength Indicator (RSSI)
pub rssi: i8,
/// Link Quality Indication (LQI)
pub lqi: u8,
}

pub(crate) fn frame_is_ack_required(frame: &[u8]) -> bool {
(frame[FRAME_AR_OFFSET] & FRAME_AR_BIT) != 0
}

pub(crate) fn frame_get_version(frame: &[u8]) -> u8 {
frame[FRAME_VERSION_OFFSET] & FRAME_VERSION_MASK
}
Loading
Loading