Skip to content

Commit

Permalink
Bugfixing for esp32; bugfixing for Alexa scanning during commissioning
Browse files Browse the repository at this point in the history
  • Loading branch information
ivmarkov committed Jan 29, 2025
1 parent 70d1679 commit 2be6a04
Show file tree
Hide file tree
Showing 7 changed files with 279 additions and 159 deletions.
91 changes: 91 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Examples for Espressif MCUs

The examples are tested and _should_ work on the rPI Pico W, esp32, esp32s3, esp32c3 and esp32c6

With that said, it is still early days for both `rs-matter` and `trouble`
(the bare-metal BLE stack in use) so you might face issues during initial commissioning.

Please [report]() those!

## Matter Controller

You need one of:
* Google:
* Google Home/Nest or other Google Matter Controller
* The Google Home app on your phone
* Alexa
* Alexa Echo Hub, Echo Dot or other Amazon Matter Controller
* The Alexa app on your phone
* Apple
* Apple TV or other Apple Matter Controller
* An iPhone with the Apple HomeKit app

Once you build and flash the firmware, follow the instructions in the phone app.

To start the commissioning process, all apps will ask you to take a screenshot of the QR code which is printed by the firmware when it starts.
Once you do that, you should see a bunch of logs for the commissioning process.

NOTE: Since the firmware is not certified, the app will warn you about that. Disregard and let it proceed anyway.

Upon successful commissioning, you should end up with a Light device which you can turn on/off, and which will also turn on/off by itself every 5 secs.

## How to build and flash

### rPI Pico W

(Support for the stock rPI via the W5500 ethernet adapter coming later.)

```sh
cd rp
cargo +nightly build

probe-rs run --chip rp2040 target/thumbv6m-none-eabi/debug/light
```

### Espressif MCUs

#### esp32

```sh
cargo install espup
espup update

cd esp
cargo +esp build --target xtensa-esp32-none-elf --no-default-features --features esp32

espflash flash target/xtensa-esp32-none-elf/debug/light --baud 1500000
espflash monitor --elf target/xtensa-esp32-none-elf/debug/light
```

#### esp32s3

```sh
cargo install espup
espup update

cd esp
cargo +esp build --target xtensa-esp32s3-none-elf --no-default-features --features esp32s3

espflash flash target/xtensa-esp32s3-none-elf/debug/light --baud 1500000
espflash monitor --elf target/xtensa-esp32s3-none-elf/debug/light
```

#### esp32c3

```sh
cd esp
cargo +nightly build --target riscv32imc-unknown-none-elf --no-default-features --features esp32c3

espflash flash target/riscv32imc-unknown-none-elf/debug/light --baud 1500000
espflash monitor --elf target/riscv32imc-unknown-none-elf/debug/light
```

#### esp32c6

```sh
cd esp
cargo +nightly build --target riscv32imac-unknown-none-elf --no-default-features --features esp32c6

espflash flash target/riscv32imac-unknown-none-elf/debug/light --baud 1500000
espflash monitor --elf target/riscv32imac-unknown-none-elf/debug/light
```
21 changes: 2 additions & 19 deletions examples/esp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,37 +39,20 @@ portable-atomic = "1"

[features]
default = ["esp32c3"]

# trouble-example-apps/esp:
#
# 'esp-hal' likely has a bug, causing _some_ ESP32 chips to give "Invalid HCI Command Parameters" BLE errors at launch,
# if the L2CAP MTU is set low enough.
#
# The error producing ranges go:
# - ESP32-C6: x..<255 // examples with 128, 251 would fail
# - ESP32-C2: RANGE NOT KNOWN // not having the hardware
# - ESP32-H2: RANGE NOT KNOWN // not having the hardware
# - ESP32, -C3, -S2, -S3: claimed not to be affected [1], so the behaviour-altering feature is not enabled for them.
#
# [1]: https://github.com/embassy-rs/trouble/pull/236#issuecomment-2586457641
#
esp32 = ["esp-hal/esp32", "esp-backtrace/esp32", "esp-hal-embassy/esp32", "esp-println/esp32", "esp-wifi/esp32", "portable-atomic/critical-section"]
esp32c2 = ["esp-hal/esp32c2", "esp-backtrace/esp32c2", "esp-hal-embassy/esp32c2", "esp-println/esp32c2", "esp-wifi/esp32c2", "portable-atomic/critical-section"]
esp32c3 = ["esp-hal/esp32c3", "esp-backtrace/esp32c3", "esp-hal-embassy/esp32c3", "esp-println/esp32c3", "esp-wifi/esp32c3", "portable-atomic/unsafe-assume-single-core"]
esp32c6 = ["esp-hal/esp32c6", "esp-backtrace/esp32c6", "esp-hal-embassy/esp32c6", "esp-println/esp32c6", "esp-wifi/esp32c6", "portable-atomic/critical-section"]
esp32h2 = ["esp-hal/esp32h2", "esp-backtrace/esp32h2", "esp-hal-embassy/esp32h2", "esp-println/esp32h2", "esp-wifi/esp32h2", "portable-atomic/critical-section"]
esp32s3 = ["esp-hal/esp32s3", "esp-backtrace/esp32s3", "esp-hal-embassy/esp32s3", "esp-println/esp32s3", "esp-wifi/esp32s3", "portable-atomic/critical-section"]

[profile.dev]
# Rust debug is too slow.
# For debug builds always builds with some optimization
opt-level = "s"
opt-level = "z"

[profile.release]
codegen-units = 1 # LLVM can perform better optimizations using a single thread
debug = 2
debug-assertions = false
incremental = false
lto = 'thin'
opt-level = 3
opt-level = "s"
overflow-checks = false
62 changes: 43 additions & 19 deletions examples/esp/src/bin/light.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
#![no_std]
#![no_main]

use core::mem::MaybeUninit;
use core::pin::pin;

use alloc::boxed::Box;
use embassy_executor::Spawner;
use embassy_futures::select::select;
use embassy_time::{Duration, Timer};
Expand Down Expand Up @@ -41,27 +43,19 @@ use rs_matter_embassy::wireless::wifi::esp::EspWifiDriverProvider;
use rs_matter_embassy::wireless::wifi::{EmbassyWifi, EmbassyWifiMatterStack};
use rs_matter_embassy::wireless::EmbassyBle;

macro_rules! mk_static {
($t:ty) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit();
x
}};
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
extern crate alloc;

#[esp_hal_embassy::main]
async fn main(_s: Spawner) {
esp_println::logger::init_logger(log::LevelFilter::Info);

info!("Starting...");

// Heap strictly necessary only for Wifi and for the only Matter dependency which needs (~4KB) alloc - `x509`
// However since `esp32` specifically has a disjoint heap which causes bss size troubles, it is easier
// to allocate the statics once from heap as well
init_heap();

// == Step 1: ==
// Necessary `esp-hal` and `esp-wifi` initialization boilerplate

Expand All @@ -71,9 +65,6 @@ async fn main(_s: Spawner) {
config
});

// For Wifi and for the only Matter dependency which needs (~4KB) alloc - `x509`
esp_alloc::heap_allocator!(100 * 1024);

let timg0 = TimerGroup::new(peripherals.TIMG0);
let rng = esp_hal::rng::Rng::new(peripherals.RNG);

Expand All @@ -95,10 +86,10 @@ async fn main(_s: Spawner) {
}

// == Step 2: ==
// Statically allocate the Matter stack.
// Allocate the Matter stack.
// For MCUs, it is best to allocate it statically, so as to avoid program stack blowups (its memory footprint is ~ 35 to 50KB).
// It is also (currently) a mandatory requirement when the wireless stack variation is used.
let stack = &*mk_static!(EmbassyWifiMatterStack<()>).init_with(EmbassyWifiMatterStack::init(
let stack = &*Box::leak(Box::new_uninit()).init_with(EmbassyWifiMatterStack::<()>::init(
&BasicInfoConfig {
vid: TEST_VID,
pid: TEST_PID,
Expand Down Expand Up @@ -204,3 +195,36 @@ const NODE: Node = Node {
},
],
};

#[allow(static_mut_refs)]
fn init_heap() {
fn add_region<const N: usize>(region: &'static mut MaybeUninit<[u8; N]>) {
unsafe {
esp_alloc::HEAP.add_region(esp_alloc::HeapRegion::new(
region.as_mut_ptr() as *mut u8,
N,
esp_alloc::MemoryCapability::Internal.into(),
));
}
}

#[cfg(feature = "esp32")]
{
// The esp32 has two disjoint memory regions for heap
// Also, it has 64KB reserved for the BT stack in the first region, so we can't use that

static mut HEAP1: MaybeUninit<[u8; 30 * 1024]> = MaybeUninit::uninit();
#[link_section = ".dram2_uninit"]
static mut HEAP2: MaybeUninit<[u8; 96 * 1024]> = MaybeUninit::uninit();

add_region(unsafe { &mut HEAP1 });
add_region(unsafe { &mut HEAP2 });
}

#[cfg(not(feature = "esp32"))]
{
static mut HEAP: MaybeUninit<[u8; 186 * 1024]> = MaybeUninit::uninit();

add_region(unsafe { &mut HEAP });
}
}
Loading

0 comments on commit 2be6a04

Please sign in to comment.