Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f15621244b | ||
|
|
d19e5aef54 | ||
|
|
27c0aa471f | ||
|
|
d8dbf520fb | ||
|
|
4e36d3b3b9 | ||
|
|
d255c4c4af | ||
|
|
559d00703d | ||
|
|
14823d669f | ||
|
|
9570a660a1 | ||
|
|
89c6f37c3f | ||
|
|
9f7565440a | ||
|
|
226bdc3038 | ||
|
|
d95be13c4d | ||
|
|
28fafa05e1 | ||
|
|
b5fe37e6e7 | ||
|
|
61b57e722e | ||
|
|
510dba03b4 | ||
|
|
0b26d3851c | ||
|
|
a72d292a74 | ||
|
|
c38ed67fb0 | ||
|
|
14f46371eb | ||
|
|
0c1d59b553 | ||
|
|
a4bc624e2d | ||
|
|
1cfc3eccb5 | ||
|
|
b51a5ed1fa | ||
|
|
8a958e92bc | ||
|
|
c0ef68115f | ||
|
|
978ae3c451 |
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -313,6 +313,8 @@ jobs:
|
||||
run: cd esp32s3-hal/ && cargo check --example=embassy_serial --features=embassy,embassy-time-timg0,async
|
||||
- name: check esp32s3-hal (async, i2c)
|
||||
run: cd esp32s3-hal/ && cargo check --example=embassy_i2c --features=embassy,embassy-time-timg0,async
|
||||
- name: check esp32s3-hal (octal psram)
|
||||
run: cd esp32s3-hal/ && cargo check --example=octal_psram --features=opsram_2m --release # This example requires release!
|
||||
|
||||
esp-riscv-rt:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
16
.github/workflows/issue_handler.yml
vendored
Normal file
16
.github/workflows/issue_handler.yml
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
name: Add new issues to project
|
||||
|
||||
on:
|
||||
issues:
|
||||
types:
|
||||
- opened
|
||||
|
||||
jobs:
|
||||
add-to-project:
|
||||
name: Add issue to project
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/add-to-project@v0.5.0
|
||||
with:
|
||||
project-url: https://github.com/orgs/esp-rs/projects/2
|
||||
github-token: ${{ secrets.PAT }}
|
||||
57
CHANGELOG.md
57
CHANGELOG.md
@ -11,48 +11,41 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
### Added
|
||||
|
||||
- Add `WithDmaSpi3` to prelude for ESP32S3 (#623)
|
||||
- Add bare-bones PSRAM support for ESP32 (#506)
|
||||
- Add initial support for the ESP32-H2 (#513)
|
||||
- Add initial support for the ESP32-H2 (#513, #526, #527, #528, #530, #538, #544, #548, #551, #556, #560, #566, #549, #564, #569, #576, #577, #589, #591, #597)
|
||||
- Add bare-bones PSRAM support for ESP32-S3 (#517)
|
||||
- Add async support to the I2C driver (#519)
|
||||
- Add initial support for RSA in ESP32-H2 (#526)
|
||||
- Add initial support for SHA in ESP32-H2 (#527)
|
||||
- Add initial support for AES in ESP32-H2 (#528)
|
||||
- Add blinky_erased_pins example for ESP32-H2 (#530)
|
||||
- Add initial support for I2C in ESP32-H2 (#538)
|
||||
- Implement Copy and Eq for EspTwaiError (#540)
|
||||
- Add LEDC hardware fade support
|
||||
- Add LEDC hardware fade support (#475)
|
||||
- Added support for multicore async GPIO (#542)
|
||||
- Add initial support for MCPWM in ESP32-H2 (#544)
|
||||
- Add some miscellaneous examples for the ESP32-H2 (#548)
|
||||
- Add initial support for PCNT in ESP32-H2 (#551)
|
||||
- Add initial support for RMT in ESP32-H2 (#556)
|
||||
- Add a fn to poll DMA transfers
|
||||
- Add initial support for LEDC in ESP32-H2 (#560)
|
||||
- Add initial support for ASSIST_DEBUG in ESP32-H2 (#566)
|
||||
- Add all `SPI` examples for the ESP32-H2 (#549)
|
||||
- Add initial support for ADC in ESP32-H2 (#564)
|
||||
- Add a fn to poll DMA transfers (#559)
|
||||
- Simplify the `Delay` driver, derive `Clone` and `Copy` (#568)
|
||||
- Add `embassy_serial` and `embassy_wait` examples for ESP32-H2 (#569)
|
||||
- Fix Async GPIO not disabling interupts on chips with multiple banks (#572)
|
||||
- Add unified field-based efuse access
|
||||
- Add `timer_interrupt` example in ESP32-H2 and refactor `clk_src` configuration (#576)
|
||||
- Add unified field-based efuse access (#567)
|
||||
- Move `esp-riscv-rt` into esp-hal (#578)
|
||||
- Add initial implementation of radio clocks for ESP32-H2 (#577)
|
||||
- Add initial support for `esp-hal-smartled` in ESP32-H2 (#589)
|
||||
- Add CRC functions from ESP ROM
|
||||
- Add initial support for RNG in ESP32-H2 (#591)
|
||||
- Add CRC functions from ESP ROM (#587)
|
||||
- Add a `debug` feature to enable the PACs' `impl-register-debug` feature (#596)
|
||||
- Add initial support for `I2S` in ESP32-H2 (#597)
|
||||
- Fix rom::crc docs
|
||||
- Add octal PSRAM support for ESP32-S3 (#610)
|
||||
- Add MD5 functions from ESP ROM (#618)
|
||||
- Add embassy async `read` support for `uart` (#620)
|
||||
|
||||
### Changed
|
||||
|
||||
- DMA types can no longer be constructed by the user (#625)
|
||||
- Move core interrupt handling from Flash to RAM for RISC-V chips (ESP32-H2, ESP32-C2, ESP32-C3, ESP32-C6) (#541)
|
||||
- Change LED pin to GPIO2 in ESP32 blinky example (#581)
|
||||
- Udpate ESP32-H2 and C6 ESP32-clocks and remove i2c_clock for all chips but ESP32 (#592)
|
||||
- Update ESP32-H2 and ESP32-C6 clocks and remove `i2c_clock` for all chips but ESP32 (#592)
|
||||
- Use both timers in `TIMG0` for embassy time driver when able (#609)
|
||||
- Re-work `RadioExt` implementations, add support for ESP32-H2 (#627)
|
||||
- Improve examples documentation (#533)
|
||||
- esp32h2-hal: added README (#585)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Corrected the expected DMA descriptor counts (#622, #625)
|
||||
- DMA is supported for SPI3 on ESP32-S3 (#507)
|
||||
- `change_bus_frequency` is now available on `SpiDma` (#529)
|
||||
- Fixed a bug where a GPIO interrupt could erroneously fire again causing the next `await` on that pin to instantly return `Poll::Ok` (#537)
|
||||
@ -61,18 +54,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- ADC driver will now apply attenuation values to the correct ADC's channels. (#554)
|
||||
- Sometimes half-duplex non-DMA SPI reads were reading garbage in non-release mode (#552)
|
||||
- ESP32-C3: Fix GPIO5 ADC channel id (#562)
|
||||
- ESP32-H2: Fix direct-boot feature
|
||||
- ESP32-C6: Support FOSC CLK calibration for ECO1+ chip revisions
|
||||
- ESP32-H2: Fix direct-boot feature (#570)
|
||||
- ESP32-C6: Support FOSC CLK calibration for ECO1+ chip revisions (#593)
|
||||
- Fixed CI by pinning the log crate to 0.4.18 (#600)
|
||||
|
||||
### Changed
|
||||
|
||||
- Improve examples documentation (#533)
|
||||
- esp32h2-hal: added README (#585)
|
||||
- ESP32-S3: Fix calculation of PSRAM start address
|
||||
- Fixed wrong variable access (FOSC CLK calibration for ESP32-C6 #593)
|
||||
- Fixed [trap location in ram](https://github.com/esp-rs/esp-hal/pull/605#issuecomment-1604039683) (#605)
|
||||
- Fixed a possible overlap of `.data` and `.rwtext` (#616)
|
||||
- Avoid SDA/SCL being low while configuring pins for I2C
|
||||
|
||||
### Breaking
|
||||
|
||||
- Simplified user-facing SpiDma and I2s types (#626)
|
||||
- Significantly simplified user-facing GPIO pin types. (#553)
|
||||
- No longer re-export the `soc` module and the contents of the `interrupt` module at the package level (#607)
|
||||
|
||||
## [0.9.0] - 2023-05-02
|
||||
|
||||
|
||||
@ -43,7 +43,7 @@ riscv-atomic-emulation-trap = { version = "0.4.0", optional = true }
|
||||
|
||||
# Xtensa
|
||||
xtensa-lx = { version = "0.8.0", optional = true }
|
||||
xtensa-lx-rt = { version = "0.15.0", optional = true }
|
||||
xtensa-lx-rt = { version = "0.15.0", optional = true, path = "/home/mabez/development/rust/embedded/projects/xtensa-lx-rt" }
|
||||
|
||||
# Part of `ufmt` containing only `uWrite` trait
|
||||
ufmt-write = { version = "0.1.0", optional = true }
|
||||
@ -82,6 +82,10 @@ psram_2m = []
|
||||
psram_4m = []
|
||||
psram_8m = []
|
||||
|
||||
opsram_2m = []
|
||||
opsram_4m = []
|
||||
opsram_8m = []
|
||||
|
||||
# Implement the `embedded-hal==1.0.0-alpha.x` traits
|
||||
eh1 = ["embedded-hal-1", "embedded-hal-nb", "embedded-can"]
|
||||
|
||||
|
||||
@ -1,4 +1,8 @@
|
||||
use std::{env, fs, path::PathBuf};
|
||||
use std::{
|
||||
env,
|
||||
fs,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use serde::Deserialize;
|
||||
|
||||
@ -144,13 +148,20 @@ fn main() {
|
||||
println!("cargo:rustc-cfg={peripheral}");
|
||||
}
|
||||
|
||||
// check PSRAM features are only given if the target supports PSRAM
|
||||
// Check PSRAM features are only given if the target supports PSRAM
|
||||
if !&device.peripherals.contains(&String::from("psram"))
|
||||
&& (cfg!(feature = "psram_2m") || cfg!(feature = "psram_4m") || cfg!(feature = "psram_8m"))
|
||||
{
|
||||
panic!("The target does not support PSRAM");
|
||||
}
|
||||
|
||||
// If the `embassy` feature is enabled, ensure that a time driver implementation
|
||||
// is available
|
||||
#[cfg(feature = "embassy")]
|
||||
{
|
||||
assert_unique_used_features!("embassy-time-systick", "embassy-time-timg0");
|
||||
}
|
||||
|
||||
// Place all linker scripts in `OUT_DIR`, and instruct Cargo how to find these
|
||||
// files:
|
||||
let out = PathBuf::from(env::var_os("OUT_DIR").unwrap());
|
||||
@ -169,10 +180,7 @@ fn main() {
|
||||
gen_efuse_table(device_name, out);
|
||||
}
|
||||
|
||||
fn copy_dir_all(
|
||||
src: impl AsRef<std::path::Path>,
|
||||
dst: impl AsRef<std::path::Path>,
|
||||
) -> std::io::Result<()> {
|
||||
fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> std::io::Result<()> {
|
||||
fs::create_dir_all(&dst)?;
|
||||
for entry in fs::read_dir(src)? {
|
||||
let entry = entry?;
|
||||
@ -186,10 +194,10 @@ fn copy_dir_all(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn gen_efuse_table(device_name: &str, out_dir: impl AsRef<std::path::Path>) {
|
||||
fn gen_efuse_table(device_name: &str, out_dir: impl AsRef<Path>) {
|
||||
use std::io::{BufRead, Write};
|
||||
|
||||
let src_path = std::path::PathBuf::from(format!("src/soc/{device_name}/efuse.csv"));
|
||||
let src_path = PathBuf::from(format!("src/soc/{device_name}/efuse.csv"));
|
||||
let out_path = out_dir.as_ref().join("efuse_fields.rs");
|
||||
|
||||
println!("cargo:rerun-if-changed={}", src_path.display());
|
||||
|
||||
@ -61,6 +61,7 @@ peripherals = [
|
||||
# ROM capabilities
|
||||
"rom_crc_le",
|
||||
"rom_crc_be",
|
||||
"rom_md5_bsd",
|
||||
|
||||
# Wakeup SOC based on ESP-IDF:
|
||||
"pm_support_ext0_wakeup",
|
||||
|
||||
@ -42,6 +42,7 @@ peripherals = [
|
||||
# ROM capabilities
|
||||
"rom_crc_le",
|
||||
"rom_crc_be",
|
||||
"rom_md5_mbedtls",
|
||||
|
||||
# Wakeup SOC based on ESP-IDF:
|
||||
"pm_support_wifi_wakeup",
|
||||
|
||||
@ -54,6 +54,7 @@ peripherals = [
|
||||
# ROM capabilities
|
||||
"rom_crc_le",
|
||||
"rom_crc_be",
|
||||
"rom_md5_bsd",
|
||||
|
||||
# Wakeup SOC based on ESP-IDF:
|
||||
"pm_support_wifi_wakeup",
|
||||
|
||||
@ -83,6 +83,7 @@ peripherals = [
|
||||
# ROM capabilities
|
||||
"rom_crc_le",
|
||||
"rom_crc_be",
|
||||
"rom_md5_bsd",
|
||||
|
||||
# Wakeup SOC based on ESP-IDF:
|
||||
"pm_support_wifi_wakeup",
|
||||
|
||||
@ -8,13 +8,13 @@ peripherals = [
|
||||
"apb_saradc",
|
||||
"assist_debug",
|
||||
"dma",
|
||||
# "ds",
|
||||
# "ecc",
|
||||
"ds",
|
||||
"ecc",
|
||||
"efuse",
|
||||
"gpio",
|
||||
# "hmac",
|
||||
# "hp_apm",
|
||||
# "hp_sys",
|
||||
"hmac",
|
||||
"hp_apm",
|
||||
"hp_sys",
|
||||
"i2c0",
|
||||
"i2c1",
|
||||
"i2s0",
|
||||
@ -22,20 +22,20 @@ peripherals = [
|
||||
"intpri",
|
||||
"io_mux",
|
||||
"ledc",
|
||||
# "lp_ana",
|
||||
# "lp_aon",
|
||||
# "lp_apm",
|
||||
"lp_ana",
|
||||
"lp_aon",
|
||||
"lp_apm",
|
||||
"lp_clkrst",
|
||||
# "lp_peri",
|
||||
# "lp_timer",
|
||||
"lp_peri",
|
||||
"lp_timer",
|
||||
"lp_wdt",
|
||||
"mcpwm0",
|
||||
"mem_monitor",
|
||||
"modem_lpcon",
|
||||
"modem_syscon",
|
||||
# "otp_debug",
|
||||
# "parl_io",
|
||||
# "pau",
|
||||
"otp_debug",
|
||||
"parl_io",
|
||||
"pau",
|
||||
"pcnt",
|
||||
"pcr",
|
||||
"pmu",
|
||||
@ -43,19 +43,19 @@ peripherals = [
|
||||
"rng",
|
||||
"rsa",
|
||||
"sha",
|
||||
# "soc_etm",
|
||||
"soc_etm",
|
||||
"spi0",
|
||||
"spi1",
|
||||
"spi2",
|
||||
"systimer",
|
||||
# "tee",
|
||||
"tee",
|
||||
"timg0",
|
||||
"timg1",
|
||||
# "trace",
|
||||
"trace",
|
||||
# "twai0",
|
||||
"uart0",
|
||||
"uart1",
|
||||
# "uhci0",
|
||||
"uhci0",
|
||||
"usb_device",
|
||||
|
||||
# Additional peripherals defined by us (the developers):
|
||||
@ -72,4 +72,5 @@ peripherals = [
|
||||
# ROM capabilities
|
||||
"rom_crc_le",
|
||||
"rom_crc_be",
|
||||
"rom_md5_bsd",
|
||||
]
|
||||
|
||||
@ -57,6 +57,7 @@ peripherals = [
|
||||
|
||||
# ROM capabilities
|
||||
"rom_crc_le",
|
||||
"rom_md5_bsd",
|
||||
|
||||
# Wakeup SOC based on ESP-IDF:
|
||||
"pm_support_ext0_wakeup",
|
||||
|
||||
@ -70,6 +70,7 @@ peripherals = [
|
||||
# ROM capabilities
|
||||
"rom_crc_le",
|
||||
"rom_crc_be",
|
||||
"rom_md5_bsd",
|
||||
|
||||
# Wakeup SOC based on ESP-IDF:
|
||||
"pm_support_ext0_wakeup",
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
|
||||
SECTIONS {
|
||||
.rodata_dummy (NOLOAD) :
|
||||
.rodata_dummy (NOLOAD) : ALIGN(4)
|
||||
{
|
||||
/* This dummy section represents the .flash.text section but in RODATA.
|
||||
* Thus, it must have its alignment and (at least) its size.
|
||||
@ -14,7 +14,7 @@ SECTIONS {
|
||||
|
||||
/* Create an empty gap as big as .text section */
|
||||
|
||||
. = SIZEOF(.text);
|
||||
. = . + SIZEOF(.text);
|
||||
|
||||
/* Prepare the alignment of the section above. Few bytes (0x20) must be
|
||||
* added for the mapping header.
|
||||
|
||||
@ -4,10 +4,10 @@
|
||||
*/
|
||||
|
||||
SECTIONS {
|
||||
.rtc_fast.dummy (NOLOAD) :
|
||||
.rtc_fast.dummy (NOLOAD) : ALIGN(4)
|
||||
{
|
||||
_rtc_dummy_start = ABSOLUTE(.); /* needed to make section proper size */
|
||||
. = SIZEOF(.rtc_fast.text);
|
||||
. = . + SIZEOF(.rtc_fast.text);
|
||||
_rtc_dummy_end = ABSOLUTE(.); /* needed to make section proper size */
|
||||
} > RTC_FAST_RWDATA
|
||||
}
|
||||
|
||||
@ -3,15 +3,18 @@
|
||||
SECTIONS {
|
||||
.rodata : ALIGN(4)
|
||||
{
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
. = ALIGN (4);
|
||||
_rodata_start = ABSOLUTE(.);
|
||||
*(.rodata .rodata.*)
|
||||
*(.srodata .srodata.*)
|
||||
_rodata_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
} > RODATA
|
||||
|
||||
.rodata.wifi : ALIGN(4)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*( .rodata_wlog_*.* )
|
||||
. = ALIGN(4);
|
||||
} > RODATA
|
||||
}
|
||||
@ -3,7 +3,8 @@
|
||||
SECTIONS {
|
||||
.rtc_fast.text : {
|
||||
. = ALIGN(4);
|
||||
*(.rtc_fast.literal .rtc_fast.text .rtc_fast.literal.* .rtc_fast.text.*)
|
||||
*(.rtc_fast.literal .rtc_fast.text .rtc_fast.literal.* .rtc_fast.text.*)
|
||||
. = ALIGN(4);
|
||||
} > RTC_FAST_RWTEXT AT > RODATA
|
||||
|
||||
.rtc_fast.data :
|
||||
@ -12,6 +13,7 @@ SECTIONS {
|
||||
_rtc_fast_data_start = ABSOLUTE(.);
|
||||
*(.rtc_fast.data .rtc_fast.data.*)
|
||||
_rtc_fast_data_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
} > RTC_FAST_RWDATA AT > RODATA
|
||||
|
||||
.rtc_fast.bss (NOLOAD) :
|
||||
@ -20,11 +22,13 @@ SECTIONS {
|
||||
_rtc_fast_bss_start = ABSOLUTE(.);
|
||||
*(.rtc_fast.bss .rtc_fast.bss.*)
|
||||
_rtc_fast_bss_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
} > RTC_FAST_RWDATA
|
||||
|
||||
.rtc_fast.noinit (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.rtc_fast.noinit .rtc_fast.noinit.*)
|
||||
. = ALIGN(4);
|
||||
} > RTC_FAST_RWDATA
|
||||
}
|
||||
@ -3,7 +3,8 @@
|
||||
SECTIONS {
|
||||
.rtc_slow.text : {
|
||||
. = ALIGN(4);
|
||||
*(.rtc_slow.literal .rtc_slow.text .rtc_slow.literal.* .rtc_slow.text.*)
|
||||
*(.rtc_slow.literal .rtc_slow.text .rtc_slow.literal.* .rtc_slow.text.*)
|
||||
. = ALIGN(4);
|
||||
} > rtc_slow_seg AT > RODATA
|
||||
|
||||
.rtc_slow.data :
|
||||
@ -12,6 +13,7 @@ SECTIONS {
|
||||
_rtc_slow_data_start = ABSOLUTE(.);
|
||||
*(.rtc_slow.data .rtc_slow.data.*)
|
||||
_rtc_slow_data_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
} > rtc_slow_seg AT > RODATA
|
||||
|
||||
.rtc_slow.bss (NOLOAD) :
|
||||
@ -20,11 +22,13 @@ SECTIONS {
|
||||
_rtc_slow_bss_start = ABSOLUTE(.);
|
||||
*(.rtc_slow.bss .rtc_slow.bss.*)
|
||||
_rtc_slow_bss_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
} > rtc_slow_seg
|
||||
|
||||
.rtc_slow.noinit (NOLOAD) :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.rtc_slow.noinit .rtc_slow.noinit.*)
|
||||
. = ALIGN(4);
|
||||
} > rtc_slow_seg
|
||||
}
|
||||
@ -9,6 +9,7 @@ SECTIONS {
|
||||
*(.data .data.*);
|
||||
*(.data1)
|
||||
_data_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
} > RWDATA AT > RODATA
|
||||
|
||||
/* LMA of .data */
|
||||
@ -32,18 +33,21 @@ SECTIONS {
|
||||
*(.gnu.linkonce.b.*)
|
||||
*(COMMON)
|
||||
_bss_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
} > RWDATA
|
||||
|
||||
.noinit (NOLOAD) : ALIGN(4)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.noinit .noinit.*)
|
||||
. = ALIGN(4);
|
||||
} > RWDATA
|
||||
|
||||
.data.wifi :
|
||||
.data.wifi : ALIGN(4)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*( .dram1 .dram1.*)
|
||||
. = ALIGN(4);
|
||||
} > RWDATA AT > RODATA
|
||||
|
||||
/* must be last segment using RWDATA */
|
||||
|
||||
@ -5,9 +5,10 @@ SECTIONS {
|
||||
{
|
||||
. = ALIGN (4);
|
||||
*(.rwtext.literal .rwtext .rwtext.literal.* .rwtext.*)
|
||||
. = ALIGN(4);
|
||||
} > RWTEXT
|
||||
|
||||
.rwtext.wifi :
|
||||
.rwtext.wifi : ALIGN(4)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*( .wifi0iram .wifi0iram.*)
|
||||
@ -16,5 +17,6 @@ SECTIONS {
|
||||
*( .wifislpiram .wifislpiram.*)
|
||||
*( .phyiram .phyiram.*)
|
||||
*( .iram1 .iram1.*)
|
||||
. = ALIGN(4);
|
||||
} > RWTEXT AT > RODATA
|
||||
}
|
||||
@ -4,7 +4,9 @@ SECTIONS {
|
||||
|
||||
.text : ALIGN(4)
|
||||
{
|
||||
. = ALIGN(4);
|
||||
*(.literal .text .literal.* .text.*)
|
||||
. = ALIGN(4);
|
||||
} > ROTEXT
|
||||
|
||||
}
|
||||
@ -9,8 +9,15 @@ use crate::{
|
||||
macro_rules! impl_channel {
|
||||
($num: literal) => {
|
||||
paste::paste! {
|
||||
#[non_exhaustive]
|
||||
pub struct [<Channel $num>] {}
|
||||
|
||||
impl ChannelTypes for [<Channel $num>] {
|
||||
type P = [<SuitablePeripheral $num>];
|
||||
type Tx<'a> = ChannelTx<'a, [<Channel $num TxImpl>], [<Channel $num>]>;
|
||||
type Rx<'a> = ChannelRx<'a, [<Channel $num RxImpl>], [<Channel $num>]>;
|
||||
}
|
||||
|
||||
impl RegisterAccess for [<Channel $num>] {
|
||||
fn init_channel() {
|
||||
// nothing special to be done here
|
||||
@ -365,6 +372,7 @@ macro_rules! impl_channel {
|
||||
}
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct [<Channel $num TxImpl>] {}
|
||||
|
||||
impl<'a> TxChannel<[<Channel $num>]> for [<Channel $num TxImpl>] {
|
||||
@ -375,6 +383,7 @@ macro_rules! impl_channel {
|
||||
}
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct [<Channel $num RxImpl>] {}
|
||||
|
||||
impl<'a> RxChannel<[<Channel $num>]> for [<Channel $num RxImpl>] {
|
||||
@ -385,19 +394,21 @@ macro_rules! impl_channel {
|
||||
}
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct [<ChannelCreator $num>] {}
|
||||
|
||||
impl [<ChannelCreator $num>] {
|
||||
/// Configure the channel for use
|
||||
///
|
||||
/// Descriptors should be sized as (BUFFERSIZE / 4092) * 3
|
||||
/// Descriptors should be sized as `((BUFFERSIZE + 4091) / 4092) * 3`. I.e., to
|
||||
/// transfer buffers of size `1..=4092`, you need 3 descriptors.
|
||||
pub fn configure<'a>(
|
||||
self,
|
||||
burst_mode: bool,
|
||||
tx_descriptors: &'a mut [u32],
|
||||
rx_descriptors: &'a mut [u32],
|
||||
priority: DmaPriority,
|
||||
) -> Channel<ChannelTx<'a, [<Channel $num TxImpl>], [<Channel $num>]>, ChannelRx<'a, [<Channel $num RxImpl>], [<Channel $num>]>, [<SuitablePeripheral $num>]> {
|
||||
) -> Channel<'a, [<Channel $num>]> {
|
||||
let mut tx_impl = [<Channel $num TxImpl>] {};
|
||||
tx_impl.init(burst_mode, priority);
|
||||
|
||||
@ -431,11 +442,11 @@ macro_rules! impl_channel {
|
||||
Channel {
|
||||
tx: tx_channel,
|
||||
rx: rx_channel,
|
||||
_phantom: PhantomData::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct [<SuitablePeripheral $num>] {}
|
||||
impl PeripheralMarker for [<SuitablePeripheral $num>] {}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! Direct Memory Access Commons
|
||||
//!
|
||||
//! Descriptors should be sized as (BUFFERSIZE / 4092) * 3
|
||||
//! Descriptors should be sized as `((BUFFERSIZE + 4091) / 4092) * 3`. I.e., to
|
||||
//! transfer buffers of size `1..=4092`, you need 3 descriptors.
|
||||
|
||||
use core::{marker::PhantomData, sync::atomic::compiler_fence};
|
||||
|
||||
@ -347,7 +348,7 @@ where
|
||||
return Err(DmaError::InvalidDescriptorSize);
|
||||
}
|
||||
|
||||
if self.descriptors.len() / 3 < len / CHUNK_SIZE {
|
||||
if self.descriptors.len() / 3 < (len + CHUNK_SIZE - 1) / CHUNK_SIZE {
|
||||
return Err(DmaError::OutOfDescriptors);
|
||||
}
|
||||
|
||||
@ -647,7 +648,7 @@ where
|
||||
return Err(DmaError::InvalidDescriptorSize);
|
||||
}
|
||||
|
||||
if self.descriptors.len() / 3 < len / CHUNK_SIZE {
|
||||
if self.descriptors.len() / 3 < (len + CHUNK_SIZE - 1) / CHUNK_SIZE {
|
||||
return Err(DmaError::OutOfDescriptors);
|
||||
}
|
||||
|
||||
@ -829,16 +830,20 @@ pub trait RegisterAccess {
|
||||
fn unlisten_in_eof();
|
||||
fn unlisten_out_eof();
|
||||
}
|
||||
|
||||
pub trait ChannelTypes {
|
||||
type P: PeripheralMarker;
|
||||
type Tx<'a>: Tx;
|
||||
type Rx<'a>: Rx;
|
||||
}
|
||||
|
||||
/// DMA Channel
|
||||
pub struct Channel<TX, RX, P>
|
||||
pub struct Channel<'d, C>
|
||||
where
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: PeripheralMarker,
|
||||
C: ChannelTypes,
|
||||
{
|
||||
pub(crate) tx: TX,
|
||||
pub(crate) rx: RX,
|
||||
_phantom: PhantomData<P>,
|
||||
pub(crate) tx: C::Tx<'d>,
|
||||
pub(crate) rx: C::Rx<'d>,
|
||||
}
|
||||
|
||||
/// Trait to be implemented for an in progress dma transfer.
|
||||
|
||||
@ -9,8 +9,15 @@ use crate::{
|
||||
macro_rules! ImplSpiChannel {
|
||||
($num: literal) => {
|
||||
paste::paste! {
|
||||
#[non_exhaustive]
|
||||
pub struct [<Spi $num DmaChannel>] {}
|
||||
|
||||
impl ChannelTypes for [<Spi $num DmaChannel>] {
|
||||
type P = [<Spi $num DmaSuitablePeripheral>];
|
||||
type Tx<'a> = ChannelTx<'a,[<Spi $num DmaChannelTxImpl>], [<Spi $num DmaChannel>]>;
|
||||
type Rx<'a> = ChannelRx<'a,[<Spi $num DmaChannelRxImpl>], [<Spi $num DmaChannel>]>;
|
||||
}
|
||||
|
||||
impl RegisterAccess for [<Spi $num DmaChannel>] {
|
||||
fn init_channel() {
|
||||
// (only) on ESP32 we need to configure DPORT for the SPI DMA channels
|
||||
@ -195,6 +202,7 @@ macro_rules! ImplSpiChannel {
|
||||
}
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct [<Spi $num DmaChannelTxImpl>] {}
|
||||
|
||||
impl<'a> TxChannel<[<Spi $num DmaChannel>]> for [<Spi $num DmaChannelTxImpl>] {
|
||||
@ -205,6 +213,7 @@ macro_rules! ImplSpiChannel {
|
||||
}
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct [<Spi $num DmaChannelRxImpl>] {}
|
||||
|
||||
impl<'a> RxChannel<[<Spi $num DmaChannel>]> for [<Spi $num DmaChannelRxImpl>] {
|
||||
@ -215,23 +224,21 @@ macro_rules! ImplSpiChannel {
|
||||
}
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct [<Spi $num DmaChannelCreator>] {}
|
||||
|
||||
impl [<Spi $num DmaChannelCreator>] {
|
||||
/// Configure the channel for use
|
||||
///
|
||||
/// Descriptors should be sized as (BUFFERSIZE / 4092) * 3
|
||||
/// Descriptors should be sized as `((BUFFERSIZE + 4091) / 4092) * 3`. I.e., to
|
||||
/// transfer buffers of size `1..=4092`, you need 3 descriptors.
|
||||
pub fn configure<'a>(
|
||||
self,
|
||||
burst_mode: bool,
|
||||
tx_descriptors: &'a mut [u32],
|
||||
rx_descriptors: &'a mut [u32],
|
||||
priority: DmaPriority,
|
||||
) -> Channel<
|
||||
ChannelTx<'a,[<Spi $num DmaChannelTxImpl>], [<Spi $num DmaChannel>]>,
|
||||
ChannelRx<'a,[<Spi $num DmaChannelRxImpl>], [<Spi $num DmaChannel>]>,
|
||||
[<Spi $num DmaSuitablePeripheral>],
|
||||
> {
|
||||
) -> Channel<'a, [<Spi $num DmaChannel>]> {
|
||||
let mut tx_impl = [<Spi $num DmaChannelTxImpl>] {};
|
||||
tx_impl.init(burst_mode, priority);
|
||||
|
||||
@ -265,7 +272,6 @@ macro_rules! ImplSpiChannel {
|
||||
Channel {
|
||||
tx: tx_channel,
|
||||
rx: rx_channel,
|
||||
_phantom: PhantomData::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -278,6 +284,12 @@ macro_rules! ImplI2sChannel {
|
||||
paste::paste! {
|
||||
pub struct [<I2s $num DmaChannel>] {}
|
||||
|
||||
impl ChannelTypes for [<I2s $num DmaChannel>] {
|
||||
type P = [<I2s $num DmaSuitablePeripheral>];
|
||||
type Tx<'a> = ChannelTx<'a,[<I2s $num DmaChannelTxImpl>], [<I2s $num DmaChannel>]>;
|
||||
type Rx<'a> = ChannelRx<'a,[<I2s $num DmaChannelRxImpl>], [<I2s $num DmaChannel>]>;
|
||||
}
|
||||
|
||||
impl RegisterAccess for [<I2s $num DmaChannel>] {
|
||||
fn init_channel() {
|
||||
// nothing to do
|
||||
@ -458,18 +470,15 @@ macro_rules! ImplI2sChannel {
|
||||
impl [<I2s $num DmaChannelCreator>] {
|
||||
/// Configure the channel for use
|
||||
///
|
||||
/// Descriptors should be sized as (BUFFERSIZE / 4092) * 3
|
||||
/// Descriptors should be sized as `((BUFFERSIZE + 4091) / 4092) * 3`. I.e., to
|
||||
/// transfer buffers of size `1..=4092`, you need 3 descriptors.
|
||||
pub fn configure<'a>(
|
||||
self,
|
||||
burst_mode: bool,
|
||||
tx_descriptors: &'a mut [u32],
|
||||
rx_descriptors: &'a mut [u32],
|
||||
priority: DmaPriority,
|
||||
) -> Channel<
|
||||
ChannelTx<'a,[<I2s $num DmaChannelTxImpl>], [<I2s $num DmaChannel>]>,
|
||||
ChannelRx<'a,[<I2s $num DmaChannelRxImpl>], [<I2s $num DmaChannel>]>,
|
||||
[<I2s $num DmaSuitablePeripheral>],
|
||||
> {
|
||||
) -> Channel<'a, [<I2s $num DmaChannel>]> {
|
||||
let mut tx_impl = [<I2s $num DmaChannelTxImpl>] {};
|
||||
tx_impl.init(burst_mode, priority);
|
||||
|
||||
@ -503,7 +512,6 @@ macro_rules! ImplI2sChannel {
|
||||
Channel {
|
||||
tx: tx_channel,
|
||||
rx: rx_channel,
|
||||
_phantom: PhantomData::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -511,11 +519,13 @@ macro_rules! ImplI2sChannel {
|
||||
};
|
||||
}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct Spi2DmaSuitablePeripheral {}
|
||||
impl PeripheralMarker for Spi2DmaSuitablePeripheral {}
|
||||
impl SpiPeripheral for Spi2DmaSuitablePeripheral {}
|
||||
impl Spi2Peripheral for Spi2DmaSuitablePeripheral {}
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct Spi3DmaSuitablePeripheral {}
|
||||
impl PeripheralMarker for Spi3DmaSuitablePeripheral {}
|
||||
impl SpiPeripheral for Spi3DmaSuitablePeripheral {}
|
||||
@ -524,6 +534,7 @@ impl Spi3Peripheral for Spi3DmaSuitablePeripheral {}
|
||||
ImplSpiChannel!(2);
|
||||
ImplSpiChannel!(3);
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct I2s0DmaSuitablePeripheral {}
|
||||
impl PeripheralMarker for I2s0DmaSuitablePeripheral {}
|
||||
impl I2sPeripheral for I2s0DmaSuitablePeripheral {}
|
||||
@ -531,6 +542,7 @@ impl I2s0Peripheral for I2s0DmaSuitablePeripheral {}
|
||||
|
||||
ImplI2sChannel!(0, "I2S0");
|
||||
|
||||
#[non_exhaustive]
|
||||
pub struct I2s1DmaSuitablePeripheral {}
|
||||
impl PeripheralMarker for I2s1DmaSuitablePeripheral {}
|
||||
impl I2sPeripheral for I2s1DmaSuitablePeripheral {}
|
||||
|
||||
@ -9,7 +9,10 @@ use crate::{
|
||||
timer::{Timer, Timer0},
|
||||
};
|
||||
|
||||
#[cfg(not(any(esp32, esp32s2, esp32s3)))]
|
||||
pub const ALARM_COUNT: usize = 1;
|
||||
#[cfg(any(esp32, esp32s2, esp32s3))]
|
||||
pub const ALARM_COUNT: usize = 2;
|
||||
|
||||
pub type TimerInner = Timer0<TIMG0>;
|
||||
pub type TimerType = Timer<TimerInner>;
|
||||
@ -49,16 +52,25 @@ impl EmbassyTimer {
|
||||
pub fn init(clocks: &Clocks, mut timer: TimerType) {
|
||||
use crate::{interrupt, interrupt::Priority};
|
||||
|
||||
// set divider to get a 1mhz clock. abp (80mhz) / 80 = 1mhz... // TODO assert
|
||||
// abp clock is the source and its at the correct speed for the divider
|
||||
// set divider to get a 1mhz clock. APB (80mhz) / 80 = 1mhz...
|
||||
// TODO: assert APB clock is the source and its at the correct speed for the
|
||||
// divider
|
||||
timer.set_divider(clocks.apb_clock.to_MHz() as u16);
|
||||
|
||||
interrupt::enable(peripherals::Interrupt::TG0_T0_LEVEL, Priority::max()).unwrap();
|
||||
#[cfg(any(esp32, esp32s2, esp32s3))]
|
||||
interrupt::enable(peripherals::Interrupt::TG0_T1_LEVEL, Priority::max()).unwrap();
|
||||
|
||||
#[interrupt]
|
||||
fn TG0_T0_LEVEL() {
|
||||
DRIVER.on_interrupt(0);
|
||||
}
|
||||
|
||||
#[cfg(any(esp32, esp32s2, esp32s3))]
|
||||
#[interrupt]
|
||||
fn TG0_T1_LEVEL() {
|
||||
DRIVER.on_interrupt(1);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn set_alarm(
|
||||
|
||||
@ -1230,6 +1230,7 @@ impl<MODE> embedded_hal_async::digital::Wait for AnyPin<Input<MODE>> {
|
||||
}
|
||||
}
|
||||
|
||||
/// General Purpose Input/Output driver
|
||||
pub struct IO {
|
||||
_io_mux: IO_MUX,
|
||||
pub pins: Pins,
|
||||
|
||||
@ -250,7 +250,10 @@ where
|
||||
|
||||
let mut i2c = I2C { peripheral: i2c };
|
||||
|
||||
// initialize SCL first to not confuse some devices like MPU6050
|
||||
// avoid SCL/SDA going low during configuration
|
||||
scl.set_output_high(true);
|
||||
sda.set_output_high(true);
|
||||
|
||||
scl.set_to_open_drain_output()
|
||||
.enable_input(true)
|
||||
.internal_pull_up(true)
|
||||
|
||||
@ -7,7 +7,16 @@ use private::*;
|
||||
use crate::dma::I2s1Peripheral;
|
||||
use crate::{
|
||||
clock::Clocks,
|
||||
dma::{Channel, DmaError, DmaTransfer, I2s0Peripheral, I2sPeripheral, Rx, Tx},
|
||||
dma::{
|
||||
Channel,
|
||||
ChannelTypes,
|
||||
DmaError,
|
||||
DmaTransfer,
|
||||
I2s0Peripheral,
|
||||
I2sPeripheral,
|
||||
RxPrivate,
|
||||
TxPrivate,
|
||||
},
|
||||
gpio::{InputPin, OutputPin},
|
||||
peripheral::{Peripheral, PeripheralRef},
|
||||
system::PeripheralClockControl,
|
||||
@ -271,21 +280,21 @@ impl I2sMclkPin for NoMclk {
|
||||
}
|
||||
|
||||
/// An in-progress DMA write transfer.
|
||||
pub struct I2sWriteDmaTransfer<T, P, TX, BUFFER>
|
||||
pub struct I2sWriteDmaTransfer<'d, T, P, CH, BUFFER>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sTxPins,
|
||||
TX: Tx,
|
||||
{
|
||||
i2s_tx: I2sTx<T, P, TX>,
|
||||
i2s_tx: I2sTx<'d, T, P, CH>,
|
||||
buffer: BUFFER,
|
||||
}
|
||||
|
||||
impl<'d, T, P, TX, BUFFER> I2sWriteDmaTransfer<T, P, TX, BUFFER>
|
||||
impl<'d, T, P, CH, BUFFER> I2sWriteDmaTransfer<'d, T, P, CH, BUFFER>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sTxPins,
|
||||
TX: Tx,
|
||||
{
|
||||
/// Amount of bytes which can be pushed.
|
||||
/// Only useful for circular DMA transfers
|
||||
@ -300,16 +309,16 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, P, TX, BUFFER> DmaTransfer<BUFFER, I2sTx<T, P, TX>>
|
||||
for I2sWriteDmaTransfer<T, P, TX, BUFFER>
|
||||
impl<'d, T, P, CH, BUFFER> DmaTransfer<BUFFER, I2sTx<'d, T, P, CH>>
|
||||
for I2sWriteDmaTransfer<'d, T, P, CH, BUFFER>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sTxPins,
|
||||
TX: Tx,
|
||||
{
|
||||
/// Wait for the DMA transfer to complete and return the buffers and the
|
||||
/// I2sTx instance.
|
||||
fn wait(self) -> (BUFFER, I2sTx<T, P, TX>) {
|
||||
fn wait(self) -> (BUFFER, I2sTx<'d, T, P, CH>) {
|
||||
self.i2s_tx.wait_tx_dma_done().ok(); // waiting for the DMA transfer is not enough
|
||||
|
||||
// `DmaTransfer` needs to have a `Drop` implementation, because we accept
|
||||
@ -333,11 +342,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, P, TX, BUFFER> Drop for I2sWriteDmaTransfer<T, P, TX, BUFFER>
|
||||
impl<'d, T, P, CH, BUFFER> Drop for I2sWriteDmaTransfer<'d, T, P, CH, BUFFER>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sTxPins,
|
||||
TX: Tx,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.i2s_tx.wait_tx_dma_done().ok();
|
||||
@ -350,53 +359,47 @@ pub trait I2sWrite<W> {
|
||||
}
|
||||
|
||||
/// Initiate a DMA tx transfer
|
||||
pub trait I2sWriteDma<'d, T, P, TX, TXBUF>
|
||||
pub trait I2sWriteDma<'d, T, P, CH, TXBUF>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sTxPins,
|
||||
TX: Tx,
|
||||
{
|
||||
/// Write I2S.
|
||||
/// Returns [I2sWriteDmaTransfer] which represents the in-ptrogress DMA
|
||||
/// Returns [I2sWriteDmaTransfer] which represents the in-progress DMA
|
||||
/// transfer
|
||||
fn write_dma(self, words: TXBUF) -> Result<I2sWriteDmaTransfer<T, P, TX, TXBUF>, Error>
|
||||
fn write_dma(self, words: TXBUF) -> Result<I2sWriteDmaTransfer<'d, T, P, CH, TXBUF>, Error>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
P: I2sTxPins,
|
||||
TX: Tx,
|
||||
TXBUF: ReadBuffer<Word = u8>;
|
||||
|
||||
/// Continously write to I2S. Returns [I2sWriteDmaTransfer] which represents
|
||||
/// the in-ptrogress DMA transfer
|
||||
/// Continuously write to I2S. Returns [I2sWriteDmaTransfer] which
|
||||
/// represents the in-progress DMA transfer
|
||||
fn write_dma_circular(
|
||||
self,
|
||||
words: TXBUF,
|
||||
) -> Result<I2sWriteDmaTransfer<T, P, TX, TXBUF>, Error>
|
||||
) -> Result<I2sWriteDmaTransfer<'d, T, P, CH, TXBUF>, Error>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
P: I2sTxPins,
|
||||
TX: Tx,
|
||||
TXBUF: ReadBuffer<Word = u8>;
|
||||
}
|
||||
|
||||
/// An in-progress DMA read transfer.
|
||||
pub struct I2sReadDmaTransfer<T, P, RX, BUFFER>
|
||||
pub struct I2sReadDmaTransfer<'d, T, P, CH, BUFFER>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sRxPins,
|
||||
RX: Rx,
|
||||
{
|
||||
i2s_rx: I2sRx<T, P, RX>,
|
||||
i2s_rx: I2sRx<'d, T, P, CH>,
|
||||
buffer: BUFFER,
|
||||
}
|
||||
|
||||
impl<'d, T, P, RX, BUFFER> I2sReadDmaTransfer<T, P, RX, BUFFER>
|
||||
impl<'d, T, P, CH, BUFFER> I2sReadDmaTransfer<'d, T, P, CH, BUFFER>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sRxPins,
|
||||
RX: Rx,
|
||||
{
|
||||
/// Amount of bytes which can be poped
|
||||
/// Amount of bytes which can be popped
|
||||
pub fn available(&mut self) -> usize {
|
||||
self.i2s_rx.rx_channel.available()
|
||||
}
|
||||
@ -409,7 +412,7 @@ where
|
||||
/// I2sTx instance after copying the read data to the given buffer.
|
||||
/// Length of the received data is returned at the third element of the
|
||||
/// tuple.
|
||||
pub fn wait_receive(mut self, dst: &mut [u8]) -> (BUFFER, I2sRx<T, P, RX>, usize) {
|
||||
pub fn wait_receive(mut self, dst: &mut [u8]) -> (BUFFER, I2sRx<'d, T, P, CH>, usize) {
|
||||
self.i2s_rx.wait_rx_dma_done().ok(); // waiting for the DMA transfer is not enough
|
||||
|
||||
let len = self.i2s_rx.rx_channel.drain_buffer(dst).unwrap();
|
||||
@ -430,16 +433,16 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, P, RX, BUFFER> DmaTransfer<BUFFER, I2sRx<T, P, RX>>
|
||||
for I2sReadDmaTransfer<T, P, RX, BUFFER>
|
||||
impl<'d, T, P, CH, BUFFER> DmaTransfer<BUFFER, I2sRx<'d, T, P, CH>>
|
||||
for I2sReadDmaTransfer<'d, T, P, CH, BUFFER>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sRxPins,
|
||||
RX: Rx,
|
||||
{
|
||||
/// Wait for the DMA transfer to complete and return the buffers and the
|
||||
/// I2sTx instance.
|
||||
fn wait(self) -> (BUFFER, I2sRx<T, P, RX>) {
|
||||
fn wait(self) -> (BUFFER, I2sRx<'d, T, P, CH>) {
|
||||
self.i2s_rx.wait_rx_dma_done().ok(); // waiting for the DMA transfer is not enough
|
||||
|
||||
// `DmaTransfer` needs to have a `Drop` implementation, because we accept
|
||||
@ -463,11 +466,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, P, RX, BUFFER> Drop for I2sReadDmaTransfer<T, P, RX, BUFFER>
|
||||
impl<T, P, CH, BUFFER> Drop for I2sReadDmaTransfer<'_, T, P, CH, BUFFER>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sRxPins,
|
||||
RX: Rx,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
self.i2s_rx.wait_rx_dma_done().ok();
|
||||
@ -479,71 +482,60 @@ pub trait I2sRead<W> {
|
||||
fn read(&mut self, words: &mut [W]) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
/// Initate a DMA rx transfer
|
||||
pub trait I2sReadDma<'d, T, P, RX, RXBUF>
|
||||
/// Initiate a DMA rx transfer
|
||||
pub trait I2sReadDma<'d, T, P, CH, RXBUF>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sRxPins,
|
||||
RX: Rx,
|
||||
{
|
||||
/// Read I2S.
|
||||
/// Returns [I2sReadDmaTransfer] which represents the in-ptrogress DMA
|
||||
/// Returns [I2sReadDmaTransfer] which represents the in-progress DMA
|
||||
/// transfer
|
||||
fn read_dma(self, words: RXBUF) -> Result<I2sReadDmaTransfer<T, P, RX, RXBUF>, Error>
|
||||
fn read_dma(self, words: RXBUF) -> Result<I2sReadDmaTransfer<'d, T, P, CH, RXBUF>, Error>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
P: I2sRxPins,
|
||||
RX: Rx,
|
||||
RXBUF: WriteBuffer<Word = u8>;
|
||||
|
||||
/// Continously read from I2S.
|
||||
/// Returns [I2sReadDmaTransfer] which represents the in-ptrogress DMA
|
||||
/// Continuously read from I2S.
|
||||
/// Returns [I2sReadDmaTransfer] which represents the in-progress DMA
|
||||
/// transfer
|
||||
fn read_dma_circular(self, words: RXBUF) -> Result<I2sReadDmaTransfer<T, P, RX, RXBUF>, Error>
|
||||
fn read_dma_circular(
|
||||
self,
|
||||
words: RXBUF,
|
||||
) -> Result<I2sReadDmaTransfer<'d, T, P, CH, RXBUF>, Error>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
P: I2sRxPins,
|
||||
RX: Rx,
|
||||
RXBUF: WriteBuffer<Word = u8>;
|
||||
}
|
||||
|
||||
/// Instance of the I2S peripheral driver
|
||||
pub struct I2s<'d, I, T, P, TX, RX>
|
||||
pub struct I2s<'d, I, P, CH>
|
||||
where
|
||||
I: Instance<T>,
|
||||
T: RegisterAccess + Clone,
|
||||
I: Instance,
|
||||
P: I2sMclkPin,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
CH: ChannelTypes,
|
||||
{
|
||||
_peripheral: PeripheralRef<'d, I>,
|
||||
_register_access: T,
|
||||
_pins: P,
|
||||
pub i2s_tx: TxCreator<T, TX>,
|
||||
pub i2s_rx: RxCreator<T, RX>,
|
||||
pub i2s_tx: TxCreator<'d, I::Peripheral, CH>,
|
||||
pub i2s_rx: RxCreator<'d, I::Peripheral, CH>,
|
||||
}
|
||||
|
||||
impl<'d, I, T, P, TX, RX> I2s<'d, I, T, P, TX, RX>
|
||||
impl<'d, I, P, CH> I2s<'d, I, P, CH>
|
||||
where
|
||||
I: Instance<T>,
|
||||
T: RegisterAccess + Clone,
|
||||
I: Instance,
|
||||
P: I2sMclkPin,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
CH: ChannelTypes,
|
||||
{
|
||||
fn new_internal<IP>(
|
||||
fn new_internal(
|
||||
i2s: impl Peripheral<P = I> + 'd,
|
||||
mut pins: P,
|
||||
standard: Standard,
|
||||
data_format: DataFormat,
|
||||
sample_rate: impl Into<fugit::HertzU32>,
|
||||
mut channel: Channel<TX, RX, IP>,
|
||||
mut channel: Channel<'d, CH>,
|
||||
peripheral_clock_control: &mut PeripheralClockControl,
|
||||
clocks: &Clocks,
|
||||
) -> Self
|
||||
where
|
||||
IP: I2sPeripheral,
|
||||
{
|
||||
) -> Self {
|
||||
// on ESP32-C3 / ESP32-S3 and later RX and TX are independent and
|
||||
// could be configured totally independently but for now handle all
|
||||
// the targets the same and force same configuration for both, TX and RX
|
||||
@ -566,7 +558,6 @@ where
|
||||
|
||||
Self {
|
||||
_peripheral: i2s,
|
||||
_register_access: register_access.clone(),
|
||||
_pins: pins,
|
||||
i2s_tx: TxCreator {
|
||||
register_access: register_access.clone(),
|
||||
@ -581,15 +572,12 @@ where
|
||||
}
|
||||
|
||||
/// Construct a new I2S peripheral driver instance for the first I2S peripheral
|
||||
pub trait I2s0New<'d, I, T, P, TX, RX, IP>
|
||||
pub trait I2s0New<'d, I, P, CH>
|
||||
where
|
||||
I: Instance<T>,
|
||||
T: RegisterAccess + Clone,
|
||||
I: Instance,
|
||||
P: I2sMclkPin,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
IP: I2sPeripheral + I2s0Peripheral,
|
||||
RX: Rx,
|
||||
CH: ChannelTypes,
|
||||
CH::P: I2sPeripheral + I2s0Peripheral,
|
||||
{
|
||||
fn new(
|
||||
i2s: impl Peripheral<P = I> + 'd,
|
||||
@ -597,20 +585,18 @@ where
|
||||
standard: Standard,
|
||||
data_format: DataFormat,
|
||||
sample_rate: impl Into<fugit::HertzU32>,
|
||||
channel: Channel<TX, RX, IP>,
|
||||
channel: Channel<'d, CH>,
|
||||
peripheral_clock_control: &mut PeripheralClockControl,
|
||||
clocks: &Clocks,
|
||||
) -> Self;
|
||||
}
|
||||
|
||||
impl<'d, I, T, P, TX, RX, IP> I2s0New<'d, I, T, P, TX, RX, IP> for I2s<'d, I, T, P, TX, RX>
|
||||
impl<'d, I, P, CH> I2s0New<'d, I, P, CH> for I2s<'d, I, P, CH>
|
||||
where
|
||||
I: Instance<T> + I2s0Instance,
|
||||
T: RegisterAccess + Clone,
|
||||
I: Instance + I2s0Instance,
|
||||
P: I2sMclkPin,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
IP: I2sPeripheral + I2s0Peripheral,
|
||||
CH: ChannelTypes,
|
||||
CH::P: I2sPeripheral + I2s0Peripheral,
|
||||
{
|
||||
fn new(
|
||||
i2s: impl Peripheral<P = I> + 'd,
|
||||
@ -618,7 +604,7 @@ where
|
||||
standard: Standard,
|
||||
data_format: DataFormat,
|
||||
sample_rate: impl Into<fugit::HertzU32>,
|
||||
channel: Channel<TX, RX, IP>,
|
||||
channel: Channel<'d, CH>,
|
||||
peripheral_clock_control: &mut PeripheralClockControl,
|
||||
clocks: &Clocks,
|
||||
) -> Self {
|
||||
@ -637,15 +623,12 @@ where
|
||||
|
||||
/// Construct a new I2S peripheral driver instance for the second I2S peripheral
|
||||
#[cfg(any(esp32s3))]
|
||||
pub trait I2s1New<'d, I, T, P, TX, RX, IP>
|
||||
pub trait I2s1New<'d, I, P, CH>
|
||||
where
|
||||
I: Instance<T>,
|
||||
T: RegisterAccess + Clone,
|
||||
I: Instance,
|
||||
P: I2sMclkPin,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
IP: I2sPeripheral + I2s1Peripheral,
|
||||
RX: Rx,
|
||||
CH: ChannelTypes,
|
||||
CH::P: I2sPeripheral + I2s1Peripheral,
|
||||
{
|
||||
fn new(
|
||||
i2s: impl Peripheral<P = I> + 'd,
|
||||
@ -653,21 +636,19 @@ where
|
||||
standard: Standard,
|
||||
data_format: DataFormat,
|
||||
sample_rate: impl Into<fugit::HertzU32>,
|
||||
channel: Channel<TX, RX, IP>,
|
||||
channel: Channel<'d, CH>,
|
||||
peripheral_clock_control: &mut PeripheralClockControl,
|
||||
clocks: &Clocks,
|
||||
) -> Self;
|
||||
}
|
||||
|
||||
#[cfg(any(esp32s3))]
|
||||
impl<'d, I, T, P, TX, RX, IP> I2s1New<'d, I, T, P, TX, RX, IP> for I2s<'d, I, T, P, TX, RX>
|
||||
impl<'d, I, P, CH> I2s1New<'d, I, P, CH> for I2s<'d, I, P, CH>
|
||||
where
|
||||
I: Instance<T> + I2s1Instance,
|
||||
T: RegisterAccess + Clone,
|
||||
I: Instance + I2s1Instance,
|
||||
P: I2sMclkPin,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
IP: I2sPeripheral + I2s1Peripheral,
|
||||
CH: ChannelTypes,
|
||||
CH::P: I2sPeripheral + I2s1Peripheral,
|
||||
{
|
||||
fn new(
|
||||
i2s: impl Peripheral<P = I> + 'd,
|
||||
@ -675,7 +656,7 @@ where
|
||||
standard: Standard,
|
||||
data_format: DataFormat,
|
||||
sample_rate: impl Into<fugit::HertzU32>,
|
||||
channel: Channel<TX, RX, IP>,
|
||||
channel: Channel<'d, CH>,
|
||||
peripheral_clock_control: &mut PeripheralClockControl,
|
||||
clocks: &Clocks,
|
||||
) -> Self {
|
||||
@ -693,24 +674,24 @@ where
|
||||
}
|
||||
|
||||
/// I2S TX channel
|
||||
pub struct I2sTx<T, P, TX>
|
||||
pub struct I2sTx<'d, T, P, CH>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sTxPins,
|
||||
TX: Tx,
|
||||
{
|
||||
register_access: T,
|
||||
_pins: P,
|
||||
tx_channel: TX,
|
||||
tx_channel: CH::Tx<'d>,
|
||||
}
|
||||
|
||||
impl<T, P, TX> I2sTx<T, P, TX>
|
||||
impl<'d, T, P, CH> I2sTx<'d, T, P, CH>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sTxPins,
|
||||
TX: Tx,
|
||||
{
|
||||
fn new(mut register_access: T, mut pins: P, tx_channel: TX) -> Self {
|
||||
fn new(mut register_access: T, mut pins: P, tx_channel: CH::Tx<'d>) -> Self {
|
||||
pins.configure(&mut register_access);
|
||||
|
||||
Self {
|
||||
@ -751,7 +732,7 @@ where
|
||||
mut self,
|
||||
words: TXBUF,
|
||||
circular: bool,
|
||||
) -> Result<I2sWriteDmaTransfer<T, P, TX, TXBUF>, Error>
|
||||
) -> Result<I2sWriteDmaTransfer<'d, T, P, CH, TXBUF>, Error>
|
||||
where
|
||||
TXBUF: ReadBuffer<Word = u8>,
|
||||
{
|
||||
@ -789,11 +770,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, P, TX, W> I2sWrite<W> for I2sTx<T, P, TX>
|
||||
impl<'d, T, P, W, CH> I2sWrite<W> for I2sTx<'d, T, P, CH>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sTxPins,
|
||||
TX: Tx,
|
||||
W: AcceptedWord,
|
||||
{
|
||||
fn write(&mut self, words: &[W]) -> Result<(), Error> {
|
||||
@ -806,20 +787,23 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, P, TX, TXBUF> I2sWriteDma<'d, T, P, TX, TXBUF> for I2sTx<T, P, TX>
|
||||
impl<'d, T, P, CH, TXBUF> I2sWriteDma<'d, T, P, CH, TXBUF> for I2sTx<'d, T, P, CH>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sTxPins,
|
||||
TX: Tx,
|
||||
{
|
||||
fn write_dma(self, words: TXBUF) -> Result<I2sWriteDmaTransfer<T, P, TX, TXBUF>, Error>
|
||||
fn write_dma(self, words: TXBUF) -> Result<I2sWriteDmaTransfer<'d, T, P, CH, TXBUF>, Error>
|
||||
where
|
||||
TXBUF: ReadBuffer<Word = u8>,
|
||||
{
|
||||
self.start_tx_transfer(words, false)
|
||||
}
|
||||
|
||||
fn write_dma_circular(self, words: TXBUF) -> Result<I2sWriteDmaTransfer<T, P, TX, TXBUF>, Error>
|
||||
fn write_dma_circular(
|
||||
self,
|
||||
words: TXBUF,
|
||||
) -> Result<I2sWriteDmaTransfer<'d, T, P, CH, TXBUF>, Error>
|
||||
where
|
||||
TXBUF: ReadBuffer<Word = u8>,
|
||||
{
|
||||
@ -828,24 +812,24 @@ where
|
||||
}
|
||||
|
||||
/// I2S RX channel
|
||||
pub struct I2sRx<T, P, RX>
|
||||
pub struct I2sRx<'d, T, P, CH>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sRxPins,
|
||||
RX: Rx,
|
||||
{
|
||||
register_access: T,
|
||||
_pins: P,
|
||||
rx_channel: RX,
|
||||
rx_channel: CH::Rx<'d>,
|
||||
}
|
||||
|
||||
impl<'d, T, P, RX> I2sRx<T, P, RX>
|
||||
impl<'d, T, P, CH> I2sRx<'d, T, P, CH>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sRxPins,
|
||||
RX: Rx,
|
||||
{
|
||||
fn new(mut register_access: T, mut pins: P, rx_channel: RX) -> Self {
|
||||
fn new(mut register_access: T, mut pins: P, rx_channel: CH::Rx<'d>) -> Self {
|
||||
pins.configure(&mut register_access);
|
||||
|
||||
Self {
|
||||
@ -886,7 +870,7 @@ where
|
||||
mut self,
|
||||
mut words: RXBUF,
|
||||
circular: bool,
|
||||
) -> Result<I2sReadDmaTransfer<T, P, RX, RXBUF>, Error>
|
||||
) -> Result<I2sReadDmaTransfer<'d, T, P, CH, RXBUF>, Error>
|
||||
where
|
||||
RXBUF: WriteBuffer<Word = u8>,
|
||||
{
|
||||
@ -931,11 +915,11 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<W, T, P, RX> I2sRead<W> for I2sRx<T, P, RX>
|
||||
impl<'d, W, T, P, CH> I2sRead<W> for I2sRx<'d, T, P, CH>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sRxPins,
|
||||
RX: Rx,
|
||||
W: AcceptedWord,
|
||||
{
|
||||
fn read(&mut self, words: &mut [W]) -> Result<(), Error> {
|
||||
@ -952,20 +936,23 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, P, RX, RXBUF> I2sReadDma<'d, T, P, RX, RXBUF> for I2sRx<T, P, RX>
|
||||
impl<'d, T, P, CH, RXBUF> I2sReadDma<'d, T, P, CH, RXBUF> for I2sRx<'d, T, P, CH>
|
||||
where
|
||||
T: RegisterAccess,
|
||||
CH: ChannelTypes,
|
||||
P: I2sRxPins,
|
||||
RX: Rx,
|
||||
{
|
||||
fn read_dma(self, words: RXBUF) -> Result<I2sReadDmaTransfer<T, P, RX, RXBUF>, Error>
|
||||
fn read_dma(self, words: RXBUF) -> Result<I2sReadDmaTransfer<'d, T, P, CH, RXBUF>, Error>
|
||||
where
|
||||
RXBUF: WriteBuffer<Word = u8>,
|
||||
{
|
||||
self.start_rx_transfer(words, false)
|
||||
}
|
||||
|
||||
fn read_dma_circular(self, words: RXBUF) -> Result<I2sReadDmaTransfer<T, P, RX, RXBUF>, Error>
|
||||
fn read_dma_circular(
|
||||
self,
|
||||
words: RXBUF,
|
||||
) -> Result<I2sReadDmaTransfer<'d, T, P, CH, RXBUF>, Error>
|
||||
where
|
||||
RXBUF: WriteBuffer<Word = u8>,
|
||||
{
|
||||
@ -1005,7 +992,7 @@ mod private {
|
||||
use crate::peripherals::i2s1::RegisterBlock;
|
||||
use crate::{
|
||||
clock::Clocks,
|
||||
dma::{DmaPeripheral, Rx, Tx},
|
||||
dma::{ChannelTypes, DmaPeripheral},
|
||||
gpio::{InputSignal, OutputSignal},
|
||||
peripherals::I2S0,
|
||||
system::Peripheral,
|
||||
@ -1013,21 +1000,21 @@ mod private {
|
||||
|
||||
pub trait I2sPins {}
|
||||
|
||||
pub struct TxCreator<T, TX>
|
||||
pub struct TxCreator<'d, T, CH>
|
||||
where
|
||||
T: RegisterAccess + Clone,
|
||||
TX: Tx,
|
||||
CH: ChannelTypes,
|
||||
{
|
||||
pub register_access: T,
|
||||
pub tx_channel: TX,
|
||||
pub tx_channel: CH::Tx<'d>,
|
||||
}
|
||||
|
||||
impl<T, TX> TxCreator<T, TX>
|
||||
impl<'d, T, CH> TxCreator<'d, T, CH>
|
||||
where
|
||||
T: RegisterAccess + Clone,
|
||||
TX: Tx,
|
||||
CH: ChannelTypes,
|
||||
{
|
||||
pub fn with_pins<P>(self, pins: P) -> I2sTx<T, P, TX>
|
||||
pub fn with_pins<P>(self, pins: P) -> I2sTx<'d, T, P, CH>
|
||||
where
|
||||
P: super::I2sTxPins,
|
||||
{
|
||||
@ -1035,21 +1022,21 @@ mod private {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RxCreator<T, RX>
|
||||
pub struct RxCreator<'d, T, CH>
|
||||
where
|
||||
T: RegisterAccess + Clone,
|
||||
RX: Rx,
|
||||
CH: ChannelTypes,
|
||||
{
|
||||
pub register_access: T,
|
||||
pub rx_channel: RX,
|
||||
pub rx_channel: CH::Rx<'d>,
|
||||
}
|
||||
|
||||
impl<T, RX> RxCreator<T, RX>
|
||||
impl<'d, T, CH> RxCreator<'d, T, CH>
|
||||
where
|
||||
T: RegisterAccess + Clone,
|
||||
RX: Rx,
|
||||
CH: ChannelTypes,
|
||||
{
|
||||
pub fn with_pins<P>(self, pins: P) -> I2sRx<T, P, RX>
|
||||
pub fn with_pins<P>(self, pins: P) -> I2sRx<'d, T, P, CH>
|
||||
where
|
||||
P: super::I2sRxPins,
|
||||
{
|
||||
@ -1061,14 +1048,15 @@ mod private {
|
||||
|
||||
pub trait I2s1Instance {}
|
||||
|
||||
pub trait Instance<R>
|
||||
where
|
||||
R: RegisterAccess,
|
||||
{
|
||||
fn register_access(&self) -> R;
|
||||
pub trait Instance {
|
||||
type Peripheral: RegisterAccess + Clone;
|
||||
|
||||
fn register_access(&self) -> Self::Peripheral;
|
||||
}
|
||||
|
||||
impl Instance<I2sPeripheral0> for I2S0 {
|
||||
impl Instance for I2S0 {
|
||||
type Peripheral = I2sPeripheral0;
|
||||
|
||||
fn register_access(&self) -> I2sPeripheral0 {
|
||||
I2sPeripheral0 {}
|
||||
}
|
||||
@ -1077,7 +1065,8 @@ mod private {
|
||||
impl I2s0Instance for I2S0 {}
|
||||
|
||||
#[cfg(esp32s3)]
|
||||
impl Instance<I2sPeripheral1> for crate::peripherals::I2S1 {
|
||||
impl Instance for crate::peripherals::I2S1 {
|
||||
type Peripheral = I2sPeripheral1;
|
||||
fn register_access(&self) -> I2sPeripheral1 {
|
||||
I2sPeripheral1 {}
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Interrupt support
|
||||
|
||||
#[cfg(riscv)]
|
||||
pub use riscv::*;
|
||||
#[cfg(xtensa)]
|
||||
|
||||
@ -69,7 +69,8 @@ pub enum InterruptKind {
|
||||
Edge,
|
||||
}
|
||||
|
||||
/// Enumeration of available CPU interrupts.
|
||||
/// Enumeration of available CPU interrupts
|
||||
///
|
||||
/// It is possible to create a handler for each of the interrupts. (e.g.
|
||||
/// `interrupt3`)
|
||||
#[repr(u32)]
|
||||
@ -531,7 +532,7 @@ pub fn _setup_interrupts() {
|
||||
}
|
||||
}
|
||||
|
||||
/// Disable the given peripheral interrupt.
|
||||
/// Disable the given peripheral interrupt
|
||||
pub fn disable(_core: Cpu, interrupt: Interrupt) {
|
||||
unsafe {
|
||||
let interrupt_number = interrupt as isize;
|
||||
@ -577,7 +578,7 @@ pub fn get_status(_core: Cpu) -> u128 {
|
||||
}
|
||||
}
|
||||
|
||||
/// Assign a peripheral interrupt to an CPU interrupt.
|
||||
/// Assign a peripheral interrupt to an CPU interrupt
|
||||
///
|
||||
/// Great care must be taken when using the `vectored` feature (enabled by
|
||||
/// default). Avoid interrupts 1 - 15 when interrupt vectoring is enabled.
|
||||
|
||||
@ -7,6 +7,7 @@ use crate::{
|
||||
};
|
||||
|
||||
/// Enumeration of available CPU interrupts
|
||||
///
|
||||
/// It's possible to create one handler per priority level. (e.g
|
||||
/// `level1_interrupt`)
|
||||
#[allow(unused)]
|
||||
@ -47,7 +48,7 @@ pub enum CpuInterrupt {
|
||||
Interrupt31EdgePriority5,
|
||||
}
|
||||
|
||||
/// Assign a peripheral interrupt to an CPU interrupt.
|
||||
/// Assign a peripheral interrupt to an CPU interrupt
|
||||
///
|
||||
/// Great care **must** be taken when using this function with interrupt
|
||||
/// vectoring (enabled by default). Avoid the following CPU interrupts:
|
||||
@ -73,7 +74,7 @@ pub unsafe fn map(core: Cpu, interrupt: Interrupt, which: CpuInterrupt) {
|
||||
.write_volatile(cpu_interrupt_number as u32);
|
||||
}
|
||||
|
||||
/// Disable the given peripheral interrupt.
|
||||
/// Disable the given peripheral interrupt
|
||||
pub fn disable(core: Cpu, interrupt: Interrupt) {
|
||||
unsafe {
|
||||
let interrupt_number = interrupt as isize;
|
||||
@ -264,6 +265,7 @@ mod vectored {
|
||||
}
|
||||
}
|
||||
|
||||
/// Enable the given peripheral interrupt
|
||||
pub fn enable(interrupt: Interrupt, level: Priority) -> Result<(), Error> {
|
||||
let cpu_interrupt =
|
||||
interrupt_level_to_cpu_interrupt(level, chip_specific::interrupt_is_edge(interrupt))?;
|
||||
|
||||
@ -50,8 +50,8 @@ pub use self::delay::Delay;
|
||||
pub use self::dma::gdma;
|
||||
#[cfg(pdma)]
|
||||
pub use self::dma::pdma;
|
||||
#[cfg(any(dport, interrupt_core0, interrupt_core1))]
|
||||
pub use self::interrupt::*;
|
||||
#[cfg(gpio)]
|
||||
pub use self::gpio::IO;
|
||||
#[cfg(rmt)]
|
||||
pub use self::pulse_control::PulseControl;
|
||||
#[cfg(rng)]
|
||||
@ -63,6 +63,8 @@ pub use self::soc::cpu_control;
|
||||
#[cfg(efuse)]
|
||||
pub use self::soc::efuse;
|
||||
pub use self::soc::peripherals;
|
||||
#[cfg(psram)]
|
||||
pub use self::soc::psram;
|
||||
#[cfg(any(spi0, spi1, spi2, spi3))]
|
||||
pub use self::spi::Spi;
|
||||
#[cfg(any(timg0, timg1))]
|
||||
@ -117,7 +119,6 @@ pub mod rsa;
|
||||
pub mod rtc_cntl;
|
||||
#[cfg(sha)]
|
||||
pub mod sha;
|
||||
pub mod soc;
|
||||
#[cfg(any(spi0, spi1, spi2, spi3))]
|
||||
pub mod spi;
|
||||
#[cfg(any(dport, pcr, system))]
|
||||
@ -141,6 +142,10 @@ pub mod trapframe {
|
||||
pub use xtensa_lx_rt::exception::Context as TrapFrame;
|
||||
}
|
||||
|
||||
// The `soc` module contains chip-specific implementation details and should not
|
||||
// be directly exposed.
|
||||
mod soc;
|
||||
|
||||
#[no_mangle]
|
||||
extern "C" fn EspDefaultHandler(_level: u32, _interrupt: peripherals::Interrupt) {}
|
||||
|
||||
@ -148,16 +153,8 @@ extern "C" fn EspDefaultHandler(_level: u32, _interrupt: peripherals::Interrupt)
|
||||
#[no_mangle]
|
||||
extern "C" fn DefaultHandler() {}
|
||||
|
||||
#[cfg(esp32c6)]
|
||||
pub fn disable_apm_filter() {
|
||||
unsafe {
|
||||
(&*esp32c6::LP_APM::PTR).func_ctrl.write(|w| w.bits(0));
|
||||
(&*esp32c6::LP_APM0::PTR).func_ctrl.write(|w| w.bits(0));
|
||||
(&*esp32c6::HP_APM::PTR).func_ctrl.write(|w| w.bits(0));
|
||||
}
|
||||
}
|
||||
|
||||
/// Enumeration of CPU cores
|
||||
/// Available CPU cores
|
||||
///
|
||||
/// The actual number of available cores depends on the target.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Cpu {
|
||||
@ -168,6 +165,7 @@ pub enum Cpu {
|
||||
AppCpu,
|
||||
}
|
||||
|
||||
/// Which core the application is currently executing on
|
||||
pub fn get_core() -> Cpu {
|
||||
#[cfg(all(xtensa, multi_core))]
|
||||
match ((xtensa_lx::get_processor_id() >> 13) & 1) != 0 {
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Pulse Counter peripheral driver
|
||||
|
||||
use self::unit::Unit;
|
||||
use crate::{
|
||||
peripheral::{Peripheral, PeripheralRef},
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Exclusive peripheral access
|
||||
|
||||
use core::{
|
||||
marker::PhantomData,
|
||||
ops::{Deref, DerefMut},
|
||||
@ -185,6 +187,7 @@ pub(crate) mod sealed {
|
||||
}
|
||||
|
||||
mod peripheral_macros {
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! peripherals {
|
||||
($($(#[$cfg:meta])? $name:ident => $from_pac:tt),*$(,)?) => {
|
||||
@ -247,6 +250,7 @@ mod peripheral_macros {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! into_ref {
|
||||
($($name:ident),*) => {
|
||||
@ -257,6 +261,7 @@ mod peripheral_macros {
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! create_peripheral {
|
||||
($(#[$cfg:meta])? $name:ident => true) => {
|
||||
|
||||
@ -70,7 +70,7 @@ pub use crate::pulse_control::{
|
||||
};
|
||||
#[cfg(radio)]
|
||||
pub use crate::radio::RadioExt as _esp_hal_RadioExt;
|
||||
#[cfg(any(esp32, esp32s2))]
|
||||
#[cfg(any(esp32, esp32s2, esp32s3))]
|
||||
pub use crate::spi::dma::WithDmaSpi3 as _esp_hal_spi_dma_WithDmaSpi3;
|
||||
#[cfg(any(spi0, spi1, spi2, spi3))]
|
||||
pub use crate::spi::{
|
||||
|
||||
@ -886,7 +886,7 @@ macro_rules! rmt {
|
||||
)+
|
||||
)
|
||||
=> {
|
||||
/// RMT peripheral (RMT)
|
||||
/// Remote Control (RMT) peripheral driver
|
||||
pub struct PulseControl<'d> {
|
||||
/// The underlying register block
|
||||
reg: PeripheralRef<'d, RMT>,
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Wireless communication peripheral implementations
|
||||
|
||||
pub trait RadioExt {
|
||||
type Components;
|
||||
|
||||
@ -68,17 +70,7 @@ impl crate::peripheral::Peripheral for LowRate {
|
||||
impl crate::peripheral::sealed::Sealed for LowRate {}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(any(esp32, esp32c2, esp32c3, esp32s3))] {
|
||||
impl RadioExt for crate::peripherals::RADIO {
|
||||
type Components = (Wifi, Bluetooth);
|
||||
|
||||
fn split(self) -> Self::Components {
|
||||
unsafe {
|
||||
(Wifi::steal(), Bluetooth::steal())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if #[cfg(esp32c6)] {
|
||||
if #[cfg(all(bt, ieee802154, wifi))] {
|
||||
impl RadioExt for crate::peripherals::RADIO {
|
||||
type Components = (Wifi, Bluetooth, LowRate);
|
||||
|
||||
@ -88,7 +80,27 @@ cfg_if::cfg_if! {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if #[cfg(esp32s2)] {
|
||||
} else if #[cfg(all(bt, ieee802154))] {
|
||||
impl RadioExt for crate::peripherals::RADIO {
|
||||
type Components = (Bluetooth, LowRate);
|
||||
|
||||
fn split(self) -> Self::Components {
|
||||
unsafe {
|
||||
(Bluetooth::steal(), LowRate::steal())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if #[cfg(all(bt, wifi))] {
|
||||
impl RadioExt for crate::peripherals::RADIO {
|
||||
type Components = (Wifi, Bluetooth);
|
||||
|
||||
fn split(self) -> Self::Components {
|
||||
unsafe {
|
||||
(Wifi::steal(), Bluetooth::steal())
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if #[cfg(wifi)] {
|
||||
impl RadioExt for crate::peripherals::RADIO {
|
||||
type Components = Wifi;
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Hardware and Software Reset
|
||||
|
||||
use crate::rtc_cntl::SocResetReason;
|
||||
|
||||
pub enum SleepSource {
|
||||
|
||||
@ -8,11 +8,11 @@
|
||||
//!
|
||||
//! The ROM provides the following polynomials for each CRC width:
|
||||
//!
|
||||
//! | CRC Width | Polynomial |
|
||||
//! | --------- | ---------- |
|
||||
//! | CRC-8 | 0x07 |
|
||||
//! | CRC-16 | 0x1021 |
|
||||
//! | CRC-32 | 0x0411db7 |
|
||||
//! | CRC Width | Polynomial |
|
||||
//! | --------- | ----------- |
|
||||
//! | CRC-8 | 0x07 |
|
||||
//! | CRC-16 | 0x1021 |
|
||||
//! | CRC-32 | 0x04c11db7 |
|
||||
//!
|
||||
//! The "big-endian" `*_be()` functions are left-shifting algorithms to be used
|
||||
//! when input and output reflection are **not** needed. If input and output
|
||||
@ -37,26 +37,35 @@
|
||||
//! <https://reveng.sourceforge.io/crc-catalogue/all.htm>
|
||||
//!
|
||||
//! CRC-32/ISO-HDLC poly=0x04c11db7 init=0xffffffff refin=true refout=true
|
||||
//! xorout=0xffffffff ```
|
||||
//! xorout=0xffffffff
|
||||
//!
|
||||
//! ```
|
||||
//! let crc = crc32_le(!0xffffffff, &data);
|
||||
//! ```
|
||||
//!
|
||||
//!
|
||||
//! CRC-32/BZIP2 poly=0x04c11db7 init=0xffffffff refin=false refout=false
|
||||
//! xorout=0xffffffff ```
|
||||
//! xorout=0xffffffff
|
||||
//!
|
||||
//! ```
|
||||
//! let crc = crc32_be(!0xffffffff, &data);
|
||||
//! ```
|
||||
//!
|
||||
//! CRC-32/MPEG-2 poly=0x04c11db7 init=0xffffffff refin=false refout=false
|
||||
//! xorout=0x00000000 ```
|
||||
//! xorout=0x00000000
|
||||
//!
|
||||
//! ```
|
||||
//! let crc = !crc32_be(!0xffffffff, &data);
|
||||
//! ```
|
||||
//!
|
||||
//!
|
||||
//! CRC-32/CKSUM poly=0x04c11db7 init=0x00000000 refin=false refout=false
|
||||
//! xorout=0xffffffff ```
|
||||
//! xorout=0xffffffff
|
||||
//!
|
||||
//! ```
|
||||
//! let crc = crc32_be(!0, &data);
|
||||
//! ```
|
||||
//!
|
||||
//! CRC-16/KERMIT poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000
|
||||
//!
|
||||
//! ```
|
||||
//! let crc = !crc16_le(!0, &data);
|
||||
//! ```
|
||||
@ -65,7 +74,7 @@
|
||||
// needed to access them, they are all referentially transparent, and the size
|
||||
// and alignment of `usize` and `u32` are identical on all ESP32 chips.
|
||||
|
||||
/// Left-shifting CRC-32 with polynomial 0x0411db7
|
||||
/// Left-shifting CRC-32 with polynomial 0x04c11db7
|
||||
#[cfg(rom_crc_be)]
|
||||
#[inline(always)]
|
||||
pub fn crc32_be(crc: u32, buf: &[u8]) -> u32 {
|
||||
@ -95,7 +104,7 @@ pub fn crc8_be(crc: u8, buf: &[u8]) -> u8 {
|
||||
unsafe { esp_rom_crc8_be(crc, buf.as_ptr(), buf.len() as u32) }
|
||||
}
|
||||
|
||||
/// Right-shifting CRC-32 with polynomial 0x0411db7
|
||||
/// Right-shifting CRC-32 with polynomial 0x04c11db7
|
||||
#[cfg(rom_crc_le)]
|
||||
#[inline(always)]
|
||||
pub fn crc32_le(crc: u32, buf: &[u8]) -> u32 {
|
||||
@ -208,7 +217,7 @@ static CRC8_BE_TABLE: [u8; 256] = [
|
||||
0xde, 0xd9, 0xd0, 0xd7, 0xc2, 0xc5, 0xcc, 0xcb, 0xe6, 0xe1, 0xe8, 0xef, 0xfa, 0xfd, 0xf4, 0xf3
|
||||
];
|
||||
|
||||
/// Left-shifting CRC-32 with polynomial 0x0411db7
|
||||
/// Left-shifting CRC-32 with polynomial 0x04c11db7
|
||||
#[cfg(not(rom_crc_be))]
|
||||
pub fn crc32_be(crc: u32, buf: &[u8]) -> u32 {
|
||||
let mut crc = !crc;
|
||||
@ -320,7 +329,7 @@ static CRC8_LE_TABLE: [u8; 256] = [
|
||||
0xb4, 0x25, 0x57, 0xc6, 0xb3, 0x22, 0x50, 0xc1, 0xba, 0x2b, 0x59, 0xc8, 0xbd, 0x2c, 0x5e, 0xcf
|
||||
];
|
||||
|
||||
/// Right-shifting CRC-32 with polynomial 0x0411db7
|
||||
/// Right-shifting CRC-32 with polynomial 0x04c11db7
|
||||
#[cfg(not(rom_crc_le))]
|
||||
pub fn crc32_le(crc: u32, buf: &[u8]) -> u32 {
|
||||
let mut crc = !crc;
|
||||
|
||||
232
esp-hal-common/src/rom/md5.rs
Normal file
232
esp-hal-common/src/rom/md5.rs
Normal file
@ -0,0 +1,232 @@
|
||||
//! MD5 Message-Digest Algorithm
|
||||
//!
|
||||
//! # Security Warning
|
||||
//!
|
||||
//! MD5 is a **cryptographically broken** message digest. It should **not**
|
||||
//! be used for data security, for example, to check if data has been
|
||||
//! intentionally tampered with.
|
||||
//!
|
||||
//! However, it is still very useful for purposes of data **integrity**, for
|
||||
//! example, to check if data has been **accidentally** tampered with, such as
|
||||
//! detecting data corrupted during transmission in a stream or stored in
|
||||
//! flash. This is especially important on microcontrollers where the
|
||||
//! computational efficiency of MD5 is desired.
|
||||
//!
|
||||
//! # Compatibility
|
||||
//!
|
||||
//! The public API exposed by this module tries to *mimic* the public API
|
||||
//! offered by the [MD5][1] crate in an effort to act as a drop-in replacement.
|
||||
//! The actual implementation, however, links to whatever is available in the
|
||||
//! ROM of the particular ESP32 target. Each chip target may offer a different
|
||||
//! underlying MD5 implementation with varying functionality.
|
||||
//!
|
||||
//! This module offers a least-common-denominator API to stay consistent with
|
||||
//! all of them. Usage of this module may help make program binaries smaller
|
||||
//! than it would be if you included an MD5 implementation in your project.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! To compute a full digest from a single buffer, use the following:
|
||||
//!
|
||||
//! ```
|
||||
//! let d: md5::Digest = md5::compute(&data);
|
||||
//! writeln!(uart0, "{}", d);
|
||||
//! ```
|
||||
//!
|
||||
//! To compute a digest over multiple buffers:
|
||||
//!
|
||||
//! ```
|
||||
//! let mut ctx = md5::Context::new();
|
||||
//! ctx.consume(&data0);
|
||||
//! ctx.consume(&data1);
|
||||
//! let d: md5::Digest = ctx.compute();
|
||||
//! writeln!(uart0, "{}", d);
|
||||
//! ```
|
||||
//!
|
||||
//! [1]: <https://crates.io/crates/md5>
|
||||
|
||||
#[allow(unused)]
|
||||
use core::ffi::{c_int, c_uchar, c_void};
|
||||
use core::{
|
||||
convert::From,
|
||||
fmt,
|
||||
mem::MaybeUninit,
|
||||
ops::{Deref, DerefMut},
|
||||
};
|
||||
|
||||
// If there is not exactly one of the MD5 variations defined in the device
|
||||
// toml file then `InternalContext` will be either undefined or multiple
|
||||
// defined and this module will fail to compile letting you know to fix it
|
||||
|
||||
#[cfg(doc)]
|
||||
struct InternalContext;
|
||||
|
||||
#[cfg(rom_md5_bsd)]
|
||||
#[derive(Clone)]
|
||||
#[repr(C)]
|
||||
struct InternalContext {
|
||||
buf: [u32; 4],
|
||||
bits: [u32; 2],
|
||||
_in: [u8; 64],
|
||||
}
|
||||
|
||||
#[cfg(rom_md5_bsd)]
|
||||
extern "C" {
|
||||
fn esp_rom_md5_init(context: *mut InternalContext);
|
||||
fn esp_rom_md5_update(context: *mut InternalContext, buf: *const c_void, len: u32);
|
||||
fn esp_rom_md5_final(digest: *mut u8, context: *mut InternalContext);
|
||||
}
|
||||
|
||||
#[cfg(rom_md5_mbedtls)]
|
||||
#[derive(Clone)]
|
||||
#[repr(C)]
|
||||
struct InternalContext {
|
||||
total: [u32; 2],
|
||||
state: [u32; 4],
|
||||
buffer: [c_uchar; 64],
|
||||
}
|
||||
|
||||
#[cfg(rom_md5_mbedtls)]
|
||||
extern "C" {
|
||||
fn esp_rom_mbedtls_md5_starts_ret(context: *mut InternalContext) -> c_int;
|
||||
fn esp_rom_mbedtls_md5_update_ret(
|
||||
context: *mut InternalContext,
|
||||
buf: *const c_void,
|
||||
len: u32,
|
||||
) -> c_int;
|
||||
fn esp_rom_mbedtls_md5_finish_ret(context: *mut InternalContext, digest: *mut u8) -> c_int;
|
||||
}
|
||||
|
||||
/// MD5 context for an ongoing computation
|
||||
#[derive(Clone)]
|
||||
pub struct Context(InternalContext);
|
||||
|
||||
impl Context {
|
||||
/// Create a new MD5 context
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
let mut ctx = MaybeUninit::<InternalContext>::uninit();
|
||||
unsafe {
|
||||
#[cfg(rom_md5_bsd)]
|
||||
esp_rom_md5_init(ctx.as_mut_ptr());
|
||||
|
||||
#[cfg(rom_md5_mbedtls)]
|
||||
let _ = esp_rom_mbedtls_md5_starts_ret(ctx.as_mut_ptr());
|
||||
|
||||
Self(ctx.assume_init())
|
||||
}
|
||||
}
|
||||
|
||||
/// Feed data to the hasher
|
||||
#[inline]
|
||||
pub fn consume<T: AsRef<[u8]>>(&mut self, data: T) {
|
||||
let data = data.as_ref();
|
||||
unsafe {
|
||||
#[cfg(rom_md5_bsd)]
|
||||
esp_rom_md5_update(
|
||||
&mut self.0 as *mut _,
|
||||
data.as_ptr() as *const c_void,
|
||||
data.len() as u32,
|
||||
);
|
||||
|
||||
#[cfg(rom_md5_mbedtls)]
|
||||
let _ = esp_rom_mbedtls_md5_update_ret(
|
||||
&mut self.0 as *mut _,
|
||||
data.as_ptr() as *const c_void,
|
||||
data.len() as u32,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Finalize and return a digest
|
||||
#[inline]
|
||||
pub fn compute(mut self) -> Digest {
|
||||
let mut digest = MaybeUninit::<[u8; 16]>::uninit();
|
||||
unsafe {
|
||||
#[cfg(rom_md5_bsd)]
|
||||
esp_rom_md5_final(digest.as_mut_ptr() as *mut _, &mut self.0 as *mut _);
|
||||
|
||||
#[cfg(rom_md5_mbedtls)]
|
||||
let _ = esp_rom_mbedtls_md5_finish_ret(
|
||||
&mut self.0 as *mut _,
|
||||
digest.as_mut_ptr() as *mut _,
|
||||
);
|
||||
|
||||
Digest(digest.assume_init())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Compute a full digest from a single buffer
|
||||
#[inline]
|
||||
pub fn compute<T: AsRef<[u8]>>(data: T) -> Digest {
|
||||
let mut ctx = Context::new();
|
||||
ctx.consume(data);
|
||||
ctx.compute()
|
||||
}
|
||||
|
||||
/// 16-byte message digest
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct Digest(pub [u8; 16]);
|
||||
|
||||
impl fmt::LowerHex for Digest {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for &byte in &self.0 {
|
||||
write!(f, "{:02x}", byte)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::UpperHex for Digest {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for &byte in &self.0 {
|
||||
write!(f, "{:02X}", byte)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for Digest {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
<Digest as fmt::LowerHex>::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Digest {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
<Digest as fmt::LowerHex>::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Digest> for [u8; 16] {
|
||||
#[inline]
|
||||
fn from(digest: Digest) -> Self {
|
||||
digest.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Context> for Digest {
|
||||
#[inline]
|
||||
fn from(context: Context) -> Digest {
|
||||
context.compute()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for Digest {
|
||||
type Target = [u8; 16];
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for Digest {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.0
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,10 @@
|
||||
pub use paste::paste;
|
||||
//! ESP ROM libraries
|
||||
//!
|
||||
//! Safe abstractions to the additional libraries provided in the ESP's
|
||||
//! read-only memory.
|
||||
|
||||
pub mod crc;
|
||||
pub mod md5;
|
||||
|
||||
#[allow(unused)]
|
||||
extern "C" {
|
||||
@ -16,6 +20,7 @@ extern "C" {
|
||||
);
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! regi2c_write {
|
||||
( $block: ident, $reg_add: ident, $indata: expr ) => {
|
||||
@ -29,6 +34,7 @@ macro_rules! regi2c_write {
|
||||
};
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! regi2c_write_mask {
|
||||
( $block: ident, $reg_add: ident, $indata: expr ) => {
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Low-power Management
|
||||
|
||||
use embedded_hal::watchdog::{Watchdog, WatchdogDisable, WatchdogEnable};
|
||||
#[cfg(not(any(esp32c6, esp32h2)))]
|
||||
use fugit::HertzU32;
|
||||
@ -116,6 +118,7 @@ pub(crate) enum RtcCalSel {
|
||||
RtcCalInternalOsc = 3,
|
||||
}
|
||||
|
||||
/// Low-power Management
|
||||
pub struct Rtc<'d> {
|
||||
_inner: PeripheralRef<'d, RtcCntl>,
|
||||
pub rwdt: Rwdt,
|
||||
|
||||
@ -646,6 +646,8 @@ impl RtcClock {
|
||||
let minor: u8 = Efuse::read_field_le(WAFER_VERSION_MINOR);
|
||||
let major: u8 = Efuse::read_field_le(WAFER_VERSION_MAJOR);
|
||||
|
||||
let mut slowclk_cycles = slowclk_cycles;
|
||||
|
||||
// The Fosc CLK of calibration circuit is divided by 32 for ECO1.
|
||||
// So we need to divide the calibrate cycles of the FOSC for ECO1 and above
|
||||
// chips by 32 to avoid excessive calibration time.*/
|
||||
@ -654,7 +656,7 @@ impl RtcClock {
|
||||
// formula: MAJOR * 100 + MINOR. (if the result is 1, then version is v0.1)
|
||||
if (major * 100 + minor) > 0 {
|
||||
if cal_clk == RtcCalSel::RtcCalRcFast {
|
||||
let slowclk_cycles = slowclk_cycles >> 5;
|
||||
slowclk_cycles >>= 5;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Secure Hash Algorithm peripheral driver
|
||||
|
||||
use core::convert::Infallible;
|
||||
|
||||
use crate::{
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Peripheral instance singletons
|
||||
|
||||
use esp32 as pac;
|
||||
// We need to export this for users to use
|
||||
pub use pac::Interrupt;
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
const PSRAM_VADDR: u32 = 0x3F800000;
|
||||
|
||||
pub fn psram_vaddr_start() -> usize {
|
||||
unsafe { PSRAM_VADDR_START as usize }
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "psram_2m")] {
|
||||
const PSRAM_SIZE: u32 = 2;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Peripheral instance singletons
|
||||
|
||||
use esp32c2 as pac;
|
||||
// We need to export this for users to use
|
||||
pub use pac::Interrupt;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Peripheral instance singletons
|
||||
|
||||
use esp32c3 as pac;
|
||||
// We need to export this for users to use
|
||||
pub use pac::Interrupt;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Peripheral instance singletons
|
||||
|
||||
use esp32c6 as pac;
|
||||
// We need to export this for users to use
|
||||
pub use pac::Interrupt;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Peripheral instance singletons
|
||||
|
||||
use esp32h2 as pac;
|
||||
// We need to export this for users to use
|
||||
pub use pac::Interrupt;
|
||||
@ -10,13 +12,13 @@ crate::peripherals! {
|
||||
APB_SARADC => true,
|
||||
ASSIST_DEBUG => true,
|
||||
DMA => true,
|
||||
// DS => true,
|
||||
// ECC => true,
|
||||
DS => true,
|
||||
ECC => true,
|
||||
EFUSE => true,
|
||||
GPIO => true,
|
||||
// HMAC => true,
|
||||
// HP_APM => true,
|
||||
// HP_SYS => true,
|
||||
HMAC => true,
|
||||
HP_APM => true,
|
||||
HP_SYS => true,
|
||||
I2C0 => true,
|
||||
I2C1 => true,
|
||||
I2S0 => true,
|
||||
@ -24,20 +26,20 @@ crate::peripherals! {
|
||||
INTPRI => true,
|
||||
IO_MUX => true,
|
||||
LEDC => true,
|
||||
// LP_ANA => true,
|
||||
// LP_AON => true,
|
||||
// LP_APM => true,
|
||||
LP_ANA => true,
|
||||
LP_AON => true,
|
||||
LP_APM => true,
|
||||
LP_CLKRST => true,
|
||||
// LP_PERI => true,
|
||||
// LP_TIMER => true,
|
||||
LP_PERI => true,
|
||||
LP_TIMER => true,
|
||||
LP_WDT => true,
|
||||
MCPWM0 => true,
|
||||
MEM_MONITOR => true,
|
||||
MODEM_LPCON => true,
|
||||
MODEM_SYSCON => true,
|
||||
// OTP_DEBUG => true,
|
||||
// PARL_IO => true,
|
||||
// PAU => true,
|
||||
OTP_DEBUG => true,
|
||||
PARL_IO => true,
|
||||
PAU => true,
|
||||
PCNT => true,
|
||||
PCR => true,
|
||||
PMU => true,
|
||||
@ -45,19 +47,19 @@ crate::peripherals! {
|
||||
RNG => true,
|
||||
RSA => true,
|
||||
SHA => true,
|
||||
// SOC_ETM => true,
|
||||
SOC_ETM => true,
|
||||
SPI0 => true,
|
||||
SPI1 => true,
|
||||
SPI2 => true,
|
||||
SYSTIMER => true,
|
||||
// TEE => true,
|
||||
TEE => true,
|
||||
TIMG0 => true,
|
||||
TIMG1 => true,
|
||||
// TRACE => true,
|
||||
// TWAI0 => true,
|
||||
TRACE => true,
|
||||
TWAI0 => true,
|
||||
UART0 => true,
|
||||
UART1 => true,
|
||||
// UHCI0 => true,
|
||||
UHCI0 => true,
|
||||
USB_DEVICE => true,
|
||||
RADIO => false,
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Peripheral instance singletons
|
||||
|
||||
use esp32s2 as pac;
|
||||
// We need to export this for users to use
|
||||
pub use pac::Interrupt;
|
||||
|
||||
@ -1,5 +1,9 @@
|
||||
const PSRAM_VADDR: u32 = 0x3f500000;
|
||||
|
||||
pub fn psram_vaddr_start() -> usize {
|
||||
unsafe { PSRAM_VADDR_START as usize }
|
||||
}
|
||||
|
||||
cfg_if::cfg_if! {
|
||||
if #[cfg(feature = "psram_2m")] {
|
||||
const PSRAM_SIZE: u32 = 2;
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! Peripheral instance singletons
|
||||
|
||||
use esp32s3 as pac;
|
||||
// We need to export this for users to use
|
||||
pub use pac::Interrupt;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -411,6 +411,7 @@ pub trait HalfDuplexReadWrite {
|
||||
) -> Result<(), Self::Error>;
|
||||
}
|
||||
|
||||
/// SPI peripheral driver
|
||||
pub struct Spi<'d, T, M> {
|
||||
spi: PeripheralRef<'d, T>,
|
||||
_mode: PhantomData<M>,
|
||||
@ -752,42 +753,48 @@ pub mod dma {
|
||||
use crate::dma::Spi3Peripheral;
|
||||
use crate::{
|
||||
clock::Clocks,
|
||||
dma::{Channel, DmaTransfer, DmaTransferRxTx, Rx, Spi2Peripheral, SpiPeripheral, Tx},
|
||||
dma::{
|
||||
Channel,
|
||||
ChannelTypes,
|
||||
DmaTransfer,
|
||||
DmaTransferRxTx,
|
||||
RxPrivate,
|
||||
Spi2Peripheral,
|
||||
SpiPeripheral,
|
||||
TxPrivate,
|
||||
},
|
||||
peripheral::PeripheralRef,
|
||||
};
|
||||
|
||||
pub trait WithDmaSpi2<'d, T, RX, TX, P, M>
|
||||
pub trait WithDmaSpi2<'d, T, C, M>
|
||||
where
|
||||
T: Instance + Spi2Instance,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: DuplexMode,
|
||||
{
|
||||
fn with_dma(self, channel: Channel<TX, RX, P>) -> SpiDma<'d, T, TX, RX, P, M>;
|
||||
fn with_dma(self, channel: Channel<'d, C>) -> SpiDma<'d, T, C, M>;
|
||||
}
|
||||
|
||||
#[cfg(any(esp32, esp32s2, esp32s3))]
|
||||
pub trait WithDmaSpi3<'d, T, RX, TX, P, M>
|
||||
pub trait WithDmaSpi3<'d, T, C, M>
|
||||
where
|
||||
T: Instance + Spi3Instance,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: DuplexMode,
|
||||
{
|
||||
fn with_dma(self, channel: Channel<TX, RX, P>) -> SpiDma<'d, T, TX, RX, P, M>;
|
||||
fn with_dma(self, channel: Channel<'d, C>) -> SpiDma<'d, T, C, M>;
|
||||
}
|
||||
|
||||
impl<'d, T, RX, TX, P, M> WithDmaSpi2<'d, T, RX, TX, P, M> for Spi<'d, T, M>
|
||||
impl<'d, T, C, M> WithDmaSpi2<'d, T, C, M> for Spi<'d, T, M>
|
||||
where
|
||||
T: Instance + Spi2Instance,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral + Spi2Peripheral,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral + Spi2Peripheral,
|
||||
M: DuplexMode,
|
||||
{
|
||||
fn with_dma(self, mut channel: Channel<TX, RX, P>) -> SpiDma<'d, T, TX, RX, P, M> {
|
||||
fn with_dma(self, mut channel: Channel<'d, C>) -> SpiDma<'d, T, C, M> {
|
||||
channel.tx.init_channel(); // no need to call this for both, TX and RX
|
||||
|
||||
SpiDma {
|
||||
@ -799,51 +806,47 @@ pub mod dma {
|
||||
}
|
||||
|
||||
#[cfg(any(esp32, esp32s2, esp32s3))]
|
||||
impl<'d, T, RX, TX, P, M> WithDmaSpi3<'d, T, RX, TX, P, M> for Spi<'d, T, M>
|
||||
impl<'d, T, C, M> WithDmaSpi3<'d, T, C, M> for Spi<'d, T, M>
|
||||
where
|
||||
T: Instance + Spi3Instance,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral + Spi3Peripheral,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral + Spi3Peripheral,
|
||||
M: DuplexMode,
|
||||
{
|
||||
fn with_dma(self, mut channel: Channel<TX, RX, P>) -> SpiDma<'d, T, TX, RX, P, M> {
|
||||
fn with_dma(self, mut channel: Channel<'d, C>) -> SpiDma<'d, T, C, M> {
|
||||
channel.tx.init_channel(); // no need to call this for both, TX and RX
|
||||
|
||||
SpiDma {
|
||||
spi: self.spi,
|
||||
channel,
|
||||
_mode: PhantomData::default(),
|
||||
_mode: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
/// An in-progress DMA transfer
|
||||
pub struct SpiDmaTransferRxTx<'d, T, TX, RX, P, RBUFFER, TBUFFER, M>
|
||||
pub struct SpiDmaTransferRxTx<'d, T, C, RBUFFER, TBUFFER, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: DuplexMode,
|
||||
{
|
||||
spi_dma: SpiDma<'d, T, TX, RX, P, M>,
|
||||
spi_dma: SpiDma<'d, T, C, M>,
|
||||
rbuffer: RBUFFER,
|
||||
tbuffer: TBUFFER,
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, RXBUF, TXBUF, M>
|
||||
DmaTransferRxTx<RXBUF, TXBUF, SpiDma<'d, T, TX, RX, P, M>>
|
||||
for SpiDmaTransferRxTx<'d, T, TX, RX, P, RXBUF, TXBUF, M>
|
||||
impl<'d, T, C, RXBUF, TXBUF, M> DmaTransferRxTx<RXBUF, TXBUF, SpiDma<'d, T, C, M>>
|
||||
for SpiDmaTransferRxTx<'d, T, C, RXBUF, TXBUF, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: DuplexMode,
|
||||
{
|
||||
/// Wait for the DMA transfer to complete and return the buffers and the
|
||||
/// SPI instance.
|
||||
fn wait(mut self) -> (RXBUF, TXBUF, SpiDma<'d, T, TX, RX, P, M>) {
|
||||
fn wait(mut self) -> (RXBUF, TXBUF, SpiDma<'d, T, C, M>) {
|
||||
self.spi_dma.spi.flush().ok(); // waiting for the DMA transfer is not enough
|
||||
|
||||
// `DmaTransfer` needs to have a `Drop` implementation, because we accept
|
||||
@ -869,13 +872,11 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, RXBUF, TXBUF, M> Drop
|
||||
for SpiDmaTransferRxTx<'d, T, TX, RX, P, RXBUF, TXBUF, M>
|
||||
impl<'d, T, C, RXBUF, TXBUF, M> Drop for SpiDmaTransferRxTx<'d, T, C, RXBUF, TXBUF, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: DuplexMode,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
@ -884,30 +885,28 @@ pub mod dma {
|
||||
}
|
||||
|
||||
/// An in-progress DMA transfer.
|
||||
pub struct SpiDmaTransfer<'d, T, TX, RX, P, BUFFER, M>
|
||||
pub struct SpiDmaTransfer<'d, T, C, BUFFER, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: DuplexMode,
|
||||
{
|
||||
spi_dma: SpiDma<'d, T, TX, RX, P, M>,
|
||||
spi_dma: SpiDma<'d, T, C, M>,
|
||||
buffer: BUFFER,
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, BUFFER, M> DmaTransfer<BUFFER, SpiDma<'d, T, TX, RX, P, M>>
|
||||
for SpiDmaTransfer<'d, T, TX, RX, P, BUFFER, M>
|
||||
impl<'d, T, C, BUFFER, M> DmaTransfer<BUFFER, SpiDma<'d, T, C, M>>
|
||||
for SpiDmaTransfer<'d, T, C, BUFFER, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: DuplexMode,
|
||||
{
|
||||
/// Wait for the DMA transfer to complete and return the buffers and the
|
||||
/// SPI instance.
|
||||
fn wait(mut self) -> (BUFFER, SpiDma<'d, T, TX, RX, P, M>) {
|
||||
fn wait(mut self) -> (BUFFER, SpiDma<'d, T, C, M>) {
|
||||
self.spi_dma.spi.flush().ok(); // waiting for the DMA transfer is not enough
|
||||
|
||||
// `DmaTransfer` needs to have a `Drop` implementation, because we accept
|
||||
@ -932,12 +931,11 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, BUFFER, M> Drop for SpiDmaTransfer<'d, T, TX, RX, P, BUFFER, M>
|
||||
impl<'d, T, C, BUFFER, M> Drop for SpiDmaTransfer<'d, T, C, BUFFER, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: DuplexMode,
|
||||
{
|
||||
fn drop(&mut self) {
|
||||
@ -946,24 +944,22 @@ pub mod dma {
|
||||
}
|
||||
|
||||
/// A DMA capable SPI instance.
|
||||
pub struct SpiDma<'d, T, TX, RX, P, M>
|
||||
pub struct SpiDma<'d, T, C, M>
|
||||
where
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: DuplexMode,
|
||||
{
|
||||
pub(crate) spi: PeripheralRef<'d, T>,
|
||||
pub(crate) channel: Channel<TX, RX, P>,
|
||||
pub(crate) channel: Channel<'d, C>,
|
||||
_mode: PhantomData<M>,
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, M> SpiDma<'d, T, TX, RX, P, M>
|
||||
impl<'d, T, C, M> SpiDma<'d, T, C, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: DuplexMode,
|
||||
{
|
||||
pub fn change_bus_frequency(&mut self, frequency: HertzU32, clocks: &Clocks) {
|
||||
@ -971,12 +967,11 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, M> SpiDma<'d, T, TX, RX, P, M>
|
||||
impl<'d, T, C, M> SpiDma<'d, T, C, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: IsFullDuplex,
|
||||
{
|
||||
/// Perform a DMA write.
|
||||
@ -987,7 +982,7 @@ pub mod dma {
|
||||
pub fn dma_write<TXBUF>(
|
||||
mut self,
|
||||
words: TXBUF,
|
||||
) -> Result<SpiDmaTransfer<'d, T, TX, RX, P, TXBUF, M>, super::Error>
|
||||
) -> Result<SpiDmaTransfer<'d, T, C, TXBUF, M>, super::Error>
|
||||
where
|
||||
TXBUF: ReadBuffer<Word = u8>,
|
||||
{
|
||||
@ -1013,7 +1008,7 @@ pub mod dma {
|
||||
pub fn dma_read<RXBUF>(
|
||||
mut self,
|
||||
mut words: RXBUF,
|
||||
) -> Result<SpiDmaTransfer<'d, T, TX, RX, P, RXBUF, M>, super::Error>
|
||||
) -> Result<SpiDmaTransfer<'d, T, C, RXBUF, M>, super::Error>
|
||||
where
|
||||
RXBUF: WriteBuffer<Word = u8>,
|
||||
{
|
||||
@ -1040,7 +1035,7 @@ pub mod dma {
|
||||
mut self,
|
||||
words: TXBUF,
|
||||
mut read_buffer: RXBUF,
|
||||
) -> Result<SpiDmaTransferRxTx<'d, T, TX, RX, P, RXBUF, TXBUF, M>, super::Error>
|
||||
) -> Result<SpiDmaTransferRxTx<'d, T, C, RXBUF, TXBUF, M>, super::Error>
|
||||
where
|
||||
TXBUF: ReadBuffer<Word = u8>,
|
||||
RXBUF: WriteBuffer<Word = u8>,
|
||||
@ -1068,12 +1063,11 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, M> SpiDma<'d, T, TX, RX, P, M>
|
||||
impl<'d, T, C, M> SpiDma<'d, T, C, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: IsHalfDuplex,
|
||||
{
|
||||
pub fn read<RXBUF>(
|
||||
@ -1083,7 +1077,7 @@ pub mod dma {
|
||||
address: Address,
|
||||
dummy: u8,
|
||||
mut buffer: RXBUF,
|
||||
) -> Result<SpiDmaTransfer<'d, T, TX, RX, P, RXBUF, M>, super::Error>
|
||||
) -> Result<SpiDmaTransfer<'d, T, C, RXBUF, M>, super::Error>
|
||||
where
|
||||
RXBUF: WriteBuffer<Word = u8>,
|
||||
{
|
||||
@ -1156,7 +1150,7 @@ pub mod dma {
|
||||
address: Address,
|
||||
dummy: u8,
|
||||
buffer: TXBUF,
|
||||
) -> Result<SpiDmaTransfer<'d, T, TX, RX, P, TXBUF, M>, super::Error>
|
||||
) -> Result<SpiDmaTransfer<'d, T, C, TXBUF, M>, super::Error>
|
||||
where
|
||||
TXBUF: ReadBuffer<Word = u8>,
|
||||
{
|
||||
@ -1223,12 +1217,11 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, M> embedded_hal::blocking::spi::Transfer<u8> for SpiDma<'d, T, TX, RX, P, M>
|
||||
impl<'d, T, C, M> embedded_hal::blocking::spi::Transfer<u8> for SpiDma<'d, T, C, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: IsFullDuplex,
|
||||
{
|
||||
type Error = super::Error;
|
||||
@ -1239,12 +1232,11 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, M> embedded_hal::blocking::spi::Write<u8> for SpiDma<'d, T, TX, RX, P, M>
|
||||
impl<'d, T, C, M> embedded_hal::blocking::spi::Write<u8> for SpiDma<'d, T, C, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: IsFullDuplex,
|
||||
{
|
||||
type Error = super::Error;
|
||||
@ -1260,12 +1252,11 @@ pub mod dma {
|
||||
mod asynch {
|
||||
use super::*;
|
||||
|
||||
impl<'d, T, TX, RX, P, M> embedded_hal_async::spi::SpiBusWrite for SpiDma<'d, T, TX, RX, P, M>
|
||||
impl<'d, T, C, M> embedded_hal_async::spi::SpiBusWrite for SpiDma<'d, T, C, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: IsFullDuplex,
|
||||
{
|
||||
async fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
|
||||
@ -1287,12 +1278,11 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, M> embedded_hal_async::spi::SpiBusFlush for SpiDma<'d, T, TX, RX, P, M>
|
||||
impl<'d, T, C, M> embedded_hal_async::spi::SpiBusFlush for SpiDma<'d, T, C, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: IsFullDuplex,
|
||||
{
|
||||
async fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
@ -1301,12 +1291,11 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, M> embedded_hal_async::spi::SpiBusRead for SpiDma<'d, T, TX, RX, P, M>
|
||||
impl<'d, T, C, M> embedded_hal_async::spi::SpiBusRead for SpiDma<'d, T, C, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: IsFullDuplex,
|
||||
{
|
||||
async fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
|
||||
@ -1322,12 +1311,11 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, M> embedded_hal_async::spi::SpiBus for SpiDma<'d, T, TX, RX, P, M>
|
||||
impl<'d, T, C, M> embedded_hal_async::spi::SpiBus for SpiDma<'d, T, C, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: IsFullDuplex,
|
||||
{
|
||||
async fn transfer<'a>(
|
||||
@ -1406,28 +1394,23 @@ pub mod dma {
|
||||
use embedded_hal_1::spi::{SpiBus, SpiBusFlush, SpiBusRead, SpiBusWrite};
|
||||
|
||||
use super::{super::InstanceDma, SpiDma, SpiPeripheral};
|
||||
use crate::{
|
||||
dma::{Rx, Tx},
|
||||
spi::IsFullDuplex,
|
||||
};
|
||||
use crate::{dma::ChannelTypes, spi::IsFullDuplex};
|
||||
|
||||
impl<'d, T, TX, RX, P, M> embedded_hal_1::spi::ErrorType for SpiDma<'d, T, TX, RX, P, M>
|
||||
impl<'d, T, C, M> embedded_hal_1::spi::ErrorType for SpiDma<'d, T, C, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: IsFullDuplex,
|
||||
{
|
||||
type Error = super::super::Error;
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, M> SpiBusWrite for SpiDma<'d, T, TX, RX, P, M>
|
||||
impl<'d, T, C, M> SpiBusWrite for SpiDma<'d, T, C, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: IsFullDuplex,
|
||||
{
|
||||
/// See also: [`write_bytes`].
|
||||
@ -1437,12 +1420,11 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, M> SpiBusRead for SpiDma<'d, T, TX, RX, P, M>
|
||||
impl<'d, T, C, M> SpiBusRead for SpiDma<'d, T, C, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: IsFullDuplex,
|
||||
{
|
||||
fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
|
||||
@ -1452,12 +1434,11 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, M> SpiBus for SpiDma<'d, T, TX, RX, P, M>
|
||||
impl<'d, T, C, M> SpiBus for SpiDma<'d, T, C, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: IsFullDuplex,
|
||||
{
|
||||
/// Write out data from `write`, read response into `read`.
|
||||
@ -1490,12 +1471,11 @@ pub mod dma {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, T, TX, RX, P, M> SpiBusFlush for SpiDma<'d, T, TX, RX, P, M>
|
||||
impl<'d, T, C, M> SpiBusFlush for SpiDma<'d, T, C, M>
|
||||
where
|
||||
T: InstanceDma<TX, RX>,
|
||||
TX: Tx,
|
||||
RX: Rx,
|
||||
P: SpiPeripheral,
|
||||
T: InstanceDma<C::Tx<'d>, C::Rx<'d>>,
|
||||
C: ChannelTypes,
|
||||
C::P: SpiPeripheral,
|
||||
M: IsFullDuplex,
|
||||
{
|
||||
fn flush(&mut self) -> Result<(), Self::Error> {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
//! System
|
||||
//! System Control
|
||||
//!
|
||||
//! The SYSTEM/DPORT peripheral needs to be split into several logical parts.
|
||||
//!
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! System Timer peripheral driver
|
||||
|
||||
use core::{intrinsics::transmute, marker::PhantomData};
|
||||
|
||||
use fugit::MillisDurationU32;
|
||||
|
||||
@ -188,13 +188,12 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// General-purpose timer
|
||||
/// General-purpose Timer driver
|
||||
pub struct Timer<T> {
|
||||
timg: T,
|
||||
apb_clk_freq: HertzU32,
|
||||
}
|
||||
|
||||
/// Timer driver
|
||||
impl<T> Timer<T>
|
||||
where
|
||||
T: Instance,
|
||||
|
||||
@ -19,7 +19,10 @@ const UART_FIFO_SIZE: u16 = 128;
|
||||
|
||||
/// Custom serial error type
|
||||
#[derive(Debug)]
|
||||
pub enum Error {}
|
||||
pub enum Error {
|
||||
#[cfg(feature = "async")]
|
||||
ReadBufferFull,
|
||||
}
|
||||
|
||||
/// UART configuration
|
||||
pub mod config {
|
||||
@ -994,11 +997,15 @@ mod asynch {
|
||||
use core::task::Poll;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
use embassy_futures::select::select;
|
||||
use embassy_sync::waitqueue::AtomicWaker;
|
||||
use procmacros::interrupt;
|
||||
|
||||
use super::{Error, Instance};
|
||||
use crate::{uart::UART_FIFO_SIZE, Uart};
|
||||
use crate::{
|
||||
uart::{RegisterBlock, UART_FIFO_SIZE},
|
||||
Uart,
|
||||
};
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(all(uart0, uart1, uart2))] {
|
||||
@ -1016,6 +1023,8 @@ mod asynch {
|
||||
pub(crate) enum Event {
|
||||
TxDone,
|
||||
TxFiFoEmpty,
|
||||
RxFifoFull,
|
||||
RxCmdCharDetected,
|
||||
}
|
||||
|
||||
pub(crate) struct UartFuture<'a, T: Instance> {
|
||||
@ -1034,6 +1043,14 @@ mod asynch {
|
||||
.register_block()
|
||||
.int_ena
|
||||
.modify(|_, w| w.txfifo_empty_int_ena().set_bit()),
|
||||
Event::RxFifoFull => instance
|
||||
.register_block()
|
||||
.int_ena
|
||||
.modify(|_, w| w.rxfifo_full_int_ena().set_bit()),
|
||||
Event::RxCmdCharDetected => instance
|
||||
.register_block()
|
||||
.int_ena
|
||||
.modify(|_, w| w.at_cmd_char_det_int_ena().set_bit()),
|
||||
}
|
||||
|
||||
Self { event, instance }
|
||||
@ -1055,6 +1072,20 @@ mod asynch {
|
||||
.read()
|
||||
.txfifo_empty_int_ena()
|
||||
.bit_is_clear(),
|
||||
Event::RxFifoFull => self
|
||||
.instance
|
||||
.register_block()
|
||||
.int_ena
|
||||
.read()
|
||||
.rxfifo_full_int_ena()
|
||||
.bit_is_clear(),
|
||||
Event::RxCmdCharDetected => self
|
||||
.instance
|
||||
.register_block()
|
||||
.int_ena
|
||||
.read()
|
||||
.at_cmd_char_det_int_ena()
|
||||
.bit_is_clear(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1079,11 +1110,42 @@ mod asynch {
|
||||
where
|
||||
T: Instance,
|
||||
{
|
||||
async fn write(&mut self, words: &[u8]) -> Result<(), Error> {
|
||||
for chunk in words.chunks(UART_FIFO_SIZE as usize) {
|
||||
for &byte in chunk {
|
||||
self.write_byte(byte).unwrap() // should never fail
|
||||
pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
let mut read_bytes = 0;
|
||||
|
||||
select(
|
||||
UartFuture::new(Event::RxCmdCharDetected, self.inner()),
|
||||
UartFuture::new(Event::RxFifoFull, self.inner()),
|
||||
)
|
||||
.await;
|
||||
|
||||
while let Ok(byte) = self.read_byte() {
|
||||
if read_bytes < buf.len() {
|
||||
buf[read_bytes] = byte;
|
||||
read_bytes += 1;
|
||||
} else {
|
||||
return Err(Error::ReadBufferFull);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(read_bytes)
|
||||
}
|
||||
|
||||
async fn write(&mut self, words: &[u8]) -> Result<(), Error> {
|
||||
let mut offset: usize = 0;
|
||||
loop {
|
||||
let mut next_offset =
|
||||
offset + (UART_FIFO_SIZE - self.uart.get_tx_fifo_count()) as usize;
|
||||
if next_offset > words.len() {
|
||||
next_offset = words.len();
|
||||
}
|
||||
for &byte in &words[offset..next_offset] {
|
||||
self.write_byte(byte).unwrap(); // should never fail
|
||||
}
|
||||
if next_offset == words.len() {
|
||||
break;
|
||||
}
|
||||
offset = next_offset;
|
||||
UartFuture::new(Event::TxFiFoEmpty, self.inner()).await;
|
||||
}
|
||||
Ok(())
|
||||
@ -1111,42 +1173,63 @@ mod asynch {
|
||||
}
|
||||
}
|
||||
|
||||
fn intr_handler(uart: &RegisterBlock) -> bool {
|
||||
let int_ena_val = uart.int_ena.read();
|
||||
let int_raw_val = uart.int_raw.read();
|
||||
if int_ena_val.txfifo_empty_int_ena().bit_is_set()
|
||||
&& int_raw_val.txfifo_empty_int_raw().bit_is_set()
|
||||
{
|
||||
uart.int_ena.write(|w| w.txfifo_empty_int_ena().clear_bit());
|
||||
return true;
|
||||
}
|
||||
if int_ena_val.tx_done_int_ena().bit_is_set() && int_raw_val.tx_done_int_raw().bit_is_set()
|
||||
{
|
||||
uart.int_ena.write(|w| w.tx_done_int_ena().clear_bit());
|
||||
return true;
|
||||
}
|
||||
if int_ena_val.at_cmd_char_det_int_ena().bit_is_set()
|
||||
&& int_raw_val.at_cmd_char_det_int_raw().bit_is_set()
|
||||
{
|
||||
uart.int_clr
|
||||
.write(|w| w.at_cmd_char_det_int_clr().set_bit());
|
||||
uart.int_ena
|
||||
.write(|w| w.at_cmd_char_det_int_ena().clear_bit());
|
||||
return true;
|
||||
}
|
||||
if int_ena_val.rxfifo_full_int_ena().bit_is_set()
|
||||
&& int_raw_val.rxfifo_full_int_raw().bit_is_set()
|
||||
{
|
||||
uart.int_clr.write(|w| w.rxfifo_full_int_clr().set_bit());
|
||||
uart.int_ena.write(|w| w.rxfifo_full_int_ena().clear_bit());
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
#[cfg(uart0)]
|
||||
#[interrupt]
|
||||
fn UART0() {
|
||||
let uart = unsafe { &*crate::peripherals::UART0::ptr() };
|
||||
uart.int_ena.modify(|_, w| {
|
||||
w.txfifo_empty_int_ena()
|
||||
.clear_bit()
|
||||
.tx_done_int_ena()
|
||||
.clear_bit()
|
||||
});
|
||||
WAKERS[0].wake();
|
||||
if intr_handler(uart) {
|
||||
WAKERS[0].wake();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(uart1)]
|
||||
#[interrupt]
|
||||
fn UART1() {
|
||||
let uart = unsafe { &*crate::peripherals::UART1::ptr() };
|
||||
uart.int_ena.modify(|_, w| {
|
||||
w.txfifo_empty_int_ena()
|
||||
.clear_bit()
|
||||
.tx_done_int_ena()
|
||||
.clear_bit()
|
||||
});
|
||||
WAKERS[1].wake();
|
||||
if intr_handler(uart) {
|
||||
WAKERS[1].wake();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(uart2)]
|
||||
#[interrupt]
|
||||
fn UART2() {
|
||||
let uart = unsafe { &*crate::peripherals::UART2::ptr() };
|
||||
uart.int_ena.modify(|_, w| {
|
||||
w.txfifo_empty_int_ena()
|
||||
.clear_bit()
|
||||
.tx_done_int_ena()
|
||||
.clear_bit()
|
||||
});
|
||||
WAKERS[2].wake();
|
||||
if intr_handler(uart) {
|
||||
WAKERS[2].wake();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
//! USB Serial JTAG peripheral driver
|
||||
|
||||
use core::convert::Infallible;
|
||||
|
||||
use crate::{
|
||||
@ -6,6 +8,7 @@ use crate::{
|
||||
system::PeripheralClockControl,
|
||||
};
|
||||
|
||||
/// USB Serial JTAG driver
|
||||
pub struct UsbSerialJtag<'d> {
|
||||
usb_serial: PeripheralRef<'d, USB_DEVICE>,
|
||||
}
|
||||
@ -150,7 +153,7 @@ impl<'d> UsbSerialJtag<'d> {
|
||||
}
|
||||
}
|
||||
|
||||
/// USB serial/JTAG peripheral instance
|
||||
/// USB Serial JTAG peripheral instance
|
||||
pub trait Instance {
|
||||
fn register_block(&self) -> &RegisterBlock;
|
||||
|
||||
|
||||
@ -3,8 +3,13 @@ runner = "espflash flash --monitor"
|
||||
|
||||
[build]
|
||||
rustflags = [
|
||||
"-C", "link-arg=-nostartfiles",
|
||||
"-C", "link-arg=-Wl,-Tlinkall.x",
|
||||
# GNU LD
|
||||
# "-C", "link-arg=-nostartfiles",
|
||||
# "-C", "link-arg=-Wl,-Tlinkall.x",
|
||||
|
||||
# LLD
|
||||
"-C", "linker=rust-lld",
|
||||
"-C", "link-arg=-Tlinkall.x",
|
||||
]
|
||||
target = "xtensa-esp32-none-elf"
|
||||
|
||||
|
||||
@ -47,6 +47,7 @@ sha2 = { version = "0.10.6", default-features = false}
|
||||
smart-leds = "0.3.0"
|
||||
ssd1306 = "0.7.1"
|
||||
static_cell = "1.0.0"
|
||||
heapless = "0.7.16"
|
||||
|
||||
[features]
|
||||
default = ["rt", "vectored", "xtal40mhz"]
|
||||
|
||||
@ -9,7 +9,7 @@ use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
rom::crc,
|
||||
rom::{crc, md5},
|
||||
timer::TimerGroup,
|
||||
Rtc,
|
||||
Uart,
|
||||
@ -40,6 +40,7 @@ fn main() -> ! {
|
||||
timer0.start(1u64.secs());
|
||||
|
||||
let data = "123456789";
|
||||
let sentence = "The quick brown fox jumps over a lazy dog";
|
||||
|
||||
writeln!(
|
||||
serial0,
|
||||
@ -66,10 +67,38 @@ fn main() -> ! {
|
||||
assert_eq!(crc_rohc, 0xd0);
|
||||
assert_eq!(crc_smbus, 0xf4);
|
||||
|
||||
// Hash the sentence one word at a time to *really* test the context
|
||||
// Use Peekable while iter_intersperse is unstable
|
||||
let mut md5_ctx = md5::Context::new();
|
||||
let mut it = sentence.split_whitespace().peekable();
|
||||
while let Some(word) = it.next() {
|
||||
md5_ctx.consume(word);
|
||||
if it.peek().is_some() {
|
||||
md5_ctx.consume(" ");
|
||||
}
|
||||
}
|
||||
let md5_digest = md5_ctx.compute();
|
||||
|
||||
assert_eq!(
|
||||
md5_digest,
|
||||
md5::Digest([
|
||||
0x30, 0xde, 0xd8, 0x07, 0xd6, 0x5e, 0xe0, 0x37, 0x0f, 0xc6, 0xd7, 0x3d, 0x6a, 0xb5,
|
||||
0x5a, 0x95
|
||||
])
|
||||
);
|
||||
|
||||
writeln!(
|
||||
serial0,
|
||||
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}",
|
||||
crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus
|
||||
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}",
|
||||
crc_hdlc,
|
||||
crc_bzip2,
|
||||
crc_mpeg2,
|
||||
crc_cksum,
|
||||
crc_kermit,
|
||||
crc_genibus,
|
||||
crc_rohc,
|
||||
crc_smbus,
|
||||
md5_digest
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
||||
@ -20,10 +20,10 @@ use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
i2c::I2C,
|
||||
interrupt,
|
||||
peripherals::{Interrupt, Peripherals, I2C0},
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
Priority,
|
||||
Rtc,
|
||||
IO,
|
||||
};
|
||||
@ -77,7 +77,7 @@ fn main() -> ! {
|
||||
&clocks,
|
||||
);
|
||||
|
||||
esp32_hal::interrupt::enable(Interrupt::I2C_EXT0, Priority::Priority1).unwrap();
|
||||
interrupt::enable(Interrupt::I2C_EXT0, interrupt::Priority::Priority1).unwrap();
|
||||
|
||||
let executor = EXECUTOR.init(Executor::new());
|
||||
executor.run(|spawner| {
|
||||
|
||||
@ -1,17 +1,20 @@
|
||||
//! embassy serial
|
||||
//!
|
||||
//! This is an example of running the embassy executor and asynchronously
|
||||
//! writing to a uart.
|
||||
//! writing to and reading from uart
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use embassy_executor::Executor;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_time::{with_timeout, Duration};
|
||||
use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
interrupt,
|
||||
peripherals::{Interrupt, Peripherals, UART0},
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
@ -19,18 +22,79 @@ use esp32_hal::{
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_hal_common::uart::config::AtCmdConfig;
|
||||
use heapless::Vec;
|
||||
use static_cell::StaticCell;
|
||||
|
||||
// rx_fifo_full_threshold
|
||||
const READ_BUF_SIZE: usize = 128;
|
||||
// EOT (CTRL-D)
|
||||
const AT_CMD: u8 = 0x04;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run(mut uart: Uart<'static, UART0>) {
|
||||
// max message size to receive
|
||||
// leave some extra space for AT-CMD characters
|
||||
const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16;
|
||||
// timeout read
|
||||
const READ_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
let mut rbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
let mut wbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
loop {
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"Hello async write!!!\r\n")
|
||||
if rbuf.is_empty() {
|
||||
embedded_hal_async::serial::Write::write(
|
||||
&mut uart,
|
||||
b"Hello async serial. Enter something ended with EOT (CTRL-D).\r\n",
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
} else {
|
||||
wbuf.clear();
|
||||
write!(&mut wbuf, "\r\n-- received {} bytes --\r\n", rbuf.len()).unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, wbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, rbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"\r\n")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||
.await
|
||||
.unwrap();
|
||||
Timer::after(Duration::from_millis(1_000)).await;
|
||||
|
||||
// set rbuf full capacity
|
||||
rbuf.resize_default(rbuf.capacity()).ok();
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
match with_timeout(READ_TIMEOUT, uart.read(&mut rbuf[offset..])).await {
|
||||
Ok(r) => {
|
||||
if let Ok(len) = r {
|
||||
offset += len;
|
||||
if offset == 0 {
|
||||
rbuf.truncate(0);
|
||||
break;
|
||||
}
|
||||
// if set_at_cmd is used than stop reading
|
||||
if len < READ_BUF_SIZE {
|
||||
rbuf.truncate(offset);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// buffer is full
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Timeout
|
||||
rbuf.truncate(offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,9 +129,11 @@ fn main() -> ! {
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
embassy::init(&clocks, timer_group0.timer0);
|
||||
|
||||
let uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None));
|
||||
uart0.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16);
|
||||
|
||||
esp32_hal::interrupt::enable(Interrupt::UART0, esp32_hal::Priority::Priority1).unwrap();
|
||||
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
|
||||
|
||||
let executor = EXECUTOR.init(Executor::new());
|
||||
executor.run(|spawner| {
|
||||
|
||||
@ -44,14 +44,7 @@ macro_rules! singleton {
|
||||
}};
|
||||
}
|
||||
|
||||
pub type SpiType<'d> = SpiDma<
|
||||
'd,
|
||||
esp32_hal::peripherals::SPI2,
|
||||
ChannelTx<'d, Spi2DmaChannelTxImpl, Spi2DmaChannel>,
|
||||
ChannelRx<'d, Spi2DmaChannelRxImpl, Spi2DmaChannel>,
|
||||
Spi2DmaSuitablePeripheral,
|
||||
FullDuplexMode,
|
||||
>;
|
||||
pub type SpiType<'d> = SpiDma<'d, esp32_hal::peripherals::SPI2, Spi2DmaChannel, FullDuplexMode>;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn spi_task(spi: &'static mut SpiType<'static>) {
|
||||
|
||||
@ -9,7 +9,7 @@ use esp32_hal::{
|
||||
clock::ClockControl,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
soc,
|
||||
psram,
|
||||
timer::TimerGroup,
|
||||
Rtc,
|
||||
};
|
||||
@ -23,10 +23,7 @@ static ALLOCATOR: esp_alloc::EspHeap = esp_alloc::EspHeap::empty();
|
||||
|
||||
fn init_psram_heap() {
|
||||
unsafe {
|
||||
ALLOCATOR.init(
|
||||
soc::psram::PSRAM_VADDR_START as *mut u8,
|
||||
soc::psram::PSRAM_BYTES,
|
||||
);
|
||||
ALLOCATOR.init(psram::PSRAM_VADDR_START as *mut u8, psram::PSRAM_BYTES);
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +35,7 @@ fn main() -> ! {
|
||||
esp_println::logger::init_logger_from_env();
|
||||
|
||||
let peripherals = Peripherals::take();
|
||||
soc::psram::init_psram(peripherals.PSRAM);
|
||||
psram::init_psram(peripherals.PSRAM);
|
||||
init_psram_heap();
|
||||
|
||||
let mut system = peripherals.DPORT.split();
|
||||
|
||||
@ -23,3 +23,7 @@ PROVIDE (esp_rom_crc8_be = 0x4005d114);
|
||||
PROVIDE (esp_rom_crc32_le = 0x4005cfec);
|
||||
PROVIDE (esp_rom_crc16_le = 0x4005d05c);
|
||||
PROVIDE (esp_rom_crc8_le = 0x4005d0e0);
|
||||
|
||||
PROVIDE (esp_rom_md5_init = 0x4005da7c);
|
||||
PROVIDE (esp_rom_md5_update = 0x4005da9c);
|
||||
PROVIDE (esp_rom_md5_final = 0x4005db1c);
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
//! `no_std` HAL for the ESP32 from Espressif.
|
||||
//!
|
||||
//! Implements a number of the traits defined by the various packages in the
|
||||
//! [embedded-hal] repository.
|
||||
//!
|
||||
//! [embedded-hal]: https://github.com/rust-embedded/embedded-hal
|
||||
|
||||
#![no_std]
|
||||
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
|
||||
|
||||
pub use embedded_hal as ehal;
|
||||
#[cfg(feature = "embassy")]
|
||||
pub use esp_hal_common::embassy;
|
||||
pub use esp_hal_common::*;
|
||||
|
||||
pub use self::gpio::IO;
|
||||
|
||||
/// Common module for analog functions
|
||||
pub mod analog {
|
||||
pub use esp_hal_common::analog::{AvailableAnalog, SensExt};
|
||||
|
||||
@ -42,6 +42,7 @@ lis3dh-async = "0.7.0"
|
||||
sha2 = { version = "0.10.6", default-features = false}
|
||||
ssd1306 = "0.7.1"
|
||||
static_cell = "1.0.0"
|
||||
heapless = "0.7.16"
|
||||
|
||||
[features]
|
||||
default = ["rt", "vectored", "xtal40mhz"]
|
||||
|
||||
@ -9,7 +9,7 @@ use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
rom::crc,
|
||||
rom::{crc, md5},
|
||||
timer::TimerGroup,
|
||||
Rtc,
|
||||
Uart,
|
||||
@ -41,6 +41,7 @@ fn main() -> ! {
|
||||
timer0.start(1u64.secs());
|
||||
|
||||
let data = "123456789";
|
||||
let sentence = "The quick brown fox jumps over a lazy dog";
|
||||
|
||||
writeln!(
|
||||
serial0,
|
||||
@ -67,10 +68,38 @@ fn main() -> ! {
|
||||
assert_eq!(crc_rohc, 0xd0);
|
||||
assert_eq!(crc_smbus, 0xf4);
|
||||
|
||||
// Hash the sentence one word at a time to *really* test the context
|
||||
// Use Peekable while iter_intersperse is unstable
|
||||
let mut md5_ctx = md5::Context::new();
|
||||
let mut it = sentence.split_whitespace().peekable();
|
||||
while let Some(word) = it.next() {
|
||||
md5_ctx.consume(word);
|
||||
if it.peek().is_some() {
|
||||
md5_ctx.consume(" ");
|
||||
}
|
||||
}
|
||||
let md5_digest = md5_ctx.compute();
|
||||
|
||||
assert_eq!(
|
||||
md5_digest,
|
||||
md5::Digest([
|
||||
0x30, 0xde, 0xd8, 0x07, 0xd6, 0x5e, 0xe0, 0x37, 0x0f, 0xc6, 0xd7, 0x3d, 0x6a, 0xb5,
|
||||
0x5a, 0x95
|
||||
])
|
||||
);
|
||||
|
||||
writeln!(
|
||||
serial0,
|
||||
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}",
|
||||
crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus
|
||||
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}",
|
||||
crc_hdlc,
|
||||
crc_bzip2,
|
||||
crc_mpeg2,
|
||||
crc_cksum,
|
||||
crc_kermit,
|
||||
crc_genibus,
|
||||
crc_rohc,
|
||||
crc_smbus,
|
||||
md5_digest
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
||||
@ -20,10 +20,10 @@ use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
i2c::I2C,
|
||||
interrupt,
|
||||
peripherals::{Interrupt, Peripherals, I2C0},
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
Priority,
|
||||
Rtc,
|
||||
IO,
|
||||
};
|
||||
@ -85,7 +85,7 @@ fn main() -> ! {
|
||||
&clocks,
|
||||
);
|
||||
|
||||
esp32c2_hal::interrupt::enable(Interrupt::I2C_EXT0, Priority::Priority1).unwrap();
|
||||
interrupt::enable(Interrupt::I2C_EXT0, interrupt::Priority::Priority1).unwrap();
|
||||
|
||||
let executor = EXECUTOR.init(Executor::new());
|
||||
executor.run(|spawner| {
|
||||
|
||||
@ -1,17 +1,20 @@
|
||||
//! embassy serial
|
||||
//!
|
||||
//! This is an example of running the embassy executor and asynchronously
|
||||
//! writing to a uart.
|
||||
//! writing to and reading from uart
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use embassy_executor::Executor;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_time::{with_timeout, Duration};
|
||||
use esp32c2_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
interrupt,
|
||||
peripherals::{Interrupt, Peripherals, UART0},
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
@ -19,18 +22,79 @@ use esp32c2_hal::{
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_hal_common::uart::config::AtCmdConfig;
|
||||
use heapless::Vec;
|
||||
use static_cell::StaticCell;
|
||||
|
||||
// rx_fifo_full_threshold
|
||||
const READ_BUF_SIZE: usize = 128;
|
||||
/// EOT; CTRL-D
|
||||
const AT_CMD: u8 = 0x04;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run(mut uart: Uart<'static, UART0>) {
|
||||
// max message size to receive
|
||||
// leave some extra space for AT-CMD characters
|
||||
const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16;
|
||||
// timeout read
|
||||
const READ_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
let mut rbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
let mut wbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
loop {
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"Hello async write!!!\r\n")
|
||||
if rbuf.is_empty() {
|
||||
embedded_hal_async::serial::Write::write(
|
||||
&mut uart,
|
||||
b"Hello async serial. Enter something ended with EOT (CTRL-D).\r\n",
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
} else {
|
||||
wbuf.clear();
|
||||
write!(&mut wbuf, "\r\n-- received {} bytes --\r\n", rbuf.len()).unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, wbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, rbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"\r\n")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||
.await
|
||||
.unwrap();
|
||||
Timer::after(Duration::from_millis(1_000)).await;
|
||||
|
||||
// set rbuf full capacity
|
||||
rbuf.resize_default(rbuf.capacity()).ok();
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
match with_timeout(READ_TIMEOUT, uart.read(&mut rbuf[offset..])).await {
|
||||
Ok(r) => {
|
||||
if let Ok(len) = r {
|
||||
offset += len;
|
||||
if offset == 0 {
|
||||
rbuf.truncate(0);
|
||||
break;
|
||||
}
|
||||
// if set_at_cmd is used than stop reading
|
||||
if len < READ_BUF_SIZE {
|
||||
rbuf.truncate(offset);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// buffer is full
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Timeout
|
||||
rbuf.truncate(offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,9 +129,11 @@ fn main() -> ! {
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
embassy::init(&clocks, timer_group0.timer0);
|
||||
|
||||
let uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None));
|
||||
uart0.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16);
|
||||
|
||||
esp32c2_hal::interrupt::enable(Interrupt::UART0, esp32c2_hal::Priority::Priority1).unwrap();
|
||||
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
|
||||
|
||||
let executor = EXECUTOR.init(Executor::new());
|
||||
executor.run(|spawner| {
|
||||
|
||||
@ -44,14 +44,8 @@ macro_rules! singleton {
|
||||
}};
|
||||
}
|
||||
|
||||
pub type SpiType<'d> = SpiDma<
|
||||
'd,
|
||||
esp32c2_hal::peripherals::SPI2,
|
||||
ChannelTx<'d, Channel0TxImpl, esp32c2_hal::gdma::Channel0>,
|
||||
ChannelRx<'d, Channel0RxImpl, esp32c2_hal::gdma::Channel0>,
|
||||
SuitablePeripheral0,
|
||||
FullDuplexMode,
|
||||
>;
|
||||
pub type SpiType<'d> =
|
||||
SpiDma<'d, esp32c2_hal::peripherals::SPI2, esp32c2_hal::gdma::Channel0, FullDuplexMode>;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn spi_task(spi: &'static mut SpiType<'static>) {
|
||||
|
||||
@ -67,7 +67,7 @@ SECTIONS {
|
||||
*(.trap.*);
|
||||
} > RWTEXT
|
||||
}
|
||||
INSERT AFTER .rwtext;
|
||||
INSERT BEFORE .rwtext;
|
||||
|
||||
SECTIONS {
|
||||
/**
|
||||
|
||||
@ -89,10 +89,10 @@ SECTIONS
|
||||
_data_size = _data_end - _data_start + 8;
|
||||
.rwtext ORIGIN(REGION_RWTEXT) + _data_size : AT(_text_size + _rodata_size + _data_size){
|
||||
_srwtext = .;
|
||||
*(.rwtext);
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.trap));
|
||||
*(.trap.*);
|
||||
*(.rwtext);
|
||||
. = ALIGN(4);
|
||||
_erwtext = .;
|
||||
} > REGION_RWTEXT
|
||||
_rwtext_size = _erwtext - _srwtext + 8;
|
||||
|
||||
@ -12,3 +12,7 @@ PROVIDE(esp_rom_crc8_be = 0x40000810);
|
||||
PROVIDE(esp_rom_crc32_le = 0x400007fc);
|
||||
PROVIDE(esp_rom_crc16_le = 0x40000800);
|
||||
PROVIDE(esp_rom_crc8_le = 0x40000804);
|
||||
|
||||
PROVIDE(esp_rom_mbedtls_md5_starts_ret = 0x40002be4);
|
||||
PROVIDE(esp_rom_mbedtls_md5_update_ret = 0x40002be8);
|
||||
PROVIDE(esp_rom_mbedtls_md5_finish_ret = 0x40002bec);
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
//! `no_std` HAL for the ESP32-C2/ESP8684 from Espressif.
|
||||
//!
|
||||
//! Implements a number of the traits defined by the various packages in the
|
||||
//! [embedded-hal] repository.
|
||||
//!
|
||||
//! [embedded-hal]: https://github.com/rust-embedded/embedded-hal
|
||||
|
||||
#![no_std]
|
||||
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
|
||||
|
||||
pub use embedded_hal as ehal;
|
||||
#[cfg(feature = "embassy")]
|
||||
pub use esp_hal_common::embassy;
|
||||
pub use esp_hal_common::*;
|
||||
|
||||
pub use self::gpio::IO;
|
||||
|
||||
/// Common module for analog functions
|
||||
pub mod analog {
|
||||
pub use esp_hal_common::analog::{AvailableAnalog, SarAdcExt};
|
||||
|
||||
@ -48,6 +48,7 @@ sha2 = { version = "0.10.6", default-features = false}
|
||||
smart-leds = "0.3.0"
|
||||
ssd1306 = "0.7.1"
|
||||
static_cell = "1.0.0"
|
||||
heapless = "0.7.16"
|
||||
|
||||
[features]
|
||||
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]
|
||||
|
||||
@ -9,7 +9,7 @@ use esp32c3_hal::{
|
||||
clock::ClockControl,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
rom::crc,
|
||||
rom::{crc, md5},
|
||||
timer::TimerGroup,
|
||||
Rtc,
|
||||
Uart,
|
||||
@ -48,6 +48,7 @@ fn main() -> ! {
|
||||
timer0.start(1u64.secs());
|
||||
|
||||
let data = "123456789";
|
||||
let sentence = "The quick brown fox jumps over a lazy dog";
|
||||
|
||||
writeln!(
|
||||
uart0,
|
||||
@ -74,10 +75,38 @@ fn main() -> ! {
|
||||
assert_eq!(crc_rohc, 0xd0);
|
||||
assert_eq!(crc_smbus, 0xf4);
|
||||
|
||||
// Hash the sentence one word at a time to *really* test the context
|
||||
// Use Peekable while iter_intersperse is unstable
|
||||
let mut md5_ctx = md5::Context::new();
|
||||
let mut it = sentence.split_whitespace().peekable();
|
||||
while let Some(word) = it.next() {
|
||||
md5_ctx.consume(word);
|
||||
if it.peek().is_some() {
|
||||
md5_ctx.consume(" ");
|
||||
}
|
||||
}
|
||||
let md5_digest = md5_ctx.compute();
|
||||
|
||||
assert_eq!(
|
||||
md5_digest,
|
||||
md5::Digest([
|
||||
0x30, 0xde, 0xd8, 0x07, 0xd6, 0x5e, 0xe0, 0x37, 0x0f, 0xc6, 0xd7, 0x3d, 0x6a, 0xb5,
|
||||
0x5a, 0x95
|
||||
])
|
||||
);
|
||||
|
||||
writeln!(
|
||||
uart0,
|
||||
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}",
|
||||
crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus
|
||||
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}",
|
||||
crc_hdlc,
|
||||
crc_bzip2,
|
||||
crc_mpeg2,
|
||||
crc_cksum,
|
||||
crc_kermit,
|
||||
crc_genibus,
|
||||
crc_rohc,
|
||||
crc_smbus,
|
||||
md5_digest
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
||||
@ -20,10 +20,10 @@ use esp32c3_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
i2c::I2C,
|
||||
interrupt,
|
||||
peripherals::{Interrupt, Peripherals, I2C0},
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
Priority,
|
||||
Rtc,
|
||||
IO,
|
||||
};
|
||||
@ -92,7 +92,7 @@ fn main() -> ! {
|
||||
&clocks,
|
||||
);
|
||||
|
||||
esp32c3_hal::interrupt::enable(Interrupt::I2C_EXT0, Priority::Priority1).unwrap();
|
||||
interrupt::enable(Interrupt::I2C_EXT0, interrupt::Priority::Priority1).unwrap();
|
||||
|
||||
let executor = EXECUTOR.init(Executor::new());
|
||||
executor.run(|spawner| {
|
||||
|
||||
@ -1,17 +1,20 @@
|
||||
//! embassy serial
|
||||
//!
|
||||
//! This is an example of running the embassy executor and asynchronously
|
||||
//! writing to a uart.
|
||||
//! writing to and reading from uart
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use embassy_executor::Executor;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_time::{with_timeout, Duration};
|
||||
use esp32c3_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
interrupt,
|
||||
peripherals::{Interrupt, Peripherals, UART0},
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
@ -19,18 +22,79 @@ use esp32c3_hal::{
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_hal_common::uart::config::AtCmdConfig;
|
||||
use heapless::Vec;
|
||||
use static_cell::StaticCell;
|
||||
|
||||
// rx_fifo_full_threshold
|
||||
const READ_BUF_SIZE: usize = 128;
|
||||
// EOT (CTRL-D)
|
||||
const AT_CMD: u8 = 0x04;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run(mut uart: Uart<'static, UART0>) {
|
||||
// max message size to receive
|
||||
// leave some extra space for AT-CMD characters
|
||||
const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16;
|
||||
// timeout read
|
||||
const READ_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
let mut rbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
let mut wbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
loop {
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"Hello async write!!!\r\n")
|
||||
if rbuf.is_empty() {
|
||||
embedded_hal_async::serial::Write::write(
|
||||
&mut uart,
|
||||
b"Hello async serial. Enter something ended with EOT (CTRL-D).\r\n",
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
} else {
|
||||
wbuf.clear();
|
||||
write!(&mut wbuf, "\r\n-- received {} bytes --\r\n", rbuf.len()).unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, wbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, rbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"\r\n")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||
.await
|
||||
.unwrap();
|
||||
Timer::after(Duration::from_millis(1_000)).await;
|
||||
|
||||
// set rbuf full capacity
|
||||
rbuf.resize_default(rbuf.capacity()).ok();
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
match with_timeout(READ_TIMEOUT, uart.read(&mut rbuf[offset..])).await {
|
||||
Ok(r) => {
|
||||
if let Ok(len) = r {
|
||||
offset += len;
|
||||
if offset == 0 {
|
||||
rbuf.truncate(0);
|
||||
break;
|
||||
}
|
||||
// if set_at_cmd is used than stop reading
|
||||
if len < READ_BUF_SIZE {
|
||||
rbuf.truncate(offset);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// buffer is full
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Timeout
|
||||
rbuf.truncate(offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,9 +136,11 @@ fn main() -> ! {
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
embassy::init(&clocks, timer_group0.timer0);
|
||||
|
||||
let uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None));
|
||||
uart0.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16);
|
||||
|
||||
esp32c3_hal::interrupt::enable(Interrupt::UART0, esp32c3_hal::Priority::Priority1).unwrap();
|
||||
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
|
||||
|
||||
let executor = EXECUTOR.init(Executor::new());
|
||||
executor.run(|spawner| {
|
||||
|
||||
@ -44,14 +44,8 @@ macro_rules! singleton {
|
||||
}};
|
||||
}
|
||||
|
||||
pub type SpiType<'d> = SpiDma<
|
||||
'd,
|
||||
esp32c3_hal::peripherals::SPI2,
|
||||
ChannelTx<'d, Channel0TxImpl, esp32c3_hal::gdma::Channel0>,
|
||||
ChannelRx<'d, Channel0RxImpl, esp32c3_hal::gdma::Channel0>,
|
||||
SuitablePeripheral0,
|
||||
FullDuplexMode,
|
||||
>;
|
||||
pub type SpiType<'d> =
|
||||
SpiDma<'d, esp32c3_hal::peripherals::SPI2, esp32c3_hal::gdma::Channel0, FullDuplexMode>;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn spi_task(spi: &'static mut SpiType<'static>) {
|
||||
|
||||
@ -67,7 +67,7 @@ SECTIONS {
|
||||
*(.trap.*);
|
||||
} > RWTEXT
|
||||
}
|
||||
INSERT AFTER .rwtext;
|
||||
INSERT BEFORE .rwtext;
|
||||
|
||||
SECTIONS {
|
||||
/**
|
||||
|
||||
@ -89,10 +89,10 @@ SECTIONS
|
||||
_data_size = _data_end - _data_start + 8;
|
||||
.rwtext ORIGIN(REGION_RWTEXT) + _data_size : AT(_text_size + _rodata_size + _data_size){
|
||||
_srwtext = .;
|
||||
*(.rwtext);
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.trap));
|
||||
*(.trap.*);
|
||||
*(.rwtext);
|
||||
. = ALIGN(4);
|
||||
_erwtext = .;
|
||||
} > REGION_RWTEXT
|
||||
_rwtext_size = _erwtext - _srwtext + 8;
|
||||
|
||||
@ -64,9 +64,9 @@ SECTIONS
|
||||
KEEP(*(.init));
|
||||
KEEP(*(.init.rust));
|
||||
KEEP(*(.text.abort));
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.trap));
|
||||
*(.trap.*);
|
||||
. = ALIGN(4);
|
||||
|
||||
*libriscv-*.rlib:riscv.*(.literal .text .literal.* .text.*);
|
||||
*libesp_riscv_rt-*.rlib:esp-riscv-rt.*(.literal .text .literal.* .text.*);
|
||||
|
||||
@ -19,3 +19,7 @@ PROVIDE(esp_rom_crc8_be = 0x4000063c);
|
||||
PROVIDE(esp_rom_crc32_le = 0x40000628);
|
||||
PROVIDE(esp_rom_crc16_le = 0x40000630);
|
||||
PROVIDE(esp_rom_crc8_le = 0x40000638);
|
||||
|
||||
PROVIDE(esp_rom_md5_init = 0x40000614);
|
||||
PROVIDE(esp_rom_md5_update = 0x40000618);
|
||||
PROVIDE(esp_rom_md5_final = 0x4000061c);
|
||||
|
||||
@ -1,16 +1,15 @@
|
||||
//! `no_std` HAL for the ESP32-C3/ESP8685 from Espressif.
|
||||
//!
|
||||
//! Implements a number of the traits defined by the various packages in the
|
||||
//! [embedded-hal] repository.
|
||||
//!
|
||||
//! [embedded-hal]: https://github.com/rust-embedded/embedded-hal
|
||||
|
||||
#![no_std]
|
||||
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
|
||||
|
||||
#[cfg(feature = "mcu-boot")]
|
||||
use core::mem::size_of;
|
||||
|
||||
pub use embedded_hal as ehal;
|
||||
#[cfg(feature = "embassy")]
|
||||
pub use esp_hal_common::embassy;
|
||||
pub use esp_hal_common::*;
|
||||
|
||||
pub use self::gpio::IO;
|
||||
|
||||
/// Common module for analog functions
|
||||
pub mod analog {
|
||||
pub use esp_hal_common::analog::{AvailableAnalog, SarAdcExt};
|
||||
@ -90,7 +89,7 @@ unsafe fn configure_mmu() {
|
||||
|
||||
const FLASH_MMU_TABLE: *mut u32 = 0x600c_5000 as *mut u32;
|
||||
const ICACHE_MMU_SIZE: usize = 0x200;
|
||||
const FLASH_MMU_TABLE_SIZE: usize = ICACHE_MMU_SIZE / size_of::<u32>();
|
||||
const FLASH_MMU_TABLE_SIZE: usize = ICACHE_MMU_SIZE / core::mem::size_of::<u32>();
|
||||
const MMU_TABLE_INVALID_VAL: u32 = 0x100;
|
||||
|
||||
for i in 0..FLASH_MMU_TABLE_SIZE {
|
||||
|
||||
@ -49,6 +49,7 @@ sha2 = { version = "0.10.6", default-features = false}
|
||||
smart-leds = "0.3.0"
|
||||
ssd1306 = "0.7.1"
|
||||
static_cell = "1.0.0"
|
||||
heapless = "0.7.16"
|
||||
|
||||
[features]
|
||||
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]
|
||||
|
||||
@ -33,7 +33,7 @@ By default, [espflash](https://github.com/esp-rs/espflash) fetches the required
|
||||
|
||||
#### Direct Boot
|
||||
|
||||
[Direct Boot](https://github.com/espressif/esp32c6-direct-boot-example#direct-boot-in-esp32-c6) allows an application stored in the External Flash to be executed directly, without being copied into Internal RAM.
|
||||
[Direct Boot](https://github.com/espressif/esp32c3-direct-boot-example#direct-boot-in-esp32-c3) allows an application stored in the External Flash to be executed directly, without being copied into Internal RAM.
|
||||
|
||||
##### Booting the Hello World example using Direct Boot
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ use esp32c6_hal::{
|
||||
clock::ClockControl,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
rom::crc,
|
||||
rom::{crc, md5},
|
||||
timer::TimerGroup,
|
||||
Rtc,
|
||||
Uart,
|
||||
@ -48,6 +48,7 @@ fn main() -> ! {
|
||||
timer0.start(1u64.secs());
|
||||
|
||||
let data = "123456789";
|
||||
let sentence = "The quick brown fox jumps over a lazy dog";
|
||||
|
||||
writeln!(
|
||||
uart0,
|
||||
@ -74,10 +75,38 @@ fn main() -> ! {
|
||||
assert_eq!(crc_rohc, 0xd0);
|
||||
assert_eq!(crc_smbus, 0xf4);
|
||||
|
||||
// Hash the sentence one word at a time to *really* test the context
|
||||
// Use Peekable while iter_intersperse is unstable
|
||||
let mut md5_ctx = md5::Context::new();
|
||||
let mut it = sentence.split_whitespace().peekable();
|
||||
while let Some(word) = it.next() {
|
||||
md5_ctx.consume(word);
|
||||
if it.peek().is_some() {
|
||||
md5_ctx.consume(" ");
|
||||
}
|
||||
}
|
||||
let md5_digest = md5_ctx.compute();
|
||||
|
||||
assert_eq!(
|
||||
md5_digest,
|
||||
md5::Digest([
|
||||
0x30, 0xde, 0xd8, 0x07, 0xd6, 0x5e, 0xe0, 0x37, 0x0f, 0xc6, 0xd7, 0x3d, 0x6a, 0xb5,
|
||||
0x5a, 0x95
|
||||
])
|
||||
);
|
||||
|
||||
writeln!(
|
||||
uart0,
|
||||
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}",
|
||||
crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus
|
||||
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}",
|
||||
crc_hdlc,
|
||||
crc_bzip2,
|
||||
crc_mpeg2,
|
||||
crc_cksum,
|
||||
crc_kermit,
|
||||
crc_genibus,
|
||||
crc_rohc,
|
||||
crc_smbus,
|
||||
md5_digest
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
||||
@ -20,10 +20,10 @@ use esp32c6_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
i2c::I2C,
|
||||
interrupt,
|
||||
peripherals::{Interrupt, Peripherals, I2C0},
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
Priority,
|
||||
Rtc,
|
||||
IO,
|
||||
};
|
||||
@ -92,7 +92,7 @@ fn main() -> ! {
|
||||
&clocks,
|
||||
);
|
||||
|
||||
esp32c6_hal::interrupt::enable(Interrupt::I2C_EXT0, Priority::Priority1).unwrap();
|
||||
interrupt::enable(Interrupt::I2C_EXT0, interrupt::Priority::Priority1).unwrap();
|
||||
|
||||
let executor = EXECUTOR.init(Executor::new());
|
||||
executor.run(|spawner| {
|
||||
|
||||
@ -1,17 +1,20 @@
|
||||
//! embassy serial
|
||||
//!
|
||||
//! This is an example of running the embassy executor and asynchronously
|
||||
//! writing to a uart.
|
||||
//! writing to and reading from uart
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(type_alias_impl_trait)]
|
||||
|
||||
use core::fmt::Write;
|
||||
|
||||
use embassy_executor::Executor;
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_time::{with_timeout, Duration};
|
||||
use esp32c6_hal::{
|
||||
clock::ClockControl,
|
||||
embassy,
|
||||
interrupt,
|
||||
peripherals::{Interrupt, Peripherals, UART0},
|
||||
prelude::*,
|
||||
timer::TimerGroup,
|
||||
@ -19,18 +22,79 @@ use esp32c6_hal::{
|
||||
Uart,
|
||||
};
|
||||
use esp_backtrace as _;
|
||||
use esp_hal_common::uart::config::AtCmdConfig;
|
||||
use heapless::Vec;
|
||||
use static_cell::StaticCell;
|
||||
|
||||
// rx_fifo_full_threshold
|
||||
const READ_BUF_SIZE: usize = 128;
|
||||
// EOT (CTRL-D)
|
||||
const AT_CMD: u8 = 0x04;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn run(mut uart: Uart<'static, UART0>) {
|
||||
// max message size to receive
|
||||
// leave some extra space for AT-CMD characters
|
||||
const MAX_BUFFER_SIZE: usize = 10 * READ_BUF_SIZE + 16;
|
||||
// timeout read
|
||||
const READ_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
|
||||
let mut rbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
let mut wbuf: Vec<u8, MAX_BUFFER_SIZE> = Vec::new();
|
||||
loop {
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"Hello async write!!!\r\n")
|
||||
if rbuf.is_empty() {
|
||||
embedded_hal_async::serial::Write::write(
|
||||
&mut uart,
|
||||
b"Hello async serial. Enter something ended with EOT (CTRL-D).\r\n",
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
} else {
|
||||
wbuf.clear();
|
||||
write!(&mut wbuf, "\r\n-- received {} bytes --\r\n", rbuf.len()).unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, wbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, rbuf.as_slice())
|
||||
.await
|
||||
.unwrap();
|
||||
embedded_hal_async::serial::Write::write(&mut uart, b"\r\n")
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
embedded_hal_async::serial::Write::flush(&mut uart)
|
||||
.await
|
||||
.unwrap();
|
||||
Timer::after(Duration::from_millis(1_000)).await;
|
||||
|
||||
// set rbuf full capacity
|
||||
rbuf.resize_default(rbuf.capacity()).ok();
|
||||
let mut offset = 0;
|
||||
loop {
|
||||
match with_timeout(READ_TIMEOUT, uart.read(&mut rbuf[offset..])).await {
|
||||
Ok(r) => {
|
||||
if let Ok(len) = r {
|
||||
offset += len;
|
||||
if offset == 0 {
|
||||
rbuf.truncate(0);
|
||||
break;
|
||||
}
|
||||
// if set_at_cmd is used than stop reading
|
||||
if len < READ_BUF_SIZE {
|
||||
rbuf.truncate(offset);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// buffer is full
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
// Timeout
|
||||
rbuf.truncate(offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,9 +136,11 @@ fn main() -> ! {
|
||||
#[cfg(feature = "embassy-time-timg0")]
|
||||
embassy::init(&clocks, timer_group0.timer0);
|
||||
|
||||
let uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
let mut uart0 = Uart::new(peripherals.UART0, &mut system.peripheral_clock_control);
|
||||
uart0.set_at_cmd(AtCmdConfig::new(None, None, None, AT_CMD, None));
|
||||
uart0.set_rx_fifo_full_threshold(READ_BUF_SIZE as u16);
|
||||
|
||||
esp32c6_hal::interrupt::enable(Interrupt::UART0, esp32c6_hal::Priority::Priority1).unwrap();
|
||||
interrupt::enable(Interrupt::UART0, interrupt::Priority::Priority1).unwrap();
|
||||
|
||||
let executor = EXECUTOR.init(Executor::new());
|
||||
executor.run(|spawner| {
|
||||
|
||||
@ -44,14 +44,8 @@ macro_rules! singleton {
|
||||
}};
|
||||
}
|
||||
|
||||
pub type SpiType<'d> = SpiDma<
|
||||
'd,
|
||||
esp32c6_hal::peripherals::SPI2,
|
||||
ChannelTx<'d, Channel0TxImpl, esp32c6_hal::gdma::Channel0>,
|
||||
ChannelRx<'d, Channel0RxImpl, esp32c6_hal::gdma::Channel0>,
|
||||
SuitablePeripheral0,
|
||||
FullDuplexMode,
|
||||
>;
|
||||
pub type SpiType<'d> =
|
||||
SpiDma<'d, esp32c6_hal::peripherals::SPI2, esp32c6_hal::gdma::Channel0, FullDuplexMode>;
|
||||
|
||||
#[embassy_executor::task]
|
||||
async fn spi_task(spi: &'static mut SpiType<'static>) {
|
||||
|
||||
@ -71,7 +71,7 @@ SECTIONS {
|
||||
*(.trap.*);
|
||||
} > RWTEXT
|
||||
}
|
||||
INSERT AFTER .rwtext;
|
||||
INSERT BEFORE .rwtext;
|
||||
|
||||
SECTIONS {
|
||||
/**
|
||||
|
||||
@ -94,10 +94,10 @@ SECTIONS
|
||||
_data_size = _data_end - _data_start + 8;
|
||||
.rwtext ORIGIN(REGION_RWTEXT) + _data_size : AT(_text_size + _rodata_size + _data_size){
|
||||
_srwtext = .;
|
||||
*(.rwtext);
|
||||
. = ALIGN(4);
|
||||
KEEP(*(.trap));
|
||||
*(.trap.*);
|
||||
*(.rwtext);
|
||||
. = ALIGN(4);
|
||||
_erwtext = .;
|
||||
} > REGION_RWTEXT
|
||||
_rwtext_size = _erwtext - _srwtext + 8;
|
||||
|
||||
@ -19,3 +19,7 @@ PROVIDE(esp_rom_crc8_be = 0x4000076c);
|
||||
PROVIDE(esp_rom_crc32_le = 0x40000758);
|
||||
PROVIDE(esp_rom_crc16_le = 0x4000075c);
|
||||
PROVIDE(esp_rom_crc8_le = 0x40000760);
|
||||
|
||||
PROVIDE(esp_rom_md5_init = 0x4000074c);
|
||||
PROVIDE(esp_rom_md5_update = 0x40000750);
|
||||
PROVIDE(esp_rom_md5_final = 0x40000754);
|
||||
|
||||
@ -1,13 +1,15 @@
|
||||
//! `no_std` HAL for the ESP32-C6 from Espressif.
|
||||
//!
|
||||
//! Implements a number of the traits defined by the various packages in the
|
||||
//! [embedded-hal] repository.
|
||||
//!
|
||||
//! [embedded-hal]: https://github.com/rust-embedded/embedded-hal
|
||||
|
||||
#![no_std]
|
||||
#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/46717278")]
|
||||
|
||||
pub use embedded_hal as ehal;
|
||||
#[cfg(feature = "embassy")]
|
||||
pub use esp_hal_common::embassy;
|
||||
pub use esp_hal_common::*;
|
||||
|
||||
pub use self::gpio::IO;
|
||||
|
||||
/// Common module for analog functions
|
||||
pub mod analog {
|
||||
pub use esp_hal_common::analog::{AvailableAnalog, SarAdcExt};
|
||||
|
||||
@ -49,6 +49,7 @@ sha2 = { version = "0.10.6", default-features = false}
|
||||
smart-leds = "0.3.0"
|
||||
ssd1306 = "0.7.1"
|
||||
static_cell = "1.0.0"
|
||||
heapless = "0.7.16"
|
||||
|
||||
[features]
|
||||
default = ["rt", "vectored", "esp-hal-common/rv-zero-rtc-bss"]
|
||||
|
||||
@ -1,17 +1,17 @@
|
||||
# esp32h2-hal
|
||||
|
||||
<!-- [](https://crates.io/crates/esp32h2-hal)
|
||||
[](https://crates.io/crates/esp32h2-hal)
|
||||
[](https://docs.rs/esp32h2-hal)
|
||||
 -->
|
||||

|
||||
[](https://matrix.to/#/#esp-rs:matrix.org)
|
||||
|
||||
`no_std` HAL for the ESP32-H2 from Espressif. Implements a number of the traits defined by [embedded-hal](https://github.com/rust-embedded/embedded-hal).
|
||||
|
||||
This device uses the RISC-V ISA, which is officially supported by the Rust compiler via the `riscv32imac-unknown-none-elf` target. Refer to the [Getting Started](#getting-started) section below for more information.
|
||||
|
||||
<!-- ## [Documentation]
|
||||
## [Documentation]
|
||||
|
||||
[documentation]: https://docs.rs/esp32h2-hal/ -->
|
||||
[documentation]: https://docs.rs/esp32h2-hal/
|
||||
|
||||
## Getting Started
|
||||
|
||||
@ -33,7 +33,7 @@ By default, [espflash](https://github.com/esp-rs/espflash) fetches the required
|
||||
|
||||
#### Direct Boot
|
||||
|
||||
Direct Boot allows an application stored in the External Flash to be executed directly, without being copied into Internal RAM.
|
||||
[Direct Boot](https://github.com/espressif/esp32c3-direct-boot-example#direct-boot-in-esp32-c3) allows an application stored in the External Flash to be executed directly, without being copied into Internal RAM.
|
||||
|
||||
##### Booting the Hello World example using Direct Boot
|
||||
|
||||
@ -73,4 +73,4 @@ at your option.
|
||||
|
||||
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.
|
||||
any additional terms or conditions.
|
||||
|
||||
@ -9,7 +9,7 @@ use esp32h2_hal::{
|
||||
clock::ClockControl,
|
||||
peripherals::Peripherals,
|
||||
prelude::*,
|
||||
rom::crc,
|
||||
rom::{crc, md5},
|
||||
timer::TimerGroup,
|
||||
Rtc,
|
||||
Uart,
|
||||
@ -49,6 +49,7 @@ fn main() -> ! {
|
||||
timer0.start(1u64.secs());
|
||||
|
||||
let data = "123456789";
|
||||
let sentence = "The quick brown fox jumps over a lazy dog";
|
||||
|
||||
writeln!(
|
||||
uart0,
|
||||
@ -75,10 +76,38 @@ fn main() -> ! {
|
||||
assert_eq!(crc_rohc, 0xd0);
|
||||
assert_eq!(crc_smbus, 0xf4);
|
||||
|
||||
// Hash the sentence one word at a time to *really* test the context
|
||||
// Use Peekable while iter_intersperse is unstable
|
||||
let mut md5_ctx = md5::Context::new();
|
||||
let mut it = sentence.split_whitespace().peekable();
|
||||
while let Some(word) = it.next() {
|
||||
md5_ctx.consume(word);
|
||||
if it.peek().is_some() {
|
||||
md5_ctx.consume(" ");
|
||||
}
|
||||
}
|
||||
let md5_digest = md5_ctx.compute();
|
||||
|
||||
assert_eq!(
|
||||
md5_digest,
|
||||
md5::Digest([
|
||||
0x30, 0xde, 0xd8, 0x07, 0xd6, 0x5e, 0xe0, 0x37, 0x0f, 0xc6, 0xd7, 0x3d, 0x6a, 0xb5,
|
||||
0x5a, 0x95
|
||||
])
|
||||
);
|
||||
|
||||
writeln!(
|
||||
uart0,
|
||||
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x}",
|
||||
crc_hdlc, crc_bzip2, crc_mpeg2, crc_cksum, crc_kermit, crc_genibus, crc_rohc, crc_smbus
|
||||
"{:08x} {:08x} {:08x} {:08x} {:04x} {:04x} {:02x} {:02x} {}",
|
||||
crc_hdlc,
|
||||
crc_bzip2,
|
||||
crc_mpeg2,
|
||||
crc_cksum,
|
||||
crc_kermit,
|
||||
crc_genibus,
|
||||
crc_rohc,
|
||||
crc_smbus,
|
||||
md5_digest
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user