From a571bf6013ab135ec6cb45ebbc619ff344bc5ced Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Thu, 5 Jan 2023 11:14:46 -0800 Subject: [PATCH 01/64] Create the `esp32c6-hal` package --- esp-hal.code-workspace | 3 + esp32c6-hal/.cargo/config.toml | 20 +++ esp32c6-hal/Cargo.toml | 76 ++++++++ esp32c6-hal/README.md | 76 ++++++++ esp32c6-hal/build.rs | 74 ++++++++ esp32c6-hal/ld/bl-esp32c6-memory.x | 43 +++++ esp32c6-hal/ld/bl-linkall.x | 3 + esp32c6-hal/ld/bl-riscv-link.x | 260 +++++++++++++++++++++++++++ esp32c6-hal/ld/db-esp32c6-link.x | 14 ++ esp32c6-hal/ld/db-esp32c6-memory.x | 43 +++++ esp32c6-hal/ld/db-linkall.x | 2 + esp32c6-hal/ld/db-riscv-link.x | 238 +++++++++++++++++++++++++ esp32c6-hal/ld/hal-defaults.x | 33 ++++ esp32c6-hal/src/lib.rs | 275 +++++++++++++++++++++++++++++ 14 files changed, 1160 insertions(+) create mode 100644 esp32c6-hal/.cargo/config.toml create mode 100644 esp32c6-hal/Cargo.toml create mode 100644 esp32c6-hal/README.md create mode 100644 esp32c6-hal/build.rs create mode 100644 esp32c6-hal/ld/bl-esp32c6-memory.x create mode 100644 esp32c6-hal/ld/bl-linkall.x create mode 100644 esp32c6-hal/ld/bl-riscv-link.x create mode 100644 esp32c6-hal/ld/db-esp32c6-link.x create mode 100644 esp32c6-hal/ld/db-esp32c6-memory.x create mode 100644 esp32c6-hal/ld/db-linkall.x create mode 100644 esp32c6-hal/ld/db-riscv-link.x create mode 100644 esp32c6-hal/ld/hal-defaults.x create mode 100644 esp32c6-hal/src/lib.rs diff --git a/esp-hal.code-workspace b/esp-hal.code-workspace index 57227a693d1..03134b729f1 100644 --- a/esp-hal.code-workspace +++ b/esp-hal.code-workspace @@ -15,6 +15,9 @@ { "path": "esp32c3-hal" }, + { + "path": "esp32c6-hal" + }, { "path": "esp32s2-hal" }, diff --git a/esp32c6-hal/.cargo/config.toml b/esp32c6-hal/.cargo/config.toml new file mode 100644 index 00000000000..1528b5124bf --- /dev/null +++ b/esp32c6-hal/.cargo/config.toml @@ -0,0 +1,20 @@ +[target.riscv32imc-unknown-none-elf] +runner = "espflash --monitor" +rustflags = [ + "-C", "link-arg=-Tlinkall.x", + "-C", "force-frame-pointers", +] + +# for testing: you can specify this target to see atomic emulation in action +[target.riscv32imac-unknown-none-elf] +runner = "espflash --monitor" +rustflags = [ + "-C", "link-arg=-Tlinkall.x", + "-C", "force-frame-pointers", +] + +[build] +target = "riscv32imc-unknown-none-elf" + +[unstable] +build-std = [ "core" ] diff --git a/esp32c6-hal/Cargo.toml b/esp32c6-hal/Cargo.toml new file mode 100644 index 00000000000..8b5169cf430 --- /dev/null +++ b/esp32c6-hal/Cargo.toml @@ -0,0 +1,76 @@ +[package] +name = "esp32c6-hal" +version = "0.3.0" +authors = [ + "Jesse Braham ", + "Björn Quentin ", +] +edition = "2021" +rust-version = "1.60.0" +description = "HAL for ESP32-C3 microcontrollers" +repository = "https://github.com/esp-rs/esp-hal" +license = "MIT OR Apache-2.0" + +keywords = [ + "embedded", + "embedded-hal", + "esp", + "esp32c3", + "no-std", +] +categories = [ + "embedded", + "hardware-support", + "no-std", +] + +[dependencies] +cfg-if = "1.0.0" +embassy-time = { version = "0.1.0", features = ["nightly"], optional = true } +embedded-hal = { version = "0.2.7", features = ["unproven"] } +embedded-hal-1 = { version = "=1.0.0-alpha.9", optional = true, package = "embedded-hal" } +embedded-hal-async = { version = "0.1.0-alpha.3", optional = true } +embedded-hal-nb = { version = "=1.0.0-alpha.1", optional = true } +esp-hal-common = { version = "0.4.0", features = ["esp32c6"], path = "../esp-hal-common" } +r0 = "1.0.0" +riscv = "0.10.0" +riscv-rt = { version = "0.10.0", optional = true } + +[dev-dependencies] +critical-section = "1.1.1" +embassy-executor = { package = "embassy-executor", git = "https://github.com/embassy-rs/embassy/", rev = "eed34f9", features = ["nightly", "integrated-timers"] } +embedded-graphics = "0.7.1" +esp-backtrace = { git = "https://github.com/jessebraham/esp-backtrace", branch = "feature/chip-support", features = ["esp32c6", "panic-handler", "exception-handler", "print-uart"] } +esp-println = { git = "https://github.com/esp-rs/esp-println", rev = "fc4e9cf", features = ["esp32c6"] } +sha2 = { version = "0.10.6", default-features = false} +smart-leds = "0.3.0" +ssd1306 = "0.7.1" +static_cell = "1.0.0" + +[features] +default = ["rt", "vectored"] +direct-boot = [] +eh1 = ["esp-hal-common/eh1", "dep:embedded-hal-1", "dep:embedded-hal-nb"] +rt = ["riscv-rt"] +smartled = ["esp-hal-common/smartled"] +ufmt = ["esp-hal-common/ufmt"] +vectored = ["esp-hal-common/vectored"] +async = ["esp-hal-common/async", "embedded-hal-async"] +embassy = ["esp-hal-common/embassy"] +embassy-time-systick = ["esp-hal-common/embassy-time-systick", "embassy-time/tick-hz-16_000_000"] + +# [[example]] +# name = "hello_rgb" +# required-features = ["smartled"] + +# [[example]] +# name = "spi_eh1_loopback" +# required-features = ["eh1"] + +# [[example]] +# name = "spi_eh1_device_loopback" +# required-features = ["eh1"] + +# [[example]] +# name = "embassy_hello_world" +# required-features = ["embassy"] diff --git a/esp32c6-hal/README.md b/esp32c6-hal/README.md new file mode 100644 index 00000000000..5f2d29f387b --- /dev/null +++ b/esp32c6-hal/README.md @@ -0,0 +1,76 @@ +# esp32c6-hal + +[![Crates.io](https://img.shields.io/crates/v/esp32c6-hal?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp32c6-hal) +[![docs.rs](https://img.shields.io/docsrs/esp32c6-hal?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.rs/esp32c6-hal) +![Crates.io](https://img.shields.io/crates/l/esp32c6-hal?labelColor=1C2C2E&style=flat-square) +[![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&labelColor=1C2C2E&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org) + +`no_std` HAL for the ESP32-C6 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 `riscv32imc-unknown-none-elf` target. Refer to the [Getting Stared](#getting-started) section below for more information. + +## [Documentation] + +[documentation]: https://docs.rs/esp32c6-hal/ + +## Getting Started + +### Installing the Rust Compiler Target + +The compilation target for this device is officially supported via the `stable` release channel and can be installed via [rustup](https://rustup.rs/): + +```shell +$ rustup target add riscv32imc-unknown-none-elf +``` + +### Supported boot methods + +#### IDF Bootloader + +The [IDF second stage bootloader](https://docs.espressif.com/projects/esp-idf/en/latest/esp32c6/api-guides/startup.html#second-stage-bootloader) is the default bootloader solution. + +By default, [espflash](https://github.com/esp-rs/espflash) fetches the required binaries (Bootloader and Partition Table) and flashes them onto the target device together with the Rust-based application firmware image. + +#### 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. + +##### Booting the Hello World example using Direct Boot + +Build the Hello World example with support for Direct Boot: + +```shell +cargo build --release --example hello_world --features direct-boot +``` + +Then proceed to generating the application binary and flashing it onto the target device: + +```shell +cargo espflash --release --format direct-boot --features direct-boot --example hello_world --monitor +``` + +The ROM Bootloader will identify the firmware image built with Direct Boot support and load it appropriately from the External Flash: + +```shell +ESP-ROM:esp32c6-api1-20210207 +Build:Feb 7 2021 +rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT) +Hello world! +Hello world! +Hello world! +``` + +## License + +Licensed under either of: + +- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +- MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in +the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without +any additional terms or conditions. diff --git a/esp32c6-hal/build.rs b/esp32c6-hal/build.rs new file mode 100644 index 00000000000..940c2dec7c1 --- /dev/null +++ b/esp32c6-hal/build.rs @@ -0,0 +1,74 @@ +use std::{env, fs::File, io::Write, path::PathBuf}; + +#[cfg(feature = "direct-boot")] +fn main() { + // Put the linker script somewhere the linker can find it + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("ld/db-esp32c6-memory.x")) + .unwrap(); + + File::create(out.join("esp32c6-link.x")) + .unwrap() + .write_all(include_bytes!("ld/db-esp32c6-link.x")) + .unwrap(); + + File::create(out.join("riscv-link.x")) + .unwrap() + .write_all(include_bytes!("ld/db-riscv-link.x")) + .unwrap(); + + File::create(out.join("linkall.x")) + .unwrap() + .write_all(include_bytes!("ld/db-linkall.x")) + .unwrap(); + + println!("cargo:rustc-link-search={}", out.display()); + + // Only re-run the build script when memory.x is changed, + // instead of when any part of the source code changes. + println!("cargo:rerun-if-changed=ld/memory.x"); + + add_defaults(); +} + +#[cfg(not(feature = "direct-boot"))] +fn main() { + // Put the linker script somewhere the linker can find it + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + File::create(out.join("memory.x")) + .unwrap() + .write_all(include_bytes!("ld/bl-esp32c6-memory.x")) + .unwrap(); + + File::create(out.join("bl-riscv-link.x")) + .unwrap() + .write_all(include_bytes!("ld/bl-riscv-link.x")) + .unwrap(); + + File::create(out.join("linkall.x")) + .unwrap() + .write_all(include_bytes!("ld/bl-linkall.x")) + .unwrap(); + + println!("cargo:rustc-link-search={}", out.display()); + + // Only re-run the build script when memory.x is changed, + // instead of when any part of the source code changes. + println!("cargo:rerun-if-changed=ld/memory.x"); + + add_defaults(); +} + +fn add_defaults() { + let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap()); + + File::create(out.join("hal-defaults.x")) + .unwrap() + .write_all(include_bytes!("ld/hal-defaults.x")) + .unwrap(); + + println!("cargo:rustc-link-search={}", out.display()); +} diff --git a/esp32c6-hal/ld/bl-esp32c6-memory.x b/esp32c6-hal/ld/bl-esp32c6-memory.x new file mode 100644 index 00000000000..01051a5b51c --- /dev/null +++ b/esp32c6-hal/ld/bl-esp32c6-memory.x @@ -0,0 +1,43 @@ +MEMORY +{ + /* MEMORY_MAP = [ + [0x00000000, 0x00010000, "PADDING"], + [0x42800000, 0x43000000, "DROM"], + [0x40800000, 0x40880000, "DRAM"], + [0x40800000, 0x40880000, "BYTE_ACCESSIBLE"], + [0x4004AC00, 0x40050000, "DROM_MASK"], + [0x40000000, 0x4004AC00, "IROM_MASK"], + [0x42000000, 0x42800000, "IROM"], + [0x40800000, 0x40880000, "IRAM"], + [0x50000000, 0x50004000, "RTC_IRAM"], + [0x50000000, 0x50004000, "RTC_DRAM"], + [0x600FE000, 0x60100000, "MEM_INTERNAL2"], + ] */ + + /* 512K of on soc RAM, 32K reserved for cache */ + ICACHE : ORIGIN = 0x40800000, LENGTH = 32K + /* Instruction RAM */ + IRAM : ORIGIN = 0x40800000 + 32K, LENGTH = 512K - 32K + /* Data RAM */ + DRAM : ORIGIN = 0x40800000 + 32K, LENGTH = 512K - 32K + + /* External flash */ + /* Instruction ROM */ + IROM : ORIGIN = 0x42000000 + 0x20, LENGTH = 0x400000 - 0x20 + /* Data ROM */ + DROM : ORIGIN = 0x42800000, LENGTH = 0x400000 + + /* RTC fast memory (executable). Persists over deep sleep. */ + RTC_FAST : ORIGIN = 0x50000000, LENGTH = 16K /*- ESP_BOOTLOADER_RESERVE_RTC*/ +} + +REGION_ALIAS("REGION_TEXT", IROM); +REGION_ALIAS("REGION_RODATA", DROM); + +REGION_ALIAS("REGION_DATA", DRAM); +REGION_ALIAS("REGION_BSS", DRAM); +REGION_ALIAS("REGION_HEAP", DRAM); +REGION_ALIAS("REGION_STACK", DRAM); + +REGION_ALIAS("REGION_RWTEXT", IRAM); +REGION_ALIAS("REGION_RTC_FAST", RTC_FAST); diff --git a/esp32c6-hal/ld/bl-linkall.x b/esp32c6-hal/ld/bl-linkall.x new file mode 100644 index 00000000000..9fbe9cd3584 --- /dev/null +++ b/esp32c6-hal/ld/bl-linkall.x @@ -0,0 +1,3 @@ +INCLUDE "memory.x" +INCLUDE "bl-riscv-link.x" +INCLUDE "hal-defaults.x" diff --git a/esp32c6-hal/ld/bl-riscv-link.x b/esp32c6-hal/ld/bl-riscv-link.x new file mode 100644 index 00000000000..abf1bc0badb --- /dev/null +++ b/esp32c6-hal/ld/bl-riscv-link.x @@ -0,0 +1,260 @@ +ENTRY(_start_hal) +PROVIDE(_start_trap = _start_trap_hal); + +PROVIDE(_stext = ORIGIN(REGION_TEXT)); +PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK)); +PROVIDE(_max_hart_id = 0); +PROVIDE(_hart_stack_size = 2K); +PROVIDE(_heap_size = 0); + +PROVIDE(UserSoft = DefaultHandler); +PROVIDE(SupervisorSoft = DefaultHandler); +PROVIDE(MachineSoft = DefaultHandler); +PROVIDE(UserTimer = DefaultHandler); +PROVIDE(SupervisorTimer = DefaultHandler); +PROVIDE(MachineTimer = DefaultHandler); +PROVIDE(UserExternal = DefaultHandler); +PROVIDE(SupervisorExternal = DefaultHandler); +PROVIDE(MachineExternal = DefaultHandler); + +PROVIDE(DefaultHandler = DefaultInterruptHandler); +PROVIDE(ExceptionHandler = DefaultExceptionHandler); + +/* # Pre-initialization function */ +/* If the user overrides this using the `#[pre_init]` attribute or by creating a `__pre_init` function, + then the function this points to will be called before the RAM is initialized. */ +PROVIDE(__pre_init = default_pre_init); + +/* A PAC/HAL defined routine that should initialize custom interrupt controller if needed. */ +PROVIDE(_setup_interrupts = default_setup_interrupts); + +/* # Multi-processing hook function + fn _mp_hook() -> bool; + + This function is called from all the harts and must return true only for one hart, + which will perform memory initialization. For other harts it must return false + and implement wake-up in platform-dependent way (e.g. after waiting for a user interrupt). +*/ +PROVIDE(_mp_hook = default_mp_hook); + +/* # Start trap function override + By default uses the riscv crates default trap handler + but by providing the `_start_trap` symbol external crates can override. +*/ +PROVIDE(_start_trap = default_start_trap); + +SECTIONS +{ + .text.dummy (NOLOAD) : + { + /* This section is intended to make _stext address work */ + . = ABSOLUTE(_stext); + } > REGION_TEXT + + .text _stext : + { + _stext = .; + /* Put reset handler first in .text section so it ends up as the entry */ + /* point of the program. */ + KEEP(*(.init)); + KEEP(*(.init.rust)); + KEEP(*(.text.abort)); + . = ALIGN(4); + KEEP(*(.trap)); + KEEP(*(.trap.rust)); + + *(.text .text.*); + _etext = .; + } > REGION_TEXT + + /** + * This dummy section represents the .text section but in rodata. + * Thus, it must have its alignement and (at least) its size. + */ + .text_dummy (NOLOAD): + { + /* Start at the same alignement constraint than .text */ + . = ALIGN(ALIGNOF(.text)); + /* Create an empty gap as big as .text section */ + . = . + SIZEOF(.text); + /* Prepare the alignement of the section above. Few bytes (0x20) must be + * added for the mapping header. */ + . = ALIGN(0x10000) + 0x20; + } > REGION_RODATA + + .rodata : ALIGN(4) + { + _srodata = .; + *(.srodata .srodata.*); + *(.rodata .rodata.*); + + /* 4-byte align the end (VMA) of this section. + This is required by LLD to ensure the LMA of the following .data + section will have the correct alignment. */ + . = ALIGN(4); + _erodata = .; + } > REGION_RODATA + + .rwtext : ALIGN(4) { + _irwtext = LOADADDR(.rwtext); + _srwtext = .; + *(.rwtext); + + *(.iram1) + *(.iram1.*) + + *(.wifi0iram .wifi0iram.*) + *(.wifirxiram .wifirxiram.*) + *(.wifislpiram .wifislpiram.*) + *(.wifislprxiram .wifislprxiram.*) + + . = ALIGN(4); + _erwtext = .; + } > REGION_RWTEXT + + /* similar as text_dummy */ + .ram_dummy (NOLOAD) : { + . = ALIGN(ALIGNOF(.rwtext)); + . = . + SIZEOF(.rwtext); + } > REGION_DATA + + .data : ALIGN(8) + { + _sidata = LOADADDR(.data); + _sdata = .; + /* Must be called __global_pointer$ for linker relaxations to work. */ + PROVIDE(__global_pointer$ = . + 0x800); + *(.sdata .sdata.* .sdata2 .sdata2.*); + *(.data .data.*); + *(.data1) + + . = ALIGN(8); + _edata = .; + } > REGION_DATA + + .bss (NOLOAD) : + { + . = ALIGN(8); + _sbss = .; + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.sbss .sbss.* .bss .bss.*); + *(.share.mem) + *(.gnu.linkonce.b.*) + *(COMMON) + + . = ALIGN(8); + _ebss = .; + } > REGION_BSS + + .uninit (NOLOAD) : ALIGN(4) + { + . = ALIGN(4); + __suninit = .; + *(.uninit .uninit.*); + . = ALIGN(4); + __euninit = .; + } > REGION_BSS + + /* fictitious region that represents the memory available for the heap */ + .heap (NOLOAD) : + { + _sheap = .; + _heap_start = .; + . += _heap_size; + . = ALIGN(4); + _eheap = .; + } > REGION_HEAP + + /* fictitious region that represents the memory available for the stack */ + .stack (NOLOAD) : + { + _estack = .; + . = ABSOLUTE(_stack_start); + _sstack = .; + } > REGION_STACK + + .rtc_fast.text : ALIGN(4) { + *(.rtc_fast.literal .rtc_fast.text .rtc_fast.literal.* .rtc_fast.text.*) + } > REGION_RTC_FAST AT > REGION_RODATA + + .rtc_fast.data : ALIGN(4) + { + _rtc_fast_data_start = ABSOLUTE(.); + *(.rtc_fast.data .rtc_fast.data.*) + _rtc_fast_data_end = ABSOLUTE(.); + } > REGION_RTC_FAST AT > REGION_RODATA + + .rtc_fast.bss (NOLOAD) : ALIGN(4) + { + _rtc_fast_bss_start = ABSOLUTE(.); + *(.rtc_fast.bss .rtc_fast.bss.*) + _rtc_fast_bss_end = ABSOLUTE(.); + } > REGION_RTC_FAST + + .rtc_fast.noinit (NOLOAD) : ALIGN(4) + { + *(.rtc_fast.noinit .rtc_fast.noinit.*) + } > REGION_RTC_FAST + + .eh_frame (INFO) : { KEEP(*(.eh_frame)) } + .eh_frame_hdr (INFO) : { *(.eh_frame_hdr) } +} + +/* Do not exceed this mark in the error messages above | */ +ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned"); + +ASSERT(ORIGIN(REGION_RODATA) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned"); + +ASSERT(ORIGIN(REGION_DATA) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned"); + +ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned"); + +ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned"); + +ASSERT(ORIGIN(REGION_STACK) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_STACK must be 4-byte aligned"); + +ASSERT(_stext % 4 == 0, " +ERROR(riscv-rt): `_stext` must be 4-byte aligned"); + +ASSERT(_sdata % 4 == 0 && _edata % 4 == 0, " +BUG(riscv-rt): .data is not 4-byte aligned"); + +ASSERT(_sidata % 4 == 0, " +BUG(riscv-rt): the LMA of .data is not 4-byte aligned"); + +ASSERT(_sbss % 4 == 0 && _ebss % 4 == 0, " +BUG(riscv-rt): .bss is not 4-byte aligned"); + +ASSERT(_sheap % 4 == 0, " +BUG(riscv-rt): start of .heap is not 4-byte aligned"); + +ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), " +ERROR(riscv-rt): The .text section must be placed inside the REGION_TEXT region. +Set _stext to an address smaller than 'ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT)'"); + +ASSERT(SIZEOF(.stack) > (_max_hart_id + 1) * _hart_stack_size, " +ERROR(riscv-rt): .stack section is too small for allocating stacks for all the harts. +Consider changing `_max_hart_id` or `_hart_stack_size`."); + +ASSERT(SIZEOF(.got) == 0, " +.got section detected in the input files. Dynamic relocations are not +supported. If you are linking to C code compiled using the `gcc` crate +then modify your build script to compile the C code _without_ the +-fPIC flag. See the documentation of the `gcc::Config.fpic` method for +details."); + +/* Do not exceed this mark in the error messages above | */ diff --git a/esp32c6-hal/ld/db-esp32c6-link.x b/esp32c6-hal/ld/db-esp32c6-link.x new file mode 100644 index 00000000000..63ba963a232 --- /dev/null +++ b/esp32c6-hal/ld/db-esp32c6-link.x @@ -0,0 +1,14 @@ +INCLUDE memory.x + +SECTIONS +{ + .header : AT(0) + { + LONG(0xaedb041d) + LONG(0xaedb041d) + } > IROM +} + +_stext = ORIGIN(IROM) + 8; + +INCLUDE riscv-link.x diff --git a/esp32c6-hal/ld/db-esp32c6-memory.x b/esp32c6-hal/ld/db-esp32c6-memory.x new file mode 100644 index 00000000000..7d8500f2cbd --- /dev/null +++ b/esp32c6-hal/ld/db-esp32c6-memory.x @@ -0,0 +1,43 @@ +MEMORY +{ + /* MEMORY_MAP = [ + [0x00000000, 0x00010000, "PADDING"], + [0x42800000, 0x43000000, "DROM"], + [0x40800000, 0x40880000, "DRAM"], + [0x40800000, 0x40880000, "BYTE_ACCESSIBLE"], + [0x4004AC00, 0x40050000, "DROM_MASK"], + [0x40000000, 0x4004AC00, "IROM_MASK"], + [0x42000000, 0x42800000, "IROM"], + [0x40800000, 0x40880000, "IRAM"], + [0x50000000, 0x50004000, "RTC_IRAM"], + [0x50000000, 0x50004000, "RTC_DRAM"], + [0x600FE000, 0x60100000, "MEM_INTERNAL2"], + ] */ + + /* 512K of on soc RAM, 32K reserved for cache */ + ICACHE : ORIGIN = 0x40800000, LENGTH = 32K + /* Instruction RAM */ + IRAM : ORIGIN = 0x40800000 + 32K, LENGTH = 512K - 32K + /* Data RAM */ + DRAM : ORIGIN = 0x40800000 + 32K, LENGTH = 512K - 32K + + /* External flash */ + /* Instruction ROM */ + IROM : ORIGIN = 0x42000000, LENGTH = 0x400000 + /* Data ROM */ + DROM : ORIGIN = 0x42800000, LENGTH = 0x400000 + + /* RTC fast memory (executable). Persists over deep sleep. */ + RTC_FAST : ORIGIN = 0x50000000, LENGTH = 16K /*- ESP_BOOTLOADER_RESERVE_RTC*/ +} + +REGION_ALIAS("REGION_TEXT", IROM); +REGION_ALIAS("REGION_RODATA", DROM); + +REGION_ALIAS("REGION_DATA", DRAM); +REGION_ALIAS("REGION_BSS", DRAM); +REGION_ALIAS("REGION_HEAP", DRAM); +REGION_ALIAS("REGION_STACK", DRAM); + +REGION_ALIAS("REGION_RWTEXT", IRAM); +REGION_ALIAS("REGION_RTC_FAST", RTC_FAST); diff --git a/esp32c6-hal/ld/db-linkall.x b/esp32c6-hal/ld/db-linkall.x new file mode 100644 index 00000000000..6e994af0107 --- /dev/null +++ b/esp32c6-hal/ld/db-linkall.x @@ -0,0 +1,2 @@ +INCLUDE "esp32c6-link.x" +INCLUDE "hal-defaults.x" diff --git a/esp32c6-hal/ld/db-riscv-link.x b/esp32c6-hal/ld/db-riscv-link.x new file mode 100644 index 00000000000..b75f8dadd7c --- /dev/null +++ b/esp32c6-hal/ld/db-riscv-link.x @@ -0,0 +1,238 @@ +ENTRY(_start_hal) +PROVIDE(_start_trap = _start_trap_hal); + +PROVIDE(_stext = ORIGIN(REGION_TEXT)); +PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK)); +PROVIDE(_max_hart_id = 0); +PROVIDE(_hart_stack_size = 2K); +PROVIDE(_heap_size = 0); + +PROVIDE(UserSoft = DefaultHandler); +PROVIDE(SupervisorSoft = DefaultHandler); +PROVIDE(MachineSoft = DefaultHandler); +PROVIDE(UserTimer = DefaultHandler); +PROVIDE(SupervisorTimer = DefaultHandler); +PROVIDE(MachineTimer = DefaultHandler); +PROVIDE(UserExternal = DefaultHandler); +PROVIDE(SupervisorExternal = DefaultHandler); +PROVIDE(MachineExternal = DefaultHandler); + +PROVIDE(DefaultHandler = DefaultInterruptHandler); +PROVIDE(ExceptionHandler = DefaultExceptionHandler); + +/* # Pre-initialization function */ +/* If the user overrides this using the `#[pre_init]` attribute or by creating a `__pre_init` function, + then the function this points to will be called before the RAM is initialized. */ +PROVIDE(__pre_init = default_pre_init); + +/* A PAC/HAL defined routine that should initialize custom interrupt controller if needed. */ +PROVIDE(_setup_interrupts = default_setup_interrupts); + +/* # Multi-processing hook function + fn _mp_hook() -> bool; + + This function is called from all the harts and must return true only for one hart, + which will perform memory initialization. For other harts it must return false + and implement wake-up in platform-dependent way (e.g. after waiting for a user interrupt). +*/ +PROVIDE(_mp_hook = default_mp_hook); + +SECTIONS +{ + .text.dummy (NOLOAD) : + { + /* This section is intended to make _stext address work */ + . = ABSOLUTE(_stext); + } > REGION_TEXT + + .text _stext : + { + /* Put reset handler first in .text section so it ends up as the entry */ + /* point of the program. */ + KEEP(*(.init)); + KEEP(*(.init.rust)); + KEEP(*(.text.abort)); + . = ALIGN(4); + KEEP(*(.trap)); + KEEP(*(.trap.rust)); + + *(.text .text.*); + _etext = .; + } > REGION_TEXT + + _text_size = _etext - _stext + 8; + .rodata ORIGIN(DROM) + _text_size : AT(_text_size) + { + _srodata = .; + *(.srodata .srodata.*); + *(.rodata .rodata.*); + + /* 4-byte align the end (VMA) of this section. + This is required by LLD to ensure the LMA of the following .data + section will have the correct alignment. */ + . = ALIGN(4); + _erodata = .; + } > REGION_RODATA + + _rodata_size = _erodata - _srodata + 8; + .data ORIGIN(DRAM) : AT(_text_size + _rodata_size) + { + _sdata = .; + /* Must be called __global_pointer$ for linker relaxations to work. */ + PROVIDE(__global_pointer$ = . + 0x800); + *(.sdata .sdata.* .sdata2 .sdata2.*); + *(.data .data.*); + . = ALIGN(4); + _edata = .; + } > REGION_DATA + + _data_size = _edata - _sdata + 8; + .rwtext ORIGIN(REGION_RWTEXT) + _data_size : AT(_text_size + _rodata_size + _data_size){ + _srwtext = .; + *(.rwtext); + . = ALIGN(4); + _erwtext = .; + } > REGION_RWTEXT + _rwtext_size = _erwtext - _srwtext + 8; + + .rwtext.dummy (NOLOAD): + { + /* This section is required to skip .rwtext area because REGION_RWTEXT + * and REGION_BSS reflect the same address space on different buses. + */ + . = ORIGIN(REGION_BSS) + _rwtext_size; + } > REGION_BSS + + .bss (NOLOAD) : + { + _sbss = .; + *(.sbss .sbss.* .bss .bss.*); + . = ALIGN(4); + _ebss = .; + } > REGION_BSS + + /* ### .uninit */ + .uninit (NOLOAD) : ALIGN(4) + { + . = ALIGN(4); + __suninit = .; + *(.uninit .uninit.*); + . = ALIGN(4); + __euninit = .; + } > REGION_BSS + + /* fictitious region that represents the memory available for the heap */ + .heap (NOLOAD) : + { + _sheap = .; + . += _heap_size; + . = ALIGN(4); + _eheap = .; + } > REGION_HEAP + + /* fictitious region that represents the memory available for the stack */ + .stack (NOLOAD) : + { + _estack = .; + . = ABSOLUTE(_stack_start); + _sstack = .; + } > REGION_STACK + + .rtc_fast.text : AT(_text_size + _rodata_size + _data_size + _rwtext_size) { + _srtc_fast_text = .; + *(.rtc_fast.literal .rtc_fast.text .rtc_fast.literal.* .rtc_fast.text.*) + . = ALIGN(4); + _ertc_fast_text = .; + } > REGION_RTC_FAST + _fast_text_size = _ertc_fast_text - _srtc_fast_text + 8; + + .rtc_fast.data : AT(_text_size + _rodata_size + _data_size + _rwtext_size + _fast_text_size) + { + _rtc_fast_data_start = ABSOLUTE(.); + *(.rtc_fast.data .rtc_fast.data.*) + . = ALIGN(4); + _rtc_fast_data_end = ABSOLUTE(.); + } > REGION_RTC_FAST + _rtc_fast_data_size = _rtc_fast_data_end - _rtc_fast_data_start + 8; + + .rtc_fast.bss (NOLOAD) : ALIGN(4) + { + _rtc_fast_bss_start = ABSOLUTE(.); + *(.rtc_fast.bss .rtc_fast.bss.*) + . = ALIGN(4); + _rtc_fast_bss_end = ABSOLUTE(.); + } > REGION_RTC_FAST + + .rtc_fast.noinit (NOLOAD) : ALIGN(4) + { + *(.rtc_fast.noinit .rtc_fast.noinit.*) + } > REGION_RTC_FAST + + /* fake output .got section */ + /* Dynamic relocations are unsupported. This section is only used to detect + relocatable code in the input files and raise an error if relocatable code + is found */ + .got (INFO) : + { + KEEP(*(.got .got.*)); + } + + .eh_frame (INFO) : { KEEP(*(.eh_frame)) } + .eh_frame_hdr (INFO) : { *(.eh_frame_hdr) } +} + +PROVIDE(_sidata = _erodata + 8); +PROVIDE(_irwtext = ORIGIN(DROM) + _text_size + _rodata_size + _data_size); +PROVIDE(_irtc_fast_text = ORIGIN(DROM) + _text_size + _rodata_size + _data_size + _rwtext_size); +PROVIDE(_irtc_fast_data = ORIGIN(DROM) + _text_size + _rodata_size + _data_size + _rwtext_size + _fast_text_size); + +/* Do not exceed this mark in the error messages above | */ +ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned"); + +ASSERT(ORIGIN(REGION_RODATA) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned"); + +ASSERT(ORIGIN(REGION_DATA) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned"); + +ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned"); + +ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned"); + +ASSERT(ORIGIN(REGION_STACK) % 4 == 0, " +ERROR(riscv-rt): the start of the REGION_STACK must be 4-byte aligned"); + +ASSERT(_stext % 4 == 0, " +ERROR(riscv-rt): `_stext` must be 4-byte aligned"); + +ASSERT(_sdata % 4 == 0 && _edata % 4 == 0, " +BUG(riscv-rt): .data is not 4-byte aligned"); + +ASSERT(_sidata % 4 == 0, " +BUG(riscv-rt): the LMA of .data is not 4-byte aligned"); + +ASSERT(_sbss % 4 == 0 && _ebss % 4 == 0, " +BUG(riscv-rt): .bss is not 4-byte aligned"); + +ASSERT(_sheap % 4 == 0, " +BUG(riscv-rt): start of .heap is not 4-byte aligned"); + +ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), " +ERROR(riscv-rt): The .text section must be placed inside the REGION_TEXT region. +Set _stext to an address smaller than 'ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT)'"); + +ASSERT(SIZEOF(.stack) > (_max_hart_id + 1) * _hart_stack_size, " +ERROR(riscv-rt): .stack section is too small for allocating stacks for all the harts. +Consider changing `_max_hart_id` or `_hart_stack_size`."); + +ASSERT(SIZEOF(.got) == 0, " +.got section detected in the input files. Dynamic relocations are not +supported. If you are linking to C code compiled using the `gcc` crate +then modify your build script to compile the C code _without_ the +-fPIC flag. See the documentation of the `gcc::Config.fpic` method for +details."); + +/* Do not exceed this mark in the error messages above | */ diff --git a/esp32c6-hal/ld/hal-defaults.x b/esp32c6-hal/ld/hal-defaults.x new file mode 100644 index 00000000000..a7bbdbb0bb7 --- /dev/null +++ b/esp32c6-hal/ld/hal-defaults.x @@ -0,0 +1,33 @@ +PROVIDE(interrupt1 = DefaultHandler); +PROVIDE(interrupt2 = DefaultHandler); +PROVIDE(interrupt3 = DefaultHandler); +PROVIDE(interrupt4 = DefaultHandler); +PROVIDE(interrupt5 = DefaultHandler); +PROVIDE(interrupt6 = DefaultHandler); +PROVIDE(interrupt7 = DefaultHandler); +PROVIDE(interrupt8 = DefaultHandler); +PROVIDE(interrupt9 = DefaultHandler); +PROVIDE(interrupt10 = DefaultHandler); +PROVIDE(interrupt11 = DefaultHandler); +PROVIDE(interrupt12 = DefaultHandler); +PROVIDE(interrupt13 = DefaultHandler); +PROVIDE(interrupt14 = DefaultHandler); +PROVIDE(interrupt15 = DefaultHandler); +PROVIDE(interrupt16 = DefaultHandler); +PROVIDE(interrupt17 = DefaultHandler); +PROVIDE(interrupt18 = DefaultHandler); +PROVIDE(interrupt19 = DefaultHandler); +PROVIDE(interrupt20 = DefaultHandler); +PROVIDE(interrupt21 = DefaultHandler); +PROVIDE(interrupt22 = DefaultHandler); +PROVIDE(interrupt23 = DefaultHandler); +PROVIDE(interrupt24 = DefaultHandler); +PROVIDE(interrupt25 = DefaultHandler); +PROVIDE(interrupt26 = DefaultHandler); +PROVIDE(interrupt27 = DefaultHandler); +PROVIDE(interrupt28 = DefaultHandler); +PROVIDE(interrupt29 = DefaultHandler); +PROVIDE(interrupt30 = DefaultHandler); +PROVIDE(interrupt31 = DefaultHandler); + +INCLUDE "device.x" diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs new file mode 100644 index 00000000000..220175b7519 --- /dev/null +++ b/esp32c6-hal/src/lib.rs @@ -0,0 +1,275 @@ +#![no_std] + +use core::arch::{asm, global_asm}; + +pub use embedded_hal as ehal; +pub use esp_hal_common::{macros, peripherals}; + +// pub use self::gpio::IO; + +// /// Common module for analog functions +// pub mod analog { +// pub use esp_hal_common::analog::{AvailableAnalog, SarAdcExt}; +// } + +extern "C" { + // Boundaries of the .iram section + static mut _srwtext: u32; + static mut _erwtext: u32; + static mut _irwtext: u32; + + // Boundaries of the .bss section + static mut _ebss: u32; + static mut _sbss: u32; + + // Boundaries of the rtc .bss section + static mut _rtc_fast_bss_start: u32; + static mut _rtc_fast_bss_end: u32; + + // Boundaries of the .rtc_fast.text section + static mut _srtc_fast_text: u32; + static mut _ertc_fast_text: u32; + static mut _irtc_fast_text: u32; + + // Boundaries of the .rtc_fast.data section + static mut _rtc_fast_data_start: u32; + static mut _rtc_fast_data_end: u32; + static mut _irtc_fast_data: u32; +} + +global_asm!( + r#" +.section .trap, "ax" +.balign 0x100 +.global _vector_table_hal +.type _vector_table_hal, @function +.option norelax + +_vector_table_hal: + .option push + .option norvc + .rept 31 + j _start_trap_hal + .endr +"# +); + +global_asm!( + r#" + /* + Trap entry point (_start_trap_hal) + Saves registers and calls _start_trap_rust_hal, + restores registers and then returns. +*/ +.section .trap, "ax" +.global _start_trap_hal +.option norelax +.align 6 + +_start_trap_hal: + addi sp, sp, -40*4 + + sw ra, 0*4(sp) + sw t0, 1*4(sp) + sw t1, 2*4(sp) + sw t2, 3*4(sp) + sw t3, 4*4(sp) + sw t4, 5*4(sp) + sw t5, 6*4(sp) + sw t6, 7*4(sp) + sw a0, 8*4(sp) + sw a1, 9*4(sp) + sw a2, 10*4(sp) + sw a3, 11*4(sp) + sw a4, 12*4(sp) + sw a5, 13*4(sp) + sw a6, 14*4(sp) + sw a7, 15*4(sp) + sw s0, 16*4(sp) + sw s1, 17*4(sp) + sw s2, 18*4(sp) + sw s3, 19*4(sp) + sw s4, 20*4(sp) + sw s5, 21*4(sp) + sw s6, 22*4(sp) + sw s7, 23*4(sp) + sw s8, 24*4(sp) + sw s9, 25*4(sp) + sw s10, 26*4(sp) + sw s11, 27*4(sp) + sw gp, 28*4(sp) + sw tp, 29*4(sp) + csrrs t1, mepc, x0 + sw t1, 31*4(sp) + csrrs t1, mstatus, x0 + sw t1, 32*4(sp) + csrrs t1, mcause, x0 + sw t1, 33*4(sp) + csrrs t1, mtval, x0 + sw t1, 34*4(sp) + + addi s0, sp, 40*4 + sw s0, 30*4(sp) + + add a0, sp, zero + // jal ra, _start_trap_rust_hal + + lw t1, 31*4(sp) + csrrw x0, mepc, t1 + + lw t1, 32*4(sp) + csrrw x0, mstatus, t1 + + lw ra, 0*4(sp) + lw t0, 1*4(sp) + lw t1, 2*4(sp) + lw t2, 3*4(sp) + lw t3, 4*4(sp) + lw t4, 5*4(sp) + lw t5, 6*4(sp) + lw t6, 7*4(sp) + lw a0, 8*4(sp) + lw a1, 9*4(sp) + lw a2, 10*4(sp) + lw a3, 11*4(sp) + lw a4, 12*4(sp) + lw a5, 13*4(sp) + lw a6, 14*4(sp) + lw a7, 15*4(sp) + lw s0, 16*4(sp) + lw s1, 17*4(sp) + lw s2, 18*4(sp) + lw s3, 19*4(sp) + lw s4, 20*4(sp) + lw s5, 21*4(sp) + lw s6, 22*4(sp) + lw s7, 23*4(sp) + lw s8, 24*4(sp) + lw s9, 25*4(sp) + lw s10, 26*4(sp) + lw s11, 27*4(sp) + lw gp, 28*4(sp) + lw tp, 29*4(sp) + lw sp, 30*4(sp) + + # SP was restored from the original SP + mret + +"# +); + +#[link_section = ".init"] +#[export_name = "_start_hal"] +unsafe fn start_hal() -> ! { + asm!( + r#" + .option norelax + + // unsupported on ESP32-C6 + // csrw mie, 0 + // csrw mip, 0 + + li x1, 0 + li x2, 0 + li x3, 0 + li x4, 0 + li x5, 0 + li x6, 0 + li x7, 0 + li x8, 0 + li x9, 0 + li x10,0 + li x11,0 + li x12,0 + li x13,0 + li x14,0 + li x15,0 + li x16,0 + li x17,0 + li x18,0 + li x19,0 + li x20,0 + li x21,0 + li x22,0 + li x23,0 + li x24,0 + li x25,0 + li x26,0 + li x27,0 + li x28,0 + li x29,0 + li x30,0 + li x31,0 + + .option push + .option norelax + la gp, __global_pointer$ + .option pop + + // Check hart id + csrr a2, mhartid + lui t0, %hi(_max_hart_id) + add t0, t0, %lo(_max_hart_id) + bgtu a2, t0, abort_hal + + // Allocate stacks + la sp, _stack_start + lui t0, %hi(_hart_stack_size) + add t0, t0, %lo(_hart_stack_size) + + beqz a2, 2f // Jump if single-hart + mv t1, a2 + mv t2, t0 + 1: + add t0, t0, t2 + addi t1, t1, -1 + bnez t1, 1b + 2: + sub sp, sp, t0 + + // Set frame pointer + add s0, sp, zero + + jal zero, _start_rust + "# + ); + + unreachable!() +} + +global_asm!( + r#" +/* Make sure there is an abort when linking */ +.globl abort_hal +abort_hal: + j abort_hal +"# +); + +#[allow(unreachable_code)] +#[export_name = "_mp_hook"] +#[doc(hidden)] +#[cfg_attr(feature = "mcu-boot", link_section = ".rwtext")] +pub fn mp_hook() -> bool { + #[cfg(feature = "mcu-boot")] + unsafe { + configure_mmu(); + } + + unsafe { + r0::zero_bss(&mut _rtc_fast_bss_start, &mut _rtc_fast_bss_end); + } + + #[cfg(feature = "direct-boot")] + return true; + + // no init data when using normal boot - but we need to zero out BSS + unsafe { + r0::zero_bss(&mut _sbss, &mut _ebss); + } + + false +} + +#[no_mangle] +extern "C" fn EspDefaultHandler(_interrupt: peripherals::Interrupt) {} From a2c61450eec9cd07827aec6c913266fc8a225ae8 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Fri, 6 Jan 2023 07:17:18 -0800 Subject: [PATCH 02/64] Teach `esp-hal-common` about the ESP32-C6 --- esp-hal-common/Cargo.toml | 2 + esp-hal-common/README.md | 1 + esp-hal-common/build.rs | 17 +++++- esp-hal-common/src/lib.rs | 3 + esp-hal-common/src/peripherals/esp32c6.rs | 71 +++++++++++++++++++++++ 5 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 esp-hal-common/src/peripherals/esp32c6.rs diff --git a/esp-hal-common/Cargo.toml b/esp-hal-common/Cargo.toml index 7aaca8ad0b5..59330a12ed7 100644 --- a/esp-hal-common/Cargo.toml +++ b/esp-hal-common/Cargo.toml @@ -56,6 +56,7 @@ ufmt-write = { version = "0.1.0", optional = true } esp32 = { version = "0.21.0", features = ["critical-section"], optional = true } esp32c2 = { version = "0.8.0", features = ["critical-section"], optional = true } esp32c3 = { version = "0.11.0", features = ["critical-section"], optional = true } +esp32c6 = { path = "C:/Users/JurajSadel/esp-pacs/esp32c6", features = ["critical-section"], optional = true } esp32s2 = { version = "0.12.0", features = ["critical-section"], optional = true } esp32s3 = { version = "0.15.0", features = ["critical-section"], optional = true } @@ -63,6 +64,7 @@ esp32s3 = { version = "0.15.0", features = ["critical-section"], optional = true esp32 = ["esp32/rt" , "xtensa", "xtensa-lx/esp32", "xtensa-lx-rt/esp32", "lock_api", "procmacros/esp32"] esp32c2 = ["esp32c2/rt", "riscv", "procmacros/esp32c2"] esp32c3 = ["esp32c3/rt", "riscv", "procmacros/esp32c3"] +esp32c6 = ["esp32c6/rt", "riscv", "procmacros/esp32c6"] esp32s2 = ["esp32s2/rt", "xtensa", "xtensa-lx/esp32s2", "xtensa-lx-rt/esp32s2", "esp-synopsys-usb-otg", "usb-device", "procmacros/esp32s2"] esp32s3 = ["esp32s3/rt", "xtensa", "xtensa-lx/esp32s3", "xtensa-lx-rt/esp32s3", "lock_api", "esp-synopsys-usb-otg", "usb-device", "procmacros/esp32s3"] diff --git a/esp-hal-common/README.md b/esp-hal-common/README.md index 98fbe61d921..63d364a08a7 100644 --- a/esp-hal-common/README.md +++ b/esp-hal-common/README.md @@ -12,6 +12,7 @@ This crate should not be used directly; you should use one of the device-specifi - [esp32-hal](../esp32-hal/README.md) - [esp32c2-hal](../esp32c2-hal/README.md) - [esp32c3-hal](../esp32c3-hal/README.md) +- [esp32c6-hal](../esp32c6-hal/README.md) - [esp32s2-hal](../esp32s2-hal/README.md) - [esp32s3-hal](../esp32s3-hal/README.md) diff --git a/esp-hal-common/build.rs b/esp-hal-common/build.rs index e57f9ed15e5..5b4ca003ac3 100644 --- a/esp-hal-common/build.rs +++ b/esp-hal-common/build.rs @@ -2,11 +2,12 @@ fn main() { let esp32 = cfg!(feature = "esp32"); let esp32c2 = cfg!(feature = "esp32c2"); let esp32c3 = cfg!(feature = "esp32c3"); + let esp32c6 = cfg!(feature = "esp32c6"); let esp32s2 = cfg!(feature = "esp32s2"); let esp32s3 = cfg!(feature = "esp32s3"); // Ensure that exactly one chip has been specified - let chip_features = [esp32, esp32c2, esp32c3, esp32s2, esp32s3]; + let chip_features = [esp32, esp32c2, esp32c3, esp32c6, esp32s2, esp32s3]; match chip_features.iter().filter(|&&f| f).count() { 1 => {} n => panic!("Exactly 1 chip must be enabled via its Cargo feature, {n} provided"), @@ -94,6 +95,20 @@ fn main() { "aes", "radio", ] + } else if esp32c6 { + vec![ + "esp32c6", + "riscv", + "single_core", + "dac", + "gdma", + "i2s", + "mcpwm", + "rmt", + "systimer", + "timg1", + "usb_serial_jtag", + ] } else if esp32s2 { vec![ "esp32s2", diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index 55147e54008..3bc0617cfc7 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -8,6 +8,7 @@ //! - [esp32-hal] //! - [esp32c2-hal] //! - [esp32c3-hal] +//! - [esp32c6-hal] //! - [esp32s2-hal] //! - [esp32s3-hal] //! @@ -15,6 +16,7 @@ //! [esp32-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32-hal //! [esp32c2-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c2-hal //! [esp32c3-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c3-hal +//! [esp32c6-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c6-hal //! [esp32s2-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32s2-hal //! [esp32s3-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32s3-hal @@ -27,6 +29,7 @@ #[cfg_attr(esp32, path = "peripherals/esp32.rs")] #[cfg_attr(esp32c3, path = "peripherals/esp32c3.rs")] #[cfg_attr(esp32c2, path = "peripherals/esp32c2.rs")] +#[cfg_attr(esp32c6, path = "peripherals/esp32c6.rs")] #[cfg_attr(esp32s2, path = "peripherals/esp32s2.rs")] #[cfg_attr(esp32s3, path = "peripherals/esp32s3.rs")] pub mod peripherals; diff --git a/esp-hal-common/src/peripherals/esp32c6.rs b/esp-hal-common/src/peripherals/esp32c6.rs new file mode 100644 index 00000000000..0b14423a2dd --- /dev/null +++ b/esp-hal-common/src/peripherals/esp32c6.rs @@ -0,0 +1,71 @@ +use esp32c6 as pac; +// We need to export this for users to use +pub use pac::Interrupt; + +// We need to export this in the hal for the drivers to use +pub(crate) use self::peripherals::*; + +crate::peripherals! { + AES, + APB_SARADC, + ASSIST_DEBUG, + ATOMIC, + DMA, + DS, + ECC, + EFUSE, + EXTMEM, + GPIO, + GPIOSD, + HINF, + HMAC, + HP_APM, + HP_SYS, + I2C0, + I2S0, + INTMTX_CORE0, + INTPRI, + IO_MUX, + LEDC, + LPPERI, + LP_ANA, + LP_AON, + LP_APM, + LP_APM0, + LP_CLKRST, + LP_I2C0, + LP_I2C_ANA_MST, + LP_IO, + LP_TEE, + LP_TIMER, + LP_UART, + LP_WDT, + MCPWM, + MEM_MONITOR, + OTP_DEBUG, + PARL_IO, + PAU, + PCNT, + PCR, + PMU, + RMT, + RNG, + RSA, + SHA, + SLCHOST, + SOC_ETM, + SPI0, + SPI1, + SPI2, + SYSTIMER, + TEE, + TIMG0, + TIMG1, + TRACE, + TWAI0, + TWAI1, + UART0, + UART1, + UHCI0, + USB_DEVICE, +} From f358cadd2e9c7594fe97f897336e266d689b3a4e Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Fri, 6 Jan 2023 07:17:31 -0800 Subject: [PATCH 03/64] Get a number of peripheral drivers building for the ESP32-C6 bckup initial clocks_ii --- esp-hal-common/src/clock/mod.rs | 3 +- esp-hal-common/src/clocks_ll/esp32c6.rs | 238 ++++++++++++++++++++++++ esp-hal-common/src/efuse/esp32c6.rs | 62 ++++++ esp-hal-common/src/lib.rs | 78 ++++---- esp-hal-common/src/rom.rs | 2 +- esp-hal-common/src/sha.rs | 2 +- esp-hal-common/src/system.rs | 86 ++++++++- esp-hal-common/src/systimer.rs | 4 +- esp-hal-common/src/timer.rs | 10 +- esp32c6-hal/examples/hello_world.rs | 12 ++ 10 files changed, 437 insertions(+), 60 deletions(-) create mode 100644 esp-hal-common/src/clocks_ll/esp32c6.rs create mode 100644 esp-hal-common/src/efuse/esp32c6.rs create mode 100644 esp32c6-hal/examples/hello_world.rs diff --git a/esp-hal-common/src/clock/mod.rs b/esp-hal-common/src/clock/mod.rs index fa8318e9ac5..c7f266ae750 100644 --- a/esp-hal-common/src/clock/mod.rs +++ b/esp-hal-common/src/clock/mod.rs @@ -9,6 +9,7 @@ use crate::{ #[cfg_attr(esp32, path = "clocks_ll/esp32.rs")] #[cfg_attr(esp32c2, path = "clocks_ll/esp32c2.rs")] #[cfg_attr(esp32c3, path = "clocks_ll/esp32c3.rs")] +#[cfg_attr(esp32c6, path = "clocks_ll/esp32c6.rs")] #[cfg_attr(esp32s2, path = "clocks_ll/esp32s2.rs")] #[cfg_attr(esp32s3, path = "clocks_ll/esp32s3.rs")] mod clocks_ll; @@ -83,7 +84,7 @@ impl Clock for XtalClock { #[allow(unused)] #[derive(Debug, Clone, Copy)] pub(crate) enum PllClock { - #[cfg(not(esp32c2))] + #[cfg(not(any(esp32c2, esp32c6)))] Pll320MHz, Pll480MHz, } diff --git a/esp-hal-common/src/clocks_ll/esp32c6.rs b/esp-hal-common/src/clocks_ll/esp32c6.rs new file mode 100644 index 00000000000..52d8f7df03e --- /dev/null +++ b/esp-hal-common/src/clocks_ll/esp32c6.rs @@ -0,0 +1,238 @@ +use paste::paste; + +use crate::{ + clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock}, + regi2c_write, + regi2c_write_mask, + rom::{ets_update_cpu_frequency, regi2c_ctrl_write_reg, regi2c_ctrl_write_reg_mask}, +}; + +const I2C_BBPLL: u32 = 0x66; +const I2C_BBPLL_HOSTID: u32 = 0; + +const I2C_BBPLL_IR_CAL_DELAY: u32 = 0; +const I2C_BBPLL_IR_CAL_DELAY_MSB: u32 = 3; +const I2C_BBPLL_IR_CAL_DELAY_LSB: u32 = 0; + +const I2C_BBPLL_IR_CAL_CK_DIV: u32 = 0; +const I2C_BBPLL_IR_CAL_CK_DIV_MSB: u32 = 7; +const I2C_BBPLL_IR_CAL_CK_DIV_LSB: u32 = 4; + +const I2C_BBPLL_IR_CAL_EXT_CAP: u32 = 1; +const I2C_BBPLL_IR_CAL_EXT_CAP_MSB: u32 = 3; +const I2C_BBPLL_IR_CAL_EXT_CAP_LSB: u32 = 0; + +const I2C_BBPLL_IR_CAL_ENX_CAP: u32 = 1; +const I2C_BBPLL_IR_CAL_ENX_CAP_MSB: u32 = 4; +const I2C_BBPLL_IR_CAL_ENX_CAP_LSB: u32 = 4; + +const I2C_BBPLL_IR_CAL_RSTB: u32 = 1; +const I2C_BBPLL_IR_CAL_RSTB_MSB: u32 = 5; +const I2C_BBPLL_IR_CAL_RSTB_LSB: u32 = 5; + +const I2C_BBPLL_IR_CAL_START: u32 = 1; +const I2C_BBPLL_IR_CAL_START_MSB: u32 = 6; +const I2C_BBPLL_IR_CAL_START_LSB: u32 = 6; + +const I2C_BBPLL_IR_CAL_UNSTOP: u32 = 1; +const I2C_BBPLL_IR_CAL_UNSTOP_MSB: u32 = 7; +const I2C_BBPLL_IR_CAL_UNSTOP_LSB: u32 = 7; + +const I2C_BBPLL_OC_REF_DIV: u32 = 2; +const I2C_BBPLL_OC_REF_DIV_MSB: u32 = 3; +const I2C_BBPLL_OC_REF_DIV_LSB: u32 = 0; + +const I2C_BBPLL_OC_DCHGP: u32 = 2; +const I2C_BBPLL_OC_DCHGP_MSB: u32 = 6; +const I2C_BBPLL_OC_DCHGP_LSB: u32 = 4; + +const I2C_BBPLL_OC_ENB_FCAL: u32 = 2; +const I2C_BBPLL_OC_ENB_FCAL_MSB: u32 = 7; +const I2C_BBPLL_OC_ENB_FCAL_LSB: u32 = 7; + +const I2C_BBPLL_OC_DIV_7_0: u32 = 3; +const I2C_BBPLL_OC_DIV_7_0_MSB: u32 = 7; +const I2C_BBPLL_OC_DIV_7_0_LSB: u32 = 0; + +const I2C_BBPLL_RSTB_DIV_ADC: u32 = 4; +const I2C_BBPLL_RSTB_DIV_ADC_MSB: u32 = 0; +const I2C_BBPLL_RSTB_DIV_ADC_LSB: u32 = 0; + +const I2C_BBPLL_MODE_HF: u32 = 4; +const I2C_BBPLL_MODE_HF_MSB: u32 = 1; +const I2C_BBPLL_MODE_HF_LSB: u32 = 1; + +const I2C_BBPLL_DIV_ADC: u32 = 4; +const I2C_BBPLL_DIV_ADC_MSB: u32 = 3; +const I2C_BBPLL_DIV_ADC_LSB: u32 = 2; + +const I2C_BBPLL_DIV_DAC: u32 = 4; +const I2C_BBPLL_DIV_DAC_MSB: u32 = 4; +const I2C_BBPLL_DIV_DAC_LSB: u32 = 4; + +const I2C_BBPLL_DIV_CPU: u32 = 4; +const I2C_BBPLL_DIV_CPU_MSB: u32 = 5; +const I2C_BBPLL_DIV_CPU_LSB: u32 = 5; + +const I2C_BBPLL_OC_ENB_VCON: u32 = 4; +const I2C_BBPLL_OC_ENB_VCON_MSB: u32 = 6; +const I2C_BBPLL_OC_ENB_VCON_LSB: u32 = 6; + +const I2C_BBPLL_OC_TSCHGP: u32 = 4; +const I2C_BBPLL_OC_TSCHGP_MSB: u32 = 7; +const I2C_BBPLL_OC_TSCHGP_LSB: u32 = 7; + +const I2C_BBPLL_OC_DR1: u32 = 5; +const I2C_BBPLL_OC_DR1_MSB: u32 = 2; +const I2C_BBPLL_OC_DR1_LSB: u32 = 0; + +const I2C_BBPLL_OC_DR3: u32 = 5; +const I2C_BBPLL_OC_DR3_MSB: u32 = 6; +const I2C_BBPLL_OC_DR3_LSB: u32 = 4; + +const I2C_BBPLL_EN_USB: u32 = 5; +const I2C_BBPLL_EN_USB_MSB: u32 = 7; +const I2C_BBPLL_EN_USB_LSB: u32 = 7; + +const I2C_BBPLL_OC_DCUR: u32 = 6; +const I2C_BBPLL_OC_DCUR_MSB: u32 = 2; +const I2C_BBPLL_OC_DCUR_LSB: u32 = 0; + +const I2C_BBPLL_INC_CUR: u32 = 6; +const I2C_BBPLL_INC_CUR_MSB: u32 = 3; +const I2C_BBPLL_INC_CUR_LSB: u32 = 3; + +const I2C_BBPLL_OC_DHREF_SEL: u32 = 6; +const I2C_BBPLL_OC_DHREF_SEL_MSB: u32 = 5; +const I2C_BBPLL_OC_DHREF_SEL_LSB: u32 = 4; + +const I2C_BBPLL_OC_DLREF_SEL: u32 = 6; +const I2C_BBPLL_OC_DLREF_SEL_MSB: u32 = 7; +const I2C_BBPLL_OC_DLREF_SEL_LSB: u32 = 6; + +const I2C_BBPLL_OR_CAL_CAP: u32 = 8; +const I2C_BBPLL_OR_CAL_CAP_MSB: u32 = 3; +const I2C_BBPLL_OR_CAL_CAP_LSB: u32 = 0; + +const I2C_BBPLL_OR_CAL_UDF: u32 = 8; +const I2C_BBPLL_OR_CAL_UDF_MSB: u32 = 4; +const I2C_BBPLL_OR_CAL_UDF_LSB: u32 = 4; + +const I2C_BBPLL_OR_CAL_OVF: u32 = 8; +const I2C_BBPLL_OR_CAL_OVF_MSB: u32 = 5; +const I2C_BBPLL_OR_CAL_OVF_LSB: u32 = 5; + +const I2C_BBPLL_OR_CAL_END: u32 = 8; +const I2C_BBPLL_OR_CAL_END_MSB: u32 = 6; +const I2C_BBPLL_OR_CAL_END_LSB: u32 = 6; + +const I2C_BBPLL_OR_LOCK: u32 = 8; +const I2C_BBPLL_OR_LOCK_MSB: u32 = 7; +const I2C_BBPLL_OR_LOCK_LSB: u32 = 7; + +const I2C_BBPLL_OC_VCO_DBIAS: u32 = 9; +const I2C_BBPLL_OC_VCO_DBIAS_MSB: u32 = 1; +const I2C_BBPLL_OC_VCO_DBIAS_LSB: u32 = 0; + +const I2C_BBPLL_BBADC_DELAY2: u32 = 9; +const I2C_BBPLL_BBADC_DELAY2_MSB: u32 = 3; +const I2C_BBPLL_BBADC_DELAY2_LSB: u32 = 2; + +const I2C_BBPLL_BBADC_DVDD: u32 = 9; +const I2C_BBPLL_BBADC_DVDD_MSB: u32 = 5; +const I2C_BBPLL_BBADC_DVDD_LSB: u32 = 4; + +const I2C_BBPLL_BBADC_DREF: u32 = 9; +const I2C_BBPLL_BBADC_DREF_MSB: u32 = 7; +const I2C_BBPLL_BBADC_DREF_LSB: u32 = 6; + +const I2C_BBPLL_BBADC_DCUR: u32 = 10; +const I2C_BBPLL_BBADC_DCUR_MSB: u32 = 1; +const I2C_BBPLL_BBADC_DCUR_LSB: u32 = 0; + +const I2C_BBPLL_BBADC_INPUT_SHORT: u32 = 10; +const I2C_BBPLL_BBADC_INPUT_SHORT_MSB: u32 = 2; +const I2C_BBPLL_BBADC_INPUT_SHORT_LSB: u32 = 2; + +const I2C_BBPLL_ENT_PLL: u32 = 10; +const I2C_BBPLL_ENT_PLL_MSB: u32 = 3; +const I2C_BBPLL_ENT_PLL_LSB: u32 = 3; + +const I2C_BBPLL_DTEST: u32 = 10; +const I2C_BBPLL_DTEST_MSB: u32 = 5; +const I2C_BBPLL_DTEST_LSB: u32 = 4; + +const I2C_BBPLL_ENT_ADC: u32 = 10; +const I2C_BBPLL_ENT_ADC_MSB: u32 = 7; +const I2C_BBPLL_ENT_ADC_LSB: u32 = 6; + +pub(crate) fn esp32c6_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClock) { + unsafe { + let div_ref = 0u32; + let div7_0 = 8u32; + let dr1 = 0u32; + let dr3 = 0u32; + let dchgp = 5u32; + let dcur = 3u32; + let dbias = 2u32; + + let i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | div_ref; + let i2c_bbpll_div_7_0 = div7_0; + let i2c_bbpll_dcur = + (1 << I2C_BBPLL_OC_DLREF_SEL_LSB) | (3 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur; + + regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, i2c_bbpll_lref); + regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0); + regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_DR1, dr1); + regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_DR3, dr3); + regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur); + regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_VCO_DBIAS, dbias); + } +} + +pub(crate) fn esp32c6_rtc_bbpll_enable() { + let pmu = unsafe { &*crate::peripherals::PMU::PTR }; + + pmu.imm_hp_ck_power.modify(|_, w| { + w.tie_high_xpd_bb_i2c() + .set_bit() + .tie_high_xpd_bbpll() + .set_bit() + .tie_high_xpd_bbpll_i2c() + .set_bit() + .tie_high_global_bbpll_icg() + .set_bit() + }); +} + +pub(crate) fn esp32c6_rtc_update_to_xtal(freq: XtalClock, _div: u8) { + // TODO + let pcr = unsafe { &*crate::peripherals::PCR::PTR }; + unsafe { + ets_update_cpu_frequency(freq.mhz()); + // Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) + // first. + pcr.apb_freq_conf.modify(|_, w| { + w.apb_div_num() + .bits(0) + .apb_div_num() + .bits(_div - 1) + }); + + // Switch clock source + pcr + .sysclk_conf + .modify(|_, w| w.soc_clk_sel().bits(0)); + } +} + +pub(crate) fn esp32c6_rtc_apb_freq_update(apb_freq: ApbClock) { + // TODO + let lp_aon = unsafe { &*crate::peripherals::LP_AON::ptr() }; + let value = ((apb_freq.hz() >> 12) & u16::MAX as u32) + | (((apb_freq.hz() >> 12) & u16::MAX as u32) << 16); + + lp_aon + .store5 + .modify(|_, w| unsafe { w.lp_aon_store5().bits(value) }); +} diff --git a/esp-hal-common/src/efuse/esp32c6.rs b/esp-hal-common/src/efuse/esp32c6.rs new file mode 100644 index 00000000000..81ae4ce5f84 --- /dev/null +++ b/esp-hal-common/src/efuse/esp32c6.rs @@ -0,0 +1,62 @@ +//! Reading of eFuses + +use crate::peripherals::EFUSE; + +pub struct Efuse; + +impl Efuse { + /// Reads chip's MAC address from the eFuse storage. + /// + /// # Example + /// + /// ``` + /// let mac_address = Efuse::get_mac_address(); + /// writeln!( + /// serial_tx, + /// "MAC: {:#X}:{:#X}:{:#X}:{:#X}:{:#X}:{:#X}", + /// mac_address[0], + /// mac_address[1], + /// mac_address[2], + /// mac_address[3], + /// mac_address[4], + /// mac_address[5] + /// ); + /// ``` + pub fn get_mac_address() -> [u8; 6] { + let efuse = unsafe { &*EFUSE::ptr() }; + + let mac_low: u32 = efuse.rd_mac_spi_sys_0.read().mac_0().bits(); + let mac_high: u32 = efuse.rd_mac_spi_sys_1.read().mac_1().bits() as u32; + + let mac_low_bytes = mac_low.to_be_bytes(); + let mac_high_bytes = mac_high.to_be_bytes(); + + [ + mac_high_bytes[2], + mac_high_bytes[3], + mac_low_bytes[0], + mac_low_bytes[1], + mac_low_bytes[2], + mac_low_bytes[3], + ] + } + + /// Get status of SPI boot encryption. + pub fn get_flash_encryption() -> bool { + let efuse = unsafe { &*EFUSE::ptr() }; + (efuse + .rd_repeat_data1 + .read() + .spi_boot_crypt_cnt() + .bits() + .count_ones() + % 2) + != 0 + } + + /// Get the multiplier for the timeout value of the RWDT STAGE 0 register. + pub fn get_rwdt_multiplier() -> u8 { + let efuse = unsafe { &*EFUSE::ptr() }; + efuse.rd_repeat_data1.read().wdt_delay_sel().bits() + } +} diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index 3bc0617cfc7..bae11d6ca2b 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -56,78 +56,76 @@ pub mod trapframe { pub use xtensa_lx_rt::exception::Context as TrapFrame; } -#[cfg(rmt)] -pub use self::pulse_control::PulseControl; -#[cfg(usb_serial_jtag)] -pub use self::usb_serial_jtag::UsbSerialJtag; -pub use self::{ - delay::Delay, - gpio::*, - interrupt::*, - rng::Rng, - rtc_cntl::{Rtc, Rwdt}, - spi::Spi, - timer::Timer, - uart::Uart, -}; - -#[cfg(aes)] -pub mod aes; -pub mod analog; +// #[cfg(rmt)] +// pub use self::pulse_control::PulseControl; +// #[cfg(usb_serial_jtag)] +// pub use self::usb_serial_jtag::UsbSerialJtag; +// pub use self::{ +// delay::Delay, +// gpio::*, +// interrupt::*, +// rng::Rng, +// rtc_cntl::{Rtc, Rwdt}, +// spi::Spi, +// timer::Timer, +// uart::Uart, +// }; + +// pub mod analog; pub mod clock; pub mod delay; -pub mod dma; +// pub mod dma; #[cfg(feature = "embassy")] pub mod embassy; -pub mod gpio; -pub mod i2c; -#[cfg(i2s)] -pub mod i2s; -pub mod ledc; -#[cfg(mcpwm)] -pub mod mcpwm; +// pub mod gpio; +// pub mod i2c; +// #[cfg(i2s)] +// pub mod i2s; +// pub mod ledc; +// #[cfg(mcpwm)] +// pub mod mcpwm; #[cfg(usb_otg)] pub mod otg_fs; #[cfg(any(esp32, esp32s2, esp32s3))] pub mod pcnt; pub mod peripheral; -pub mod prelude; -#[cfg(rmt)] -pub mod pulse_control; +// pub mod prelude; +// #[cfg(rmt)] +// pub mod pulse_control; #[cfg(radio)] pub mod radio; pub mod rng; pub mod rom; +#[cfg(not(esp32c6))] pub mod rtc_cntl; pub mod sha; -pub mod spi; +// pub mod spi; pub mod system; #[cfg(systimer)] pub mod systimer; pub mod timer; -#[cfg(any(esp32s3, esp32c3))] -pub mod twai; -pub mod uart; +// pub mod uart; #[cfg(usb_serial_jtag)] pub mod usb_serial_jtag; -#[cfg(rmt)] -pub mod utils; +// #[cfg(rmt)] +// pub mod utils; #[cfg_attr(esp32, path = "cpu_control/esp32.rs")] -#[cfg_attr(any(esp32c2, esp32c3, esp32s2), path = "cpu_control/none.rs")] #[cfg_attr(esp32s3, path = "cpu_control/esp32s3.rs")] +#[cfg_attr(not(any(esp32, esp32s3)), path = "cpu_control/none.rs")] pub mod cpu_control; #[cfg_attr(esp32, path = "efuse/esp32.rs")] #[cfg_attr(esp32c2, path = "efuse/esp32c2.rs")] #[cfg_attr(esp32c3, path = "efuse/esp32c3.rs")] +#[cfg_attr(esp32c6, path = "efuse/esp32c6.rs")] #[cfg_attr(esp32s2, path = "efuse/esp32s2.rs")] #[cfg_attr(esp32s3, path = "efuse/esp32s3.rs")] pub mod efuse; -#[cfg_attr(riscv, path = "interrupt/riscv.rs")] -#[cfg_attr(xtensa, path = "interrupt/xtensa.rs")] -pub mod interrupt; +// #[cfg_attr(riscv, path = "interrupt/riscv.rs")] +// #[cfg_attr(xtensa, path = "interrupt/xtensa.rs")] +// pub mod interrupt; /// Enumeration of CPU cores /// The actual number of available cores depends on the target. @@ -269,4 +267,4 @@ mod critical_section_impl { } } } -} +} \ No newline at end of file diff --git a/esp-hal-common/src/rom.rs b/esp-hal-common/src/rom.rs index f4549cdbc8c..3fa58515c59 100644 --- a/esp-hal-common/src/rom.rs +++ b/esp-hal-common/src/rom.rs @@ -40,4 +40,4 @@ macro_rules! regi2c_write_mask { ); } }; -} +} \ No newline at end of file diff --git a/esp-hal-common/src/sha.rs b/esp-hal-common/src/sha.rs index 46084635e20..e7b28c482eb 100644 --- a/esp-hal-common/src/sha.rs +++ b/esp-hal-common/src/sha.rs @@ -296,7 +296,7 @@ impl<'d> Sha<'d> { ShaMode::SHA1 | ShaMode::SHA256 => 64, #[cfg(not(esp32))] ShaMode::SHA224 => 64, - #[cfg(not(any(esp32c2, esp32c3)))] + #[cfg(not(any(esp32c2, esp32c3, esp32c6)))] _ => 128, }; } diff --git a/esp-hal-common/src/system.rs b/esp-hal-common/src/system.rs index d24cee19829..17bf9fa0892 100644 --- a/esp-hal-common/src/system.rs +++ b/esp-hal-common/src/system.rs @@ -10,10 +10,13 @@ //! ``` use crate::peripheral::PeripheralRef; -#[cfg(not(esp32))] -type SystemPeripheral = crate::peripherals::SYSTEM; + #[cfg(esp32)] type SystemPeripheral = crate::peripherals::DPORT; +#[cfg(esp32c6)] +type SystemPeripheral = crate::peripherals::PCR; +#[cfg(not(any(esp32, esp32c6)))] +type SystemPeripheral = crate::peripherals::SYSTEM; /// Peripherals which can be enabled via [PeripheralClockControl] pub enum Peripheral { @@ -26,13 +29,13 @@ pub enum Peripheral { #[cfg(rmt)] Rmt, Ledc, - #[cfg(any(esp32, esp32s3))] + #[cfg(mcpwm)] Mcpwm0, - #[cfg(any(esp32, esp32s3))] + #[cfg(mcpwm)] Mcpwm1, #[cfg(any(esp32, esp32s2, esp32s3))] Pcnt, - #[cfg(any(esp32c2, esp32c3))] + #[cfg(any(esp32c2, esp32c3, esp32c6))] ApbSarAdc, #[cfg(gdma)] Gdma, @@ -40,7 +43,7 @@ pub enum Peripheral { Dma, #[cfg(not(esp32c2))] I2s0, - #[cfg(not(any(esp32c2, esp32s2, esp32c3)))] + #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32s2)))] I2s1, #[cfg(usb_otg)] Usb, @@ -48,6 +51,10 @@ pub enum Peripheral { Twai, #[cfg(aes)] Aes, + #[cfg(esp32c6)] + Twai0, + #[cfg(esp32c6)] + Twai1, } /// Controls the enablement of peripheral clocks. @@ -55,6 +62,7 @@ pub struct PeripheralClockControl { _private: (), } +#[cfg(not(esp32c6))] impl PeripheralClockControl { /// Enables and resets the given peripheral pub fn enable(&mut self, peripheral: Peripheral) { @@ -72,7 +80,7 @@ impl PeripheralClockControl { ) }; - #[cfg(any(esp32c2, esp32c3, esp32s2, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s2, esp32s3))] let (perip_clk_en1, perip_rst_en1) = { (&system.perip_clk_en1, &system.perip_rst_en1) }; match peripheral { @@ -109,12 +117,12 @@ impl PeripheralClockControl { perip_clk_en0.modify(|_, w| w.ledc_clk_en().set_bit()); perip_rst_en0.modify(|_, w| w.ledc_rst().clear_bit()); } - #[cfg(any(esp32, esp32s3))] + #[cfg(mcpwm)] Peripheral::Mcpwm0 => { perip_clk_en0.modify(|_, w| w.pwm0_clk_en().set_bit()); perip_rst_en0.modify(|_, w| w.pwm0_rst().clear_bit()); } - #[cfg(any(esp32, esp32s3))] + #[cfg(mcpwm)] Peripheral::Mcpwm1 => { perip_clk_en0.modify(|_, w| w.pwm1_clk_en().set_bit()); perip_rst_en0.modify(|_, w| w.pwm1_rst().clear_bit()); @@ -186,6 +194,61 @@ impl PeripheralClockControl { } } +#[cfg(esp32c6)] +impl PeripheralClockControl { + /// Enables and resets the given peripheral + pub fn enable(&mut self, peripheral: Peripheral) { + let system = unsafe { &*SystemPeripheral::PTR }; + + match peripheral { + Peripheral::Spi2 => { + system.spi2_conf.modify(|_, w| w.spi2_clk_en().set_bit()); + system.spi2_conf.modify(|_, w| w.spi2_rst_en().clear_bit()); + } + Peripheral::I2cExt0 => { + // FIXME + // perip_clk_en0.modify(|_, w| w.i2c_ext0_clk_en().set_bit()); + // perip_rst_en0.modify(|_, w| w.i2c_ext0_rst().clear_bit()); + } + Peripheral::Rmt => { + system.rmt_conf.modify(|_, w| w.rmt_clk_en().set_bit()); + system.rmt_conf.modify(|_, w| w.rmt_rst_en().clear_bit()); + } + Peripheral::Ledc => { + system.ledc_conf.modify(|_, w| w.ledc_clk_en().set_bit()); + system.ledc_conf.modify(|_, w| w.ledc_rst_en().clear_bit()); + } + Peripheral::Mcpwm0 | Peripheral::Mcpwm1 => { + system.pwm_conf.modify(|_, w| w.pwm_clk_en().set_bit()); + system.pwm_conf.modify(|_, w| w.pwm_rst_en().clear_bit()); + } + Peripheral::ApbSarAdc => { + // TODO + } + Peripheral::Gdma => { + system.gdma_conf.modify(|_, w| w.gdma_clk_en().set_bit()); + system.gdma_conf.modify(|_, w| w.gdma_rst_en().clear_bit()); + } + Peripheral::I2s0 => { + system.i2s_conf.modify(|_, w| w.i2s_clk_en().set_bit()); + system.i2s_conf.modify(|_, w| w.i2s_rst_en().clear_bit()); + } + Peripheral::Twai0 => { + system.twai0_conf.modify(|_, w| w.twai0_clk_en().set_bit()); + system + .twai0_conf + .modify(|_, w| w.twai0_rst_en().clear_bit()); + } + Peripheral::Twai1 => { + system.twai1_conf.modify(|_, w| w.twai1_clk_en().set_bit()); + system + .twai1_conf + .modify(|_, w| w.twai1_rst_en().clear_bit()); + } + } + } +} + /// Controls the configuration of the chip's clocks. pub struct SystemClockControl { _private: (), @@ -238,13 +301,16 @@ impl<'d, T: crate::peripheral::Peripheral

+ 'd> SystemExt< impl crate::peripheral::Peripheral for SystemClockControl { type P = SystemClockControl; + #[inline] unsafe fn clone_unchecked(&mut self) -> Self::P { SystemClockControl { _private: () } } } + impl crate::peripheral::Peripheral for &mut SystemClockControl { type P = SystemClockControl; + #[inline] unsafe fn clone_unchecked(&mut self) -> Self::P { SystemClockControl { _private: () } @@ -275,4 +341,4 @@ mod dma_peripheral { impl crate::peripheral::sealed::Sealed for Dma {} impl crate::peripheral::sealed::Sealed for &mut Dma {} -} +} \ No newline at end of file diff --git a/esp-hal-common/src/systimer.rs b/esp-hal-common/src/systimer.rs index 09c23bf557f..4fc5b91564e 100644 --- a/esp-hal-common/src/systimer.rs +++ b/esp-hal-common/src/systimer.rs @@ -27,12 +27,12 @@ pub struct SystemTimer<'d> { impl<'d> SystemTimer<'d> { #[cfg(esp32s2)] pub const BIT_MASK: u64 = u64::MAX; - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(not(esp32s2))] pub const BIT_MASK: u64 = 0xFFFFFFFFFFFFF; #[cfg(esp32s2)] pub const TICKS_PER_SECOND: u64 = 80_000_000; // TODO this can change when we have support for changing APB frequency - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(not(esp32s2))] pub const TICKS_PER_SECOND: u64 = 16_000_000; pub fn new(p: impl Peripheral

+ 'd) -> Self { diff --git a/esp-hal-common/src/timer.rs b/esp-hal-common/src/timer.rs index a55eeca0d4a..30364499223 100644 --- a/esp-hal-common/src/timer.rs +++ b/esp-hal-common/src/timer.rs @@ -36,7 +36,7 @@ where { _timer_group: PeripheralRef<'d, T>, pub timer0: Timer>, - #[cfg(not(any(esp32c2, esp32c3)))] + #[cfg(not(any(esp32c2, esp32c3, esp32c6)))] pub timer1: Timer>, pub wdt: Wdt, } @@ -74,7 +74,7 @@ where clocks.apb_clock, ); - #[cfg(not(any(esp32c2, esp32c3)))] + #[cfg(not(any(esp32c2, esp32c3, esp32c6)))] let timer1 = Timer::new( Timer1 { phantom: PhantomData::default(), @@ -87,7 +87,7 @@ where Self { _timer_group: timer_group, timer0, - #[cfg(not(any(esp32c2, esp32c3)))] + #[cfg(not(any(esp32c2, esp32c3, esp32c6)))] timer1, wdt, } @@ -314,13 +314,13 @@ where } } -#[cfg(not(any(esp32c2, esp32c3)))] +#[cfg(not(any(esp32c2, esp32c3, esp32c6)))] pub struct Timer1 { phantom: PhantomData, } /// Timer peripheral instance -#[cfg(not(any(esp32c2, esp32c3)))] +#[cfg(not(any(esp32c2, esp32c3, esp32c6)))] impl Instance for Timer1 where TG: TimerGroupInstance, diff --git a/esp32c6-hal/examples/hello_world.rs b/esp32c6-hal/examples/hello_world.rs new file mode 100644 index 00000000000..2159a8b8587 --- /dev/null +++ b/esp32c6-hal/examples/hello_world.rs @@ -0,0 +1,12 @@ +#![no_std] +#![no_main] + +use esp32c6_hal::peripherals; +use esp_backtrace as _; + +#[riscv_rt::entry] +fn main() -> ! { + esp_println::println!("Hello!"); + + loop {} +} From fc65b3f3ca9b5b5e0a216867c5ce386416179316 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Thu, 5 Jan 2023 11:14:46 -0800 Subject: [PATCH 04/64] Create the `esp32c6-hal` package C6: update --- esp-hal-common/Cargo.toml | 3 + esp-hal-common/src/clock/mod.rs | 56 ++++- esp-hal-common/src/clocks_ll/esp32c6.rs | 2 - esp-hal-common/src/gpio.rs | 11 +- esp-hal-common/src/gpio/esp32c6.rs | 285 ++++++++++++++++++++++ esp-hal-common/src/interrupt/riscv.rs | 28 +++ esp-hal-common/src/lib.rs | 14 +- esp-hal-common/src/peripherals/esp32c6.rs | 4 +- esp-hal-common/src/prelude.rs | 50 ++-- esp-hal-common/src/uart.rs | 4 +- esp32c6-hal/Cargo.toml | 16 +- esp32c6-hal/examples/blinky.rs | 44 ++++ esp32c6-hal/examples/hello_world.rs | 84 ++++++- esp32c6-hal/ld/bl-esp32c6-memory.x | 36 ++- esp32c6-hal/ld/bl-riscv-link.x | 26 +- esp32c6-hal/ld/db-esp32c6-memory.x | 2 +- esp32c6-hal/src/lib.rs | 4 +- 17 files changed, 568 insertions(+), 101 deletions(-) create mode 100644 esp-hal-common/src/gpio/esp32c6.rs create mode 100644 esp32c6-hal/examples/blinky.rs diff --git a/esp-hal-common/Cargo.toml b/esp-hal-common/Cargo.toml index 59330a12ed7..b266b53446c 100644 --- a/esp-hal-common/Cargo.toml +++ b/esp-hal-common/Cargo.toml @@ -60,6 +60,9 @@ esp32c6 = { path = "C:/Users/JurajSadel/esp-pacs/esp32c6", features = ["critica esp32s2 = { version = "0.12.0", features = ["critical-section"], optional = true } esp32s3 = { version = "0.15.0", features = ["critical-section"], optional = true } +# REMOVE BEFOFE MERGE +esp-println = { git = "https://github.com/esp-rs/esp-println", features = ["esp32c6"] } + [features] esp32 = ["esp32/rt" , "xtensa", "xtensa-lx/esp32", "xtensa-lx-rt/esp32", "lock_api", "procmacros/esp32"] esp32c2 = ["esp32c2/rt", "riscv", "procmacros/esp32c2"] diff --git a/esp-hal-common/src/clock/mod.rs b/esp-hal-common/src/clock/mod.rs index c7f266ae750..b19999c2ef2 100644 --- a/esp-hal-common/src/clock/mod.rs +++ b/esp-hal-common/src/clock/mod.rs @@ -34,7 +34,7 @@ pub enum CpuClock { Clock120MHz, #[cfg(not(esp32c2))] Clock160MHz, - #[cfg(not(any(esp32c2, esp32c3)))] + #[cfg(not(any(esp32c2, esp32c3, esp32c6)))] Clock240MHz, } @@ -47,7 +47,7 @@ impl Clock for CpuClock { CpuClock::Clock120MHz => HertzU32::MHz(120), #[cfg(not(esp32c2))] CpuClock::Clock160MHz => HertzU32::MHz(160), - #[cfg(not(any(esp32c2, esp32c3)))] + #[cfg(not(any(esp32c2, esp32c3, esp32c6)))] CpuClock::Clock240MHz => HertzU32::MHz(240), } } @@ -369,6 +369,58 @@ impl<'d> ClockControl<'d> { } } +#[cfg(esp32c6)] +impl<'d> ClockControl<'d> { + /// Use what is considered the default settings after boot. + #[allow(unused)] + pub fn boot_defaults( + clock_control: impl Peripheral

+ 'd, + ) -> ClockControl<'d> { + ClockControl { + _private: clock_control.into_ref(), + desired_rates: RawClocks { + cpu_clock: HertzU32::MHz(80), + apb_clock: HertzU32::MHz(80), + xtal_clock: HertzU32::MHz(40), + i2c_clock: HertzU32::MHz(40), + }, + } + } + + /// Configure the CPU clock speed. + #[allow(unused)] + pub fn configure( + clock_control: impl Peripheral

+ 'd, + cpu_clock_speed: CpuClock, + ) -> ClockControl<'d> { + let apb_freq; + let xtal_freq = XtalClock::RtcXtalFreq40M; + let pll_freq = PllClock::Pll480MHz; + + if cpu_clock_speed.mhz() <= xtal_freq.mhz() { + apb_freq = ApbClock::ApbFreqOther(cpu_clock_speed.mhz()); + clocks_ll::esp32c6_rtc_update_to_xtal(xtal_freq, 1); + clocks_ll::esp32c6_rtc_apb_freq_update(apb_freq); + } else { + apb_freq = ApbClock::ApbFreq80MHz; + clocks_ll::esp32c6_rtc_bbpll_enable(); + clocks_ll::esp32c6_rtc_bbpll_configure(xtal_freq, pll_freq); + // clocks_ll::esp32c6_rtc_freq_to_pll_mhz(cpu_clock_speed); + clocks_ll::esp32c6_rtc_apb_freq_update(apb_freq); + } + + ClockControl { + _private: clock_control.into_ref(), + desired_rates: RawClocks { + cpu_clock: cpu_clock_speed.frequency(), + apb_clock: apb_freq.frequency(), + xtal_clock: xtal_freq.frequency(), + i2c_clock: HertzU32::MHz(40), + }, + } + } +} + #[cfg(esp32s2)] impl<'d> ClockControl<'d> { /// Use what is considered the default settings after boot. diff --git a/esp-hal-common/src/clocks_ll/esp32c6.rs b/esp-hal-common/src/clocks_ll/esp32c6.rs index 52d8f7df03e..381b2b85474 100644 --- a/esp-hal-common/src/clocks_ll/esp32c6.rs +++ b/esp-hal-common/src/clocks_ll/esp32c6.rs @@ -206,7 +206,6 @@ pub(crate) fn esp32c6_rtc_bbpll_enable() { } pub(crate) fn esp32c6_rtc_update_to_xtal(freq: XtalClock, _div: u8) { - // TODO let pcr = unsafe { &*crate::peripherals::PCR::PTR }; unsafe { ets_update_cpu_frequency(freq.mhz()); @@ -227,7 +226,6 @@ pub(crate) fn esp32c6_rtc_update_to_xtal(freq: XtalClock, _div: u8) { } pub(crate) fn esp32c6_rtc_apb_freq_update(apb_freq: ApbClock) { - // TODO let lp_aon = unsafe { &*crate::peripherals::LP_AON::ptr() }; let value = ((apb_freq.hz() >> 12) & u16::MAX as u32) | (((apb_freq.hz() >> 12) & u16::MAX as u32) << 16); diff --git a/esp-hal-common/src/gpio.rs b/esp-hal-common/src/gpio.rs index 299fc0185f2..bf52bac93df 100644 --- a/esp-hal-common/src/gpio.rs +++ b/esp-hal-common/src/gpio.rs @@ -14,6 +14,7 @@ use core::marker::PhantomData; #[cfg_attr(esp32, path = "gpio/esp32.rs")] #[cfg_attr(esp32c2, path = "gpio/esp32c2.rs")] #[cfg_attr(esp32c3, path = "gpio/esp32c3.rs")] +#[cfg_attr(esp32c6, path = "gpio/esp32c6.rs")] #[cfg_attr(esp32s2, path = "gpio/esp32s2.rs")] #[cfg_attr(esp32s3, path = "gpio/esp32s3.rs")] pub mod types; @@ -275,7 +276,7 @@ impl InteruptStatusRegisterAccess for SingleCoreInteruptStatusRegisterAccessBank // interrupt enable bit see // https://github.com/espressif/esp-idf/blob/c04803e88b871a4044da152dfb3699cf47354d18/components/hal/esp32s3/include/hal/gpio_ll.h#L32 // Treating it as SingleCore in the gpio macro makes this work. -#[cfg(not(any(esp32c2, esp32c3, esp32s2, esp32s3)))] +#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32s2, esp32s3)))] impl InteruptStatusRegisterAccess for DualCoreInteruptStatusRegisterAccessBank0 { fn pro_cpu_interrupt_status_read() -> u32 { unsafe { &*GPIO::PTR }.pcpu_int.read().bits() @@ -298,7 +299,7 @@ impl InteruptStatusRegisterAccess for DualCoreInteruptStatusRegisterAccessBank0 // interrupt enable bit see // https://github.com/espressif/esp-idf/blob/c04803e88b871a4044da152dfb3699cf47354d18/components/hal/esp32s3/include/hal/gpio_ll.h#L32 // Treating it as SingleCore in the gpio macro makes this work. -#[cfg(not(any(esp32c2, esp32c3, esp32s2, esp32s3)))] +#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32s2, esp32s3)))] impl InteruptStatusRegisterAccess for DualCoreInteruptStatusRegisterAccessBank1 { fn pro_cpu_interrupt_status_read() -> u32 { unsafe { &*GPIO::PTR }.pcpu_int1.read().bits() @@ -462,7 +463,7 @@ impl BankGpioRegisterAccess for Bank0GpioRegisterAccess { } } -#[cfg(not(any(esp32c2, esp32c3)))] +#[cfg(not(any(esp32c2, esp32c3, esp32c6)))] impl BankGpioRegisterAccess for Bank1GpioRegisterAccess { fn write_out_en_clear(word: u32) { unsafe { &*GPIO::PTR } @@ -1692,7 +1693,7 @@ pub fn enable_iomux_clk_gate() { } } -#[cfg(not(any(esp32c2, esp32c3, esp32s2)))] +#[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32s2)))] #[doc(hidden)] #[macro_export] macro_rules! analog { @@ -1810,7 +1811,7 @@ macro_rules! analog { } } -#[cfg(any(esp32c2, esp32c3))] +#[cfg(any(esp32c2, esp32c3, esp32c6))] #[doc(hidden)] #[macro_export] macro_rules! analog { diff --git a/esp-hal-common/src/gpio/esp32c6.rs b/esp-hal-common/src/gpio/esp32c6.rs new file mode 100644 index 00000000000..7bf64885325 --- /dev/null +++ b/esp-hal-common/src/gpio/esp32c6.rs @@ -0,0 +1,285 @@ +use paste::paste; + +use crate::{ + gpio::PhantomData, + peripherals::GPIO, + AlternateFunction, + Bank0GpioRegisterAccess, + GpioPin, + InputOutputAnalogPinType, + InputOutputPinType, + Unknown, +}; + +pub type OutputSignalType = u8; +pub const OUTPUT_SIGNAL_MAX: u8 = 128; +pub const INPUT_SIGNAL_MAX: u8 = 124; + +pub const ONE_INPUT: u8 = 0x1e; +pub const ZERO_INPUT: u8 = 0x1f; + +pub(crate) const GPIO_FUNCTION: AlternateFunction = AlternateFunction::Function1; + +pub(crate) const fn get_io_mux_reg(gpio_num: u8) -> &'static crate::peripherals::io_mux::GPIO { + unsafe { &(&*crate::peripherals::IO_MUX::PTR).gpio[gpio_num as usize] } +} + +pub(crate) fn gpio_intr_enable(int_enable: bool, nmi_enable: bool) -> u8 { + int_enable as u8 | ((nmi_enable as u8) << 1) +} + +/// Peripheral input signals for the GPIO mux +#[allow(non_camel_case_types)] +#[derive(PartialEq, Copy, Clone)] +pub enum InputSignal { + EXT_ADC_START = 0, + U0RXD = 6, + U0CTS = 7, + U0DSR = 8, + U1RXD = 9, + U1CTS = 10, + U1DSR = 11, + I2S_MCLK = 12, + I2SO_BCK = 13, + I2SO_WS = 14, + I2SI_SD = 15, + I2SI_BCK = 16, + I2SI_WS = 17, + USB_JTAG_TDO_BRIDGE = 19, + CPU_TESTBUS0 = 20, //TODO: verify + CPU_GPIO_IN0 = 28, + CPU_GPIO_IN1 = 29, + CPU_GPIO_IN2 = 30, + CPU_GPIO_IN3 = 31, + CPU_GPIO_IN4 = 32, + CPU_GPIO_IN5 = 33, + CPU_GPIO_IN6 = 34, + CPU_GPIO_IN7 = 35, + USB_JTAG_TMS = 37, + USB_EXTPHY_OEN = 40, + USB_EXTPHY_VM = 41, + USB_EXTPHY_VPO = 42, + I2CEXT0_SCL = 45, + I2CEXT0_SDA = 46, + PARL_RX_DATA0 = 47, + PARL_RX_DATA1 = 48, + PARL_RX_DATA2 = 49, + PARL_RX_DATA3 = 50, + PARL_RX_DATA4 = 51, + PARL_RX_DATA5 = 52, + PARL_RX_DATA6 = 53, + PARL_RX_DATA7 = 54, + PARL_RX_DATA8 = 55, + PARL_RX_DATA9 = 56, + PARL_RX_DATA10 = 57, + PARL_RX_DATA11 = 58, + PARL_RX_DATA12 = 59, + PARL_RX_DATA13 = 60, + PARL_RX_DATA14 = 61, + PARL_RX_DATA15 = 62, + FSPICLK = 63, + FSPIQ = 64, + FSPID = 65, + FSPIHD = 66, + FSPIWP = 67, + FSPICS0 = 68, + PARL_RX_CLK = 69, + PARL_TX_CLK = 70, + RMT_SIG_IN0 = 71, + MODEM_DIAG1 = 72, + TWAI0_RX = 73, + TWAI1_RX = 77, + PWM0_SYNC0 = 87, + PWM0_SYNC1 = 88, + PWM0_SYNC2 = 89, + PWM0_F0 = 90, + PWM0_F1 = 91, + PWM0_F2 = 92, + PWM0_CAP0 = 93, + PWM0_CAP1 = 94, + PWM0_CAP2 = 95, + SIG_IN_FUNC97 = 97, + SIG_IN_FUNC98 = 98, + SIG_IN_FUNC99 = 99, + SIG_IN_FUNC100 = 100, + PCNT_SIG_CH0_IN0 = 101, + PCNT_SIG_CH1_IN0 = 102, + PCNT_CTRL_CH0_IN0 = 103, + PCNT_CTRL_CH1_IN0 = 104, + PCNT_SIG_CH0_IN1 = 105, + PCNT_SIG_CH1_IN1 = 106, + PCNT_CTRL_CH0_IN1 = 107, + PCNT_CTRL_CH1_IN1 = 108, + PCNT_SIG_CH0_IN2 = 109, + PCNT_SIG_CH1_IN2 = 110, + PCNT_CTRL_CH0_IN2 = 111, + PCNT_CTRL_CH1_IN2 = 112, + PCNT_SIG_CH0_IN3 = 113, + PCNT_SIG_CH1_IN3 = 114, + PCNT_CTRL_CH0_IN3 = 115, + PCNT_CTRL_CH1_IN3 = 116, + SPIQ = 121, + SPID = 122, + SPIHD = 123, + SPIWP = 124, +} + +/// Peripheral input signals for the GPIO mux +#[allow(non_camel_case_types)] +#[derive(PartialEq, Copy, Clone)] +pub enum OutputSignal { + LEDC_LS_SIG_OUT0 = 0, + LEDC_LS_SIG_OUT1 = 1, + LEDC_LS_SIG_OUT2 = 2, + LEDC_LS_SIG_OUT3 = 3, + LEDC_LS_SIG_OUT4 = 4, + LEDC_LS_SIG_OUT5 = 5, + U0TXD = 6, + U0RTS = 7, + U0DTR = 8, + U1TXD = 9, + U1RTS = 10, + U1DTR = 11, + I2S_MCLK = 12, + I2SO_BCK = 13, + I2SO_WS = 14, + I2SO_SD = 15, + I2SI_BCK = 16, + I2SI_WS = 17, + I2SO_SD1 = 18, + USB_JTAG_TRST = 19, // TODO: Verify + CPU_GPIO_OUT0 = 28, + CPU_GPIO_OUT1 = 29, + CPU_GPIO_OUT2 = 30, + CPU_GPIO_OUT3 = 31, + CPU_GPIO_OUT4 = 32, + CPU_GPIO_OUT5 = 33, + CPU_GPIO_OUT6 = 34, + CPU_GPIO_OUT7 = 35, + USB_JTAG_TCK = 36, + USB_JTAG_TMS = 37, + USB_JTAG_TDI = 38, + USB_JTAG_TDO = 39, + I2CEXT0_SCL = 45, + I2CEXT0_SDA = 46, + PARL_TX_DATA0 = 47, + PARL_TX_DATA1 = 48, + PARL_TX_DATA2 = 49, + PARL_TX_DATA3 = 50, + PARL_TX_DATA4 = 51, + PARL_TX_DATA5 = 52, + PARL_TX_DATA6 = 53, + PARL_TX_DATA7 = 54, + PARL_TX_DATA8 = 55, + PARL_TX_DATA9 = 56, + PARL_TX_DATA10 = 57, + PARL_TX_DATA11 = 58, + PARL_TX_DATA12 = 59, + PARL_TX_DATA13 = 60, + PARL_TX_DATA14 = 61, + PARL_TX_DATA15 = 62, + FSPICLK_MUX = 63, + FSPIQ = 64, + FSPID = 65, + FSPIHD = 66, + FSPIWP = 67, + FSPICS0 = 68, + SDIO_TOHOST_INT = 69, + PARL_TX_CLK = 70, + RMT_SIG_OUT0 = 71, + RMT_SIG_OUT1 = 72, + TWAI0_TX = 73, + TWAI0_BUS_OFF_ON = 74, + TWAI0_CLKOUT = 75, + TWAI0_STANDBY = 76, + TWAI1_TX = 77, + TWAI1_BUS_OFF_ON = 78, + TWAI1_CLKOUT = 79, + TWAI1_STANDBY = 80, + GPIO_SD0 = 83, + GPIO_SD1 = 84, + GPIO_SD2 = 85, + GPIO_SD3 = 86, + PWM0_OUT0A = 87, + PWM0_OUT0B = 88, + PWM0_OUT1A = 89, + PWM0_OUT1B = 90, + PWM0_OUT2A = 91, + PWM0_OUT2B = 92, + SIG_IN_FUNC97 = 97, + SIG_IN_FUNC98 = 98, + SIG_IN_FUNC99 = 99, + SIG_IN_FUNC100 = 100, + FSPICS1 = 101, + FSPICS2 = 102, + FSPICS3 = 103, + FSPICS4 = 104, + FSPICS5 = 105, + SPICLK_MUX = 114, + SPICS0 = 115, + SPICS1 = 116, + GPIO_TASK_MATRIX_OUT0 = 117, // TODO: verify rhis group - not in TRM but in ESP_IDF + GPIO_TASK_MATRIX_OUT1 = 118, + GPIO_TASK_MATRIX_OUT2 = 119, + GPIO_TASK_MATRIX_OUT3 = 120, + SPIQ = 121, + SPID = 122, + SPIHD = 123, + SPIWP = 124, + CLK_OUT_OUT1 = 125, + CLK_OUT_OUT2 = 126, + CLK_OUT_OUT3 = 127, + GPIO = 128, +} + +crate::gpio::gpio! { + Single, + (0, 0, InputOutputAnalog) + (1, 0, InputOutputAnalog) + (2, 0, InputOutputAnalog (2 => FSPIQ) (2 => FSPIQ)) + (3, 0, InputOutputAnalog) + (4, 0, InputOutputAnalog (2 => FSPIHD) (0 => USB_JTAG_TMS 2 => FSPIHD)) + (5, 0, InputOutputAnalog (2 => FSPIWP) (0 => USB_JTAG_TDI 2 => FSPIWP)) + (6, 0, InputOutputAnalog (2 => FSPICLK) (0 => USB_JTAG_TCK 2 => FSPICLK_MUX)) + (7, 0, InputOutputAnalog (2 => FSPID) (0 => USB_JTAG_TDO 2 => FSPID)) + (8, 0, InputOutput) + (9, 0, InputOutput) + (10, 0, InputOutput) + (11, 0, InputOutput) + (12, 0, InputOutput) + (13, 0, InputOutput) + (14, 0, InputOutput) + (15, 0, InputOutput) + (16, 0, InputOutput (0 => U0RXD) (2 => FSPICS0)) + (17, 0, InputOutput () (0 => U0TXD 2 => FSPICS1)) + (18, 0, InputOutput () (2 => FSPICS2)) // TODO 0 => SDIO_CMD + (19, 0, InputOutput () (2 => FSPICS3)) // TODO 0 => SDIO_CLK + (20, 0, InputOutput () (2 => FSPICS4)) //TODO 0 => SDIO_DATA0 + (21, 0, InputOutput () (2 => FSPICS5)) // TODO 0 => SDIO_DATA1 + (22, 0, InputOutput () ()) // TODO 0 => SDIO_DATA2 + (23, 0, InputOutput () ()) // TODO 0 => SDIO_DATA3 + (24, 0, InputOutput () (0 => SPICS0)) + (25, 0, InputOutput (0 => SPIQ) (0 => SPIQ)) + (26, 0, InputOutput (0 => SPIWP) (0 => SPIWP)) + (27, 0, InputOutput) + (28, 0, InputOutput (0 => SPIHD) (0 => SPIHD)) + (29, 0, InputOutput () (0 => SPICLK_MUX)) + (30, 0, InputOutput (0 => SPID) (0 => SPID)) +} + +crate::gpio::analog! { + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 +} + +// TODO USB pins +// implement marker traits on USB pins +// impl crate::otg_fs::UsbSel for Gpio?? {} +// impl crate::otg_fs::UsbDp for Gpio12 {} +// impl crate::otg_fs::UsbDm for Gpio13 {} \ No newline at end of file diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index d9c4623d418..fd182526b58 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -24,7 +24,9 @@ use crate::{ extern "C" { fn interrupt1(frame: &mut TrapFrame); fn interrupt2(frame: &mut TrapFrame); + #[cfg(not(feature = "esp32c6"))] fn interrupt3(frame: &mut TrapFrame); + #[cfg(not(feature = "esp32c6"))] fn interrupt4(frame: &mut TrapFrame); fn interrupt5(frame: &mut TrapFrame); fn interrupt6(frame: &mut TrapFrame); @@ -69,6 +71,8 @@ pub enum InterruptKind { #[repr(u32)] #[derive(Debug, Copy, Clone)] pub enum CpuInterrupt { + #[cfg(feature = "esp32c6")] + // Interrupt0 = 0, Interrupt1 = 1, Interrupt2, Interrupt3, @@ -141,7 +145,10 @@ pub unsafe fn map(_core: Cpu, interrupt: Interrupt, which: CpuInterrupt) { let interrupt_number = interrupt as isize; let cpu_interrupt_number = which as isize; let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; + #[cfg(not(feature = "esp32c6"))] let intr_map_base = intr.mac_intr_map.as_ptr(); + #[cfg(feature = "esp32c6")] + let intr_map_base = intr.wifi_mac_intr_map.as_ptr(); intr_map_base .offset(interrupt_number) .write_volatile(cpu_interrupt_number as u32); @@ -150,7 +157,10 @@ pub unsafe fn map(_core: Cpu, interrupt: Interrupt, which: CpuInterrupt) { /// Enable a CPU interrupt pub unsafe fn enable_cpu_interrupt(which: CpuInterrupt) { let cpu_interrupt_number = which as isize; + #[cfg(not(feature = "esp32c6"))] let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; + #[cfg(feature = "esp32c6")] + let intr = &*crate::peripherals::INTPRI::PTR; intr.cpu_int_enable .modify(|r, w| w.bits((1 << cpu_interrupt_number) | r.bits())); } @@ -160,7 +170,10 @@ pub fn disable(_core: Cpu, interrupt: Interrupt) { unsafe { let interrupt_number = interrupt as isize; let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; + #[cfg(not(feature = "esp32c6"))] let intr_map_base = intr.mac_intr_map.as_ptr(); + #[cfg(feature = "esp32c6")] + let intr_map_base = intr.wifi_mac_intr_map.as_ptr(); intr_map_base.offset(interrupt_number).write_volatile(0); } } @@ -171,7 +184,10 @@ pub fn disable(_core: Cpu, interrupt: Interrupt) { /// interrupt handler will take care of clearing edge interrupt bits. pub fn set_kind(_core: Cpu, which: CpuInterrupt, kind: InterruptKind) { unsafe { + #[cfg(not(feature = "esp32c6"))] let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; + #[cfg(feature = "esp32c6")] + let intr = &*crate::peripherals::INTPRI::PTR; let cpu_interrupt_number = which as isize; let interrupt_type = match kind { @@ -192,7 +208,10 @@ pub fn set_kind(_core: Cpu, which: CpuInterrupt, kind: InterruptKind) { /// default). Avoid changing the priority of interrupts 1 - 15 when interrupt /// vectoring is enabled. pub unsafe fn set_priority(_core: Cpu, which: CpuInterrupt, priority: Priority) { + #[cfg(not(feature = "esp32c6"))] let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; + #[cfg(feature = "esp32c6")] + let intr = &*crate::peripherals::INTPRI::PTR; let cpu_interrupt_number = which as isize; let intr_prio_base = intr.cpu_int_pri_0.as_ptr(); @@ -206,7 +225,10 @@ pub unsafe fn set_priority(_core: Cpu, which: CpuInterrupt, priority: Priority) pub fn clear(_core: Cpu, which: CpuInterrupt) { unsafe { let cpu_interrupt_number = which as isize; + #[cfg(not(feature = "esp32c6"))] let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; + #[cfg(feature = "esp32c6")] + let intr = &*crate::peripherals::INTPRI::PTR; intr.cpu_int_clear .write(|w| w.bits(1 << cpu_interrupt_number)); } @@ -260,7 +282,13 @@ mod vectored { fn get_configured_interrupts(_core: Cpu, mut status: u128) -> [u128; 16] { unsafe { let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; + #[cfg(not(feature = "esp32c6"))] let intr_map_base = intr.mac_intr_map.as_ptr(); + #[cfg(feature = "esp32c6")] + let intr_map_base = intr.wifi_mac_intr_map.as_ptr(); + + #[cfg(feature = "esp32c6")] + let intr = &*crate::peripherals::INTPRI::PTR; let intr_prio_base = intr.cpu_int_pri_0.as_ptr(); let mut prios = [0u128; 16]; diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index bae11d6ca2b..dcc9c7cf97b 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -71,13 +71,15 @@ pub mod trapframe { // uart::Uart, // }; +pub use self::{gpio::*, uart::Uart, timer::Timer, delay::Delay, interrupt::*, }; + // pub mod analog; pub mod clock; pub mod delay; // pub mod dma; #[cfg(feature = "embassy")] pub mod embassy; -// pub mod gpio; +pub mod gpio; // pub mod i2c; // #[cfg(i2s)] // pub mod i2s; @@ -89,7 +91,7 @@ pub mod otg_fs; #[cfg(any(esp32, esp32s2, esp32s3))] pub mod pcnt; pub mod peripheral; -// pub mod prelude; +pub mod prelude; // #[cfg(rmt)] // pub mod pulse_control; #[cfg(radio)] @@ -104,7 +106,7 @@ pub mod system; #[cfg(systimer)] pub mod systimer; pub mod timer; -// pub mod uart; +pub mod uart; #[cfg(usb_serial_jtag)] pub mod usb_serial_jtag; // #[cfg(rmt)] @@ -123,9 +125,9 @@ pub mod cpu_control; #[cfg_attr(esp32s3, path = "efuse/esp32s3.rs")] pub mod efuse; -// #[cfg_attr(riscv, path = "interrupt/riscv.rs")] -// #[cfg_attr(xtensa, path = "interrupt/xtensa.rs")] -// pub mod interrupt; +#[cfg_attr(riscv, path = "interrupt/riscv.rs")] +#[cfg_attr(xtensa, path = "interrupt/xtensa.rs")] +pub mod interrupt; /// Enumeration of CPU cores /// The actual number of available cores depends on the target. diff --git a/esp-hal-common/src/peripherals/esp32c6.rs b/esp-hal-common/src/peripherals/esp32c6.rs index 0b14423a2dd..255bf93252a 100644 --- a/esp-hal-common/src/peripherals/esp32c6.rs +++ b/esp-hal-common/src/peripherals/esp32c6.rs @@ -23,11 +23,11 @@ crate::peripherals! { HP_SYS, I2C0, I2S0, - INTMTX_CORE0, + INTERRUPT_CORE0, INTPRI, IO_MUX, LEDC, - LPPERI, + LP_PERI, LP_ANA, LP_AON, LP_APM, diff --git a/esp-hal-common/src/prelude.rs b/esp-hal-common/src/prelude.rs index ae16750d11a..1dd50f11faa 100644 --- a/esp-hal-common/src/prelude.rs +++ b/esp-hal-common/src/prelude.rs @@ -24,44 +24,44 @@ pub use nb; pub use crate::analog::SarAdcExt as _esp_hal_analog_SarAdcExt; #[cfg(any(esp32, esp32s2, esp32s3))] pub use crate::analog::SensExt as _esp_hal_analog_SensExt; -#[cfg(rmt)] -pub use crate::pulse_control::{ - ConfiguredChannel as _esp_hal_pulse_control_ConfiguredChannel, - OutputChannel as _esp_hal_pulse_control_OutputChannel, -}; +//#[cfg(rmt)] +//pub use crate::pulse_control::{ +// ConfiguredChannel as _esp_hal_pulse_control_ConfiguredChannel, +// OutputChannel as _esp_hal_pulse_control_OutputChannel, +//}; #[cfg(radio)] pub use crate::radio::RadioExt as _esp_hal_RadioExt; #[cfg(any(esp32, esp32s2))] pub use crate::spi::dma::WithDmaSpi3 as _esp_hal_spi_dma_WithDmaSpi3; pub use crate::{ clock::Clock as _esp_hal_clock_Clock, - dma::{ - DmaTransfer as _esp_hal_dma_DmaTransfer, - DmaTransferRxTx as _esp_hal_dma_DmaTransferRxTx, - }, + //dma::{ + // DmaTransfer as _esp_hal_dma_DmaTransfer, + // DmaTransferRxTx as _esp_hal_dma_DmaTransferRxTx, + //}, entry, gpio::{ InputPin as _esp_hal_gpio_InputPin, OutputPin as _esp_hal_gpio_OutputPin, Pin as _esp_hal_gpio_Pin, }, - i2c::Instance as _esp_hal_i2c_Instance, - ledc::{ - channel::{ - ChannelHW as _esp_hal_ledc_channel_ChannelHW, - ChannelIFace as _esp_hal_ledc_channel_ChannelIFace, - }, - timer::{ - TimerHW as _esp_hal_ledc_timer_TimerHW, - TimerIFace as _esp_hal_ledc_timer_TimerIFace, - }, - }, + // i2c::Instance as _esp_hal_i2c_Instance, + // ledc::{ + // channel::{ + // ChannelHW as _esp_hal_ledc_channel_ChannelHW, + // ChannelIFace as _esp_hal_ledc_channel_ChannelIFace, + // }, + // timer::{ + // TimerHW as _esp_hal_ledc_timer_TimerHW, + // TimerIFace as _esp_hal_ledc_timer_TimerIFace, + // }, + // }, macros::*, - spi::{ - dma::WithDmaSpi2 as _esp_hal_spi_dma_WithDmaSpi2, - Instance as _esp_hal_spi_Instance, - InstanceDma as _esp_hal_spi_InstanceDma, - }, + // spi::{ + // dma::WithDmaSpi2 as _esp_hal_spi_dma_WithDmaSpi2, + // Instance as _esp_hal_spi_Instance, + // InstanceDma as _esp_hal_spi_InstanceDma, + // }, system::SystemExt as _esp_hal_system_SystemExt, timer::{ Instance as _esp_hal_timer_Instance, diff --git a/esp-hal-common/src/uart.rs b/esp-hal-common/src/uart.rs index bc10e55a299..98afe823426 100644 --- a/esp-hal-common/src/uart.rs +++ b/esp-hal-common/src/uart.rs @@ -347,7 +347,7 @@ where /// Configures the RX-FIFO threshold pub fn set_rx_fifo_full_threshold(&mut self, threshold: u16) { - #[cfg(esp32)] + #[cfg(any(esp32, esp32c6))] let threshold: u8 = threshold as u8; self.uart @@ -559,7 +559,7 @@ where self } - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] fn change_baud(&self, baudrate: u32, clocks: &Clocks) { // we force the clock source to be APB and don't use the decimal part of the // divider diff --git a/esp32c6-hal/Cargo.toml b/esp32c6-hal/Cargo.toml index 8b5169cf430..a2000961588 100644 --- a/esp32c6-hal/Cargo.toml +++ b/esp32c6-hal/Cargo.toml @@ -15,7 +15,7 @@ keywords = [ "embedded", "embedded-hal", "esp", - "esp32c3", + "esp32c6", "no-std", ] categories = [ @@ -31,14 +31,15 @@ embedded-hal = { version = "0.2.7", features = ["unproven"] } embedded-hal-1 = { version = "=1.0.0-alpha.9", optional = true, package = "embedded-hal" } embedded-hal-async = { version = "0.1.0-alpha.3", optional = true } embedded-hal-nb = { version = "=1.0.0-alpha.1", optional = true } -esp-hal-common = { version = "0.4.0", features = ["esp32c6"], path = "../esp-hal-common" } +embedded-can = { version = "0.4.1", optional = true } +esp-hal-common = { features = ["esp32c6"], path = "../esp-hal-common" } r0 = "1.0.0" -riscv = "0.10.0" -riscv-rt = { version = "0.10.0", optional = true } +riscv = "0.10.1" +riscv-rt = { version = "0.11.0", optional = true } [dev-dependencies] critical-section = "1.1.1" -embassy-executor = { package = "embassy-executor", git = "https://github.com/embassy-rs/embassy/", rev = "eed34f9", features = ["nightly", "integrated-timers"] } +embassy-executor = { package = "embassy-executor", git = "https://github.com/embassy-rs/embassy/", rev = "cd9a65b", features = ["nightly", "integrated-timers"] } embedded-graphics = "0.7.1" esp-backtrace = { git = "https://github.com/jessebraham/esp-backtrace", branch = "feature/chip-support", features = ["esp32c6", "panic-handler", "exception-handler", "print-uart"] } esp-println = { git = "https://github.com/esp-rs/esp-println", rev = "fc4e9cf", features = ["esp32c6"] } @@ -49,15 +50,18 @@ static_cell = "1.0.0" [features] default = ["rt", "vectored"] +mcu-boot = [] direct-boot = [] -eh1 = ["esp-hal-common/eh1", "dep:embedded-hal-1", "dep:embedded-hal-nb"] +eh1 = ["esp-hal-common/eh1", "dep:embedded-hal-1", "dep:embedded-hal-nb", "dep:embedded-can"] rt = ["riscv-rt"] smartled = ["esp-hal-common/smartled"] ufmt = ["esp-hal-common/ufmt"] vectored = ["esp-hal-common/vectored"] +allow-opt-level-z = [] async = ["esp-hal-common/async", "embedded-hal-async"] embassy = ["esp-hal-common/embassy"] embassy-time-systick = ["esp-hal-common/embassy-time-systick", "embassy-time/tick-hz-16_000_000"] +embassy-time-timg0 = ["esp-hal-common/embassy-time-timg0", "embassy-time/tick-hz-1_000_000"] # [[example]] # name = "hello_rgb" diff --git a/esp32c6-hal/examples/blinky.rs b/esp32c6-hal/examples/blinky.rs new file mode 100644 index 00000000000..4851e1b4929 --- /dev/null +++ b/esp32c6-hal/examples/blinky.rs @@ -0,0 +1,44 @@ +//! Blinks an LED +//! +//! This assumes that a LED is connected to the pin assigned to `led`. (GPIO5) + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + gpio::IO, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Delay, +}; +use esp_backtrace as _; +use riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let mut wdt1 = timer_group1.wdt; + + // Set GPIO5 as an output, and set its state high initially. + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let mut led = io.pins.gpio5.into_push_pull_output(); + + led.set_high().unwrap(); + + // Initialize the Delay peripheral, and use it to toggle the LED state in a + // loop. + let mut delay = Delay::new(&clocks); + + loop { + led.toggle().unwrap(); + delay.delay_ms(500u32); + } +} diff --git a/esp32c6-hal/examples/hello_world.rs b/esp32c6-hal/examples/hello_world.rs index 2159a8b8587..83112037704 100644 --- a/esp32c6-hal/examples/hello_world.rs +++ b/esp32c6-hal/examples/hello_world.rs @@ -1,12 +1,90 @@ +#![feature(stmt_expr_attributes)] #![no_std] #![no_main] -use esp32c6_hal::peripherals; +// use esp32c6_hal::peripherals; +use core::{cell::RefCell, fmt::Write}; + +use critical_section::Mutex; + +use esp32c6_hal::{ + clock::{ClockControl, CpuClock}, + gpio::IO, + peripherals::{self, Peripherals, UART0}, + prelude::*, + //timer::TimerGroup, + //uart::{ + // config::{Config, DataBits, Parity, StopBits, AtCmdConfig}, + // TxRxPins, + //}, + //Uart, + //Cpu, +}; + +use nb::block; + +use esp_hal_common::system::SystemExt; + use esp_backtrace as _; +// static SERIAL: Mutex>>> = Mutex::new(RefCell::new(None)); + +use esp_println::println; + #[riscv_rt::entry] fn main() -> ! { - esp_println::println!("Hello!"); + esp_println::println!("fffff"); + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + // let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + let clocks = ClockControl::configure( + system.clock_control, + CpuClock::Clock80MHz, + ) + .freeze(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let mut led = io.pins.gpio5.into_push_pull_output(); + + led.set_high().unwrap(); + + // let mut serial0 = Uart::new(peripherals.UART0); - loop {} + // let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + // let mut timer0 = timer_group0.timer0; + // let mut wdt0 = timer_group0.wdt; + // let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + // let mut wdt1 = timer_group1.wdt; + + // let config = Config { + // baudrate: 115200, + // data_bits: DataBits::DataBits8, + // parity: Parity::ParityNone, + // stop_bits: StopBits::STOP1, + // }; + + // let pins = TxRxPins::new_tx_rx( + // io.pins.gpio1.into_push_pull_output(), + // io.pins.gpio2.into_floating_input(), + // ); + + // let mut serial1 = Uart::new_with_config(peripherals.UART1, Some(config), Some(pins), &clocks); + + // timer0.start(250u64.millis()); + + // println!("Start"); + // loop { + // serial1.write(0x42).ok(); + // let read = block!(serial1.read()); + + // match read { + // Ok(read) => println!("Read {:02x}", read), + // Err(err) => println!("Error {:?}", err), + // } + + // block!(timer0.wait()).unwrap(); + // } + loop{} } + + diff --git a/esp32c6-hal/ld/bl-esp32c6-memory.x b/esp32c6-hal/ld/bl-esp32c6-memory.x index 01051a5b51c..a12a7746b48 100644 --- a/esp32c6-hal/ld/bl-esp32c6-memory.x +++ b/esp32c6-hal/ld/bl-esp32c6-memory.x @@ -3,41 +3,37 @@ MEMORY /* MEMORY_MAP = [ [0x00000000, 0x00010000, "PADDING"], [0x42800000, 0x43000000, "DROM"], - [0x40800000, 0x40880000, "DRAM"], + [0x40800000, 0x40880000, "RAM"], [0x40800000, 0x40880000, "BYTE_ACCESSIBLE"], [0x4004AC00, 0x40050000, "DROM_MASK"], - [0x40000000, 0x4004AC00, "IROM_MASK"], - [0x42000000, 0x42800000, "IROM"], - [0x40800000, 0x40880000, "IRAM"], - [0x50000000, 0x50004000, "RTC_IRAM"], - [0x50000000, 0x50004000, "RTC_DRAM"], + [0x40000000, 0x4004AC00, "ROM_MASK"], + [0x42000000, 0x42800000, "ROM"], + [0x40800000, 0x40880000, "RAM"], + [0x50000000, 0x50004000, "RTC_RAM"], + [0x50000000, 0x50004000, "RTC_RAM"], [0x600FE000, 0x60100000, "MEM_INTERNAL2"], ] */ /* 512K of on soc RAM, 32K reserved for cache */ ICACHE : ORIGIN = 0x40800000, LENGTH = 32K /* Instruction RAM */ - IRAM : ORIGIN = 0x40800000 + 32K, LENGTH = 512K - 32K - /* Data RAM */ - DRAM : ORIGIN = 0x40800000 + 32K, LENGTH = 512K - 32K + RAM : ORIGIN = 0x40800000 + 32K, LENGTH = 512K /* External flash */ /* Instruction ROM */ - IROM : ORIGIN = 0x42000000 + 0x20, LENGTH = 0x400000 - 0x20 - /* Data ROM */ - DROM : ORIGIN = 0x42800000, LENGTH = 0x400000 + ROM : ORIGIN = 0x42000000 + 0x20, LENGTH = 0x400000 - 0x20 /* RTC fast memory (executable). Persists over deep sleep. */ - RTC_FAST : ORIGIN = 0x50000000, LENGTH = 16K /*- ESP_BOOTLOADER_RESERVE_RTC*/ + RTC_FAST : ORIGIN = 0x50000000, LENGTH = 16K /*- ESP_BOOTLOADER_RESERVE_RTC*/ } -REGION_ALIAS("REGION_TEXT", IROM); -REGION_ALIAS("REGION_RODATA", DROM); +REGION_ALIAS("REGION_TEXT", ROM); +REGION_ALIAS("REGION_RODATA", ROM); -REGION_ALIAS("REGION_DATA", DRAM); -REGION_ALIAS("REGION_BSS", DRAM); -REGION_ALIAS("REGION_HEAP", DRAM); -REGION_ALIAS("REGION_STACK", DRAM); +REGION_ALIAS("REGION_DATA", RAM); +REGION_ALIAS("REGION_BSS", RAM); +REGION_ALIAS("REGION_HEAP", RAM); +REGION_ALIAS("REGION_STACK", RAM); -REGION_ALIAS("REGION_RWTEXT", IRAM); +REGION_ALIAS("REGION_RWTEXT", RAM); REGION_ALIAS("REGION_RTC_FAST", RTC_FAST); diff --git a/esp32c6-hal/ld/bl-riscv-link.x b/esp32c6-hal/ld/bl-riscv-link.x index abf1bc0badb..c75b7d1a662 100644 --- a/esp32c6-hal/ld/bl-riscv-link.x +++ b/esp32c6-hal/ld/bl-riscv-link.x @@ -45,14 +45,10 @@ PROVIDE(_start_trap = default_start_trap); SECTIONS { - .text.dummy (NOLOAD) : - { - /* This section is intended to make _stext address work */ - . = ABSOLUTE(_stext); - } > REGION_TEXT .text _stext : { + . = ALIGN(4); _stext = .; /* Put reset handler first in .text section so it ends up as the entry */ /* point of the program. */ @@ -67,20 +63,6 @@ SECTIONS _etext = .; } > REGION_TEXT - /** - * This dummy section represents the .text section but in rodata. - * Thus, it must have its alignement and (at least) its size. - */ - .text_dummy (NOLOAD): - { - /* Start at the same alignement constraint than .text */ - . = ALIGN(ALIGNOF(.text)); - /* Create an empty gap as big as .text section */ - . = . + SIZEOF(.text); - /* Prepare the alignement of the section above. Few bytes (0x20) must be - * added for the mapping header. */ - . = ALIGN(0x10000) + 0x20; - } > REGION_RODATA .rodata : ALIGN(4) { @@ -112,12 +94,6 @@ SECTIONS _erwtext = .; } > REGION_RWTEXT - /* similar as text_dummy */ - .ram_dummy (NOLOAD) : { - . = ALIGN(ALIGNOF(.rwtext)); - . = . + SIZEOF(.rwtext); - } > REGION_DATA - .data : ALIGN(8) { _sidata = LOADADDR(.data); diff --git a/esp32c6-hal/ld/db-esp32c6-memory.x b/esp32c6-hal/ld/db-esp32c6-memory.x index 7d8500f2cbd..68a8d68e65e 100644 --- a/esp32c6-hal/ld/db-esp32c6-memory.x +++ b/esp32c6-hal/ld/db-esp32c6-memory.x @@ -28,7 +28,7 @@ MEMORY DROM : ORIGIN = 0x42800000, LENGTH = 0x400000 /* RTC fast memory (executable). Persists over deep sleep. */ - RTC_FAST : ORIGIN = 0x50000000, LENGTH = 16K /*- ESP_BOOTLOADER_RESERVE_RTC*/ + RTC_FAST : ORIGIN = 0x50000000, LENGTH = 16K /*- ESP_BOOTLOADER_RESERVE_RTC*/ } REGION_ALIAS("REGION_TEXT", IROM); diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index 220175b7519..9200068be25 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -3,9 +3,9 @@ use core::arch::{asm, global_asm}; pub use embedded_hal as ehal; -pub use esp_hal_common::{macros, peripherals}; +pub use esp_hal_common::{macros, peripherals, clock, gpio, prelude, uart, Uart, timer, Cpu, Delay, interrupt}; -// pub use self::gpio::IO; +pub use self::gpio::IO; // /// Common module for analog functions // pub mod analog { From bea124235ef1ae2af6563e49f0d29c606dbd1920 Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Fri, 20 Jan 2023 13:20:29 +0100 Subject: [PATCH 05/64] Simplify and fix the linker script update --- .../src/{ => clock}/clocks_ll/esp32c6.rs | 6 +- esp-hal-common/src/dma/gdma.rs | 62 ++++++++++++++----- esp-hal-common/src/dma/mod.rs | 8 +-- esp-hal-common/src/gpio/esp32c6.rs | 12 ++-- esp-hal-common/src/i2c.rs | 10 +-- esp-hal-common/src/interrupt/riscv.rs | 6 +- esp-hal-common/src/ledc/channel.rs | 38 +++++++++--- esp-hal-common/src/ledc/timer.rs | 1 + esp-hal-common/src/lib.rs | 10 +-- esp-hal-common/src/prelude.rs | 18 +++--- esp-hal-common/src/rom.rs | 2 +- esp-hal-common/src/spi.rs | 10 +-- esp-hal-common/src/systimer.rs | 4 +- esp-hal-common/src/timer.rs | 2 +- esp32c6-hal/Cargo.toml | 2 +- esp32c6-hal/examples/blinky.rs | 2 +- esp32c6-hal/ld/bl-esp32c6-memory.x | 12 +--- esp32c6-hal/ld/bl-riscv-link.x | 36 ++++++----- esp32c6-hal/ld/hal-defaults.x | 1 + esp32c6-hal/ld/rom-functions.x | 12 ++++ esp32c6-hal/src/lib.rs | 3 +- 21 files changed, 169 insertions(+), 88 deletions(-) rename esp-hal-common/src/{ => clock}/clocks_ll/esp32c6.rs (98%) create mode 100644 esp32c6-hal/ld/rom-functions.x diff --git a/esp-hal-common/src/clocks_ll/esp32c6.rs b/esp-hal-common/src/clock/clocks_ll/esp32c6.rs similarity index 98% rename from esp-hal-common/src/clocks_ll/esp32c6.rs rename to esp-hal-common/src/clock/clocks_ll/esp32c6.rs index 381b2b85474..6dd981fabea 100644 --- a/esp-hal-common/src/clocks_ll/esp32c6.rs +++ b/esp-hal-common/src/clock/clocks_ll/esp32c6.rs @@ -4,9 +4,13 @@ use crate::{ clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock}, regi2c_write, regi2c_write_mask, - rom::{ets_update_cpu_frequency, regi2c_ctrl_write_reg, regi2c_ctrl_write_reg_mask}, + rom::{rom_i2c_writeReg, rom_i2c_writeReg_Mask}, }; +extern "C" { + fn ets_update_cpu_frequency(ticks_per_us: u32); +} + const I2C_BBPLL: u32 = 0x66; const I2C_BBPLL_HOSTID: u32 = 0; diff --git a/esp-hal-common/src/dma/gdma.rs b/esp-hal-common/src/dma/gdma.rs index 1eda25228fe..bab17872c87 100644 --- a/esp-hal-common/src/dma/gdma.rs +++ b/esp-hal-common/src/dma/gdma.rs @@ -36,7 +36,7 @@ macro_rules! impl_channel { fn clear_out_interrupts() { let dma = unsafe { &*crate::peripherals::DMA::PTR }; - #[cfg(not(esp32s3))] + #[cfg(not(any(esp32c6, esp32s3)))] dma.[].write(|w| { w.out_eof() .set_bit() @@ -52,6 +52,22 @@ macro_rules! impl_channel { .set_bit() }); + #[cfg(esp32c6)] + dma.[].write(|w| { + w.out_eof() + .set_bit() + .out_dscr_err() + .set_bit() + .out_done() + .set_bit() + .out_total_eof() + .set_bit() + .outfifo_ovf() + .set_bit() + .outfifo_udf() + .set_bit() + }); + #[cfg(esp32s3)] dma.[].write(|w| { w.out_eof() @@ -89,9 +105,9 @@ macro_rules! impl_channel { fn has_out_descriptor_error() -> bool { let dma = unsafe { &*crate::peripherals::DMA::PTR }; - #[cfg(not(esp32s3))] + #[cfg(not(any(esp32c6, esp32s3)))] let ret = dma.[].read().out_dscr_err().bit(); - #[cfg(esp32s3)] + #[cfg(any(esp32c6, esp32s3))] let ret = dma.[].read().out_dscr_err().bit(); ret @@ -112,9 +128,9 @@ macro_rules! impl_channel { fn is_out_done() -> bool { let dma = unsafe { &*crate::peripherals::DMA::PTR }; - #[cfg(not(esp32s3))] + #[cfg(not(any(esp32c6, esp32s3)))] let ret = dma.[].read().out_total_eof().bit(); - #[cfg(esp32s3)] + #[cfg(any(esp32c6, esp32s3))] let ret = dma.[].read().out_total_eof().bit(); ret @@ -128,9 +144,9 @@ macro_rules! impl_channel { fn is_out_eof_interrupt_set() -> bool { let dma = unsafe { &*crate::peripherals::DMA::PTR }; - #[cfg(not(esp32s3))] + #[cfg(not(any(esp32c6, esp32s3)))] let ret = dma.[].read().out_eof().bit(); - #[cfg(esp32s3)] + #[cfg(any(esp32c6, esp32s3))] let ret = dma.[].read().out_eof().bit(); ret @@ -139,13 +155,13 @@ macro_rules! impl_channel { fn reset_out_eof_interrupt() { let dma = unsafe { &*crate::peripherals::DMA::PTR }; - #[cfg(not(esp32s3))] + #[cfg(not(any(esp32c6, esp32s3)))] dma.[].write(|w| { w.out_eof() .set_bit() }); - #[cfg(esp32s3)] + #[cfg(any(esp32c6, esp32s3))] dma.[].write(|w| { w.out_eof() .set_bit() @@ -171,7 +187,7 @@ macro_rules! impl_channel { fn clear_in_interrupts() { let dma = unsafe { &*crate::peripherals::DMA::PTR }; - #[cfg(not(esp32s3))] + #[cfg(not(any(esp32c6, esp32s3)))] dma.[].write(|w| { w.in_suc_eof() .set_bit() @@ -189,6 +205,24 @@ macro_rules! impl_channel { .set_bit() }); + #[cfg(esp32c6)] + dma.[].write(|w| { + w.in_suc_eof() + .set_bit() + .in_err_eof() + .set_bit() + .in_dscr_err() + .set_bit() + .in_dscr_empty() + .set_bit() + .in_done() + .set_bit() + .infifo_ovf() + .set_bit() + .infifo_udf() + .set_bit() + }); + #[cfg(esp32s3)] dma.[].write(|w| { w.in_suc_eof() @@ -228,9 +262,9 @@ macro_rules! impl_channel { fn has_in_descriptor_error() -> bool { let dma = unsafe { &*crate::peripherals::DMA::PTR }; - #[cfg(not(esp32s3))] + #[cfg(not(any(esp32c6, esp32s3)))] let ret = dma.[].read().in_dscr_err().bit(); - #[cfg(esp32s3)] + #[cfg(any(esp32c6, esp32s3))] let ret = dma.[].read().in_dscr_err().bit(); ret @@ -251,9 +285,9 @@ macro_rules! impl_channel { fn is_in_done() -> bool { let dma = unsafe { &*crate::peripherals::DMA::PTR }; - #[cfg(not(esp32s3))] + #[cfg(not(any(esp32c6, esp32s3)))] let ret = dma.[].read().in_suc_eof().bit(); - #[cfg(esp32s3)] + #[cfg(any(esp32c6, esp32s3))] let ret = dma.[].read().in_suc_eof().bit(); ret diff --git a/esp-hal-common/src/dma/mod.rs b/esp-hal-common/src/dma/mod.rs index b723b9be2f3..4c7247fc73d 100644 --- a/esp-hal-common/src/dma/mod.rs +++ b/esp-hal-common/src/dma/mod.rs @@ -54,19 +54,19 @@ pub enum DmaPeripheral { Spi2 = 0, #[cfg(any(pdma, esp32s3))] Spi3 = 1, - #[cfg(any(esp32c3, esp32s3))] + #[cfg(any(esp32c3, esp32c6, esp32s3))] Uhci0 = 2, - #[cfg(any(esp32, esp32s2, esp32c3, esp32s3))] + #[cfg(any(esp32, esp32s2, esp32c3, esp32c6, esp32s3))] I2s0 = 3, #[cfg(any(esp32, esp32s3))] I2s1 = 4, #[cfg(esp32s3)] LcdCam = 5, - #[cfg(any(esp32c3, esp32s3))] + #[cfg(any(esp32c3, esp32c6, esp32s3))] Aes = 6, #[cfg(gdma)] Sha = 7, - #[cfg(any(esp32c3, esp32s3))] + #[cfg(any(esp32c3, esp32c6, esp32s3))] Adc = 8, #[cfg(esp32s3)] Rmt = 9, diff --git a/esp-hal-common/src/gpio/esp32c6.rs b/esp-hal-common/src/gpio/esp32c6.rs index 7bf64885325..e5b38e6f985 100644 --- a/esp-hal-common/src/gpio/esp32c6.rs +++ b/esp-hal-common/src/gpio/esp32c6.rs @@ -128,12 +128,12 @@ pub enum InputSignal { #[allow(non_camel_case_types)] #[derive(PartialEq, Copy, Clone)] pub enum OutputSignal { - LEDC_LS_SIG_OUT0 = 0, - LEDC_LS_SIG_OUT1 = 1, - LEDC_LS_SIG_OUT2 = 2, - LEDC_LS_SIG_OUT3 = 3, - LEDC_LS_SIG_OUT4 = 4, - LEDC_LS_SIG_OUT5 = 5, + LEDC_LS_SIG0 = 0, + LEDC_LS_SIG1 = 1, + LEDC_LS_SIG2 = 2, + LEDC_LS_SIG3 = 3, + LEDC_LS_SIG4 = 4, + LEDC_LS_SIG5 = 5, U0TXD = 6, U0RTS = 7, U0DTR = 8, diff --git a/esp-hal-common/src/i2c.rs b/esp-hal-common/src/i2c.rs index e6cde248b18..4d18d301d0f 100644 --- a/esp-hal-common/src/i2c.rs +++ b/esp-hal-common/src/i2c.rs @@ -136,7 +136,7 @@ enum Ack { Nack, } -#[cfg(any(esp32c2, esp32c3, esp32s3))] +#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] enum Opcode { RStart = 6, Write = 1, @@ -352,7 +352,7 @@ pub trait Instance { self.set_frequency(clocks.i2c_clock.convert(), frequency); // Propagate configuration changes (only necessary with C2, C3, and S3) - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] self.register_block() .ctr .modify(|_, w| w.conf_upgate().set_bit()); @@ -553,7 +553,7 @@ pub trait Instance { ); } - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] /// Sets the frequency of the I2C interface by calculating and applying the /// associated timings - corresponds to i2c_ll_cal_bus_clk and /// i2c_ll_set_bus_timing in ESP-IDF @@ -641,7 +641,7 @@ pub trait Instance { ) { unsafe { // divider - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] self.register_block().clk_conf.modify(|_, w| { w.sclk_sel() .clear_bit() @@ -962,7 +962,7 @@ pub trait Instance { fn update_config(&self) { // Ensure that the configuration of the peripheral is correctly propagated // (only necessary for C3 and S3 variant) - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] self.register_block() .ctr .modify(|_, w| w.conf_upgate().set_bit()); diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index fd182526b58..43153429b1d 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -22,6 +22,8 @@ use crate::{ // general. However this makes things like preemtive multitasking easier in // future extern "C" { + #[cfg(feature = "esp32c6")] + fn interrupt0(frame: &mut TrapFrame); fn interrupt1(frame: &mut TrapFrame); fn interrupt2(frame: &mut TrapFrame); #[cfg(not(feature = "esp32c6"))] @@ -72,7 +74,7 @@ pub enum InterruptKind { #[derive(Debug, Copy, Clone)] pub enum CpuInterrupt { #[cfg(feature = "esp32c6")] - // Interrupt0 = 0, + Interrupt0 = 0, Interrupt1 = 1, Interrupt2, Interrupt3, @@ -466,6 +468,8 @@ pub unsafe extern "C" fn start_trap_rust_hal(trap_frame: *mut TrapFrame) { } else { let code = mcause::read().code(); match code { + #[cfg(esp32c6)] + 0 => interrupt0(trap_frame.as_mut().unwrap()), 1 => interrupt1(trap_frame.as_mut().unwrap()), 2 => interrupt2(trap_frame.as_mut().unwrap()), 3 => interrupt3(trap_frame.as_mut().unwrap()), diff --git a/esp-hal-common/src/ledc/channel.rs b/esp-hal-common/src/ledc/channel.rs index 25bff088a14..48d5ef7ab59 100644 --- a/esp-hal-common/src/ledc/channel.rs +++ b/esp-hal-common/src/ledc/channel.rs @@ -32,9 +32,9 @@ pub enum Number { Channel3, Channel4, Channel5, - #[cfg(not(any(esp32c2, esp32c3)))] + #[cfg(not(any(esp32c2, esp32c3, esp32c6)))] Channel6, - #[cfg(not(any(esp32c2, esp32c3)))] + #[cfg(not(any(esp32c2, esp32c3, esp32c6)))] Channel7, } @@ -192,7 +192,31 @@ macro_rules! start_duty_without_fading { }; } -#[cfg(not(esp32))] +#[cfg(esp32c6)] +/// Macro to start duty cycle, without fading +macro_rules! start_duty_without_fading { + ($self: ident, $num: literal) => { + paste! { + $self.ledc.[].write(|w| unsafe { + w.[]() + .set_bit() + }); + $self.ledc.[].write(|w| unsafe { + w.[]() + .set_bit() + .[]() + .bits(0x1) + .[]() + .bits(0x1) + .[]() + .bits(0x0) + }); + } + }; +} + + +#[cfg(not(any(esp32, esp32c6)))] /// Macro to start duty cycle, without fading macro_rules! start_duty_without_fading { ($self: ident, $num: literal) => { @@ -399,14 +423,14 @@ where self.output_pin .connect_peripheral_to_output(OutputSignal::LEDC_LS_SIG5); } - #[cfg(not(any(esp32c2, esp32c3)))] + #[cfg(not(any(esp32c2, esp32c3, esp32c6)))] Number::Channel6 => { set_channel!(self, l, 6, timer_number); update_channel!(self, l, 6); self.output_pin .connect_peripheral_to_output(OutputSignal::LEDC_LS_SIG6); } - #[cfg(not(any(esp32c2, esp32c3)))] + #[cfg(not(any(esp32c2, esp32c3, esp32c6)))] Number::Channel7 => { set_channel!(self, l, 7, timer_number); update_channel!(self, l, 7); @@ -430,9 +454,9 @@ where Number::Channel3 => set_duty!(self, l, 3, duty), Number::Channel4 => set_duty!(self, l, 4, duty), Number::Channel5 => set_duty!(self, l, 5, duty), - #[cfg(not(any(esp32c2, esp32c3)))] + #[cfg(not(any(esp32c2, esp32c3, esp32c6)))] Number::Channel6 => set_duty!(self, l, 6, duty), - #[cfg(not(any(esp32c2, esp32c3)))] + #[cfg(not(any(esp32c2, esp32c3, esp32c6)))] Number::Channel7 => set_duty!(self, l, 7, duty), }; } diff --git a/esp-hal-common/src/ledc/timer.rs b/esp-hal-common/src/ledc/timer.rs index 3e86587b8ea..0a942304084 100644 --- a/esp-hal-common/src/ledc/timer.rs +++ b/esp-hal-common/src/ledc/timer.rs @@ -171,6 +171,7 @@ where return Err(Error::Divisor); } + esp_println::println!("{src_freq}, {frequency}, {divisor}"); self.configure_hw(divisor as u32); self.update_hw(); diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index dcc9c7cf97b..f2184bca9dc 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -71,19 +71,19 @@ pub mod trapframe { // uart::Uart, // }; -pub use self::{gpio::*, uart::Uart, timer::Timer, delay::Delay, interrupt::*, }; +pub use self::{gpio::*, uart::Uart, timer::Timer, delay::Delay, interrupt::*, spi::Spi,}; // pub mod analog; pub mod clock; pub mod delay; -// pub mod dma; +pub mod dma; #[cfg(feature = "embassy")] pub mod embassy; pub mod gpio; -// pub mod i2c; +pub mod i2c; // #[cfg(i2s)] // pub mod i2s; -// pub mod ledc; +pub mod ledc; // #[cfg(mcpwm)] // pub mod mcpwm; #[cfg(usb_otg)] @@ -101,7 +101,7 @@ pub mod rom; #[cfg(not(esp32c6))] pub mod rtc_cntl; pub mod sha; -// pub mod spi; +pub mod spi; pub mod system; #[cfg(systimer)] pub mod systimer; diff --git a/esp-hal-common/src/prelude.rs b/esp-hal-common/src/prelude.rs index 1dd50f11faa..01a025ca57c 100644 --- a/esp-hal-common/src/prelude.rs +++ b/esp-hal-common/src/prelude.rs @@ -35,10 +35,10 @@ pub use crate::radio::RadioExt as _esp_hal_RadioExt; pub use crate::spi::dma::WithDmaSpi3 as _esp_hal_spi_dma_WithDmaSpi3; pub use crate::{ clock::Clock as _esp_hal_clock_Clock, - //dma::{ - // DmaTransfer as _esp_hal_dma_DmaTransfer, - // DmaTransferRxTx as _esp_hal_dma_DmaTransferRxTx, - //}, + dma::{ + DmaTransfer as _esp_hal_dma_DmaTransfer, + DmaTransferRxTx as _esp_hal_dma_DmaTransferRxTx, + }, entry, gpio::{ InputPin as _esp_hal_gpio_InputPin, @@ -57,11 +57,11 @@ pub use crate::{ // }, // }, macros::*, - // spi::{ - // dma::WithDmaSpi2 as _esp_hal_spi_dma_WithDmaSpi2, - // Instance as _esp_hal_spi_Instance, - // InstanceDma as _esp_hal_spi_InstanceDma, - // }, + spi::{ + dma::WithDmaSpi2 as _esp_hal_spi_dma_WithDmaSpi2, + Instance as _esp_hal_spi_Instance, + InstanceDma as _esp_hal_spi_InstanceDma, + }, system::SystemExt as _esp_hal_system_SystemExt, timer::{ Instance as _esp_hal_timer_Instance, diff --git a/esp-hal-common/src/rom.rs b/esp-hal-common/src/rom.rs index 3fa58515c59..f4549cdbc8c 100644 --- a/esp-hal-common/src/rom.rs +++ b/esp-hal-common/src/rom.rs @@ -40,4 +40,4 @@ macro_rules! regi2c_write_mask { ); } }; -} \ No newline at end of file +} diff --git a/esp-hal-common/src/spi.rs b/esp-hal-common/src/spi.rs index 07f6e1a6d29..8515bb1b0cf 100644 --- a/esp-hal-common/src/spi.rs +++ b/esp-hal-common/src/spi.rs @@ -1212,7 +1212,7 @@ where } } - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] fn enable_dma(&self) { let reg_block = self.register_block(); reg_block.dma_conf.modify(|_, w| w.dma_tx_ena().set_bit()); @@ -1224,7 +1224,7 @@ where // for non GDMA this is done in `assign_tx_device` / `assign_rx_device` } - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] fn clear_dma_interrupts(&self) { let reg_block = self.register_block(); reg_block.dma_int_clr.write(|w| { @@ -1680,12 +1680,12 @@ pub trait Instance { fn configure_datalen(&self, len: u32) { let reg_block = self.register_block(); - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] reg_block .ms_dlen .write(|w| unsafe { w.ms_data_bitlen().bits(len - 1) }); - #[cfg(not(any(esp32c2, esp32c3, esp32s3)))] + #[cfg(not(any(esp32c2, esp32c3, esp32c6, esp32s3)))] { reg_block .mosi_dlen @@ -1698,7 +1698,7 @@ pub trait Instance { } } -#[cfg(any(esp32c2, esp32c3))] +#[cfg(any(esp32c2, esp32c3, esp32c6))] impl Instance for crate::peripherals::SPI2 { #[inline(always)] fn register_block(&self) -> &RegisterBlock { diff --git a/esp-hal-common/src/systimer.rs b/esp-hal-common/src/systimer.rs index 4fc5b91564e..5bab37803ca 100644 --- a/esp-hal-common/src/systimer.rs +++ b/esp-hal-common/src/systimer.rs @@ -138,7 +138,7 @@ impl Alarm { #[cfg(esp32s2)] systimer.step.write(|w| w.timer_xtal_step().bits(0x1)); // run at XTAL freq, not 80 * XTAL freq - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] { tconf.write(|w| w.target0_timer_unit_sel().clear_bit()); // default, use unit 0 systimer @@ -148,7 +148,7 @@ impl Alarm { conf(tconf, hi, lo); - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] { match CHANNEL { 0 => { diff --git a/esp-hal-common/src/timer.rs b/esp-hal-common/src/timer.rs index 30364499223..384804e1035 100644 --- a/esp-hal-common/src/timer.rs +++ b/esp-hal-common/src/timer.rs @@ -622,7 +622,7 @@ where .bits(0) }); - #[cfg(any(esp32c2, esp32c3))] + #[cfg(any(esp32c2, esp32c3, esp32c6))] reg_block .wdtconfig0 .modify(|_, w| w.wdt_conf_update_en().set_bit()); diff --git a/esp32c6-hal/Cargo.toml b/esp32c6-hal/Cargo.toml index a2000961588..413c1225684 100644 --- a/esp32c6-hal/Cargo.toml +++ b/esp32c6-hal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "esp32c6-hal" -version = "0.3.0" +version = "0.1.0" authors = [ "Jesse Braham ", "Björn Quentin ", diff --git a/esp32c6-hal/examples/blinky.rs b/esp32c6-hal/examples/blinky.rs index 4851e1b4929..c13a4313c9d 100644 --- a/esp32c6-hal/examples/blinky.rs +++ b/esp32c6-hal/examples/blinky.rs @@ -39,6 +39,6 @@ fn main() -> ! { loop { led.toggle().unwrap(); - delay.delay_ms(500u32); + delay.delay_ms(2000u32); } } diff --git a/esp32c6-hal/ld/bl-esp32c6-memory.x b/esp32c6-hal/ld/bl-esp32c6-memory.x index a12a7746b48..d899e977cd1 100644 --- a/esp32c6-hal/ld/bl-esp32c6-memory.x +++ b/esp32c6-hal/ld/bl-esp32c6-memory.x @@ -16,11 +16,11 @@ MEMORY /* 512K of on soc RAM, 32K reserved for cache */ ICACHE : ORIGIN = 0x40800000, LENGTH = 32K - /* Instruction RAM */ - RAM : ORIGIN = 0x40800000 + 32K, LENGTH = 512K + /* Instruction and Data RAM */ + RAM : ORIGIN = 0x40800000 + 32K, LENGTH = 512K - 32K /* External flash */ - /* Instruction ROM */ + /* Instruction and Data ROM */ ROM : ORIGIN = 0x42000000 + 0x20, LENGTH = 0x400000 - 0x20 /* RTC fast memory (executable). Persists over deep sleep. */ @@ -30,10 +30,4 @@ MEMORY REGION_ALIAS("REGION_TEXT", ROM); REGION_ALIAS("REGION_RODATA", ROM); -REGION_ALIAS("REGION_DATA", RAM); -REGION_ALIAS("REGION_BSS", RAM); -REGION_ALIAS("REGION_HEAP", RAM); -REGION_ALIAS("REGION_STACK", RAM); - -REGION_ALIAS("REGION_RWTEXT", RAM); REGION_ALIAS("REGION_RTC_FAST", RTC_FAST); diff --git a/esp32c6-hal/ld/bl-riscv-link.x b/esp32c6-hal/ld/bl-riscv-link.x index c75b7d1a662..7cfcc72eef6 100644 --- a/esp32c6-hal/ld/bl-riscv-link.x +++ b/esp32c6-hal/ld/bl-riscv-link.x @@ -2,7 +2,7 @@ ENTRY(_start_hal) PROVIDE(_start_trap = _start_trap_hal); PROVIDE(_stext = ORIGIN(REGION_TEXT)); -PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK)); +PROVIDE(_stack_start = ORIGIN(RAM) + LENGTH(RAM)); PROVIDE(_max_hart_id = 0); PROVIDE(_hart_stack_size = 2K); PROVIDE(_heap_size = 0); @@ -45,10 +45,8 @@ PROVIDE(_start_trap = default_start_trap); SECTIONS { - .text _stext : { - . = ALIGN(4); _stext = .; /* Put reset handler first in .text section so it ends up as the entry */ /* point of the program. */ @@ -61,8 +59,16 @@ SECTIONS *(.text .text.*); _etext = .; - } > REGION_TEXT + } > ROM + /** + * Bootloader really wants to have separate segments for ROTEXT and RODATA + * Thus, we need to force a gap here. + */ + .text_gap (NOLOAD): { + . = . + 4; + . = ALIGN(4) + 0x20; + } > ROM .rodata : ALIGN(4) { @@ -75,7 +81,7 @@ SECTIONS section will have the correct alignment. */ . = ALIGN(4); _erodata = .; - } > REGION_RODATA + } > ROM .rwtext : ALIGN(4) { _irwtext = LOADADDR(.rwtext); @@ -92,7 +98,7 @@ SECTIONS . = ALIGN(4); _erwtext = .; - } > REGION_RWTEXT + } > RAM .data : ALIGN(8) { @@ -106,7 +112,7 @@ SECTIONS . = ALIGN(8); _edata = .; - } > REGION_DATA + } > RAM .bss (NOLOAD) : { @@ -128,7 +134,7 @@ SECTIONS . = ALIGN(8); _ebss = .; - } > REGION_BSS + } > RAM .uninit (NOLOAD) : ALIGN(4) { @@ -137,7 +143,7 @@ SECTIONS *(.uninit .uninit.*); . = ALIGN(4); __euninit = .; - } > REGION_BSS + } > RAM /* fictitious region that represents the memory available for the heap */ .heap (NOLOAD) : @@ -147,7 +153,7 @@ SECTIONS . += _heap_size; . = ALIGN(4); _eheap = .; - } > REGION_HEAP + } > RAM /* fictitious region that represents the memory available for the stack */ .stack (NOLOAD) : @@ -155,7 +161,7 @@ SECTIONS _estack = .; . = ABSOLUTE(_stack_start); _sstack = .; - } > REGION_STACK + } > RAM .rtc_fast.text : ALIGN(4) { *(.rtc_fast.literal .rtc_fast.text .rtc_fast.literal.* .rtc_fast.text.*) @@ -191,16 +197,16 @@ ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned"); ASSERT(ORIGIN(REGION_RODATA) % 4 == 0, " ERROR(riscv-rt): the start of the REGION_RODATA must be 4-byte aligned"); -ASSERT(ORIGIN(REGION_DATA) % 4 == 0, " -ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned"); +ASSERT(ORIGIN(RAM) % 4 == 0, " +ERROR(riscv-rt): the start of the RAM must be 4-byte aligned"); -ASSERT(ORIGIN(REGION_HEAP) % 4 == 0, " +ASSERT(_sheap % 4 == 0, " ERROR(riscv-rt): the start of the REGION_HEAP must be 4-byte aligned"); ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, " ERROR(riscv-rt): the start of the REGION_TEXT must be 4-byte aligned"); -ASSERT(ORIGIN(REGION_STACK) % 4 == 0, " +ASSERT(_sstack % 4 == 0, " ERROR(riscv-rt): the start of the REGION_STACK must be 4-byte aligned"); ASSERT(_stext % 4 == 0, " diff --git a/esp32c6-hal/ld/hal-defaults.x b/esp32c6-hal/ld/hal-defaults.x index a7bbdbb0bb7..85c38b127c7 100644 --- a/esp32c6-hal/ld/hal-defaults.x +++ b/esp32c6-hal/ld/hal-defaults.x @@ -1,3 +1,4 @@ +PROVIDE(interrupt0 = DefaultHandler); PROVIDE(interrupt1 = DefaultHandler); PROVIDE(interrupt2 = DefaultHandler); PROVIDE(interrupt3 = DefaultHandler); diff --git a/esp32c6-hal/ld/rom-functions.x b/esp32c6-hal/ld/rom-functions.x new file mode 100644 index 00000000000..b3afc9d2bfa --- /dev/null +++ b/esp32c6-hal/ld/rom-functions.x @@ -0,0 +1,12 @@ +ets_printf = 0x40000028; +PROVIDE(esp_rom_printf = ets_printf); +PROVIDE(cache_invalidate_icache_all = 0x4000064c); +PROVIDE(cache_suspend_icache = 0x40000698); +PROVIDE(cache_resume_icache = 0x4000069c); +/* TODO PROVIDE(cache_ibus_mmu_set = 0x40000560); */ +/* TODO PROVIDE(cache_dbus_mmu_set = 0x40000564); */ +PROVIDE(ets_delay_us = 0x40000040); +PROVIDE(ets_update_cpu_frequency_rom = 0x40000048); +PROVIDE(rom_i2c_writeReg = 0x400012c0); +PROVIDE(rom_i2c_writeReg_Mask = 0x400012e8); +PROVIDE(rtc_get_reset_reason = 0x40000018); diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index 9200068be25..7bc301fc286 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -3,7 +3,8 @@ use core::arch::{asm, global_asm}; pub use embedded_hal as ehal; -pub use esp_hal_common::{macros, peripherals, clock, gpio, prelude, uart, Uart, timer, Cpu, Delay, interrupt}; +pub use esp_hal_common::{macros, peripherals, clock, gpio, prelude, uart, Uart, timer, Cpu, Delay, interrupt, i2c, ledc, +systimer, dma, dma::gdma, spi }; pub use self::gpio::IO; From 5f8e2d15f3c49f4d40c8aee4f69bcfebd4b80082 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Wed, 25 Jan 2023 09:43:32 +0100 Subject: [PATCH 06/64] C6: add I2S --- esp-hal-common/src/gpio/esp32c3.rs | 2 +- esp-hal-common/src/i2s.rs | 12 ++++++------ esp-hal-common/src/lib.rs | 4 ++-- esp-hal-common/src/peripherals/esp32c6.rs | 2 +- esp32c6-hal/src/lib.rs | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/esp-hal-common/src/gpio/esp32c3.rs b/esp-hal-common/src/gpio/esp32c3.rs index 12b67709b1d..4a7a3490f02 100644 --- a/esp-hal-common/src/gpio/esp32c3.rs +++ b/esp-hal-common/src/gpio/esp32c3.rs @@ -97,7 +97,7 @@ pub enum OutputSignal { I2S_MCLK = 12, I2SO_BCK = 13, I2SO_WS = 14, - I2SI_SD = 15, + I2SO_SD = 15, I2SI_BCK = 16, I2SI_WS = 17, GPIO_WLAN_PRIO = 18, diff --git a/esp-hal-common/src/i2s.rs b/esp-hal-common/src/i2s.rs index 90b5670ccf2..27160ae1f59 100644 --- a/esp-hal-common/src/i2s.rs +++ b/esp-hal-common/src/i2s.rs @@ -17,7 +17,7 @@ use crate::{ #[cfg(any(esp32, esp32s2, esp32s3))] const I2S_LL_MCLK_DIVIDER_BIT_WIDTH: usize = 6; -#[cfg(any(esp32c3))] +#[cfg(any(esp32c3, esp32c6))] const I2S_LL_MCLK_DIVIDER_BIT_WIDTH: usize = 9; const I2S_LL_MCLK_DIVIDER_MAX: usize = (1 << I2S_LL_MCLK_DIVIDER_BIT_WIDTH) - 1; @@ -988,13 +988,13 @@ mod private { use fugit::HertzU32; use super::{DataFormat, I2sRx, I2sTx, RegisterAccess, Standard, I2S_LL_MCLK_DIVIDER_MAX}; - #[cfg(any(esp32c3, esp32s2))] + #[cfg(any(esp32c3, esp32c6, esp32s2))] use crate::peripherals::i2s::RegisterBlock; // on ESP32-S3 I2S1 doesn't support all features - use that to avoid using those features // by accident #[cfg(any(esp32s3, esp32))] use crate::peripherals::i2s1::RegisterBlock; - #[cfg(any(esp32c3, esp32s2))] + #[cfg(any(esp32c3, esp32c6, esp32s2))] use crate::peripherals::I2S; #[cfg(any(esp32s3, esp32))] use crate::peripherals::I2S0 as I2S; @@ -1289,7 +1289,7 @@ mod private { } } - #[cfg(any(esp32c3, esp32s3))] + #[cfg(any(esp32c3, esp32c6, esp32s3))] pub trait RegisterAccessPrivate: Signals + RegBlock { fn set_clock(&self, clock_settings: I2sClockDividers) { let i2s = self.register_block(); @@ -1609,7 +1609,7 @@ mod private { #[derive(Clone)] pub struct I2sPeripheral1 {} - #[cfg(esp32c3)] + #[cfg(any(esp32c3, esp32c6))] impl Signals for I2sPeripheral0 { fn get_peripheral(&self) -> Peripheral { Peripheral::I2s0 @@ -1632,7 +1632,7 @@ mod private { } fn dout_signal(&self) -> OutputSignal { - OutputSignal::I2SI_SD + OutputSignal::I2SO_SD } fn bclk_rx_signal(&self) -> OutputSignal { diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index f2184bca9dc..c95f450eebc 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -81,8 +81,8 @@ pub mod dma; pub mod embassy; pub mod gpio; pub mod i2c; -// #[cfg(i2s)] -// pub mod i2s; +#[cfg(i2s)] +pub mod i2s; pub mod ledc; // #[cfg(mcpwm)] // pub mod mcpwm; diff --git a/esp-hal-common/src/peripherals/esp32c6.rs b/esp-hal-common/src/peripherals/esp32c6.rs index 255bf93252a..72674f4c724 100644 --- a/esp-hal-common/src/peripherals/esp32c6.rs +++ b/esp-hal-common/src/peripherals/esp32c6.rs @@ -22,7 +22,7 @@ crate::peripherals! { HP_APM, HP_SYS, I2C0, - I2S0, + I2S, INTERRUPT_CORE0, INTPRI, IO_MUX, diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index 7bc301fc286..ebfd046841d 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -4,7 +4,7 @@ use core::arch::{asm, global_asm}; pub use embedded_hal as ehal; pub use esp_hal_common::{macros, peripherals, clock, gpio, prelude, uart, Uart, timer, Cpu, Delay, interrupt, i2c, ledc, -systimer, dma, dma::gdma, spi }; +systimer, dma, dma::gdma, spi, i2s, }; pub use self::gpio::IO; From 6db490d2564739505870c413966d0ddfdc1ec42d Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Thu, 5 Jan 2023 11:14:46 -0800 Subject: [PATCH 07/64] Create the `esp32c6-hal` package --- esp32c6-hal/ld/bl-riscv-link.x | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esp32c6-hal/ld/bl-riscv-link.x b/esp32c6-hal/ld/bl-riscv-link.x index 7cfcc72eef6..33c4229d43c 100644 --- a/esp32c6-hal/ld/bl-riscv-link.x +++ b/esp32c6-hal/ld/bl-riscv-link.x @@ -167,21 +167,21 @@ SECTIONS *(.rtc_fast.literal .rtc_fast.text .rtc_fast.literal.* .rtc_fast.text.*) } > REGION_RTC_FAST AT > REGION_RODATA - .rtc_fast.data : ALIGN(4) + .rtc_fast.data : ALIGN(4) { _rtc_fast_data_start = ABSOLUTE(.); *(.rtc_fast.data .rtc_fast.data.*) _rtc_fast_data_end = ABSOLUTE(.); } > REGION_RTC_FAST AT > REGION_RODATA - .rtc_fast.bss (NOLOAD) : ALIGN(4) + .rtc_fast.bss (NOLOAD) : ALIGN(4) { _rtc_fast_bss_start = ABSOLUTE(.); *(.rtc_fast.bss .rtc_fast.bss.*) _rtc_fast_bss_end = ABSOLUTE(.); } > REGION_RTC_FAST - .rtc_fast.noinit (NOLOAD) : ALIGN(4) + .rtc_fast.noinit (NOLOAD) : ALIGN(4) { *(.rtc_fast.noinit .rtc_fast.noinit.*) } > REGION_RTC_FAST From a38ced1cfdb8f338940e24556d69762cd4144d6f Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Fri, 6 Jan 2023 07:17:18 -0800 Subject: [PATCH 08/64] Teach `esp-hal-common` about the ESP32-C6 --- esp-hal-common/build.rs | 14 ++++++++++++++ esp-hal-common/src/peripherals/esp32c6.rs | 6 +++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/esp-hal-common/build.rs b/esp-hal-common/build.rs index 5b4ca003ac3..19b58f6f607 100644 --- a/esp-hal-common/build.rs +++ b/esp-hal-common/build.rs @@ -109,6 +109,20 @@ fn main() { "timg1", "usb_serial_jtag", ] + } else if esp32c6 { + vec![ + "esp32c6", + "riscv", + "single_core", + "dac", + "gdma", + "i2s", + "mcpwm", + "rmt", + "systimer", + "timg1", + "usb_serial_jtag", + ] } else if esp32s2 { vec![ "esp32s2", diff --git a/esp-hal-common/src/peripherals/esp32c6.rs b/esp-hal-common/src/peripherals/esp32c6.rs index 72674f4c724..0b14423a2dd 100644 --- a/esp-hal-common/src/peripherals/esp32c6.rs +++ b/esp-hal-common/src/peripherals/esp32c6.rs @@ -22,12 +22,12 @@ crate::peripherals! { HP_APM, HP_SYS, I2C0, - I2S, - INTERRUPT_CORE0, + I2S0, + INTMTX_CORE0, INTPRI, IO_MUX, LEDC, - LP_PERI, + LPPERI, LP_ANA, LP_AON, LP_APM, From 730f57f9b02e69f4ee2af3666e2553167b68f3d5 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Fri, 6 Jan 2023 07:17:31 -0800 Subject: [PATCH 09/64] Get a number of peripheral drivers building for the ESP32-C6 bckup initial clocks_ii --- esp-hal-common/src/clocks_ll/esp32c6.rs | 238 ++++++++++++++++++++++++ esp-hal-common/src/lib.rs | 10 +- esp-hal-common/src/rom.rs | 2 +- esp-hal-common/src/system.rs | 59 ++++++ 4 files changed, 303 insertions(+), 6 deletions(-) create mode 100644 esp-hal-common/src/clocks_ll/esp32c6.rs diff --git a/esp-hal-common/src/clocks_ll/esp32c6.rs b/esp-hal-common/src/clocks_ll/esp32c6.rs new file mode 100644 index 00000000000..52d8f7df03e --- /dev/null +++ b/esp-hal-common/src/clocks_ll/esp32c6.rs @@ -0,0 +1,238 @@ +use paste::paste; + +use crate::{ + clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock}, + regi2c_write, + regi2c_write_mask, + rom::{ets_update_cpu_frequency, regi2c_ctrl_write_reg, regi2c_ctrl_write_reg_mask}, +}; + +const I2C_BBPLL: u32 = 0x66; +const I2C_BBPLL_HOSTID: u32 = 0; + +const I2C_BBPLL_IR_CAL_DELAY: u32 = 0; +const I2C_BBPLL_IR_CAL_DELAY_MSB: u32 = 3; +const I2C_BBPLL_IR_CAL_DELAY_LSB: u32 = 0; + +const I2C_BBPLL_IR_CAL_CK_DIV: u32 = 0; +const I2C_BBPLL_IR_CAL_CK_DIV_MSB: u32 = 7; +const I2C_BBPLL_IR_CAL_CK_DIV_LSB: u32 = 4; + +const I2C_BBPLL_IR_CAL_EXT_CAP: u32 = 1; +const I2C_BBPLL_IR_CAL_EXT_CAP_MSB: u32 = 3; +const I2C_BBPLL_IR_CAL_EXT_CAP_LSB: u32 = 0; + +const I2C_BBPLL_IR_CAL_ENX_CAP: u32 = 1; +const I2C_BBPLL_IR_CAL_ENX_CAP_MSB: u32 = 4; +const I2C_BBPLL_IR_CAL_ENX_CAP_LSB: u32 = 4; + +const I2C_BBPLL_IR_CAL_RSTB: u32 = 1; +const I2C_BBPLL_IR_CAL_RSTB_MSB: u32 = 5; +const I2C_BBPLL_IR_CAL_RSTB_LSB: u32 = 5; + +const I2C_BBPLL_IR_CAL_START: u32 = 1; +const I2C_BBPLL_IR_CAL_START_MSB: u32 = 6; +const I2C_BBPLL_IR_CAL_START_LSB: u32 = 6; + +const I2C_BBPLL_IR_CAL_UNSTOP: u32 = 1; +const I2C_BBPLL_IR_CAL_UNSTOP_MSB: u32 = 7; +const I2C_BBPLL_IR_CAL_UNSTOP_LSB: u32 = 7; + +const I2C_BBPLL_OC_REF_DIV: u32 = 2; +const I2C_BBPLL_OC_REF_DIV_MSB: u32 = 3; +const I2C_BBPLL_OC_REF_DIV_LSB: u32 = 0; + +const I2C_BBPLL_OC_DCHGP: u32 = 2; +const I2C_BBPLL_OC_DCHGP_MSB: u32 = 6; +const I2C_BBPLL_OC_DCHGP_LSB: u32 = 4; + +const I2C_BBPLL_OC_ENB_FCAL: u32 = 2; +const I2C_BBPLL_OC_ENB_FCAL_MSB: u32 = 7; +const I2C_BBPLL_OC_ENB_FCAL_LSB: u32 = 7; + +const I2C_BBPLL_OC_DIV_7_0: u32 = 3; +const I2C_BBPLL_OC_DIV_7_0_MSB: u32 = 7; +const I2C_BBPLL_OC_DIV_7_0_LSB: u32 = 0; + +const I2C_BBPLL_RSTB_DIV_ADC: u32 = 4; +const I2C_BBPLL_RSTB_DIV_ADC_MSB: u32 = 0; +const I2C_BBPLL_RSTB_DIV_ADC_LSB: u32 = 0; + +const I2C_BBPLL_MODE_HF: u32 = 4; +const I2C_BBPLL_MODE_HF_MSB: u32 = 1; +const I2C_BBPLL_MODE_HF_LSB: u32 = 1; + +const I2C_BBPLL_DIV_ADC: u32 = 4; +const I2C_BBPLL_DIV_ADC_MSB: u32 = 3; +const I2C_BBPLL_DIV_ADC_LSB: u32 = 2; + +const I2C_BBPLL_DIV_DAC: u32 = 4; +const I2C_BBPLL_DIV_DAC_MSB: u32 = 4; +const I2C_BBPLL_DIV_DAC_LSB: u32 = 4; + +const I2C_BBPLL_DIV_CPU: u32 = 4; +const I2C_BBPLL_DIV_CPU_MSB: u32 = 5; +const I2C_BBPLL_DIV_CPU_LSB: u32 = 5; + +const I2C_BBPLL_OC_ENB_VCON: u32 = 4; +const I2C_BBPLL_OC_ENB_VCON_MSB: u32 = 6; +const I2C_BBPLL_OC_ENB_VCON_LSB: u32 = 6; + +const I2C_BBPLL_OC_TSCHGP: u32 = 4; +const I2C_BBPLL_OC_TSCHGP_MSB: u32 = 7; +const I2C_BBPLL_OC_TSCHGP_LSB: u32 = 7; + +const I2C_BBPLL_OC_DR1: u32 = 5; +const I2C_BBPLL_OC_DR1_MSB: u32 = 2; +const I2C_BBPLL_OC_DR1_LSB: u32 = 0; + +const I2C_BBPLL_OC_DR3: u32 = 5; +const I2C_BBPLL_OC_DR3_MSB: u32 = 6; +const I2C_BBPLL_OC_DR3_LSB: u32 = 4; + +const I2C_BBPLL_EN_USB: u32 = 5; +const I2C_BBPLL_EN_USB_MSB: u32 = 7; +const I2C_BBPLL_EN_USB_LSB: u32 = 7; + +const I2C_BBPLL_OC_DCUR: u32 = 6; +const I2C_BBPLL_OC_DCUR_MSB: u32 = 2; +const I2C_BBPLL_OC_DCUR_LSB: u32 = 0; + +const I2C_BBPLL_INC_CUR: u32 = 6; +const I2C_BBPLL_INC_CUR_MSB: u32 = 3; +const I2C_BBPLL_INC_CUR_LSB: u32 = 3; + +const I2C_BBPLL_OC_DHREF_SEL: u32 = 6; +const I2C_BBPLL_OC_DHREF_SEL_MSB: u32 = 5; +const I2C_BBPLL_OC_DHREF_SEL_LSB: u32 = 4; + +const I2C_BBPLL_OC_DLREF_SEL: u32 = 6; +const I2C_BBPLL_OC_DLREF_SEL_MSB: u32 = 7; +const I2C_BBPLL_OC_DLREF_SEL_LSB: u32 = 6; + +const I2C_BBPLL_OR_CAL_CAP: u32 = 8; +const I2C_BBPLL_OR_CAL_CAP_MSB: u32 = 3; +const I2C_BBPLL_OR_CAL_CAP_LSB: u32 = 0; + +const I2C_BBPLL_OR_CAL_UDF: u32 = 8; +const I2C_BBPLL_OR_CAL_UDF_MSB: u32 = 4; +const I2C_BBPLL_OR_CAL_UDF_LSB: u32 = 4; + +const I2C_BBPLL_OR_CAL_OVF: u32 = 8; +const I2C_BBPLL_OR_CAL_OVF_MSB: u32 = 5; +const I2C_BBPLL_OR_CAL_OVF_LSB: u32 = 5; + +const I2C_BBPLL_OR_CAL_END: u32 = 8; +const I2C_BBPLL_OR_CAL_END_MSB: u32 = 6; +const I2C_BBPLL_OR_CAL_END_LSB: u32 = 6; + +const I2C_BBPLL_OR_LOCK: u32 = 8; +const I2C_BBPLL_OR_LOCK_MSB: u32 = 7; +const I2C_BBPLL_OR_LOCK_LSB: u32 = 7; + +const I2C_BBPLL_OC_VCO_DBIAS: u32 = 9; +const I2C_BBPLL_OC_VCO_DBIAS_MSB: u32 = 1; +const I2C_BBPLL_OC_VCO_DBIAS_LSB: u32 = 0; + +const I2C_BBPLL_BBADC_DELAY2: u32 = 9; +const I2C_BBPLL_BBADC_DELAY2_MSB: u32 = 3; +const I2C_BBPLL_BBADC_DELAY2_LSB: u32 = 2; + +const I2C_BBPLL_BBADC_DVDD: u32 = 9; +const I2C_BBPLL_BBADC_DVDD_MSB: u32 = 5; +const I2C_BBPLL_BBADC_DVDD_LSB: u32 = 4; + +const I2C_BBPLL_BBADC_DREF: u32 = 9; +const I2C_BBPLL_BBADC_DREF_MSB: u32 = 7; +const I2C_BBPLL_BBADC_DREF_LSB: u32 = 6; + +const I2C_BBPLL_BBADC_DCUR: u32 = 10; +const I2C_BBPLL_BBADC_DCUR_MSB: u32 = 1; +const I2C_BBPLL_BBADC_DCUR_LSB: u32 = 0; + +const I2C_BBPLL_BBADC_INPUT_SHORT: u32 = 10; +const I2C_BBPLL_BBADC_INPUT_SHORT_MSB: u32 = 2; +const I2C_BBPLL_BBADC_INPUT_SHORT_LSB: u32 = 2; + +const I2C_BBPLL_ENT_PLL: u32 = 10; +const I2C_BBPLL_ENT_PLL_MSB: u32 = 3; +const I2C_BBPLL_ENT_PLL_LSB: u32 = 3; + +const I2C_BBPLL_DTEST: u32 = 10; +const I2C_BBPLL_DTEST_MSB: u32 = 5; +const I2C_BBPLL_DTEST_LSB: u32 = 4; + +const I2C_BBPLL_ENT_ADC: u32 = 10; +const I2C_BBPLL_ENT_ADC_MSB: u32 = 7; +const I2C_BBPLL_ENT_ADC_LSB: u32 = 6; + +pub(crate) fn esp32c6_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClock) { + unsafe { + let div_ref = 0u32; + let div7_0 = 8u32; + let dr1 = 0u32; + let dr3 = 0u32; + let dchgp = 5u32; + let dcur = 3u32; + let dbias = 2u32; + + let i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | div_ref; + let i2c_bbpll_div_7_0 = div7_0; + let i2c_bbpll_dcur = + (1 << I2C_BBPLL_OC_DLREF_SEL_LSB) | (3 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur; + + regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, i2c_bbpll_lref); + regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0); + regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_DR1, dr1); + regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_DR3, dr3); + regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur); + regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_VCO_DBIAS, dbias); + } +} + +pub(crate) fn esp32c6_rtc_bbpll_enable() { + let pmu = unsafe { &*crate::peripherals::PMU::PTR }; + + pmu.imm_hp_ck_power.modify(|_, w| { + w.tie_high_xpd_bb_i2c() + .set_bit() + .tie_high_xpd_bbpll() + .set_bit() + .tie_high_xpd_bbpll_i2c() + .set_bit() + .tie_high_global_bbpll_icg() + .set_bit() + }); +} + +pub(crate) fn esp32c6_rtc_update_to_xtal(freq: XtalClock, _div: u8) { + // TODO + let pcr = unsafe { &*crate::peripherals::PCR::PTR }; + unsafe { + ets_update_cpu_frequency(freq.mhz()); + // Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) + // first. + pcr.apb_freq_conf.modify(|_, w| { + w.apb_div_num() + .bits(0) + .apb_div_num() + .bits(_div - 1) + }); + + // Switch clock source + pcr + .sysclk_conf + .modify(|_, w| w.soc_clk_sel().bits(0)); + } +} + +pub(crate) fn esp32c6_rtc_apb_freq_update(apb_freq: ApbClock) { + // TODO + let lp_aon = unsafe { &*crate::peripherals::LP_AON::ptr() }; + let value = ((apb_freq.hz() >> 12) & u16::MAX as u32) + | (((apb_freq.hz() >> 12) & u16::MAX as u32) << 16); + + lp_aon + .store5 + .modify(|_, w| unsafe { w.lp_aon_store5().bits(value) }); +} diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index c95f450eebc..f49993aebde 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -76,7 +76,7 @@ pub use self::{gpio::*, uart::Uart, timer::Timer, delay::Delay, interrupt::*, sp // pub mod analog; pub mod clock; pub mod delay; -pub mod dma; +// pub mod dma; #[cfg(feature = "embassy")] pub mod embassy; pub mod gpio; @@ -101,7 +101,7 @@ pub mod rom; #[cfg(not(esp32c6))] pub mod rtc_cntl; pub mod sha; -pub mod spi; +// pub mod spi; pub mod system; #[cfg(systimer)] pub mod systimer; @@ -125,9 +125,9 @@ pub mod cpu_control; #[cfg_attr(esp32s3, path = "efuse/esp32s3.rs")] pub mod efuse; -#[cfg_attr(riscv, path = "interrupt/riscv.rs")] -#[cfg_attr(xtensa, path = "interrupt/xtensa.rs")] -pub mod interrupt; +// #[cfg_attr(riscv, path = "interrupt/riscv.rs")] +// #[cfg_attr(xtensa, path = "interrupt/xtensa.rs")] +// pub mod interrupt; /// Enumeration of CPU cores /// The actual number of available cores depends on the target. diff --git a/esp-hal-common/src/rom.rs b/esp-hal-common/src/rom.rs index f4549cdbc8c..3fa58515c59 100644 --- a/esp-hal-common/src/rom.rs +++ b/esp-hal-common/src/rom.rs @@ -40,4 +40,4 @@ macro_rules! regi2c_write_mask { ); } }; -} +} \ No newline at end of file diff --git a/esp-hal-common/src/system.rs b/esp-hal-common/src/system.rs index 17bf9fa0892..7fa7dd9af5a 100644 --- a/esp-hal-common/src/system.rs +++ b/esp-hal-common/src/system.rs @@ -80,7 +80,11 @@ impl PeripheralClockControl { ) }; +<<<<<<< HEAD #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s2, esp32s3))] +======= + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] +>>>>>>> b278bca (Get a number of peripheral drivers building for the ESP32-C6) let (perip_clk_en1, perip_rst_en1) = { (&system.perip_clk_en1, &system.perip_rst_en1) }; match peripheral { @@ -249,6 +253,61 @@ impl PeripheralClockControl { } } +#[cfg(esp32c6)] +impl PeripheralClockControl { + /// Enables and resets the given peripheral + pub fn enable(&mut self, peripheral: Peripheral) { + let system = unsafe { &*SystemPeripheral::PTR }; + + match peripheral { + Peripheral::Spi2 => { + system.spi2_conf.modify(|_, w| w.spi2_clk_en().set_bit()); + system.spi2_conf.modify(|_, w| w.spi2_rst_en().clear_bit()); + } + Peripheral::I2cExt0 => { + // FIXME + // perip_clk_en0.modify(|_, w| w.i2c_ext0_clk_en().set_bit()); + // perip_rst_en0.modify(|_, w| w.i2c_ext0_rst().clear_bit()); + } + Peripheral::Rmt => { + system.rmt_conf.modify(|_, w| w.rmt_clk_en().set_bit()); + system.rmt_conf.modify(|_, w| w.rmt_rst_en().clear_bit()); + } + Peripheral::Ledc => { + system.ledc_conf.modify(|_, w| w.ledc_clk_en().set_bit()); + system.ledc_conf.modify(|_, w| w.ledc_rst_en().clear_bit()); + } + Peripheral::Mcpwm0 | Peripheral::Mcpwm1 => { + system.pwm_conf.modify(|_, w| w.pwm_clk_en().set_bit()); + system.pwm_conf.modify(|_, w| w.pwm_rst_en().clear_bit()); + } + Peripheral::ApbSarAdc => { + // TODO + } + Peripheral::Gdma => { + system.gdma_conf.modify(|_, w| w.gdma_clk_en().set_bit()); + system.gdma_conf.modify(|_, w| w.gdma_rst_en().clear_bit()); + } + Peripheral::I2s0 => { + system.i2s_conf.modify(|_, w| w.i2s_clk_en().set_bit()); + system.i2s_conf.modify(|_, w| w.i2s_rst_en().clear_bit()); + } + Peripheral::Twai0 => { + system.twai0_conf.modify(|_, w| w.twai0_clk_en().set_bit()); + system + .twai0_conf + .modify(|_, w| w.twai0_rst_en().clear_bit()); + } + Peripheral::Twai1 => { + system.twai1_conf.modify(|_, w| w.twai1_clk_en().set_bit()); + system + .twai1_conf + .modify(|_, w| w.twai1_rst_en().clear_bit()); + } + } + } +} + /// Controls the configuration of the chip's clocks. pub struct SystemClockControl { _private: (), From 3cec8bb948354c6d8474ae4c009b6a97c89b6f6d Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Thu, 5 Jan 2023 11:14:46 -0800 Subject: [PATCH 10/64] Create the `esp32c6-hal` package --- esp-hal-common/src/clocks_ll/esp32c6.rs | 2 -- esp-hal-common/src/lib.rs | 6 +++--- esp-hal-common/src/peripherals/esp32c6.rs | 4 ++-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/esp-hal-common/src/clocks_ll/esp32c6.rs b/esp-hal-common/src/clocks_ll/esp32c6.rs index 52d8f7df03e..381b2b85474 100644 --- a/esp-hal-common/src/clocks_ll/esp32c6.rs +++ b/esp-hal-common/src/clocks_ll/esp32c6.rs @@ -206,7 +206,6 @@ pub(crate) fn esp32c6_rtc_bbpll_enable() { } pub(crate) fn esp32c6_rtc_update_to_xtal(freq: XtalClock, _div: u8) { - // TODO let pcr = unsafe { &*crate::peripherals::PCR::PTR }; unsafe { ets_update_cpu_frequency(freq.mhz()); @@ -227,7 +226,6 @@ pub(crate) fn esp32c6_rtc_update_to_xtal(freq: XtalClock, _div: u8) { } pub(crate) fn esp32c6_rtc_apb_freq_update(apb_freq: ApbClock) { - // TODO let lp_aon = unsafe { &*crate::peripherals::LP_AON::ptr() }; let value = ((apb_freq.hz() >> 12) & u16::MAX as u32) | (((apb_freq.hz() >> 12) & u16::MAX as u32) << 16); diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index f49993aebde..fa832f1891b 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -125,9 +125,9 @@ pub mod cpu_control; #[cfg_attr(esp32s3, path = "efuse/esp32s3.rs")] pub mod efuse; -// #[cfg_attr(riscv, path = "interrupt/riscv.rs")] -// #[cfg_attr(xtensa, path = "interrupt/xtensa.rs")] -// pub mod interrupt; +#[cfg_attr(riscv, path = "interrupt/riscv.rs")] +#[cfg_attr(xtensa, path = "interrupt/xtensa.rs")] +pub mod interrupt; /// Enumeration of CPU cores /// The actual number of available cores depends on the target. diff --git a/esp-hal-common/src/peripherals/esp32c6.rs b/esp-hal-common/src/peripherals/esp32c6.rs index 0b14423a2dd..255bf93252a 100644 --- a/esp-hal-common/src/peripherals/esp32c6.rs +++ b/esp-hal-common/src/peripherals/esp32c6.rs @@ -23,11 +23,11 @@ crate::peripherals! { HP_SYS, I2C0, I2S0, - INTMTX_CORE0, + INTERRUPT_CORE0, INTPRI, IO_MUX, LEDC, - LPPERI, + LP_PERI, LP_ANA, LP_AON, LP_APM, From 1e5ef3c2a72aaa67734891dbb15e9e98c89e0f85 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Fri, 20 Jan 2023 11:21:10 +0100 Subject: [PATCH 11/64] C6: update --- esp-hal-common/src/interrupt/riscv.rs | 2 +- esp32c6-hal/ld/bl-riscv-link.x | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index 43153429b1d..8836d9f411f 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -74,7 +74,7 @@ pub enum InterruptKind { #[derive(Debug, Copy, Clone)] pub enum CpuInterrupt { #[cfg(feature = "esp32c6")] - Interrupt0 = 0, + // Interrupt0 = 0, Interrupt1 = 1, Interrupt2, Interrupt3, diff --git a/esp32c6-hal/ld/bl-riscv-link.x b/esp32c6-hal/ld/bl-riscv-link.x index 33c4229d43c..6dcb6404fd8 100644 --- a/esp32c6-hal/ld/bl-riscv-link.x +++ b/esp32c6-hal/ld/bl-riscv-link.x @@ -47,6 +47,7 @@ SECTIONS { .text _stext : { + . = ALIGN(4); _stext = .; /* Put reset handler first in .text section so it ends up as the entry */ /* point of the program. */ From e6df68d74fdb9e8834b51bb3b11c3725ec459c83 Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Fri, 20 Jan 2023 13:20:29 +0100 Subject: [PATCH 12/64] Simplify and fix the linker script --- esp32c6-hal/ld/bl-riscv-link.x | 1 - 1 file changed, 1 deletion(-) diff --git a/esp32c6-hal/ld/bl-riscv-link.x b/esp32c6-hal/ld/bl-riscv-link.x index 6dcb6404fd8..33c4229d43c 100644 --- a/esp32c6-hal/ld/bl-riscv-link.x +++ b/esp32c6-hal/ld/bl-riscv-link.x @@ -47,7 +47,6 @@ SECTIONS { .text _stext : { - . = ALIGN(4); _stext = .; /* Put reset handler first in .text section so it ends up as the entry */ /* point of the program. */ From d2b07347a67a60132d5d6a25cdf774ab43129a0b Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Tue, 24 Jan 2023 13:46:52 +0100 Subject: [PATCH 13/64] update --- esp-hal-common/src/clocks_ll/esp32c6.rs | 236 ------------------------ esp-hal-common/src/interrupt/riscv.rs | 2 +- esp-hal-common/src/lib.rs | 4 +- esp-hal-common/src/rom.rs | 2 +- 4 files changed, 4 insertions(+), 240 deletions(-) delete mode 100644 esp-hal-common/src/clocks_ll/esp32c6.rs diff --git a/esp-hal-common/src/clocks_ll/esp32c6.rs b/esp-hal-common/src/clocks_ll/esp32c6.rs deleted file mode 100644 index 381b2b85474..00000000000 --- a/esp-hal-common/src/clocks_ll/esp32c6.rs +++ /dev/null @@ -1,236 +0,0 @@ -use paste::paste; - -use crate::{ - clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock}, - regi2c_write, - regi2c_write_mask, - rom::{ets_update_cpu_frequency, regi2c_ctrl_write_reg, regi2c_ctrl_write_reg_mask}, -}; - -const I2C_BBPLL: u32 = 0x66; -const I2C_BBPLL_HOSTID: u32 = 0; - -const I2C_BBPLL_IR_CAL_DELAY: u32 = 0; -const I2C_BBPLL_IR_CAL_DELAY_MSB: u32 = 3; -const I2C_BBPLL_IR_CAL_DELAY_LSB: u32 = 0; - -const I2C_BBPLL_IR_CAL_CK_DIV: u32 = 0; -const I2C_BBPLL_IR_CAL_CK_DIV_MSB: u32 = 7; -const I2C_BBPLL_IR_CAL_CK_DIV_LSB: u32 = 4; - -const I2C_BBPLL_IR_CAL_EXT_CAP: u32 = 1; -const I2C_BBPLL_IR_CAL_EXT_CAP_MSB: u32 = 3; -const I2C_BBPLL_IR_CAL_EXT_CAP_LSB: u32 = 0; - -const I2C_BBPLL_IR_CAL_ENX_CAP: u32 = 1; -const I2C_BBPLL_IR_CAL_ENX_CAP_MSB: u32 = 4; -const I2C_BBPLL_IR_CAL_ENX_CAP_LSB: u32 = 4; - -const I2C_BBPLL_IR_CAL_RSTB: u32 = 1; -const I2C_BBPLL_IR_CAL_RSTB_MSB: u32 = 5; -const I2C_BBPLL_IR_CAL_RSTB_LSB: u32 = 5; - -const I2C_BBPLL_IR_CAL_START: u32 = 1; -const I2C_BBPLL_IR_CAL_START_MSB: u32 = 6; -const I2C_BBPLL_IR_CAL_START_LSB: u32 = 6; - -const I2C_BBPLL_IR_CAL_UNSTOP: u32 = 1; -const I2C_BBPLL_IR_CAL_UNSTOP_MSB: u32 = 7; -const I2C_BBPLL_IR_CAL_UNSTOP_LSB: u32 = 7; - -const I2C_BBPLL_OC_REF_DIV: u32 = 2; -const I2C_BBPLL_OC_REF_DIV_MSB: u32 = 3; -const I2C_BBPLL_OC_REF_DIV_LSB: u32 = 0; - -const I2C_BBPLL_OC_DCHGP: u32 = 2; -const I2C_BBPLL_OC_DCHGP_MSB: u32 = 6; -const I2C_BBPLL_OC_DCHGP_LSB: u32 = 4; - -const I2C_BBPLL_OC_ENB_FCAL: u32 = 2; -const I2C_BBPLL_OC_ENB_FCAL_MSB: u32 = 7; -const I2C_BBPLL_OC_ENB_FCAL_LSB: u32 = 7; - -const I2C_BBPLL_OC_DIV_7_0: u32 = 3; -const I2C_BBPLL_OC_DIV_7_0_MSB: u32 = 7; -const I2C_BBPLL_OC_DIV_7_0_LSB: u32 = 0; - -const I2C_BBPLL_RSTB_DIV_ADC: u32 = 4; -const I2C_BBPLL_RSTB_DIV_ADC_MSB: u32 = 0; -const I2C_BBPLL_RSTB_DIV_ADC_LSB: u32 = 0; - -const I2C_BBPLL_MODE_HF: u32 = 4; -const I2C_BBPLL_MODE_HF_MSB: u32 = 1; -const I2C_BBPLL_MODE_HF_LSB: u32 = 1; - -const I2C_BBPLL_DIV_ADC: u32 = 4; -const I2C_BBPLL_DIV_ADC_MSB: u32 = 3; -const I2C_BBPLL_DIV_ADC_LSB: u32 = 2; - -const I2C_BBPLL_DIV_DAC: u32 = 4; -const I2C_BBPLL_DIV_DAC_MSB: u32 = 4; -const I2C_BBPLL_DIV_DAC_LSB: u32 = 4; - -const I2C_BBPLL_DIV_CPU: u32 = 4; -const I2C_BBPLL_DIV_CPU_MSB: u32 = 5; -const I2C_BBPLL_DIV_CPU_LSB: u32 = 5; - -const I2C_BBPLL_OC_ENB_VCON: u32 = 4; -const I2C_BBPLL_OC_ENB_VCON_MSB: u32 = 6; -const I2C_BBPLL_OC_ENB_VCON_LSB: u32 = 6; - -const I2C_BBPLL_OC_TSCHGP: u32 = 4; -const I2C_BBPLL_OC_TSCHGP_MSB: u32 = 7; -const I2C_BBPLL_OC_TSCHGP_LSB: u32 = 7; - -const I2C_BBPLL_OC_DR1: u32 = 5; -const I2C_BBPLL_OC_DR1_MSB: u32 = 2; -const I2C_BBPLL_OC_DR1_LSB: u32 = 0; - -const I2C_BBPLL_OC_DR3: u32 = 5; -const I2C_BBPLL_OC_DR3_MSB: u32 = 6; -const I2C_BBPLL_OC_DR3_LSB: u32 = 4; - -const I2C_BBPLL_EN_USB: u32 = 5; -const I2C_BBPLL_EN_USB_MSB: u32 = 7; -const I2C_BBPLL_EN_USB_LSB: u32 = 7; - -const I2C_BBPLL_OC_DCUR: u32 = 6; -const I2C_BBPLL_OC_DCUR_MSB: u32 = 2; -const I2C_BBPLL_OC_DCUR_LSB: u32 = 0; - -const I2C_BBPLL_INC_CUR: u32 = 6; -const I2C_BBPLL_INC_CUR_MSB: u32 = 3; -const I2C_BBPLL_INC_CUR_LSB: u32 = 3; - -const I2C_BBPLL_OC_DHREF_SEL: u32 = 6; -const I2C_BBPLL_OC_DHREF_SEL_MSB: u32 = 5; -const I2C_BBPLL_OC_DHREF_SEL_LSB: u32 = 4; - -const I2C_BBPLL_OC_DLREF_SEL: u32 = 6; -const I2C_BBPLL_OC_DLREF_SEL_MSB: u32 = 7; -const I2C_BBPLL_OC_DLREF_SEL_LSB: u32 = 6; - -const I2C_BBPLL_OR_CAL_CAP: u32 = 8; -const I2C_BBPLL_OR_CAL_CAP_MSB: u32 = 3; -const I2C_BBPLL_OR_CAL_CAP_LSB: u32 = 0; - -const I2C_BBPLL_OR_CAL_UDF: u32 = 8; -const I2C_BBPLL_OR_CAL_UDF_MSB: u32 = 4; -const I2C_BBPLL_OR_CAL_UDF_LSB: u32 = 4; - -const I2C_BBPLL_OR_CAL_OVF: u32 = 8; -const I2C_BBPLL_OR_CAL_OVF_MSB: u32 = 5; -const I2C_BBPLL_OR_CAL_OVF_LSB: u32 = 5; - -const I2C_BBPLL_OR_CAL_END: u32 = 8; -const I2C_BBPLL_OR_CAL_END_MSB: u32 = 6; -const I2C_BBPLL_OR_CAL_END_LSB: u32 = 6; - -const I2C_BBPLL_OR_LOCK: u32 = 8; -const I2C_BBPLL_OR_LOCK_MSB: u32 = 7; -const I2C_BBPLL_OR_LOCK_LSB: u32 = 7; - -const I2C_BBPLL_OC_VCO_DBIAS: u32 = 9; -const I2C_BBPLL_OC_VCO_DBIAS_MSB: u32 = 1; -const I2C_BBPLL_OC_VCO_DBIAS_LSB: u32 = 0; - -const I2C_BBPLL_BBADC_DELAY2: u32 = 9; -const I2C_BBPLL_BBADC_DELAY2_MSB: u32 = 3; -const I2C_BBPLL_BBADC_DELAY2_LSB: u32 = 2; - -const I2C_BBPLL_BBADC_DVDD: u32 = 9; -const I2C_BBPLL_BBADC_DVDD_MSB: u32 = 5; -const I2C_BBPLL_BBADC_DVDD_LSB: u32 = 4; - -const I2C_BBPLL_BBADC_DREF: u32 = 9; -const I2C_BBPLL_BBADC_DREF_MSB: u32 = 7; -const I2C_BBPLL_BBADC_DREF_LSB: u32 = 6; - -const I2C_BBPLL_BBADC_DCUR: u32 = 10; -const I2C_BBPLL_BBADC_DCUR_MSB: u32 = 1; -const I2C_BBPLL_BBADC_DCUR_LSB: u32 = 0; - -const I2C_BBPLL_BBADC_INPUT_SHORT: u32 = 10; -const I2C_BBPLL_BBADC_INPUT_SHORT_MSB: u32 = 2; -const I2C_BBPLL_BBADC_INPUT_SHORT_LSB: u32 = 2; - -const I2C_BBPLL_ENT_PLL: u32 = 10; -const I2C_BBPLL_ENT_PLL_MSB: u32 = 3; -const I2C_BBPLL_ENT_PLL_LSB: u32 = 3; - -const I2C_BBPLL_DTEST: u32 = 10; -const I2C_BBPLL_DTEST_MSB: u32 = 5; -const I2C_BBPLL_DTEST_LSB: u32 = 4; - -const I2C_BBPLL_ENT_ADC: u32 = 10; -const I2C_BBPLL_ENT_ADC_MSB: u32 = 7; -const I2C_BBPLL_ENT_ADC_LSB: u32 = 6; - -pub(crate) fn esp32c6_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClock) { - unsafe { - let div_ref = 0u32; - let div7_0 = 8u32; - let dr1 = 0u32; - let dr3 = 0u32; - let dchgp = 5u32; - let dcur = 3u32; - let dbias = 2u32; - - let i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | div_ref; - let i2c_bbpll_div_7_0 = div7_0; - let i2c_bbpll_dcur = - (1 << I2C_BBPLL_OC_DLREF_SEL_LSB) | (3 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur; - - regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, i2c_bbpll_lref); - regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0); - regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_DR1, dr1); - regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_DR3, dr3); - regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur); - regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_VCO_DBIAS, dbias); - } -} - -pub(crate) fn esp32c6_rtc_bbpll_enable() { - let pmu = unsafe { &*crate::peripherals::PMU::PTR }; - - pmu.imm_hp_ck_power.modify(|_, w| { - w.tie_high_xpd_bb_i2c() - .set_bit() - .tie_high_xpd_bbpll() - .set_bit() - .tie_high_xpd_bbpll_i2c() - .set_bit() - .tie_high_global_bbpll_icg() - .set_bit() - }); -} - -pub(crate) fn esp32c6_rtc_update_to_xtal(freq: XtalClock, _div: u8) { - let pcr = unsafe { &*crate::peripherals::PCR::PTR }; - unsafe { - ets_update_cpu_frequency(freq.mhz()); - // Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) - // first. - pcr.apb_freq_conf.modify(|_, w| { - w.apb_div_num() - .bits(0) - .apb_div_num() - .bits(_div - 1) - }); - - // Switch clock source - pcr - .sysclk_conf - .modify(|_, w| w.soc_clk_sel().bits(0)); - } -} - -pub(crate) fn esp32c6_rtc_apb_freq_update(apb_freq: ApbClock) { - let lp_aon = unsafe { &*crate::peripherals::LP_AON::ptr() }; - let value = ((apb_freq.hz() >> 12) & u16::MAX as u32) - | (((apb_freq.hz() >> 12) & u16::MAX as u32) << 16); - - lp_aon - .store5 - .modify(|_, w| unsafe { w.lp_aon_store5().bits(value) }); -} diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index 8836d9f411f..43153429b1d 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -74,7 +74,7 @@ pub enum InterruptKind { #[derive(Debug, Copy, Clone)] pub enum CpuInterrupt { #[cfg(feature = "esp32c6")] - // Interrupt0 = 0, + Interrupt0 = 0, Interrupt1 = 1, Interrupt2, Interrupt3, diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index fa832f1891b..c95f450eebc 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -76,7 +76,7 @@ pub use self::{gpio::*, uart::Uart, timer::Timer, delay::Delay, interrupt::*, sp // pub mod analog; pub mod clock; pub mod delay; -// pub mod dma; +pub mod dma; #[cfg(feature = "embassy")] pub mod embassy; pub mod gpio; @@ -101,7 +101,7 @@ pub mod rom; #[cfg(not(esp32c6))] pub mod rtc_cntl; pub mod sha; -// pub mod spi; +pub mod spi; pub mod system; #[cfg(systimer)] pub mod systimer; diff --git a/esp-hal-common/src/rom.rs b/esp-hal-common/src/rom.rs index 3fa58515c59..f4549cdbc8c 100644 --- a/esp-hal-common/src/rom.rs +++ b/esp-hal-common/src/rom.rs @@ -40,4 +40,4 @@ macro_rules! regi2c_write_mask { ); } }; -} \ No newline at end of file +} From bde4bb5b51f57dbf35060e8ffee1ef462a566240 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Wed, 25 Jan 2023 09:43:32 +0100 Subject: [PATCH 14/64] C6: add I2S --- esp-hal-common/src/peripherals/esp32c6.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp-hal-common/src/peripherals/esp32c6.rs b/esp-hal-common/src/peripherals/esp32c6.rs index 255bf93252a..72674f4c724 100644 --- a/esp-hal-common/src/peripherals/esp32c6.rs +++ b/esp-hal-common/src/peripherals/esp32c6.rs @@ -22,7 +22,7 @@ crate::peripherals! { HP_APM, HP_SYS, I2C0, - I2S0, + I2S, INTERRUPT_CORE0, INTPRI, IO_MUX, From 6351eee0014f4ecb2ec22c3013f38755f0609a95 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Tue, 24 Jan 2023 13:46:52 +0100 Subject: [PATCH 15/64] update --- esp-hal-common/src/lib.rs | 5 ++--- esp32c6-hal/src/lib.rs | 22 ++++++++++++++++++++-- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index c95f450eebc..847ebcd9d93 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -70,8 +70,7 @@ pub mod trapframe { // timer::Timer, // uart::Uart, // }; - -pub use self::{gpio::*, uart::Uart, timer::Timer, delay::Delay, interrupt::*, spi::Spi,}; +pub use self::{delay::Delay, gpio::*, interrupt::*, spi::Spi, timer::Timer, uart::Uart}; // pub mod analog; pub mod clock; @@ -269,4 +268,4 @@ mod critical_section_impl { } } } -} \ No newline at end of file +} diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index ebfd046841d..2fec965f82d 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -3,8 +3,26 @@ use core::arch::{asm, global_asm}; pub use embedded_hal as ehal; -pub use esp_hal_common::{macros, peripherals, clock, gpio, prelude, uart, Uart, timer, Cpu, Delay, interrupt, i2c, ledc, -systimer, dma, dma::gdma, spi, i2s, }; +pub use esp_hal_common::{ + clock, + dma, + dma::gdma, + gpio, + i2c, + i2s, + interrupt, + ledc, + macros, + peripherals, + prelude, + spi, + systimer, + timer, + uart, + Cpu, + Delay, + Uart, +}; pub use self::gpio::IO; From 51cb4c02ccbdb1b257e13400a7d194850345292e Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Wed, 25 Jan 2023 11:13:06 +0100 Subject: [PATCH 16/64] C6 Interrupts --- esp-hal-common/src/interrupt/riscv.rs | 51 +++++++++++++--- esp32c6-hal/.cargo/config.toml | 2 +- esp32c6-hal/examples/gpio_interrupt.rs | 82 ++++++++++++++++++++++++++ esp32c6-hal/src/lib.rs | 8 +-- 4 files changed, 130 insertions(+), 13 deletions(-) create mode 100644 esp32c6-hal/examples/gpio_interrupt.rs diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index 43153429b1d..debc9cfff25 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -73,8 +73,6 @@ pub enum InterruptKind { #[repr(u32)] #[derive(Debug, Copy, Clone)] pub enum CpuInterrupt { - #[cfg(feature = "esp32c6")] - Interrupt0 = 0, Interrupt1 = 1, Interrupt2, Interrupt3, @@ -157,7 +155,13 @@ pub unsafe fn map(_core: Cpu, interrupt: Interrupt, which: CpuInterrupt) { } /// Enable a CPU interrupt +#[cfg(not(any(esp32c6)))] pub unsafe fn enable_cpu_interrupt(which: CpuInterrupt) { + let cpu_interrupt_number = which as isize; + let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; + intr.cpu_int_enable + .modify(|r, w| w.bits((1 << cpu_interrupt_number) | r.bits())); + let cpu_interrupt_number = which as isize; #[cfg(not(feature = "esp32c6"))] let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; @@ -167,6 +171,18 @@ pub unsafe fn enable_cpu_interrupt(which: CpuInterrupt) { .modify(|r, w| w.bits((1 << cpu_interrupt_number) | r.bits())); } +/// Enable a CPU interrupt +#[cfg(esp32c6)] +pub unsafe fn enable_cpu_interrupt(which: CpuInterrupt) { + let cpu_interrupt_number = which as isize; + const DR_REG_PLIC_MX_BASE: u32 = 0x20001000; + const PLIC_MXINT_ENABLE_REG: u32 = DR_REG_PLIC_MX_BASE + 0x0; + let mxint_enable = PLIC_MXINT_ENABLE_REG as *mut u32; + unsafe { + mxint_enable.write_volatile(mxint_enable.read_volatile() | 1 << cpu_interrupt_number); + } +} + /// Disable the given peripheral interrupt. pub fn disable(_core: Cpu, interrupt: Interrupt) { unsafe { @@ -261,10 +277,18 @@ mod vectored { use super::*; + #[cfg(not(any(esp32c6)))] + const PRIORITY_TO_INTERRUPT: [usize; 15] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + + // don't use interrupts reserved for CLIC (0,3,5,7) + #[cfg(any(esp32c6))] + const PRIORITY_TO_INTERRUPT: [usize; 15] = + [1, 2, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]; + // Setup interrupts 1-15 ready for vectoring #[doc(hidden)] pub(crate) unsafe fn init_vectoring() { - for i in 1..=15 { + for i in PRIORITY_TO_INTERRUPT { set_kind( crate::get_core(), core::mem::transmute(i), @@ -284,13 +308,15 @@ mod vectored { fn get_configured_interrupts(_core: Cpu, mut status: u128) -> [u128; 16] { unsafe { let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; - #[cfg(not(feature = "esp32c6"))] + + #[cfg(not(esp32c6))] let intr_map_base = intr.mac_intr_map.as_ptr(); - #[cfg(feature = "esp32c6")] + #[cfg(esp32c6)] let intr_map_base = intr.wifi_mac_intr_map.as_ptr(); - #[cfg(feature = "esp32c6")] + #[cfg(esp32c6)] let intr = &*crate::peripherals::INTPRI::PTR; + let intr_prio_base = intr.cpu_int_pri_0.as_ptr(); let mut prios = [0u128; 16]; @@ -328,7 +354,8 @@ mod vectored { return Err(Error::InvalidInterruptPriority); } unsafe { - let cpu_interrupt = core::mem::transmute(level as u8 as u32); + let cpu_interrupt = + core::mem::transmute(PRIORITY_TO_INTERRUPT[(level as usize) - 1] as u32); map(crate::get_core(), interrupt, cpu_interrupt); enable_cpu_interrupt(cpu_interrupt); } @@ -611,4 +638,14 @@ pub fn _setup_interrupts() { #[cfg(feature = "vectored")] crate::interrupt::init_vectoring(); }; + + #[cfg(esp32c6)] + write_mie(u32::MAX); +} + +#[cfg(esp32c6)] +fn write_mie(val: u32) { + unsafe { + core::arch::asm!("csrw mie, {0}", in(reg) val); + } } diff --git a/esp32c6-hal/.cargo/config.toml b/esp32c6-hal/.cargo/config.toml index 1528b5124bf..09b3d4e3a48 100644 --- a/esp32c6-hal/.cargo/config.toml +++ b/esp32c6-hal/.cargo/config.toml @@ -1,5 +1,5 @@ [target.riscv32imc-unknown-none-elf] -runner = "espflash --monitor" +runner = "espflash flash --monitor" rustflags = [ "-C", "link-arg=-Tlinkall.x", "-C", "force-frame-pointers", diff --git a/esp32c6-hal/examples/gpio_interrupt.rs b/esp32c6-hal/examples/gpio_interrupt.rs new file mode 100644 index 00000000000..6282b3f03e8 --- /dev/null +++ b/esp32c6-hal/examples/gpio_interrupt.rs @@ -0,0 +1,82 @@ +//! GPIO interrupt +//! +//! This prints "Interrupt" when the boot button is pressed. +//! It also blinks an LED like the blinky example. + +#![no_std] +#![no_main] + +use core::{arch::asm, cell::RefCell}; + +use critical_section::Mutex; +use esp32c6_hal::{ + clock::ClockControl, + gpio::{Event, Gpio9, Input, PullDown, IO}, + interrupt, + peripherals::{self, Peripherals}, + prelude::*, + systimer::SystemTimer, + // Rtc, + timer::TimerGroup, + Delay, +}; +use esp_backtrace as _; +use esp_println::println; +use riscv_rt::entry; + +static BUTTON: Mutex>>>> = Mutex::new(RefCell::new(None)); + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C3, this includes the Super WDT, + // the RTC WDT, and the TIMG WDTs. + // let mut rtc = Rtc::new(peripherals.RTC_CNTL); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let mut wdt1 = timer_group1.wdt; + + // rtc.swd.disable(); + // rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); + + // Set GPIO5 as an output + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let mut led = io.pins.gpio5.into_push_pull_output(); + + // Set GPIO9 as an input + let mut button = io.pins.gpio9.into_pull_down_input(); + button.listen(Event::FallingEdge); + + critical_section::with(|cs| BUTTON.borrow_ref_mut(cs).replace(button)); + + interrupt::enable(peripherals::Interrupt::GPIO, interrupt::Priority::Priority3).unwrap(); + + unsafe { + riscv::interrupt::enable(); + } + + let mut delay = Delay::new(&clocks); + loop { + led.toggle().unwrap(); + delay.delay_ms(500u32); + } +} + +#[interrupt] +fn GPIO() { + critical_section::with(|cs| { + esp_println::println!("Interrupt"); + + BUTTON + .borrow_ref_mut(cs) + .as_mut() + .unwrap() + .clear_interrupt(); + }); +} diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index 2fec965f82d..6032c4701ca 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -9,7 +9,6 @@ pub use esp_hal_common::{ dma::gdma, gpio, i2c, - i2s, interrupt, ledc, macros, @@ -131,7 +130,7 @@ _start_trap_hal: sw s0, 30*4(sp) add a0, sp, zero - // jal ra, _start_trap_rust_hal + jal ra, _start_trap_rust_hal lw t1, 31*4(sp) csrrw x0, mepc, t1 @@ -184,9 +183,8 @@ unsafe fn start_hal() -> ! { r#" .option norelax - // unsupported on ESP32-C6 - // csrw mie, 0 - // csrw mip, 0 + csrw mie, 0 + csrw mip, 0 li x1, 0 li x2, 0 From 753414a5b7582281ae0666fc70902a3831a45f80 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Fri, 27 Jan 2023 15:19:36 +0100 Subject: [PATCH 17/64] C6: Update build.rs, linker scripts and initial examples --- esp32c6-hal/build.rs | 5 +++++ esp32c6-hal/examples/gpio_interrupt.rs | 6 +++--- esp32c6-hal/examples/hello_world.rs | 2 +- esp32c6-hal/ld/bl-linkall.x | 1 + esp32c6-hal/ld/db-linkall.x | 1 + esp32c6-hal/ld/rom-functions.x | 1 + esp32c6-hal/src/lib.rs | 3 +++ 7 files changed, 15 insertions(+), 4 deletions(-) diff --git a/esp32c6-hal/build.rs b/esp32c6-hal/build.rs index 940c2dec7c1..11f038a0be0 100644 --- a/esp32c6-hal/build.rs +++ b/esp32c6-hal/build.rs @@ -70,5 +70,10 @@ fn add_defaults() { .write_all(include_bytes!("ld/hal-defaults.x")) .unwrap(); + File::create(out.join("rom-functions.x")) + .unwrap() + .write_all(include_bytes!("ld/rom-functions.x")) + .unwrap(); + println!("cargo:rustc-link-search={}", out.display()); } diff --git a/esp32c6-hal/examples/gpio_interrupt.rs b/esp32c6-hal/examples/gpio_interrupt.rs index 6282b3f03e8..bd29d452255 100644 --- a/esp32c6-hal/examples/gpio_interrupt.rs +++ b/esp32c6-hal/examples/gpio_interrupt.rs @@ -11,7 +11,7 @@ use core::{arch::asm, cell::RefCell}; use critical_section::Mutex; use esp32c6_hal::{ clock::ClockControl, - gpio::{Event, Gpio9, Input, PullDown, IO}, + gpio::{Event, Gpio7, Input, PullDown, IO}, interrupt, peripherals::{self, Peripherals}, prelude::*, @@ -24,7 +24,7 @@ use esp_backtrace as _; use esp_println::println; use riscv_rt::entry; -static BUTTON: Mutex>>>> = Mutex::new(RefCell::new(None)); +static BUTTON: Mutex>>>> = Mutex::new(RefCell::new(None)); #[entry] fn main() -> ! { @@ -50,7 +50,7 @@ fn main() -> ! { let mut led = io.pins.gpio5.into_push_pull_output(); // Set GPIO9 as an input - let mut button = io.pins.gpio9.into_pull_down_input(); + let mut button = io.pins.gpio7.into_pull_down_input(); button.listen(Event::FallingEdge); critical_section::with(|cs| BUTTON.borrow_ref_mut(cs).replace(button)); diff --git a/esp32c6-hal/examples/hello_world.rs b/esp32c6-hal/examples/hello_world.rs index 83112037704..3409f2646f0 100644 --- a/esp32c6-hal/examples/hello_world.rs +++ b/esp32c6-hal/examples/hello_world.rs @@ -39,7 +39,7 @@ fn main() -> ! { // let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); let clocks = ClockControl::configure( system.clock_control, - CpuClock::Clock80MHz, + CpuClock::Clock160MHz, ) .freeze(); diff --git a/esp32c6-hal/ld/bl-linkall.x b/esp32c6-hal/ld/bl-linkall.x index 9fbe9cd3584..e604dc6f8f8 100644 --- a/esp32c6-hal/ld/bl-linkall.x +++ b/esp32c6-hal/ld/bl-linkall.x @@ -1,3 +1,4 @@ INCLUDE "memory.x" INCLUDE "bl-riscv-link.x" INCLUDE "hal-defaults.x" +INCLUDE "rom-functions.x" diff --git a/esp32c6-hal/ld/db-linkall.x b/esp32c6-hal/ld/db-linkall.x index 6e994af0107..99a75142965 100644 --- a/esp32c6-hal/ld/db-linkall.x +++ b/esp32c6-hal/ld/db-linkall.x @@ -1,2 +1,3 @@ INCLUDE "esp32c6-link.x" INCLUDE "hal-defaults.x" +INCLUDE "rom-functions.x" diff --git a/esp32c6-hal/ld/rom-functions.x b/esp32c6-hal/ld/rom-functions.x index b3afc9d2bfa..12aeb3dab2a 100644 --- a/esp32c6-hal/ld/rom-functions.x +++ b/esp32c6-hal/ld/rom-functions.x @@ -1,4 +1,5 @@ ets_printf = 0x40000028; +ets_update_cpu_frequency = ets_update_cpu_frequency_rom; PROVIDE(esp_rom_printf = ets_printf); PROVIDE(cache_invalidate_icache_all = 0x4000064c); PROVIDE(cache_suspend_icache = 0x40000698); diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index 6032c4701ca..f81d08d06ff 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -14,12 +14,15 @@ pub use esp_hal_common::{ macros, peripherals, prelude, + pulse_control, spi, systimer, timer, uart, Cpu, Delay, + PulseControl, + utils, Uart, }; From dece8b4be5bf964f5a2921a8d3c6d874e99d5eb0 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Fri, 27 Jan 2023 15:20:20 +0100 Subject: [PATCH 18/64] C6: RMT --- esp-hal-common/src/gpio/esp32c6.rs | 8 ++-- esp-hal-common/src/lib.rs | 12 ++--- esp-hal-common/src/prelude.rs | 46 +++++++++---------- esp-hal-common/src/pulse_control.rs | 41 +++++++++-------- .../src/utils/smart_leds_adapter.rs | 4 +- 5 files changed, 59 insertions(+), 52 deletions(-) diff --git a/esp-hal-common/src/gpio/esp32c6.rs b/esp-hal-common/src/gpio/esp32c6.rs index e5b38e6f985..09bccfac6ec 100644 --- a/esp-hal-common/src/gpio/esp32c6.rs +++ b/esp-hal-common/src/gpio/esp32c6.rs @@ -85,8 +85,8 @@ pub enum InputSignal { FSPICS0 = 68, PARL_RX_CLK = 69, PARL_TX_CLK = 70, - RMT_SIG_IN0 = 71, - MODEM_DIAG1 = 72, + RMT_SIG_0 = 71, + RMT_SIG_1 = 72, TWAI0_RX = 73, TWAI1_RX = 77, PWM0_SYNC0 = 87, @@ -186,8 +186,8 @@ pub enum OutputSignal { FSPICS0 = 68, SDIO_TOHOST_INT = 69, PARL_TX_CLK = 70, - RMT_SIG_OUT0 = 71, - RMT_SIG_OUT1 = 72, + RMT_SIG_0 = 71, + RMT_SIG_1 = 72, TWAI0_TX = 73, TWAI0_BUS_OFF_ON = 74, TWAI0_CLKOUT = 75, diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index 847ebcd9d93..eb8d980b3eb 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -56,8 +56,8 @@ pub mod trapframe { pub use xtensa_lx_rt::exception::Context as TrapFrame; } -// #[cfg(rmt)] -// pub use self::pulse_control::PulseControl; +#[cfg(rmt)] +pub use self::pulse_control::PulseControl; // #[cfg(usb_serial_jtag)] // pub use self::usb_serial_jtag::UsbSerialJtag; // pub use self::{ @@ -91,8 +91,8 @@ pub mod otg_fs; pub mod pcnt; pub mod peripheral; pub mod prelude; -// #[cfg(rmt)] -// pub mod pulse_control; +#[cfg(rmt)] +pub mod pulse_control; #[cfg(radio)] pub mod radio; pub mod rng; @@ -108,8 +108,8 @@ pub mod timer; pub mod uart; #[cfg(usb_serial_jtag)] pub mod usb_serial_jtag; -// #[cfg(rmt)] -// pub mod utils; +#[cfg(rmt)] +pub mod utils; #[cfg_attr(esp32, path = "cpu_control/esp32.rs")] #[cfg_attr(esp32s3, path = "cpu_control/esp32s3.rs")] diff --git a/esp-hal-common/src/prelude.rs b/esp-hal-common/src/prelude.rs index 01a025ca57c..30bb17b2418 100644 --- a/esp-hal-common/src/prelude.rs +++ b/esp-hal-common/src/prelude.rs @@ -20,15 +20,15 @@ pub use fugit::{ }; pub use nb; -#[cfg(any(esp32c2, esp32c3))] -pub use crate::analog::SarAdcExt as _esp_hal_analog_SarAdcExt; -#[cfg(any(esp32, esp32s2, esp32s3))] -pub use crate::analog::SensExt as _esp_hal_analog_SensExt; -//#[cfg(rmt)] -//pub use crate::pulse_control::{ -// ConfiguredChannel as _esp_hal_pulse_control_ConfiguredChannel, -// OutputChannel as _esp_hal_pulse_control_OutputChannel, -//}; +// #[cfg(any(esp32c2, esp32c3))] +// pub use crate::analog::SarAdcExt as _esp_hal_analog_SarAdcExt; +// #[cfg(any(esp32, esp32s2, esp32s3))] +// pub use crate::analog::SensExt as _esp_hal_analog_SensExt; +// #[cfg(rmt)] +// pub use crate::pulse_control::{ +// ConfiguredChannel as _esp_hal_pulse_control_ConfiguredChannel, +// OutputChannel as _esp_hal_pulse_control_OutputChannel, +// }; #[cfg(radio)] pub use crate::radio::RadioExt as _esp_hal_RadioExt; #[cfg(any(esp32, esp32s2))] @@ -36,8 +36,8 @@ pub use crate::spi::dma::WithDmaSpi3 as _esp_hal_spi_dma_WithDmaSpi3; pub use crate::{ clock::Clock as _esp_hal_clock_Clock, dma::{ - DmaTransfer as _esp_hal_dma_DmaTransfer, - DmaTransferRxTx as _esp_hal_dma_DmaTransferRxTx, + DmaTransfer as _esp_hal_dma_DmaTransfer, + DmaTransferRxTx as _esp_hal_dma_DmaTransferRxTx, }, entry, gpio::{ @@ -45,20 +45,20 @@ pub use crate::{ OutputPin as _esp_hal_gpio_OutputPin, Pin as _esp_hal_gpio_Pin, }, - // i2c::Instance as _esp_hal_i2c_Instance, - // ledc::{ - // channel::{ - // ChannelHW as _esp_hal_ledc_channel_ChannelHW, - // ChannelIFace as _esp_hal_ledc_channel_ChannelIFace, - // }, - // timer::{ - // TimerHW as _esp_hal_ledc_timer_TimerHW, - // TimerIFace as _esp_hal_ledc_timer_TimerIFace, - // }, - // }, + i2c::Instance as _esp_hal_i2c_Instance, + ledc::{ + channel::{ + ChannelHW as _esp_hal_ledc_channel_ChannelHW, + ChannelIFace as _esp_hal_ledc_channel_ChannelIFace, + }, + timer::{ + TimerHW as _esp_hal_ledc_timer_TimerHW, + TimerIFace as _esp_hal_ledc_timer_TimerIFace, + }, + }, macros::*, spi::{ - dma::WithDmaSpi2 as _esp_hal_spi_dma_WithDmaSpi2, + dma::WithDmaSpi2 as _esp_hal_spi_dma_WithDmaSpi2, Instance as _esp_hal_spi_Instance, InstanceDma as _esp_hal_spi_InstanceDma, }, diff --git a/esp-hal-common/src/pulse_control.rs b/esp-hal-common/src/pulse_control.rs index 80a6740e5c2..fb6c66a6274 100644 --- a/esp-hal-common/src/pulse_control.rs +++ b/esp-hal-common/src/pulse_control.rs @@ -21,6 +21,9 @@ //! * The **ESP32-C3** has 4 channels, `Channel0` and `Channel1` hardcoded for //! transmitting signals and `Channel2` and `Channel3` hardcoded for receiving //! signals. +//! * The **ESP32-C6** has 4 channels, `Channel0` and `Channel1` hardcoded for +//! transmitting signals and `Channel2` and `Channel3` hardcoded for receiving +//! signals. //! * The **ESP32-S2** has 4 channels, each of them can be either receiver or //! transmitter. //! * The **ESP32-S3** has 8 channels, `Channel0`-`Channel3` hardcdoded for @@ -124,7 +127,7 @@ pub enum RepeatMode { } /// Specify the clock source for the RMT peripheral -#[cfg(any(esp32c3, esp32s3))] +#[cfg(any(esp32c3, esp32c6, esp32s3))] #[derive(Debug, Copy, Clone)] pub enum ClockSource { /// Application-level clock @@ -150,7 +153,7 @@ pub enum ClockSource { // to the RMT channel #[cfg(any(esp32s2, esp32))] const CHANNEL_RAM_SIZE: u8 = 64; -#[cfg(any(esp32c3, esp32s3))] +#[cfg(any(esp32c3, esp32c6, esp32s3))] const CHANNEL_RAM_SIZE: u8 = 48; // Specifies where the RMT RAM section starts for the particular ESP32 variant @@ -158,6 +161,8 @@ const CHANNEL_RAM_SIZE: u8 = 48; const RMT_RAM_START: usize = 0x3f416400; #[cfg(esp32c3)] const RMT_RAM_START: usize = 0x60016400; +#[cfg(esp32c6)] +const RMT_RAM_START: usize = 0x60006400; #[cfg(esp32)] const RMT_RAM_START: usize = 0x3ff56800; #[cfg(esp32s3)] @@ -283,7 +288,7 @@ macro_rules! channel_instance { let mut channel = $cxi { mem_offset: 0 }; cfg_if::cfg_if! { - if #[cfg(any(esp32c3, esp32s3))] { + if #[cfg(any(esp32c3, esp32c6, esp32s3))] { // Apply default configuration unsafe { &*RMT::PTR }.ch_tx_conf0[$num].modify(|_, w| unsafe { // Configure memory block size @@ -459,7 +464,7 @@ macro_rules! channel_instance { } } - #[cfg(any(esp32c3, esp32s3))] + #[cfg(any(esp32c3, esp32c6, esp32s3))] conf_reg.modify(|_, w| { // Set config update bit w.conf_update().set_bit() @@ -540,14 +545,14 @@ macro_rules! channel_instance { } // always enable tx wrap - #[cfg(any(esp32c3, esp32s3))] + #[cfg(any(esp32c3, esp32c6, esp32s3))] unsafe { &*RMT::PTR }.ch_tx_conf0[$num].modify(|_, w| { w.mem_tx_wrap_en() .set_bit() }); // apply configuration updates - #[cfg(any(esp32c3, esp32s3))] + #[cfg(any(esp32c3, esp32c6, esp32s3))] unsafe { &*RMT::PTR }.ch_tx_conf0[$num].modify(|_, w| { w.conf_update() .set_bit() @@ -577,9 +582,9 @@ macro_rules! channel_instance { #[cfg(esp32)] false, // The C3/S3 have a slightly different interrupt naming scheme - #[cfg(any(esp32, feature= "esp32s2"))] + #[cfg(any(esp32, esp32s2))] unsafe { interrupts.ch_err_int_raw($num).bit() }, - #[cfg(any(esp32c3, feature= "esp32s3"))] + #[cfg(any(esp32c3, esp32c6, esp32s3))] unsafe { interrupts.ch_tx_err_int_raw($num).bit() }, unsafe { interrupts.ch_tx_thr_event_int_raw($num).bit() }, ) { @@ -612,9 +617,9 @@ macro_rules! channel_instance { #[cfg(esp32)] false, // The C3/S3 have a slightly different interrupt naming scheme - #[cfg(any(esp32, feature= "esp32s2"))] + #[cfg(any(esp32, esp32s2))] unsafe { interrupts.ch_err_int_raw($num).bit() }, - #[cfg(any(esp32c3, feature= "esp32s3"))] + #[cfg(any(esp32c3, esp32c6, esp32s3))] unsafe { interrupts.ch_tx_err_int_raw($num).bit() }, unsafe { interrupts.ch_tx_thr_event_int_raw($num).bit() }, )) @@ -632,7 +637,7 @@ macro_rules! channel_instance { /// previously a sequence was sent with `RepeatMode::Forever`. fn stop_transmission(&self) { cfg_if::cfg_if! { - if #[cfg(any(esp32c3, esp32s3))] { + if #[cfg(any(esp32c3, esp32c6, esp32s3))] { unsafe { &*RMT::PTR } .ch_tx_conf0[$num] .modify(|_, w| w.tx_stop().set_bit()); @@ -666,7 +671,7 @@ macro_rules! output_channel { #[inline(always)] fn set_idle_output_level(&mut self, level: bool) -> &mut Self { cfg_if::cfg_if! { - if #[cfg(any(esp32c3, esp32s3))] { + if #[cfg(any(esp32c3, esp32c6, esp32s3))] { unsafe { &*RMT::PTR } .ch_tx_conf0[$num] .modify(|_, w| w.idle_out_lv().bit(level)); @@ -683,7 +688,7 @@ macro_rules! output_channel { #[inline(always)] fn set_idle_output(&mut self, state: bool) -> &mut Self { cfg_if::cfg_if! { - if #[cfg(any(esp32c3, esp32s3))] { + if #[cfg(any(esp32c3, esp32c6, esp32s3))] { unsafe { &*RMT::PTR } .ch_tx_conf0[$num] .modify(|_, w| w.idle_out_en().bit(state)); @@ -700,7 +705,7 @@ macro_rules! output_channel { #[inline(always)] fn set_channel_divider(&mut self, divider: u8) -> &mut Self { cfg_if::cfg_if! { - if #[cfg(any(esp32c3, esp32s3))] { + if #[cfg(any(esp32c3, esp32c6, esp32s3))] { unsafe { &*RMT::PTR } .ch_tx_conf0[$num] .modify(|_, w| unsafe { w.div_cnt().bits(divider) }); @@ -717,7 +722,7 @@ macro_rules! output_channel { #[inline(always)] fn set_carrier_modulation(&mut self, state: bool) -> &mut Self { cfg_if::cfg_if! { - if #[cfg(any(esp32c3, esp32s3))] { + if #[cfg(any(esp32c3, esp32c6, esp32s3))] { unsafe { &*RMT::PTR } .ch_tx_conf0[$num] .modify(|_, w| w.carrier_en().bit(state)); @@ -845,7 +850,7 @@ macro_rules! rmt { impl<'d> PulseControl<'d> { /// Create a new pulse controller instance - #[cfg(any(esp32c3, esp32s3))] + #[cfg(any(esp32c3, esp32c6, esp32s3))] pub fn new( instance: impl Peripheral

+ 'd, peripheral_clock_control: &mut PeripheralClockControl, @@ -902,7 +907,7 @@ macro_rules! rmt { /// clock is calculated as follows: /// /// divider = absolute_part + 1 + (fractional_part_a / fractional_part_b) - #[cfg(any(esp32c3, esp32s3))] + #[cfg(any(esp32c3, esp32c6, esp32s3))] fn config_global( &self, clk_source: ClockSource, @@ -1018,7 +1023,7 @@ macro_rules! rmt { }; } -#[cfg(esp32c3)] +#[cfg(any(esp32c3, esp32c6))] rmt!( sys_conf, (0, Channel0, channel0, OutputSignal::RMT_SIG_0), diff --git a/esp-hal-common/src/utils/smart_leds_adapter.rs b/esp-hal-common/src/utils/smart_leds_adapter.rs index ebed154615a..4c7cd468acb 100644 --- a/esp-hal-common/src/utils/smart_leds_adapter.rs +++ b/esp-hal-common/src/utils/smart_leds_adapter.rs @@ -31,6 +31,8 @@ use crate::{ // #44 have been addressed. #[cfg(esp32c3)] const SOURCE_CLK_FREQ: u32 = 40_000_000; +#[cfg(esp32c6)] +const SOURCE_CLK_FREQ: u32 = 40_000_000; #[cfg(esp32s2)] const SOURCE_CLK_FREQ: u32 = 40_000_000; #[cfg(esp32)] @@ -99,7 +101,7 @@ where where UnconfiguredChannel: OutputChannel = CHANNEL>, { - #[cfg(any(esp32c3, esp32s3))] + #[cfg(any(esp32c3, esp32c6, esp32s3))] channel .set_idle_output_level(false) .set_carrier_modulation(false) From 3ad20aa60712db848ef4d00925aa38079395de9d Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Thu, 26 Jan 2023 10:00:35 +0100 Subject: [PATCH 19/64] Fix interrupt handling --- esp-hal-common/build.rs | 16 +- esp-hal-common/src/interrupt/riscv.rs | 350 +++++++++++++++++--------- 2 files changed, 231 insertions(+), 135 deletions(-) diff --git a/esp-hal-common/build.rs b/esp-hal-common/build.rs index 19b58f6f607..07d612bf599 100644 --- a/esp-hal-common/build.rs +++ b/esp-hal-common/build.rs @@ -47,6 +47,7 @@ fn main() { // - 'usb_otg' // - 'usb_serial_jtag' // - 'aes' + // - 'plic' // - 'radio' // // New symbols can be added as needed, but please be sure to update both this @@ -108,20 +109,7 @@ fn main() { "systimer", "timg1", "usb_serial_jtag", - ] - } else if esp32c6 { - vec![ - "esp32c6", - "riscv", - "single_core", - "dac", - "gdma", - "i2s", - "mcpwm", - "rmt", - "systimer", - "timg1", - "usb_serial_jtag", + "plic", ] } else if esp32s2 { vec![ diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index debc9cfff25..7d162ce01a7 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -3,6 +3,8 @@ //! When the `vectored` feature is enabled, CPU interrupts 1 through 15 are //! reserved for each of the possible interrupt priorities. //! +//! On chips with a PLIC CPU interrupts 1,2,5,6,9 .. 19 are used. +//! //! ```rust //! interrupt1() => Priority::Priority1 //! interrupt2() => Priority::Priority2 @@ -10,8 +12,7 @@ //! interrupt15() => Priority::Priority15 //! ``` -use esp_riscv_rt::riscv::register::{mcause, mepc, mtvec}; -pub use esp_riscv_rt::TrapFrame; +use riscv::register::mcause; use crate::{ peripherals::{self, Interrupt}, @@ -22,13 +23,9 @@ use crate::{ // general. However this makes things like preemtive multitasking easier in // future extern "C" { - #[cfg(feature = "esp32c6")] - fn interrupt0(frame: &mut TrapFrame); fn interrupt1(frame: &mut TrapFrame); fn interrupt2(frame: &mut TrapFrame); - #[cfg(not(feature = "esp32c6"))] fn interrupt3(frame: &mut TrapFrame); - #[cfg(not(feature = "esp32c6"))] fn interrupt4(frame: &mut TrapFrame); fn interrupt5(frame: &mut TrapFrame); fn interrupt6(frame: &mut TrapFrame); @@ -145,9 +142,9 @@ pub unsafe fn map(_core: Cpu, interrupt: Interrupt, which: CpuInterrupt) { let interrupt_number = interrupt as isize; let cpu_interrupt_number = which as isize; let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; - #[cfg(not(feature = "esp32c6"))] + #[cfg(not(esp32c6))] let intr_map_base = intr.mac_intr_map.as_ptr(); - #[cfg(feature = "esp32c6")] + #[cfg(esp32c6)] let intr_map_base = intr.wifi_mac_intr_map.as_ptr(); intr_map_base .offset(interrupt_number) @@ -161,14 +158,6 @@ pub unsafe fn enable_cpu_interrupt(which: CpuInterrupt) { let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; intr.cpu_int_enable .modify(|r, w| w.bits((1 << cpu_interrupt_number) | r.bits())); - - let cpu_interrupt_number = which as isize; - #[cfg(not(feature = "esp32c6"))] - let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; - #[cfg(feature = "esp32c6")] - let intr = &*crate::peripherals::INTPRI::PTR; - intr.cpu_int_enable - .modify(|r, w| w.bits((1 << cpu_interrupt_number) | r.bits())); } /// Enable a CPU interrupt @@ -188,9 +177,9 @@ pub fn disable(_core: Cpu, interrupt: Interrupt) { unsafe { let interrupt_number = interrupt as isize; let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; - #[cfg(not(feature = "esp32c6"))] + #[cfg(not(esp32c6))] let intr_map_base = intr.mac_intr_map.as_ptr(); - #[cfg(feature = "esp32c6")] + #[cfg(esp32c6)] let intr_map_base = intr.wifi_mac_intr_map.as_ptr(); intr_map_base.offset(interrupt_number).write_volatile(0); } @@ -202,9 +191,9 @@ pub fn disable(_core: Cpu, interrupt: Interrupt) { /// interrupt handler will take care of clearing edge interrupt bits. pub fn set_kind(_core: Cpu, which: CpuInterrupt, kind: InterruptKind) { unsafe { - #[cfg(not(feature = "esp32c6"))] + #[cfg(not(esp32c6))] let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; - #[cfg(feature = "esp32c6")] + #[cfg(esp32c6)] let intr = &*crate::peripherals::INTPRI::PTR; let cpu_interrupt_number = which as isize; @@ -225,16 +214,32 @@ pub fn set_kind(_core: Cpu, which: CpuInterrupt, kind: InterruptKind) { /// Great care must be taken when using the `vectored` feature (enabled by /// default). Avoid changing the priority of interrupts 1 - 15 when interrupt /// vectoring is enabled. +#[cfg(not(plic))] pub unsafe fn set_priority(_core: Cpu, which: CpuInterrupt, priority: Priority) { - #[cfg(not(feature = "esp32c6"))] let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; - #[cfg(feature = "esp32c6")] - let intr = &*crate::peripherals::INTPRI::PTR; let cpu_interrupt_number = which as isize; let intr_prio_base = intr.cpu_int_pri_0.as_ptr(); intr_prio_base - .offset(cpu_interrupt_number as isize) + .offset(cpu_interrupt_number) + .write_volatile(priority as u32); +} + +/// Set the priority level of an CPU interrupt +/// +/// Great care must be taken when using the `vectored` feature (enabled by +/// default). Avoid changing the priority of interrupts 1 - 15 when interrupt +/// vectoring is enabled. +#[cfg(plic)] +pub unsafe fn set_priority(_core: Cpu, which: CpuInterrupt, priority: Priority) { + const DR_REG_PLIC_MX_BASE: u32 = 0x20001000; + const PLIC_MXINT0_PRI_REG: u32 = DR_REG_PLIC_MX_BASE + 0x10; + + let plic_mxint_pri_ptr = PLIC_MXINT0_PRI_REG as *mut u32; + + let cpu_interrupt_number = which as isize; + plic_mxint_pri_ptr + .offset(cpu_interrupt_number) .write_volatile(priority as u32); } @@ -243,9 +248,9 @@ pub unsafe fn set_priority(_core: Cpu, which: CpuInterrupt, priority: Priority) pub fn clear(_core: Cpu, which: CpuInterrupt) { unsafe { let cpu_interrupt_number = which as isize; - #[cfg(not(feature = "esp32c6"))] + #[cfg(not(esp32c6))] let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; - #[cfg(feature = "esp32c6")] + #[cfg(esp32c6)] let intr = &*crate::peripherals::INTPRI::PTR; intr.cpu_int_clear .write(|w| w.bits(1 << cpu_interrupt_number)); @@ -277,29 +282,39 @@ mod vectored { use super::*; - #[cfg(not(any(esp32c6)))] + #[cfg(not(plic))] const PRIORITY_TO_INTERRUPT: [usize; 15] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; - // don't use interrupts reserved for CLIC (0,3,5,7) - #[cfg(any(esp32c6))] + #[cfg(not(plic))] + const INTERRUPT_TO_PRIORITY: [usize; 15] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + + // don't use interrupts reserved for CLIC (0,3,4,7) + // for some reason also CPU interrupt 8 doesn't work as expected - so don't use + // that, too + #[cfg(plic)] const PRIORITY_TO_INTERRUPT: [usize; 15] = - [1, 2, 5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]; + [1, 2, 5, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]; - // Setup interrupts 1-15 ready for vectoring + #[cfg(plic)] + const INTERRUPT_TO_PRIORITY: [usize; 19] = [ + 1, 2, 0, 0, 3, 4, 0, 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + ]; + + // Setup interrupts ready for vectoring #[doc(hidden)] pub(crate) unsafe fn init_vectoring() { - for i in PRIORITY_TO_INTERRUPT { + for (prio, num) in PRIORITY_TO_INTERRUPT.iter().enumerate() { set_kind( crate::get_core(), - core::mem::transmute(i), + core::mem::transmute(*num), InterruptKind::Level, ); set_priority( crate::get_core(), - core::mem::transmute(i), - core::mem::transmute(i as u8), + core::mem::transmute(*num), + core::mem::transmute((prio as u8) + 1), ); - enable_cpu_interrupt(core::mem::transmute(i)); + enable_cpu_interrupt(core::mem::transmute(*num)); } } @@ -314,11 +329,6 @@ mod vectored { #[cfg(esp32c6)] let intr_map_base = intr.wifi_mac_intr_map.as_ptr(); - #[cfg(esp32c6)] - let intr = &*crate::peripherals::INTPRI::PTR; - - let intr_prio_base = intr.cpu_int_pri_0.as_ptr(); - let mut prios = [0u128; 16]; while status != 0 { @@ -327,9 +337,7 @@ mod vectored { let cpu_interrupt = intr_map_base.offset(i).read_volatile(); // safety: cast is safe because of repr(u32) let cpu_interrupt: CpuInterrupt = core::mem::transmute(cpu_interrupt); - let prio = intr_prio_base - .offset(cpu_interrupt as isize) - .read_volatile(); + let prio = get_priority(cpu_interrupt); prios[prio as usize] |= 1 << i; status &= !(1u128 << interrupt_nr); @@ -339,6 +347,35 @@ mod vectored { } } + /// Get interrupt priority + #[cfg(not(plic))] + #[inline] + unsafe fn get_priority(cpu_interrupt: CpuInterrupt) -> Priority { + let intr = &*crate::peripherals::INTERRUPT_CORE0::PTR; + let intr_prio_base = intr.cpu_int_pri_0.as_ptr(); + + let prio = intr_prio_base + .offset(cpu_interrupt as isize) + .read_volatile(); + core::mem::transmute(prio as u8) + } + + /// Get interrupt priority + #[cfg(plic)] + #[inline] + unsafe fn get_priority(cpu_interrupt: CpuInterrupt) -> Priority { + const DR_REG_PLIC_MX_BASE: u32 = 0x20001000; + const PLIC_MXINT0_PRI_REG: u32 = DR_REG_PLIC_MX_BASE + 0x10; + + let plic_mxint_pri_ptr = PLIC_MXINT0_PRI_REG as *mut u32; + + let cpu_interrupt_number = cpu_interrupt as isize; + let prio = plic_mxint_pri_ptr + .offset(cpu_interrupt_number) + .read_volatile(); + core::mem::transmute(prio as u8) + } + /// Interrupt Error #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Error { @@ -371,7 +408,8 @@ mod vectored { clear(crate::get_core(), cpu_intr); let configured_interrupts = get_configured_interrupts(crate::get_core(), status); - let mut interrupt_mask = status & configured_interrupts[cpu_intr as usize]; + let mut interrupt_mask = + status & configured_interrupts[INTERRUPT_TO_PRIORITY[cpu_intr as usize - 1]]; while interrupt_mask != 0 { let interrupt_nr = interrupt_mask.trailing_zeros(); // Interrupt::try_from can fail if interrupt already de-asserted: @@ -474,6 +512,73 @@ mod vectored { pub unsafe fn interrupt15(context: &mut TrapFrame) { handle_interrupts(CpuInterrupt::Interrupt15, context) } + #[cfg(plic)] + #[no_mangle] + #[ram] + pub unsafe fn interrupt16(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt16, context) + } + #[cfg(plic)] + #[no_mangle] + #[ram] + pub unsafe fn interrupt17(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt17, context) + } + #[cfg(plic)] + #[no_mangle] + #[ram] + pub unsafe fn interrupt18(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt18, context) + } + #[cfg(plic)] + #[no_mangle] + #[ram] + pub unsafe fn interrupt19(context: &mut TrapFrame) { + handle_interrupts(CpuInterrupt::Interrupt19, context) + } +} + +/// Registers saved in trap handler +#[doc(hidden)] +#[allow(missing_docs)] +#[derive(Debug, Default, Clone, Copy)] +#[repr(C)] +pub struct TrapFrame { + pub ra: usize, + pub t0: usize, + pub t1: usize, + pub t2: usize, + pub t3: usize, + pub t4: usize, + pub t5: usize, + pub t6: usize, + pub a0: usize, + pub a1: usize, + pub a2: usize, + pub a3: usize, + pub a4: usize, + pub a5: usize, + pub a6: usize, + pub a7: usize, + pub s0: usize, + pub s1: usize, + pub s2: usize, + pub s3: usize, + pub s4: usize, + pub s5: usize, + pub s6: usize, + pub s7: usize, + pub s8: usize, + pub s9: usize, + pub s10: usize, + pub s11: usize, + pub gp: usize, + pub tp: usize, + pub sp: usize, + pub pc: usize, + pub mstatus: usize, + pub mcause: usize, + pub mtval: usize, } /// # Safety @@ -490,13 +595,11 @@ pub unsafe extern "C" fn start_trap_rust_hal(trap_frame: *mut TrapFrame) { let cause = mcause::read(); if cause.is_exception() { - let pc = mepc::read(); + let pc = riscv::register::mepc::read(); handle_exception(pc, trap_frame); } else { - let code = mcause::read().code(); + let code = riscv::register::mcause::read().code(); match code { - #[cfg(esp32c6)] - 0 => interrupt0(trap_frame.as_mut().unwrap()), 1 => interrupt1(trap_frame.as_mut().unwrap()), 2 => interrupt2(trap_frame.as_mut().unwrap()), 3 => interrupt3(trap_frame.as_mut().unwrap()), @@ -553,87 +656,92 @@ unsafe fn handle_exception(pc: usize, trap_frame: *mut TrapFrame) { return; } - let mut frame = [ - 0, - (*trap_frame).ra, - (*trap_frame).sp, - (*trap_frame).gp, - (*trap_frame).tp, - (*trap_frame).t0, - (*trap_frame).t1, - (*trap_frame).t2, - (*trap_frame).s0, - (*trap_frame).s1, - (*trap_frame).a0, - (*trap_frame).a1, - (*trap_frame).a2, - (*trap_frame).a3, - (*trap_frame).a4, - (*trap_frame).a5, - (*trap_frame).a6, - (*trap_frame).a7, - (*trap_frame).s2, - (*trap_frame).s3, - (*trap_frame).s4, - (*trap_frame).s5, - (*trap_frame).s6, - (*trap_frame).s7, - (*trap_frame).s8, - (*trap_frame).s9, - (*trap_frame).s10, - (*trap_frame).s11, - (*trap_frame).t3, - (*trap_frame).t4, - (*trap_frame).t5, - (*trap_frame).t6, - ]; + extern "C" { + pub fn _start_trap_atomic_rust(trap_frame: *mut riscv_atomic_emulation_trap::TrapFrame); + } + + let mut atomic_emulation_trap_frame = riscv_atomic_emulation_trap::TrapFrame { + x0: 0, + ra: (*trap_frame).ra, + sp: (*trap_frame).sp, + gp: (*trap_frame).gp, + tp: (*trap_frame).tp, + t0: (*trap_frame).t0, + t1: (*trap_frame).t1, + t2: (*trap_frame).t2, + fp: (*trap_frame).s0, + s1: (*trap_frame).s1, + a0: (*trap_frame).a0, + a1: (*trap_frame).a1, + a2: (*trap_frame).a2, + a3: (*trap_frame).a3, + a4: (*trap_frame).a4, + a5: (*trap_frame).a5, + a6: (*trap_frame).a6, + a7: (*trap_frame).a7, + s2: (*trap_frame).s2, + s3: (*trap_frame).s3, + s4: (*trap_frame).s4, + s5: (*trap_frame).s5, + s6: (*trap_frame).s6, + s7: (*trap_frame).s7, + s8: (*trap_frame).s8, + s9: (*trap_frame).s9, + s10: (*trap_frame).s10, + s11: (*trap_frame).s11, + t3: (*trap_frame).t3, + t4: (*trap_frame).t4, + t5: (*trap_frame).t5, + t6: (*trap_frame).t6, + pc: (*trap_frame).pc, + }; - riscv_atomic_emulation_trap::atomic_emulation((*trap_frame).pc, &mut frame); - - (*trap_frame).ra = frame[1]; - (*trap_frame).sp = frame[2]; - (*trap_frame).gp = frame[3]; - (*trap_frame).tp = frame[4]; - (*trap_frame).t0 = frame[5]; - (*trap_frame).t1 = frame[6]; - (*trap_frame).t2 = frame[7]; - (*trap_frame).s0 = frame[8]; - (*trap_frame).s1 = frame[9]; - (*trap_frame).a0 = frame[10]; - (*trap_frame).a1 = frame[11]; - (*trap_frame).a2 = frame[12]; - (*trap_frame).a3 = frame[13]; - (*trap_frame).a4 = frame[14]; - (*trap_frame).a5 = frame[15]; - (*trap_frame).a6 = frame[16]; - (*trap_frame).a7 = frame[17]; - (*trap_frame).s2 = frame[18]; - (*trap_frame).s3 = frame[19]; - (*trap_frame).s4 = frame[20]; - (*trap_frame).s5 = frame[21]; - (*trap_frame).s6 = frame[22]; - (*trap_frame).s7 = frame[23]; - (*trap_frame).s8 = frame[24]; - (*trap_frame).s9 = frame[25]; - (*trap_frame).s10 = frame[26]; - (*trap_frame).s11 = frame[27]; - (*trap_frame).t3 = frame[28]; - (*trap_frame).t4 = frame[29]; - (*trap_frame).t5 = frame[30]; - (*trap_frame).t6 = frame[31]; - (*trap_frame).pc = pc + 4; + _start_trap_atomic_rust(&mut atomic_emulation_trap_frame); + + (*trap_frame).pc = atomic_emulation_trap_frame.pc; + (*trap_frame).ra = atomic_emulation_trap_frame.ra; + (*trap_frame).sp = atomic_emulation_trap_frame.sp; + (*trap_frame).gp = atomic_emulation_trap_frame.gp; + (*trap_frame).tp = atomic_emulation_trap_frame.tp; + (*trap_frame).t0 = atomic_emulation_trap_frame.t0; + (*trap_frame).t1 = atomic_emulation_trap_frame.t1; + (*trap_frame).t2 = atomic_emulation_trap_frame.t2; + (*trap_frame).s0 = atomic_emulation_trap_frame.fp; + (*trap_frame).s1 = atomic_emulation_trap_frame.s1; + (*trap_frame).a0 = atomic_emulation_trap_frame.a0; + (*trap_frame).a1 = atomic_emulation_trap_frame.a1; + (*trap_frame).a2 = atomic_emulation_trap_frame.a2; + (*trap_frame).a3 = atomic_emulation_trap_frame.a3; + (*trap_frame).a4 = atomic_emulation_trap_frame.a4; + (*trap_frame).a5 = atomic_emulation_trap_frame.a5; + (*trap_frame).a6 = atomic_emulation_trap_frame.a6; + (*trap_frame).a7 = atomic_emulation_trap_frame.a7; + (*trap_frame).s2 = atomic_emulation_trap_frame.s2; + (*trap_frame).s3 = atomic_emulation_trap_frame.s3; + (*trap_frame).s4 = atomic_emulation_trap_frame.s4; + (*trap_frame).s5 = atomic_emulation_trap_frame.s5; + (*trap_frame).s6 = atomic_emulation_trap_frame.s6; + (*trap_frame).s7 = atomic_emulation_trap_frame.s7; + (*trap_frame).s8 = atomic_emulation_trap_frame.s8; + (*trap_frame).s9 = atomic_emulation_trap_frame.s9; + (*trap_frame).s10 = atomic_emulation_trap_frame.s10; + (*trap_frame).s11 = atomic_emulation_trap_frame.s11; + (*trap_frame).t3 = atomic_emulation_trap_frame.t3; + (*trap_frame).t4 = atomic_emulation_trap_frame.t4; + (*trap_frame).t5 = atomic_emulation_trap_frame.t5; + (*trap_frame).t6 = atomic_emulation_trap_frame.t6; } #[doc(hidden)] #[no_mangle] pub fn _setup_interrupts() { extern "C" { - static _vector_table: *const u32; + static _vector_table_hal: *const u32; } unsafe { - let vec_table = &_vector_table as *const _ as usize; - mtvec::write(vec_table, mtvec::TrapMode::Vectored); + let vec_table = &_vector_table_hal as *const _ as usize; + riscv::register::mtvec::write(vec_table, riscv::register::mtvec::TrapMode::Vectored); #[cfg(feature = "vectored")] crate::interrupt::init_vectoring(); @@ -648,4 +756,4 @@ fn write_mie(val: u32) { unsafe { core::arch::asm!("csrw mie, {0}", in(reg) val); } -} +} \ No newline at end of file From 731f1cbdc1b88694c1f690b0132788b946d90a90 Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Fri, 27 Jan 2023 13:35:40 +0100 Subject: [PATCH 20/64] Fix `ClockControl::configure` --- esp-hal-common/src/clock/clocks_ll/esp32c6.rs | 340 +++++++++++++++--- esp-hal-common/src/clock/mod.rs | 2 +- esp32c6-hal/ld/rom-functions.x | 3 +- 3 files changed, 302 insertions(+), 43 deletions(-) diff --git a/esp-hal-common/src/clock/clocks_ll/esp32c6.rs b/esp-hal-common/src/clock/clocks_ll/esp32c6.rs index 6dd981fabea..6a397791368 100644 --- a/esp-hal-common/src/clock/clocks_ll/esp32c6.rs +++ b/esp-hal-common/src/clock/clocks_ll/esp32c6.rs @@ -1,18 +1,11 @@ -use paste::paste; - -use crate::{ - clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock}, - regi2c_write, - regi2c_write_mask, - rom::{rom_i2c_writeReg, rom_i2c_writeReg_Mask}, -}; +use crate::clock::{ApbClock, Clock, CpuClock, PllClock, XtalClock}; extern "C" { fn ets_update_cpu_frequency(ticks_per_us: u32); } -const I2C_BBPLL: u32 = 0x66; -const I2C_BBPLL_HOSTID: u32 = 0; +const I2C_BBPLL: u8 = 0x66; +const I2C_BBPLL_HOSTID: u8 = 0; const I2C_BBPLL_IR_CAL_DELAY: u32 = 0; const I2C_BBPLL_IR_CAL_DELAY_MSB: u32 = 3; @@ -42,7 +35,7 @@ const I2C_BBPLL_IR_CAL_UNSTOP: u32 = 1; const I2C_BBPLL_IR_CAL_UNSTOP_MSB: u32 = 7; const I2C_BBPLL_IR_CAL_UNSTOP_LSB: u32 = 7; -const I2C_BBPLL_OC_REF_DIV: u32 = 2; +const I2C_BBPLL_OC_REF_DIV: u8 = 2; const I2C_BBPLL_OC_REF_DIV_MSB: u32 = 3; const I2C_BBPLL_OC_REF_DIV_LSB: u32 = 0; @@ -54,7 +47,7 @@ const I2C_BBPLL_OC_ENB_FCAL: u32 = 2; const I2C_BBPLL_OC_ENB_FCAL_MSB: u32 = 7; const I2C_BBPLL_OC_ENB_FCAL_LSB: u32 = 7; -const I2C_BBPLL_OC_DIV_7_0: u32 = 3; +const I2C_BBPLL_OC_DIV_7_0: u8 = 3; const I2C_BBPLL_OC_DIV_7_0_MSB: u32 = 7; const I2C_BBPLL_OC_DIV_7_0_LSB: u32 = 0; @@ -86,19 +79,19 @@ const I2C_BBPLL_OC_TSCHGP: u32 = 4; const I2C_BBPLL_OC_TSCHGP_MSB: u32 = 7; const I2C_BBPLL_OC_TSCHGP_LSB: u32 = 7; -const I2C_BBPLL_OC_DR1: u32 = 5; -const I2C_BBPLL_OC_DR1_MSB: u32 = 2; -const I2C_BBPLL_OC_DR1_LSB: u32 = 0; +const I2C_BBPLL_OC_DR1: u8 = 5; +const I2C_BBPLL_OC_DR1_MSB: u8 = 2; +const I2C_BBPLL_OC_DR1_LSB: u8 = 0; -const I2C_BBPLL_OC_DR3: u32 = 5; -const I2C_BBPLL_OC_DR3_MSB: u32 = 6; -const I2C_BBPLL_OC_DR3_LSB: u32 = 4; +const I2C_BBPLL_OC_DR3: u8 = 5; +const I2C_BBPLL_OC_DR3_MSB: u8 = 6; +const I2C_BBPLL_OC_DR3_LSB: u8 = 4; const I2C_BBPLL_EN_USB: u32 = 5; const I2C_BBPLL_EN_USB_MSB: u32 = 7; const I2C_BBPLL_EN_USB_LSB: u32 = 7; -const I2C_BBPLL_OC_DCUR: u32 = 6; +const I2C_BBPLL_OC_DCUR: u8 = 6; const I2C_BBPLL_OC_DCUR_MSB: u32 = 2; const I2C_BBPLL_OC_DCUR_LSB: u32 = 0; @@ -134,9 +127,9 @@ const I2C_BBPLL_OR_LOCK: u32 = 8; const I2C_BBPLL_OR_LOCK_MSB: u32 = 7; const I2C_BBPLL_OR_LOCK_LSB: u32 = 7; -const I2C_BBPLL_OC_VCO_DBIAS: u32 = 9; -const I2C_BBPLL_OC_VCO_DBIAS_MSB: u32 = 1; -const I2C_BBPLL_OC_VCO_DBIAS_LSB: u32 = 0; +const I2C_BBPLL_OC_VCO_DBIAS: u8 = 9; +const I2C_BBPLL_OC_VCO_DBIAS_MSB: u8 = 1; +const I2C_BBPLL_OC_VCO_DBIAS_LSB: u8 = 0; const I2C_BBPLL_BBADC_DELAY2: u32 = 9; const I2C_BBPLL_BBADC_DELAY2_MSB: u32 = 3; @@ -170,8 +163,38 @@ const I2C_BBPLL_ENT_ADC: u32 = 10; const I2C_BBPLL_ENT_ADC_MSB: u32 = 7; const I2C_BBPLL_ENT_ADC_LSB: u32 = 6; +// Analog function control register +const I2C_MST_ANA_CONF0_REG: u32 = 0x600AF818; +const I2C_MST_BBPLL_STOP_FORCE_HIGH: u32 = 1 << 2; +const I2C_MST_BBPLL_STOP_FORCE_LOW: u32 = 1 << 3; +const I2C_MST_BBPLL_CAL_DONE: u32 = 1 << 24; + +const MODEM_LPCON_CLK_CONF_FORCE_ON_REG: u32 = DR_REG_MODEM_LPCON_BASE + 0x1c; +const MODEM_LPCON_CLK_I2C_MST_FO: u32 = 1 << 2; +const MODEM_LPCON_I2C_MST_CLK_CONF_REG: u32 = DR_REG_MODEM_LPCON_BASE + 0x10; +const MODEM_LPCON_CLK_I2C_MST_SEL_160M: u32 = 1 << 0; + pub(crate) fn esp32c6_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClock) { unsafe { + // enable i2c mst clk by force on temporarily + (MODEM_LPCON_CLK_CONF_FORCE_ON_REG as *mut u32).write_volatile( + (MODEM_LPCON_CLK_CONF_FORCE_ON_REG as *mut u32).read_volatile() + | MODEM_LPCON_CLK_I2C_MST_FO, + ); + (MODEM_LPCON_I2C_MST_CLK_CONF_REG as *mut u32).write_volatile( + (MODEM_LPCON_I2C_MST_CLK_CONF_REG as *mut u32).read_volatile() + | MODEM_LPCON_CLK_I2C_MST_SEL_160M, + ); + + let i2c_mst_ana_conf0_reg_ptr = I2C_MST_ANA_CONF0_REG as *mut u32; + // BBPLL CALIBRATION START + i2c_mst_ana_conf0_reg_ptr.write_volatile( + i2c_mst_ana_conf0_reg_ptr.read_volatile() & !I2C_MST_BBPLL_STOP_FORCE_HIGH, + ); + i2c_mst_ana_conf0_reg_ptr.write_volatile( + i2c_mst_ana_conf0_reg_ptr.read_volatile() | I2C_MST_BBPLL_STOP_FORCE_LOW, + ); + let div_ref = 0u32; let div7_0 = 8u32; let dr1 = 0u32; @@ -185,12 +208,59 @@ pub(crate) fn esp32c6_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClo let i2c_bbpll_dcur = (1 << I2C_BBPLL_OC_DLREF_SEL_LSB) | (3 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur; - regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, i2c_bbpll_lref); - regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0); - regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_DR1, dr1); - regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_DR3, dr3); - regi2c_write!(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur); - regi2c_write_mask!(I2C_BBPLL, I2C_BBPLL_OC_VCO_DBIAS, dbias); + regi2c_write( + I2C_BBPLL, + I2C_BBPLL_HOSTID, + I2C_BBPLL_OC_REF_DIV, + i2c_bbpll_lref as u8, + ); + regi2c_write( + I2C_BBPLL, + I2C_BBPLL_HOSTID, + I2C_BBPLL_OC_DIV_7_0, + i2c_bbpll_div_7_0 as u8, + ); + regi2c_write_mask( + I2C_BBPLL, + I2C_BBPLL_HOSTID, + I2C_BBPLL_OC_DR1, + I2C_BBPLL_OC_DR1_MSB, + I2C_BBPLL_OC_DR1_LSB, + dr1 as u8, + ); + regi2c_write_mask( + I2C_BBPLL, + I2C_BBPLL_HOSTID, + I2C_BBPLL_OC_DR3, + I2C_BBPLL_OC_DR3_MSB, + I2C_BBPLL_OC_DR3_LSB, + dr3 as u8, + ); + regi2c_write( + I2C_BBPLL, + I2C_BBPLL_HOSTID, + I2C_BBPLL_OC_DCUR, + i2c_bbpll_dcur as u8, + ); + regi2c_write_mask( + I2C_BBPLL, + I2C_BBPLL_HOSTID, + I2C_BBPLL_OC_VCO_DBIAS, + I2C_BBPLL_OC_VCO_DBIAS_MSB, + I2C_BBPLL_OC_VCO_DBIAS_LSB, + dbias as u8, + ); + + // WAIT CALIBRATION DONE + while (i2c_mst_ana_conf0_reg_ptr.read_volatile() & I2C_MST_BBPLL_CAL_DONE) == 0 {} + + // BBPLL CALIBRATION STOP + i2c_mst_ana_conf0_reg_ptr.write_volatile( + i2c_mst_ana_conf0_reg_ptr.read_volatile() | I2C_MST_BBPLL_STOP_FORCE_HIGH, + ); + i2c_mst_ana_conf0_reg_ptr.write_volatile( + i2c_mst_ana_conf0_reg_ptr.read_volatile() & !I2C_MST_BBPLL_STOP_FORCE_LOW, + ); } } @@ -204,28 +274,49 @@ pub(crate) fn esp32c6_rtc_bbpll_enable() { .set_bit() .tie_high_xpd_bbpll_i2c() .set_bit() - .tie_high_global_bbpll_icg() - .set_bit() }); + + pmu.imm_hp_ck_power + .modify(|_, w| w.tie_high_global_bbpll_icg().set_bit()); } pub(crate) fn esp32c6_rtc_update_to_xtal(freq: XtalClock, _div: u8) { - let pcr = unsafe { &*crate::peripherals::PCR::PTR }; + let pcr = unsafe { &*crate::peripherals::PCR::PTR }; unsafe { ets_update_cpu_frequency(freq.mhz()); // Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) // first. - pcr.apb_freq_conf.modify(|_, w| { - w.apb_div_num() - .bits(0) - .apb_div_num() - .bits(_div - 1) - }); + pcr.apb_freq_conf + .modify(|_, w| w.apb_div_num().bits(0).apb_div_num().bits(_div - 1)); // Switch clock source - pcr - .sysclk_conf - .modify(|_, w| w.soc_clk_sel().bits(0)); + pcr.sysclk_conf.modify(|_, w| w.soc_clk_sel().bits(0)); + } +} + +pub(crate) fn esp32c6_rtc_freq_to_pll_mhz(cpu_clock_speed: CpuClock) { + // On ESP32C6, MSPI source clock's default HS divider leads to 120MHz, which is + // unusable before calibration Therefore, before switching SOC_ROOT_CLK to + // HS, we need to set MSPI source clock HS divider to make it run at + // 80MHz after the switch. PLL = 480MHz, so divider is 6. + clk_ll_mspi_fast_set_hs_divider(6); + + let pcr = unsafe { &*crate::peripherals::PCR::PTR }; + unsafe { + pcr.cpu_freq_conf.modify(|_, w| { + w.cpu_hs_div_num() + .bits(((480 / cpu_clock_speed.mhz() / 3) - 1) as u8) + .cpu_hs_120m_force() + .clear_bit() + }); + + pcr.cpu_freq_conf + .modify(|_, w| w.cpu_hs_120m_force().clear_bit()); + + pcr.sysclk_conf.modify(|_, w| { + w.soc_clk_sel().bits(1) // PLL = 1 + }); + ets_update_cpu_frequency(cpu_clock_speed.mhz()); } } @@ -238,3 +329,172 @@ pub(crate) fn esp32c6_rtc_apb_freq_update(apb_freq: ApbClock) { .store5 .modify(|_, w| unsafe { w.lp_aon_store5().bits(value) }); } + +fn clk_ll_mspi_fast_set_hs_divider(divider: u32) { + // SOC_ROOT_CLK ------> MSPI_FAST_CLK + // HS divider option: 4, 5, 6 (PCR_MSPI_FAST_HS_DIV_NUM=3, 4, 5) + let pcr = unsafe { &*crate::peripherals::PCR::PTR }; + + unsafe { + match (divider) { + 4 => pcr + .mspi_clk_conf + .modify(|_, w| w.mspi_fast_hs_div_num().bits(3)), + 5 => pcr + .mspi_clk_conf + .modify(|_, w| w.mspi_fast_hs_div_num().bits(4)), + 6 => pcr + .mspi_clk_conf + .modify(|_, w| w.mspi_fast_hs_div_num().bits(5)), + _ => panic!("Unsupported HS MSPI_FAST divider"), + } + } +} + +fn reg_set_bit(reg: u32, bit: u32) { + unsafe { + (reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() | bit); + } +} + +fn reg_clr_bit(reg: u32, bit: u32) { + unsafe { + (reg as *mut u32).write_volatile((reg as *mut u32).read_volatile() & !bit); + } +} + +fn reg_write(reg: u32, v: u32) { + unsafe { + (reg as *mut u32).write_volatile(v); + } +} + +fn reg_get_bit(reg: u32, b: u32) -> u32 { + unsafe { (reg as *mut u32).read_volatile() & b } +} + +fn reg_get_field(reg: u32, s: u32, v: u32) -> u32 { + unsafe { ((reg as *mut u32).read_volatile() >> s) & v } +} + +const DR_REG_MODEM_LPCON_BASE: u32 = 0x600AF000; +const MODEM_LPCON_CLK_CONF_REG: u32 = DR_REG_MODEM_LPCON_BASE + 0x18; +const MODEM_LPCON_CLK_I2C_MST_EN: u32 = 1 << 2; +const DR_REG_LP_I2C_ANA_MST_BASE: u32 = 0x600B2400; +const LP_I2C_ANA_MST_DATE_REG: u32 = DR_REG_LP_I2C_ANA_MST_BASE + 0x3fc; +const LP_I2C_ANA_MST_I2C_MAT_CLK_EN: u32 = 1 << 28; +const REGI2C_BIAS: u8 = 0x6a; +const REGI2C_DIG_REG: u8 = 0x6d; +const REGI2C_ULP_CAL: u8 = 0x61; +const REGI2C_SAR_I2C: u8 = 0x69; + +const LP_I2C_ANA_MST_DEVICE_EN_REG: u32 = DR_REG_LP_I2C_ANA_MST_BASE + 0x14; +const REGI2C_BBPLL_DEVICE_EN: u32 = 1 << 5; +const REGI2C_BIAS_DEVICE_EN: u32 = 1 << 4; +const REGI2C_DIG_REG_DEVICE_EN: u32 = 1 << 8; +const REGI2C_ULP_CAL_DEVICE_EN: u32 = 1 << 6; +const REGI2C_SAR_I2C_DEVICE_EN: u32 = 1 << 7; + +const REGI2C_RTC_SLAVE_ID_V: u8 = 0xFF; +const REGI2C_RTC_SLAVE_ID_S: u8 = 0; +const REGI2C_RTC_ADDR_V: u8 = 0xFF; +const REGI2C_RTC_ADDR_S: u8 = 8; +const REGI2C_RTC_WR_CNTL_V: u8 = 0x1; +const REGI2C_RTC_WR_CNTL_S: u8 = 24; +const REGI2C_RTC_DATA_V: u8 = 0xFF; +const REGI2C_RTC_DATA_S: u8 = 16; + +const LP_I2C_ANA_MST_I2C0_CTRL_REG: u32 = DR_REG_LP_I2C_ANA_MST_BASE + 0x0; +const LP_I2C_ANA_MST_I2C0_BUSY: u32 = 1 << 25; + +const LP_I2C_ANA_MST_I2C0_DATA_REG: u32 = DR_REG_LP_I2C_ANA_MST_BASE + 0x8; +const LP_I2C_ANA_MST_I2C0_RDATA_V: u32 = 0x000000FF; +const LP_I2C_ANA_MST_I2C0_RDATA_S: u32 = 0; + +fn regi2c_enable_block(block: u8) { + reg_set_bit(MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN); + reg_set_bit(LP_I2C_ANA_MST_DATE_REG, LP_I2C_ANA_MST_I2C_MAT_CLK_EN); + + // Before config I2C register, enable corresponding slave. + match block { + REGI2C_BBPLL => { + reg_set_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_BBPLL_DEVICE_EN); + } + REGI2C_BIAS => { + reg_set_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_BIAS_DEVICE_EN); + } + REGI2C_DIG_REG => { + reg_set_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_DIG_REG_DEVICE_EN); + } + REGI2C_ULP_CAL => { + reg_set_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_ULP_CAL_DEVICE_EN); + } + REGI2C_SAR_I2C => { + reg_set_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_SAR_I2C_DEVICE_EN); + } + _ => (), + } +} + +fn regi2c_disable_block(block: u8) { + match block { + REGI2C_BBPLL => { + reg_clr_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_BBPLL_DEVICE_EN); + } + REGI2C_BIAS => { + reg_clr_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_BIAS_DEVICE_EN); + } + REGI2C_DIG_REG => { + reg_clr_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_DIG_REG_DEVICE_EN); + } + REGI2C_ULP_CAL => { + reg_clr_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_ULP_CAL_DEVICE_EN); + } + REGI2C_SAR_I2C => { + reg_clr_bit(LP_I2C_ANA_MST_DEVICE_EN_REG, REGI2C_SAR_I2C_DEVICE_EN); + } + _ => (), + } +} + +fn regi2c_write(block: u8, host_id: u8, reg_add: u8, data: u8) { + regi2c_enable_block(block); + + let temp: u32 = ((block as u32 & REGI2C_RTC_SLAVE_ID_V as u32) << REGI2C_RTC_SLAVE_ID_S as u32) + | ((reg_add as u32 & REGI2C_RTC_ADDR_V as u32) << REGI2C_RTC_ADDR_S as u32) + | ((0x1 & REGI2C_RTC_WR_CNTL_V as u32) << REGI2C_RTC_WR_CNTL_S as u32) // 0: READ I2C register; 1: Write I2C register; + | (((data as u32) & REGI2C_RTC_DATA_V as u32) << REGI2C_RTC_DATA_S as u32); + reg_write(LP_I2C_ANA_MST_I2C0_CTRL_REG, temp); + while reg_get_bit(LP_I2C_ANA_MST_I2C0_CTRL_REG, LP_I2C_ANA_MST_I2C0_BUSY) != 0 {} + + regi2c_disable_block(block); +} + +fn regi2c_write_mask(block: u8, host_id: u8, reg_add: u8, msb: u8, lsb: u8, data: u8) { + assert!(msb - lsb < 8); + regi2c_enable_block(block); + + // Read the i2c bus register + let mut temp: u32 = ((block as u32 & REGI2C_RTC_SLAVE_ID_V as u32) + << REGI2C_RTC_SLAVE_ID_S as u32) + | (reg_add as u32 & REGI2C_RTC_ADDR_V as u32) << REGI2C_RTC_ADDR_S as u32; + reg_write(LP_I2C_ANA_MST_I2C0_CTRL_REG, temp); + while reg_get_bit(LP_I2C_ANA_MST_I2C0_CTRL_REG, LP_I2C_ANA_MST_I2C0_BUSY) != 0 {} + temp = reg_get_field( + LP_I2C_ANA_MST_I2C0_DATA_REG, + LP_I2C_ANA_MST_I2C0_RDATA_S, + LP_I2C_ANA_MST_I2C0_RDATA_V, + ); + // Write the i2c bus register + temp &= (!(0xFFFFFFFF << lsb)) | (0xFFFFFFFF << (msb + 1)); + temp = + ((data as u32 & (!(0xFFFFFFFF << (msb as u32 - lsb as u32 + 1)))) << (lsb as u32)) | temp; + temp = ((block as u32 & REGI2C_RTC_SLAVE_ID_V as u32) << REGI2C_RTC_SLAVE_ID_S as u32) + | ((reg_add as u32 & REGI2C_RTC_ADDR_V as u32) << REGI2C_RTC_ADDR_S as u32) + | ((0x1 & REGI2C_RTC_WR_CNTL_V as u32) << REGI2C_RTC_WR_CNTL_S as u32) + | ((temp & REGI2C_RTC_DATA_V as u32) << REGI2C_RTC_DATA_S as u32); + reg_write(LP_I2C_ANA_MST_I2C0_CTRL_REG, temp); + while reg_get_bit(LP_I2C_ANA_MST_I2C0_CTRL_REG, LP_I2C_ANA_MST_I2C0_BUSY) != 0 {} + + regi2c_disable_block(block); +} diff --git a/esp-hal-common/src/clock/mod.rs b/esp-hal-common/src/clock/mod.rs index b19999c2ef2..7252b7637af 100644 --- a/esp-hal-common/src/clock/mod.rs +++ b/esp-hal-common/src/clock/mod.rs @@ -405,7 +405,7 @@ impl<'d> ClockControl<'d> { apb_freq = ApbClock::ApbFreq80MHz; clocks_ll::esp32c6_rtc_bbpll_enable(); clocks_ll::esp32c6_rtc_bbpll_configure(xtal_freq, pll_freq); - // clocks_ll::esp32c6_rtc_freq_to_pll_mhz(cpu_clock_speed); + clocks_ll::esp32c6_rtc_freq_to_pll_mhz(cpu_clock_speed); clocks_ll::esp32c6_rtc_apb_freq_update(apb_freq); } diff --git a/esp32c6-hal/ld/rom-functions.x b/esp32c6-hal/ld/rom-functions.x index 12aeb3dab2a..60f3c118301 100644 --- a/esp32c6-hal/ld/rom-functions.x +++ b/esp32c6-hal/ld/rom-functions.x @@ -8,6 +8,5 @@ PROVIDE(cache_resume_icache = 0x4000069c); /* TODO PROVIDE(cache_dbus_mmu_set = 0x40000564); */ PROVIDE(ets_delay_us = 0x40000040); PROVIDE(ets_update_cpu_frequency_rom = 0x40000048); -PROVIDE(rom_i2c_writeReg = 0x400012c0); -PROVIDE(rom_i2c_writeReg_Mask = 0x400012e8); PROVIDE(rtc_get_reset_reason = 0x40000018); +ets_update_cpu_frequency = 0x40000048; From b0e7a59856a5a9f04e265cb76c472b209d8e5454 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Mon, 30 Jan 2023 15:00:05 +0100 Subject: [PATCH 21/64] C6: revert to I2S0 instead of just I2S --- esp-hal-common/src/clock/clocks_ll/esp32c6.rs | 2 +- esp-hal-common/src/i2s.rs | 8 +++++--- esp-hal-common/src/peripherals/esp32c6.rs | 2 +- esp32c6-hal/src/lib.rs | 1 + 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/esp-hal-common/src/clock/clocks_ll/esp32c6.rs b/esp-hal-common/src/clock/clocks_ll/esp32c6.rs index 6a397791368..322dfd00dc5 100644 --- a/esp-hal-common/src/clock/clocks_ll/esp32c6.rs +++ b/esp-hal-common/src/clock/clocks_ll/esp32c6.rs @@ -336,7 +336,7 @@ fn clk_ll_mspi_fast_set_hs_divider(divider: u32) { let pcr = unsafe { &*crate::peripherals::PCR::PTR }; unsafe { - match (divider) { + match divider { 4 => pcr .mspi_clk_conf .modify(|_, w| w.mspi_fast_hs_div_num().bits(3)), diff --git a/esp-hal-common/src/i2s.rs b/esp-hal-common/src/i2s.rs index 27160ae1f59..a68b2eda1a3 100644 --- a/esp-hal-common/src/i2s.rs +++ b/esp-hal-common/src/i2s.rs @@ -988,15 +988,17 @@ mod private { use fugit::HertzU32; use super::{DataFormat, I2sRx, I2sTx, RegisterAccess, Standard, I2S_LL_MCLK_DIVIDER_MAX}; - #[cfg(any(esp32c3, esp32c6, esp32s2))] + #[cfg(any(esp32c3, esp32s2))] use crate::peripherals::i2s::RegisterBlock; + #[cfg(esp32c6)] + use crate::peripherals::i2s0::RegisterBlock; // on ESP32-S3 I2S1 doesn't support all features - use that to avoid using those features // by accident #[cfg(any(esp32s3, esp32))] use crate::peripherals::i2s1::RegisterBlock; - #[cfg(any(esp32c3, esp32c6, esp32s2))] + #[cfg(any(esp32c3, esp32s2))] use crate::peripherals::I2S; - #[cfg(any(esp32s3, esp32))] + #[cfg(any(esp32s3, esp32, esp32c6))] use crate::peripherals::I2S0 as I2S; use crate::{ clock::Clocks, diff --git a/esp-hal-common/src/peripherals/esp32c6.rs b/esp-hal-common/src/peripherals/esp32c6.rs index 72674f4c724..255bf93252a 100644 --- a/esp-hal-common/src/peripherals/esp32c6.rs +++ b/esp-hal-common/src/peripherals/esp32c6.rs @@ -22,7 +22,7 @@ crate::peripherals! { HP_APM, HP_SYS, I2C0, - I2S, + I2S0, INTERRUPT_CORE0, INTPRI, IO_MUX, diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index f81d08d06ff..7c9b3b06049 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -9,6 +9,7 @@ pub use esp_hal_common::{ dma::gdma, gpio, i2c, + i2s, interrupt, ledc, macros, From ae4e4b5576c8761a96e21d30889da376bf654e55 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Wed, 1 Feb 2023 14:34:28 +0100 Subject: [PATCH 22/64] C6: rebase and update --- esp-hal-common/src/interrupt/riscv.rs | 192 ++++++++++--------------- esp-hal-common/src/lib.rs | 6 +- esp-hal-common/src/system.rs | 59 -------- esp32c6-hal/Cargo.toml | 14 +- esp32c6-hal/examples/blinky.rs | 3 +- esp32c6-hal/examples/gpio_interrupt.rs | 7 +- esp32c6-hal/examples/hello_world.rs | 9 +- esp32c6-hal/ld/db-esp32c6-link.x | 4 +- esp32c6-hal/ld/db-esp32c6-memory.x | 27 ++-- esp32c6-hal/ld/db-riscv-link.x | 12 +- 10 files changed, 113 insertions(+), 220 deletions(-) diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index 7d162ce01a7..0f3f2ac0175 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -12,7 +12,8 @@ //! interrupt15() => Priority::Priority15 //! ``` -use riscv::register::mcause; +use esp_riscv_rt::riscv::register::{mcause, mepc, mtvec}; +pub use esp_riscv_rt::TrapFrame; use crate::{ peripherals::{self, Interrupt}, @@ -538,48 +539,6 @@ mod vectored { } } -/// Registers saved in trap handler -#[doc(hidden)] -#[allow(missing_docs)] -#[derive(Debug, Default, Clone, Copy)] -#[repr(C)] -pub struct TrapFrame { - pub ra: usize, - pub t0: usize, - pub t1: usize, - pub t2: usize, - pub t3: usize, - pub t4: usize, - pub t5: usize, - pub t6: usize, - pub a0: usize, - pub a1: usize, - pub a2: usize, - pub a3: usize, - pub a4: usize, - pub a5: usize, - pub a6: usize, - pub a7: usize, - pub s0: usize, - pub s1: usize, - pub s2: usize, - pub s3: usize, - pub s4: usize, - pub s5: usize, - pub s6: usize, - pub s7: usize, - pub s8: usize, - pub s9: usize, - pub s10: usize, - pub s11: usize, - pub gp: usize, - pub tp: usize, - pub sp: usize, - pub pc: usize, - pub mstatus: usize, - pub mcause: usize, - pub mtval: usize, -} /// # Safety /// @@ -595,10 +554,10 @@ pub unsafe extern "C" fn start_trap_rust_hal(trap_frame: *mut TrapFrame) { let cause = mcause::read(); if cause.is_exception() { - let pc = riscv::register::mepc::read(); + let pc = mepc::read(); handle_exception(pc, trap_frame); } else { - let code = riscv::register::mcause::read().code(); + let code = mcause::read().code(); match code { 1 => interrupt1(trap_frame.as_mut().unwrap()), 2 => interrupt2(trap_frame.as_mut().unwrap()), @@ -656,80 +615,75 @@ unsafe fn handle_exception(pc: usize, trap_frame: *mut TrapFrame) { return; } - extern "C" { - pub fn _start_trap_atomic_rust(trap_frame: *mut riscv_atomic_emulation_trap::TrapFrame); - } - - let mut atomic_emulation_trap_frame = riscv_atomic_emulation_trap::TrapFrame { - x0: 0, - ra: (*trap_frame).ra, - sp: (*trap_frame).sp, - gp: (*trap_frame).gp, - tp: (*trap_frame).tp, - t0: (*trap_frame).t0, - t1: (*trap_frame).t1, - t2: (*trap_frame).t2, - fp: (*trap_frame).s0, - s1: (*trap_frame).s1, - a0: (*trap_frame).a0, - a1: (*trap_frame).a1, - a2: (*trap_frame).a2, - a3: (*trap_frame).a3, - a4: (*trap_frame).a4, - a5: (*trap_frame).a5, - a6: (*trap_frame).a6, - a7: (*trap_frame).a7, - s2: (*trap_frame).s2, - s3: (*trap_frame).s3, - s4: (*trap_frame).s4, - s5: (*trap_frame).s5, - s6: (*trap_frame).s6, - s7: (*trap_frame).s7, - s8: (*trap_frame).s8, - s9: (*trap_frame).s9, - s10: (*trap_frame).s10, - s11: (*trap_frame).s11, - t3: (*trap_frame).t3, - t4: (*trap_frame).t4, - t5: (*trap_frame).t5, - t6: (*trap_frame).t6, - pc: (*trap_frame).pc, - }; + let mut frame = [ + 0, + (*trap_frame).ra, + (*trap_frame).sp, + (*trap_frame).gp, + (*trap_frame).tp, + (*trap_frame).t0, + (*trap_frame).t1, + (*trap_frame).t2, + (*trap_frame).s0, + (*trap_frame).s1, + (*trap_frame).a0, + (*trap_frame).a1, + (*trap_frame).a2, + (*trap_frame).a3, + (*trap_frame).a4, + (*trap_frame).a5, + (*trap_frame).a6, + (*trap_frame).a7, + (*trap_frame).s2, + (*trap_frame).s3, + (*trap_frame).s4, + (*trap_frame).s5, + (*trap_frame).s6, + (*trap_frame).s7, + (*trap_frame).s8, + (*trap_frame).s9, + (*trap_frame).s10, + (*trap_frame).s11, + (*trap_frame).t3, + (*trap_frame).t4, + (*trap_frame).t5, + (*trap_frame).t6, + ]; - _start_trap_atomic_rust(&mut atomic_emulation_trap_frame); - - (*trap_frame).pc = atomic_emulation_trap_frame.pc; - (*trap_frame).ra = atomic_emulation_trap_frame.ra; - (*trap_frame).sp = atomic_emulation_trap_frame.sp; - (*trap_frame).gp = atomic_emulation_trap_frame.gp; - (*trap_frame).tp = atomic_emulation_trap_frame.tp; - (*trap_frame).t0 = atomic_emulation_trap_frame.t0; - (*trap_frame).t1 = atomic_emulation_trap_frame.t1; - (*trap_frame).t2 = atomic_emulation_trap_frame.t2; - (*trap_frame).s0 = atomic_emulation_trap_frame.fp; - (*trap_frame).s1 = atomic_emulation_trap_frame.s1; - (*trap_frame).a0 = atomic_emulation_trap_frame.a0; - (*trap_frame).a1 = atomic_emulation_trap_frame.a1; - (*trap_frame).a2 = atomic_emulation_trap_frame.a2; - (*trap_frame).a3 = atomic_emulation_trap_frame.a3; - (*trap_frame).a4 = atomic_emulation_trap_frame.a4; - (*trap_frame).a5 = atomic_emulation_trap_frame.a5; - (*trap_frame).a6 = atomic_emulation_trap_frame.a6; - (*trap_frame).a7 = atomic_emulation_trap_frame.a7; - (*trap_frame).s2 = atomic_emulation_trap_frame.s2; - (*trap_frame).s3 = atomic_emulation_trap_frame.s3; - (*trap_frame).s4 = atomic_emulation_trap_frame.s4; - (*trap_frame).s5 = atomic_emulation_trap_frame.s5; - (*trap_frame).s6 = atomic_emulation_trap_frame.s6; - (*trap_frame).s7 = atomic_emulation_trap_frame.s7; - (*trap_frame).s8 = atomic_emulation_trap_frame.s8; - (*trap_frame).s9 = atomic_emulation_trap_frame.s9; - (*trap_frame).s10 = atomic_emulation_trap_frame.s10; - (*trap_frame).s11 = atomic_emulation_trap_frame.s11; - (*trap_frame).t3 = atomic_emulation_trap_frame.t3; - (*trap_frame).t4 = atomic_emulation_trap_frame.t4; - (*trap_frame).t5 = atomic_emulation_trap_frame.t5; - (*trap_frame).t6 = atomic_emulation_trap_frame.t6; + riscv_atomic_emulation_trap::atomic_emulation((*trap_frame).pc, &mut frame); + + (*trap_frame).ra = frame[1]; + (*trap_frame).sp = frame[2]; + (*trap_frame).gp = frame[3]; + (*trap_frame).tp = frame[4]; + (*trap_frame).t0 = frame[5]; + (*trap_frame).t1 = frame[6]; + (*trap_frame).t2 = frame[7]; + (*trap_frame).s0 = frame[8]; + (*trap_frame).s1 = frame[9]; + (*trap_frame).a0 = frame[10]; + (*trap_frame).a1 = frame[11]; + (*trap_frame).a2 = frame[12]; + (*trap_frame).a3 = frame[13]; + (*trap_frame).a4 = frame[14]; + (*trap_frame).a5 = frame[15]; + (*trap_frame).a6 = frame[16]; + (*trap_frame).a7 = frame[17]; + (*trap_frame).s2 = frame[18]; + (*trap_frame).s3 = frame[19]; + (*trap_frame).s4 = frame[20]; + (*trap_frame).s5 = frame[21]; + (*trap_frame).s6 = frame[22]; + (*trap_frame).s7 = frame[23]; + (*trap_frame).s8 = frame[24]; + (*trap_frame).s9 = frame[25]; + (*trap_frame).s10 = frame[26]; + (*trap_frame).s11 = frame[27]; + (*trap_frame).t3 = frame[28]; + (*trap_frame).t4 = frame[29]; + (*trap_frame).t5 = frame[30]; + (*trap_frame).t6 = frame[31]; + (*trap_frame).pc = pc + 4; } #[doc(hidden)] @@ -741,7 +695,7 @@ pub fn _setup_interrupts() { unsafe { let vec_table = &_vector_table_hal as *const _ as usize; - riscv::register::mtvec::write(vec_table, riscv::register::mtvec::TrapMode::Vectored); + mtvec::write(vec_table, mtvec::TrapMode::Vectored); #[cfg(feature = "vectored")] crate::interrupt::init_vectoring(); diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index eb8d980b3eb..6453e157ebe 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -70,7 +70,7 @@ pub use self::pulse_control::PulseControl; // timer::Timer, // uart::Uart, // }; -pub use self::{delay::Delay, gpio::*, interrupt::*, spi::Spi, timer::Timer, uart::Uart}; +pub use self::{delay::Delay, gpio::*, interrupt::*, spi::Spi, timer::Timer, uart::Uart, /*rtc_cntl::{Rtc, Rwdt},*/}; // pub mod analog; pub mod clock; @@ -97,8 +97,8 @@ pub mod pulse_control; pub mod radio; pub mod rng; pub mod rom; -#[cfg(not(esp32c6))] -pub mod rtc_cntl; +// #[cfg(not(esp32c6))] +// pub mod rtc_cntl; pub mod sha; pub mod spi; pub mod system; diff --git a/esp-hal-common/src/system.rs b/esp-hal-common/src/system.rs index 7fa7dd9af5a..17bf9fa0892 100644 --- a/esp-hal-common/src/system.rs +++ b/esp-hal-common/src/system.rs @@ -80,11 +80,7 @@ impl PeripheralClockControl { ) }; -<<<<<<< HEAD #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s2, esp32s3))] -======= - #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] ->>>>>>> b278bca (Get a number of peripheral drivers building for the ESP32-C6) let (perip_clk_en1, perip_rst_en1) = { (&system.perip_clk_en1, &system.perip_rst_en1) }; match peripheral { @@ -253,61 +249,6 @@ impl PeripheralClockControl { } } -#[cfg(esp32c6)] -impl PeripheralClockControl { - /// Enables and resets the given peripheral - pub fn enable(&mut self, peripheral: Peripheral) { - let system = unsafe { &*SystemPeripheral::PTR }; - - match peripheral { - Peripheral::Spi2 => { - system.spi2_conf.modify(|_, w| w.spi2_clk_en().set_bit()); - system.spi2_conf.modify(|_, w| w.spi2_rst_en().clear_bit()); - } - Peripheral::I2cExt0 => { - // FIXME - // perip_clk_en0.modify(|_, w| w.i2c_ext0_clk_en().set_bit()); - // perip_rst_en0.modify(|_, w| w.i2c_ext0_rst().clear_bit()); - } - Peripheral::Rmt => { - system.rmt_conf.modify(|_, w| w.rmt_clk_en().set_bit()); - system.rmt_conf.modify(|_, w| w.rmt_rst_en().clear_bit()); - } - Peripheral::Ledc => { - system.ledc_conf.modify(|_, w| w.ledc_clk_en().set_bit()); - system.ledc_conf.modify(|_, w| w.ledc_rst_en().clear_bit()); - } - Peripheral::Mcpwm0 | Peripheral::Mcpwm1 => { - system.pwm_conf.modify(|_, w| w.pwm_clk_en().set_bit()); - system.pwm_conf.modify(|_, w| w.pwm_rst_en().clear_bit()); - } - Peripheral::ApbSarAdc => { - // TODO - } - Peripheral::Gdma => { - system.gdma_conf.modify(|_, w| w.gdma_clk_en().set_bit()); - system.gdma_conf.modify(|_, w| w.gdma_rst_en().clear_bit()); - } - Peripheral::I2s0 => { - system.i2s_conf.modify(|_, w| w.i2s_clk_en().set_bit()); - system.i2s_conf.modify(|_, w| w.i2s_rst_en().clear_bit()); - } - Peripheral::Twai0 => { - system.twai0_conf.modify(|_, w| w.twai0_clk_en().set_bit()); - system - .twai0_conf - .modify(|_, w| w.twai0_rst_en().clear_bit()); - } - Peripheral::Twai1 => { - system.twai1_conf.modify(|_, w| w.twai1_clk_en().set_bit()); - system - .twai1_conf - .modify(|_, w| w.twai1_rst_en().clear_bit()); - } - } - } -} - /// Controls the configuration of the chip's clocks. pub struct SystemClockControl { _private: (), diff --git a/esp32c6-hal/Cargo.toml b/esp32c6-hal/Cargo.toml index 413c1225684..3da07dd80b7 100644 --- a/esp32c6-hal/Cargo.toml +++ b/esp32c6-hal/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" authors = [ "Jesse Braham ", "Björn Quentin ", + "Juraj Sadel ", ] edition = "2021" rust-version = "1.60.0" @@ -29,15 +30,15 @@ cfg-if = "1.0.0" embassy-time = { version = "0.1.0", features = ["nightly"], optional = true } embedded-hal = { version = "0.2.7", features = ["unproven"] } embedded-hal-1 = { version = "=1.0.0-alpha.9", optional = true, package = "embedded-hal" } -embedded-hal-async = { version = "0.1.0-alpha.3", optional = true } +embedded-hal-async = { version = "0.2.0-alpha.0", optional = true } embedded-hal-nb = { version = "=1.0.0-alpha.1", optional = true } embedded-can = { version = "0.4.1", optional = true } -esp-hal-common = { features = ["esp32c6"], path = "../esp-hal-common" } +esp-hal-common = { version = "0.5.0", features = ["esp32c6"], path = "../esp-hal-common" } +esp-riscv-rt = { version = "0.1.0", optional = true } r0 = "1.0.0" -riscv = "0.10.1" -riscv-rt = { version = "0.11.0", optional = true } [dev-dependencies] +aes = "0.8.2" critical-section = "1.1.1" embassy-executor = { package = "embassy-executor", git = "https://github.com/embassy-rs/embassy/", rev = "cd9a65b", features = ["nightly", "integrated-timers"] } embedded-graphics = "0.7.1" @@ -53,7 +54,7 @@ default = ["rt", "vectored"] mcu-boot = [] direct-boot = [] eh1 = ["esp-hal-common/eh1", "dep:embedded-hal-1", "dep:embedded-hal-nb", "dep:embedded-can"] -rt = ["riscv-rt"] +rt = ["esp-riscv-rt"] smartled = ["esp-hal-common/smartled"] ufmt = ["esp-hal-common/ufmt"] vectored = ["esp-hal-common/vectored"] @@ -78,3 +79,6 @@ embassy-time-timg0 = ["esp-hal-common/embassy-time-timg0", "embassy-time/tick-hz # [[example]] # name = "embassy_hello_world" # required-features = ["embassy"] + +[profile.dev] +opt-level = 1 \ No newline at end of file diff --git a/esp32c6-hal/examples/blinky.rs b/esp32c6-hal/examples/blinky.rs index c13a4313c9d..f7bc1768081 100644 --- a/esp32c6-hal/examples/blinky.rs +++ b/esp32c6-hal/examples/blinky.rs @@ -14,7 +14,8 @@ use esp32c6_hal::{ Delay, }; use esp_backtrace as _; -use riscv_rt::entry; +use esp_riscv_rt::entry; + #[entry] fn main() -> ! { diff --git a/esp32c6-hal/examples/gpio_interrupt.rs b/esp32c6-hal/examples/gpio_interrupt.rs index bd29d452255..48a39ddeb07 100644 --- a/esp32c6-hal/examples/gpio_interrupt.rs +++ b/esp32c6-hal/examples/gpio_interrupt.rs @@ -6,7 +6,7 @@ #![no_std] #![no_main] -use core::{arch::asm, cell::RefCell}; +use core::cell::RefCell; use critical_section::Mutex; use esp32c6_hal::{ @@ -15,14 +15,13 @@ use esp32c6_hal::{ interrupt, peripherals::{self, Peripherals}, prelude::*, - systimer::SystemTimer, - // Rtc, timer::TimerGroup, Delay, + // Rtc, }; use esp_backtrace as _; +use esp_riscv_rt::{entry, riscv}; use esp_println::println; -use riscv_rt::entry; static BUTTON: Mutex>>>> = Mutex::new(RefCell::new(None)); diff --git a/esp32c6-hal/examples/hello_world.rs b/esp32c6-hal/examples/hello_world.rs index 3409f2646f0..007c9c41a7d 100644 --- a/esp32c6-hal/examples/hello_world.rs +++ b/esp32c6-hal/examples/hello_world.rs @@ -21,17 +21,16 @@ use esp32c6_hal::{ //Cpu, }; -use nb::block; use esp_hal_common::system::SystemExt; use esp_backtrace as _; - -// static SERIAL: Mutex>>> = Mutex::new(RefCell::new(None)); - use esp_println::println; +use esp_riscv_rt::entry; +use nb::block; + -#[riscv_rt::entry] +#[entry] fn main() -> ! { esp_println::println!("fffff"); let peripherals = Peripherals::take(); diff --git a/esp32c6-hal/ld/db-esp32c6-link.x b/esp32c6-hal/ld/db-esp32c6-link.x index 63ba963a232..b2e740b39dc 100644 --- a/esp32c6-hal/ld/db-esp32c6-link.x +++ b/esp32c6-hal/ld/db-esp32c6-link.x @@ -6,9 +6,9 @@ SECTIONS { LONG(0xaedb041d) LONG(0xaedb041d) - } > IROM + } > ROM } -_stext = ORIGIN(IROM) + 8; +_stext = ORIGIN(ROM) + 8; INCLUDE riscv-link.x diff --git a/esp32c6-hal/ld/db-esp32c6-memory.x b/esp32c6-hal/ld/db-esp32c6-memory.x index 68a8d68e65e..33949c5bfdc 100644 --- a/esp32c6-hal/ld/db-esp32c6-memory.x +++ b/esp32c6-hal/ld/db-esp32c6-memory.x @@ -16,28 +16,23 @@ MEMORY /* 512K of on soc RAM, 32K reserved for cache */ ICACHE : ORIGIN = 0x40800000, LENGTH = 32K - /* Instruction RAM */ - IRAM : ORIGIN = 0x40800000 + 32K, LENGTH = 512K - 32K - /* Data RAM */ - DRAM : ORIGIN = 0x40800000 + 32K, LENGTH = 512K - 32K + + RAM : ORIGIN = 0x40800000 + 32K, LENGTH = 512K - 32K /* External flash */ - /* Instruction ROM */ - IROM : ORIGIN = 0x42000000, LENGTH = 0x400000 - /* Data ROM */ - DROM : ORIGIN = 0x42800000, LENGTH = 0x400000 + ROM : ORIGIN = 0x42000000, LENGTH = 0x400000 /* RTC fast memory (executable). Persists over deep sleep. */ RTC_FAST : ORIGIN = 0x50000000, LENGTH = 16K /*- ESP_BOOTLOADER_RESERVE_RTC*/ } -REGION_ALIAS("REGION_TEXT", IROM); -REGION_ALIAS("REGION_RODATA", DROM); +REGION_ALIAS("REGION_TEXT", ROM); +REGION_ALIAS("REGION_RODATA", ROM); -REGION_ALIAS("REGION_DATA", DRAM); -REGION_ALIAS("REGION_BSS", DRAM); -REGION_ALIAS("REGION_HEAP", DRAM); -REGION_ALIAS("REGION_STACK", DRAM); +REGION_ALIAS("REGION_DATA", RAM); +REGION_ALIAS("REGION_BSS", RAM); +REGION_ALIAS("REGION_HEAP", RAM); +REGION_ALIAS("REGION_STACK", RAM); -REGION_ALIAS("REGION_RWTEXT", IRAM); -REGION_ALIAS("REGION_RTC_FAST", RTC_FAST); +REGION_ALIAS("REGION_RWTEXT", RAM); +REGION_ALIAS("REGION_RTC_FAST", RTC_FAST); \ No newline at end of file diff --git a/esp32c6-hal/ld/db-riscv-link.x b/esp32c6-hal/ld/db-riscv-link.x index b75f8dadd7c..9033f790b75 100644 --- a/esp32c6-hal/ld/db-riscv-link.x +++ b/esp32c6-hal/ld/db-riscv-link.x @@ -61,7 +61,7 @@ SECTIONS } > REGION_TEXT _text_size = _etext - _stext + 8; - .rodata ORIGIN(DROM) + _text_size : AT(_text_size) + .rodata ORIGIN(ROM) + _text_size : AT(_text_size) { _srodata = .; *(.srodata .srodata.*); @@ -75,7 +75,7 @@ SECTIONS } > REGION_RODATA _rodata_size = _erodata - _srodata + 8; - .data ORIGIN(DRAM) : AT(_text_size + _rodata_size) + .data ORIGIN(RAM) : AT(_text_size + _rodata_size) { _sdata = .; /* Must be called __global_pointer$ for linker relaxations to work. */ @@ -182,9 +182,9 @@ SECTIONS } PROVIDE(_sidata = _erodata + 8); -PROVIDE(_irwtext = ORIGIN(DROM) + _text_size + _rodata_size + _data_size); -PROVIDE(_irtc_fast_text = ORIGIN(DROM) + _text_size + _rodata_size + _data_size + _rwtext_size); -PROVIDE(_irtc_fast_data = ORIGIN(DROM) + _text_size + _rodata_size + _data_size + _rwtext_size + _fast_text_size); +PROVIDE(_irwtext = ORIGIN(ROM) + _text_size + _rodata_size + _data_size); +PROVIDE(_irtc_fast_text = ORIGIN(ROM) + _text_size + _rodata_size + _data_size + _rwtext_size); +PROVIDE(_irtc_fast_data = ORIGIN(ROM) + _text_size + _rodata_size + _data_size + _rwtext_size + _fast_text_size); /* Do not exceed this mark in the error messages above | */ ASSERT(ORIGIN(REGION_TEXT) % 4 == 0, " @@ -235,4 +235,4 @@ then modify your build script to compile the C code _without_ the -fPIC flag. See the documentation of the `gcc::Config.fpic` method for details."); -/* Do not exceed this mark in the error messages above | */ +/* Do not exceed this mark in the error messages above | */ \ No newline at end of file From a4edc469ca11ba6185b6fe72bc7f1bb9f906ae5a Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Thu, 2 Feb 2023 10:59:46 +0100 Subject: [PATCH 23/64] RTC not buildable --- esp-hal-common/src/lib.rs | 5 +- esp-hal-common/src/rtc_cntl/mod.rs | 372 ++++++++++++++++++++- esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs | 289 ++++++++++++++++ 3 files changed, 657 insertions(+), 9 deletions(-) create mode 100644 esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index 6453e157ebe..78c96868560 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -70,7 +70,7 @@ pub use self::pulse_control::PulseControl; // timer::Timer, // uart::Uart, // }; -pub use self::{delay::Delay, gpio::*, interrupt::*, spi::Spi, timer::Timer, uart::Uart, /*rtc_cntl::{Rtc, Rwdt},*/}; +pub use self::{delay::Delay, gpio::*, interrupt::*, spi::Spi, timer::Timer, uart::Uart, rtc_cntl::{Rtc, Rwdt},}; // pub mod analog; pub mod clock; @@ -97,8 +97,7 @@ pub mod pulse_control; pub mod radio; pub mod rng; pub mod rom; -// #[cfg(not(esp32c6))] -// pub mod rtc_cntl; +pub mod rtc_cntl; pub mod sha; pub mod spi; pub mod system; diff --git a/esp-hal-common/src/rtc_cntl/mod.rs b/esp-hal-common/src/rtc_cntl/mod.rs index 69ff5e86060..3cafd5904a9 100644 --- a/esp-hal-common/src/rtc_cntl/mod.rs +++ b/esp-hal-common/src/rtc_cntl/mod.rs @@ -7,13 +7,19 @@ use crate::efuse::Efuse; use crate::{ clock::{Clock, XtalClock}, peripheral::{Peripheral, PeripheralRef}, - peripherals::{RTC_CNTL, TIMG0}, + peripherals::{TIMG0}, Cpu, }; +#[cfg(not(esp32c6))] +use crate::peripherals::RTC_CNTL; +#[cfg(esp32c6)] +use crate::peripherals::{LP_CLKRST, LP_AON, PCR, PMU}; + #[cfg_attr(esp32, path = "rtc/esp32.rs")] #[cfg_attr(esp32c2, path = "rtc/esp32c2.rs")] #[cfg_attr(esp32c3, path = "rtc/esp32c3.rs")] +#[cfg_attr(esp32c6, path = "rtc/esp32c6.rs")] #[cfg_attr(esp32s2, path = "rtc/esp32s2.rs")] #[cfg_attr(esp32s3, path = "rtc/esp32s3.rs")] mod rtc; @@ -47,6 +53,7 @@ impl Clock for RtcFastClock { } #[allow(unused)] +#[cfg(not(esp32c6))] #[derive(Debug, Clone, Copy)] /// RTC SLOW_CLK frequency values pub(crate) enum RtcSlowClock { @@ -58,6 +65,22 @@ pub(crate) enum RtcSlowClock { RtcSlowClock8mD256 = 2, } +#[allow(unused)] +#[cfg(esp32c6)] +#[derive(Debug, Clone, Copy, PartialEq)] +/// RTC SLOW_CLK frequency values +pub(crate) enum RtcSlowClock { + /// Internal slow RC oscillator + RtcSlowClockRtc = 0, + /// External 32 KHz XTAL + RtcSlowClock32kXtal = 1, + /// TODO + RtcSlowClock32kRc = 2, + /// Internal 150 KHz RC oscillator + RtcCalInternalOsc = 3, + RtcCalRcFast +} + impl Clock for RtcSlowClock { fn frequency(&self) -> HertzU32 { match self { @@ -65,18 +88,22 @@ impl Clock for RtcSlowClock { RtcSlowClock::RtcSlowClockRtc => HertzU32::Hz(150_000), #[cfg(esp32s2)] RtcSlowClock::RtcSlowClockRtc => HertzU32::Hz(90_000), - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] RtcSlowClock::RtcSlowClockRtc => HertzU32::Hz(136_000), RtcSlowClock::RtcSlowClock32kXtal => HertzU32::Hz(32768), #[cfg(any(esp32, esp32s2))] RtcSlowClock::RtcSlowClock8mD256 => HertzU32::Hz(8_500_000 / 256), #[cfg(any(esp32c2, esp32c3, esp32s3))] RtcSlowClock::RtcSlowClock8mD256 => HertzU32::Hz(17_500_000 / 256), + #[cfg(esp32c6)] + RtcSlowClock::RtcCalRcFast => HertzU32::Hz(17_500_00), + } } } #[allow(unused)] +#[cfg(not(esp32c6))] #[derive(Debug, Clone, Copy)] /// Clock source to be calibrated using rtc_clk_cal function pub(crate) enum RtcCalSel { @@ -91,6 +118,32 @@ pub(crate) enum RtcCalSel { RtcCalInternalOsc = 3, } +#[allow(unused)] +#[cfg(esp32c6)] +#[derive(Debug, Clone, Copy, PartialEq)] +/// Clock source to be calibrated using rtc_clk_cal function +pub(crate) enum RtcCalSel { + /// Currently selected RTC SLOW_CLK + RtcCalRtcMux = -1, + /// Currently selected RTC SLOW_CLK + RtcCalRcSlow = 0, + /// External 32 KHz XTAL + RtcCal32kXtal = 1, + /// TODO + RtcCal32kRc = 2, + #[cfg(not(esp32))] + /// Internal 150 KHz RC oscillator TODO + RtcCalInternalOsc= 3, + RtcCalRcFast +} + +#[cfg(esp32c6)] +pub(crate) enum RtcCaliClkSel { + CaliClkRcSlow = 0, + CaliClkRcFast = 1, + CaliClk32k = 2, +} + pub struct Rtc<'d> { _inner: PeripheralRef<'d, RTC_CNTL>, pub rwdt: Rwdt, @@ -135,6 +188,7 @@ impl RtcClock { /// /// When 8MHz/256 divided output is not needed, the divider should be /// disabled to reduce power consumption. + #[cfg(not(esp32c6))] fn enable_8m(clk_8m_en: bool, d256_en: bool) { let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; @@ -160,13 +214,33 @@ impl RtcClock { } } + #[cfg(esp32c6)] + fn enable_8m(clk_8m_en: bool, _d256_en: bool) { + let pmu = unsafe { &*PMU::ptr() }; + + if clk_8m_en { + pmu.hp_sleep_lp_ck_power.modify(|_, w| w.hp_sleep_xpd_fosc_clk().set_bit()); + unsafe { + ets_delay_us(50); + } + } else { + pmu.hp_sleep_lp_ck_power.modify(|_, w| w.hp_sleep_xpd_fosc_clk().clear_bit()); + } + } + /// Get main XTAL frequency /// This is the value stored in RTC register RTC_XTAL_FREQ_REG by the /// bootloader, as passed to rtc_clk_init function. fn get_xtal_freq() -> XtalClock { + #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; + #[cfg(not(esp32c6))] let xtal_freq_reg = rtc_cntl.store4.read().bits(); + #[cfg(esp32c6)] + let lp_aon = unsafe { &*LP_AON::ptr() }; + #[cfg(esp32c6)] + let xtal_freq_reg = lp_aon.store4.read().bits(); // Values of RTC_XTAL_FREQ_REG and RTC_APB_FREQ_REG are stored as two copies in // lower and upper 16-bit halves. These are the routines to work with such a // representation. @@ -192,6 +266,7 @@ impl RtcClock { } /// Get the RTC_SLOW_CLK source + #[cfg(not(esp32c6))] fn get_slow_freq() -> RtcSlowClock { let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; let slow_freq = rtc_cntl.clk_conf.read().ana_clk_rtc_sel().bits(); @@ -203,6 +278,22 @@ impl RtcClock { } } + /// Get the RTC_SLOW_CLK source + #[cfg(esp32c6)] + fn get_slow_freq() -> RtcSlowClock { + let lp_clrst = &*LP_CLKRST::ptr(); + let pcr = &*PCR::ptr(); + + let slow_freq = lp_clrst.lp_clk_conf.read().slow_clk_sel().bits(); + match slow_freq { + 0 => RtcSlowClock::RtcSlowClockRtc, + 1 => RtcSlowClock::RtcSlowClock32kXtal, + 2 => RtcSlowClock::RtcSlowClock32kRc, + 3 => RtcSlowClock::RtcCalInternalOsc, + _ => unreachable!(), + } + } + /// Select source for RTC_SLOW_CLK fn set_slow_freq(slow_freq: RtcSlowClock) { unsafe { @@ -226,9 +317,6 @@ impl RtcClock { _ => false, }) }); - - ets_delay_us(300u32); - }; } /// Select source for RTC_FAST_CLK @@ -249,6 +337,7 @@ impl RtcClock { /// Calibration of RTC_SLOW_CLK is performed using a special feature of /// TIMG0. This feature counts the number of XTAL clock cycles within a /// given number of RTC_SLOW_CLK cycles. + #[cfg(not(esp32c6))] fn calibrate_internal(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { // Except for ESP32, choosing RTC_CAL_RTC_MUX results in calibration of // the 150k RTC clock (90k on ESP32-S2) regardless of the currently selected @@ -264,6 +353,7 @@ impl RtcClock { RtcCalSel::RtcCalInternalOsc => RtcCalSel::RtcCalRtcMux, _ => cal_clk, }; + let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; let timg0 = unsafe { &*TIMG0::ptr() }; @@ -393,6 +483,272 @@ impl RtcClock { cal_val } + /// Calibration of RTC_SLOW_CLK is performed using a special feature of + /// TIMG0. This feature counts the number of XTAL clock cycles within a + /// given number of RTC_SLOW_CLK cycles. + #[cfg(esp32c6)] + fn calibrate_internal(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { + // Except for ESP32, choosing RTC_CAL_RTC_MUX results in calibration of + // the 150k RTC clock (90k on ESP32-S2) regardless of the currently selected + // SLOW_CLK. On the ESP32, it uses the currently selected SLOW_CLK. + // The following code emulates ESP32 behavior for the other chips: + #[cfg(not(any(esp32, esp32c6)))] + let cal_clk = match cal_clk { + RtcCalSel::RtcCalRtcMux => match RtcClock::get_slow_freq() { + RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, + RtcSlowClock::RtcSlowClock8mD256 => RtcCalSel::RtcCal8mD256, + _ => cal_clk, + }, + RtcCalSel::RtcCalInternalOsc => RtcCalSel::RtcCalRtcMux, + _ => cal_clk, + }; + + #[cfg(esp32c6)] + if cal_clk == RtcCalSel::RtcCalRtcMux { + cal_clk = match cal_clk { + RtcCalSel::RtcCalRtcMux => match RtcClock::get_slow_freq() { + RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, + RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc, + _ => cal_clk, + }, + RtcCalSel::RtcCalInternalOsc => RtcCalSel::RtcCalRtcMux, + _ => cal_clk, + }; + } + + let lp_clkrst = unsafe { &*LP_CLKRST::ptr() }; + // let lp_clkrst = &*LP_CLKRST::ptr(); + let pcr = &*PCR::ptr(); + let pmu = &*PMU::ptr(); + + const SOC_CLK_RC_FAST_FREQ_APPROX :u32 = 17_500_000; + const SOC_CLK_RC_SLOW_FREQ_APPROX :u32 = 136_000 ; + const SOC_CLK_RC32K_FREQ_APPROX :u32 = 32768 ; + const SOC_CLK_XTAL32K_FREQ_APPROX :u32 = 32768 ; + const SOC_CLK_OSC_SLOW_FREQ_APPROX :u32 = 32768; + + let clk_src = RtcClock::get_slow_freq(); + + let old_clk_sel = match pcr.ctrl_32k_conf.read().clk_32k_sel().bits() { + 0 => RtcSlowClock::RtcSlowClockRtc, + 1 => RtcSlowClock::RtcSlowClock32kXtal, + 2 => RtcSlowClock::RtcSlowClock32kRc, + _ => unreachable!(), + }; + + if cal_clk == RtcCalSel::RtcCalRtcMux { + cal_clk = match clk_src { + RtcSlowClock::RtcSlowClockRtc => RtcCalSel::RtcCalRcSlow, + RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, + RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc, + RtcSlowClock::RtcCalInternalOsc => RtcCalSel::RtcCalInternalOsc, + _ => unreachable!() + }; + } + + let cali_clk_sel = match cal_clk { + RtcCalSel::RtcCalRcFast => RtcCaliClkSel::CaliClkRcFast, + RtcCalSel::RtcCalRcSlow => RtcCaliClkSel::CaliClkRcSlow, + _ => { + match clk_src { + RtcSlowClock::RtcSlowClock32kRc => pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(0)), + RtcSlowClock::RtcSlowClock32kXtal => pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(1)), + RtcSlowClock::RtcCalInternalOsc => pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(2)), + _ => unreachable!() + }; + RtcCaliClkSel::CaliClk32k + } + }; + + // if cal_clk == RtcCalSel::RtcCalRcFast { + // cali_clk_sel = RtcCaliClkSel::CaliClkRcFast; + // } else if cal_clk == RtcCalSel::RtcCalRcSlow { + // cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_SLOW; + // } else { + // cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_32K; + // match clk_src { + // RtcSlowClock::RtcSlowClock32kRc => pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(0)), + // RtcSlowClock::RtcSlowClock32kXtal => pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(1)), + // RtcSlowClock::RtcCalInternalOsc => pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(2)), + // _ => unreachable!() + // } + // } + + // Enable requested clock (150k is always on) + // Some delay is required before the time is stable + // Only enable if originaly was disabled + // If clock is already on, do nothing + + let dig_32k_xtal_enabled = lp_clkrst.clk_to_hp.read().icg_hp_xtal32k().bit_is_set(); + + if cal_clk == RtcCalSel::RtcCal32kXtal && !dig_32k_xtal_enabled { + lp_clkrst.clk_to_hp.modify(|_, w| w.icg_hp_xtal32k().set_bit()); + } + + let rc_fast_enabled = pmu.hp_sleep_lp_ck_power.read().hp_sleep_xpd_fosc_clk().bit_is_set(); + let dig_rc_fast_enabled = lp_clkrst.clk_to_hp.read().icg_hp_fosc().bit_is_set(); + + if cal_clk == RtcCalSel::RtcCalRcFast { + if !rc_fast_enabled { + pmu.hp_sleep_lp_ck_power.write(|w| w.hp_sleep_xpd_fosc_clk().set_bit()); + unsafe { + ets_delay_us(50); + } + } + + if !dig_rc_fast_enabled { + lp_clkrst.clk_to_hp.write(|w| w.icg_hp_fosc().set_bit()); + unsafe { + ets_delay_us(5); + } + } + } + + let rc32k_enabled = pmu.hp_sleep_lp_ck_power.read().hp_sleep_xpd_rc32k().bit_is_set(); + let dig_rc32k_enabled = lp_clkrst.clk_to_hp.read().icg_hp_osc32k().bit_is_set(); + + if cal_clk == RtcCalSel::RtcCal32kRc { + if !rc32k_enabled { + pmu.hp_sleep_lp_ck_power.write(|w| w.hp_sleep_xpd_rc32k().set_bit()); + unsafe { + ets_delay_us(300); + } + } + if !dig_rc32k_enabled { + lp_clkrst.clk_to_hp.write(|w| w.icg_hp_osc32k().set_bit()); + } + } + + // Check if there is already running calibration process + let timg0 = unsafe { &*TIMG0::ptr() }; + + if timg0.rtccalicfg.read().rtc_cali_start_cycling().bit_is_set() { + timg0.rtccalicfg2.modify(|_, w| w.rtc_cali_timeout_thres().bits(1)); + + // Set small timeout threshold to accelerate the generation of timeot + // Internal circuit will be reset when timeout occurs and will not affect the next calibration + while timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_clear() + && timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_clear() {} + } + + // Prepare calibration + timg0.rtccalicfg.modify(|_, w| w.rtc_cali_clk_sel().bits(cali_clk_sel as u8)); + timg0.rtccalicfg.write(|w| w.rtc_cali_start_cycling().clear_bit()); + timg0.rtccalicfg.modify(|_, w| w.rtc_cali_max().bits(slowclk_cycles.try_into().unwrap())); + + let expected_freq = match cali_clk_sel { + RtcCaliClkSel::CaliClk32k => { + #[cfg(not(esp32))] + timg0.rtccalicfg2.modify(|_, w| w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12)); + RtcSlowClock::RtcSlowClock32kXtal + } + RtcCaliClkSel::CaliClkRcFast => { + #[cfg(not(esp32))] + timg0.rtccalicfg2.modify(|_, w| w.rtc_cali_timeout_thres().bits(0x01FFFFFF)); + RtcSlowClock::RtcCalRcFast + } + _ => { + #[cfg(not(esp32))] + timg0.rtccalicfg2.modify(|_, w| w.rtc_cali_timeout_thres().bits(slowclk_cycles << 10)); + RtcSlowClock::RtcSlowClockRtc + } + }; + + // if cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_32K { + // timg0.rtccalicfg2.modify(|_, w| w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12)); + // expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX; + // } else if cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST { + // timg0.rtccalicfg2.modify(|_, w| w.rtc_cali_timeout_thres().bits(0x01FFFFFF)); + // expected_freq = 17_500_000; + // } else { + // timg0.rtccalicfg2.modify(|_, w| w.rtc_cali_timeout_thres().bits(slowclk_cycles << 10)); + // expected_freq = 136_000; + // } + + let us_time_estimate = HertzU32::MHz(slowclk_cycles) / expected_freq.frequency(); + + + // Start calibration + timg0 + .rtccalicfg + .modify(|_, w| w.rtc_cali_start().clear_bit().rtc_cali_start().set_bit()); + + // Wait for calibration to finish up to another us_time_estimate + unsafe { + ets_delay_us(us_time_estimate); + } + + let cal_val = loop { + if timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_set() { + break timg0.rtccalicfg1.read().rtc_cali_value().bits(); + } + + #[cfg(not(esp32))] + if timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_set() { + // Timed out waiting for calibration + break 0; + } + + // #[cfg(esp32)] + // if timeout_us > 0 { + // timeout_us -= 1; + // unsafe { + // ets_delay_us(1); + // } + // } else { + // // Timed out waiting for calibration + // break 0; + // } + }; + + timg0 + .rtccalicfg + .modify(|_, w| w.rtc_cali_start().clear_bit()); + + if cal_clk == RtcCalSel::RtcCal32kXtal && !dig_32k_xtal_enabled { + lp_clkrst + .clk_to_hp + .modify(|_, w| w.icg_hp_xtal32k().bit(dig_32k_xtal_enabled)); + } + + if cal_clk == RtcCalSel::RtcCalRcFast { + if !rc_fast_enabled { //TODO rtc_dig_clk8m_disable(); + pmu.hp_sleep_lp_ck_power.write(|w| w.hp_sleep_xpd_fosc_clk().set_bit()); + unsafe { + ets_delay_us(50); + } + } + + if !dig_rc_fast_enabled { //TODO rtc_dig_clk8m_disable(); + lp_clkrst.clk_to_hp.write(|w| w.icg_hp_fosc().set_bit()); + unsafe { + ets_delay_us(5); + } + } + } + + if cal_clk == RtcCalSel::RtcCal32kRc { + if !rc32k_enabled { + pmu.hp_sleep_lp_ck_power.write(|w| w.hp_sleep_xpd_rc32k().set_bit()); + unsafe { + ets_delay_us(300); + } + } + if !dig_rc32k_enabled { + lp_clkrst.clk_to_hp.write(|w| w.icg_hp_osc32k().set_bit()); + } + } + + // if matches!(cal_clk, RtcCalSel::RtcCal8mD256) { + // rtc_cntl + // .clk_conf + // .modify(|_, w| w.dig_clk8m_d256_en().clear_bit()); + // } + + cal_val + } + + /// Measure ratio between XTAL frequency and RTC slow clock frequency fn get_calibration_ratio(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { let xtal_cycles = RtcClock::calibrate_internal(cal_clk, slowclk_cycles) as u64; @@ -423,7 +779,10 @@ impl RtcClock { match RtcClock::get_slow_freq() { RtcSlowClock::RtcSlowClockRtc => RtcCalSel::RtcCalRtcMux, RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, + #[cfg(not(esp32c6))] RtcSlowClock::RtcSlowClock8mD256 => RtcCalSel::RtcCal8mD256, + #[cfg(esp32c6)] + RtcSlowClock::RtcCalRcFast => RtcCalSel::RtcCalRcFast, }, 1024, ); @@ -434,6 +793,7 @@ impl RtcClock { (100_000_000 * 1000 / period) as u16 } + #[cfg(not(esp32c6))] fn estimate_xtal_frequency() -> u32 { // Number of 8M/256 clock cycles to use for XTAL frequency estimation. const XTAL_FREQ_EST_CYCLES: u32 = 10; @@ -456,7 +816,7 @@ impl RtcClock { freq_mhz } } - +} /// Behavior of the RWDT stage if it times out #[allow(unused)] #[derive(Debug, Clone, Copy)] diff --git a/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs b/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs new file mode 100644 index 00000000000..5d0639783c4 --- /dev/null +++ b/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs @@ -0,0 +1,289 @@ +use paste::paste; +use strum::FromRepr; + +use crate::{ + clock::XtalClock, + peripherals::{EXTMEM, SPI0, SPI1, PCR, LP_AON, PMU}, + regi2c_write_mask, + rom::rom_i2c_writeReg_Mask, + rtc_cntl::{RtcCalSel, RtcClock, RtcFastClock, RtcSlowClock}, +}; + +const I2C_DIG_REG: u32 = 0x6d; +const I2C_DIG_REG_HOSTID: u32 = 0; + +const I2C_ULP: u32 = 0x61; +const I2C_ULP_HOSTID: u32 = 0; + +const I2C_DIG_REG_XPD_RTC_REG: u32 = 13; +const I2C_DIG_REG_XPD_RTC_REG_MSB: u32 = 2; +const I2C_DIG_REG_XPD_RTC_REG_LSB: u32 = 2; + +const I2C_DIG_REG_XPD_DIG_REG: u32 = 13; +const I2C_DIG_REG_XPD_DIG_REG_MSB: u32 = 3; +const I2C_DIG_REG_XPD_DIG_REG_LSB: u32 = 3; + +const I2C_ULP_IR_FORCE_XPD_CK: u32 = 0; +const I2C_ULP_IR_FORCE_XPD_CK_MSB: u32 = 2; +const I2C_ULP_IR_FORCE_XPD_CK_LSB: u32 = 2; + +const I2C_DIG_REG_ENIF_RTC_DREG: u32 = 5; +const I2C_DIG_REG_ENIF_RTC_DREG_MSB: u32 = 7; +const I2C_DIG_REG_ENIF_RTC_DREG_LSB: u32 = 7; + +const I2C_DIG_REG_ENIF_DIG_DREG:u32 = 7; +const I2C_DIG_REG_ENIF_DIG_DREG_MSB:u32 = 7; +const I2C_DIG_REG_ENIF_DIG_DREG_LSB:u32 = 7; + +pub(crate) fn init() { + let pmu = unsafe { &*PMU::ptr() }; + + /* + SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB); + SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C); + + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); + REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, 25); + REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, 26); + */ + + pmu.rf_pwc.modify(|_, w| + w.perif_i2c_rstb().set_bit(). + xpd_perif_i2c().set_bit()); + + unsafe { + // crate::clock::clocks_ll::regi2c_write_mask(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); use i2c macro from C6 clock + regi2c_write_mask!(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); + regi2c_write_mask!(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1); + + regi2c_write_mask!(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); + regi2c_write_mask!(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); + + pmu.hp_active_hp_regulator0.modify(|_, w| + w.hp_active_hp_regulator_dbias().bits(25)); + pmu.hp_sleep_lp_regulator0.modify(|_, w| + w.hp_sleep_lp_regulator_dbias().bits(26)); + + } +} + +pub(crate) fn configure_clock() { + assert!(matches!( + RtcClock::get_xtal_freq(), + XtalClock::RtcXtalFreq40M + )); + + RtcClock::set_fast_freq(RtcFastClock::RtcFastClock8m); + + let cal_val = loop { + RtcClock::set_slow_freq(RtcSlowClock::RtcSlowClockRtc); + + let res = RtcClock::calibrate(RtcCalSel::RtcCalRtcMux, 1024); + if res != 0 { + break res; + } + }; + + unsafe { + let lp_aon = &*LP_AON::ptr(); + lp_aon.store1.write(|w| w.bits(cal_val)); + } +} + +fn calibrate_ocode() {} + +fn set_rtc_dig_dbias() {} + +/// Perform clock control related initialization +// fn clock_control_init() { +// let extmem = unsafe { &*EXTMEM::ptr() }; +// let spi_mem_0 = unsafe { &*SPI0::ptr() }; +// let spi_mem_1 = unsafe { &*SPI1::ptr() }; + +// // Clear CMMU clock force on +// extmem +// .cache_mmu_power_ctrl +// .modify(|_, w| w.cache_mmu_mem_force_on().clear_bit()); + +// // Clear tag clock force on +// extmem +// .icache_tag_power_ctrl +// .modify(|_, w| w.icache_tag_mem_force_on().clear_bit()); + +// // Clear register clock force on +// spi_mem_0.clock_gate.modify(|_, w| w.clk_en().clear_bit()); +// spi_mem_1.clock_gate.modify(|_, w| w.clk_en().clear_bit()); +// } + +/// Perform power control related initialization +// fn power_control_init() { +// let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; +// let pcr = unsafe { &*PCR::ptr() }; +// rtc_cntl +// .clk_conf +// .modify(|_, w| w.ck8m_force_pu().clear_bit()); + +// // Cancel XTAL force PU if no need to force power up +// // Cannot cancel XTAL force PU if PLL is force power on +// rtc_cntl +// .options0 +// .modify(|_, w| w.xtl_force_pu().clear_bit()); + +// // Force PD APLL +// rtc_cntl.ana_conf.modify(|_, w| { +// w.plla_force_pu() +// .clear_bit() +// .plla_force_pd() +// .set_bit() +// // Open SAR_I2C protect function to avoid SAR_I2C +// // Reset when rtc_ldo is low. +// .reset_por_force_pd() +// .clear_bit() +// }); + +// // Cancel BBPLL force PU if setting no force power up +// rtc_cntl.options0.modify(|_, w| { +// w.bbpll_force_pu() +// .clear_bit() +// .bbpll_i2c_force_pu() +// .clear_bit() +// .bb_i2c_force_pu() +// .clear_bit() +// }); +// rtc_cntl.rtc_cntl.modify(|_, w| { +// w.regulator_force_pu() +// .clear_bit() +// .dboost_force_pu() +// .clear_bit() +// .dboost_force_pd() +// .set_bit() +// }); + +// // If this mask is enabled, all soc memories cannot enter power down mode. +// // We should control soc memory power down mode from RTC, +// // so we will not touch this register any more. +// pcr +// .mem_pd_mask +// .modify(|_, w| w.lslp_mem_pd_mask().clear_bit()); + +// rtc_sleep_pu(); + +// rtc_cntl.dig_pwc.modify(|_, w| { +// w.dg_wrap_force_pu() +// .clear_bit() +// .wifi_force_pu() +// .clear_bit() +// .bt_force_pu() +// .clear_bit() +// .cpu_top_force_pu() +// .clear_bit() +// .dg_peri_force_pu() +// .clear_bit() +// }); +// rtc_cntl.dig_iso.modify(|_, w| { +// w.dg_wrap_force_noiso() +// .clear_bit() +// .wifi_force_noiso() +// .clear_bit() +// .bt_force_noiso() +// .clear_bit() +// .cpu_top_force_noiso() +// .clear_bit() +// .dg_peri_force_noiso() +// .clear_bit() +// }); + +// // Cancel digital PADS force no iso +// system +// .cpu_per_conf +// .modify(|_, w| w.cpu_wait_mode_force_on().clear_bit()); + +// // If SYSTEM_CPU_WAIT_MODE_FORCE_ON == 0, +// // the CPU clock will be closed when CPU enter WAITI mode. +// rtc_cntl.dig_iso.modify(|_, w| { +// w.dg_pad_force_unhold() +// .clear_bit() +// .dg_pad_force_noiso() +// .clear_bit() +// }); +// } + +/// Configure whether certain peripherals are powered down in deep sleep +// fn rtc_sleep_pu() { +// let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; +// let apb_ctrl = unsafe { &*APB_CTRL::ptr() }; + +// rtc_cntl.dig_pwc.modify(|_, w| { +// w.lslp_mem_force_pu() +// .clear_bit() +// .fastmem_force_lpu() +// .clear_bit() +// }); + +// apb_ctrl.front_end_mem_pd.modify(|_, w| { +// w.dc_mem_force_pu() +// .clear_bit() +// .pbus_mem_force_pu() +// .clear_bit() +// .agc_mem_force_pu() +// .clear_bit() +// }); +// apb_ctrl +// .mem_power_up +// .modify(|_, w| unsafe { w.sram_power_up().bits(0u8).rom_power_up().bits(0u8) }); +// } + +// Terminology: +// +// CPU Reset: Reset CPU core only, once reset done, CPU will execute from +// reset vector +// Core Reset: Reset the whole digital system except RTC sub-system +// System Reset: Reset the whole digital system, including RTC sub-system +// Chip Reset: Reset the whole chip, including the analog part + +#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr)] +pub enum SocResetReason { + /// Power on reset + /// + /// In ESP-IDF this value (0x01) can *also* be `ChipBrownOut` or + /// `ChipSuperWdt`, however that is not really compatible with Rust-style + /// enums. + ChipPowerOn = 0x01, + /// Software resets the digital core by RTC_CNTL_SW_SYS_RST + CoreSw = 0x03, + /// Deep sleep reset the digital core + CoreDeepSleep = 0x05, + /// SDIO Core reset + CoreSDIO = 0x06, + /// Main watch dog 0 resets digital core + CoreMwdt0 = 0x07, + /// Main watch dog 1 resets digital core + CoreMwdt1 = 0x08, + /// RTC watch dog resets digital core + CoreRtcWdt = 0x09, + /// Main watch dog 0 resets CPU 0 + Cpu0Mwdt0 = 0x0B, + /// Software resets CPU 0 by RTC_CNTL_SW_PROCPU_RST + Cpu0Sw = 0x0C, + /// RTC watch dog resets CPU 0 + Cpu0RtcWdt = 0x0D, + /// VDD voltage is not stable and resets the digital core + SysBrownOut = 0x0F, + /// RTC watch dog resets digital core and rtc module + SysRtcWdt = 0x10, + /// Main watch dog 1 resets CPU 0 + Cpu0Mwdt1 = 0x11, + /// Super watch dog resets the digital core and rtc module + SysSuperWdt = 0x12, + /// eFuse CRC error resets the digital core + CoreEfuseCrc = 0x14, + /// USB UART resets the digital core + CoreUsbUart = 0x15, + /// USB JTAG resets the digital core + CoreUsbJtag = 0x16, + /// JTAG resets CPU + Cpu0JtagCpu = 0x18, +} From 988b1d02e7ee49f4980bd094b38eb6b2f25e64bd Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Thu, 2 Feb 2023 14:02:48 +0100 Subject: [PATCH 24/64] Implement RWDT and SWD disable --- esp-hal-common/src/clock/clocks_ll/esp32c6.rs | 4 +- esp-hal-common/src/clock/mod.rs | 2 +- esp-hal-common/src/rtc_cntl/mod.rs | 152 ++++++++++++++++-- esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs | 74 ++++----- esp32c6-hal/examples/blinky.rs | 11 +- esp32c6-hal/src/lib.rs | 1 + 6 files changed, 193 insertions(+), 51 deletions(-) diff --git a/esp-hal-common/src/clock/clocks_ll/esp32c6.rs b/esp-hal-common/src/clock/clocks_ll/esp32c6.rs index 322dfd00dc5..9e4e65a4e4b 100644 --- a/esp-hal-common/src/clock/clocks_ll/esp32c6.rs +++ b/esp-hal-common/src/clock/clocks_ll/esp32c6.rs @@ -457,7 +457,7 @@ fn regi2c_disable_block(block: u8) { } } -fn regi2c_write(block: u8, host_id: u8, reg_add: u8, data: u8) { +pub(crate) fn regi2c_write(block: u8, host_id: u8, reg_add: u8, data: u8) { regi2c_enable_block(block); let temp: u32 = ((block as u32 & REGI2C_RTC_SLAVE_ID_V as u32) << REGI2C_RTC_SLAVE_ID_S as u32) @@ -470,7 +470,7 @@ fn regi2c_write(block: u8, host_id: u8, reg_add: u8, data: u8) { regi2c_disable_block(block); } -fn regi2c_write_mask(block: u8, host_id: u8, reg_add: u8, msb: u8, lsb: u8, data: u8) { +pub(crate) fn regi2c_write_mask(block: u8, host_id: u8, reg_add: u8, msb: u8, lsb: u8, data: u8) { assert!(msb - lsb < 8); regi2c_enable_block(block); diff --git a/esp-hal-common/src/clock/mod.rs b/esp-hal-common/src/clock/mod.rs index 7252b7637af..8475da20ea1 100644 --- a/esp-hal-common/src/clock/mod.rs +++ b/esp-hal-common/src/clock/mod.rs @@ -12,7 +12,7 @@ use crate::{ #[cfg_attr(esp32c6, path = "clocks_ll/esp32c6.rs")] #[cfg_attr(esp32s2, path = "clocks_ll/esp32s2.rs")] #[cfg_attr(esp32s3, path = "clocks_ll/esp32s3.rs")] -mod clocks_ll; +pub(crate) mod clocks_ll; pub trait Clock { fn frequency(&self) -> HertzU32; diff --git a/esp-hal-common/src/rtc_cntl/mod.rs b/esp-hal-common/src/rtc_cntl/mod.rs index 3cafd5904a9..cacd60d9ac1 100644 --- a/esp-hal-common/src/rtc_cntl/mod.rs +++ b/esp-hal-common/src/rtc_cntl/mod.rs @@ -14,7 +14,13 @@ use crate::{ #[cfg(not(esp32c6))] use crate::peripherals::RTC_CNTL; #[cfg(esp32c6)] -use crate::peripherals::{LP_CLKRST, LP_AON, PCR, PMU}; +use crate::peripherals::{LP_CLKRST, LP_AON, PCR, PMU, LP_WDT}; + +#[cfg(not(esp32c6))] +type RTC_PERIPHERAL = RTC_CNTL; + +#[cfg(esp32c6)] +type RTC_PERIPHERAL = LP_CLKRST; #[cfg_attr(esp32, path = "rtc/esp32.rs")] #[cfg_attr(esp32c2, path = "rtc/esp32c2.rs")] @@ -46,7 +52,7 @@ impl Clock for RtcFastClock { RtcFastClock::RtcFastClockXtalD4 => HertzU32::Hz(40_000_000 / 4), #[cfg(any(esp32, esp32s2))] RtcFastClock::RtcFastClock8m => HertzU32::Hz(8_500_000), - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32s3, esp32c6))] RtcFastClock::RtcFastClock8m => HertzU32::Hz(17_500_000), } } @@ -97,7 +103,10 @@ impl Clock for RtcSlowClock { RtcSlowClock::RtcSlowClock8mD256 => HertzU32::Hz(17_500_000 / 256), #[cfg(esp32c6)] RtcSlowClock::RtcCalRcFast => HertzU32::Hz(17_500_00), - + #[cfg(esp32c6)] + RtcSlowClock::RtcSlowClock32kRc => HertzU32::Hz(17_500_00), // ?? + #[cfg(esp32c6)] + RtcSlowClock::RtcCalInternalOsc => HertzU32::Hz(17_500_00), // ?? } } } @@ -145,25 +154,26 @@ pub(crate) enum RtcCaliClkSel { } pub struct Rtc<'d> { - _inner: PeripheralRef<'d, RTC_CNTL>, + _inner: PeripheralRef<'d, RTC_PERIPHERAL>, pub rwdt: Rwdt, - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32s3, esp32c6))] pub swd: Swd, } impl<'d> Rtc<'d> { - pub fn new(rtc_cntl: impl Peripheral

+ 'd) -> Self { + pub fn new(rtc_cntl: impl Peripheral

+ 'd) -> Self { rtc::init(); rtc::configure_clock(); Self { _inner: rtc_cntl.into_ref(), rwdt: Rwdt::default(), - #[cfg(any(esp32c2, esp32c3, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32s3, esp32c6))] swd: Swd::new(), } } + #[cfg(not(esp32c6))] pub fn estimate_xtal_frequency(&mut self) -> u32 { RtcClock::estimate_xtal_frequency() } @@ -281,8 +291,8 @@ impl RtcClock { /// Get the RTC_SLOW_CLK source #[cfg(esp32c6)] fn get_slow_freq() -> RtcSlowClock { - let lp_clrst = &*LP_CLKRST::ptr(); - let pcr = &*PCR::ptr(); + let lp_clrst = unsafe { &*LP_CLKRST::ptr() }; + let pcr = unsafe { &*PCR::ptr() }; let slow_freq = lp_clrst.lp_clk_conf.read().slow_clk_sel().bits(); match slow_freq { @@ -294,7 +304,13 @@ impl RtcClock { } } + #[cfg(esp32c6)] + fn set_slow_freq(slow_freq: RtcSlowClock) { + todo!() + } + /// Select source for RTC_SLOW_CLK + #[cfg(not(esp32c6))] fn set_slow_freq(slow_freq: RtcSlowClock) { unsafe { let rtc_cntl = &*RTC_CNTL::ptr(); @@ -847,6 +863,7 @@ impl Default for Rwdt { } } +#[cfg(not(esp32c6))] /// RTC Watchdog Timer driver impl Rwdt { pub fn listen(&mut self) { @@ -927,6 +944,7 @@ impl Rwdt { } } +#[cfg(not(esp32c6))] impl WatchdogDisable for Rwdt { fn disable(&mut self) { let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; @@ -941,6 +959,7 @@ impl WatchdogDisable for Rwdt { } } +#[cfg(not(esp32c6))] impl WatchdogEnable for Rwdt { type Time = MicrosDurationU64; @@ -987,6 +1006,7 @@ impl WatchdogEnable for Rwdt { } } +#[cfg(not(esp32c6))] impl Watchdog for Rwdt { fn feed(&mut self) { let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; @@ -999,7 +1019,88 @@ impl Watchdog for Rwdt { } } -#[cfg(any(esp32c2, esp32c3, esp32s3))] + +#[cfg(any(esp32c6))] +/// RTC Watchdog Timer driver +impl Rwdt { + pub fn listen(&mut self) { + let rtc_cntl = unsafe { &*LP_WDT::ptr() }; + + self.stg0_action = RwdtStageAction::RwdtStageActionInterrupt; + + self.set_write_protection(false); + + // Configure STAGE0 to trigger an interrupt upon expiration + rtc_cntl + .config0 + .modify(|_, w| unsafe { w.wdt_stg0().bits(self.stg0_action as u8) }); + + rtc_cntl + .int_ena + .modify(|_, w| w.lp_wdt_int_ena().set_bit()); + + self.set_write_protection(true); + } + + pub fn unlisten(&mut self) { + let rtc_cntl = unsafe { &*LP_WDT::ptr() }; + + self.stg0_action = RwdtStageAction::RwdtStageActionResetRtc; + + self.set_write_protection(false); + + // Configure STAGE0 to reset the main system and the RTC upon expiration. + rtc_cntl + .config0 + .modify(|_, w| unsafe { w.wdt_stg0().bits(self.stg0_action as u8) }); + + rtc_cntl + .int_ena + .modify(|_, w| w.lp_wdt_int_ena().clear_bit()); + + self.set_write_protection(true); + } + + pub fn clear_interrupt(&mut self) { + let rtc_cntl = unsafe { &*LP_WDT::ptr() }; + + self.set_write_protection(false); + + rtc_cntl.int_clr.write(|w| w.lp_wdt_int_clr().set_bit()); + + self.set_write_protection(true); + } + + pub fn is_interrupt_set(&self) -> bool { + let rtc_cntl = unsafe { &*LP_WDT::ptr() }; + rtc_cntl.int_st.read().lp_wdt_int_st().bit_is_set() + } + + /// Enable/disable write protection for WDT registers + fn set_write_protection(&mut self, enable: bool) { + let rtc_cntl = unsafe { &*LP_WDT::ptr() }; + let wkey = if enable { 0u32 } else { 0x50D8_3AA1 }; + + rtc_cntl.wprotect.write(|w| unsafe { w.bits(wkey) }); + } +} + +#[cfg(esp32c6)] +impl WatchdogDisable for Rwdt { + fn disable(&mut self) { + let rtc_cntl = unsafe { &*LP_WDT::ptr() }; + + self.set_write_protection(false); + + rtc_cntl + .config0 + .modify(|_, w| w.wdt_en().clear_bit().wdt_flashboot_mod_en().clear_bit()); + + self.set_write_protection(true); + } +} + +#[cfg(any(esp32c2, esp32c3, esp32s3, esp32c6))] /// Super Watchdog pub struct Swd; @@ -1034,6 +1135,37 @@ impl WatchdogDisable for Swd { } } +#[cfg(esp32c6)] +impl Swd { + pub fn new() -> Self { + Self + } + + /// Enable/disable write protection for WDT registers + fn set_write_protection(&mut self, enable: bool) { + let rtc_cntl = unsafe { &*LP_WDT::ptr() }; + let wkey = if enable { 0u32 } else { 0x8F1D_312A }; + let wkey = if enable { 0u32 } else { 0x50D8_3AA1 }; + + rtc_cntl + .swd_wprotect + .write(|w| unsafe { w.swd_wkey().bits(wkey) }); + } +} + +#[cfg(any(esp32c6))] +impl WatchdogDisable for Swd { + fn disable(&mut self) { + let rtc_cntl = unsafe { &*LP_WDT::ptr() }; + + self.set_write_protection(false); + + rtc_cntl.swd_config.write(|w| w.swd_auto_feed_en().set_bit()); + + self.set_write_protection(true); + } +} + pub fn get_reset_reason(cpu: Cpu) -> Option { let reason = unsafe { rtc_get_reset_reason(cpu as u32) }; let reason = SocResetReason::from_repr(reason as usize); diff --git a/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs b/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs index 5d0639783c4..503ec47f2bc 100644 --- a/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs +++ b/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs @@ -4,36 +4,36 @@ use strum::FromRepr; use crate::{ clock::XtalClock, peripherals::{EXTMEM, SPI0, SPI1, PCR, LP_AON, PMU}, - regi2c_write_mask, - rom::rom_i2c_writeReg_Mask, rtc_cntl::{RtcCalSel, RtcClock, RtcFastClock, RtcSlowClock}, + clock::clocks_ll::regi2c_write, + clock::clocks_ll::regi2c_write_mask, }; -const I2C_DIG_REG: u32 = 0x6d; -const I2C_DIG_REG_HOSTID: u32 = 0; +const I2C_DIG_REG: u8 = 0x6d; +const I2C_DIG_REG_HOSTID: u8 = 0; -const I2C_ULP: u32 = 0x61; -const I2C_ULP_HOSTID: u32 = 0; +const I2C_ULP: u8 = 0x61; +const I2C_ULP_HOSTID: u8 = 0; -const I2C_DIG_REG_XPD_RTC_REG: u32 = 13; -const I2C_DIG_REG_XPD_RTC_REG_MSB: u32 = 2; -const I2C_DIG_REG_XPD_RTC_REG_LSB: u32 = 2; +const I2C_DIG_REG_XPD_RTC_REG: u8 = 13; +const I2C_DIG_REG_XPD_RTC_REG_MSB: u8 = 2; +const I2C_DIG_REG_XPD_RTC_REG_LSB: u8 = 2; -const I2C_DIG_REG_XPD_DIG_REG: u32 = 13; -const I2C_DIG_REG_XPD_DIG_REG_MSB: u32 = 3; -const I2C_DIG_REG_XPD_DIG_REG_LSB: u32 = 3; +const I2C_DIG_REG_XPD_DIG_REG: u8 = 13; +const I2C_DIG_REG_XPD_DIG_REG_MSB: u8 = 3; +const I2C_DIG_REG_XPD_DIG_REG_LSB: u8 = 3; -const I2C_ULP_IR_FORCE_XPD_CK: u32 = 0; -const I2C_ULP_IR_FORCE_XPD_CK_MSB: u32 = 2; -const I2C_ULP_IR_FORCE_XPD_CK_LSB: u32 = 2; +const I2C_ULP_IR_FORCE_XPD_CK: u8 = 0; +const I2C_ULP_IR_FORCE_XPD_CK_MSB: u8 = 2; +const I2C_ULP_IR_FORCE_XPD_CK_LSB: u8 = 2; -const I2C_DIG_REG_ENIF_RTC_DREG: u32 = 5; -const I2C_DIG_REG_ENIF_RTC_DREG_MSB: u32 = 7; -const I2C_DIG_REG_ENIF_RTC_DREG_LSB: u32 = 7; +const I2C_DIG_REG_ENIF_RTC_DREG: u8 = 5; +const I2C_DIG_REG_ENIF_RTC_DREG_MSB: u8 = 7; +const I2C_DIG_REG_ENIF_RTC_DREG_LSB: u8 = 7; -const I2C_DIG_REG_ENIF_DIG_DREG:u32 = 7; -const I2C_DIG_REG_ENIF_DIG_DREG_MSB:u32 = 7; -const I2C_DIG_REG_ENIF_DIG_DREG_LSB:u32 = 7; +const I2C_DIG_REG_ENIF_DIG_DREG:u8 = 7; +const I2C_DIG_REG_ENIF_DIG_DREG_MSB:u8 = 7; +const I2C_DIG_REG_ENIF_DIG_DREG_LSB:u8 = 7; pub(crate) fn init() { let pmu = unsafe { &*PMU::ptr() }; @@ -56,11 +56,11 @@ pub(crate) fn init() { unsafe { // crate::clock::clocks_ll::regi2c_write_mask(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); use i2c macro from C6 clock - regi2c_write_mask!(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); - regi2c_write_mask!(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1); + regi2c_write_mask(I2C_DIG_REG, I2C_DIG_REG_HOSTID, I2C_DIG_REG_ENIF_RTC_DREG, I2C_DIG_REG_ENIF_RTC_DREG_MSB, I2C_DIG_REG_ENIF_RTC_DREG_LSB, 1); + regi2c_write_mask(I2C_DIG_REG, I2C_DIG_REG_HOSTID, I2C_DIG_REG_ENIF_DIG_DREG, I2C_DIG_REG_ENIF_DIG_DREG_MSB, I2C_DIG_REG_ENIF_DIG_DREG_LSB, 1); - regi2c_write_mask!(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); - regi2c_write_mask!(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); + regi2c_write_mask(I2C_DIG_REG, I2C_DIG_REG_HOSTID, I2C_DIG_REG_XPD_RTC_REG, I2C_DIG_REG_XPD_RTC_REG_MSB, I2C_DIG_REG_XPD_RTC_REG_LSB, 0); + regi2c_write_mask(I2C_DIG_REG, I2C_DIG_REG_HOSTID, I2C_DIG_REG_XPD_DIG_REG, I2C_DIG_REG_XPD_DIG_REG_MSB, I2C_DIG_REG_XPD_DIG_REG_LSB, 0); pmu.hp_active_hp_regulator0.modify(|_, w| w.hp_active_hp_regulator_dbias().bits(25)); @@ -76,21 +76,21 @@ pub(crate) fn configure_clock() { XtalClock::RtcXtalFreq40M )); - RtcClock::set_fast_freq(RtcFastClock::RtcFastClock8m); + // RtcClock::set_fast_freq(RtcFastClock::RtcFastClock8m); - let cal_val = loop { - RtcClock::set_slow_freq(RtcSlowClock::RtcSlowClockRtc); + // let cal_val = loop { + // RtcClock::set_slow_freq(RtcSlowClock::RtcSlowClockRtc); - let res = RtcClock::calibrate(RtcCalSel::RtcCalRtcMux, 1024); - if res != 0 { - break res; - } - }; + // let res = RtcClock::calibrate(RtcCalSel::RtcCalRtcMux, 1024); + // if res != 0 { + // break res; + // } + // }; - unsafe { - let lp_aon = &*LP_AON::ptr(); - lp_aon.store1.write(|w| w.bits(cal_val)); - } + // unsafe { + // let lp_aon = &*LP_AON::ptr(); + // lp_aon.store1.write(|w| w.bits(cal_val)); + // } } fn calibrate_ocode() {} diff --git a/esp32c6-hal/examples/blinky.rs b/esp32c6-hal/examples/blinky.rs index f7bc1768081..eb5bfe0127f 100644 --- a/esp32c6-hal/examples/blinky.rs +++ b/esp32c6-hal/examples/blinky.rs @@ -12,11 +12,11 @@ use esp32c6_hal::{ prelude::*, timer::TimerGroup, Delay, + Rtc, }; use esp_backtrace as _; use esp_riscv_rt::entry; - #[entry] fn main() -> ! { let peripherals = Peripherals::take(); @@ -28,6 +28,10 @@ fn main() -> ! { let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); let mut wdt1 = timer_group1.wdt; + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + rtc.rwdt.disable(); + rtc.swd.disable(); + // Set GPIO5 as an output, and set its state high initially. let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); let mut led = io.pins.gpio5.into_push_pull_output(); @@ -38,7 +42,12 @@ fn main() -> ! { // loop. let mut delay = Delay::new(&clocks); + // just for testing ... remove this + let rst_reason = unsafe { (0x600b0410 as *mut u32).read_volatile() & 0b11111 }; + esp_println::println!("raw rst reason {} 0x{:x}", rst_reason, rst_reason); + loop { + esp_println::println!("blinky"); led.toggle().unwrap(); delay.delay_ms(2000u32); } diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index 7c9b3b06049..763869b3515 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -25,6 +25,7 @@ pub use esp_hal_common::{ PulseControl, utils, Uart, + Rtc, }; pub use self::gpio::IO; From ac4c4475774154f0e9a38846657a3486105e5d2c Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Fri, 3 Feb 2023 14:07:08 +0100 Subject: [PATCH 25/64] C6: working LEDC --- esp-hal-common/src/ledc/mod.rs | 11 ++++++++++- esp-hal-common/src/ledc/timer.rs | 1 - 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/esp-hal-common/src/ledc/mod.rs b/esp-hal-common/src/ledc/mod.rs index 003971618fa..f0cf2ef0c59 100644 --- a/esp-hal-common/src/ledc/mod.rs +++ b/esp-hal-common/src/ledc/mod.rs @@ -133,9 +133,18 @@ impl<'d> LEDC<'d> { #[cfg(not(esp32))] /// Set global slow clock source pub fn set_global_slow_clock(&mut self, clock_source: LSGlobalClkSource) { + #[cfg(esp32c6)] + let pcr = unsafe { &*crate::peripherals::PCR::ptr() }; + + #[cfg(esp32c6)] + pcr.ledc_sclk_conf.write(|w| w.ledc_sclk_en().set_bit()); + match clock_source { LSGlobalClkSource::APBClk => { - self.ledc.conf.write(|w| unsafe { w.apb_clk_sel().bits(1) }) + #[cfg(not(esp32c6))] + self.ledc.conf.write(|w| unsafe { w.apb_clk_sel().bits(1) }); + #[cfg(esp32c6)] + pcr.ledc_sclk_conf.write(|w| unsafe { w.ledc_sclk_sel().bits(1) }); } } self.ledc.timer0_conf.modify(|_, w| w.para_up().set_bit()); diff --git a/esp-hal-common/src/ledc/timer.rs b/esp-hal-common/src/ledc/timer.rs index 0a942304084..3e86587b8ea 100644 --- a/esp-hal-common/src/ledc/timer.rs +++ b/esp-hal-common/src/ledc/timer.rs @@ -171,7 +171,6 @@ where return Err(Error::Divisor); } - esp_println::println!("{src_freq}, {frequency}, {divisor}"); self.configure_hw(divisor as u32); self.update_hw(); From 8ddaf7efa8925564ec327c26900be5e4a5d3f78a Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Fri, 3 Feb 2023 14:07:25 +0100 Subject: [PATCH 26/64] C6: working RMT --- esp-hal-common/src/pulse_control.rs | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/esp-hal-common/src/pulse_control.rs b/esp-hal-common/src/pulse_control.rs index fb6c66a6274..6baf086b14c 100644 --- a/esp-hal-common/src/pulse_control.rs +++ b/esp-hal-common/src/pulse_control.rs @@ -93,6 +93,9 @@ use crate::{ system::PeripheralClockControl, }; +#[cfg(esp32c6)] +use crate::peripherals::PCR; + /// Errors that can occur when the peripheral is configured #[derive(Debug)] pub enum SetupError { @@ -927,6 +930,14 @@ macro_rules! rmt { // addressed! // Configure peripheral + + #[cfg(esp32c6)] + let pcr = unsafe { &*PCR::ptr() }; + + #[cfg(esp32c6)] + pcr.rmt_sclk_conf.write(|w| w.sclk_en().set_bit()); + + self.reg.sys_conf.modify(|_, w| unsafe { // Enable clock w.clk_en() @@ -942,9 +953,23 @@ macro_rules! rmt { .clear_bit() // Disable FIFO mode .apb_fifo_mask() - .set_bit() + .set_bit() }); // Select clock source - .sclk_sel() + #[cfg(not(esp32c6))] + self.reg.sys_conf.modify(|_, w| unsafe { + w.sclk_sel() + .bits(clk_source as u8) + // Set absolute part of divider + .sclk_div_num() + .bits(div_abs) + // Set fractional parts of divider to 0 + .sclk_div_a() + .bits(div_frac_a) + .sclk_div_b() + .bits(div_frac_b) }); + #[cfg(esp32c6)] + pcr.rmt_sclk_conf.modify(|_,w| unsafe { + w.sclk_sel() .bits(clk_source as u8) // Set absolute part of divider .sclk_div_num() From 2b7fd7d682812f00df520fda45540e4539407343 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Tue, 7 Feb 2023 17:53:53 +0100 Subject: [PATCH 27/64] C6: add aes --- esp-hal-common/src/aes/{esp32c3.rs => esp32cX.rs} | 2 +- esp-hal-common/src/aes/mod.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) rename esp-hal-common/src/aes/{esp32c3.rs => esp32cX.rs} (99%) diff --git a/esp-hal-common/src/aes/esp32c3.rs b/esp-hal-common/src/aes/esp32cX.rs similarity index 99% rename from esp-hal-common/src/aes/esp32c3.rs rename to esp-hal-common/src/aes/esp32cX.rs index e0bc104a23e..3142d1fe6a4 100644 --- a/esp-hal-common/src/aes/esp32c3.rs +++ b/esp-hal-common/src/aes/esp32cX.rs @@ -55,4 +55,4 @@ impl AesFlavour for Aes256 { type KeyType<'b> = &'b [u8; 32]; const ENCRYPT_MODE: u32 = 2; const DECRYPT_MODE: u32 = 6; -} +} \ No newline at end of file diff --git a/esp-hal-common/src/aes/mod.rs b/esp-hal-common/src/aes/mod.rs index 441915342a0..bb1d9e216f1 100644 --- a/esp-hal-common/src/aes/mod.rs +++ b/esp-hal-common/src/aes/mod.rs @@ -30,7 +30,8 @@ use crate::{ #[cfg_attr(esp32, path = "esp32.rs")] #[cfg_attr(esp32s3, path = "esp32s3.rs")] #[cfg_attr(esp32s2, path = "esp32s2.rs")] -#[cfg_attr(esp32c3, path = "esp32c3.rs")] +#[cfg_attr(esp32c3, path = "esp32cX.rs")] +#[cfg_attr(esp32c6, path = "esp32cX.rs")] mod aes_spec_impl; const ALIGN_SIZE: usize = core::mem::size_of::(); From b100cb2dd4a89e5099996beeb4f136f3f643cef3 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Tue, 7 Feb 2023 17:54:40 +0100 Subject: [PATCH 28/64] C6: add mcpwm --- esp-hal-common/src/mcpwm/mod.rs | 41 +++++++++++++++++---- esp-hal-common/src/mcpwm/operator.rs | 53 ++++++++++++++++++++++++++++ esp-hal-common/src/mcpwm/timer.rs | 44 ++++++++++++++++++++++- 3 files changed, 130 insertions(+), 8 deletions(-) diff --git a/esp-hal-common/src/mcpwm/mod.rs b/esp-hal-common/src/mcpwm/mod.rs index 48dcdd1e889..5e6bd851e4a 100644 --- a/esp-hal-common/src/mcpwm/mod.rs +++ b/esp-hal-common/src/mcpwm/mod.rs @@ -75,6 +75,16 @@ pub mod operator; /// MCPWM timers pub mod timer; +#[cfg(not(esp32c6))] +type RegisterBlock = crate::peripherals::pwm0::RegisterBlock; +#[cfg(esp32c6)] +type RegisterBlock = crate::peripherals::mcpwm::RegisterBlock; + +#[cfg(not(esp32c6))] +type PWM = crate::peripherals::PWM0; +#[cfg(esp32c6)] +type PWM = crate::peripherals::MCPWM; + /// The MCPWM peripheral #[non_exhaustive] pub struct MCPWM<'d, PWM> { @@ -106,12 +116,25 @@ impl<'d, PWM: PwmPeripheral> MCPWM<'d, PWM> { PWM::enable(system); // set prescaler + #[cfg(not(esp32c6))] peripheral .clk_cfg .write(|w| w.clk_prescale().variant(peripheral_clock.prescaler)); // enable clock + #[cfg(not(esp32c6))] peripheral.clk.write(|w| w.en().set_bit()); + #[cfg(esp32c6)] + let pcr = unsafe { &*crate::peripherals::PCR::ptr() }; + #[cfg(esp32c6)] + pcr.pwm_clk_conf + .write(|w| w.pwm_div_num().variant(peripheral_clock.prescaler)); + #[cfg(esp32c6)] + pcr.pwm_clk_conf.write(|w| w.pwm_clkm_en().set_bit()); + // TODO: Add other clock sources + #[cfg(esp32c6)] + pcr.pwm_clk_conf + .write(|w| unsafe { w.pwm_clkm_sel().bits(1) }); MCPWM { _inner: peripheral, timer0: Timer::new(), @@ -145,6 +168,8 @@ impl<'a> PeripheralClockConfig<'a> { let source_clock = clocks.pwm_clock; #[cfg(esp32s3)] let source_clock = clocks.crypto_pwm_clock; + #[cfg(esp32c6)] + let source_clock = clocks.crypto_clock; PeripheralClockConfig { frequency: source_clock / (prescaler as u32 + 1), @@ -175,6 +200,8 @@ impl<'a> PeripheralClockConfig<'a> { let source_clock = clocks.pwm_clock; #[cfg(esp32s3)] let source_clock = clocks.crypto_pwm_clock; + #[cfg(esp32c6)] + let source_clock = clocks.crypto_clock; if target_freq.raw() == 0 || target_freq > source_clock { return Err(FrequencyError); @@ -183,6 +210,7 @@ impl<'a> PeripheralClockConfig<'a> { if prescaler > u8::MAX as u32 { return Err(FrequencyError); } + esp_println::println!("{source_clock}, {target_freq}, {prescaler}"); Ok(Self::with_prescaler(clocks, prescaler as u8)) } @@ -237,23 +265,21 @@ impl<'a> PeripheralClockConfig<'a> { pub struct FrequencyError; /// A MCPWM peripheral -pub unsafe trait PwmPeripheral: - Deref -{ +pub unsafe trait PwmPeripheral: Deref { /// Enable peripheral fn enable(system: &mut PeripheralClockControl); /// Get a pointer to the peripheral RegisterBlock - fn block() -> *const crate::peripherals::pwm0::RegisterBlock; + fn block() -> *const RegisterBlock; /// Get operator GPIO mux output signal fn output_signal() -> OutputSignal; } -unsafe impl PwmPeripheral for crate::peripherals::PWM0 { +unsafe impl PwmPeripheral for PWM { fn enable(system: &mut PeripheralClockControl) { system.enable(PeripheralEnable::Mcpwm0) } - fn block() -> *const crate::peripherals::pwm0::RegisterBlock { + fn block() -> *const RegisterBlock { Self::ptr() } @@ -270,12 +296,13 @@ unsafe impl PwmPeripheral for crate::peripherals::PWM0 { } } +#[cfg(not(esp32c6))] unsafe impl PwmPeripheral for crate::peripherals::PWM1 { fn enable(system: &mut PeripheralClockControl) { system.enable(PeripheralEnable::Mcpwm1) } - fn block() -> *const crate::peripherals::pwm0::RegisterBlock { + fn block() -> *const RegisterBlock { Self::ptr() } diff --git a/esp-hal-common/src/mcpwm/operator.rs b/esp-hal-common/src/mcpwm/operator.rs index 5124bd99265..cad3cc01c75 100644 --- a/esp-hal-common/src/mcpwm/operator.rs +++ b/esp-hal-common/src/mcpwm/operator.rs @@ -223,6 +223,38 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> } } + /// Set how a new timestamp syncs with the timer + #[cfg(esp32c6)] + pub fn set_update_method(&mut self, update_method: PwmUpdateMethod) { + // SAFETY: + // We only write to our GENx_x_UPMETHOD register + let block = unsafe { &*PWM::block() }; + let bits = update_method.0; + match (OP, IS_A) { + (0, true) => block + .gen0_stmp_cfg + .modify(|_, w| w.cmpr0_a_upmethod().variant(bits)), + (1, true) => block + .gen1_stmp_cfg + .modify(|_, w| w.cmpr1_a_upmethod().variant(bits)), + (2, true) => block + .gen2_stmp_cfg + .modify(|_, w| w.cmpr2_a_upmethod().variant(bits)), + (0, false) => block + .gen0_stmp_cfg + .modify(|_, w| w.cmpr0_b_upmethod().variant(bits)), + (1, false) => block + .gen1_stmp_cfg + .modify(|_, w| w.cmpr1_b_upmethod().variant(bits)), + (2, false) => block + .gen2_stmp_cfg + .modify(|_, w| w.cmpr2_b_upmethod().variant(bits)), + _ => { + unreachable!() + } + } + } + /// Set how a new timestamp syncs with the timer. /// The written value will take effect according to the set /// [`PwmUpdateMethod`]. @@ -264,6 +296,27 @@ impl<'d, Pin: OutputPin, PWM: PwmPeripheral, const OP: u8, const IS_A: bool> } } } + + /// Write a new timestamp. + /// The written value will take effect according to the set + /// [`PwmUpdateMethod`]. + #[cfg(esp32c6)] + pub fn set_timestamp(&mut self, value: u16) { + // SAFETY: + // We only write to our GENx_TSTMP_x register + let block = unsafe { &*PWM::block() }; + match (OP, IS_A) { + (0, true) => block.gen0_tstmp_a.write(|w| w.cmpr0_a().variant(value)), + (1, true) => block.gen1_tstmp_a.write(|w| w.cmpr1_a().variant(value)), + (2, true) => block.gen2_tstmp_a.write(|w| w.cmpr2_a().variant(value)), + (0, false) => block.gen0_tstmp_b.write(|w| w.cmpr0_b().variant(value)), + (1, false) => block.gen1_tstmp_b.write(|w| w.cmpr1_b().variant(value)), + (2, false) => block.gen2_tstmp_b.write(|w| w.cmpr2_b().variant(value)), + _ => { + unreachable!() + } + } + } } /// An action the operator applies to an output diff --git a/esp-hal-common/src/mcpwm/timer.rs b/esp-hal-common/src/mcpwm/timer.rs index dbaa5ccbcfe..f3c5bcc0934 100644 --- a/esp-hal-common/src/mcpwm/timer.rs +++ b/esp-hal-common/src/mcpwm/timer.rs @@ -45,7 +45,7 @@ impl Timer { .timer0_period_upmethod() .variant(0) }); - + esp_println::println!("QQ: {} {}", timer_config.prescaler, timer_config.period); // set timer to continuously run and set the timer working mode self.cfg1().write(|w| { w.timer0_start() @@ -141,6 +141,7 @@ impl Timer { } } + #[cfg(not(esp32c6))] fn cfg0(&mut self) -> &crate::peripherals::pwm0::TIMER0_CFG0 { // SAFETY: // We only grant access to our CFG0 register with the lifetime of &mut self @@ -158,6 +159,8 @@ impl Timer { } } } + + #[cfg(not(esp32c6))] fn cfg1(&mut self) -> &crate::peripherals::pwm0::TIMER0_CFG1 { // SAFETY: // We only grant access to our CFG1 register with the lifetime of &mut self @@ -175,6 +178,44 @@ impl Timer { } } } + + #[cfg(esp32c6)] + fn cfg0(&mut self) -> &crate::peripherals::mcpwm::TIMER0_CFG0 { + // SAFETY: + // We only grant access to our CFG0 register with the lifetime of &mut self + let block = unsafe { &*PWM::block() }; + + // SAFETY: + // The CFG0 registers are identical for all timers so we can pretend they're + // TIMER0_CFG0 + match TIM { + 0 => &block.timer0_cfg0, + 1 => unsafe { &*(&block.timer1_cfg0 as *const _ as *const _) }, + 2 => unsafe { &*(&block.timer2_cfg0 as *const _ as *const _) }, + _ => { + unreachable!() + } + } + } + + #[cfg(esp32c6)] + fn cfg1(&mut self) -> &crate::peripherals::mcpwm::TIMER0_CFG1 { + // SAFETY: + // We only grant access to our CFG1 register with the lifetime of &mut self + let block = unsafe { &*PWM::block() }; + + // SAFETY: + // The CFG1 registers are identical for all timers so we can pretend they're + // TIMER0_CFG1 + match TIM { + 0 => &block.timer0_cfg1, + 1 => unsafe { &*(&block.timer1_cfg1 as *const _ as *const _) }, + 2 => unsafe { &*(&block.timer2_cfg1 as *const _ as *const _) }, + _ => { + unreachable!() + } + } + } } /// Clock configuration of a MCPWM timer @@ -237,6 +278,7 @@ impl<'a> TimerClockConfig<'a> { } let frequency = clock.frequency / (prescaler + 1) / cycle_period; + esp_println::println!("{target_timer_frequency} {target_freq} {prescaler}"); Ok(TimerClockConfig { frequency, prescaler: prescaler as u8, From 9968157a95288df42900f2686f20676547705299 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Tue, 7 Feb 2023 17:56:56 +0100 Subject: [PATCH 29/64] C6: add rtc_cntln - not finished --- esp-hal-common/src/rtc_cntl/mod.rs | 908 +++++++++++---------- esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs | 104 ++- 2 files changed, 544 insertions(+), 468 deletions(-) diff --git a/esp-hal-common/src/rtc_cntl/mod.rs b/esp-hal-common/src/rtc_cntl/mod.rs index cacd60d9ac1..30d162df92b 100644 --- a/esp-hal-common/src/rtc_cntl/mod.rs +++ b/esp-hal-common/src/rtc_cntl/mod.rs @@ -4,18 +4,17 @@ use fugit::{HertzU32, MicrosDurationU64}; use self::rtc::SocResetReason; #[cfg(not(esp32))] use crate::efuse::Efuse; +#[cfg(not(esp32c6))] +use crate::peripherals::RTC_CNTL; +#[cfg(esp32c6)] +use crate::peripherals::{LP_AON, LP_CLKRST, LP_WDT, PCR, PMU}; use crate::{ clock::{Clock, XtalClock}, peripheral::{Peripheral, PeripheralRef}, - peripherals::{TIMG0}, + peripherals::TIMG0, Cpu, }; -#[cfg(not(esp32c6))] -use crate::peripherals::RTC_CNTL; -#[cfg(esp32c6)] -use crate::peripherals::{LP_CLKRST, LP_AON, PCR, PMU, LP_WDT}; - #[cfg(not(esp32c6))] type RTC_PERIPHERAL = RTC_CNTL; @@ -81,10 +80,10 @@ pub(crate) enum RtcSlowClock { /// External 32 KHz XTAL RtcSlowClock32kXtal = 1, /// TODO - RtcSlowClock32kRc = 2, + RtcSlowClock32kRc = 2, /// Internal 150 KHz RC oscillator - RtcCalInternalOsc = 3, - RtcCalRcFast + RtcCalInternalOsc = 3, + RtcCalRcFast, } impl Clock for RtcSlowClock { @@ -142,15 +141,15 @@ pub(crate) enum RtcCalSel { RtcCal32kRc = 2, #[cfg(not(esp32))] /// Internal 150 KHz RC oscillator TODO - RtcCalInternalOsc= 3, - RtcCalRcFast + RtcCalInternalOsc = 3, + RtcCalRcFast, } #[cfg(esp32c6)] pub(crate) enum RtcCaliClkSel { CaliClkRcSlow = 0, CaliClkRcFast = 1, - CaliClk32k = 2, + CaliClk32k = 2, } pub struct Rtc<'d> { @@ -229,12 +228,14 @@ impl RtcClock { let pmu = unsafe { &*PMU::ptr() }; if clk_8m_en { - pmu.hp_sleep_lp_ck_power.modify(|_, w| w.hp_sleep_xpd_fosc_clk().set_bit()); + pmu.hp_sleep_lp_ck_power + .modify(|_, w| w.hp_sleep_xpd_fosc_clk().set_bit()); unsafe { ets_delay_us(50); } } else { - pmu.hp_sleep_lp_ck_power.modify(|_, w| w.hp_sleep_xpd_fosc_clk().clear_bit()); + pmu.hp_sleep_lp_ck_power + .modify(|_, w| w.hp_sleep_xpd_fosc_clk().clear_bit()); } } @@ -333,506 +334,554 @@ impl RtcClock { _ => false, }) }); - } + } - /// Select source for RTC_FAST_CLK - fn set_fast_freq(fast_freq: RtcFastClock) { - unsafe { - let rtc_cntl = &*RTC_CNTL::ptr(); - rtc_cntl.clk_conf.modify(|_, w| { - w.fast_clk_rtc_sel().bit(match fast_freq { - RtcFastClock::RtcFastClock8m => true, - RtcFastClock::RtcFastClockXtalD4 => false, - }) - }); + /// Select source for RTC_FAST_CLK + fn set_fast_freq(fast_freq: RtcFastClock) { + unsafe { + let rtc_cntl = &*RTC_CNTL::ptr(); + rtc_cntl.clk_conf.modify(|_, w| { + w.fast_clk_rtc_sel().bit(match fast_freq { + RtcFastClock::RtcFastClock8m => true, + RtcFastClock::RtcFastClockXtalD4 => false, + }) + }); - ets_delay_us(3u32); - }; - } + ets_delay_us(3u32); + }; + } - /// Calibration of RTC_SLOW_CLK is performed using a special feature of - /// TIMG0. This feature counts the number of XTAL clock cycles within a - /// given number of RTC_SLOW_CLK cycles. - #[cfg(not(esp32c6))] - fn calibrate_internal(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { - // Except for ESP32, choosing RTC_CAL_RTC_MUX results in calibration of - // the 150k RTC clock (90k on ESP32-S2) regardless of the currently selected - // SLOW_CLK. On the ESP32, it uses the currently selected SLOW_CLK. - // The following code emulates ESP32 behavior for the other chips: - #[cfg(not(esp32))] - let cal_clk = match cal_clk { - RtcCalSel::RtcCalRtcMux => match RtcClock::get_slow_freq() { - RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, - RtcSlowClock::RtcSlowClock8mD256 => RtcCalSel::RtcCal8mD256, + /// Calibration of RTC_SLOW_CLK is performed using a special feature of + /// TIMG0. This feature counts the number of XTAL clock cycles within a + /// given number of RTC_SLOW_CLK cycles. + #[cfg(not(esp32c6))] + fn calibrate_internal(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { + // Except for ESP32, choosing RTC_CAL_RTC_MUX results in calibration of + // the 150k RTC clock (90k on ESP32-S2) regardless of the currently selected + // SLOW_CLK. On the ESP32, it uses the currently selected SLOW_CLK. + // The following code emulates ESP32 behavior for the other chips: + #[cfg(not(esp32))] + let cal_clk = match cal_clk { + RtcCalSel::RtcCalRtcMux => match RtcClock::get_slow_freq() { + RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, + RtcSlowClock::RtcSlowClock8mD256 => RtcCalSel::RtcCal8mD256, + _ => cal_clk, + }, + RtcCalSel::RtcCalInternalOsc => RtcCalSel::RtcCalRtcMux, _ => cal_clk, - }, - RtcCalSel::RtcCalInternalOsc => RtcCalSel::RtcCalRtcMux, - _ => cal_clk, - }; - - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; - let timg0 = unsafe { &*TIMG0::ptr() }; - - // Enable requested clock (150k clock is always on) - let dig_32k_xtal_enabled = rtc_cntl.clk_conf.read().dig_xtal32k_en().bit_is_set(); + }; - if matches!(cal_clk, RtcCalSel::RtcCal32kXtal) && !dig_32k_xtal_enabled { - rtc_cntl - .clk_conf - .modify(|_, w| w.dig_xtal32k_en().set_bit()); - } + let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; + let timg0 = unsafe { &*TIMG0::ptr() }; - if matches!(cal_clk, RtcCalSel::RtcCal8mD256) { - rtc_cntl - .clk_conf - .modify(|_, w| w.dig_clk8m_d256_en().set_bit()); - } + // Enable requested clock (150k clock is always on) + let dig_32k_xtal_enabled = rtc_cntl.clk_conf.read().dig_xtal32k_en().bit_is_set(); - // There may be another calibration process already running during we - // call this function, so we should wait the last process is done. - #[cfg(not(esp32))] - if timg0 - .rtccalicfg - .read() - .rtc_cali_start_cycling() - .bit_is_set() - { - // Set a small timeout threshold to accelerate the generation of timeout. - // The internal circuit will be reset when the timeout occurs and will not - // affect the next calibration. - timg0 - .rtccalicfg2 - .modify(|_, w| unsafe { w.rtc_cali_timeout_thres().bits(1) }); + if matches!(cal_clk, RtcCalSel::RtcCal32kXtal) && !dig_32k_xtal_enabled { + rtc_cntl + .clk_conf + .modify(|_, w| w.dig_xtal32k_en().set_bit()); + } - while timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_clear() - && timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_clear() - {} - } + if matches!(cal_clk, RtcCalSel::RtcCal8mD256) { + rtc_cntl + .clk_conf + .modify(|_, w| w.dig_clk8m_d256_en().set_bit()); + } - // Prepare calibration - timg0.rtccalicfg.modify(|_, w| unsafe { - w.rtc_cali_clk_sel() - .bits(cal_clk as u8) + // There may be another calibration process already running during we + // call this function, so we should wait the last process is done. + #[cfg(not(esp32))] + if timg0 + .rtccalicfg + .read() .rtc_cali_start_cycling() - .clear_bit() - .rtc_cali_max() - .bits(slowclk_cycles as u16) - }); - - // Figure out how long to wait for calibration to finish - // Set timeout reg and expect time delay - let expected_freq = match cal_clk { - RtcCalSel::RtcCal32kXtal => { - #[cfg(not(esp32))] - timg0.rtccalicfg2.modify(|_, w| unsafe { - w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12) - }); - RtcSlowClock::RtcSlowClock32kXtal - } - RtcCalSel::RtcCal8mD256 => { - #[cfg(not(esp32))] - timg0.rtccalicfg2.modify(|_, w| unsafe { - w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12) - }); - RtcSlowClock::RtcSlowClock8mD256 - } - _ => { - #[cfg(not(esp32))] - timg0.rtccalicfg2.modify(|_, w| unsafe { - w.rtc_cali_timeout_thres().bits(slowclk_cycles << 10) - }); - RtcSlowClock::RtcSlowClockRtc + .bit_is_set() + { + // Set a small timeout threshold to accelerate the generation of timeout. + // The internal circuit will be reset when the timeout occurs and will not + // affect the next calibration. + timg0 + .rtccalicfg2 + .modify(|_, w| unsafe { w.rtc_cali_timeout_thres().bits(1) }); + + while timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_clear() + && timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_clear() + {} } - }; - - let us_time_estimate = HertzU32::MHz(slowclk_cycles) / expected_freq.frequency(); - // Start calibration - timg0 - .rtccalicfg - .modify(|_, w| w.rtc_cali_start().clear_bit().rtc_cali_start().set_bit()); + // Prepare calibration + timg0.rtccalicfg.modify(|_, w| unsafe { + w.rtc_cali_clk_sel() + .bits(cal_clk as u8) + .rtc_cali_start_cycling() + .clear_bit() + .rtc_cali_max() + .bits(slowclk_cycles as u16) + }); - // Wait for calibration to finish up to another us_time_estimate - unsafe { - ets_delay_us(us_time_estimate); - } + // Figure out how long to wait for calibration to finish + // Set timeout reg and expect time delay + let expected_freq = match cal_clk { + RtcCalSel::RtcCal32kXtal => { + #[cfg(not(esp32))] + timg0.rtccalicfg2.modify(|_, w| unsafe { + w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12) + }); + RtcSlowClock::RtcSlowClock32kXtal + } + RtcCalSel::RtcCal8mD256 => { + #[cfg(not(esp32))] + timg0.rtccalicfg2.modify(|_, w| unsafe { + w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12) + }); + RtcSlowClock::RtcSlowClock8mD256 + } + _ => { + #[cfg(not(esp32))] + timg0.rtccalicfg2.modify(|_, w| unsafe { + w.rtc_cali_timeout_thres().bits(slowclk_cycles << 10) + }); + RtcSlowClock::RtcSlowClockRtc + } + }; - #[cfg(esp32)] - let mut timeout_us = us_time_estimate; + let us_time_estimate = HertzU32::MHz(slowclk_cycles) / expected_freq.frequency(); - let cal_val = loop { - if timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_set() { - break timg0.rtccalicfg1.read().rtc_cali_value().bits(); - } + // Start calibration + timg0 + .rtccalicfg + .modify(|_, w| w.rtc_cali_start().clear_bit().rtc_cali_start().set_bit()); - #[cfg(not(esp32))] - if timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_set() { - // Timed out waiting for calibration - break 0; + // Wait for calibration to finish up to another us_time_estimate + unsafe { + ets_delay_us(us_time_estimate); } #[cfg(esp32)] - if timeout_us > 0 { - timeout_us -= 1; - unsafe { - ets_delay_us(1); + let mut timeout_us = us_time_estimate; + + let cal_val = loop { + if timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_set() { + break timg0.rtccalicfg1.read().rtc_cali_value().bits(); } - } else { - // Timed out waiting for calibration - break 0; - } - }; - timg0 - .rtccalicfg - .modify(|_, w| w.rtc_cali_start().clear_bit()); - rtc_cntl - .clk_conf - .modify(|_, w| w.dig_xtal32k_en().bit(dig_32k_xtal_enabled)); + #[cfg(not(esp32))] + if timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_set() { + // Timed out waiting for calibration + break 0; + } + + #[cfg(esp32)] + if timeout_us > 0 { + timeout_us -= 1; + unsafe { + ets_delay_us(1); + } + } else { + // Timed out waiting for calibration + break 0; + } + }; - if matches!(cal_clk, RtcCalSel::RtcCal8mD256) { + timg0 + .rtccalicfg + .modify(|_, w| w.rtc_cali_start().clear_bit()); rtc_cntl .clk_conf - .modify(|_, w| w.dig_clk8m_d256_en().clear_bit()); - } + .modify(|_, w| w.dig_xtal32k_en().bit(dig_32k_xtal_enabled)); - cal_val - } + if matches!(cal_clk, RtcCalSel::RtcCal8mD256) { + rtc_cntl + .clk_conf + .modify(|_, w| w.dig_clk8m_d256_en().clear_bit()); + } - /// Calibration of RTC_SLOW_CLK is performed using a special feature of - /// TIMG0. This feature counts the number of XTAL clock cycles within a - /// given number of RTC_SLOW_CLK cycles. - #[cfg(esp32c6)] - fn calibrate_internal(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { - // Except for ESP32, choosing RTC_CAL_RTC_MUX results in calibration of - // the 150k RTC clock (90k on ESP32-S2) regardless of the currently selected - // SLOW_CLK. On the ESP32, it uses the currently selected SLOW_CLK. - // The following code emulates ESP32 behavior for the other chips: - #[cfg(not(any(esp32, esp32c6)))] - let cal_clk = match cal_clk { - RtcCalSel::RtcCalRtcMux => match RtcClock::get_slow_freq() { - RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, - RtcSlowClock::RtcSlowClock8mD256 => RtcCalSel::RtcCal8mD256, - _ => cal_clk, - }, - RtcCalSel::RtcCalInternalOsc => RtcCalSel::RtcCalRtcMux, - _ => cal_clk, - }; + cal_val + } + /// Calibration of RTC_SLOW_CLK is performed using a special feature of + /// TIMG0. This feature counts the number of XTAL clock cycles within a + /// given number of RTC_SLOW_CLK cycles. #[cfg(esp32c6)] - if cal_clk == RtcCalSel::RtcCalRtcMux { - cal_clk = match cal_clk { + fn calibrate_internal(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { + // Except for ESP32, choosing RTC_CAL_RTC_MUX results in calibration of + // the 150k RTC clock (90k on ESP32-S2) regardless of the currently selected + // SLOW_CLK. On the ESP32, it uses the currently selected SLOW_CLK. + // The following code emulates ESP32 behavior for the other chips: + #[cfg(not(any(esp32, esp32c6)))] + let cal_clk = match cal_clk { RtcCalSel::RtcCalRtcMux => match RtcClock::get_slow_freq() { RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, - RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc, + RtcSlowClock::RtcSlowClock8mD256 => RtcCalSel::RtcCal8mD256, _ => cal_clk, }, RtcCalSel::RtcCalInternalOsc => RtcCalSel::RtcCalRtcMux, _ => cal_clk, }; - } - let lp_clkrst = unsafe { &*LP_CLKRST::ptr() }; - // let lp_clkrst = &*LP_CLKRST::ptr(); - let pcr = &*PCR::ptr(); - let pmu = &*PMU::ptr(); + #[cfg(esp32c6)] + if cal_clk == RtcCalSel::RtcCalRtcMux { + cal_clk = match cal_clk { + RtcCalSel::RtcCalRtcMux => match RtcClock::get_slow_freq() { + RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, + RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc, + _ => cal_clk, + }, + RtcCalSel::RtcCalInternalOsc => RtcCalSel::RtcCalRtcMux, + _ => cal_clk, + }; + } - const SOC_CLK_RC_FAST_FREQ_APPROX :u32 = 17_500_000; - const SOC_CLK_RC_SLOW_FREQ_APPROX :u32 = 136_000 ; - const SOC_CLK_RC32K_FREQ_APPROX :u32 = 32768 ; - const SOC_CLK_XTAL32K_FREQ_APPROX :u32 = 32768 ; - const SOC_CLK_OSC_SLOW_FREQ_APPROX :u32 = 32768; + let lp_clkrst = unsafe { &*LP_CLKRST::ptr() }; + // let lp_clkrst = &*LP_CLKRST::ptr(); + let pcr = &*PCR::ptr(); + let pmu = &*PMU::ptr(); - let clk_src = RtcClock::get_slow_freq(); + const SOC_CLK_RC_FAST_FREQ_APPROX: u32 = 17_500_000; + const SOC_CLK_RC_SLOW_FREQ_APPROX: u32 = 136_000; + const SOC_CLK_RC32K_FREQ_APPROX: u32 = 32768; + const SOC_CLK_XTAL32K_FREQ_APPROX: u32 = 32768; + const SOC_CLK_OSC_SLOW_FREQ_APPROX: u32 = 32768; - let old_clk_sel = match pcr.ctrl_32k_conf.read().clk_32k_sel().bits() { - 0 => RtcSlowClock::RtcSlowClockRtc, - 1 => RtcSlowClock::RtcSlowClock32kXtal, - 2 => RtcSlowClock::RtcSlowClock32kRc, - _ => unreachable!(), - }; + let clk_src = RtcClock::get_slow_freq(); - if cal_clk == RtcCalSel::RtcCalRtcMux { - cal_clk = match clk_src { - RtcSlowClock::RtcSlowClockRtc => RtcCalSel::RtcCalRcSlow, - RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, - RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc, - RtcSlowClock::RtcCalInternalOsc => RtcCalSel::RtcCalInternalOsc, - _ => unreachable!() + let old_clk_sel = match pcr.ctrl_32k_conf.read().clk_32k_sel().bits() { + 0 => RtcSlowClock::RtcSlowClockRtc, + 1 => RtcSlowClock::RtcSlowClock32kXtal, + 2 => RtcSlowClock::RtcSlowClock32kRc, + _ => unreachable!(), }; - } - let cali_clk_sel = match cal_clk { - RtcCalSel::RtcCalRcFast => RtcCaliClkSel::CaliClkRcFast, - RtcCalSel::RtcCalRcSlow => RtcCaliClkSel::CaliClkRcSlow, - _ => { - match clk_src { - RtcSlowClock::RtcSlowClock32kRc => pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(0)), - RtcSlowClock::RtcSlowClock32kXtal => pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(1)), - RtcSlowClock::RtcCalInternalOsc => pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(2)), - _ => unreachable!() + if cal_clk == RtcCalSel::RtcCalRtcMux { + cal_clk = match clk_src { + RtcSlowClock::RtcSlowClockRtc => RtcCalSel::RtcCalRcSlow, + RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, + RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc, + RtcSlowClock::RtcCalInternalOsc => RtcCalSel::RtcCalInternalOsc, + _ => unreachable!(), }; - RtcCaliClkSel::CaliClk32k } - }; - // if cal_clk == RtcCalSel::RtcCalRcFast { - // cali_clk_sel = RtcCaliClkSel::CaliClkRcFast; - // } else if cal_clk == RtcCalSel::RtcCalRcSlow { - // cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_SLOW; - // } else { - // cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_32K; - // match clk_src { - // RtcSlowClock::RtcSlowClock32kRc => pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(0)), - // RtcSlowClock::RtcSlowClock32kXtal => pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(1)), - // RtcSlowClock::RtcCalInternalOsc => pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(2)), - // _ => unreachable!() - // } - // } - - // Enable requested clock (150k is always on) - // Some delay is required before the time is stable - // Only enable if originaly was disabled - // If clock is already on, do nothing - - let dig_32k_xtal_enabled = lp_clkrst.clk_to_hp.read().icg_hp_xtal32k().bit_is_set(); - - if cal_clk == RtcCalSel::RtcCal32kXtal && !dig_32k_xtal_enabled { - lp_clkrst.clk_to_hp.modify(|_, w| w.icg_hp_xtal32k().set_bit()); - } + let cali_clk_sel = match cal_clk { + RtcCalSel::RtcCalRcFast => RtcCaliClkSel::CaliClkRcFast, + RtcCalSel::RtcCalRcSlow => RtcCaliClkSel::CaliClkRcSlow, + _ => { + match clk_src { + RtcSlowClock::RtcSlowClock32kRc => { + pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(0)) + } + RtcSlowClock::RtcSlowClock32kXtal => { + pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(1)) + } + RtcSlowClock::RtcCalInternalOsc => { + pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(2)) + } + _ => unreachable!(), + }; + RtcCaliClkSel::CaliClk32k + } + }; - let rc_fast_enabled = pmu.hp_sleep_lp_ck_power.read().hp_sleep_xpd_fosc_clk().bit_is_set(); - let dig_rc_fast_enabled = lp_clkrst.clk_to_hp.read().icg_hp_fosc().bit_is_set(); + // if cal_clk == RtcCalSel::RtcCalRcFast { + // cali_clk_sel = RtcCaliClkSel::CaliClkRcFast; + // } else if cal_clk == RtcCalSel::RtcCalRcSlow { + // cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_SLOW; + // } else { + // cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_32K; + // match clk_src { + // RtcSlowClock::RtcSlowClock32kRc => pcr.ctrl_32k_conf.modify(|_, w| + // w.clk_32k_sel().bits(0)), + // RtcSlowClock::RtcSlowClock32kXtal => pcr.ctrl_32k_conf.modify(|_, w| + // w.clk_32k_sel().bits(1)), RtcSlowClock::RtcCalInternalOsc + // => pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(2)), + // _ => unreachable!() + // } + // } - if cal_clk == RtcCalSel::RtcCalRcFast { - if !rc_fast_enabled { - pmu.hp_sleep_lp_ck_power.write(|w| w.hp_sleep_xpd_fosc_clk().set_bit()); - unsafe { - ets_delay_us(50); - } + // Enable requested clock (150k is always on) + // Some delay is required before the time is stable + // Only enable if originaly was disabled + // If clock is already on, do nothing + + let dig_32k_xtal_enabled = lp_clkrst.clk_to_hp.read().icg_hp_xtal32k().bit_is_set(); + + if cal_clk == RtcCalSel::RtcCal32kXtal && !dig_32k_xtal_enabled { + lp_clkrst + .clk_to_hp + .modify(|_, w| w.icg_hp_xtal32k().set_bit()); } - if !dig_rc_fast_enabled { - lp_clkrst.clk_to_hp.write(|w| w.icg_hp_fosc().set_bit()); - unsafe { - ets_delay_us(5); + let rc_fast_enabled = pmu + .hp_sleep_lp_ck_power + .read() + .hp_sleep_xpd_fosc_clk() + .bit_is_set(); + let dig_rc_fast_enabled = lp_clkrst.clk_to_hp.read().icg_hp_fosc().bit_is_set(); + + if cal_clk == RtcCalSel::RtcCalRcFast { + if !rc_fast_enabled { + pmu.hp_sleep_lp_ck_power + .write(|w| w.hp_sleep_xpd_fosc_clk().set_bit()); + unsafe { + ets_delay_us(50); + } } - } - } - let rc32k_enabled = pmu.hp_sleep_lp_ck_power.read().hp_sleep_xpd_rc32k().bit_is_set(); - let dig_rc32k_enabled = lp_clkrst.clk_to_hp.read().icg_hp_osc32k().bit_is_set(); + if !dig_rc_fast_enabled { + lp_clkrst.clk_to_hp.write(|w| w.icg_hp_fosc().set_bit()); + unsafe { + ets_delay_us(5); + } + } + } - if cal_clk == RtcCalSel::RtcCal32kRc { - if !rc32k_enabled { - pmu.hp_sleep_lp_ck_power.write(|w| w.hp_sleep_xpd_rc32k().set_bit()); - unsafe { - ets_delay_us(300); + let rc32k_enabled = pmu + .hp_sleep_lp_ck_power + .read() + .hp_sleep_xpd_rc32k() + .bit_is_set(); + let dig_rc32k_enabled = lp_clkrst.clk_to_hp.read().icg_hp_osc32k().bit_is_set(); + + if cal_clk == RtcCalSel::RtcCal32kRc { + if !rc32k_enabled { + pmu.hp_sleep_lp_ck_power + .write(|w| w.hp_sleep_xpd_rc32k().set_bit()); + unsafe { + ets_delay_us(300); + } + } + if !dig_rc32k_enabled { + lp_clkrst.clk_to_hp.write(|w| w.icg_hp_osc32k().set_bit()); } } - if !dig_rc32k_enabled { - lp_clkrst.clk_to_hp.write(|w| w.icg_hp_osc32k().set_bit()); + + // Check if there is already running calibration process + let timg0 = unsafe { &*TIMG0::ptr() }; + + if timg0 + .rtccalicfg + .read() + .rtc_cali_start_cycling() + .bit_is_set() + { + timg0 + .rtccalicfg2 + .modify(|_, w| w.rtc_cali_timeout_thres().bits(1)); + + // Set small timeout threshold to accelerate the generation of timeot + // Internal circuit will be reset when timeout occurs and will not affect the + // next calibration + while timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_clear() + && timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_clear() + {} } - } - // Check if there is already running calibration process - let timg0 = unsafe { &*TIMG0::ptr() }; + // Prepare calibration + timg0 + .rtccalicfg + .modify(|_, w| w.rtc_cali_clk_sel().bits(cali_clk_sel as u8)); + timg0 + .rtccalicfg + .write(|w| w.rtc_cali_start_cycling().clear_bit()); + timg0 + .rtccalicfg + .modify(|_, w| w.rtc_cali_max().bits(slowclk_cycles.try_into().unwrap())); + + let expected_freq = match cali_clk_sel { + RtcCaliClkSel::CaliClk32k => { + #[cfg(not(esp32))] + timg0 + .rtccalicfg2 + .modify(|_, w| w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12)); + RtcSlowClock::RtcSlowClock32kXtal + } + RtcCaliClkSel::CaliClkRcFast => { + #[cfg(not(esp32))] + timg0 + .rtccalicfg2 + .modify(|_, w| w.rtc_cali_timeout_thres().bits(0x01FFFFFF)); + RtcSlowClock::RtcCalRcFast + } + _ => { + #[cfg(not(esp32))] + timg0 + .rtccalicfg2 + .modify(|_, w| w.rtc_cali_timeout_thres().bits(slowclk_cycles << 10)); + RtcSlowClock::RtcSlowClockRtc + } + }; - if timg0.rtccalicfg.read().rtc_cali_start_cycling().bit_is_set() { - timg0.rtccalicfg2.modify(|_, w| w.rtc_cali_timeout_thres().bits(1)); + // if cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_32K { + // timg0.rtccalicfg2.modify(|_, w| + // w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12)); + // expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX; + // } else if cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST { + // timg0.rtccalicfg2.modify(|_, w| + // w.rtc_cali_timeout_thres().bits(0x01FFFFFF)); expected_freq = + // 17_500_000; } else { + // timg0.rtccalicfg2.modify(|_, w| + // w.rtc_cali_timeout_thres().bits(slowclk_cycles << 10)); + // expected_freq = 136_000; + // } - // Set small timeout threshold to accelerate the generation of timeot - // Internal circuit will be reset when timeout occurs and will not affect the next calibration - while timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_clear() - && timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_clear() {} - } + let us_time_estimate = HertzU32::MHz(slowclk_cycles) / expected_freq.frequency(); - // Prepare calibration - timg0.rtccalicfg.modify(|_, w| w.rtc_cali_clk_sel().bits(cali_clk_sel as u8)); - timg0.rtccalicfg.write(|w| w.rtc_cali_start_cycling().clear_bit()); - timg0.rtccalicfg.modify(|_, w| w.rtc_cali_max().bits(slowclk_cycles.try_into().unwrap())); + // Start calibration + timg0 + .rtccalicfg + .modify(|_, w| w.rtc_cali_start().clear_bit().rtc_cali_start().set_bit()); - let expected_freq = match cali_clk_sel { - RtcCaliClkSel::CaliClk32k => { - #[cfg(not(esp32))] - timg0.rtccalicfg2.modify(|_, w| w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12)); - RtcSlowClock::RtcSlowClock32kXtal - } - RtcCaliClkSel::CaliClkRcFast => { - #[cfg(not(esp32))] - timg0.rtccalicfg2.modify(|_, w| w.rtc_cali_timeout_thres().bits(0x01FFFFFF)); - RtcSlowClock::RtcCalRcFast - } - _ => { - #[cfg(not(esp32))] - timg0.rtccalicfg2.modify(|_, w| w.rtc_cali_timeout_thres().bits(slowclk_cycles << 10)); - RtcSlowClock::RtcSlowClockRtc + // Wait for calibration to finish up to another us_time_estimate + unsafe { + ets_delay_us(us_time_estimate); } - }; - - // if cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_32K { - // timg0.rtccalicfg2.modify(|_, w| w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12)); - // expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX; - // } else if cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST { - // timg0.rtccalicfg2.modify(|_, w| w.rtc_cali_timeout_thres().bits(0x01FFFFFF)); - // expected_freq = 17_500_000; - // } else { - // timg0.rtccalicfg2.modify(|_, w| w.rtc_cali_timeout_thres().bits(slowclk_cycles << 10)); - // expected_freq = 136_000; - // } - - let us_time_estimate = HertzU32::MHz(slowclk_cycles) / expected_freq.frequency(); - - - // Start calibration - timg0 - .rtccalicfg - .modify(|_, w| w.rtc_cali_start().clear_bit().rtc_cali_start().set_bit()); - - // Wait for calibration to finish up to another us_time_estimate - unsafe { - ets_delay_us(us_time_estimate); - } - let cal_val = loop { - if timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_set() { - break timg0.rtccalicfg1.read().rtc_cali_value().bits(); - } + let cal_val = loop { + if timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_set() { + break timg0.rtccalicfg1.read().rtc_cali_value().bits(); + } - #[cfg(not(esp32))] - if timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_set() { - // Timed out waiting for calibration - break 0; - } + #[cfg(not(esp32))] + if timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_set() { + // Timed out waiting for calibration + break 0; + } - // #[cfg(esp32)] - // if timeout_us > 0 { - // timeout_us -= 1; - // unsafe { - // ets_delay_us(1); - // } - // } else { - // // Timed out waiting for calibration - // break 0; - // } - }; + // #[cfg(esp32)] + // if timeout_us > 0 { + // timeout_us -= 1; + // unsafe { + // ets_delay_us(1); + // } + // } else { + // // Timed out waiting for calibration + // break 0; + // } + }; - timg0 - .rtccalicfg - .modify(|_, w| w.rtc_cali_start().clear_bit()); + timg0 + .rtccalicfg + .modify(|_, w| w.rtc_cali_start().clear_bit()); - if cal_clk == RtcCalSel::RtcCal32kXtal && !dig_32k_xtal_enabled { - lp_clkrst - .clk_to_hp - .modify(|_, w| w.icg_hp_xtal32k().bit(dig_32k_xtal_enabled)); - } + if cal_clk == RtcCalSel::RtcCal32kXtal && !dig_32k_xtal_enabled { + lp_clkrst + .clk_to_hp + .modify(|_, w| w.icg_hp_xtal32k().bit(dig_32k_xtal_enabled)); + } - if cal_clk == RtcCalSel::RtcCalRcFast { - if !rc_fast_enabled { //TODO rtc_dig_clk8m_disable(); - pmu.hp_sleep_lp_ck_power.write(|w| w.hp_sleep_xpd_fosc_clk().set_bit()); - unsafe { - ets_delay_us(50); + if cal_clk == RtcCalSel::RtcCalRcFast { + if !rc_fast_enabled { + // TODO rtc_dig_clk8m_disable(); + pmu.hp_sleep_lp_ck_power + .write(|w| w.hp_sleep_xpd_fosc_clk().set_bit()); + unsafe { + ets_delay_us(50); + } } - } - if !dig_rc_fast_enabled { //TODO rtc_dig_clk8m_disable(); - lp_clkrst.clk_to_hp.write(|w| w.icg_hp_fosc().set_bit()); - unsafe { - ets_delay_us(5); + if !dig_rc_fast_enabled { + // TODO rtc_dig_clk8m_disable(); + lp_clkrst.clk_to_hp.write(|w| w.icg_hp_fosc().set_bit()); + unsafe { + ets_delay_us(5); + } } } - } - if cal_clk == RtcCalSel::RtcCal32kRc { - if !rc32k_enabled { - pmu.hp_sleep_lp_ck_power.write(|w| w.hp_sleep_xpd_rc32k().set_bit()); - unsafe { - ets_delay_us(300); + if cal_clk == RtcCalSel::RtcCal32kRc { + if !rc32k_enabled { + pmu.hp_sleep_lp_ck_power + .write(|w| w.hp_sleep_xpd_rc32k().set_bit()); + unsafe { + ets_delay_us(300); + } + } + if !dig_rc32k_enabled { + lp_clkrst.clk_to_hp.write(|w| w.icg_hp_osc32k().set_bit()); } } - if !dig_rc32k_enabled { - lp_clkrst.clk_to_hp.write(|w| w.icg_hp_osc32k().set_bit()); - } - } - // if matches!(cal_clk, RtcCalSel::RtcCal8mD256) { - // rtc_cntl - // .clk_conf - // .modify(|_, w| w.dig_clk8m_d256_en().clear_bit()); - // } + // if matches!(cal_clk, RtcCalSel::RtcCal8mD256) { + // rtc_cntl + // .clk_conf + // .modify(|_, w| w.dig_clk8m_d256_en().clear_bit()); + // } - cal_val - } + cal_val + } + /// Measure ratio between XTAL frequency and RTC slow clock frequency + fn get_calibration_ratio(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { + let xtal_cycles = RtcClock::calibrate_internal(cal_clk, slowclk_cycles) as u64; + let ratio = (xtal_cycles << RtcClock::CAL_FRACT) / slowclk_cycles as u64; - /// Measure ratio between XTAL frequency and RTC slow clock frequency - fn get_calibration_ratio(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { - let xtal_cycles = RtcClock::calibrate_internal(cal_clk, slowclk_cycles) as u64; - let ratio = (xtal_cycles << RtcClock::CAL_FRACT) / slowclk_cycles as u64; + (ratio & (u32::MAX as u64)) as u32 + } - (ratio & (u32::MAX as u64)) as u32 - } + /// Measure RTC slow clock's period, based on main XTAL frequency + /// + /// This function will time out and return 0 if the time for the given + /// number of cycles to be counted exceeds the expected time twice. This + /// may happen if 32k XTAL is being calibrated, but the oscillator has + /// not started up (due to incorrect loading capacitance, board design + /// issue, or lack of 32 XTAL on board). + fn calibrate(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { + let xtal_freq = RtcClock::get_xtal_freq(); + let xtal_cycles = RtcClock::calibrate_internal(cal_clk, slowclk_cycles) as u64; + let divider = xtal_freq.mhz() as u64 * slowclk_cycles as u64; + let period_64 = + ((xtal_cycles << RtcClock::CAL_FRACT) + divider / 2u64 - 1u64) / divider; + + (period_64 & u32::MAX as u64) as u32 + } - /// Measure RTC slow clock's period, based on main XTAL frequency - /// - /// This function will time out and return 0 if the time for the given - /// number of cycles to be counted exceeds the expected time twice. This - /// may happen if 32k XTAL is being calibrated, but the oscillator has - /// not started up (due to incorrect loading capacitance, board design - /// issue, or lack of 32 XTAL on board). - fn calibrate(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { - let xtal_freq = RtcClock::get_xtal_freq(); - let xtal_cycles = RtcClock::calibrate_internal(cal_clk, slowclk_cycles) as u64; - let divider = xtal_freq.mhz() as u64 * slowclk_cycles as u64; - let period_64 = ((xtal_cycles << RtcClock::CAL_FRACT) + divider / 2u64 - 1u64) / divider; - - (period_64 & u32::MAX as u64) as u32 - } + /// Calculate the necessary RTC_SLOW_CLK cycles to complete 1 + /// millisecond. + fn cycles_to_1ms() -> u16 { + let period_13q19 = RtcClock::calibrate( + match RtcClock::get_slow_freq() { + RtcSlowClock::RtcSlowClockRtc => RtcCalSel::RtcCalRtcMux, + RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, + #[cfg(not(esp32c6))] + RtcSlowClock::RtcSlowClock8mD256 => RtcCalSel::RtcCal8mD256, + #[cfg(esp32c6)] + RtcSlowClock::RtcCalRcFast => RtcCalSel::RtcCalRcFast, + }, + 1024, + ); - /// Calculate the necessary RTC_SLOW_CLK cycles to complete 1 millisecond. - fn cycles_to_1ms() -> u16 { - let period_13q19 = RtcClock::calibrate( - match RtcClock::get_slow_freq() { - RtcSlowClock::RtcSlowClockRtc => RtcCalSel::RtcCalRtcMux, - RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, - #[cfg(not(esp32c6))] - RtcSlowClock::RtcSlowClock8mD256 => RtcCalSel::RtcCal8mD256, - #[cfg(esp32c6)] - RtcSlowClock::RtcCalRcFast => RtcCalSel::RtcCalRcFast, - }, - 1024, - ); - - // 100_000_000 is used to get rid of `float` calculations - let period = (100_000_000 * period_13q19 as u64) / (1 << RtcClock::CAL_FRACT); - - (100_000_000 * 1000 / period) as u16 - } + // 100_000_000 is used to get rid of `float` calculations + let period = (100_000_000 * period_13q19 as u64) / (1 << RtcClock::CAL_FRACT); - #[cfg(not(esp32c6))] - fn estimate_xtal_frequency() -> u32 { - // Number of 8M/256 clock cycles to use for XTAL frequency estimation. - const XTAL_FREQ_EST_CYCLES: u32 = 10; + (100_000_000 * 1000 / period) as u16 + } - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; - let clk_8m_enabled = rtc_cntl.clk_conf.read().enb_ck8m().bit_is_clear(); - let clk_8md256_enabled = rtc_cntl.clk_conf.read().enb_ck8m_div().bit_is_clear(); + #[cfg(not(esp32c6))] + fn estimate_xtal_frequency() -> u32 { + // Number of 8M/256 clock cycles to use for XTAL frequency estimation. + const XTAL_FREQ_EST_CYCLES: u32 = 10; - if !clk_8md256_enabled { - RtcClock::enable_8m(true, true); - } + let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; + let clk_8m_enabled = rtc_cntl.clk_conf.read().enb_ck8m().bit_is_clear(); + let clk_8md256_enabled = rtc_cntl.clk_conf.read().enb_ck8m_div().bit_is_clear(); - let ratio = RtcClock::get_calibration_ratio(RtcCalSel::RtcCal8mD256, XTAL_FREQ_EST_CYCLES); - let freq_mhz = - ((ratio as u64 * RtcFastClock::RtcFastClock8m.hz() as u64 / 1_000_000u64 / 256u64) - >> RtcClock::CAL_FRACT) as u32; + if !clk_8md256_enabled { + RtcClock::enable_8m(true, true); + } + + let ratio = + RtcClock::get_calibration_ratio(RtcCalSel::RtcCal8mD256, XTAL_FREQ_EST_CYCLES); + let freq_mhz = + ((ratio as u64 * RtcFastClock::RtcFastClock8m.hz() as u64 / 1_000_000u64 / 256u64) + >> RtcClock::CAL_FRACT) as u32; - RtcClock::enable_8m(clk_8m_enabled, clk_8md256_enabled); + RtcClock::enable_8m(clk_8m_enabled, clk_8md256_enabled); - freq_mhz + freq_mhz + } } } -} /// Behavior of the RWDT stage if it times out #[allow(unused)] #[derive(Debug, Clone, Copy)] @@ -1019,7 +1068,6 @@ impl Watchdog for Rwdt { } } - #[cfg(any(esp32c6))] /// RTC Watchdog Timer driver impl Rwdt { @@ -1035,9 +1083,7 @@ impl Rwdt { .config0 .modify(|_, w| unsafe { w.wdt_stg0().bits(self.stg0_action as u8) }); - rtc_cntl - .int_ena - .modify(|_, w| w.lp_wdt_int_ena().set_bit()); + rtc_cntl.int_ena.modify(|_, w| w.lp_wdt_int_ena().set_bit()); self.set_write_protection(true); } @@ -1160,7 +1206,9 @@ impl WatchdogDisable for Swd { self.set_write_protection(false); - rtc_cntl.swd_config.write(|w| w.swd_auto_feed_en().set_bit()); + rtc_cntl + .swd_config + .write(|w| w.swd_auto_feed_en().set_bit()); self.set_write_protection(true); } diff --git a/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs b/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs index 503ec47f2bc..985b3acaf6c 100644 --- a/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs +++ b/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs @@ -2,11 +2,12 @@ use paste::paste; use strum::FromRepr; use crate::{ - clock::XtalClock, - peripherals::{EXTMEM, SPI0, SPI1, PCR, LP_AON, PMU}, + clock::{ + clocks_ll::{regi2c_write, regi2c_write_mask}, + XtalClock, + }, + peripherals::{EXTMEM, LP_AON, PCR, PMU, SPI0, SPI1}, rtc_cntl::{RtcCalSel, RtcClock, RtcFastClock, RtcSlowClock}, - clock::clocks_ll::regi2c_write, - clock::clocks_ll::regi2c_write_mask, }; const I2C_DIG_REG: u8 = 0x6d; @@ -27,46 +28,73 @@ const I2C_ULP_IR_FORCE_XPD_CK: u8 = 0; const I2C_ULP_IR_FORCE_XPD_CK_MSB: u8 = 2; const I2C_ULP_IR_FORCE_XPD_CK_LSB: u8 = 2; -const I2C_DIG_REG_ENIF_RTC_DREG: u8 = 5; -const I2C_DIG_REG_ENIF_RTC_DREG_MSB: u8 = 7; -const I2C_DIG_REG_ENIF_RTC_DREG_LSB: u8 = 7; +const I2C_DIG_REG_ENIF_RTC_DREG: u8 = 5; +const I2C_DIG_REG_ENIF_RTC_DREG_MSB: u8 = 7; +const I2C_DIG_REG_ENIF_RTC_DREG_LSB: u8 = 7; -const I2C_DIG_REG_ENIF_DIG_DREG:u8 = 7; -const I2C_DIG_REG_ENIF_DIG_DREG_MSB:u8 = 7; -const I2C_DIG_REG_ENIF_DIG_DREG_LSB:u8 = 7; +const I2C_DIG_REG_ENIF_DIG_DREG: u8 = 7; +const I2C_DIG_REG_ENIF_DIG_DREG_MSB: u8 = 7; +const I2C_DIG_REG_ENIF_DIG_DREG_LSB: u8 = 7; pub(crate) fn init() { let pmu = unsafe { &*PMU::ptr() }; - /* - SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB); - SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C); - - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); - REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); - REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, 25); - REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, 26); - */ - - pmu.rf_pwc.modify(|_, w| - w.perif_i2c_rstb().set_bit(). - xpd_perif_i2c().set_bit()); + // SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB); + // SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C); + // + // REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); + // REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1); + // REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); + // REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); + // REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, + // PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, 25); + // REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, + // PMU_HP_SLEEP_LP_REGULATOR_DBIAS, 26); + + pmu.rf_pwc + .modify(|_, w| w.perif_i2c_rstb().set_bit().xpd_perif_i2c().set_bit()); unsafe { - // crate::clock::clocks_ll::regi2c_write_mask(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); use i2c macro from C6 clock - regi2c_write_mask(I2C_DIG_REG, I2C_DIG_REG_HOSTID, I2C_DIG_REG_ENIF_RTC_DREG, I2C_DIG_REG_ENIF_RTC_DREG_MSB, I2C_DIG_REG_ENIF_RTC_DREG_LSB, 1); - regi2c_write_mask(I2C_DIG_REG, I2C_DIG_REG_HOSTID, I2C_DIG_REG_ENIF_DIG_DREG, I2C_DIG_REG_ENIF_DIG_DREG_MSB, I2C_DIG_REG_ENIF_DIG_DREG_LSB, 1); - - regi2c_write_mask(I2C_DIG_REG, I2C_DIG_REG_HOSTID, I2C_DIG_REG_XPD_RTC_REG, I2C_DIG_REG_XPD_RTC_REG_MSB, I2C_DIG_REG_XPD_RTC_REG_LSB, 0); - regi2c_write_mask(I2C_DIG_REG, I2C_DIG_REG_HOSTID, I2C_DIG_REG_XPD_DIG_REG, I2C_DIG_REG_XPD_DIG_REG_MSB, I2C_DIG_REG_XPD_DIG_REG_LSB, 0); - - pmu.hp_active_hp_regulator0.modify(|_, w| - w.hp_active_hp_regulator_dbias().bits(25)); - pmu.hp_sleep_lp_regulator0.modify(|_, w| - w.hp_sleep_lp_regulator_dbias().bits(26)); - + // crate::clock::clocks_ll::regi2c_write_mask(I2C_DIG_REG, + // I2C_DIG_REG_ENIF_RTC_DREG, 1); use i2c macro from C6 clock + regi2c_write_mask( + I2C_DIG_REG, + I2C_DIG_REG_HOSTID, + I2C_DIG_REG_ENIF_RTC_DREG, + I2C_DIG_REG_ENIF_RTC_DREG_MSB, + I2C_DIG_REG_ENIF_RTC_DREG_LSB, + 1, + ); + regi2c_write_mask( + I2C_DIG_REG, + I2C_DIG_REG_HOSTID, + I2C_DIG_REG_ENIF_DIG_DREG, + I2C_DIG_REG_ENIF_DIG_DREG_MSB, + I2C_DIG_REG_ENIF_DIG_DREG_LSB, + 1, + ); + + regi2c_write_mask( + I2C_DIG_REG, + I2C_DIG_REG_HOSTID, + I2C_DIG_REG_XPD_RTC_REG, + I2C_DIG_REG_XPD_RTC_REG_MSB, + I2C_DIG_REG_XPD_RTC_REG_LSB, + 0, + ); + regi2c_write_mask( + I2C_DIG_REG, + I2C_DIG_REG_HOSTID, + I2C_DIG_REG_XPD_DIG_REG, + I2C_DIG_REG_XPD_DIG_REG_MSB, + I2C_DIG_REG_XPD_DIG_REG_LSB, + 0, + ); + + pmu.hp_active_hp_regulator0 + .modify(|_, w| w.hp_active_hp_regulator_dbias().bits(25)); + pmu.hp_sleep_lp_regulator0 + .modify(|_, w| w.hp_sleep_lp_regulator_dbias().bits(26)); } } @@ -285,5 +313,5 @@ pub enum SocResetReason { /// USB JTAG resets the digital core CoreUsbJtag = 0x16, /// JTAG resets CPU - Cpu0JtagCpu = 0x18, + Cpu0JtagCpu = 0x18, } From cfb8445fdf7ad940b9078b03943910be3ef41f10 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Tue, 7 Feb 2023 18:02:13 +0100 Subject: [PATCH 30/64] C6: update and formatting --- esp-hal-common/build.rs | 1 + esp-hal-common/src/clock/mod.rs | 8 ++++++ esp-hal-common/src/interrupt/riscv.rs | 3 +-- esp-hal-common/src/ledc/channel.rs | 1 - esp-hal-common/src/ledc/mod.rs | 3 ++- esp-hal-common/src/lib.rs | 36 ++++++++++++++------------- esp-hal-common/src/pulse_control.rs | 5 ++-- esp-hal-common/src/system.rs | 12 +++++++-- esp-hal-common/src/timer.rs | 16 ++++++++++++ 9 files changed, 59 insertions(+), 26 deletions(-) diff --git a/esp-hal-common/build.rs b/esp-hal-common/build.rs index 07d612bf599..38490a559da 100644 --- a/esp-hal-common/build.rs +++ b/esp-hal-common/build.rs @@ -110,6 +110,7 @@ fn main() { "timg1", "usb_serial_jtag", "plic", + "aes", ] } else if esp32s2 { vec![ diff --git a/esp-hal-common/src/clock/mod.rs b/esp-hal-common/src/clock/mod.rs index 8475da20ea1..2503dedcc3e 100644 --- a/esp-hal-common/src/clock/mod.rs +++ b/esp-hal-common/src/clock/mod.rs @@ -121,6 +121,8 @@ pub struct Clocks<'d> { pub pwm_clock: HertzU32, #[cfg(esp32s3)] pub crypto_pwm_clock: HertzU32, + #[cfg(esp32c6)] + pub crypto_clock: HertzU32, // TODO chip specific additional ones as needed } @@ -144,6 +146,8 @@ impl<'d> Clocks<'d> { pwm_clock: raw_clocks.pwm_clock, #[cfg(esp32s3)] crypto_pwm_clock: raw_clocks.crypto_pwm_clock, + #[cfg(esp32c6)] + crypto_clock: raw_clocks.crypto_clock, } } } @@ -158,6 +162,8 @@ pub struct RawClocks { pub pwm_clock: HertzU32, #[cfg(esp32s3)] pub crypto_pwm_clock: HertzU32, + #[cfg(esp32c6)] + pub crypto_clock: HertzU32, // TODO chip specific additional ones as needed } @@ -383,6 +389,7 @@ impl<'d> ClockControl<'d> { apb_clock: HertzU32::MHz(80), xtal_clock: HertzU32::MHz(40), i2c_clock: HertzU32::MHz(40), + crypto_clock: HertzU32::MHz(160), }, } } @@ -416,6 +423,7 @@ impl<'d> ClockControl<'d> { apb_clock: apb_freq.frequency(), xtal_clock: xtal_freq.frequency(), i2c_clock: HertzU32::MHz(40), + crypto_clock: HertzU32::MHz(160), }, } } diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index 0f3f2ac0175..54730dfbfd9 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -539,7 +539,6 @@ mod vectored { } } - /// # Safety /// /// This function is called from an assembly trap handler. @@ -710,4 +709,4 @@ fn write_mie(val: u32) { unsafe { core::arch::asm!("csrw mie, {0}", in(reg) val); } -} \ No newline at end of file +} diff --git a/esp-hal-common/src/ledc/channel.rs b/esp-hal-common/src/ledc/channel.rs index 48d5ef7ab59..8456bef5699 100644 --- a/esp-hal-common/src/ledc/channel.rs +++ b/esp-hal-common/src/ledc/channel.rs @@ -215,7 +215,6 @@ macro_rules! start_duty_without_fading { }; } - #[cfg(not(any(esp32, esp32c6)))] /// Macro to start duty cycle, without fading macro_rules! start_duty_without_fading { diff --git a/esp-hal-common/src/ledc/mod.rs b/esp-hal-common/src/ledc/mod.rs index f0cf2ef0c59..9a5ffcc27c0 100644 --- a/esp-hal-common/src/ledc/mod.rs +++ b/esp-hal-common/src/ledc/mod.rs @@ -144,7 +144,8 @@ impl<'d> LEDC<'d> { #[cfg(not(esp32c6))] self.ledc.conf.write(|w| unsafe { w.apb_clk_sel().bits(1) }); #[cfg(esp32c6)] - pcr.ledc_sclk_conf.write(|w| unsafe { w.ledc_sclk_sel().bits(1) }); + pcr.ledc_sclk_conf + .write(|w| unsafe { w.ledc_sclk_sel().bits(1) }); } } self.ledc.timer0_conf.modify(|_, w| w.para_up().set_bit()); diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index 78c96868560..be1f5c6e530 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -58,20 +58,20 @@ pub mod trapframe { #[cfg(rmt)] pub use self::pulse_control::PulseControl; -// #[cfg(usb_serial_jtag)] -// pub use self::usb_serial_jtag::UsbSerialJtag; -// pub use self::{ -// delay::Delay, -// gpio::*, -// interrupt::*, -// rng::Rng, -// rtc_cntl::{Rtc, Rwdt}, -// spi::Spi, -// timer::Timer, -// uart::Uart, -// }; -pub use self::{delay::Delay, gpio::*, interrupt::*, spi::Spi, timer::Timer, uart::Uart, rtc_cntl::{Rtc, Rwdt},}; - +#[cfg(usb_serial_jtag)] +pub use self::usb_serial_jtag::UsbSerialJtag; +pub use self::{ + delay::Delay, + gpio::*, + interrupt::*, + rtc_cntl::{Rtc, Rwdt}, + spi::Spi, + timer::Timer, + uart::Uart, +}; + +#[cfg(aes)] +pub mod aes; // pub mod analog; pub mod clock; pub mod delay; @@ -83,11 +83,11 @@ pub mod i2c; #[cfg(i2s)] pub mod i2s; pub mod ledc; -// #[cfg(mcpwm)] -// pub mod mcpwm; +#[cfg(mcpwm)] +pub mod mcpwm; #[cfg(usb_otg)] pub mod otg_fs; -#[cfg(any(esp32, esp32s2, esp32s3))] +#[cfg(any(esp32, esp32s2, esp32s3, esp32c6))] pub mod pcnt; pub mod peripheral; pub mod prelude; @@ -104,6 +104,8 @@ pub mod system; #[cfg(systimer)] pub mod systimer; pub mod timer; +// #[cfg(any(esp32s3, esp32c3, esp32c6))] +// pub mod twai; pub mod uart; #[cfg(usb_serial_jtag)] pub mod usb_serial_jtag; diff --git a/esp-hal-common/src/pulse_control.rs b/esp-hal-common/src/pulse_control.rs index 6baf086b14c..7994831936a 100644 --- a/esp-hal-common/src/pulse_control.rs +++ b/esp-hal-common/src/pulse_control.rs @@ -86,6 +86,8 @@ use core::slice::Iter; use fugit::NanosDurationU32; pub use paste::paste; +#[cfg(esp32c6)] +use crate::peripherals::PCR; use crate::{ gpio::{types::OutputSignal, OutputPin}, peripheral::{Peripheral, PeripheralRef}, @@ -93,9 +95,6 @@ use crate::{ system::PeripheralClockControl, }; -#[cfg(esp32c6)] -use crate::peripherals::PCR; - /// Errors that can occur when the peripheral is configured #[derive(Debug)] pub enum SetupError { diff --git a/esp-hal-common/src/system.rs b/esp-hal-common/src/system.rs index 17bf9fa0892..66fee258f05 100644 --- a/esp-hal-common/src/system.rs +++ b/esp-hal-common/src/system.rs @@ -33,7 +33,7 @@ pub enum Peripheral { Mcpwm0, #[cfg(mcpwm)] Mcpwm1, - #[cfg(any(esp32, esp32s2, esp32s3))] + #[cfg(any(esp32, esp32s2, esp32s3, esp32c6))] Pcnt, #[cfg(any(esp32c2, esp32c3, esp32c6))] ApbSarAdc, @@ -245,6 +245,14 @@ impl PeripheralClockControl { .twai1_conf .modify(|_, w| w.twai1_rst_en().clear_bit()); } + Peripheral::Aes => { + system.aes_conf.modify(|_, w| w.aes_clk_en().set_bit()); + system.aes_conf.modify(|_, w| w.aes_rst_en().clear_bit()); + } + Peripheral::Pcnt => { + system.pcnt_conf.modify(|_, w| w.pcnt_clk_en().set_bit()); + system.pcnt_conf.modify(|_, w| w.pcnt_rst_en().clear_bit()); + } } } } @@ -341,4 +349,4 @@ mod dma_peripheral { impl crate::peripheral::sealed::Sealed for Dma {} impl crate::peripheral::sealed::Sealed for &mut Dma {} -} \ No newline at end of file +} diff --git a/esp-hal-common/src/timer.rs b/esp-hal-common/src/timer.rs index 384804e1035..5d3249b91ab 100644 --- a/esp-hal-common/src/timer.rs +++ b/esp-hal-common/src/timer.rs @@ -109,6 +109,8 @@ where pub fn new(timg: T, apb_clk_freq: HertzU32) -> Self { // TODO: this currently assumes APB_CLK is being used, as we don't yet have a // way to select the XTAL_CLK. + #[cfg(esp32c6)] + Self::enable_clock(); Self { timg, apb_clk_freq } } @@ -116,6 +118,20 @@ where pub fn free(self) -> T { self.timg } + + #[cfg(esp32c6)] + fn enable_clock() { + let pcr = unsafe { &*crate::peripherals::PCR::ptr() }; + pcr.timergroup0_timer_clk_conf + .write(|w| w.tg0_timer_clk_en().set_bit()); + pcr.timergroup0_timer_clk_conf + .write(|w| unsafe { w.tg0_timer_clk_sel().bits(1) }); + + pcr.timergroup1_timer_clk_conf + .write(|w| w.tg1_timer_clk_en().set_bit()); + pcr.timergroup1_timer_clk_conf + .write(|w| unsafe { w.tg1_timer_clk_sel().bits(1) }); + } } impl Deref for Timer From f9b7e196af211e7393d93879c62e7e3085279115 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Tue, 7 Feb 2023 18:02:38 +0100 Subject: [PATCH 31/64] C6: add pcnt --- esp-hal-common/src/gpio/esp32c6.rs | 240 ++++++++++++++--------------- 1 file changed, 120 insertions(+), 120 deletions(-) diff --git a/esp-hal-common/src/gpio/esp32c6.rs b/esp-hal-common/src/gpio/esp32c6.rs index 09bccfac6ec..07ee4212b07 100644 --- a/esp-hal-common/src/gpio/esp32c6.rs +++ b/esp-hal-common/src/gpio/esp32c6.rs @@ -46,7 +46,7 @@ pub enum InputSignal { I2SI_BCK = 16, I2SI_WS = 17, USB_JTAG_TDO_BRIDGE = 19, - CPU_TESTBUS0 = 20, //TODO: verify + CPU_TESTBUS0 = 20, // TODO: verify CPU_GPIO_IN0 = 28, CPU_GPIO_IN1 = 29, CPU_GPIO_IN2 = 30, @@ -102,22 +102,22 @@ pub enum InputSignal { SIG_IN_FUNC98 = 98, SIG_IN_FUNC99 = 99, SIG_IN_FUNC100 = 100, - PCNT_SIG_CH0_IN0 = 101, - PCNT_SIG_CH1_IN0 = 102, - PCNT_CTRL_CH0_IN0 = 103, - PCNT_CTRL_CH1_IN0 = 104, - PCNT_SIG_CH0_IN1 = 105, - PCNT_SIG_CH1_IN1 = 106, - PCNT_CTRL_CH0_IN1 = 107, - PCNT_CTRL_CH1_IN1 = 108, - PCNT_SIG_CH0_IN2 = 109, - PCNT_SIG_CH1_IN2 = 110, - PCNT_CTRL_CH0_IN2 = 111, - PCNT_CTRL_CH1_IN2 = 112, - PCNT_SIG_CH0_IN3 = 113, - PCNT_SIG_CH1_IN3 = 114, - PCNT_CTRL_CH0_IN3 = 115, - PCNT_CTRL_CH1_IN3 = 116, + PCNT0_SIG_CH0 = 101, + PCNT0_SIG_CH1 = 102, + PCNT0_CTRL_CH0 = 103, + PCNT0_CTRL_CH1 = 104, + PCNT1_SIG_CH0 = 105, + PCNT1_SIG_CH1 = 106, + PCNT1_CTRL_CH0 = 107, + PCNT1_CTRL_CH1 = 108, + PCNT2_SIG_CH0 = 109, + PCNT2_SIG_CH1 = 110, + PCNT2_CTRL_CH0 = 111, + PCNT2_CTRL_CH1 = 112, + PCNT3_SIG_CH0 = 113, + PCNT3_SIG_CH1 = 114, + PCNT3_CTRL_CH0 = 115, + PCNT3_CTRL_CH1 = 116, SPIQ = 121, SPID = 122, SPIHD = 123, @@ -128,108 +128,108 @@ pub enum InputSignal { #[allow(non_camel_case_types)] #[derive(PartialEq, Copy, Clone)] pub enum OutputSignal { - LEDC_LS_SIG0 = 0, - LEDC_LS_SIG1 = 1, - LEDC_LS_SIG2 = 2, - LEDC_LS_SIG3 = 3, - LEDC_LS_SIG4 = 4, - LEDC_LS_SIG5 = 5, - U0TXD = 6, - U0RTS = 7, - U0DTR = 8, - U1TXD = 9, - U1RTS = 10, - U1DTR = 11, - I2S_MCLK = 12, - I2SO_BCK = 13, - I2SO_WS = 14, - I2SO_SD = 15, - I2SI_BCK = 16, - I2SI_WS = 17, - I2SO_SD1 = 18, - USB_JTAG_TRST = 19, // TODO: Verify - CPU_GPIO_OUT0 = 28, - CPU_GPIO_OUT1 = 29, - CPU_GPIO_OUT2 = 30, - CPU_GPIO_OUT3 = 31, - CPU_GPIO_OUT4 = 32, - CPU_GPIO_OUT5 = 33, - CPU_GPIO_OUT6 = 34, - CPU_GPIO_OUT7 = 35, - USB_JTAG_TCK = 36, - USB_JTAG_TMS = 37, - USB_JTAG_TDI = 38, - USB_JTAG_TDO = 39, - I2CEXT0_SCL = 45, - I2CEXT0_SDA = 46, - PARL_TX_DATA0 = 47, - PARL_TX_DATA1 = 48, - PARL_TX_DATA2 = 49, - PARL_TX_DATA3 = 50, - PARL_TX_DATA4 = 51, - PARL_TX_DATA5 = 52, - PARL_TX_DATA6 = 53, - PARL_TX_DATA7 = 54, - PARL_TX_DATA8 = 55, - PARL_TX_DATA9 = 56, - PARL_TX_DATA10 = 57, - PARL_TX_DATA11 = 58, - PARL_TX_DATA12 = 59, - PARL_TX_DATA13 = 60, - PARL_TX_DATA14 = 61, - PARL_TX_DATA15 = 62, - FSPICLK_MUX = 63, - FSPIQ = 64, - FSPID = 65, - FSPIHD = 66, - FSPIWP = 67, - FSPICS0 = 68, - SDIO_TOHOST_INT = 69, - PARL_TX_CLK = 70, - RMT_SIG_0 = 71, - RMT_SIG_1 = 72, - TWAI0_TX = 73, - TWAI0_BUS_OFF_ON = 74, - TWAI0_CLKOUT = 75, - TWAI0_STANDBY = 76, - TWAI1_TX = 77, - TWAI1_BUS_OFF_ON = 78, - TWAI1_CLKOUT = 79, - TWAI1_STANDBY = 80, - GPIO_SD0 = 83, - GPIO_SD1 = 84, - GPIO_SD2 = 85, - GPIO_SD3 = 86, - PWM0_OUT0A = 87, - PWM0_OUT0B = 88, - PWM0_OUT1A = 89, - PWM0_OUT1B = 90, - PWM0_OUT2A = 91, - PWM0_OUT2B = 92, - SIG_IN_FUNC97 = 97, - SIG_IN_FUNC98 = 98, - SIG_IN_FUNC99 = 99, - SIG_IN_FUNC100 = 100, - FSPICS1 = 101, - FSPICS2 = 102, - FSPICS3 = 103, - FSPICS4 = 104, - FSPICS5 = 105, - SPICLK_MUX = 114, - SPICS0 = 115, - SPICS1 = 116, - GPIO_TASK_MATRIX_OUT0 = 117, // TODO: verify rhis group - not in TRM but in ESP_IDF - GPIO_TASK_MATRIX_OUT1 = 118, - GPIO_TASK_MATRIX_OUT2 = 119, - GPIO_TASK_MATRIX_OUT3 = 120, - SPIQ = 121, - SPID = 122, - SPIHD = 123, - SPIWP = 124, - CLK_OUT_OUT1 = 125, - CLK_OUT_OUT2 = 126, - CLK_OUT_OUT3 = 127, - GPIO = 128, + LEDC_LS_SIG0 = 0, + LEDC_LS_SIG1 = 1, + LEDC_LS_SIG2 = 2, + LEDC_LS_SIG3 = 3, + LEDC_LS_SIG4 = 4, + LEDC_LS_SIG5 = 5, + U0TXD = 6, + U0RTS = 7, + U0DTR = 8, + U1TXD = 9, + U1RTS = 10, + U1DTR = 11, + I2S_MCLK = 12, + I2SO_BCK = 13, + I2SO_WS = 14, + I2SO_SD = 15, + I2SI_BCK = 16, + I2SI_WS = 17, + I2SO_SD1 = 18, + USB_JTAG_TRST = 19, // TODO: Verify + CPU_GPIO_OUT0 = 28, + CPU_GPIO_OUT1 = 29, + CPU_GPIO_OUT2 = 30, + CPU_GPIO_OUT3 = 31, + CPU_GPIO_OUT4 = 32, + CPU_GPIO_OUT5 = 33, + CPU_GPIO_OUT6 = 34, + CPU_GPIO_OUT7 = 35, + USB_JTAG_TCK = 36, + USB_JTAG_TMS = 37, + USB_JTAG_TDI = 38, + USB_JTAG_TDO = 39, + I2CEXT0_SCL = 45, + I2CEXT0_SDA = 46, + PARL_TX_DATA0 = 47, + PARL_TX_DATA1 = 48, + PARL_TX_DATA2 = 49, + PARL_TX_DATA3 = 50, + PARL_TX_DATA4 = 51, + PARL_TX_DATA5 = 52, + PARL_TX_DATA6 = 53, + PARL_TX_DATA7 = 54, + PARL_TX_DATA8 = 55, + PARL_TX_DATA9 = 56, + PARL_TX_DATA10 = 57, + PARL_TX_DATA11 = 58, + PARL_TX_DATA12 = 59, + PARL_TX_DATA13 = 60, + PARL_TX_DATA14 = 61, + PARL_TX_DATA15 = 62, + FSPICLK_MUX = 63, + FSPIQ = 64, + FSPID = 65, + FSPIHD = 66, + FSPIWP = 67, + FSPICS0 = 68, + SDIO_TOHOST_INT = 69, + PARL_TX_CLK = 70, + RMT_SIG_0 = 71, + RMT_SIG_1 = 72, + TWAI0_TX = 73, + TWAI0_BUS_OFF_ON = 74, + TWAI0_CLKOUT = 75, + TWAI0_STANDBY = 76, + TWAI1_TX = 77, + TWAI1_BUS_OFF_ON = 78, + TWAI1_CLKOUT = 79, + TWAI1_STANDBY = 80, + GPIO_SD0 = 83, + GPIO_SD1 = 84, + GPIO_SD2 = 85, + GPIO_SD3 = 86, + PWM0_0A = 87, + PWM0_0B = 88, + PWM0_1A = 89, + PWM0_1B = 90, + PWM0_2A = 91, + PWM0_2B = 92, + SIG_IN_FUNC97 = 97, + SIG_IN_FUNC98 = 98, + SIG_IN_FUNC99 = 99, + SIG_IN_FUNC100 = 100, + FSPICS1 = 101, + FSPICS2 = 102, + FSPICS3 = 103, + FSPICS4 = 104, + FSPICS5 = 105, + SPICLK_MUX = 114, + SPICS0 = 115, + SPICS1 = 116, + GPIO_TASK_MATRIX_OUT0 = 117, // TODO: verify rhis group - not in TRM but in ESP_IDF + GPIO_TASK_MATRIX_OUT1 = 118, + GPIO_TASK_MATRIX_OUT2 = 119, + GPIO_TASK_MATRIX_OUT3 = 120, + SPIQ = 121, + SPID = 122, + SPIHD = 123, + SPIWP = 124, + CLK_OUT_OUT1 = 125, + CLK_OUT_OUT2 = 126, + CLK_OUT_OUT3 = 127, + GPIO = 128, } crate::gpio::gpio! { @@ -282,4 +282,4 @@ crate::gpio::analog! { // implement marker traits on USB pins // impl crate::otg_fs::UsbSel for Gpio?? {} // impl crate::otg_fs::UsbDp for Gpio12 {} -// impl crate::otg_fs::UsbDm for Gpio13 {} \ No newline at end of file +// impl crate::otg_fs::UsbDm for Gpio13 {} From a7e14a9ebc5b79bb05d9d9221bd9b3cedfa86df2 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Tue, 7 Feb 2023 18:03:23 +0100 Subject: [PATCH 32/64] C6: add examples and format --- esp32c6-hal/examples/advanced_serial.rs | 74 +++++++++ esp32c6-hal/examples/aes.rs | 101 ++++++++++++ esp32c6-hal/examples/blinky.rs | 4 +- esp32c6-hal/examples/gpio_interrupt.rs | 21 ++- esp32c6-hal/examples/hello_rgb.rs | 97 +++++++++++ esp32c6-hal/examples/hello_world.rs | 90 +++-------- esp32c6-hal/examples/i2c.rs | 63 ++++++++ .../examples/i2c_bmp180_calibration_data.rs | 60 +++++++ esp32c6-hal/examples/i2c_display.rs | 132 +++++++++++++++ esp32c6-hal/examples/i2s_read.rs | 100 ++++++++++++ esp32c6-hal/examples/i2s_sound.rs | 139 ++++++++++++++++ esp32c6-hal/examples/ledc.rs | 75 +++++++++ esp32c6-hal/examples/mcpwm.rs | 69 ++++++++ esp32c6-hal/examples/pcnt_encoder.rs | 150 +++++++++++++++++ esp32c6-hal/examples/pulse_control.rs | 90 +++++++++++ esp32c6-hal/examples/read_efuse.rs | 39 +++++ esp32c6-hal/examples/serial_interrupts.rs | 102 ++++++++++++ esp32c6-hal/examples/sha.rs | 82 ++++++++++ .../examples/spi_eh1_device_loopback.rs | 151 ++++++++++++++++++ esp32c6-hal/examples/spi_eh1_loopback.rs | 123 ++++++++++++++ esp32c6-hal/examples/spi_loopback.rs | 79 +++++++++ esp32c6-hal/examples/spi_loopback_dma.rs | 123 ++++++++++++++ esp32c6-hal/examples/systimer.rs | 130 +++++++++++++++ esp32c6-hal/examples/timer_interrupt.rs | 101 ++++++++++++ esp32c6-hal/examples/usb_serial_jtag.rs | 94 +++++++++++ esp32c6-hal/examples/watchdog.rs | 45 ++++++ esp32c6-hal/src/lib.rs | 10 +- 27 files changed, 2261 insertions(+), 83 deletions(-) create mode 100644 esp32c6-hal/examples/advanced_serial.rs create mode 100644 esp32c6-hal/examples/aes.rs create mode 100644 esp32c6-hal/examples/hello_rgb.rs create mode 100644 esp32c6-hal/examples/i2c.rs create mode 100644 esp32c6-hal/examples/i2c_bmp180_calibration_data.rs create mode 100644 esp32c6-hal/examples/i2c_display.rs create mode 100644 esp32c6-hal/examples/i2s_read.rs create mode 100644 esp32c6-hal/examples/i2s_sound.rs create mode 100644 esp32c6-hal/examples/ledc.rs create mode 100644 esp32c6-hal/examples/mcpwm.rs create mode 100644 esp32c6-hal/examples/pcnt_encoder.rs create mode 100644 esp32c6-hal/examples/pulse_control.rs create mode 100644 esp32c6-hal/examples/read_efuse.rs create mode 100644 esp32c6-hal/examples/serial_interrupts.rs create mode 100644 esp32c6-hal/examples/sha.rs create mode 100644 esp32c6-hal/examples/spi_eh1_device_loopback.rs create mode 100644 esp32c6-hal/examples/spi_eh1_loopback.rs create mode 100644 esp32c6-hal/examples/spi_loopback.rs create mode 100644 esp32c6-hal/examples/spi_loopback_dma.rs create mode 100644 esp32c6-hal/examples/systimer.rs create mode 100644 esp32c6-hal/examples/timer_interrupt.rs create mode 100644 esp32c6-hal/examples/usb_serial_jtag.rs create mode 100644 esp32c6-hal/examples/watchdog.rs diff --git a/esp32c6-hal/examples/advanced_serial.rs b/esp32c6-hal/examples/advanced_serial.rs new file mode 100644 index 00000000000..b7b87cadca7 --- /dev/null +++ b/esp32c6-hal/examples/advanced_serial.rs @@ -0,0 +1,74 @@ +//! This shows how to configure UART +//! You can short the TX and RX pin and see it reads what was written. +//! Additionally you can connect a logic analzyer to TX and see how the changes +//! of the configuration change the output signal. + +#![feature(stmt_expr_attributes)] +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + uart::{ + config::{Config, DataBits, Parity, StopBits}, + TxRxPins, + }, + Rtc, + Uart, + IO, +}; +use esp_backtrace as _; +use esp_println::println; +use esp_riscv_rt::entry; +use nb::block; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut timer0 = timer_group0.timer0; + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + // Disable watchdog timers + rtc.swd.disable(); + rtc.rwdt.disable(); + + let config = Config { + baudrate: 115200, + data_bits: DataBits::DataBits8, + parity: Parity::ParityNone, + stop_bits: StopBits::STOP1, + }; + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let pins = TxRxPins::new_tx_rx( + io.pins.gpio1.into_push_pull_output(), + io.pins.gpio2.into_floating_input(), + ); + + let mut serial1 = Uart::new_with_config(peripherals.UART1, Some(config), Some(pins), &clocks); + + timer0.start(250u64.millis()); + + println!("Start"); + loop { + serial1.write(0x42).ok(); + let read = block!(serial1.read()); + + match read { + Ok(read) => println!("Read {:02x}", read), + Err(err) => println!("Error {:?}", err), + } + + block!(timer0.wait()).unwrap(); + } +} diff --git a/esp32c6-hal/examples/aes.rs b/esp32c6-hal/examples/aes.rs new file mode 100644 index 00000000000..307edf29c66 --- /dev/null +++ b/esp32c6-hal/examples/aes.rs @@ -0,0 +1,101 @@ +#![no_std] +#![no_main] +use aes::{ + cipher::{generic_array::GenericArray, BlockDecrypt, BlockEncrypt, KeyInit}, + Aes128 as Aes128SW, +}; +use esp32c6_hal::{ + aes::{Aes, Aes128, Cipher, Key}, + clock::ClockControl, + peripherals::Peripherals, + prelude::*, + systimer::SystemTimer, + timer::TimerGroup, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; +use esp_riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + rtc.rwdt.disable(); + rtc.swd.disable(); + + let mut aes = Aes::new(peripherals.AES, &mut system.peripheral_clock_control); + + let keytext = "SUp4SeCp@sSw0rd".as_bytes(); + let plaintext = "message".as_bytes(); + + // create an array with aes128 key size + let mut keybuf = [0_u8; 16]; + keybuf[..keytext.len()].copy_from_slice(keytext); + + // create an array with aes block size + let mut block_buf = [0_u8; 16]; + block_buf[..plaintext.len()].copy_from_slice(plaintext); + + let key = Key::::from(&keybuf); + let mut cipher = Cipher::new(&mut aes, &key); + let mut block = block_buf.clone(); + let pre_hw_encrypt = SystemTimer::now(); + cipher.encrypt_block(&mut block); + let post_hw_encrypt = SystemTimer::now(); + println!( + "it took {} cycles for hw encrypt", + post_hw_encrypt - pre_hw_encrypt + ); + let hw_encrypted = block.clone(); + let pre_hw_decrypt = SystemTimer::now(); + cipher.decrypt_block(&mut block); + let post_hw_decrypt = SystemTimer::now(); + println!( + "it took {} cycles for hw decrypt", + post_hw_decrypt - pre_hw_decrypt + ); + let hw_decrypted = block; + + let key = GenericArray::from(keybuf); + let mut block = GenericArray::from(block_buf); + let cipher = Aes128SW::new(&key); + let pre_sw_encrypt = SystemTimer::now(); + cipher.encrypt_block(&mut block); + let post_sw_encrypt = SystemTimer::now(); + println!( + "it took {} cycles for sw encrypt", + post_sw_encrypt - pre_sw_encrypt + ); + let sw_encrypted = block.clone(); + let pre_sw_decrypt = SystemTimer::now(); + cipher.decrypt_block(&mut block); + let post_sw_decrypt = SystemTimer::now(); + println!( + "it took {} cycles for sw decrypt", + post_sw_decrypt - pre_sw_decrypt + ); + let sw_decrypted = block; + + assert!(eq(&sw_encrypted.into(), &hw_encrypted)); + assert!(eq(&sw_decrypted.into(), &hw_decrypted)); + + println!("done"); + + loop {} +} +fn eq(slice1: &[u8; 16], slice2: &[u8; 16]) -> bool { + slice1.iter().zip(slice2.iter()).all(|(a, b)| a == b) +} diff --git a/esp32c6-hal/examples/blinky.rs b/esp32c6-hal/examples/blinky.rs index eb5bfe0127f..74f90a0a8a8 100644 --- a/esp32c6-hal/examples/blinky.rs +++ b/esp32c6-hal/examples/blinky.rs @@ -24,9 +24,9 @@ fn main() -> ! { let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let mut wdt0 = timer_group0.wdt; + let _wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let mut wdt1 = timer_group1.wdt; + let _wdt1 = timer_group1.wdt; let mut rtc = Rtc::new(peripherals.LP_CLKRST); rtc.rwdt.disable(); diff --git a/esp32c6-hal/examples/gpio_interrupt.rs b/esp32c6-hal/examples/gpio_interrupt.rs index 48a39ddeb07..73fa9d545f4 100644 --- a/esp32c6-hal/examples/gpio_interrupt.rs +++ b/esp32c6-hal/examples/gpio_interrupt.rs @@ -17,11 +17,10 @@ use esp32c6_hal::{ prelude::*, timer::TimerGroup, Delay, - // Rtc, + Rtc, }; use esp_backtrace as _; use esp_riscv_rt::{entry, riscv}; -use esp_println::println; static BUTTON: Mutex>>>> = Mutex::new(RefCell::new(None)); @@ -31,18 +30,18 @@ fn main() -> ! { let system = peripherals.PCR.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - // Disable the watchdog timers. For the ESP32-C3, this includes the Super WDT, - // the RTC WDT, and the TIMG WDTs. - // let mut rtc = Rtc::new(peripherals.RTC_CNTL); + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let mut wdt0 = timer_group0.wdt; + let _wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let mut wdt1 = timer_group1.wdt; + let _wdt1 = timer_group1.wdt; - // rtc.swd.disable(); - // rtc.rwdt.disable(); - wdt0.disable(); - wdt1.disable(); + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + rtc.rwdt.disable(); + rtc.swd.disable(); // Set GPIO5 as an output let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/esp32c6-hal/examples/hello_rgb.rs b/esp32c6-hal/examples/hello_rgb.rs new file mode 100644 index 00000000000..f9b32e15864 --- /dev/null +++ b/esp32c6-hal/examples/hello_rgb.rs @@ -0,0 +1,97 @@ +//! //! RGB LED Demo +//! +//! This example drives an SK68XX RGB LED that is connected to the GPIO8 pin. +//! A RGB LED is connected to that pin on the ESP32-C6-DevKitC-1 and board. +//! +//! The demo will leverage the [`smart_leds`](https://crates.io/crates/smart-leds) +//! crate functionality to circle through the HSV hue color space (with +//! saturation and value both at 255). Additionally, we apply a gamma correction +//! and limit the brightness to 10 (out of 255). +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + peripherals, + prelude::*, + pulse_control::ClockSource, + timer::TimerGroup, + utils::{smartLedAdapter, SmartLedsAdapter}, + Delay, + PulseControl, + Rtc, + IO, +}; +#[allow(unused_imports)] +use esp_backtrace as _; +use esp_riscv_rt::entry; +use smart_leds::{ + brightness, + gamma, + hsv::{hsv2rgb, Hsv}, + SmartLedsWrite, +}; + +#[entry] +fn main() -> ! { + let peripherals = peripherals::Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + rtc.rwdt.disable(); + rtc.swd.disable(); + + // Configure RMT peripheral globally + let pulse = PulseControl::new( + peripherals.RMT, + &mut system.peripheral_clock_control, + ClockSource::APB, + 0, + 0, + 0, + ) + .unwrap(); + + // We use one of the RMT channels to instantiate a `SmartLedsAdapter` which can + // be used directly with all `smart_led` implementations + let mut led = ::new(pulse.channel0, io.pins.gpio8); + + // Initialize the Delay peripheral, and use it to toggle the LED state in a + // loop. + let mut delay = Delay::new(&clocks); + + let mut color = Hsv { + hue: 0, + sat: 255, + val: 255, + }; + let mut data; + + loop { + // Iterate over the rainbow! + for hue in 0..=255 { + color.hue = hue; + // Convert from the HSV color space (where we can easily transition from one + // color to the other) to the RGB color space that we can then send to the LED + data = [hsv2rgb(color)]; + // When sending to the LED, we do a gamma correction first (see smart_leds + // documentation for details) and then limit the brightness to 10 out of 255 so + // that the output it's not too bright. + led.write(brightness(gamma(data.iter().cloned()), 10)) + .unwrap(); + delay.delay_ms(20u8); + } + } +} diff --git a/esp32c6-hal/examples/hello_world.rs b/esp32c6-hal/examples/hello_world.rs index 007c9c41a7d..29de78b39a6 100644 --- a/esp32c6-hal/examples/hello_world.rs +++ b/esp32c6-hal/examples/hello_world.rs @@ -1,89 +1,43 @@ +//! This shows how to write text to uart0. +//! You can see the output with `espflash` if you provide the `--monitor` option + #![feature(stmt_expr_attributes)] #![no_std] #![no_main] -// use esp32c6_hal::peripherals; -use core::{cell::RefCell, fmt::Write}; - -use critical_section::Mutex; +use core::fmt::Write; use esp32c6_hal::{ - clock::{ClockControl, CpuClock}, - gpio::IO, - peripherals::{self, Peripherals, UART0}, + clock::ClockControl, + peripherals::Peripherals, prelude::*, - //timer::TimerGroup, - //uart::{ - // config::{Config, DataBits, Parity, StopBits, AtCmdConfig}, - // TxRxPins, - //}, - //Uart, - //Cpu, + timer::TimerGroup, + Rtc, + Uart, }; - - -use esp_hal_common::system::SystemExt; - use esp_backtrace as _; -use esp_println::println; use esp_riscv_rt::entry; use nb::block; - #[entry] fn main() -> ! { - esp_println::println!("fffff"); let peripherals = Peripherals::take(); let system = peripherals.PCR.split(); - // let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let clocks = ClockControl::configure( - system.clock_control, - CpuClock::Clock160MHz, - ) - .freeze(); - - let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); - let mut led = io.pins.gpio5.into_push_pull_output(); - - led.set_high().unwrap(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - // let mut serial0 = Uart::new(peripherals.UART0); + let mut uart0 = Uart::new(peripherals.UART0); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut timer0 = timer_group0.timer0; + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; - // let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - // let mut timer0 = timer_group0.timer0; - // let mut wdt0 = timer_group0.wdt; - // let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - // let mut wdt1 = timer_group1.wdt; + let _rtc = Rtc::new(peripherals.LP_CLKRST); - // let config = Config { - // baudrate: 115200, - // data_bits: DataBits::DataBits8, - // parity: Parity::ParityNone, - // stop_bits: StopBits::STOP1, - // }; + timer0.start(1u64.secs()); - // let pins = TxRxPins::new_tx_rx( - // io.pins.gpio1.into_push_pull_output(), - // io.pins.gpio2.into_floating_input(), - // ); - - // let mut serial1 = Uart::new_with_config(peripherals.UART1, Some(config), Some(pins), &clocks); - - // timer0.start(250u64.millis()); - - // println!("Start"); - // loop { - // serial1.write(0x42).ok(); - // let read = block!(serial1.read()); - - // match read { - // Ok(read) => println!("Read {:02x}", read), - // Err(err) => println!("Error {:?}", err), - // } - - // block!(timer0.wait()).unwrap(); - // } - loop{} + loop { + writeln!(uart0, "Hello world!").unwrap(); + block!(timer0.wait()).unwrap(); + } } - - diff --git a/esp32c6-hal/examples/i2c.rs b/esp32c6-hal/examples/i2c.rs new file mode 100644 index 00000000000..d197e7066ca --- /dev/null +++ b/esp32c6-hal/examples/i2c.rs @@ -0,0 +1,63 @@ +//! Read calibration data from BMP180 sensor +//! +//! This example dumps the calibration data from a BMP180 sensor +//! +//! The following wiring is assumed: +//! - SDA => GPIO1 +//! - SCL => GPIO2 + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + gpio::IO, + i2c::I2C, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; +use esp_riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + rtc.rwdt.disable(); + rtc.swd.disable(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + + // Create a new peripheral object with the described wiring + // and standard I2C clock speed + let mut i2c = I2C::new( + peripherals.I2C0, + io.pins.gpio1, + io.pins.gpio2, + 100u32.kHz(), + &mut system.peripheral_clock_control, + &clocks, + ); + + loop { + let mut data = [0u8; 1]; + i2c.write_read(0x76, &[0xD0], &mut data).ok(); + + println!("{:02x?}", data); + } +} diff --git a/esp32c6-hal/examples/i2c_bmp180_calibration_data.rs b/esp32c6-hal/examples/i2c_bmp180_calibration_data.rs new file mode 100644 index 00000000000..971d4924b75 --- /dev/null +++ b/esp32c6-hal/examples/i2c_bmp180_calibration_data.rs @@ -0,0 +1,60 @@ +//! Read calibration data from BMP180 sensor +//! +//! This example dumps the calibration data from a BMP180 sensor +//! +//! The following wiring is assumed: +//! - SDA => GPIO1 +//! - SCL => GPIO2 + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + gpio::IO, + i2c::I2C, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; +use esp_riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + // Disable watchdog timers + rtc.swd.disable(); + rtc.rwdt.disable(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + + // Create a new peripheral object with the described wiring + // and standard I2C clock speed + let mut i2c = I2C::new( + peripherals.I2C0, + io.pins.gpio1, + io.pins.gpio2, + 100u32.kHz(), + &mut system.peripheral_clock_control, + &clocks, + ); + + loop { + let mut data = [0u8; 22]; + i2c.write_read(0x77, &[0xaa], &mut data).ok(); + + println!("{:02x?}", data); + } +} diff --git a/esp32c6-hal/examples/i2c_display.rs b/esp32c6-hal/examples/i2c_display.rs new file mode 100644 index 00000000000..db53c002fde --- /dev/null +++ b/esp32c6-hal/examples/i2c_display.rs @@ -0,0 +1,132 @@ +//! I2C Display example +//! +//! This example prints some text on an SSD1306-based +//! display (via I2C) +//! +//! The following wiring is assumed: +//! - SDA => GPIO1 +//! - SCL => GPIO2 + +#![no_std] +#![no_main] + +use embedded_graphics::{ + mono_font::{ + ascii::{FONT_6X10, FONT_9X18_BOLD}, + MonoTextStyleBuilder, + }, + pixelcolor::BinaryColor, + prelude::*, + text::{Alignment, Text}, +}; +use esp32c6_hal::{ + clock::ClockControl, + gpio::IO, + i2c::I2C, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, +}; +use esp_backtrace as _; +use esp_riscv_rt::entry; +use nb::block; +use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306}; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut timer0 = timer_group0.timer0; + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + // Disable watchdog timers + rtc.swd.disable(); + rtc.rwdt.disable(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + + // Create a new peripheral object with the described wiring + // and standard I2C clock speed + let i2c = I2C::new( + peripherals.I2C0, + io.pins.gpio1, + io.pins.gpio2, + 100u32.kHz(), + &mut system.peripheral_clock_control, + &clocks, + ); + + // Start timer (5 second interval) + timer0.start(5u64.secs()); + + // Initialize display + let interface = I2CDisplayInterface::new(i2c); + let mut display = Ssd1306::new(interface, DisplaySize128x64, DisplayRotation::Rotate0) + .into_buffered_graphics_mode(); + display.init().unwrap(); + + // Specify different text styles + let text_style = MonoTextStyleBuilder::new() + .font(&FONT_6X10) + .text_color(BinaryColor::On) + .build(); + let text_style_big = MonoTextStyleBuilder::new() + .font(&FONT_9X18_BOLD) + .text_color(BinaryColor::On) + .build(); + + loop { + // Fill display bufffer with a centered text with two lines (and two text + // styles) + Text::with_alignment( + "esp-hal", + display.bounding_box().center() + Point::new(0, 0), + text_style_big, + Alignment::Center, + ) + .draw(&mut display) + .unwrap(); + + Text::with_alignment( + "Chip: ESP32-C6", + display.bounding_box().center() + Point::new(0, 14), + text_style, + Alignment::Center, + ) + .draw(&mut display) + .unwrap(); + + // Write buffer to display + display.flush().unwrap(); + // Clear display buffer + display.clear(); + + // Wait 5 seconds + block!(timer0.wait()).unwrap(); + + // Write single-line centered text "Hello World" to buffer + Text::with_alignment( + "Hello World!", + display.bounding_box().center(), + text_style_big, + Alignment::Center, + ) + .draw(&mut display) + .unwrap(); + + // Write buffer to display + display.flush().unwrap(); + // Clear display buffer + display.clear(); + + // Wait 5 seconds + block!(timer0.wait()).unwrap(); + } +} diff --git a/esp32c6-hal/examples/i2s_read.rs b/esp32c6-hal/examples/i2s_read.rs new file mode 100644 index 00000000000..5a563a4f994 --- /dev/null +++ b/esp32c6-hal/examples/i2s_read.rs @@ -0,0 +1,100 @@ +//! This shows how to continously receive data via I2S +//! +//! Pins used +//! MCLK GPIO4 +//! BCLK GPIO1 +//! WS GPIO2 +//! DIN GPIO5 +//! +//! Without an additional I2S source device you can connect 3V3 or GND to DIN to +//! read 0 or 0xFF or connect DIN to WS to read two different values +//! +//! You can also inspect the MCLK, BCLK and WS with a logic analyzer + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + dma::DmaPriority, + gdma::Gdma, + i2s::{DataFormat, I2s, I2s0New, I2sReadDma, MclkPin, PinsBclkWsDin, Standard}, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, + IO, +}; +use esp_backtrace as _; +use esp_println::println; +use esp_riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + rtc.rwdt.disable(); + rtc.swd.disable(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + + let dma = Gdma::new(peripherals.DMA, &mut system.peripheral_clock_control); + let dma_channel = dma.channel0; + + let mut tx_descriptors = [0u32; 8 * 3]; + let mut rx_descriptors = [0u32; 8 * 3]; + + let i2s = I2s::new( + peripherals.I2S0, + MclkPin::new(io.pins.gpio4), + Standard::Philips, + DataFormat::Data16Channel16, + 44100u32.Hz(), + dma_channel.configure( + false, + &mut tx_descriptors, + &mut rx_descriptors, + DmaPriority::Priority0, + ), + &mut system.peripheral_clock_control, + &clocks, + ); + + let i2s_rx = i2s.i2s_rx.with_pins(PinsBclkWsDin::new( + io.pins.gpio1, + io.pins.gpio2, + io.pins.gpio5, + )); + + let buffer = dma_buffer(); + + let mut transfer = i2s_rx.read_dma_circular(buffer).unwrap(); + println!("Started transfer"); + + loop { + let avail = transfer.available(); + + if avail > 0 { + let mut rcv = [0u8; 5000]; + transfer.pop(&mut rcv[..avail]).unwrap(); + println!("Received {:x?}...", &rcv[..30]); + } + } +} + +fn dma_buffer() -> &'static mut [u8; 4092 * 4] { + static mut BUFFER: [u8; 4092 * 4] = [0u8; 4092 * 4]; + unsafe { &mut BUFFER } +} diff --git a/esp32c6-hal/examples/i2s_sound.rs b/esp32c6-hal/examples/i2s_sound.rs new file mode 100644 index 00000000000..ddef77005c5 --- /dev/null +++ b/esp32c6-hal/examples/i2s_sound.rs @@ -0,0 +1,139 @@ +//! This shows how to transmit data continously via I2S +//! +//! Pins used +//! MCLK GPIO4 +//! BCLK GPIO1 +//! WS GPIO2 +//! DOUT GPIO3 +//! +//! Without an additional I2S sink device you can inspect the MCLK, BCLK, WS and +//! DOUT with a logic analyzer +//! +//! You can also connect e.g. a PCM510x to hear an annoying loud sine tone (full +//! scale), so turn down the volume before running this example. +//! +//! Wiring is like this +//! +//! | Pin | Connected to | +//! |-------|-----------------| +//! | BCK | GPIO1 | +//! | DIN | GPIO3 | +//! | LRCK | GPIO2 | +//! | SCK | Gnd | +//! | GND | Gnd | +//! | VIN | +3V3 | +//! | FLT | Gnd | +//! | FMT | Gnd | +//! | DEMP | Gnd | +//! | XSMT | +3V3 | + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + dma::DmaPriority, + gdma::Gdma, + i2s::{DataFormat, I2s, I2s0New, I2sWriteDma, MclkPin, PinsBclkWsDout, Standard}, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, + IO, +}; +use esp_backtrace as _; +use esp_riscv_rt::entry; + +const SINE: [i16; 64] = [ + 0, 3211, 6392, 9511, 12539, 15446, 18204, 20787, 23169, 25329, 27244, 28897, 30272, 31356, + 32137, 32609, 32767, 32609, 32137, 31356, 30272, 28897, 27244, 25329, 23169, 20787, 18204, + 15446, 12539, 9511, 6392, 3211, 0, -3211, -6392, -9511, -12539, -15446, -18204, -20787, -23169, + -25329, -27244, -28897, -30272, -31356, -32137, -32609, -32767, -32609, -32137, -31356, -30272, + -28897, -27244, -25329, -23169, -20787, -18204, -15446, -12539, -9511, -6392, -3211, +]; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + // Disable watchdog timers + rtc.swd.disable(); + rtc.rwdt.disable(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + + let dma = Gdma::new(peripherals.DMA, &mut system.peripheral_clock_control); + let dma_channel = dma.channel0; + + let mut tx_descriptors = [0u32; 20 * 3]; + let mut rx_descriptors = [0u32; 8 * 3]; + + let i2s = I2s::new( + peripherals.I2S0, + MclkPin::new(io.pins.gpio4), + Standard::Philips, + DataFormat::Data16Channel16, + 44100u32.Hz(), + dma_channel.configure( + false, + &mut tx_descriptors, + &mut rx_descriptors, + DmaPriority::Priority0, + ), + &mut system.peripheral_clock_control, + &clocks, + ); + + let i2s_tx = i2s.i2s_tx.with_pins(PinsBclkWsDout::new( + io.pins.gpio1, + io.pins.gpio2, + io.pins.gpio3, + )); + + let data = + unsafe { core::slice::from_raw_parts(&SINE as *const _ as *const u8, SINE.len() * 2) }; + + let buffer = dma_buffer(); + let mut idx = 0; + for i in 0..usize::min(data.len(), buffer.len()) { + buffer[i] = data[idx]; + + idx += 1; + + if idx >= data.len() { + idx = 0; + } + } + + let mut filler = [0u8; 10000]; + + let mut transfer = i2s_tx.write_dma_circular(buffer).unwrap(); + loop { + let avail = transfer.available(); + if avail > 0 { + let avail = usize::min(10000, avail); + for bidx in 0..avail { + filler[bidx] = data[idx]; + idx += 1; + + if idx >= data.len() { + idx = 0; + } + } + transfer.push(&filler[0..avail]).unwrap(); + } + } +} + +fn dma_buffer() -> &'static mut [u8; 32000] { + static mut BUFFER: [u8; 32000] = [0u8; 32000]; + unsafe { &mut BUFFER } +} diff --git a/esp32c6-hal/examples/ledc.rs b/esp32c6-hal/examples/ledc.rs new file mode 100644 index 00000000000..cdd3a5b793b --- /dev/null +++ b/esp32c6-hal/examples/ledc.rs @@ -0,0 +1,75 @@ +//! Turns on LED with the option to change LED intensity depending on `duty` +//! value. Possible values (`u32`) are in range 0..100. +//! +//! This assumes that a LED is connected to the pin assigned to `led`. (GPIO4) + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + gpio::IO, + ledc::{ + channel::{self, ChannelIFace}, + timer::{self, TimerIFace}, + LSGlobalClkSource, + LowSpeed, + LEDC, + }, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, +}; +use esp_backtrace as _; +use esp_riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + rtc.rwdt.disable(); + rtc.swd.disable(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let led = io.pins.gpio4.into_push_pull_output(); + + let mut ledc = LEDC::new( + peripherals.LEDC, + &clocks, + &mut system.peripheral_clock_control, + ); + ledc.set_global_slow_clock(LSGlobalClkSource::APBClk); + let mut lstimer0 = ledc.get_timer::(timer::Number::Timer2); + + lstimer0 + .configure(timer::config::Config { + duty: timer::config::Duty::Duty5Bit, + clock_source: timer::LSClockSource::APBClk, + frequency: 24u32.kHz(), + }) + .unwrap(); + + let mut channel0 = ledc.get_channel(channel::Number::Channel0, led); + channel0 + .configure(channel::config::Config { + timer: &lstimer0, + duty_pct: 10, + }) + .unwrap(); + + esp_println::println!("Dd"); + loop {} +} diff --git a/esp32c6-hal/examples/mcpwm.rs b/esp32c6-hal/examples/mcpwm.rs new file mode 100644 index 00000000000..68c2aa9d594 --- /dev/null +++ b/esp32c6-hal/examples/mcpwm.rs @@ -0,0 +1,69 @@ +//! Uses timer0 and operator0 of the MCPWM0 peripheral to output a 50% duty +//! signal at 20 kHz. +//! +//! The signal will be output to the pin assigned to `pin`. (GPIO4) + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + gpio::IO, + mcpwm::{operator::PwmPinConfig, timer::PwmWorkingMode, PeripheralClockConfig, MCPWM}, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, +}; +use esp_backtrace as _; +use esp_riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + rtc.rwdt.disable(); + rtc.swd.disable(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let pin = io.pins.gpio4; + + // initialize peripheral + let clock_cfg = PeripheralClockConfig::with_frequency(&clocks, 40u32.MHz()).unwrap(); + let mut mcpwm = MCPWM::new( + peripherals.MCPWM, + clock_cfg, + &mut system.peripheral_clock_control, + ); + + // connect operator0 to timer0 + mcpwm.operator0.set_timer(&mcpwm.timer0); + // connect operator0 to pin + let mut pwm_pin = mcpwm + .operator0 + .with_pin_a(pin, PwmPinConfig::UP_ACTIVE_HIGH); + + // start timer with timestamp values in the range of 0..=99 and a frequency of + // 20 kHz + let timer_clock_cfg = clock_cfg + .timer_clock_with_frequency(99, PwmWorkingMode::Increase, 20u32.kHz()) + .unwrap(); + mcpwm.timer0.start(timer_clock_cfg); + + // pin will be high 50% of the time + pwm_pin.set_timestamp(50); + + loop {} +} diff --git a/esp32c6-hal/examples/pcnt_encoder.rs b/esp32c6-hal/examples/pcnt_encoder.rs new file mode 100644 index 00000000000..358d1e41616 --- /dev/null +++ b/esp32c6-hal/examples/pcnt_encoder.rs @@ -0,0 +1,150 @@ +//! PCNT Encoder Demo +//! +//! This example decodes a quadrature encoder +//! +//! Since the PCNT units reset to zero when they reach their limits +//! we enable an interrupt on the upper and lower limits and +//! track the overflow in an AtomicI32 + +#![no_std] +#![no_main] +use core::{ + cell::RefCell, + cmp::min, + sync::atomic::{AtomicI32, Ordering}, +}; + +use critical_section::Mutex; +use esp32c6_hal as esp_hal; +use esp_backtrace as _; +use esp_hal::{ + clock::ClockControl, + interrupt, + pcnt::{channel, channel::PcntSource, unit, PCNT}, + peripherals::{self, Peripherals}, + prelude::*, + timer::TimerGroup, + Rtc, + IO, +}; +use esp_println::println; +use esp_riscv_rt::entry; + +static UNIT0: Mutex>> = Mutex::new(RefCell::new(None)); +static VALUE: AtomicI32 = AtomicI32::new(0); + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + rtc.rwdt.disable(); + rtc.swd.disable(); + + let unit_number = unit::Number::Unit1; + + // setup a pulse couter + println!("setup pulse counter unit 0"); + let pcnt = PCNT::new(peripherals.PCNT, &mut system.peripheral_clock_control); + let mut u0 = pcnt.get_unit(unit_number); + u0.configure(unit::Config { + low_limit: -100, + high_limit: 100, + filter: Some(min(10u16 * 80, 1023u16)), + ..Default::default() + }) + .unwrap(); + + println!("setup channel 0"); + let mut ch0 = u0.get_channel(channel::Number::Channel0); + let mut pin_a = io.pins.gpio5.into_pull_up_input(); + let mut pin_b = io.pins.gpio6.into_pull_up_input(); + + ch0.configure( + PcntSource::from_pin(&mut pin_a), + PcntSource::from_pin(&mut pin_b), + channel::Config { + lctrl_mode: channel::CtrlMode::Reverse, + hctrl_mode: channel::CtrlMode::Keep, + pos_edge: channel::EdgeMode::Decrement, + neg_edge: channel::EdgeMode::Increment, + invert_ctrl: false, + invert_sig: false, + }, + ); + + println!("setup channel 1"); + let mut ch1 = u0.get_channel(channel::Number::Channel1); + ch1.configure( + PcntSource::from_pin(&mut pin_b), + PcntSource::from_pin(&mut pin_a), + channel::Config { + lctrl_mode: channel::CtrlMode::Reverse, + hctrl_mode: channel::CtrlMode::Keep, + pos_edge: channel::EdgeMode::Increment, + neg_edge: channel::EdgeMode::Decrement, + invert_ctrl: false, + invert_sig: false, + }, + ); + println!("subscribing to events"); + u0.events(unit::Events { + low_limit: true, + high_limit: true, + thresh0: false, + thresh1: false, + zero: false, + }); + + println!("enabling interrupts"); + u0.listen(); + println!("resume pulse counter unit 0"); + u0.resume(); + + critical_section::with(|cs| UNIT0.borrow_ref_mut(cs).replace(u0)); + + interrupt::enable(peripherals::Interrupt::PCNT, interrupt::Priority::Priority2).unwrap(); + + let mut last_value: i32 = 0; + loop { + critical_section::with(|cs| { + let mut u0 = UNIT0.borrow_ref_mut(cs); + let u0 = u0.as_mut().unwrap(); + let value: i32 = u0.get_value() as i32 + VALUE.load(Ordering::SeqCst); + if value != last_value { + println!("value: {value}"); + last_value = value; + } + }); + } +} + +#[interrupt] +fn PCNT() { + critical_section::with(|cs| { + let mut u0 = UNIT0.borrow_ref_mut(cs); + let u0 = u0.as_mut().unwrap(); + if u0.interrupt_set() { + let events = u0.get_events(); + if events.high_limit { + VALUE.fetch_add(100, Ordering::SeqCst); + } else if events.low_limit { + VALUE.fetch_add(-100, Ordering::SeqCst); + } + u0.reset_interrupt(); + } + }); +} diff --git a/esp32c6-hal/examples/pulse_control.rs b/esp32c6-hal/examples/pulse_control.rs new file mode 100644 index 00000000000..e2cd2ef6fee --- /dev/null +++ b/esp32c6-hal/examples/pulse_control.rs @@ -0,0 +1,90 @@ +//! This demos basic usage of RMT / PulseControl +//! Use a logic analyzer to see the generated pulses. +//! The correct output is only achieved when running in release mode. + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + gpio::IO, + peripherals::Peripherals, + prelude::*, + pulse_control::{ClockSource, ConfiguredChannel, OutputChannel, PulseCode, RepeatMode}, + timer::TimerGroup, + PulseControl, + Rtc, +}; +use esp_backtrace as _; +use esp_riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + rtc.rwdt.disable(); + rtc.swd.disable(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + + // Configure RMT peripheral globally + let pulse = PulseControl::new( + peripherals.RMT, + &mut system.peripheral_clock_control, + ClockSource::APB, + 0, + 0, + 0, + ) + .unwrap(); + + let mut rmt_channel0 = pulse.channel0; + + // Set up channel + rmt_channel0 + .set_idle_output_level(false) + .set_carrier_modulation(false) + .set_channel_divider(1) + .set_idle_output(true); + + // Assign GPIO pin where pulses should be sent to + let mut rmt_channel0 = rmt_channel0.assign_pin(io.pins.gpio4); + + // Create pulse sequence + let mut seq = [PulseCode { + level1: true, + length1: 0u32.nanos(), + level2: false, + length2: 0u32.nanos(), + }; 128]; + + // -1 to make sure that the last element is a transmission end marker (i.e. + // lenght 0) + for i in 0..(seq.len() - 1) { + seq[i] = PulseCode { + level1: true, + length1: (10u32 * (i as u32 + 1u32)).nanos(), + level2: false, + length2: 60u32.nanos(), + }; + } + + loop { + // Send sequence + rmt_channel0 + .send_pulse_sequence(RepeatMode::SingleShot, &seq) + .unwrap(); + } +} diff --git a/esp32c6-hal/examples/read_efuse.rs b/esp32c6-hal/examples/read_efuse.rs new file mode 100644 index 00000000000..831563ff006 --- /dev/null +++ b/esp32c6-hal/examples/read_efuse.rs @@ -0,0 +1,39 @@ +//! This shows how to read selected information from eFuses. +//! e.g. the MAC address + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + efuse::Efuse, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; +use esp_riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + // Disable watchdog timers + rtc.swd.disable(); + rtc.rwdt.disable(); + + println!("MAC address {:02x?}", Efuse::get_mac_address()); + println!("Flash Encryption {:?}", Efuse::get_flash_encryption()); + + loop {} +} diff --git a/esp32c6-hal/examples/serial_interrupts.rs b/esp32c6-hal/examples/serial_interrupts.rs new file mode 100644 index 00000000000..5b3179c2e6f --- /dev/null +++ b/esp32c6-hal/examples/serial_interrupts.rs @@ -0,0 +1,102 @@ +//! This shows some of the interrupts that can be generated by UART/Serial. +//! Use a proper serial terminal to connect to the board (espmonitor and +//! espflash won't work) + +#![no_std] +#![no_main] + +use core::{cell::RefCell, fmt::Write}; + +use critical_section::Mutex; +use esp32c6_hal::{ + clock::ClockControl, + interrupt, + peripherals::{self, Peripherals, UART0}, + prelude::*, + timer::TimerGroup, + uart::config::AtCmdConfig, + Cpu, + Rtc, + Uart, +}; +use esp_backtrace as _; +use esp_riscv_rt::{entry, riscv}; +use nb::block; + +static SERIAL: Mutex>>> = Mutex::new(RefCell::new(None)); + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let mut serial0 = Uart::new(peripherals.UART0); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut timer0 = timer_group0.timer0; + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + // Disable watchdog timers + rtc.swd.disable(); + rtc.rwdt.disable(); + + serial0.set_at_cmd(AtCmdConfig::new(None, None, None, b'#', None)); + serial0.set_rx_fifo_full_threshold(30); + serial0.listen_at_cmd(); + serial0.listen_rx_fifo_full(); + + timer0.start(1u64.secs()); + + critical_section::with(|cs| SERIAL.borrow_ref_mut(cs).replace(serial0)); + + interrupt::enable( + peripherals::Interrupt::UART0, + interrupt::Priority::Priority1, + ) + .unwrap(); + interrupt::set_kind( + Cpu::ProCpu, + interrupt::CpuInterrupt::Interrupt1, // Interrupt 1 handles priority one interrupts + interrupt::InterruptKind::Edge, + ); + + unsafe { + riscv::interrupt::enable(); + } + + loop { + critical_section::with(|cs| { + writeln!(SERIAL.borrow_ref_mut(cs).as_mut().unwrap(), "Hello World! Send a single `#` character or send at least 30 characters and see the interrupts trigger.").ok(); + }); + + block!(timer0.wait()).unwrap(); + } +} + +#[interrupt] +fn UART0() { + critical_section::with(|cs| { + let mut serial = SERIAL.borrow_ref_mut(cs); + let serial = serial.as_mut().unwrap(); + + let mut cnt = 0; + while let nb::Result::Ok(_c) = serial.read() { + cnt += 1; + } + writeln!(serial, "Read {} bytes", cnt,).ok(); + + writeln!( + serial, + "Interrupt AT-CMD: {} RX-FIFO-FULL: {}", + serial.at_cmd_interrupt_set(), + serial.rx_fifo_full_interrupt_set(), + ) + .ok(); + + serial.reset_at_cmd_interrupt(); + serial.reset_rx_fifo_full_interrupt(); + }); +} diff --git a/esp32c6-hal/examples/sha.rs b/esp32c6-hal/examples/sha.rs new file mode 100644 index 00000000000..70f4d55c572 --- /dev/null +++ b/esp32c6-hal/examples/sha.rs @@ -0,0 +1,82 @@ +//! Demonstrates the use of the SHA peripheral and compares the speed of +//! hardware-accelerated and pure software hashing. + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + peripherals::Peripherals, + prelude::*, + sha::{Sha, ShaMode}, + timer::TimerGroup, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; +use esp_riscv_rt::entry; +use nb::block; +use sha2::{Digest, Sha256}; + +#[entry] +fn main() -> ! { + // TODO: need to debug + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt = timer_group0.wdt; + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + wdt.disable(); + rtc.rwdt.disable(); + + let source_data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa".as_bytes(); + let mut remaining = source_data.clone(); + let mut hasher = Sha::new(peripherals.SHA, ShaMode::SHA256); + + // Short hashes can be created by decreasing the output buffer to the desired + // length + let mut output = [0u8; 32]; + + // let pre_calc = xtensa_lx::timer::get_cycle_count(); + // The hardware implementation takes a subslice of the input, and returns the + // unprocessed parts The unprocessed parts can be input in the next + // iteration, you can always add more data until finish() is called. After + // finish() is called update()'s will contribute to a new hash which + // can be extracted again with finish(). + + while remaining.len() > 0 { + // Can add println to view progress, however println takes a few orders of + // magnitude longer than the Sha function itself so not useful for + // comparing processing time println!("Remaining len: {}", + // remaining.len()); + + // All the HW Sha functions are infallible so unwrap is fine to use if you use + // block! + remaining = block!(hasher.update(remaining)).unwrap(); + } + + // Finish can be called as many times as desired to get mutliple copies of the + // output. + block!(hasher.finish(output.as_mut_slice())).unwrap(); + // let post_calc = xtensa_lx::timer::get_cycle_count(); + // let hw_time = post_calc - pre_calc; + // println!("Took {} cycles", hw_time); + println!("SHA256 Hash output {:02x?}", output); + + // let pre_calc = xtensa_lx::timer::get_cycle_count(); + let mut hasher = Sha256::new(); + hasher.update(source_data); + let soft_result = hasher.finalize(); + // let post_calc = xtensa_lx::timer::get_cycle_count(); + // let soft_time = post_calc - pre_calc; + // println!("Took {} cycles", soft_time); + println!("SHA256 Hash output {:02x?}", soft_result); + + // println!("HW SHA is {}x faster", soft_time/hw_time); + + loop {} +} diff --git a/esp32c6-hal/examples/spi_eh1_device_loopback.rs b/esp32c6-hal/examples/spi_eh1_device_loopback.rs new file mode 100644 index 00000000000..caf35a5e63a --- /dev/null +++ b/esp32c6-hal/examples/spi_eh1_device_loopback.rs @@ -0,0 +1,151 @@ +//! SPI loopback test +//! +//! Folowing pins are used: +//! SCLK GPIO6 +//! MISO GPIO2 +//! MOSI GPIO7 +//! CS 1 GPIO3 +//! CS 2 GPIO4 +//! CS 3 GPIO5 +//! +//! Depending on your target and the board you are using you have to change the +//! pins. +//! +//! This example transfers data via SPI. +//! Connect MISO and MOSI pins to see the outgoing data is read as incoming +//! data. + +#![no_std] +#![no_main] + +use embedded_hal_1::spi::SpiDevice; +use esp32c6_hal::{ + clock::ClockControl, + gpio::IO, + peripherals::Peripherals, + prelude::*, + spi::{Spi, SpiBusController, SpiMode}, + timer::TimerGroup, + Delay, + Rtc, +}; +use esp_backtrace as _; +use esp_println::{print, println}; +use esp_riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // the RTC WDT, and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + rtc.swd.disable(); + rtc.rwdt.disable(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let sclk = io.pins.gpio6; + let miso = io.pins.gpio2; + let mosi = io.pins.gpio7; + + let spi_controller = SpiBusController::from_spi(Spi::new_no_cs( + peripherals.SPI2, + sclk, + mosi, + miso, + 1000u32.kHz(), + SpiMode::Mode0, + &mut system.peripheral_clock_control, + &clocks, + )); + let mut spi_device_1 = spi_controller.add_device(io.pins.gpio3); + let mut spi_device_2 = spi_controller.add_device(io.pins.gpio4); + let mut spi_device_3 = spi_controller.add_device(io.pins.gpio5); + + let mut delay = Delay::new(&clocks); + println!("=== SPI example with embedded-hal-1 traits ==="); + + loop { + // --- Symmetric transfer (Read as much as we write) --- + print!("Starting symmetric transfer..."); + let write = [0xde, 0xad, 0xbe, 0xef]; + let mut read: [u8; 4] = [0x00u8; 4]; + + spi_device_1.transfer(&mut read[..], &write[..]).unwrap(); + assert_eq!(write, read); + spi_device_2.transfer(&mut read[..], &write[..]).unwrap(); + spi_device_3.transfer(&mut read[..], &write[..]).unwrap(); + println!(" SUCCESS"); + delay.delay_ms(250u32); + + // --- Asymmetric transfer (Read more than we write) --- + print!("Starting asymetric transfer (read > write)..."); + let mut read: [u8; 4] = [0x00; 4]; + + spi_device_1 + .transfer(&mut read[0..2], &write[..]) + .expect("Asymmetric transfer failed"); + assert_eq!(write[0], read[0]); + assert_eq!(read[2], 0x00u8); + spi_device_2 + .transfer(&mut read[0..2], &write[..]) + .expect("Asymmetric transfer failed"); + spi_device_3 + .transfer(&mut read[0..2], &write[..]) + .expect("Asymmetric transfer failed"); + println!(" SUCCESS"); + delay.delay_ms(250u32); + + // --- Symmetric transfer with huge buffer --- + // Only your RAM is the limit! + print!("Starting huge transfer..."); + let mut write = [0x55u8; 4096]; + for byte in 0..write.len() { + write[byte] = byte as u8; + } + let mut read = [0x00u8; 4096]; + + spi_device_1 + .transfer(&mut read[..], &write[..]) + .expect("Huge transfer failed"); + assert_eq!(write, read); + spi_device_2 + .transfer(&mut read[..], &write[..]) + .expect("Huge transfer failed"); + spi_device_3 + .transfer(&mut read[..], &write[..]) + .expect("Huge transfer failed"); + println!(" SUCCESS"); + delay.delay_ms(250u32); + + // --- Symmetric transfer with huge buffer in-place (No additional allocation + // needed) --- + print!("Starting huge transfer (in-place)..."); + let mut write = [0x55u8; 4096]; + for byte in 0..write.len() { + write[byte] = byte as u8; + } + + spi_device_1 + .transfer_in_place(&mut write[..]) + .expect("Huge transfer failed"); + for byte in 0..write.len() { + assert_eq!(write[byte], byte as u8); + } + spi_device_2 + .transfer_in_place(&mut write[..]) + .expect("Huge transfer failed"); + spi_device_3 + .transfer_in_place(&mut write[..]) + .expect("Huge transfer failed"); + println!(" SUCCESS"); + delay.delay_ms(250u32); + } +} diff --git a/esp32c6-hal/examples/spi_eh1_loopback.rs b/esp32c6-hal/examples/spi_eh1_loopback.rs new file mode 100644 index 00000000000..3e45dc8c34b --- /dev/null +++ b/esp32c6-hal/examples/spi_eh1_loopback.rs @@ -0,0 +1,123 @@ +//! SPI loopback test +//! +//! Folowing pins are used: +//! SCLK GPIO6 +//! MISO GPIO2 +//! MOSI GPIO7 +//! CS GPIO10 +//! +//! Depending on your target and the board you are using you have to change the +//! pins. +//! +//! This example transfers data via SPI. +//! Connect MISO and MOSI pins to see the outgoing data is read as incoming +//! data. + +#![no_std] +#![no_main] + +use embedded_hal_1::spi::SpiBus; +use esp32c6_hal::{ + clock::ClockControl, + gpio::IO, + peripherals::Peripherals, + prelude::*, + spi::{Spi, SpiMode}, + timer::TimerGroup, + Delay, + Rtc, +}; +use esp_backtrace as _; +use esp_println::{print, println}; +use esp_riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // the RTC WDT, and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + rtc.swd.disable(); + rtc.rwdt.disable(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let sclk = io.pins.gpio6; + let miso = io.pins.gpio2; + let mosi = io.pins.gpio7; + let cs = io.pins.gpio10; + + let mut spi = Spi::new( + peripherals.SPI2, + sclk, + mosi, + miso, + cs, + 1000u32.kHz(), + SpiMode::Mode0, + &mut system.peripheral_clock_control, + &clocks, + ); + + let mut delay = Delay::new(&clocks); + println!("=== SPI example with embedded-hal-1 traits ==="); + + loop { + // --- Symmetric transfer (Read as much as we write) --- + print!("Starting symmetric transfer..."); + let write = [0xde, 0xad, 0xbe, 0xef]; + let mut read: [u8; 4] = [0x00u8; 4]; + + SpiBus::transfer(&mut spi, &mut read[..], &write[..]).expect("Symmetric transfer failed"); + assert_eq!(write, read); + println!(" SUCCESS"); + delay.delay_ms(250u32); + + // --- Asymmetric transfer (Read more than we write) --- + print!("Starting asymetric transfer (read > write)..."); + let mut read: [u8; 4] = [0x00; 4]; + + SpiBus::transfer(&mut spi, &mut read[0..2], &write[..]) + .expect("Asymmetric transfer failed"); + assert_eq!(write[0], read[0]); + assert_eq!(read[2], 0x00u8); + println!(" SUCCESS"); + delay.delay_ms(250u32); + + // --- Symmetric transfer with huge buffer --- + // Only your RAM is the limit! + print!("Starting huge transfer..."); + let mut write = [0x55u8; 4096]; + for byte in 0..write.len() { + write[byte] = byte as u8; + } + let mut read = [0x00u8; 4096]; + + SpiBus::transfer(&mut spi, &mut read[..], &write[..]).expect("Huge transfer failed"); + assert_eq!(write, read); + println!(" SUCCESS"); + delay.delay_ms(250u32); + + // --- Symmetric transfer with huge buffer in-place (No additional allocation + // needed) --- + print!("Starting huge transfer (in-place)..."); + let mut write = [0x55u8; 4096]; + for byte in 0..write.len() { + write[byte] = byte as u8; + } + + SpiBus::transfer_in_place(&mut spi, &mut write[..]).expect("Huge transfer failed"); + for byte in 0..write.len() { + assert_eq!(write[byte], byte as u8); + } + println!(" SUCCESS"); + delay.delay_ms(250u32); + } +} diff --git a/esp32c6-hal/examples/spi_loopback.rs b/esp32c6-hal/examples/spi_loopback.rs new file mode 100644 index 00000000000..f27d3c5fcaa --- /dev/null +++ b/esp32c6-hal/examples/spi_loopback.rs @@ -0,0 +1,79 @@ +//! SPI loopback test +//! +//! Folowing pins are used: +//! SCLK GPIO6 +//! MISO GPIO2 +//! MOSI GPIO7 +//! CS GPIO10 +//! +//! Depending on your target and the board you are using you have to change the +//! pins. +//! +//! This example transfers data via SPI. +//! Connect MISO and MOSI pins to see the outgoing data is read as incoming +//! data. + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + gpio::IO, + peripherals::Peripherals, + prelude::*, + spi::{Spi, SpiMode}, + timer::TimerGroup, + Delay, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; +use esp_riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + rtc.rwdt.disable(); + rtc.swd.disable(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let sclk = io.pins.gpio6; + let miso = io.pins.gpio2; + let mosi = io.pins.gpio7; + let cs = io.pins.gpio10; + + let mut spi = Spi::new( + peripherals.SPI2, + sclk, + mosi, + miso, + cs, + 100u32.kHz(), + SpiMode::Mode0, + &mut system.peripheral_clock_control, + &clocks, + ); + + let mut delay = Delay::new(&clocks); + + loop { + let mut data = [0xde, 0xca, 0xfb, 0xad]; + spi.transfer(&mut data).unwrap(); + println!("{:x?}", data); + + delay.delay_ms(250u32); + } +} diff --git a/esp32c6-hal/examples/spi_loopback_dma.rs b/esp32c6-hal/examples/spi_loopback_dma.rs new file mode 100644 index 00000000000..27e2cd4d612 --- /dev/null +++ b/esp32c6-hal/examples/spi_loopback_dma.rs @@ -0,0 +1,123 @@ +//! SPI loopback test using DMA +//! +//! Folowing pins are used: +//! SCLK GPIO6 +//! MISO GPIO2 +//! MOSI GPIO7 +//! CS GPIO10 +//! +//! Depending on your target and the board you are using you have to change the +//! pins. +//! +//! This example transfers data via SPI. +//! Connect MISO and MOSI pins to see the outgoing data is read as incoming +//! data. + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + dma::DmaPriority, + gdma::Gdma, + gpio::IO, + peripherals::Peripherals, + prelude::*, + spi::{Spi, SpiMode}, + timer::TimerGroup, + Delay, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; +use esp_riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + rtc.rwdt.disable(); + rtc.swd.disable(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let sclk = io.pins.gpio6; + let miso = io.pins.gpio2; + let mosi = io.pins.gpio7; + let cs = io.pins.gpio10; + + let dma = Gdma::new(peripherals.DMA, &mut system.peripheral_clock_control); + let dma_channel = dma.channel0; + + let mut descriptors = [0u32; 8 * 3]; + let mut rx_descriptors = [0u32; 8 * 3]; + + let mut spi = Spi::new( + peripherals.SPI2, + sclk, + mosi, + miso, + cs, + 100u32.kHz(), + SpiMode::Mode0, + &mut system.peripheral_clock_control, + &clocks, + ) + .with_dma(dma_channel.configure( + false, + &mut descriptors, + &mut rx_descriptors, + DmaPriority::Priority0, + )); + + let mut delay = Delay::new(&clocks); + + // DMA buffer require a static life-time + let mut send = buffer1(); + let mut receive = buffer2(); + let mut i = 0; + + for (i, v) in send.iter_mut().enumerate() { + *v = (i % 255) as u8; + } + + loop { + send[0] = i; + send[send.len() - 1] = i; + i = i.wrapping_add(1); + + let transfer = spi.dma_transfer(send, receive).unwrap(); + // here we could do something else while DMA transfer is in progress + // the buffers and spi is moved into the transfer and we can get it back via + // `wait` + (receive, send, spi) = transfer.wait(); + println!( + "{:x?} .. {:x?}", + &receive[..10], + &receive[receive.len() - 10..] + ); + + delay.delay_ms(250u32); + } +} + +fn buffer1() -> &'static mut [u8; 32000] { + static mut BUFFER: [u8; 32000] = [0u8; 32000]; + unsafe { &mut BUFFER } +} + +fn buffer2() -> &'static mut [u8; 32000] { + static mut BUFFER: [u8; 32000] = [0u8; 32000]; + unsafe { &mut BUFFER } +} diff --git a/esp32c6-hal/examples/systimer.rs b/esp32c6-hal/examples/systimer.rs new file mode 100644 index 00000000000..d33982fe195 --- /dev/null +++ b/esp32c6-hal/examples/systimer.rs @@ -0,0 +1,130 @@ +//! This shows how to use the SYSTIMER peripheral including interrupts. +//! It's an additional timer besides the TIMG peripherals. + +#![no_std] +#![no_main] + +use core::cell::RefCell; + +use critical_section::Mutex; +use esp32c6_hal::{ + clock::ClockControl, + interrupt, + interrupt::Priority, + peripherals::{self, Peripherals}, + prelude::*, + systimer::{Alarm, Periodic, SystemTimer, Target}, + timer::TimerGroup, + Delay, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; +use esp_riscv_rt::entry; + +static ALARM0: Mutex>>> = Mutex::new(RefCell::new(None)); +static ALARM1: Mutex>>> = Mutex::new(RefCell::new(None)); +static ALARM2: Mutex>>> = Mutex::new(RefCell::new(None)); + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + rtc.rwdt.disable(); + rtc.swd.disable(); + + let syst = SystemTimer::new(peripherals.SYSTIMER); + + println!("SYSTIMER Current value = {}", SystemTimer::now()); + + let alarm0 = syst.alarm0.into_periodic(); + alarm0.set_period(1u32.Hz()); + alarm0.clear_interrupt(); + alarm0.interrupt_enable(true); + + let alarm1 = syst.alarm1; + alarm1.set_target(SystemTimer::now() + (SystemTimer::TICKS_PER_SECOND * 2)); + alarm1.interrupt_enable(true); + + let alarm2 = syst.alarm2; + alarm2.set_target(SystemTimer::now() + (SystemTimer::TICKS_PER_SECOND * 3)); + alarm2.interrupt_enable(true); + + critical_section::with(|cs| { + ALARM0.borrow_ref_mut(cs).replace(alarm0); + ALARM1.borrow_ref_mut(cs).replace(alarm1); + ALARM2.borrow_ref_mut(cs).replace(alarm2); + }); + + interrupt::enable( + peripherals::Interrupt::SYSTIMER_TARGET0, + Priority::Priority1, + ) + .unwrap(); + interrupt::enable( + peripherals::Interrupt::SYSTIMER_TARGET1, + Priority::Priority2, + ) + .unwrap(); + interrupt::enable( + peripherals::Interrupt::SYSTIMER_TARGET2, + Priority::Priority2, + ) + .unwrap(); + + // Initialize the Delay peripheral, and use it to toggle the LED state in a + // loop. + let mut delay = Delay::new(&clocks); + + loop { + delay.delay_ms(10000u32); + } +} + +#[interrupt] +fn SYSTIMER_TARGET0() { + println!("Interrupt lvl1 (alarm0)"); + critical_section::with(|cs| { + ALARM0 + .borrow_ref_mut(cs) + .as_mut() + .unwrap() + .clear_interrupt() + }); +} + +#[interrupt] +fn SYSTIMER_TARGET1() { + println!("Interrupt lvl2 (alarm1)"); + critical_section::with(|cs| { + ALARM1 + .borrow_ref_mut(cs) + .as_mut() + .unwrap() + .clear_interrupt() + }); +} + +#[interrupt] +fn SYSTIMER_TARGET2() { + println!("Interrupt lvl2 (alarm2)"); + critical_section::with(|cs| { + ALARM2 + .borrow_ref_mut(cs) + .as_mut() + .unwrap() + .clear_interrupt() + }); +} diff --git a/esp32c6-hal/examples/timer_interrupt.rs b/esp32c6-hal/examples/timer_interrupt.rs new file mode 100644 index 00000000000..d1a3bedf1f0 --- /dev/null +++ b/esp32c6-hal/examples/timer_interrupt.rs @@ -0,0 +1,101 @@ +//! This shows how to use the TIMG peripheral interrupts. +//! There is TIMG0 and TIMG1 each of them containing a general purpose timer and +//! a watchdog timer. + +#![no_std] +#![no_main] + +use core::cell::RefCell; + +use critical_section::Mutex; +use esp32c6_hal::{ + clock::ClockControl, + interrupt, + peripherals::{self, Peripherals, TIMG0, TIMG1}, + prelude::*, + timer::{Timer, Timer0, TimerGroup}, + Rtc, +}; +use esp_backtrace as _; +use esp_riscv_rt::{entry, riscv}; + +static TIMER0: Mutex>>>> = Mutex::new(RefCell::new(None)); +static TIMER1: Mutex>>>> = Mutex::new(RefCell::new(None)); + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut timer0 = timer_group0.timer0; + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let mut timer1 = timer_group1.timer0; + let _wdt1 = timer_group1.wdt; + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + rtc.rwdt.disable(); + rtc.swd.disable(); + + interrupt::enable( + peripherals::Interrupt::TG0_T0_LEVEL, + interrupt::Priority::Priority2, + ) + .unwrap(); + + timer0.start(500u64.millis()); + + timer0.listen(); + + interrupt::enable( + peripherals::Interrupt::TG1_T0_LEVEL, + interrupt::Priority::Priority2, + ) + .unwrap(); + + timer1.start(1u64.secs()); + timer1.listen(); + + critical_section::with(|cs| { + TIMER0.borrow_ref_mut(cs).replace(timer0); + TIMER1.borrow_ref_mut(cs).replace(timer1); + }); + + unsafe { + riscv::interrupt::enable(); + } + + loop {} +} + +#[interrupt] +fn TG0_T0_LEVEL() { + critical_section::with(|cs| { + esp_println::println!("Interrupt 1"); + + let mut timer0 = TIMER0.borrow_ref_mut(cs); + let timer0 = timer0.as_mut().unwrap(); + + timer0.clear_interrupt(); + timer0.start(10000u64.millis()); + }); +} + +#[interrupt] +fn TG1_T0_LEVEL() { + critical_section::with(|cs| { + esp_println::println!("Interrupt 11"); + + let mut timer1 = TIMER1.borrow_ref_mut(cs); + let timer1 = timer1.as_mut().unwrap(); + + timer1.clear_interrupt(); + timer1.start(19500u64.millis()); + }); +} diff --git a/esp32c6-hal/examples/usb_serial_jtag.rs b/esp32c6-hal/examples/usb_serial_jtag.rs new file mode 100644 index 00000000000..50972b20893 --- /dev/null +++ b/esp32c6-hal/examples/usb_serial_jtag.rs @@ -0,0 +1,94 @@ +//! This shows how to output text via USB Serial/JTAG. +//! You need to connect via the Serial/JTAG interface to see any output. +//! Most dev-kits use a USB-UART-bridge - in that case you won't see any output. + +#![no_std] +#![no_main] + +use core::{cell::RefCell, fmt::Write}; + +use critical_section::Mutex; +use esp32c6_hal::{ + clock::ClockControl, + interrupt, + peripherals::{self, Peripherals, USB_DEVICE}, + prelude::*, + timer::TimerGroup, + Cpu, + Rtc, + UsbSerialJtag, +}; +use esp_backtrace as _; +use esp_riscv_rt::{entry, riscv}; +use nb::block; + +static USB_SERIAL: Mutex>>> = + Mutex::new(RefCell::new(None)); + +#[entry] +fn main() -> ! { + // TODO: test this + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut timer0 = timer_group0.timer0; + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + // Disable watchdog timers + rtc.swd.disable(); + rtc.rwdt.disable(); + + let mut usb_serial = UsbSerialJtag::new(peripherals.USB_DEVICE); + + usb_serial.listen_rx_packet_recv_interrupt(); + + timer0.start(1u64.secs()); + + critical_section::with(|cs| USB_SERIAL.borrow_ref_mut(cs).replace(usb_serial)); + + interrupt::enable( + peripherals::Interrupt::USB_SERIAL_JTAG, + interrupt::Priority::Priority1, + ) + .unwrap(); + + interrupt::set_kind( + Cpu::ProCpu, + interrupt::CpuInterrupt::Interrupt1, + interrupt::InterruptKind::Edge, + ); + + unsafe { + riscv::interrupt::enable(); + } + + loop { + critical_section::with(|cs| { + writeln!( + USB_SERIAL.borrow_ref_mut(cs).as_mut().unwrap(), + "Hello world!" + ) + .ok(); + }); + + block!(timer0.wait()).unwrap(); + } +} + +#[interrupt] +fn USB_SERIAL_JTAG() { + critical_section::with(|cs| { + let mut usb_serial = USB_SERIAL.borrow_ref_mut(cs); + let usb_serial = usb_serial.as_mut().unwrap(); + writeln!(usb_serial, "USB serial interrupt").unwrap(); + while let nb::Result::Ok(c) = usb_serial.read_byte() { + writeln!(usb_serial, "Read byte: {:02x}", c).unwrap(); + } + usb_serial.reset_rx_packet_recv_interrupt(); + }); +} diff --git a/esp32c6-hal/examples/watchdog.rs b/esp32c6-hal/examples/watchdog.rs new file mode 100644 index 00000000000..1b81f3f0a90 --- /dev/null +++ b/esp32c6-hal/examples/watchdog.rs @@ -0,0 +1,45 @@ +//! This demos the watchdog timer. +//! Basically the same as `hello_world` but if you remove the call to +//! `wdt.feed()` the watchdog will reset the system. + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; +use esp_riscv_rt::entry; +use nb::block; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut timer0 = timer_group0.timer0; + let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + // Disable watchdog timers + rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.start(2u64.secs()); + + timer0.start(1u64.secs()); + + loop { + wdt0.feed(); + println!("Hello world!"); + block!(timer0.wait()).unwrap(); + } +} diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index 763869b3515..09c4a4d903d 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -4,28 +4,34 @@ use core::arch::{asm, global_asm}; pub use embedded_hal as ehal; pub use esp_hal_common::{ + aes, clock, dma, dma::gdma, + efuse, gpio, i2c, i2s, interrupt, ledc, macros, + mcpwm, + pcnt, peripherals, prelude, pulse_control, + sha, spi, systimer, timer, uart, + utils, Cpu, Delay, PulseControl, - utils, - Uart, Rtc, + Uart, + UsbSerialJtag, }; pub use self::gpio::IO; From b7f03167de09fd6b5f140782b262d3269da84c62 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Tue, 7 Feb 2023 10:11:57 -0800 Subject: [PATCH 33/64] Remove inline assembly, fix interrupts and linker scripts --- esp-hal-common/src/interrupt/riscv.rs | 4 +- esp32c6-hal/ld/bl-riscv-link.x | 3 +- esp32c6-hal/ld/db-riscv-link.x | 11 +- esp32c6-hal/src/lib.rs | 210 -------------------------- 4 files changed, 11 insertions(+), 217 deletions(-) diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index 54730dfbfd9..be1f24b4eb2 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -689,11 +689,11 @@ unsafe fn handle_exception(pc: usize, trap_frame: *mut TrapFrame) { #[no_mangle] pub fn _setup_interrupts() { extern "C" { - static _vector_table_hal: *const u32; + static _vector_table: *const u32; } unsafe { - let vec_table = &_vector_table_hal as *const _ as usize; + let vec_table = &_vector_table as *const _ as usize; mtvec::write(vec_table, mtvec::TrapMode::Vectored); #[cfg(feature = "vectored")] diff --git a/esp32c6-hal/ld/bl-riscv-link.x b/esp32c6-hal/ld/bl-riscv-link.x index 33c4229d43c..82e1b39629e 100644 --- a/esp32c6-hal/ld/bl-riscv-link.x +++ b/esp32c6-hal/ld/bl-riscv-link.x @@ -1,5 +1,4 @@ -ENTRY(_start_hal) -PROVIDE(_start_trap = _start_trap_hal); +ENTRY(_start) PROVIDE(_stext = ORIGIN(REGION_TEXT)); PROVIDE(_stack_start = ORIGIN(RAM) + LENGTH(RAM)); diff --git a/esp32c6-hal/ld/db-riscv-link.x b/esp32c6-hal/ld/db-riscv-link.x index 9033f790b75..183304cfd0f 100644 --- a/esp32c6-hal/ld/db-riscv-link.x +++ b/esp32c6-hal/ld/db-riscv-link.x @@ -1,5 +1,4 @@ -ENTRY(_start_hal) -PROVIDE(_start_trap = _start_trap_hal); +ENTRY(_start) PROVIDE(_stext = ORIGIN(REGION_TEXT)); PROVIDE(_stack_start = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK)); @@ -37,6 +36,12 @@ PROVIDE(_setup_interrupts = default_setup_interrupts); */ PROVIDE(_mp_hook = default_mp_hook); +/* # Start trap function override + By default uses the riscv crates default trap handler + but by providing the `_start_trap` symbol external crates can override. +*/ +PROVIDE(_start_trap = default_start_trap); + SECTIONS { .text.dummy (NOLOAD) : @@ -235,4 +240,4 @@ then modify your build script to compile the C code _without_ the -fPIC flag. See the documentation of the `gcc::Config.fpic` method for details."); -/* Do not exceed this mark in the error messages above | */ \ No newline at end of file +/* Do not exceed this mark in the error messages above | */ diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index 09c4a4d903d..c88d101f079 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -1,7 +1,5 @@ #![no_std] -use core::arch::{asm, global_asm}; - pub use embedded_hal as ehal; pub use esp_hal_common::{ aes, @@ -66,214 +64,6 @@ extern "C" { static mut _irtc_fast_data: u32; } -global_asm!( - r#" -.section .trap, "ax" -.balign 0x100 -.global _vector_table_hal -.type _vector_table_hal, @function -.option norelax - -_vector_table_hal: - .option push - .option norvc - .rept 31 - j _start_trap_hal - .endr -"# -); - -global_asm!( - r#" - /* - Trap entry point (_start_trap_hal) - Saves registers and calls _start_trap_rust_hal, - restores registers and then returns. -*/ -.section .trap, "ax" -.global _start_trap_hal -.option norelax -.align 6 - -_start_trap_hal: - addi sp, sp, -40*4 - - sw ra, 0*4(sp) - sw t0, 1*4(sp) - sw t1, 2*4(sp) - sw t2, 3*4(sp) - sw t3, 4*4(sp) - sw t4, 5*4(sp) - sw t5, 6*4(sp) - sw t6, 7*4(sp) - sw a0, 8*4(sp) - sw a1, 9*4(sp) - sw a2, 10*4(sp) - sw a3, 11*4(sp) - sw a4, 12*4(sp) - sw a5, 13*4(sp) - sw a6, 14*4(sp) - sw a7, 15*4(sp) - sw s0, 16*4(sp) - sw s1, 17*4(sp) - sw s2, 18*4(sp) - sw s3, 19*4(sp) - sw s4, 20*4(sp) - sw s5, 21*4(sp) - sw s6, 22*4(sp) - sw s7, 23*4(sp) - sw s8, 24*4(sp) - sw s9, 25*4(sp) - sw s10, 26*4(sp) - sw s11, 27*4(sp) - sw gp, 28*4(sp) - sw tp, 29*4(sp) - csrrs t1, mepc, x0 - sw t1, 31*4(sp) - csrrs t1, mstatus, x0 - sw t1, 32*4(sp) - csrrs t1, mcause, x0 - sw t1, 33*4(sp) - csrrs t1, mtval, x0 - sw t1, 34*4(sp) - - addi s0, sp, 40*4 - sw s0, 30*4(sp) - - add a0, sp, zero - jal ra, _start_trap_rust_hal - - lw t1, 31*4(sp) - csrrw x0, mepc, t1 - - lw t1, 32*4(sp) - csrrw x0, mstatus, t1 - - lw ra, 0*4(sp) - lw t0, 1*4(sp) - lw t1, 2*4(sp) - lw t2, 3*4(sp) - lw t3, 4*4(sp) - lw t4, 5*4(sp) - lw t5, 6*4(sp) - lw t6, 7*4(sp) - lw a0, 8*4(sp) - lw a1, 9*4(sp) - lw a2, 10*4(sp) - lw a3, 11*4(sp) - lw a4, 12*4(sp) - lw a5, 13*4(sp) - lw a6, 14*4(sp) - lw a7, 15*4(sp) - lw s0, 16*4(sp) - lw s1, 17*4(sp) - lw s2, 18*4(sp) - lw s3, 19*4(sp) - lw s4, 20*4(sp) - lw s5, 21*4(sp) - lw s6, 22*4(sp) - lw s7, 23*4(sp) - lw s8, 24*4(sp) - lw s9, 25*4(sp) - lw s10, 26*4(sp) - lw s11, 27*4(sp) - lw gp, 28*4(sp) - lw tp, 29*4(sp) - lw sp, 30*4(sp) - - # SP was restored from the original SP - mret - -"# -); - -#[link_section = ".init"] -#[export_name = "_start_hal"] -unsafe fn start_hal() -> ! { - asm!( - r#" - .option norelax - - csrw mie, 0 - csrw mip, 0 - - li x1, 0 - li x2, 0 - li x3, 0 - li x4, 0 - li x5, 0 - li x6, 0 - li x7, 0 - li x8, 0 - li x9, 0 - li x10,0 - li x11,0 - li x12,0 - li x13,0 - li x14,0 - li x15,0 - li x16,0 - li x17,0 - li x18,0 - li x19,0 - li x20,0 - li x21,0 - li x22,0 - li x23,0 - li x24,0 - li x25,0 - li x26,0 - li x27,0 - li x28,0 - li x29,0 - li x30,0 - li x31,0 - - .option push - .option norelax - la gp, __global_pointer$ - .option pop - - // Check hart id - csrr a2, mhartid - lui t0, %hi(_max_hart_id) - add t0, t0, %lo(_max_hart_id) - bgtu a2, t0, abort_hal - - // Allocate stacks - la sp, _stack_start - lui t0, %hi(_hart_stack_size) - add t0, t0, %lo(_hart_stack_size) - - beqz a2, 2f // Jump if single-hart - mv t1, a2 - mv t2, t0 - 1: - add t0, t0, t2 - addi t1, t1, -1 - bnez t1, 1b - 2: - sub sp, sp, t0 - - // Set frame pointer - add s0, sp, zero - - jal zero, _start_rust - "# - ); - - unreachable!() -} - -global_asm!( - r#" -/* Make sure there is an abort when linking */ -.globl abort_hal -abort_hal: - j abort_hal -"# -); - #[allow(unreachable_code)] #[export_name = "_mp_hook"] #[doc(hidden)] From a2e4c9363c39c08e25cebdce94f72b43099ce112 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Tue, 7 Feb 2023 10:12:41 -0800 Subject: [PATCH 34/64] Remove unused features, update cargo config for atomic emu, misc cleanup --- esp32c6-hal/.cargo/config.toml | 23 +++++++++++++++-------- esp32c6-hal/Cargo.toml | 25 ++++++++++--------------- esp32c6-hal/examples/advanced_serial.rs | 1 - esp32c6-hal/examples/hello_world.rs | 1 - esp32c6-hal/examples/sha.rs | 1 - esp32c6-hal/examples/usb_serial_jtag.rs | 9 ++------- esp32c6-hal/src/lib.rs | 8 ++------ 7 files changed, 29 insertions(+), 39 deletions(-) diff --git a/esp32c6-hal/.cargo/config.toml b/esp32c6-hal/.cargo/config.toml index 09b3d4e3a48..922b77a223d 100644 --- a/esp32c6-hal/.cargo/config.toml +++ b/esp32c6-hal/.cargo/config.toml @@ -2,15 +2,22 @@ runner = "espflash flash --monitor" rustflags = [ "-C", "link-arg=-Tlinkall.x", - "-C", "force-frame-pointers", -] -# for testing: you can specify this target to see atomic emulation in action -[target.riscv32imac-unknown-none-elf] -runner = "espflash --monitor" -rustflags = [ - "-C", "link-arg=-Tlinkall.x", - "-C", "force-frame-pointers", + # comment the cfgs below if you do _not_ wish to emulate atomics. + # enable the atomic codegen option for RISCV + "-C", "target-feature=+a", + # tell the core library have atomics even though it's not specified in the target definition + "--cfg", "target_has_atomic_load_store", + "--cfg", 'target_has_atomic_load_store="8"', + "--cfg", 'target_has_atomic_load_store="16"', + "--cfg", 'target_has_atomic_load_store="32"', + "--cfg", 'target_has_atomic_load_store="ptr"', + # enable cas + "--cfg", "target_has_atomic", + "--cfg", 'target_has_atomic="8"', + "--cfg", 'target_has_atomic="16"', + "--cfg", 'target_has_atomic="32"', + "--cfg", 'target_has_atomic="ptr"', ] [build] diff --git a/esp32c6-hal/Cargo.toml b/esp32c6-hal/Cargo.toml index 3da07dd80b7..b3d673e19d7 100644 --- a/esp32c6-hal/Cargo.toml +++ b/esp32c6-hal/Cargo.toml @@ -8,7 +8,7 @@ authors = [ ] edition = "2021" rust-version = "1.60.0" -description = "HAL for ESP32-C3 microcontrollers" +description = "HAL for ESP32-C6 microcontrollers" repository = "https://github.com/esp-rs/esp-hal" license = "MIT OR Apache-2.0" @@ -51,34 +51,29 @@ static_cell = "1.0.0" [features] default = ["rt", "vectored"] -mcu-boot = [] direct-boot = [] eh1 = ["esp-hal-common/eh1", "dep:embedded-hal-1", "dep:embedded-hal-nb", "dep:embedded-can"] rt = ["esp-riscv-rt"] smartled = ["esp-hal-common/smartled"] ufmt = ["esp-hal-common/ufmt"] vectored = ["esp-hal-common/vectored"] -allow-opt-level-z = [] async = ["esp-hal-common/async", "embedded-hal-async"] embassy = ["esp-hal-common/embassy"] embassy-time-systick = ["esp-hal-common/embassy-time-systick", "embassy-time/tick-hz-16_000_000"] embassy-time-timg0 = ["esp-hal-common/embassy-time-timg0", "embassy-time/tick-hz-1_000_000"] -# [[example]] -# name = "hello_rgb" -# required-features = ["smartled"] +[[example]] +name = "hello_rgb" +required-features = ["smartled"] -# [[example]] -# name = "spi_eh1_loopback" -# required-features = ["eh1"] +[[example]] +name = "spi_eh1_loopback" +required-features = ["eh1"] -# [[example]] -# name = "spi_eh1_device_loopback" -# required-features = ["eh1"] +[[example]] +name = "spi_eh1_device_loopback" +required-features = ["eh1"] # [[example]] # name = "embassy_hello_world" # required-features = ["embassy"] - -[profile.dev] -opt-level = 1 \ No newline at end of file diff --git a/esp32c6-hal/examples/advanced_serial.rs b/esp32c6-hal/examples/advanced_serial.rs index b7b87cadca7..3ca083b9122 100644 --- a/esp32c6-hal/examples/advanced_serial.rs +++ b/esp32c6-hal/examples/advanced_serial.rs @@ -3,7 +3,6 @@ //! Additionally you can connect a logic analzyer to TX and see how the changes //! of the configuration change the output signal. -#![feature(stmt_expr_attributes)] #![no_std] #![no_main] diff --git a/esp32c6-hal/examples/hello_world.rs b/esp32c6-hal/examples/hello_world.rs index 29de78b39a6..6471e71c849 100644 --- a/esp32c6-hal/examples/hello_world.rs +++ b/esp32c6-hal/examples/hello_world.rs @@ -1,7 +1,6 @@ //! This shows how to write text to uart0. //! You can see the output with `espflash` if you provide the `--monitor` option -#![feature(stmt_expr_attributes)] #![no_std] #![no_main] diff --git a/esp32c6-hal/examples/sha.rs b/esp32c6-hal/examples/sha.rs index 70f4d55c572..aa841f90c70 100644 --- a/esp32c6-hal/examples/sha.rs +++ b/esp32c6-hal/examples/sha.rs @@ -20,7 +20,6 @@ use sha2::{Digest, Sha256}; #[entry] fn main() -> ! { - // TODO: need to debug let peripherals = Peripherals::take(); let system = peripherals.PCR.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); diff --git a/esp32c6-hal/examples/usb_serial_jtag.rs b/esp32c6-hal/examples/usb_serial_jtag.rs index 50972b20893..74a0e1b42c8 100644 --- a/esp32c6-hal/examples/usb_serial_jtag.rs +++ b/esp32c6-hal/examples/usb_serial_jtag.rs @@ -27,7 +27,6 @@ static USB_SERIAL: Mutex>>> = #[entry] fn main() -> ! { - // TODO: test this let peripherals = Peripherals::take(); let system = peripherals.PCR.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); @@ -51,11 +50,7 @@ fn main() -> ! { critical_section::with(|cs| USB_SERIAL.borrow_ref_mut(cs).replace(usb_serial)); - interrupt::enable( - peripherals::Interrupt::USB_SERIAL_JTAG, - interrupt::Priority::Priority1, - ) - .unwrap(); + interrupt::enable(peripherals::Interrupt::USB, interrupt::Priority::Priority1).unwrap(); interrupt::set_kind( Cpu::ProCpu, @@ -81,7 +76,7 @@ fn main() -> ! { } #[interrupt] -fn USB_SERIAL_JTAG() { +fn USB() { critical_section::with(|cs| { let mut usb_serial = USB_SERIAL.borrow_ref_mut(cs); let usb_serial = usb_serial.as_mut().unwrap(); diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index c88d101f079..918cad53c28 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -1,6 +1,8 @@ #![no_std] pub use embedded_hal as ehal; +#[cfg(feature = "embassy")] +pub use esp_hal_common::embassy; pub use esp_hal_common::{ aes, clock, @@ -67,13 +69,7 @@ extern "C" { #[allow(unreachable_code)] #[export_name = "_mp_hook"] #[doc(hidden)] -#[cfg_attr(feature = "mcu-boot", link_section = ".rwtext")] pub fn mp_hook() -> bool { - #[cfg(feature = "mcu-boot")] - unsafe { - configure_mmu(); - } - unsafe { r0::zero_bss(&mut _rtc_fast_bss_start, &mut _rtc_fast_bss_end); } From 82171475b8f57d3d15a19c3c581f46bd471d01ed Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Tue, 7 Feb 2023 13:33:00 -0800 Subject: [PATCH 35/64] Get ADC building and example "working" (as much as it ever does) --- esp-hal-common/build.rs | 1 - esp-hal-common/src/analog/adc/riscv.rs | 32 +++++++++++-- esp-hal-common/src/analog/mod.rs | 41 ++++------------- esp-hal-common/src/lib.rs | 2 +- esp-hal-common/src/prelude.rs | 18 ++++---- esp32c6-hal/examples/adc.rs | 63 ++++++++++++++++++++++++++ esp32c6-hal/src/lib.rs | 9 ++-- 7 files changed, 115 insertions(+), 51 deletions(-) create mode 100644 esp32c6-hal/examples/adc.rs diff --git a/esp-hal-common/build.rs b/esp-hal-common/build.rs index 38490a559da..83f2fff4756 100644 --- a/esp-hal-common/build.rs +++ b/esp-hal-common/build.rs @@ -101,7 +101,6 @@ fn main() { "esp32c6", "riscv", "single_core", - "dac", "gdma", "i2s", "mcpwm", diff --git a/esp-hal-common/src/analog/adc/riscv.rs b/esp-hal-common/src/analog/adc/riscv.rs index 20333238dca..f0c025c9504 100644 --- a/esp-hal-common/src/analog/adc/riscv.rs +++ b/esp-hal-common/src/analog/adc/riscv.rs @@ -287,6 +287,30 @@ macro_rules! impl_adc_interface { pub use impl_adc_interface; +#[cfg(esp32c2)] +pub mod implementation { + //! Analog to digital (ADC) conversion support. + //! + //! This module provides functions for reading analog values from the + //! analog to digital converter available on the ESP32-C2: `ADC1`. + + use embedded_hal::adc::Channel; + + use super::impl_adc_interface; + pub use crate::analog::{adc::*, ADC1}; + use crate::gpio::*; + + impl_adc_interface! { + ADC1 [ + (Gpio0, 0), + (Gpio1, 1), + (Gpio2, 2), + (Gpio3, 3), + (Gpio4, 4), + ] + } +} + #[cfg(esp32c3)] pub mod implementation { //! Analog to digital (ADC) conversion support. @@ -318,12 +342,12 @@ pub mod implementation { } } -#[cfg(esp32c2)] +#[cfg(esp32c6)] pub mod implementation { //! Analog to digital (ADC) conversion support. //! - //! This module provides functions for reading analog values from the - //! analog to digital converter available on the ESP32-C2: `ADC1`. + //! This module provides functions for reading analog values from one + //! analog to digital converter available on the ESP32-C6: `ADC1`. use embedded_hal::adc::Channel; @@ -338,6 +362,8 @@ pub mod implementation { (Gpio2, 2), (Gpio3, 3), (Gpio4, 4), + (Gpio5, 5), + (Gpio6, 6), ] } } diff --git a/esp-hal-common/src/analog/mod.rs b/esp-hal-common/src/analog/mod.rs index 316d8ce2d13..cd4aa748909 100644 --- a/esp-hal-common/src/analog/mod.rs +++ b/esp-hal-common/src/analog/mod.rs @@ -1,8 +1,6 @@ #[cfg_attr(esp32, path = "adc/esp32.rs")] -#[cfg_attr(esp32c2, path = "adc/riscv.rs")] -#[cfg_attr(esp32c3, path = "adc/riscv.rs")] -#[cfg_attr(esp32s2, path = "adc/xtensa.rs")] -#[cfg_attr(esp32s3, path = "adc/xtensa.rs")] +#[cfg_attr(any(esp32c2, esp32c3, esp32c6), path = "adc/riscv.rs")] +#[cfg_attr(any(esp32s2, esp32s3), path = "adc/xtensa.rs")] pub mod adc; #[cfg(dac)] pub mod dac; @@ -10,6 +8,7 @@ pub mod dac; pub struct ADC1 { _private: (), } + pub struct ADC2 { _private: (), } @@ -95,6 +94,7 @@ impl crate::peripheral::sealed::Sealed for DAC1 {} impl crate::peripheral::Peripheral for DAC2 { type P = DAC2; + #[inline] unsafe fn clone_unchecked(&mut self) -> Self::P { DAC2 { _private: () } @@ -103,6 +103,7 @@ impl crate::peripheral::Peripheral for DAC2 { impl crate::peripheral::Peripheral for &mut DAC2 { type P = DAC2; + #[inline] unsafe fn clone_unchecked(&mut self) -> Self::P { DAC2 { _private: () } @@ -114,7 +115,6 @@ impl crate::peripheral::sealed::Sealed for DAC2 {} cfg_if::cfg_if! { if #[cfg(any(esp32, esp32s2, esp32s3))] { - use crate::peripherals::SENS; pub struct AvailableAnalog { @@ -151,12 +151,12 @@ cfg_if::cfg_if! { } cfg_if::cfg_if! { - if #[cfg(esp32c3)] { - + if #[cfg(any(esp32c2, esp32c3, esp32c6))] { use crate::peripherals::APB_SARADC; pub struct AvailableAnalog { pub adc1: ADC1, + #[cfg(esp32c3)] pub adc2: ADC2, } @@ -171,6 +171,7 @@ cfg_if::cfg_if! { adc1: ADC1 { _private: (), }, + #[cfg(esp32c3)] adc2: ADC2 { _private: (), }, @@ -179,29 +180,3 @@ cfg_if::cfg_if! { } } } - -cfg_if::cfg_if! { - if #[cfg(esp32c2)] { - - use crate::peripherals::APB_SARADC; - - pub struct AvailableAnalog { - pub adc1: ADC1, - } - - /// Extension trait to split a APB_SARADC peripheral in independent parts - pub trait SarAdcExt { - fn split(self) -> AvailableAnalog; - } - - impl<'d, T: crate::peripheral::Peripheral

+ 'd> SarAdcExt for T { - fn split(self) -> AvailableAnalog { - AvailableAnalog { - adc1: ADC1 { - _private: (), - }, - } - } - } - } -} diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index be1f5c6e530..b10657ebc84 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -72,7 +72,7 @@ pub use self::{ #[cfg(aes)] pub mod aes; -// pub mod analog; +pub mod analog; pub mod clock; pub mod delay; pub mod dma; diff --git a/esp-hal-common/src/prelude.rs b/esp-hal-common/src/prelude.rs index 30bb17b2418..1e3b0a326c5 100644 --- a/esp-hal-common/src/prelude.rs +++ b/esp-hal-common/src/prelude.rs @@ -20,15 +20,15 @@ pub use fugit::{ }; pub use nb; -// #[cfg(any(esp32c2, esp32c3))] -// pub use crate::analog::SarAdcExt as _esp_hal_analog_SarAdcExt; -// #[cfg(any(esp32, esp32s2, esp32s3))] -// pub use crate::analog::SensExt as _esp_hal_analog_SensExt; -// #[cfg(rmt)] -// pub use crate::pulse_control::{ -// ConfiguredChannel as _esp_hal_pulse_control_ConfiguredChannel, -// OutputChannel as _esp_hal_pulse_control_OutputChannel, -// }; +#[cfg(any(esp32c2, esp32c3, esp32c6))] +pub use crate::analog::SarAdcExt as _esp_hal_analog_SarAdcExt; +#[cfg(any(esp32, esp32s2, esp32s3))] +pub use crate::analog::SensExt as _esp_hal_analog_SensExt; +#[cfg(rmt)] +pub use crate::pulse_control::{ + ConfiguredChannel as _esp_hal_pulse_control_ConfiguredChannel, + OutputChannel as _esp_hal_pulse_control_OutputChannel, +}; #[cfg(radio)] pub use crate::radio::RadioExt as _esp_hal_RadioExt; #[cfg(any(esp32, esp32s2))] diff --git a/esp32c6-hal/examples/adc.rs b/esp32c6-hal/examples/adc.rs new file mode 100644 index 00000000000..50d60829ac2 --- /dev/null +++ b/esp32c6-hal/examples/adc.rs @@ -0,0 +1,63 @@ +//! Connect a potentiometer to PIN2 and see the read values change when +//! rotating the shaft. Alternatively you could also connect the PIN to GND or +//! 3V3 to see the maximum and minimum raw values read. + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + adc::{AdcConfig, Attenuation, ADC, ADC1}, + clock::ClockControl, + gpio::IO, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Delay, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; +use esp_riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let _wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let _wdt1 = timer_group1.wdt; + + // Disable MWDT and RWDT (Watchdog) flash boot protection + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + rtc.rwdt.disable(); + rtc.swd.disable(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + + // Create ADC instances + let analog = peripherals.APB_SARADC.split(); + + let mut adc1_config = AdcConfig::new(); + + let mut pin = adc1_config.enable_pin(io.pins.gpio2.into_analog(), Attenuation::Attenuation11dB); + + let mut adc1 = ADC::::adc( + &mut system.peripheral_clock_control, + analog.adc1, + adc1_config, + ) + .unwrap(); + + let mut delay = Delay::new(&clocks); + + loop { + let pin_value: u16 = nb::block!(adc1.read(&mut pin)).unwrap(); + println!("PIN2 ADC reading = {}", pin_value); + delay.delay_ms(1500u32); + } +} diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index 918cad53c28..af3749285e0 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -5,6 +5,7 @@ pub use embedded_hal as ehal; pub use esp_hal_common::embassy; pub use esp_hal_common::{ aes, + analog::adc::implementation as adc, clock, dma, dma::gdma, @@ -36,10 +37,10 @@ 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}; -// } +/// Common module for analog functions +pub mod analog { + pub use esp_hal_common::analog::{AvailableAnalog, SarAdcExt}; +} extern "C" { // Boundaries of the .iram section From a9330930960ca78add08bd2857d5d9277a63a703 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Tue, 7 Feb 2023 13:42:20 -0800 Subject: [PATCH 36/64] Remove a bunch of unused constants which were copied from ESP-IDF --- esp-hal-common/src/clock/clocks_ll/esp32c6.rs | 133 ------------------ 1 file changed, 133 deletions(-) diff --git a/esp-hal-common/src/clock/clocks_ll/esp32c6.rs b/esp-hal-common/src/clock/clocks_ll/esp32c6.rs index 9e4e65a4e4b..4c2afb094c4 100644 --- a/esp-hal-common/src/clock/clocks_ll/esp32c6.rs +++ b/esp-hal-common/src/clock/clocks_ll/esp32c6.rs @@ -7,77 +7,10 @@ extern "C" { const I2C_BBPLL: u8 = 0x66; const I2C_BBPLL_HOSTID: u8 = 0; -const I2C_BBPLL_IR_CAL_DELAY: u32 = 0; -const I2C_BBPLL_IR_CAL_DELAY_MSB: u32 = 3; -const I2C_BBPLL_IR_CAL_DELAY_LSB: u32 = 0; - -const I2C_BBPLL_IR_CAL_CK_DIV: u32 = 0; -const I2C_BBPLL_IR_CAL_CK_DIV_MSB: u32 = 7; -const I2C_BBPLL_IR_CAL_CK_DIV_LSB: u32 = 4; - -const I2C_BBPLL_IR_CAL_EXT_CAP: u32 = 1; -const I2C_BBPLL_IR_CAL_EXT_CAP_MSB: u32 = 3; -const I2C_BBPLL_IR_CAL_EXT_CAP_LSB: u32 = 0; - -const I2C_BBPLL_IR_CAL_ENX_CAP: u32 = 1; -const I2C_BBPLL_IR_CAL_ENX_CAP_MSB: u32 = 4; -const I2C_BBPLL_IR_CAL_ENX_CAP_LSB: u32 = 4; - -const I2C_BBPLL_IR_CAL_RSTB: u32 = 1; -const I2C_BBPLL_IR_CAL_RSTB_MSB: u32 = 5; -const I2C_BBPLL_IR_CAL_RSTB_LSB: u32 = 5; - -const I2C_BBPLL_IR_CAL_START: u32 = 1; -const I2C_BBPLL_IR_CAL_START_MSB: u32 = 6; -const I2C_BBPLL_IR_CAL_START_LSB: u32 = 6; - -const I2C_BBPLL_IR_CAL_UNSTOP: u32 = 1; -const I2C_BBPLL_IR_CAL_UNSTOP_MSB: u32 = 7; -const I2C_BBPLL_IR_CAL_UNSTOP_LSB: u32 = 7; - const I2C_BBPLL_OC_REF_DIV: u8 = 2; -const I2C_BBPLL_OC_REF_DIV_MSB: u32 = 3; -const I2C_BBPLL_OC_REF_DIV_LSB: u32 = 0; - -const I2C_BBPLL_OC_DCHGP: u32 = 2; -const I2C_BBPLL_OC_DCHGP_MSB: u32 = 6; const I2C_BBPLL_OC_DCHGP_LSB: u32 = 4; -const I2C_BBPLL_OC_ENB_FCAL: u32 = 2; -const I2C_BBPLL_OC_ENB_FCAL_MSB: u32 = 7; -const I2C_BBPLL_OC_ENB_FCAL_LSB: u32 = 7; - const I2C_BBPLL_OC_DIV_7_0: u8 = 3; -const I2C_BBPLL_OC_DIV_7_0_MSB: u32 = 7; -const I2C_BBPLL_OC_DIV_7_0_LSB: u32 = 0; - -const I2C_BBPLL_RSTB_DIV_ADC: u32 = 4; -const I2C_BBPLL_RSTB_DIV_ADC_MSB: u32 = 0; -const I2C_BBPLL_RSTB_DIV_ADC_LSB: u32 = 0; - -const I2C_BBPLL_MODE_HF: u32 = 4; -const I2C_BBPLL_MODE_HF_MSB: u32 = 1; -const I2C_BBPLL_MODE_HF_LSB: u32 = 1; - -const I2C_BBPLL_DIV_ADC: u32 = 4; -const I2C_BBPLL_DIV_ADC_MSB: u32 = 3; -const I2C_BBPLL_DIV_ADC_LSB: u32 = 2; - -const I2C_BBPLL_DIV_DAC: u32 = 4; -const I2C_BBPLL_DIV_DAC_MSB: u32 = 4; -const I2C_BBPLL_DIV_DAC_LSB: u32 = 4; - -const I2C_BBPLL_DIV_CPU: u32 = 4; -const I2C_BBPLL_DIV_CPU_MSB: u32 = 5; -const I2C_BBPLL_DIV_CPU_LSB: u32 = 5; - -const I2C_BBPLL_OC_ENB_VCON: u32 = 4; -const I2C_BBPLL_OC_ENB_VCON_MSB: u32 = 6; -const I2C_BBPLL_OC_ENB_VCON_LSB: u32 = 6; - -const I2C_BBPLL_OC_TSCHGP: u32 = 4; -const I2C_BBPLL_OC_TSCHGP_MSB: u32 = 7; -const I2C_BBPLL_OC_TSCHGP_LSB: u32 = 7; const I2C_BBPLL_OC_DR1: u8 = 5; const I2C_BBPLL_OC_DR1_MSB: u8 = 2; @@ -87,82 +20,16 @@ const I2C_BBPLL_OC_DR3: u8 = 5; const I2C_BBPLL_OC_DR3_MSB: u8 = 6; const I2C_BBPLL_OC_DR3_LSB: u8 = 4; -const I2C_BBPLL_EN_USB: u32 = 5; -const I2C_BBPLL_EN_USB_MSB: u32 = 7; -const I2C_BBPLL_EN_USB_LSB: u32 = 7; - const I2C_BBPLL_OC_DCUR: u8 = 6; -const I2C_BBPLL_OC_DCUR_MSB: u32 = 2; -const I2C_BBPLL_OC_DCUR_LSB: u32 = 0; - -const I2C_BBPLL_INC_CUR: u32 = 6; -const I2C_BBPLL_INC_CUR_MSB: u32 = 3; -const I2C_BBPLL_INC_CUR_LSB: u32 = 3; -const I2C_BBPLL_OC_DHREF_SEL: u32 = 6; -const I2C_BBPLL_OC_DHREF_SEL_MSB: u32 = 5; const I2C_BBPLL_OC_DHREF_SEL_LSB: u32 = 4; -const I2C_BBPLL_OC_DLREF_SEL: u32 = 6; -const I2C_BBPLL_OC_DLREF_SEL_MSB: u32 = 7; const I2C_BBPLL_OC_DLREF_SEL_LSB: u32 = 6; -const I2C_BBPLL_OR_CAL_CAP: u32 = 8; -const I2C_BBPLL_OR_CAL_CAP_MSB: u32 = 3; -const I2C_BBPLL_OR_CAL_CAP_LSB: u32 = 0; - -const I2C_BBPLL_OR_CAL_UDF: u32 = 8; -const I2C_BBPLL_OR_CAL_UDF_MSB: u32 = 4; -const I2C_BBPLL_OR_CAL_UDF_LSB: u32 = 4; - -const I2C_BBPLL_OR_CAL_OVF: u32 = 8; -const I2C_BBPLL_OR_CAL_OVF_MSB: u32 = 5; -const I2C_BBPLL_OR_CAL_OVF_LSB: u32 = 5; - -const I2C_BBPLL_OR_CAL_END: u32 = 8; -const I2C_BBPLL_OR_CAL_END_MSB: u32 = 6; -const I2C_BBPLL_OR_CAL_END_LSB: u32 = 6; - -const I2C_BBPLL_OR_LOCK: u32 = 8; -const I2C_BBPLL_OR_LOCK_MSB: u32 = 7; -const I2C_BBPLL_OR_LOCK_LSB: u32 = 7; - const I2C_BBPLL_OC_VCO_DBIAS: u8 = 9; const I2C_BBPLL_OC_VCO_DBIAS_MSB: u8 = 1; const I2C_BBPLL_OC_VCO_DBIAS_LSB: u8 = 0; -const I2C_BBPLL_BBADC_DELAY2: u32 = 9; -const I2C_BBPLL_BBADC_DELAY2_MSB: u32 = 3; -const I2C_BBPLL_BBADC_DELAY2_LSB: u32 = 2; - -const I2C_BBPLL_BBADC_DVDD: u32 = 9; -const I2C_BBPLL_BBADC_DVDD_MSB: u32 = 5; -const I2C_BBPLL_BBADC_DVDD_LSB: u32 = 4; - -const I2C_BBPLL_BBADC_DREF: u32 = 9; -const I2C_BBPLL_BBADC_DREF_MSB: u32 = 7; -const I2C_BBPLL_BBADC_DREF_LSB: u32 = 6; - -const I2C_BBPLL_BBADC_DCUR: u32 = 10; -const I2C_BBPLL_BBADC_DCUR_MSB: u32 = 1; -const I2C_BBPLL_BBADC_DCUR_LSB: u32 = 0; - -const I2C_BBPLL_BBADC_INPUT_SHORT: u32 = 10; -const I2C_BBPLL_BBADC_INPUT_SHORT_MSB: u32 = 2; -const I2C_BBPLL_BBADC_INPUT_SHORT_LSB: u32 = 2; - -const I2C_BBPLL_ENT_PLL: u32 = 10; -const I2C_BBPLL_ENT_PLL_MSB: u32 = 3; -const I2C_BBPLL_ENT_PLL_LSB: u32 = 3; - -const I2C_BBPLL_DTEST: u32 = 10; -const I2C_BBPLL_DTEST_MSB: u32 = 5; -const I2C_BBPLL_DTEST_LSB: u32 = 4; - -const I2C_BBPLL_ENT_ADC: u32 = 10; -const I2C_BBPLL_ENT_ADC_MSB: u32 = 7; -const I2C_BBPLL_ENT_ADC_LSB: u32 = 6; - // Analog function control register const I2C_MST_ANA_CONF0_REG: u32 = 0x600AF818; const I2C_MST_BBPLL_STOP_FORCE_HIGH: u32 = 1 << 2; From 93f926f7836ccfd3b372799a184ce2ee93cf63ed Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Tue, 7 Feb 2023 14:02:24 -0800 Subject: [PATCH 37/64] The `mcpwm` example now works correctly --- esp-hal-common/src/mcpwm/mod.rs | 56 +++++++++++++++----------- esp-hal-common/src/mcpwm/timer.rs | 67 +++++-------------------------- 2 files changed, 43 insertions(+), 80 deletions(-) diff --git a/esp-hal-common/src/mcpwm/mod.rs b/esp-hal-common/src/mcpwm/mod.rs index 5e6bd851e4a..7cc198da996 100644 --- a/esp-hal-common/src/mcpwm/mod.rs +++ b/esp-hal-common/src/mcpwm/mod.rs @@ -115,26 +115,33 @@ impl<'d, PWM: PwmPeripheral> MCPWM<'d, PWM> { PWM::enable(system); - // set prescaler #[cfg(not(esp32c6))] - peripheral - .clk_cfg - .write(|w| w.clk_prescale().variant(peripheral_clock.prescaler)); - // enable clock - #[cfg(not(esp32c6))] - peripheral.clk.write(|w| w.en().set_bit()); + { + // set prescaler + peripheral + .clk_cfg + .write(|w| w.clk_prescale().variant(peripheral_clock.prescaler)); + + // enable clock + peripheral.clk.write(|w| w.en().set_bit()); + } #[cfg(esp32c6)] - let pcr = unsafe { &*crate::peripherals::PCR::ptr() }; - #[cfg(esp32c6)] - pcr.pwm_clk_conf - .write(|w| w.pwm_div_num().variant(peripheral_clock.prescaler)); - #[cfg(esp32c6)] - pcr.pwm_clk_conf.write(|w| w.pwm_clkm_en().set_bit()); - // TODO: Add other clock sources - #[cfg(esp32c6)] - pcr.pwm_clk_conf - .write(|w| unsafe { w.pwm_clkm_sel().bits(1) }); + { + unsafe { &*crate::peripherals::PCR::PTR } + .pwm_clk_conf + .modify(|_, w| unsafe { + w.pwm_div_num() + .variant(peripheral_clock.prescaler) + .pwm_clkm_en() + .set_bit() + .pwm_clkm_sel() + .bits(1) + }); + + // TODO: Add other clock sources + } + MCPWM { _inner: peripheral, timer0: Timer::new(), @@ -166,10 +173,10 @@ impl<'a> PeripheralClockConfig<'a> { pub fn with_prescaler(clocks: &'a Clocks, prescaler: u8) -> Self { #[cfg(esp32)] let source_clock = clocks.pwm_clock; - #[cfg(esp32s3)] - let source_clock = clocks.crypto_pwm_clock; #[cfg(esp32c6)] let source_clock = clocks.crypto_clock; + #[cfg(esp32s3)] + let source_clock = clocks.crypto_pwm_clock; PeripheralClockConfig { frequency: source_clock / (prescaler as u32 + 1), @@ -198,19 +205,20 @@ impl<'a> PeripheralClockConfig<'a> { ) -> Result { #[cfg(esp32)] let source_clock = clocks.pwm_clock; - #[cfg(esp32s3)] - let source_clock = clocks.crypto_pwm_clock; #[cfg(esp32c6)] let source_clock = clocks.crypto_clock; + #[cfg(esp32s3)] + let source_clock = clocks.crypto_pwm_clock; if target_freq.raw() == 0 || target_freq > source_clock { return Err(FrequencyError); } + let prescaler = source_clock / target_freq - 1; if prescaler > u8::MAX as u32 { return Err(FrequencyError); } - esp_println::println!("{source_clock}, {target_freq}, {prescaler}"); + Ok(Self::with_prescaler(clocks, prescaler as u8)) } @@ -280,7 +288,7 @@ unsafe impl PwmPeripheral for PWM { } fn block() -> *const RegisterBlock { - Self::ptr() + Self::PTR } fn output_signal() -> OutputSignal { @@ -303,7 +311,7 @@ unsafe impl PwmPeripheral for crate::peripherals::PWM1 { } fn block() -> *const RegisterBlock { - Self::ptr() + Self::PTR } fn output_signal() -> OutputSignal { diff --git a/esp-hal-common/src/mcpwm/timer.rs b/esp-hal-common/src/mcpwm/timer.rs index f3c5bcc0934..f104a942ed6 100644 --- a/esp-hal-common/src/mcpwm/timer.rs +++ b/esp-hal-common/src/mcpwm/timer.rs @@ -2,6 +2,10 @@ use core::marker::PhantomData; use fugit::HertzU32; +#[cfg(esp32c6)] +use crate::peripherals::mcpwm::{TIMER0_CFG0, TIMER0_CFG1}; +#[cfg(not(esp32c6))] +use crate::peripherals::pwm0::{TIMER0_CFG0, TIMER0_CFG1}; use crate::{ clock::Clocks, mcpwm::{FrequencyError, PeripheralClockConfig, PwmPeripheral}, @@ -45,7 +49,7 @@ impl Timer { .timer0_period_upmethod() .variant(0) }); - esp_println::println!("QQ: {} {}", timer_config.prescaler, timer_config.period); + // set timer to continuously run and set the timer working mode self.cfg1().write(|w| { w.timer0_start() @@ -101,9 +105,7 @@ impl Timer { .variant(!sw) }); } - _ => { - unreachable!() - } + _ => unreachable!(), } } @@ -135,14 +137,11 @@ impl Timer { reg.timer2_direction().bit_is_set().into(), ) } - _ => { - unreachable!() - } + _ => unreachable!(), } } - #[cfg(not(esp32c6))] - fn cfg0(&mut self) -> &crate::peripherals::pwm0::TIMER0_CFG0 { + fn cfg0(&mut self) -> &TIMER0_CFG0 { // SAFETY: // We only grant access to our CFG0 register with the lifetime of &mut self let block = unsafe { &*PWM::block() }; @@ -154,14 +153,11 @@ impl Timer { 0 => &block.timer0_cfg0, 1 => unsafe { &*(&block.timer1_cfg0 as *const _ as *const _) }, 2 => unsafe { &*(&block.timer2_cfg0 as *const _ as *const _) }, - _ => { - unreachable!() - } + _ => unreachable!(), } } - #[cfg(not(esp32c6))] - fn cfg1(&mut self) -> &crate::peripherals::pwm0::TIMER0_CFG1 { + fn cfg1(&mut self) -> &TIMER0_CFG1 { // SAFETY: // We only grant access to our CFG1 register with the lifetime of &mut self let block = unsafe { &*PWM::block() }; @@ -173,47 +169,7 @@ impl Timer { 0 => &block.timer0_cfg1, 1 => unsafe { &*(&block.timer1_cfg1 as *const _ as *const _) }, 2 => unsafe { &*(&block.timer2_cfg1 as *const _ as *const _) }, - _ => { - unreachable!() - } - } - } - - #[cfg(esp32c6)] - fn cfg0(&mut self) -> &crate::peripherals::mcpwm::TIMER0_CFG0 { - // SAFETY: - // We only grant access to our CFG0 register with the lifetime of &mut self - let block = unsafe { &*PWM::block() }; - - // SAFETY: - // The CFG0 registers are identical for all timers so we can pretend they're - // TIMER0_CFG0 - match TIM { - 0 => &block.timer0_cfg0, - 1 => unsafe { &*(&block.timer1_cfg0 as *const _ as *const _) }, - 2 => unsafe { &*(&block.timer2_cfg0 as *const _ as *const _) }, - _ => { - unreachable!() - } - } - } - - #[cfg(esp32c6)] - fn cfg1(&mut self) -> &crate::peripherals::mcpwm::TIMER0_CFG1 { - // SAFETY: - // We only grant access to our CFG1 register with the lifetime of &mut self - let block = unsafe { &*PWM::block() }; - - // SAFETY: - // The CFG1 registers are identical for all timers so we can pretend they're - // TIMER0_CFG1 - match TIM { - 0 => &block.timer0_cfg1, - 1 => unsafe { &*(&block.timer1_cfg1 as *const _ as *const _) }, - 2 => unsafe { &*(&block.timer2_cfg1 as *const _ as *const _) }, - _ => { - unreachable!() - } + _ => unreachable!(), } } } @@ -278,7 +234,6 @@ impl<'a> TimerClockConfig<'a> { } let frequency = clock.frequency / (prescaler + 1) / cycle_period; - esp_println::println!("{target_timer_frequency} {target_freq} {prescaler}"); Ok(TimerClockConfig { frequency, prescaler: prescaler as u8, From 59a599de75f7ea7ce543e940e28dffb9a0b6b88f Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Wed, 8 Feb 2023 08:51:42 -0800 Subject: [PATCH 38/64] Get `TWAI` peripheral driver building for C6 --- esp-hal-common/src/dma/gdma.rs | 16 ++++++---- esp-hal-common/src/lib.rs | 4 +-- esp-hal-common/src/twai/mod.rs | 57 ++++++++++++++++++++++++++++++---- 3 files changed, 63 insertions(+), 14 deletions(-) diff --git a/esp-hal-common/src/dma/gdma.rs b/esp-hal-common/src/dma/gdma.rs index bab17872c87..82dfc285773 100644 --- a/esp-hal-common/src/dma/gdma.rs +++ b/esp-hal-common/src/dma/gdma.rs @@ -301,17 +301,18 @@ macro_rules! impl_channel { fn is_listening_in_eof() -> bool { let dma = unsafe { &*crate::peripherals::DMA::PTR }; cfg_if::cfg_if! { - if #[cfg(esp32s3)] { + if #[cfg(any(esp32c6, esp32s3))] { dma.[].read().in_suc_eof().bit_is_set() } else { dma.[].read().in_suc_eof().bit_is_set() } } } + fn is_listening_out_eof() -> bool { let dma = unsafe { &*crate::peripherals::DMA::PTR }; cfg_if::cfg_if! { - if #[cfg(esp32s3)] { + if #[cfg(any(esp32c6, esp32s3))] { dma.[].read().out_total_eof().bit_is_set() } else { dma.[].read().out_total_eof().bit_is_set() @@ -322,37 +323,40 @@ macro_rules! impl_channel { fn listen_in_eof() { let dma = unsafe { &*crate::peripherals::DMA::PTR }; cfg_if::cfg_if! { - if #[cfg(esp32s3)] { + if #[cfg(any(esp32c6, esp32s3))] { dma.[].modify(|_, w| w.in_suc_eof().set_bit()) } else { dma.[].modify(|_, w| w.in_suc_eof().set_bit()) } } } + fn listen_out_eof() { let dma = unsafe { &*crate::peripherals::DMA::PTR }; cfg_if::cfg_if! { - if #[cfg(esp32s3)] { + if #[cfg(any(esp32c6, esp32s3))] { dma.[].modify(|_, w| w.out_total_eof().set_bit()) } else { dma.[].modify(|_, w| w.out_total_eof().set_bit()) } } } + fn unlisten_in_eof() { let dma = unsafe { &*crate::peripherals::DMA::PTR }; cfg_if::cfg_if! { - if #[cfg(esp32s3)] { + if #[cfg(any(esp32c6, esp32s3))] { dma.[].modify(|_, w| w.in_suc_eof().clear_bit()) } else { dma.[].modify(|_, w| w.in_suc_eof().clear_bit()) } } } + fn unlisten_out_eof() { let dma = unsafe { &*crate::peripherals::DMA::PTR }; cfg_if::cfg_if! { - if #[cfg(esp32s3)] { + if #[cfg(any(esp32c6, esp32s3))] { dma.[].modify(|_, w| w.out_total_eof().clear_bit()) } else { dma.[].modify(|_, w| w.out_total_eof().clear_bit()) diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index b10657ebc84..d234013c5b8 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -104,8 +104,8 @@ pub mod system; #[cfg(systimer)] pub mod systimer; pub mod timer; -// #[cfg(any(esp32s3, esp32c3, esp32c6))] -// pub mod twai; +#[cfg(any(esp32c3, esp32c6, esp32s3))] +pub mod twai; pub mod uart; #[cfg(usb_serial_jtag)] pub mod usb_serial_jtag; diff --git a/esp-hal-common/src/twai/mod.rs b/esp-hal-common/src/twai/mod.rs index 4d76006d7b2..14b88d9234b 100644 --- a/esp-hal-common/src/twai/mod.rs +++ b/esp-hal-common/src/twai/mod.rs @@ -11,11 +11,14 @@ use embedded_hal::can::{Can, Error, ErrorKind, ExtendedId, Frame, Id, StandardId use fugit::HertzU32; use self::filter::{Filter, FilterType}; +#[cfg(not(esp32c6))] +use crate::peripherals::twai::RegisterBlock; +#[cfg(esp32c6)] +use crate::peripherals::twai0::RegisterBlock; use crate::{ clock::Clocks, peripheral::{Peripheral, PeripheralRef}, - peripherals::twai::RegisterBlock, - system::PeripheralClockControl, + system::{self, PeripheralClockControl}, types::{InputSignal, OutputSignal}, InputPin, OutputPin, @@ -137,6 +140,7 @@ pub enum BaudRate { B1000K, Custom(TimingConfig), } + impl BaudRate { /// Convert the BaudRate into the timings that the peripheral needs. // These timings are copied from the ESP IDF C driver. @@ -208,12 +212,12 @@ where baud_rate: BaudRate, ) -> Self { // Enable the peripheral clock for the TWAI peripheral. - clock_control.enable(crate::system::Peripheral::Twai); + clock_control.enable(T::SYSTEM_PERIPHERAL); // Set up the GPIO pins. crate::into_ref!(tx_pin, rx_pin); - tx_pin.connect_peripheral_to_output(OutputSignal::TWAI_TX); - rx_pin.connect_input_to_peripheral(InputSignal::TWAI_RX); + tx_pin.connect_peripheral_to_output(T::OUTPUT_SIGNAL); + rx_pin.connect_input_to_peripheral(T::INPUT_SIGNAL); crate::into_ref!(peripheral); let mut cfg = TwaiConfiguration { peripheral }; @@ -348,6 +352,7 @@ where peripheral: self.peripheral, } } + pub fn receive_error_count(&self) -> u8 { self.peripheral .register_block() @@ -356,6 +361,7 @@ where .rx_err_cnt() .bits() } + pub fn transmit_error_count(&self) -> u8 { self.peripheral .register_block() @@ -388,6 +394,7 @@ where .rx_message_counter() .bits() } + /// Clear the receive FIFO, discarding any valid, partial, or invalid /// packets. /// @@ -417,6 +424,7 @@ pub enum EspTwaiError { BusOff, EmbeddedHAL(ErrorKind), } + impl Error for EspTwaiError { fn kind(&self) -> ErrorKind { match self { @@ -569,6 +577,7 @@ where // embedded-can/embedded-hal trait. nb::Result::Ok(None) } + /// Return a received frame if there are any available. fn receive(&mut self) -> nb::Result { let status = self.peripheral.register_block().status.read(); @@ -702,11 +711,47 @@ where } pub trait Instance { + const SYSTEM_PERIPHERAL: system::Peripheral; + + const INPUT_SIGNAL: InputSignal; + const OUTPUT_SIGNAL: OutputSignal; + fn register_block(&self) -> &RegisterBlock; } -#[cfg(any(esp32s3, esp32c3))] +#[cfg(any(esp32c3, esp32s3))] impl Instance for crate::peripherals::TWAI { + const SYSTEM_PERIPHERAL: system::Peripheral = system::Peripheral::Twai; + + const INPUT_SIGNAL: InputSignal = InputSignal::TWAI_RX; + const OUTPUT_SIGNAL: OutputSignal = OutputSignal::TWAI_TX; + + #[inline(always)] + fn register_block(&self) -> &RegisterBlock { + self + } +} + +#[cfg(esp32c6)] +impl Instance for crate::peripherals::TWAI0 { + const SYSTEM_PERIPHERAL: system::Peripheral = system::Peripheral::Twai0; + + const INPUT_SIGNAL: InputSignal = InputSignal::TWAI0_RX; + const OUTPUT_SIGNAL: OutputSignal = OutputSignal::TWAI0_TX; + + #[inline(always)] + fn register_block(&self) -> &RegisterBlock { + self + } +} + +#[cfg(esp32c6)] +impl Instance for crate::peripherals::TWAI1 { + const SYSTEM_PERIPHERAL: system::Peripheral = system::Peripheral::Twai1; + + const INPUT_SIGNAL: InputSignal = InputSignal::TWAI1_RX; + const OUTPUT_SIGNAL: OutputSignal = OutputSignal::TWAI1_TX; + #[inline(always)] fn register_block(&self) -> &RegisterBlock { self From 46487eb0f7f39340380c2266bc3795e834d6e4f2 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Wed, 8 Feb 2023 10:19:19 -0800 Subject: [PATCH 39/64] Clean up the `rtc_cntl` module and get all the other HALs building again --- esp-hal-common/src/lib.rs | 1 + esp-hal-common/src/rtc_cntl/mod.rs | 839 ++++++++++------------------- 2 files changed, 276 insertions(+), 564 deletions(-) diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index d234013c5b8..f80a541c4e2 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -64,6 +64,7 @@ pub use self::{ delay::Delay, gpio::*, interrupt::*, + rng::Rng, rtc_cntl::{Rtc, Rwdt}, spi::Spi, timer::Timer, diff --git a/esp-hal-common/src/rtc_cntl/mod.rs b/esp-hal-common/src/rtc_cntl/mod.rs index 30d162df92b..332c72a8b7c 100644 --- a/esp-hal-common/src/rtc_cntl/mod.rs +++ b/esp-hal-common/src/rtc_cntl/mod.rs @@ -2,24 +2,22 @@ use embedded_hal::watchdog::{Watchdog, WatchdogDisable, WatchdogEnable}; use fugit::{HertzU32, MicrosDurationU64}; use self::rtc::SocResetReason; -#[cfg(not(esp32))] +#[cfg(not(any(esp32, esp32c6)))] use crate::efuse::Efuse; -#[cfg(not(esp32c6))] -use crate::peripherals::RTC_CNTL; #[cfg(esp32c6)] -use crate::peripherals::{LP_AON, LP_CLKRST, LP_WDT, PCR, PMU}; +use crate::peripherals::{LP_AON, LP_CLKRST, LP_WDT, PMU}; +#[cfg(not(esp32c6))] +use crate::peripherals::{RTC_CNTL, TIMG0}; use crate::{ clock::{Clock, XtalClock}, peripheral::{Peripheral, PeripheralRef}, - peripherals::TIMG0, Cpu, }; -#[cfg(not(esp32c6))] -type RTC_PERIPHERAL = RTC_CNTL; - #[cfg(esp32c6)] -type RTC_PERIPHERAL = LP_CLKRST; +type RtcCntl = crate::peripherals::LP_CLKRST; +#[cfg(not(esp32c6))] +type RtcCntl = crate::peripherals::RTC_CNTL; #[cfg_attr(esp32, path = "rtc/esp32.rs")] #[cfg_attr(esp32c2, path = "rtc/esp32c2.rs")] @@ -31,7 +29,6 @@ mod rtc; extern "C" { fn ets_delay_us(us: u32); - fn rtc_get_reset_reason(cpu_num: u32) -> u32; } @@ -51,13 +48,12 @@ impl Clock for RtcFastClock { RtcFastClock::RtcFastClockXtalD4 => HertzU32::Hz(40_000_000 / 4), #[cfg(any(esp32, esp32s2))] RtcFastClock::RtcFastClock8m => HertzU32::Hz(8_500_000), - #[cfg(any(esp32c2, esp32c3, esp32s3, esp32c6))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] RtcFastClock::RtcFastClock8m => HertzU32::Hz(17_500_000), } } } -#[allow(unused)] #[cfg(not(esp32c6))] #[derive(Debug, Clone, Copy)] /// RTC SLOW_CLK frequency values @@ -70,7 +66,6 @@ pub(crate) enum RtcSlowClock { RtcSlowClock8mD256 = 2, } -#[allow(unused)] #[cfg(esp32c6)] #[derive(Debug, Clone, Copy, PartialEq)] /// RTC SLOW_CLK frequency values @@ -95,22 +90,21 @@ impl Clock for RtcSlowClock { RtcSlowClock::RtcSlowClockRtc => HertzU32::Hz(90_000), #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] RtcSlowClock::RtcSlowClockRtc => HertzU32::Hz(136_000), - RtcSlowClock::RtcSlowClock32kXtal => HertzU32::Hz(32768), + RtcSlowClock::RtcSlowClock32kXtal => HertzU32::Hz(32_768), #[cfg(any(esp32, esp32s2))] RtcSlowClock::RtcSlowClock8mD256 => HertzU32::Hz(8_500_000 / 256), #[cfg(any(esp32c2, esp32c3, esp32s3))] RtcSlowClock::RtcSlowClock8mD256 => HertzU32::Hz(17_500_000 / 256), #[cfg(esp32c6)] - RtcSlowClock::RtcCalRcFast => HertzU32::Hz(17_500_00), + RtcSlowClock::RtcSlowClock32kRc => HertzU32::Hz(32_768), #[cfg(esp32c6)] - RtcSlowClock::RtcSlowClock32kRc => HertzU32::Hz(17_500_00), // ?? + RtcSlowClock::RtcCalInternalOsc => HertzU32::Hz(32_768), #[cfg(esp32c6)] - RtcSlowClock::RtcCalInternalOsc => HertzU32::Hz(17_500_00), // ?? + RtcSlowClock::RtcCalRcFast => HertzU32::Hz(150_000), } } } -#[allow(unused)] #[cfg(not(esp32c6))] #[derive(Debug, Clone, Copy)] /// Clock source to be calibrated using rtc_clk_cal function @@ -126,7 +120,6 @@ pub(crate) enum RtcCalSel { RtcCalInternalOsc = 3, } -#[allow(unused)] #[cfg(esp32c6)] #[derive(Debug, Clone, Copy, PartialEq)] /// Clock source to be calibrated using rtc_clk_cal function @@ -153,26 +146,25 @@ pub(crate) enum RtcCaliClkSel { } pub struct Rtc<'d> { - _inner: PeripheralRef<'d, RTC_PERIPHERAL>, + _inner: PeripheralRef<'d, RtcCntl>, pub rwdt: Rwdt, - #[cfg(any(esp32c2, esp32c3, esp32s3, esp32c6))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] pub swd: Swd, } impl<'d> Rtc<'d> { - pub fn new(rtc_cntl: impl Peripheral

+ 'd) -> Self { + pub fn new(rtc_cntl: impl Peripheral

+ 'd) -> Self { rtc::init(); rtc::configure_clock(); Self { _inner: rtc_cntl.into_ref(), rwdt: Rwdt::default(), - #[cfg(any(esp32c2, esp32c3, esp32s3, esp32c6))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] swd: Swd::new(), } } - #[cfg(not(esp32c6))] pub fn estimate_xtal_frequency(&mut self) -> u32 { RtcClock::estimate_xtal_frequency() } @@ -199,7 +191,7 @@ impl RtcClock { /// disabled to reduce power consumption. #[cfg(not(esp32c6))] fn enable_8m(clk_8m_en: bool, d256_en: bool) { - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; + let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; if clk_8m_en { rtc_cntl.clk_conf.modify(|_, w| w.enb_ck8m().clear_bit()); @@ -225,14 +217,13 @@ impl RtcClock { #[cfg(esp32c6)] fn enable_8m(clk_8m_en: bool, _d256_en: bool) { - let pmu = unsafe { &*PMU::ptr() }; + let pmu = unsafe { &*PMU::PTR }; if clk_8m_en { pmu.hp_sleep_lp_ck_power .modify(|_, w| w.hp_sleep_xpd_fosc_clk().set_bit()); - unsafe { - ets_delay_us(50); - } + + unsafe { ets_delay_us(50) }; } else { pmu.hp_sleep_lp_ck_power .modify(|_, w| w.hp_sleep_xpd_fosc_clk().clear_bit()); @@ -243,15 +234,11 @@ impl RtcClock { /// This is the value stored in RTC register RTC_XTAL_FREQ_REG by the /// bootloader, as passed to rtc_clk_init function. fn get_xtal_freq() -> XtalClock { + #[cfg(esp32c6)] + let xtal_freq_reg = unsafe { &*LP_AON::PTR }.store4.read().bits(); #[cfg(not(esp32c6))] - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; - #[cfg(not(esp32c6))] - let xtal_freq_reg = rtc_cntl.store4.read().bits(); + let xtal_freq_reg = unsafe { &*RTC_CNTL::PTR }.store4.read().bits(); - #[cfg(esp32c6)] - let lp_aon = unsafe { &*LP_AON::ptr() }; - #[cfg(esp32c6)] - let xtal_freq_reg = lp_aon.store4.read().bits(); // Values of RTC_XTAL_FREQ_REG and RTC_APB_FREQ_REG are stored as two copies in // lower and upper 16-bit halves. These are the routines to work with such a // representation. @@ -279,7 +266,7 @@ impl RtcClock { /// Get the RTC_SLOW_CLK source #[cfg(not(esp32c6))] fn get_slow_freq() -> RtcSlowClock { - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; + let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; let slow_freq = rtc_cntl.clk_conf.read().ana_clk_rtc_sel().bits(); match slow_freq { 0 => RtcSlowClock::RtcSlowClockRtc, @@ -293,7 +280,6 @@ impl RtcClock { #[cfg(esp32c6)] fn get_slow_freq() -> RtcSlowClock { let lp_clrst = unsafe { &*LP_CLKRST::ptr() }; - let pcr = unsafe { &*PCR::ptr() }; let slow_freq = lp_clrst.lp_clk_conf.read().slow_clk_sel().bits(); match slow_freq { @@ -305,16 +291,11 @@ impl RtcClock { } } - #[cfg(esp32c6)] - fn set_slow_freq(slow_freq: RtcSlowClock) { - todo!() - } - /// Select source for RTC_SLOW_CLK #[cfg(not(esp32c6))] fn set_slow_freq(slow_freq: RtcSlowClock) { unsafe { - let rtc_cntl = &*RTC_CNTL::ptr(); + let rtc_cntl = &*RTC_CNTL::PTR; rtc_cntl.clk_conf.modify(|_, w| { w.ana_clk_rtc_sel() .bits(slow_freq as u8) @@ -334,554 +315,270 @@ impl RtcClock { _ => false, }) }); - } - - /// Select source for RTC_FAST_CLK - fn set_fast_freq(fast_freq: RtcFastClock) { - unsafe { - let rtc_cntl = &*RTC_CNTL::ptr(); - rtc_cntl.clk_conf.modify(|_, w| { - w.fast_clk_rtc_sel().bit(match fast_freq { - RtcFastClock::RtcFastClock8m => true, - RtcFastClock::RtcFastClockXtalD4 => false, - }) - }); - - ets_delay_us(3u32); - }; - } - /// Calibration of RTC_SLOW_CLK is performed using a special feature of - /// TIMG0. This feature counts the number of XTAL clock cycles within a - /// given number of RTC_SLOW_CLK cycles. - #[cfg(not(esp32c6))] - fn calibrate_internal(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { - // Except for ESP32, choosing RTC_CAL_RTC_MUX results in calibration of - // the 150k RTC clock (90k on ESP32-S2) regardless of the currently selected - // SLOW_CLK. On the ESP32, it uses the currently selected SLOW_CLK. - // The following code emulates ESP32 behavior for the other chips: - #[cfg(not(esp32))] - let cal_clk = match cal_clk { - RtcCalSel::RtcCalRtcMux => match RtcClock::get_slow_freq() { - RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, - RtcSlowClock::RtcSlowClock8mD256 => RtcCalSel::RtcCal8mD256, - _ => cal_clk, - }, - RtcCalSel::RtcCalInternalOsc => RtcCalSel::RtcCalRtcMux, - _ => cal_clk, - }; - - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; - let timg0 = unsafe { &*TIMG0::ptr() }; - - // Enable requested clock (150k clock is always on) - let dig_32k_xtal_enabled = rtc_cntl.clk_conf.read().dig_xtal32k_en().bit_is_set(); - - if matches!(cal_clk, RtcCalSel::RtcCal32kXtal) && !dig_32k_xtal_enabled { - rtc_cntl - .clk_conf - .modify(|_, w| w.dig_xtal32k_en().set_bit()); - } - - if matches!(cal_clk, RtcCalSel::RtcCal8mD256) { - rtc_cntl - .clk_conf - .modify(|_, w| w.dig_clk8m_d256_en().set_bit()); - } + ets_delay_us(300u32); + }; + } - // There may be another calibration process already running during we - // call this function, so we should wait the last process is done. - #[cfg(not(esp32))] - if timg0 - .rtccalicfg - .read() - .rtc_cali_start_cycling() - .bit_is_set() - { - // Set a small timeout threshold to accelerate the generation of timeout. - // The internal circuit will be reset when the timeout occurs and will not - // affect the next calibration. - timg0 - .rtccalicfg2 - .modify(|_, w| unsafe { w.rtc_cali_timeout_thres().bits(1) }); - - while timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_clear() - && timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_clear() - {} - } + #[cfg(esp32c6)] + fn set_slow_freq(slow_freq: RtcSlowClock) { + todo!() + } - // Prepare calibration - timg0.rtccalicfg.modify(|_, w| unsafe { - w.rtc_cali_clk_sel() - .bits(cal_clk as u8) - .rtc_cali_start_cycling() - .clear_bit() - .rtc_cali_max() - .bits(slowclk_cycles as u16) + /// Select source for RTC_FAST_CLK + #[cfg(not(esp32c6))] + fn set_fast_freq(fast_freq: RtcFastClock) { + unsafe { + let rtc_cntl = &*RTC_CNTL::PTR; + rtc_cntl.clk_conf.modify(|_, w| { + w.fast_clk_rtc_sel().bit(match fast_freq { + RtcFastClock::RtcFastClock8m => true, + RtcFastClock::RtcFastClockXtalD4 => false, + }) }); - // Figure out how long to wait for calibration to finish - // Set timeout reg and expect time delay - let expected_freq = match cal_clk { - RtcCalSel::RtcCal32kXtal => { - #[cfg(not(esp32))] - timg0.rtccalicfg2.modify(|_, w| unsafe { - w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12) - }); - RtcSlowClock::RtcSlowClock32kXtal - } - RtcCalSel::RtcCal8mD256 => { - #[cfg(not(esp32))] - timg0.rtccalicfg2.modify(|_, w| unsafe { - w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12) - }); - RtcSlowClock::RtcSlowClock8mD256 - } - _ => { - #[cfg(not(esp32))] - timg0.rtccalicfg2.modify(|_, w| unsafe { - w.rtc_cali_timeout_thres().bits(slowclk_cycles << 10) - }); - RtcSlowClock::RtcSlowClockRtc - } - }; - - let us_time_estimate = HertzU32::MHz(slowclk_cycles) / expected_freq.frequency(); - - // Start calibration - timg0 - .rtccalicfg - .modify(|_, w| w.rtc_cali_start().clear_bit().rtc_cali_start().set_bit()); - - // Wait for calibration to finish up to another us_time_estimate - unsafe { - ets_delay_us(us_time_estimate); - } + ets_delay_us(3u32); + }; + } - #[cfg(esp32)] - let mut timeout_us = us_time_estimate; + #[cfg(esp32c6)] + fn set_fast_freq(fast_freq: RtcFastClock) { + todo!() + } - let cal_val = loop { - if timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_set() { - break timg0.rtccalicfg1.read().rtc_cali_value().bits(); - } + /// Calibration of RTC_SLOW_CLK is performed using a special feature of + /// TIMG0. This feature counts the number of XTAL clock cycles within a + /// given number of RTC_SLOW_CLK cycles. + #[cfg(not(esp32c6))] + fn calibrate_internal(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { + // Except for ESP32, choosing RTC_CAL_RTC_MUX results in calibration of + // the 150k RTC clock (90k on ESP32-S2) regardless of the currently selected + // SLOW_CLK. On the ESP32, it uses the currently selected SLOW_CLK. + // The following code emulates ESP32 behavior for the other chips: + #[cfg(not(esp32))] + let cal_clk = match cal_clk { + RtcCalSel::RtcCalRtcMux => match RtcClock::get_slow_freq() { + RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, + RtcSlowClock::RtcSlowClock8mD256 => RtcCalSel::RtcCal8mD256, + _ => cal_clk, + }, + RtcCalSel::RtcCalInternalOsc => RtcCalSel::RtcCalRtcMux, + _ => cal_clk, + }; + let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; + let timg0 = unsafe { &*TIMG0::PTR }; - #[cfg(not(esp32))] - if timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_set() { - // Timed out waiting for calibration - break 0; - } + // Enable requested clock (150k clock is always on) + let dig_32k_xtal_enabled = rtc_cntl.clk_conf.read().dig_xtal32k_en().bit_is_set(); - #[cfg(esp32)] - if timeout_us > 0 { - timeout_us -= 1; - unsafe { - ets_delay_us(1); - } - } else { - // Timed out waiting for calibration - break 0; - } - }; + if matches!(cal_clk, RtcCalSel::RtcCal32kXtal) && !dig_32k_xtal_enabled { + rtc_cntl + .clk_conf + .modify(|_, w| w.dig_xtal32k_en().set_bit()); + } - timg0 - .rtccalicfg - .modify(|_, w| w.rtc_cali_start().clear_bit()); + if matches!(cal_clk, RtcCalSel::RtcCal8mD256) { rtc_cntl .clk_conf - .modify(|_, w| w.dig_xtal32k_en().bit(dig_32k_xtal_enabled)); + .modify(|_, w| w.dig_clk8m_d256_en().set_bit()); + } - if matches!(cal_clk, RtcCalSel::RtcCal8mD256) { - rtc_cntl - .clk_conf - .modify(|_, w| w.dig_clk8m_d256_en().clear_bit()); - } + // There may be another calibration process already running during we + // call this function, so we should wait the last process is done. + #[cfg(not(esp32))] + if timg0 + .rtccalicfg + .read() + .rtc_cali_start_cycling() + .bit_is_set() + { + // Set a small timeout threshold to accelerate the generation of timeout. + // The internal circuit will be reset when the timeout occurs and will not + // affect the next calibration. + timg0 + .rtccalicfg2 + .modify(|_, w| unsafe { w.rtc_cali_timeout_thres().bits(1) }); - cal_val + while timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_clear() + && timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_clear() + {} } - /// Calibration of RTC_SLOW_CLK is performed using a special feature of - /// TIMG0. This feature counts the number of XTAL clock cycles within a - /// given number of RTC_SLOW_CLK cycles. - #[cfg(esp32c6)] - fn calibrate_internal(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { - // Except for ESP32, choosing RTC_CAL_RTC_MUX results in calibration of - // the 150k RTC clock (90k on ESP32-S2) regardless of the currently selected - // SLOW_CLK. On the ESP32, it uses the currently selected SLOW_CLK. - // The following code emulates ESP32 behavior for the other chips: - #[cfg(not(any(esp32, esp32c6)))] - let cal_clk = match cal_clk { - RtcCalSel::RtcCalRtcMux => match RtcClock::get_slow_freq() { - RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, - RtcSlowClock::RtcSlowClock8mD256 => RtcCalSel::RtcCal8mD256, - _ => cal_clk, - }, - RtcCalSel::RtcCalInternalOsc => RtcCalSel::RtcCalRtcMux, - _ => cal_clk, - }; - - #[cfg(esp32c6)] - if cal_clk == RtcCalSel::RtcCalRtcMux { - cal_clk = match cal_clk { - RtcCalSel::RtcCalRtcMux => match RtcClock::get_slow_freq() { - RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, - RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc, - _ => cal_clk, - }, - RtcCalSel::RtcCalInternalOsc => RtcCalSel::RtcCalRtcMux, - _ => cal_clk, - }; + // Prepare calibration + timg0.rtccalicfg.modify(|_, w| unsafe { + w.rtc_cali_clk_sel() + .bits(cal_clk as u8) + .rtc_cali_start_cycling() + .clear_bit() + .rtc_cali_max() + .bits(slowclk_cycles as u16) + }); + + // Figure out how long to wait for calibration to finish + // Set timeout reg and expect time delay + let expected_freq = match cal_clk { + RtcCalSel::RtcCal32kXtal => { + #[cfg(not(esp32))] + timg0.rtccalicfg2.modify(|_, w| unsafe { + w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12) + }); + RtcSlowClock::RtcSlowClock32kXtal } - - let lp_clkrst = unsafe { &*LP_CLKRST::ptr() }; - // let lp_clkrst = &*LP_CLKRST::ptr(); - let pcr = &*PCR::ptr(); - let pmu = &*PMU::ptr(); - - const SOC_CLK_RC_FAST_FREQ_APPROX: u32 = 17_500_000; - const SOC_CLK_RC_SLOW_FREQ_APPROX: u32 = 136_000; - const SOC_CLK_RC32K_FREQ_APPROX: u32 = 32768; - const SOC_CLK_XTAL32K_FREQ_APPROX: u32 = 32768; - const SOC_CLK_OSC_SLOW_FREQ_APPROX: u32 = 32768; - - let clk_src = RtcClock::get_slow_freq(); - - let old_clk_sel = match pcr.ctrl_32k_conf.read().clk_32k_sel().bits() { - 0 => RtcSlowClock::RtcSlowClockRtc, - 1 => RtcSlowClock::RtcSlowClock32kXtal, - 2 => RtcSlowClock::RtcSlowClock32kRc, - _ => unreachable!(), - }; - - if cal_clk == RtcCalSel::RtcCalRtcMux { - cal_clk = match clk_src { - RtcSlowClock::RtcSlowClockRtc => RtcCalSel::RtcCalRcSlow, - RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, - RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc, - RtcSlowClock::RtcCalInternalOsc => RtcCalSel::RtcCalInternalOsc, - _ => unreachable!(), - }; + RtcCalSel::RtcCal8mD256 => { + #[cfg(not(esp32))] + timg0.rtccalicfg2.modify(|_, w| unsafe { + w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12) + }); + RtcSlowClock::RtcSlowClock8mD256 } - - let cali_clk_sel = match cal_clk { - RtcCalSel::RtcCalRcFast => RtcCaliClkSel::CaliClkRcFast, - RtcCalSel::RtcCalRcSlow => RtcCaliClkSel::CaliClkRcSlow, - _ => { - match clk_src { - RtcSlowClock::RtcSlowClock32kRc => { - pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(0)) - } - RtcSlowClock::RtcSlowClock32kXtal => { - pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(1)) - } - RtcSlowClock::RtcCalInternalOsc => { - pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(2)) - } - _ => unreachable!(), - }; - RtcCaliClkSel::CaliClk32k - } - }; - - // if cal_clk == RtcCalSel::RtcCalRcFast { - // cali_clk_sel = RtcCaliClkSel::CaliClkRcFast; - // } else if cal_clk == RtcCalSel::RtcCalRcSlow { - // cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_SLOW; - // } else { - // cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_32K; - // match clk_src { - // RtcSlowClock::RtcSlowClock32kRc => pcr.ctrl_32k_conf.modify(|_, w| - // w.clk_32k_sel().bits(0)), - // RtcSlowClock::RtcSlowClock32kXtal => pcr.ctrl_32k_conf.modify(|_, w| - // w.clk_32k_sel().bits(1)), RtcSlowClock::RtcCalInternalOsc - // => pcr.ctrl_32k_conf.modify(|_, w| w.clk_32k_sel().bits(2)), - // _ => unreachable!() - // } - // } - - // Enable requested clock (150k is always on) - // Some delay is required before the time is stable - // Only enable if originaly was disabled - // If clock is already on, do nothing - - let dig_32k_xtal_enabled = lp_clkrst.clk_to_hp.read().icg_hp_xtal32k().bit_is_set(); - - if cal_clk == RtcCalSel::RtcCal32kXtal && !dig_32k_xtal_enabled { - lp_clkrst - .clk_to_hp - .modify(|_, w| w.icg_hp_xtal32k().set_bit()); + _ => { + #[cfg(not(esp32))] + timg0.rtccalicfg2.modify(|_, w| unsafe { + w.rtc_cali_timeout_thres().bits(slowclk_cycles << 10) + }); + RtcSlowClock::RtcSlowClockRtc } + }; - let rc_fast_enabled = pmu - .hp_sleep_lp_ck_power - .read() - .hp_sleep_xpd_fosc_clk() - .bit_is_set(); - let dig_rc_fast_enabled = lp_clkrst.clk_to_hp.read().icg_hp_fosc().bit_is_set(); - - if cal_clk == RtcCalSel::RtcCalRcFast { - if !rc_fast_enabled { - pmu.hp_sleep_lp_ck_power - .write(|w| w.hp_sleep_xpd_fosc_clk().set_bit()); - unsafe { - ets_delay_us(50); - } - } + let us_time_estimate = HertzU32::MHz(slowclk_cycles) / expected_freq.frequency(); - if !dig_rc_fast_enabled { - lp_clkrst.clk_to_hp.write(|w| w.icg_hp_fosc().set_bit()); - unsafe { - ets_delay_us(5); - } - } - } + // Start calibration + timg0 + .rtccalicfg + .modify(|_, w| w.rtc_cali_start().clear_bit().rtc_cali_start().set_bit()); - let rc32k_enabled = pmu - .hp_sleep_lp_ck_power - .read() - .hp_sleep_xpd_rc32k() - .bit_is_set(); - let dig_rc32k_enabled = lp_clkrst.clk_to_hp.read().icg_hp_osc32k().bit_is_set(); - - if cal_clk == RtcCalSel::RtcCal32kRc { - if !rc32k_enabled { - pmu.hp_sleep_lp_ck_power - .write(|w| w.hp_sleep_xpd_rc32k().set_bit()); - unsafe { - ets_delay_us(300); - } - } - if !dig_rc32k_enabled { - lp_clkrst.clk_to_hp.write(|w| w.icg_hp_osc32k().set_bit()); - } - } + // Wait for calibration to finish up to another us_time_estimate + unsafe { + ets_delay_us(us_time_estimate); + } - // Check if there is already running calibration process - let timg0 = unsafe { &*TIMG0::ptr() }; + #[cfg(esp32)] + let mut timeout_us = us_time_estimate; - if timg0 - .rtccalicfg - .read() - .rtc_cali_start_cycling() - .bit_is_set() - { - timg0 - .rtccalicfg2 - .modify(|_, w| w.rtc_cali_timeout_thres().bits(1)); - - // Set small timeout threshold to accelerate the generation of timeot - // Internal circuit will be reset when timeout occurs and will not affect the - // next calibration - while timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_clear() - && timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_clear() - {} + let cal_val = loop { + if timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_set() { + break timg0.rtccalicfg1.read().rtc_cali_value().bits(); } - // Prepare calibration - timg0 - .rtccalicfg - .modify(|_, w| w.rtc_cali_clk_sel().bits(cali_clk_sel as u8)); - timg0 - .rtccalicfg - .write(|w| w.rtc_cali_start_cycling().clear_bit()); - timg0 - .rtccalicfg - .modify(|_, w| w.rtc_cali_max().bits(slowclk_cycles.try_into().unwrap())); - - let expected_freq = match cali_clk_sel { - RtcCaliClkSel::CaliClk32k => { - #[cfg(not(esp32))] - timg0 - .rtccalicfg2 - .modify(|_, w| w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12)); - RtcSlowClock::RtcSlowClock32kXtal - } - RtcCaliClkSel::CaliClkRcFast => { - #[cfg(not(esp32))] - timg0 - .rtccalicfg2 - .modify(|_, w| w.rtc_cali_timeout_thres().bits(0x01FFFFFF)); - RtcSlowClock::RtcCalRcFast - } - _ => { - #[cfg(not(esp32))] - timg0 - .rtccalicfg2 - .modify(|_, w| w.rtc_cali_timeout_thres().bits(slowclk_cycles << 10)); - RtcSlowClock::RtcSlowClockRtc - } - }; - - // if cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_32K { - // timg0.rtccalicfg2.modify(|_, w| - // w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12)); - // expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX; - // } else if cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST { - // timg0.rtccalicfg2.modify(|_, w| - // w.rtc_cali_timeout_thres().bits(0x01FFFFFF)); expected_freq = - // 17_500_000; } else { - // timg0.rtccalicfg2.modify(|_, w| - // w.rtc_cali_timeout_thres().bits(slowclk_cycles << 10)); - // expected_freq = 136_000; - // } - - let us_time_estimate = HertzU32::MHz(slowclk_cycles) / expected_freq.frequency(); - - // Start calibration - timg0 - .rtccalicfg - .modify(|_, w| w.rtc_cali_start().clear_bit().rtc_cali_start().set_bit()); - - // Wait for calibration to finish up to another us_time_estimate - unsafe { - ets_delay_us(us_time_estimate); + #[cfg(not(esp32))] + if timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_set() { + // Timed out waiting for calibration + break 0; } - let cal_val = loop { - if timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_set() { - break timg0.rtccalicfg1.read().rtc_cali_value().bits(); - } - - #[cfg(not(esp32))] - if timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_set() { - // Timed out waiting for calibration - break 0; + #[cfg(esp32)] + if timeout_us > 0 { + timeout_us -= 1; + unsafe { + ets_delay_us(1); } - - // #[cfg(esp32)] - // if timeout_us > 0 { - // timeout_us -= 1; - // unsafe { - // ets_delay_us(1); - // } - // } else { - // // Timed out waiting for calibration - // break 0; - // } - }; - - timg0 - .rtccalicfg - .modify(|_, w| w.rtc_cali_start().clear_bit()); - - if cal_clk == RtcCalSel::RtcCal32kXtal && !dig_32k_xtal_enabled { - lp_clkrst - .clk_to_hp - .modify(|_, w| w.icg_hp_xtal32k().bit(dig_32k_xtal_enabled)); + } else { + // Timed out waiting for calibration + break 0; } + }; - if cal_clk == RtcCalSel::RtcCalRcFast { - if !rc_fast_enabled { - // TODO rtc_dig_clk8m_disable(); - pmu.hp_sleep_lp_ck_power - .write(|w| w.hp_sleep_xpd_fosc_clk().set_bit()); - unsafe { - ets_delay_us(50); - } - } - - if !dig_rc_fast_enabled { - // TODO rtc_dig_clk8m_disable(); - lp_clkrst.clk_to_hp.write(|w| w.icg_hp_fosc().set_bit()); - unsafe { - ets_delay_us(5); - } - } - } + timg0 + .rtccalicfg + .modify(|_, w| w.rtc_cali_start().clear_bit()); + rtc_cntl + .clk_conf + .modify(|_, w| w.dig_xtal32k_en().bit(dig_32k_xtal_enabled)); - if cal_clk == RtcCalSel::RtcCal32kRc { - if !rc32k_enabled { - pmu.hp_sleep_lp_ck_power - .write(|w| w.hp_sleep_xpd_rc32k().set_bit()); - unsafe { - ets_delay_us(300); - } - } - if !dig_rc32k_enabled { - lp_clkrst.clk_to_hp.write(|w| w.icg_hp_osc32k().set_bit()); - } - } + if matches!(cal_clk, RtcCalSel::RtcCal8mD256) { + rtc_cntl + .clk_conf + .modify(|_, w| w.dig_clk8m_d256_en().clear_bit()); + } - // if matches!(cal_clk, RtcCalSel::RtcCal8mD256) { - // rtc_cntl - // .clk_conf - // .modify(|_, w| w.dig_clk8m_d256_en().clear_bit()); - // } + cal_val + } - cal_val - } + /// Calibration of RTC_SLOW_CLK is performed using a special feature of + /// TIMG0. This feature counts the number of XTAL clock cycles within a + /// given number of RTC_SLOW_CLK cycles. + #[cfg(esp32c6)] + fn calibrate_internal(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { + todo!() + } - /// Measure ratio between XTAL frequency and RTC slow clock frequency - fn get_calibration_ratio(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { - let xtal_cycles = RtcClock::calibrate_internal(cal_clk, slowclk_cycles) as u64; - let ratio = (xtal_cycles << RtcClock::CAL_FRACT) / slowclk_cycles as u64; + /// Measure ratio between XTAL frequency and RTC slow clock frequency + fn get_calibration_ratio(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { + let xtal_cycles = RtcClock::calibrate_internal(cal_clk, slowclk_cycles) as u64; + let ratio = (xtal_cycles << RtcClock::CAL_FRACT) / slowclk_cycles as u64; - (ratio & (u32::MAX as u64)) as u32 - } + (ratio & (u32::MAX as u64)) as u32 + } - /// Measure RTC slow clock's period, based on main XTAL frequency - /// - /// This function will time out and return 0 if the time for the given - /// number of cycles to be counted exceeds the expected time twice. This - /// may happen if 32k XTAL is being calibrated, but the oscillator has - /// not started up (due to incorrect loading capacitance, board design - /// issue, or lack of 32 XTAL on board). - fn calibrate(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { - let xtal_freq = RtcClock::get_xtal_freq(); - let xtal_cycles = RtcClock::calibrate_internal(cal_clk, slowclk_cycles) as u64; - let divider = xtal_freq.mhz() as u64 * slowclk_cycles as u64; - let period_64 = - ((xtal_cycles << RtcClock::CAL_FRACT) + divider / 2u64 - 1u64) / divider; - - (period_64 & u32::MAX as u64) as u32 - } + /// Measure RTC slow clock's period, based on main XTAL frequency + /// + /// This function will time out and return 0 if the time for the given + /// number of cycles to be counted exceeds the expected time twice. This + /// may happen if 32k XTAL is being calibrated, but the oscillator has + /// not started up (due to incorrect loading capacitance, board design + /// issue, or lack of 32 XTAL on board). + fn calibrate(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { + let xtal_freq = RtcClock::get_xtal_freq(); + let xtal_cycles = RtcClock::calibrate_internal(cal_clk, slowclk_cycles) as u64; + let divider = xtal_freq.mhz() as u64 * slowclk_cycles as u64; + let period_64 = ((xtal_cycles << RtcClock::CAL_FRACT) + divider / 2u64 - 1u64) / divider; + + (period_64 & u32::MAX as u64) as u32 + } + + /// Calculate the necessary RTC_SLOW_CLK cycles to complete 1 millisecond. + fn cycles_to_1ms() -> u16 { + let period_13q19 = RtcClock::calibrate( + match RtcClock::get_slow_freq() { + RtcSlowClock::RtcSlowClockRtc => RtcCalSel::RtcCalRtcMux, + RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, + #[cfg(not(esp32c6))] + RtcSlowClock::RtcSlowClock8mD256 => RtcCalSel::RtcCal8mD256, + #[cfg(esp32c6)] + RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc, + #[cfg(esp32c6)] + RtcSlowClock::RtcCalInternalOsc => RtcCalSel::RtcCalInternalOsc, + #[cfg(esp32c6)] + RtcSlowClock::RtcCalRcFast => RtcCalSel::RtcCalRcFast, + }, + 1024, + ); + + // 100_000_000 is used to get rid of `float` calculations + let period = (100_000_000 * period_13q19 as u64) / (1 << RtcClock::CAL_FRACT); + + (100_000_000 * 1000 / period) as u16 + } - /// Calculate the necessary RTC_SLOW_CLK cycles to complete 1 - /// millisecond. - fn cycles_to_1ms() -> u16 { - let period_13q19 = RtcClock::calibrate( - match RtcClock::get_slow_freq() { - RtcSlowClock::RtcSlowClockRtc => RtcCalSel::RtcCalRtcMux, - RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, - #[cfg(not(esp32c6))] - RtcSlowClock::RtcSlowClock8mD256 => RtcCalSel::RtcCal8mD256, - #[cfg(esp32c6)] - RtcSlowClock::RtcCalRcFast => RtcCalSel::RtcCalRcFast, - }, - 1024, - ); - - // 100_000_000 is used to get rid of `float` calculations - let period = (100_000_000 * period_13q19 as u64) / (1 << RtcClock::CAL_FRACT); - - (100_000_000 * 1000 / period) as u16 - } + #[cfg(not(esp32c6))] + fn estimate_xtal_frequency() -> u32 { + // Number of 8M/256 clock cycles to use for XTAL frequency estimation. + const XTAL_FREQ_EST_CYCLES: u32 = 10; - #[cfg(not(esp32c6))] - fn estimate_xtal_frequency() -> u32 { - // Number of 8M/256 clock cycles to use for XTAL frequency estimation. - const XTAL_FREQ_EST_CYCLES: u32 = 10; + let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; + let clk_8m_enabled = rtc_cntl.clk_conf.read().enb_ck8m().bit_is_clear(); + let clk_8md256_enabled = rtc_cntl.clk_conf.read().enb_ck8m_div().bit_is_clear(); - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; - let clk_8m_enabled = rtc_cntl.clk_conf.read().enb_ck8m().bit_is_clear(); - let clk_8md256_enabled = rtc_cntl.clk_conf.read().enb_ck8m_div().bit_is_clear(); + if !clk_8md256_enabled { + RtcClock::enable_8m(true, true); + } - if !clk_8md256_enabled { - RtcClock::enable_8m(true, true); - } + let ratio = RtcClock::get_calibration_ratio(RtcCalSel::RtcCal8mD256, XTAL_FREQ_EST_CYCLES); + let freq_mhz = + ((ratio as u64 * RtcFastClock::RtcFastClock8m.hz() as u64 / 1_000_000u64 / 256u64) + >> RtcClock::CAL_FRACT) as u32; - let ratio = - RtcClock::get_calibration_ratio(RtcCalSel::RtcCal8mD256, XTAL_FREQ_EST_CYCLES); - let freq_mhz = - ((ratio as u64 * RtcFastClock::RtcFastClock8m.hz() as u64 / 1_000_000u64 / 256u64) - >> RtcClock::CAL_FRACT) as u32; + RtcClock::enable_8m(clk_8m_enabled, clk_8md256_enabled); - RtcClock::enable_8m(clk_8m_enabled, clk_8md256_enabled); + freq_mhz + } - freq_mhz - } + #[cfg(esp32c6)] + fn estimate_xtal_frequency() -> u32 { + todo!() } } + /// Behavior of the RWDT stage if it times out #[allow(unused)] #[derive(Debug, Clone, Copy)] @@ -916,7 +613,7 @@ impl Default for Rwdt { /// RTC Watchdog Timer driver impl Rwdt { pub fn listen(&mut self) { - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; + let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; self.stg0_action = RwdtStageAction::RwdtStageActionInterrupt; @@ -938,7 +635,7 @@ impl Rwdt { } pub fn unlisten(&mut self) { - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; + let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; self.stg0_action = RwdtStageAction::RwdtStageActionResetRtc; @@ -960,7 +657,7 @@ impl Rwdt { } pub fn clear_interrupt(&mut self) { - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; + let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; self.set_write_protection(false); @@ -973,7 +670,7 @@ impl Rwdt { } pub fn is_interrupt_set(&self) -> bool { - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; + let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; cfg_if::cfg_if! { if #[cfg(esp32)] { @@ -986,7 +683,7 @@ impl Rwdt { /// Enable/disable write protection for WDT registers fn set_write_protection(&mut self, enable: bool) { - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; + let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; let wkey = if enable { 0u32 } else { 0x50D8_3AA1 }; rtc_cntl.wdtwprotect.write(|w| unsafe { w.bits(wkey) }); @@ -996,7 +693,7 @@ impl Rwdt { #[cfg(not(esp32c6))] impl WatchdogDisable for Rwdt { fn disable(&mut self) { - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; + let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; self.set_write_protection(false); @@ -1016,7 +713,7 @@ impl WatchdogEnable for Rwdt { where T: Into, { - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; + let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; let timeout_raw = (period.into().to_millis() * (RtcClock::cycles_to_1ms() as u64)) as u32; self.set_write_protection(false); @@ -1058,17 +755,15 @@ impl WatchdogEnable for Rwdt { #[cfg(not(esp32c6))] impl Watchdog for Rwdt { fn feed(&mut self) { - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; + let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; self.set_write_protection(false); - rtc_cntl.wdtfeed.write(|w| unsafe { w.bits(1) }); - self.set_write_protection(true); } } -#[cfg(any(esp32c6))] +#[cfg(esp32c6)] /// RTC Watchdog Timer driver impl Rwdt { pub fn listen(&mut self) { @@ -1146,7 +841,26 @@ impl WatchdogDisable for Rwdt { } } -#[cfg(any(esp32c2, esp32c3, esp32s3, esp32c6))] +#[cfg(esp32c6)] +impl WatchdogEnable for Rwdt { + type Time = MicrosDurationU64; + + fn start(&mut self, period: T) + where + T: Into, + { + todo!() + } +} + +#[cfg(esp32c6)] +impl Watchdog for Rwdt { + fn feed(&mut self) { + todo!() + } +} + +#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] /// Super Watchdog pub struct Swd; @@ -1159,7 +873,7 @@ impl Swd { /// Enable/disable write protection for WDT registers fn set_write_protection(&mut self, enable: bool) { - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; + let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; let wkey = if enable { 0u32 } else { 0x8F1D_312A }; rtc_cntl @@ -1171,12 +885,10 @@ impl Swd { #[cfg(any(esp32c2, esp32c3, esp32s3))] impl WatchdogDisable for Swd { fn disable(&mut self) { - let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; + let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; self.set_write_protection(false); - rtc_cntl.swd_conf.write(|w| w.swd_auto_feed_en().set_bit()); - self.set_write_protection(true); } } @@ -1190,7 +902,6 @@ impl Swd { /// Enable/disable write protection for WDT registers fn set_write_protection(&mut self, enable: bool) { let rtc_cntl = unsafe { &*LP_WDT::ptr() }; - let wkey = if enable { 0u32 } else { 0x8F1D_312A }; let wkey = if enable { 0u32 } else { 0x50D8_3AA1 }; rtc_cntl @@ -1199,7 +910,7 @@ impl Swd { } } -#[cfg(any(esp32c6))] +#[cfg(esp32c6)] impl WatchdogDisable for Swd { fn disable(&mut self) { let rtc_cntl = unsafe { &*LP_WDT::ptr() }; From 4f9734210cf1cb6f73c2ca56267577662428c04c Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Wed, 8 Feb 2023 10:34:21 -0800 Subject: [PATCH 40/64] Add the C6 to our CI workflow --- .github/workflows/ci.yml | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 201b2e3cfb0..d79221a4bdd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -118,6 +118,39 @@ jobs: - name: check esp32c3-hal (async, spi) run: cd esp32c3-hal/ && cargo check --example=embassy_spi --features=embassy,embassy-time-systick,async + esp32c6-hal: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: dtolnay/rust-toolchain@v1 + with: + target: riscv32imc-unknown-none-elf + toolchain: nightly + components: rust-src + - uses: Swatinem/rust-cache@v2 + + # Perform a full build initially to verify that the examples not only + # build, but also link successfully. + # We also use this as an opportunity to verify that the examples link + # for each supported image format. + - name: build esp32c6-hal (no features) + run: cd esp32c6-hal/ && cargo build --examples + - name: build esp32c6-hal (direct-boot) + run: cd esp32c6-hal/ && cargo build --examples --features=direct-boot + # Subsequent steps can just check the examples instead, as we're already + # confident that they link. + - name: check esp32c6-hal (common features) + run: cd esp32c6-hal/ && cargo check --examples --features=eh1,ufmt + - name: check esp32c6-hal (async, systick) + run: cd esp32c6-hal/ && cargo check --example=embassy_hello_world --features=embassy,embassy-time-systick + - name: check esp32c6-hal (async, timg0) + run: cd esp32c6-hal/ && cargo check --example=embassy_hello_world --features=embassy,embassy-time-timg0 + - name: check esp32c6-hal (async, gpio) + run: cd esp32c6-hal/ && cargo check --example=embassy_wait --features=embassy,embassy-time-systick,async + - name: check esp32c6-hal (async, spi) + run: cd esp32c6-hal/ && cargo check --example=embassy_spi --features=embassy,embassy-time-systick,async + esp32s2-hal: runs-on: ubuntu-latest @@ -180,6 +213,7 @@ jobs: run: cd esp32s3-hal/ && cargo check --example=embassy_wait --features=embassy,embassy-time-timg0,async - name: check esp32s3-hal (async, spi) run: cd esp32s3-hal/ && cargo check --example=embassy_spi --features=embassy,embassy-time-timg0,async + # -------------------------------------------------------------------------- # MSRV @@ -199,6 +233,8 @@ jobs: run: cd esp32c2-hal/ && cargo check --features=eh1,ufmt - name: msrv (esp32c3-hal) run: cd esp32c3-hal/ && cargo check --features=eh1,ufmt,smartled + - name: msrv (esp32c6-hal) + run: cd esp32c6-hal/ && cargo check --features=eh1,ufmt,smartled msrv-xtensa: runs-on: ubuntu-latest @@ -238,6 +274,8 @@ jobs: run: cargo +stable clippy --manifest-path=esp32c2-hal/Cargo.toml -- --no-deps - name: clippy (esp32c3-hal) run: cargo +stable clippy --manifest-path=esp32c3-hal/Cargo.toml -- --no-deps + - name: clippy (esp32c6-hal) + run: cargo +stable clippy --manifest-path=esp32c6-hal/Cargo.toml -- --no-deps clippy-xtensa: runs-on: ubuntu-latest @@ -286,6 +324,8 @@ jobs: run: cargo fmt --all --manifest-path=esp32c2-hal/Cargo.toml -- --check - name: rustfmt (esp32c3-hal) run: cargo fmt --all --manifest-path=esp32c3-hal/Cargo.toml -- --check + - name: rustfmt (esp32c6-hal) + run: cargo fmt --all --manifest-path=esp32c6-hal/Cargo.toml -- --check - name: rustfmt (esp32s2-hal) run: cargo fmt --all --manifest-path=esp32s2-hal/Cargo.toml -- --check - name: rustfmt (esp32s3-hal) From 403c6402b0e06200160a1382b55349275ead0fcc Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Wed, 8 Feb 2023 11:44:20 -0800 Subject: [PATCH 41/64] Fix various things that have been missed when rebasing Still missing a few examples (`clock_monitor`, `embassy_spi`, `ram`) --- README.md | 21 +++--- esp-hal-common/src/dma/mod.rs | 73 ++++++++++++++++++- esp-hal-common/src/gpio/esp32c6.rs | 2 + esp32c6-hal/Cargo.toml | 12 +++- esp32c6-hal/examples/blinky_erased_pins.rs | 63 ++++++++++++++++ esp32c6-hal/examples/embassy_hello_world.rs | 74 +++++++++++++++++++ esp32c6-hal/examples/embassy_wait.rs | 80 +++++++++++++++++++++ esp32c6-hal/examples/i2c.rs | 63 ---------------- 8 files changed, 314 insertions(+), 74 deletions(-) create mode 100644 esp32c6-hal/examples/blinky_erased_pins.rs create mode 100644 esp32c6-hal/examples/embassy_hello_world.rs create mode 100644 esp32c6-hal/examples/embassy_wait.rs delete mode 100644 esp32c6-hal/examples/i2c.rs diff --git a/README.md b/README.md index 35e42820cd7..2bd15275a9c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ![MIT/Apache-2.0 licensed](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue?style=flat-square) [![Matrix](https://img.shields.io/matrix/esp-rs:matrix.org?label=join%20matrix&color=BEC5C9&logo=matrix&style=flat-square)](https://matrix.to/#/#esp-rs:matrix.org) -**H**ardware **A**bstraction **L**ayer crates for the **ESP32**, **ESP32-C2**, **ESP32-C3**, **ESP32-S2**, and **ESP32-S3** from Espressif. +**H**ardware **A**bstraction **L**ayer crates for the **ESP32**, **ESP32-C2/C3/C6**, and **ESP32-S2/S3** from Espressif. These HALs are `no_std`; if you are looking for `std` support, please use [esp-idf-hal] instead. @@ -12,13 +12,14 @@ This project is still in the early stages of development, and as such there shou If you have any questions, comments, or concerns, please [open an issue], [start a new discussion], or join us on [Matrix]. For additional information regarding any of the crates in this repository, please refer to the crate's README. -| Crate | Target | Technical Reference Manual | -| :-----------: | :-----------------------------------------------------------------: | :------------------------: | -| [esp32-hal] | `xtensa-esp32-none-elf` | [ESP32] | -| [esp32c2-hal] | `riscv32imc-unknown-none-elf` | [ESP32-C2] | -| [esp32c3-hal] | `riscv32imc-unknown-none-elf` | [ESP32-C3] | -| [esp32s2-hal] | `xtensa-esp32s2-none-elf` | [ESP32-S2] | -| [esp32s3-hal] | `xtensa-esp32s3-none-elf` | [ESP32-S3] | +| Crate | Target | Technical Reference Manual | +| :-----------: | :---------------------------: | :------------------------: | +| [esp32-hal] | `xtensa-esp32-none-elf` | [ESP32] | +| [esp32c2-hal] | `riscv32imc-unknown-none-elf` | [ESP32-C2] | +| [esp32c3-hal] | `riscv32imc-unknown-none-elf` | [ESP32-C3] | +| [esp32c6-hal] | `riscv32imc-unknown-none-elf` | [ESP32-C6] | +| [esp32s2-hal] | `xtensa-esp32s2-none-elf` | [ESP32-S2] | +| [esp32s3-hal] | `xtensa-esp32s3-none-elf` | [ESP32-S3] | [here]: https://github.com/esp-rs/esp-hal/issues/19 [esp-idf-hal]: https://github.com/esp-rs/esp-idf-hal @@ -28,11 +29,13 @@ If you have any questions, comments, or concerns, please [open an issue], [start [esp32-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32-hal [esp32c2-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c2-hal [esp32c3-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c3-hal +[esp32c6-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32c6-hal [esp32s2-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32s2-hal [esp32s3-hal]: https://github.com/esp-rs/esp-hal/tree/main/esp32s3-hal [esp32]: https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf [esp32-c2]: https://www.espressif.com/sites/default/files/documentation/esp8684_technical_reference_manual_en.pdf [esp32-c3]: https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf +[esp32-c6]: https://www.espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf [esp32-s2]: https://www.espressif.com/sites/default/files/documentation/esp32-s2_technical_reference_manual_en.pdf [esp32-s3]: https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdf [atomic emulation]: https://github.com/esp-rs/riscv-atomic-emulation-trap @@ -62,6 +65,7 @@ There are a number of other crates within the [esp-rs organization] which can be | [esp-backtrace] | Backtrace support for bare-metal applications | | [esp-println] | Provides `print!` and `println!` implementations | | [esp-storage] | Implementation of [embedded-storage] traits to access unencrypted flash memory | +| [esp-wifi] | Experimental `no_std` Wi-Fi/Bluetooth LE support | [esp-rs organization]: https://github.com/esp-rs [esp-alloc]: https://github.com/esp-rs/esp-alloc @@ -69,6 +73,7 @@ There are a number of other crates within the [esp-rs organization] which can be [esp-println]: https://github.com/esp-rs/esp-println [esp-storage]: https://github.com/esp-rs/esp-storage [embedded-storage]: https://github.com/rust-embedded-community/embedded-storage +[esp-wifi]: https://github.com/esp-rs/esp-wifi ## MSRV diff --git a/esp-hal-common/src/dma/mod.rs b/esp-hal-common/src/dma/mod.rs index 4c7247fc73d..6574c2ae035 100644 --- a/esp-hal-common/src/dma/mod.rs +++ b/esp-hal-common/src/dma/mod.rs @@ -1024,6 +1024,77 @@ pub(crate) mod asynch { } } + #[cfg(esp32c6)] + mod interrupt { + use super::*; + + #[interrupt] + fn DMA_IN_CH0() { + use crate::dma::gdma::{Channel0 as Channel, Channel0RxImpl as ChannelRxImpl}; + + if Channel::is_in_done() { + Channel::clear_in_interrupts(); + Channel::unlisten_in_eof(); + ChannelRxImpl::waker().wake() + } + } + + #[interrupt] + fn DMA_OUT_CH0() { + use crate::dma::gdma::{Channel0 as Channel, Channel0TxImpl as ChannelTxImpl}; + + if Channel::is_out_done() { + Channel::clear_out_interrupts(); + Channel::unlisten_out_eof(); + ChannelTxImpl::waker().wake() + } + } + + #[interrupt] + fn DMA_IN_CH1() { + use crate::dma::gdma::{Channel1 as Channel, Channel1RxImpl as ChannelRxImpl}; + + if Channel::is_in_done() { + Channel::clear_in_interrupts(); + Channel::unlisten_in_eof(); + ChannelRxImpl::waker().wake() + } + } + + #[interrupt] + fn DMA_OUT_CH1() { + use crate::dma::gdma::{Channel1 as Channel, Channel1TxImpl as ChannelTxImpl}; + + if Channel::is_out_done() { + Channel::clear_out_interrupts(); + Channel::unlisten_out_eof(); + ChannelTxImpl::waker().wake() + } + } + + #[interrupt] + fn DMA_IN_CH2() { + use crate::dma::gdma::{Channel2 as Channel, Channel2RxImpl as ChannelRxImpl}; + + if Channel::is_in_done() { + Channel::clear_in_interrupts(); + Channel::unlisten_in_eof(); + ChannelRxImpl::waker().wake() + } + } + + #[interrupt] + fn DMA_OUT_CH2() { + use crate::dma::gdma::{Channel2 as Channel, Channel2TxImpl as ChannelTxImpl}; + + if Channel::is_out_done() { + Channel::clear_out_interrupts(); + Channel::unlisten_out_eof(); + ChannelTxImpl::waker().wake() + } + } + } + #[cfg(esp32s3)] mod interrupt { use super::*; @@ -1117,7 +1188,7 @@ pub(crate) mod asynch { } } - #[cfg(any(esp32s2, esp32))] + #[cfg(any(esp32, esp32s2))] mod interrupt { use super::*; diff --git a/esp-hal-common/src/gpio/esp32c6.rs b/esp-hal-common/src/gpio/esp32c6.rs index 07ee4212b07..ca8bb15c791 100644 --- a/esp-hal-common/src/gpio/esp32c6.rs +++ b/esp-hal-common/src/gpio/esp32c6.rs @@ -11,6 +11,8 @@ use crate::{ Unknown, }; +pub const NUM_PINS: usize = 30; + pub type OutputSignalType = u8; pub const OUTPUT_SIGNAL_MAX: u8 = 128; pub const INPUT_SIGNAL_MAX: u8 = 124; diff --git a/esp32c6-hal/Cargo.toml b/esp32c6-hal/Cargo.toml index b3d673e19d7..da3e7f632fc 100644 --- a/esp32c6-hal/Cargo.toml +++ b/esp32c6-hal/Cargo.toml @@ -74,6 +74,14 @@ required-features = ["eh1"] name = "spi_eh1_device_loopback" required-features = ["eh1"] +[[example]] +name = "embassy_hello_world" +required-features = ["async", "embassy"] + +[[example]] +name = "embassy_wait" +required-features = ["async", "embassy"] + # [[example]] -# name = "embassy_hello_world" -# required-features = ["embassy"] +# name = "embassy_spi" +# required-features = ["async", "embassy"] diff --git a/esp32c6-hal/examples/blinky_erased_pins.rs b/esp32c6-hal/examples/blinky_erased_pins.rs new file mode 100644 index 00000000000..81d40cd20bf --- /dev/null +++ b/esp32c6-hal/examples/blinky_erased_pins.rs @@ -0,0 +1,63 @@ +//! Blinks an LED +//! +//! This assumes that LEDs are connected to GPIO3, 4 and 5. + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + gpio::{AnyPin, Input, Output, PullDown, PushPull, IO}, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Delay, + Rtc, +}; +use esp_backtrace as _; +use esp_riscv_rt::entry; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt = timer_group0.wdt; + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + // Disable MWDT and RWDT (Watchdog) flash boot protection + wdt.disable(); + rtc.rwdt.disable(); + + // Set GPIO4 as an output, and set its state high initially. + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let led1 = io.pins.gpio3.into_push_pull_output(); + let led2 = io.pins.gpio4.into_push_pull_output(); + let led3 = io.pins.gpio5.into_push_pull_output(); + + let button = io.pins.gpio0.into_pull_down_input().degrade(); + + // you can use `into` or `degrade` + let mut pins = [led1.into(), led2.into(), led3.degrade()]; + + // Initialize the Delay peripheral, and use it to toggle the LED state in a + // loop. + let mut delay = Delay::new(&clocks); + + loop { + toggle_pins(&mut pins, &button); + delay.delay_ms(500u32); + } +} + +fn toggle_pins(leds: &mut [AnyPin>], button: &AnyPin>) { + for pin in leds.iter_mut() { + pin.toggle().unwrap(); + } + + if button.is_low().unwrap() { + esp_println::println!("Button"); + } +} diff --git a/esp32c6-hal/examples/embassy_hello_world.rs b/esp32c6-hal/examples/embassy_hello_world.rs new file mode 100644 index 00000000000..88712c9da0b --- /dev/null +++ b/esp32c6-hal/examples/embassy_hello_world.rs @@ -0,0 +1,74 @@ +//! embassy hello world +//! +//! This is an example of running the embassy executor with multiple tasks +//! concurrently. + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use embassy_executor::Executor; +use embassy_time::{Duration, Timer}; +use esp32c6_hal::{ + clock::ClockControl, + embassy, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, +}; +use esp_backtrace as _; +use static_cell::StaticCell; + +#[embassy_executor::task] +async fn run1() { + loop { + esp_println::println!("Hello world from embassy using esp-hal-async!"); + Timer::after(Duration::from_millis(1_000)).await; + } +} + +#[embassy_executor::task] +async fn run2() { + loop { + esp_println::println!("Bing!"); + Timer::after(Duration::from_millis(5_000)).await; + } +} + +static EXECUTOR: StaticCell = StaticCell::new(); + +#[esp_riscv_rt::entry] +fn main() -> ! { + esp_println::println!("Init!"); + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let mut wdt1 = timer_group1.wdt; + + // Disable watchdog timers + rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); + + #[cfg(feature = "embassy-time-systick")] + embassy::init( + &clocks, + esp32c6_hal::systimer::SystemTimer::new(peripherals.SYSTIMER), + ); + + #[cfg(feature = "embassy-time-timg0")] + embassy::init(&clocks, timer_group0.timer0); + + let executor = EXECUTOR.init(Executor::new()); + executor.run(|spawner| { + spawner.spawn(run1()).ok(); + spawner.spawn(run2()).ok(); + }); +} diff --git a/esp32c6-hal/examples/embassy_wait.rs b/esp32c6-hal/examples/embassy_wait.rs new file mode 100644 index 00000000000..8844c0444b7 --- /dev/null +++ b/esp32c6-hal/examples/embassy_wait.rs @@ -0,0 +1,80 @@ +//! embassy wait +//! +//! This is an example of asynchronously `Wait`ing for a pin state to change. + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use embassy_executor::Executor; +use embassy_time::{Duration, Timer}; +use embedded_hal_async::digital::Wait; +use esp32c6_hal::{ + clock::ClockControl, + embassy, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, + IO, +}; +use esp_backtrace as _; +use esp_hal_common::{Gpio0, Input, PullDown}; +use static_cell::StaticCell; + +#[embassy_executor::task] +async fn ping(mut pin: Gpio0>) { + loop { + esp_println::println!("Waiting..."); + pin.wait_for_rising_edge().await.unwrap(); + esp_println::println!("Ping!"); + Timer::after(Duration::from_millis(100)).await; + } +} + +static EXECUTOR: StaticCell = StaticCell::new(); + +#[esp_riscv_rt::entry] +fn main() -> ! { + esp_println::println!("Init!"); + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let mut wdt1 = timer_group1.wdt; + + // Disable watchdog timers + rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); + + #[cfg(feature = "embassy-time-systick")] + embassy::init( + &clocks, + esp32c6_hal::systimer::SystemTimer::new(peripherals.SYSTIMER), + ); + + #[cfg(feature = "embassy-time-timg0")] + embassy::init(&clocks, timer_group0.timer0); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + // GPIO 0 as input + let input = io.pins.gpio0.into_pull_down_input(); + + // Async requires the GPIO interrupt to wake futures + esp32c6_hal::interrupt::enable( + esp32c6_hal::peripherals::Interrupt::GPIO, + esp32c6_hal::interrupt::Priority::Priority1, + ) + .unwrap(); + + let executor = EXECUTOR.init(Executor::new()); + executor.run(|spawner| { + spawner.spawn(ping(input)).ok(); + }); +} diff --git a/esp32c6-hal/examples/i2c.rs b/esp32c6-hal/examples/i2c.rs deleted file mode 100644 index d197e7066ca..00000000000 --- a/esp32c6-hal/examples/i2c.rs +++ /dev/null @@ -1,63 +0,0 @@ -//! Read calibration data from BMP180 sensor -//! -//! This example dumps the calibration data from a BMP180 sensor -//! -//! The following wiring is assumed: -//! - SDA => GPIO1 -//! - SCL => GPIO2 - -#![no_std] -#![no_main] - -use esp32c6_hal::{ - clock::ClockControl, - gpio::IO, - i2c::I2C, - peripherals::Peripherals, - prelude::*, - timer::TimerGroup, - Rtc, -}; -use esp_backtrace as _; -use esp_println::println; -use esp_riscv_rt::entry; - -#[entry] -fn main() -> ! { - let peripherals = Peripherals::take(); - let mut system = peripherals.PCR.split(); - let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - - // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, - // and the TIMG WDTs. - let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; - let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; - - let mut rtc = Rtc::new(peripherals.LP_CLKRST); - - // Disable MWDT and RWDT (Watchdog) flash boot protection - rtc.rwdt.disable(); - rtc.swd.disable(); - - let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); - - // Create a new peripheral object with the described wiring - // and standard I2C clock speed - let mut i2c = I2C::new( - peripherals.I2C0, - io.pins.gpio1, - io.pins.gpio2, - 100u32.kHz(), - &mut system.peripheral_clock_control, - &clocks, - ); - - loop { - let mut data = [0u8; 1]; - i2c.write_read(0x76, &[0xD0], &mut data).ok(); - - println!("{:02x?}", data); - } -} From 08f6f19eae0a505d29fb6fac8a1a1b432330f045 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Thu, 9 Feb 2023 17:11:25 +0100 Subject: [PATCH 42/64] C6: Small updates in wdt (#1) * C6: Update WDT * C6: Update examples with WDT update --- esp-hal-common/src/rtc_cntl/mod.rs | 178 +++++------------- esp-hal-common/src/timer.rs | 16 ++ esp32c6-hal/examples/adc.rs | 11 +- esp32c6-hal/examples/advanced_serial.rs | 9 +- esp32c6-hal/examples/aes.rs | 14 +- esp32c6-hal/examples/blinky.rs | 12 +- esp32c6-hal/examples/blinky_erased_pins.rs | 13 +- esp32c6-hal/examples/gpio_interrupt.rs | 13 +- esp32c6-hal/examples/hello_rgb.rs | 15 +- esp32c6-hal/examples/hello_world.rs | 11 +- .../examples/i2c_bmp180_calibration_data.rs | 6 +- esp32c6-hal/examples/i2c_display.rs | 6 +- esp32c6-hal/examples/i2s_read.rs | 13 +- esp32c6-hal/examples/i2s_sound.rs | 6 +- esp32c6-hal/examples/ledc.rs | 13 +- esp32c6-hal/examples/mcpwm.rs | 13 +- esp32c6-hal/examples/pcnt_encoder.rs | 16 +- esp32c6-hal/examples/pulse_control.rs | 13 +- esp32c6-hal/examples/read_efuse.rs | 6 +- esp32c6-hal/examples/serial_interrupts.rs | 6 +- .../examples/spi_eh1_device_loopback.rs | 7 +- esp32c6-hal/examples/spi_eh1_loopback.rs | 7 +- esp32c6-hal/examples/spi_loopback.rs | 13 +- esp32c6-hal/examples/spi_loopback_dma.rs | 13 +- esp32c6-hal/examples/systimer.rs | 13 +- esp32c6-hal/examples/timer_interrupt.rs | 17 +- esp32c6-hal/examples/usb_serial_jtag.rs | 6 +- esp32c6-hal/examples/watchdog.rs | 3 +- 28 files changed, 219 insertions(+), 250 deletions(-) diff --git a/esp-hal-common/src/rtc_cntl/mod.rs b/esp-hal-common/src/rtc_cntl/mod.rs index 332c72a8b7c..0d5d3c3e1bf 100644 --- a/esp-hal-common/src/rtc_cntl/mod.rs +++ b/esp-hal-common/src/rtc_cntl/mod.rs @@ -2,7 +2,7 @@ use embedded_hal::watchdog::{Watchdog, WatchdogDisable, WatchdogEnable}; use fugit::{HertzU32, MicrosDurationU64}; use self::rtc::SocResetReason; -#[cfg(not(any(esp32, esp32c6)))] +#[cfg(not(any(esp32)))] use crate::efuse::Efuse; #[cfg(esp32c6)] use crate::peripherals::{LP_AON, LP_CLKRST, LP_WDT, PMU}; @@ -609,11 +609,14 @@ impl Default for Rwdt { } } -#[cfg(not(esp32c6))] /// RTC Watchdog Timer driver impl Rwdt { pub fn listen(&mut self) { + + #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; + #[cfg(esp32c6)] + let rtc_cntl = unsafe { &*LP_WDT::PTR }; self.stg0_action = RwdtStageAction::RwdtStageActionInterrupt; @@ -635,7 +638,11 @@ impl Rwdt { } pub fn unlisten(&mut self) { + + #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; + #[cfg(esp32c6)] + let rtc_cntl = unsafe { &*LP_WDT::PTR }; self.stg0_action = RwdtStageAction::RwdtStageActionResetRtc; @@ -657,7 +664,11 @@ impl Rwdt { } pub fn clear_interrupt(&mut self) { + + #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; + #[cfg(esp32c6)] + let rtc_cntl = unsafe { &*LP_WDT::PTR }; self.set_write_protection(false); @@ -670,7 +681,11 @@ impl Rwdt { } pub fn is_interrupt_set(&self) -> bool { + + #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; + #[cfg(esp32c6)] + let rtc_cntl = unsafe { &*LP_WDT::PTR }; cfg_if::cfg_if! { if #[cfg(esp32)] { @@ -683,17 +698,24 @@ impl Rwdt { /// Enable/disable write protection for WDT registers fn set_write_protection(&mut self, enable: bool) { + + #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; + #[cfg(esp32c6)] + let rtc_cntl = unsafe { &*LP_WDT::PTR }; let wkey = if enable { 0u32 } else { 0x50D8_3AA1 }; rtc_cntl.wdtwprotect.write(|w| unsafe { w.bits(wkey) }); } } -#[cfg(not(esp32c6))] impl WatchdogDisable for Rwdt { fn disable(&mut self) { + + #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; + #[cfg(esp32c6)] + let rtc_cntl = unsafe { &*LP_WDT::PTR }; self.set_write_protection(false); @@ -713,9 +735,11 @@ impl WatchdogEnable for Rwdt { where T: Into, { + #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; + #[cfg(esp32c6)] + let rtc_cntl = unsafe { &*LP_WDT::PTR }; let timeout_raw = (period.into().to_millis() * (RtcClock::cycles_to_1ms() as u64)) as u32; - self.set_write_protection(false); unsafe { @@ -752,10 +776,13 @@ impl WatchdogEnable for Rwdt { } } -#[cfg(not(esp32c6))] impl Watchdog for Rwdt { fn feed(&mut self) { + + #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; + #[cfg(esp32c6)] + let rtc_cntl = unsafe { &*LP_WDT::PTR }; self.set_write_protection(false); rtc_cntl.wdtfeed.write(|w| unsafe { w.bits(1) }); @@ -763,108 +790,11 @@ impl Watchdog for Rwdt { } } -#[cfg(esp32c6)] -/// RTC Watchdog Timer driver -impl Rwdt { - pub fn listen(&mut self) { - let rtc_cntl = unsafe { &*LP_WDT::ptr() }; - - self.stg0_action = RwdtStageAction::RwdtStageActionInterrupt; - - self.set_write_protection(false); - - // Configure STAGE0 to trigger an interrupt upon expiration - rtc_cntl - .config0 - .modify(|_, w| unsafe { w.wdt_stg0().bits(self.stg0_action as u8) }); - - rtc_cntl.int_ena.modify(|_, w| w.lp_wdt_int_ena().set_bit()); - - self.set_write_protection(true); - } - - pub fn unlisten(&mut self) { - let rtc_cntl = unsafe { &*LP_WDT::ptr() }; - - self.stg0_action = RwdtStageAction::RwdtStageActionResetRtc; - - self.set_write_protection(false); - - // Configure STAGE0 to reset the main system and the RTC upon expiration. - rtc_cntl - .config0 - .modify(|_, w| unsafe { w.wdt_stg0().bits(self.stg0_action as u8) }); - - rtc_cntl - .int_ena - .modify(|_, w| w.lp_wdt_int_ena().clear_bit()); - - self.set_write_protection(true); - } - - pub fn clear_interrupt(&mut self) { - let rtc_cntl = unsafe { &*LP_WDT::ptr() }; - - self.set_write_protection(false); - - rtc_cntl.int_clr.write(|w| w.lp_wdt_int_clr().set_bit()); - - self.set_write_protection(true); - } - - pub fn is_interrupt_set(&self) -> bool { - let rtc_cntl = unsafe { &*LP_WDT::ptr() }; - rtc_cntl.int_st.read().lp_wdt_int_st().bit_is_set() - } - - /// Enable/disable write protection for WDT registers - fn set_write_protection(&mut self, enable: bool) { - let rtc_cntl = unsafe { &*LP_WDT::ptr() }; - let wkey = if enable { 0u32 } else { 0x50D8_3AA1 }; - - rtc_cntl.wprotect.write(|w| unsafe { w.bits(wkey) }); - } -} - -#[cfg(esp32c6)] -impl WatchdogDisable for Rwdt { - fn disable(&mut self) { - let rtc_cntl = unsafe { &*LP_WDT::ptr() }; - - self.set_write_protection(false); - - rtc_cntl - .config0 - .modify(|_, w| w.wdt_en().clear_bit().wdt_flashboot_mod_en().clear_bit()); - - self.set_write_protection(true); - } -} - -#[cfg(esp32c6)] -impl WatchdogEnable for Rwdt { - type Time = MicrosDurationU64; - - fn start(&mut self, period: T) - where - T: Into, - { - todo!() - } -} - -#[cfg(esp32c6)] -impl Watchdog for Rwdt { - fn feed(&mut self) { - todo!() - } -} - #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] /// Super Watchdog pub struct Swd; -#[cfg(any(esp32c2, esp32c3, esp32s3))] +#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] /// Super Watchdog driver impl Swd { pub fn new() -> Self { @@ -873,7 +803,11 @@ impl Swd { /// Enable/disable write protection for WDT registers fn set_write_protection(&mut self, enable: bool) { + + #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; + #[cfg(esp32c6)] + let rtc_cntl = unsafe { &*LP_WDT::PTR }; let wkey = if enable { 0u32 } else { 0x8F1D_312A }; rtc_cntl @@ -882,10 +816,14 @@ impl Swd { } } -#[cfg(any(esp32c2, esp32c3, esp32s3))] +#[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] impl WatchdogDisable for Swd { fn disable(&mut self) { + + #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; + #[cfg(esp32c6)] + let rtc_cntl = unsafe { &*LP_WDT::PTR }; self.set_write_protection(false); rtc_cntl.swd_conf.write(|w| w.swd_auto_feed_en().set_bit()); @@ -893,38 +831,6 @@ impl WatchdogDisable for Swd { } } -#[cfg(esp32c6)] -impl Swd { - pub fn new() -> Self { - Self - } - - /// Enable/disable write protection for WDT registers - fn set_write_protection(&mut self, enable: bool) { - let rtc_cntl = unsafe { &*LP_WDT::ptr() }; - let wkey = if enable { 0u32 } else { 0x50D8_3AA1 }; - - rtc_cntl - .swd_wprotect - .write(|w| unsafe { w.swd_wkey().bits(wkey) }); - } -} - -#[cfg(esp32c6)] -impl WatchdogDisable for Swd { - fn disable(&mut self) { - let rtc_cntl = unsafe { &*LP_WDT::ptr() }; - - self.set_write_protection(false); - - rtc_cntl - .swd_config - .write(|w| w.swd_auto_feed_en().set_bit()); - - self.set_write_protection(true); - } -} - pub fn get_reset_reason(cpu: Cpu) -> Option { let reason = unsafe { rtc_get_reset_reason(cpu as u32) }; let reason = SocResetReason::from_repr(reason as usize); diff --git a/esp-hal-common/src/timer.rs b/esp-hal-common/src/timer.rs index 5d3249b91ab..b43777fb52b 100644 --- a/esp-hal-common/src/timer.rs +++ b/esp-hal-common/src/timer.rs @@ -566,11 +566,27 @@ where { /// Create a new watchdog timer instance pub fn new() -> Self { + #[cfg(esp32c6)] + Self::enable_clock(); Self { phantom: PhantomData::default(), } } + #[cfg(esp32c6)] + fn enable_clock() { + let pcr = unsafe { &*crate::peripherals::PCR::ptr() }; + pcr.timergroup0_wdt_clk_conf + .write(|w| w.tg0_wdt_clk_en().set_bit()); + pcr.timergroup0_wdt_clk_conf + .write(|w| unsafe { w.tg0_wdt_clk_sel().bits(1) }); + + pcr.timergroup1_timer_clk_conf + .write(|w| w.tg1_timer_clk_en().set_bit()); + pcr.timergroup1_timer_clk_conf + .write(|w| unsafe { w.tg1_timer_clk_sel().bits(1) }); + } + fn set_wdt_enabled(&mut self, enabled: bool) { let reg_block = unsafe { &*TG::register_block() }; diff --git a/esp32c6-hal/examples/adc.rs b/esp32c6-hal/examples/adc.rs index 50d60829ac2..c3583086391 100644 --- a/esp32c6-hal/examples/adc.rs +++ b/esp32c6-hal/examples/adc.rs @@ -27,15 +27,16 @@ fn main() -> ! { // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; + let mut wdt1 = timer_group1.wdt; - // Disable MWDT and RWDT (Watchdog) flash boot protection - let mut rtc = Rtc::new(peripherals.LP_CLKRST); - rtc.rwdt.disable(); rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/esp32c6-hal/examples/advanced_serial.rs b/esp32c6-hal/examples/advanced_serial.rs index 3ca083b9122..30e8853d7bc 100644 --- a/esp32c6-hal/examples/advanced_serial.rs +++ b/esp32c6-hal/examples/advanced_serial.rs @@ -30,16 +30,19 @@ fn main() -> ! { let system = peripherals.PCR.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); let mut timer0 = timer_group0.timer0; - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; + let mut wdt1 = timer_group1.wdt; - // Disable watchdog timers rtc.swd.disable(); rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let config = Config { baudrate: 115200, diff --git a/esp32c6-hal/examples/aes.rs b/esp32c6-hal/examples/aes.rs index 307edf29c66..3b4ca590054 100644 --- a/esp32c6-hal/examples/aes.rs +++ b/esp32c6-hal/examples/aes.rs @@ -25,16 +25,18 @@ fn main() -> ! { // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, // and the TIMG WDTs. + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; + let mut wdt1 = timer_group1.wdt; - let mut rtc = Rtc::new(peripherals.LP_CLKRST); - - // Disable MWDT and RWDT (Watchdog) flash boot protection - rtc.rwdt.disable(); rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let mut aes = Aes::new(peripherals.AES, &mut system.peripheral_clock_control); diff --git a/esp32c6-hal/examples/blinky.rs b/esp32c6-hal/examples/blinky.rs index 74f90a0a8a8..2285cfc1c5b 100644 --- a/esp32c6-hal/examples/blinky.rs +++ b/esp32c6-hal/examples/blinky.rs @@ -23,14 +23,18 @@ fn main() -> ! { let system = peripherals.PCR.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; + let mut wdt1 = timer_group1.wdt; - let mut rtc = Rtc::new(peripherals.LP_CLKRST); - rtc.rwdt.disable(); rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); // Set GPIO5 as an output, and set its state high initially. let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/esp32c6-hal/examples/blinky_erased_pins.rs b/esp32c6-hal/examples/blinky_erased_pins.rs index 81d40cd20bf..11f3a88c8e6 100644 --- a/esp32c6-hal/examples/blinky_erased_pins.rs +++ b/esp32c6-hal/examples/blinky_erased_pins.rs @@ -23,13 +23,18 @@ fn main() -> ! { let system = peripherals.PCR.split(); let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); - let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let mut wdt = timer_group0.wdt; + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let mut wdt1 = timer_group1.wdt; - // Disable MWDT and RWDT (Watchdog) flash boot protection - wdt.disable(); + rtc.swd.disable(); rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); // Set GPIO4 as an output, and set its state high initially. let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/esp32c6-hal/examples/gpio_interrupt.rs b/esp32c6-hal/examples/gpio_interrupt.rs index 73fa9d545f4..11afcede303 100644 --- a/esp32c6-hal/examples/gpio_interrupt.rs +++ b/esp32c6-hal/examples/gpio_interrupt.rs @@ -32,16 +32,17 @@ fn main() -> ! { // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; - - let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let mut wdt1 = timer_group1.wdt; - // Disable MWDT and RWDT (Watchdog) flash boot protection - rtc.rwdt.disable(); + // Disable watchdog timers rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); // Set GPIO5 as an output let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/esp32c6-hal/examples/hello_rgb.rs b/esp32c6-hal/examples/hello_rgb.rs index f9b32e15864..ba6f1f20b21 100644 --- a/esp32c6-hal/examples/hello_rgb.rs +++ b/esp32c6-hal/examples/hello_rgb.rs @@ -40,18 +40,17 @@ fn main() -> ! { // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; - - let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let mut wdt1 = timer_group1.wdt; - let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); - - // Disable MWDT and RWDT (Watchdog) flash boot protection - rtc.rwdt.disable(); + // Disable watchdog timers rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); // Configure RMT peripheral globally let pulse = PulseControl::new( diff --git a/esp32c6-hal/examples/hello_world.rs b/esp32c6-hal/examples/hello_world.rs index 6471e71c849..d69b14fd3c4 100644 --- a/esp32c6-hal/examples/hello_world.rs +++ b/esp32c6-hal/examples/hello_world.rs @@ -25,13 +25,18 @@ fn main() -> ! { let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); let mut uart0 = Uart::new(peripherals.UART0); + let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); let mut timer0 = timer_group0.timer0; - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; + let mut wdt1 = timer_group1.wdt; - let _rtc = Rtc::new(peripherals.LP_CLKRST); + // Disable watchdog timers + rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); timer0.start(1u64.secs()); diff --git a/esp32c6-hal/examples/i2c_bmp180_calibration_data.rs b/esp32c6-hal/examples/i2c_bmp180_calibration_data.rs index 971d4924b75..85fc6699b43 100644 --- a/esp32c6-hal/examples/i2c_bmp180_calibration_data.rs +++ b/esp32c6-hal/examples/i2c_bmp180_calibration_data.rs @@ -30,13 +30,15 @@ fn main() -> ! { let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; + let mut wdt1 = timer_group1.wdt; // Disable watchdog timers rtc.swd.disable(); rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/esp32c6-hal/examples/i2c_display.rs b/esp32c6-hal/examples/i2c_display.rs index db53c002fde..9d3b0ad00be 100644 --- a/esp32c6-hal/examples/i2c_display.rs +++ b/esp32c6-hal/examples/i2c_display.rs @@ -42,13 +42,15 @@ fn main() -> ! { let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); let mut timer0 = timer_group0.timer0; - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; + let mut wdt1 = timer_group1.wdt; // Disable watchdog timers rtc.swd.disable(); rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/esp32c6-hal/examples/i2s_read.rs b/esp32c6-hal/examples/i2s_read.rs index 5a563a4f994..aa288a76653 100644 --- a/esp32c6-hal/examples/i2s_read.rs +++ b/esp32c6-hal/examples/i2s_read.rs @@ -37,16 +37,17 @@ fn main() -> ! { // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; - - let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let mut wdt1 = timer_group1.wdt; - // Disable MWDT and RWDT (Watchdog) flash boot protection - rtc.rwdt.disable(); + // Disable watchdog timers rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/esp32c6-hal/examples/i2s_sound.rs b/esp32c6-hal/examples/i2s_sound.rs index ddef77005c5..6e63af90684 100644 --- a/esp32c6-hal/examples/i2s_sound.rs +++ b/esp32c6-hal/examples/i2s_sound.rs @@ -60,13 +60,15 @@ fn main() -> ! { let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; + let mut wdt1 = timer_group1.wdt; // Disable watchdog timers rtc.swd.disable(); rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/esp32c6-hal/examples/ledc.rs b/esp32c6-hal/examples/ledc.rs index cdd3a5b793b..24ed968586e 100644 --- a/esp32c6-hal/examples/ledc.rs +++ b/esp32c6-hal/examples/ledc.rs @@ -32,16 +32,17 @@ fn main() -> ! { // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; - - let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let mut wdt1 = timer_group1.wdt; - // Disable MWDT and RWDT (Watchdog) flash boot protection - rtc.rwdt.disable(); + // Disable watchdog timers rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); let led = io.pins.gpio4.into_push_pull_output(); diff --git a/esp32c6-hal/examples/mcpwm.rs b/esp32c6-hal/examples/mcpwm.rs index 68c2aa9d594..6886a857303 100644 --- a/esp32c6-hal/examples/mcpwm.rs +++ b/esp32c6-hal/examples/mcpwm.rs @@ -26,16 +26,17 @@ fn main() -> ! { // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; - - let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let mut wdt1 = timer_group1.wdt; - // Disable MWDT and RWDT (Watchdog) flash boot protection - rtc.rwdt.disable(); + // Disable watchdog timers rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); let pin = io.pins.gpio4; diff --git a/esp32c6-hal/examples/pcnt_encoder.rs b/esp32c6-hal/examples/pcnt_encoder.rs index 358d1e41616..7f21d166f9b 100644 --- a/esp32c6-hal/examples/pcnt_encoder.rs +++ b/esp32c6-hal/examples/pcnt_encoder.rs @@ -41,18 +41,17 @@ fn main() -> ! { // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; - - let mut rtc = Rtc::new(peripherals.LP_CLKRST); - - let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let mut wdt1 = timer_group1.wdt; - // Disable MWDT and RWDT (Watchdog) flash boot protection - rtc.rwdt.disable(); + // Disable watchdog timers rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let unit_number = unit::Number::Unit1; @@ -70,6 +69,7 @@ fn main() -> ! { println!("setup channel 0"); let mut ch0 = u0.get_channel(channel::Number::Channel0); + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); let mut pin_a = io.pins.gpio5.into_pull_up_input(); let mut pin_b = io.pins.gpio6.into_pull_up_input(); diff --git a/esp32c6-hal/examples/pulse_control.rs b/esp32c6-hal/examples/pulse_control.rs index e2cd2ef6fee..54096f47c7e 100644 --- a/esp32c6-hal/examples/pulse_control.rs +++ b/esp32c6-hal/examples/pulse_control.rs @@ -26,16 +26,17 @@ fn main() -> ! { // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; - - let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let mut wdt1 = timer_group1.wdt; - // Disable MWDT and RWDT (Watchdog) flash boot protection - rtc.rwdt.disable(); + // Disable watchdog timers rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); diff --git a/esp32c6-hal/examples/read_efuse.rs b/esp32c6-hal/examples/read_efuse.rs index 831563ff006..ffbb52ab557 100644 --- a/esp32c6-hal/examples/read_efuse.rs +++ b/esp32c6-hal/examples/read_efuse.rs @@ -24,13 +24,15 @@ fn main() -> ! { let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; + let mut wdt1 = timer_group1.wdt; // Disable watchdog timers rtc.swd.disable(); rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); println!("MAC address {:02x?}", Efuse::get_mac_address()); println!("Flash Encryption {:?}", Efuse::get_flash_encryption()); diff --git a/esp32c6-hal/examples/serial_interrupts.rs b/esp32c6-hal/examples/serial_interrupts.rs index 5b3179c2e6f..a0232043b0e 100644 --- a/esp32c6-hal/examples/serial_interrupts.rs +++ b/esp32c6-hal/examples/serial_interrupts.rs @@ -35,13 +35,15 @@ fn main() -> ! { let mut serial0 = Uart::new(peripherals.UART0); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); let mut timer0 = timer_group0.timer0; - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; + let mut wdt1 = timer_group1.wdt; // Disable watchdog timers rtc.swd.disable(); rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); serial0.set_at_cmd(AtCmdConfig::new(None, None, None, b'#', None)); serial0.set_rx_fifo_full_threshold(30); diff --git a/esp32c6-hal/examples/spi_eh1_device_loopback.rs b/esp32c6-hal/examples/spi_eh1_device_loopback.rs index caf35a5e63a..7ac85b6800b 100644 --- a/esp32c6-hal/examples/spi_eh1_device_loopback.rs +++ b/esp32c6-hal/examples/spi_eh1_device_loopback.rs @@ -43,12 +43,15 @@ fn main() -> ! { // the RTC WDT, and the TIMG WDTs. let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; + let mut wdt1 = timer_group1.wdt; + // Disable watchdog timers rtc.swd.disable(); rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); let sclk = io.pins.gpio6; diff --git a/esp32c6-hal/examples/spi_eh1_loopback.rs b/esp32c6-hal/examples/spi_eh1_loopback.rs index 3e45dc8c34b..5edb3202f81 100644 --- a/esp32c6-hal/examples/spi_eh1_loopback.rs +++ b/esp32c6-hal/examples/spi_eh1_loopback.rs @@ -41,12 +41,15 @@ fn main() -> ! { // the RTC WDT, and the TIMG WDTs. let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; + let mut wdt1 = timer_group1.wdt; + // Disable watchdog timers rtc.swd.disable(); rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); let sclk = io.pins.gpio6; diff --git a/esp32c6-hal/examples/spi_loopback.rs b/esp32c6-hal/examples/spi_loopback.rs index f27d3c5fcaa..e8fffecaeb4 100644 --- a/esp32c6-hal/examples/spi_loopback.rs +++ b/esp32c6-hal/examples/spi_loopback.rs @@ -38,16 +38,17 @@ fn main() -> ! { // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; - - let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let mut wdt1 = timer_group1.wdt; - // Disable MWDT and RWDT (Watchdog) flash boot protection - rtc.rwdt.disable(); + // Disable watchdog timers rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); let sclk = io.pins.gpio6; diff --git a/esp32c6-hal/examples/spi_loopback_dma.rs b/esp32c6-hal/examples/spi_loopback_dma.rs index 27e2cd4d612..c5bd1b0564b 100644 --- a/esp32c6-hal/examples/spi_loopback_dma.rs +++ b/esp32c6-hal/examples/spi_loopback_dma.rs @@ -40,16 +40,17 @@ fn main() -> ! { // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; - - let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let mut wdt1 = timer_group1.wdt; - // Disable MWDT and RWDT (Watchdog) flash boot protection - rtc.rwdt.disable(); + // Disable watchdog timers rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); let sclk = io.pins.gpio6; diff --git a/esp32c6-hal/examples/systimer.rs b/esp32c6-hal/examples/systimer.rs index d33982fe195..0344b67f3a1 100644 --- a/esp32c6-hal/examples/systimer.rs +++ b/esp32c6-hal/examples/systimer.rs @@ -34,16 +34,17 @@ fn main() -> ! { // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; - - let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let mut wdt1 = timer_group1.wdt; - // Disable MWDT and RWDT (Watchdog) flash boot protection - rtc.rwdt.disable(); + // Disable watchdog timers rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let syst = SystemTimer::new(peripherals.SYSTIMER); diff --git a/esp32c6-hal/examples/timer_interrupt.rs b/esp32c6-hal/examples/timer_interrupt.rs index d1a3bedf1f0..dc1432649ee 100644 --- a/esp32c6-hal/examples/timer_interrupt.rs +++ b/esp32c6-hal/examples/timer_interrupt.rs @@ -30,18 +30,19 @@ fn main() -> ! { // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); let mut timer0 = timer_group0.timer0; - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); let mut timer1 = timer_group1.timer0; - let _wdt1 = timer_group1.wdt; - - let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let mut wdt1 = timer_group1.wdt; - // Disable MWDT and RWDT (Watchdog) flash boot protection - rtc.rwdt.disable(); + // Disable watchdog timers rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); interrupt::enable( peripherals::Interrupt::TG0_T0_LEVEL, @@ -83,7 +84,7 @@ fn TG0_T0_LEVEL() { let timer0 = timer0.as_mut().unwrap(); timer0.clear_interrupt(); - timer0.start(10000u64.millis()); + timer0.start(500u64.millis()); }); } @@ -96,6 +97,6 @@ fn TG1_T0_LEVEL() { let timer1 = timer1.as_mut().unwrap(); timer1.clear_interrupt(); - timer1.start(19500u64.millis()); + timer1.start(1u64.secs()); }); } diff --git a/esp32c6-hal/examples/usb_serial_jtag.rs b/esp32c6-hal/examples/usb_serial_jtag.rs index 74a0e1b42c8..f4371ae8b92 100644 --- a/esp32c6-hal/examples/usb_serial_jtag.rs +++ b/esp32c6-hal/examples/usb_serial_jtag.rs @@ -34,13 +34,15 @@ fn main() -> ! { let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); let mut timer0 = timer_group0.timer0; - let _wdt0 = timer_group0.wdt; + let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; + let mut wdt1 = timer_group1.wdt; // Disable watchdog timers rtc.swd.disable(); rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); let mut usb_serial = UsbSerialJtag::new(peripherals.USB_DEVICE); diff --git a/esp32c6-hal/examples/watchdog.rs b/esp32c6-hal/examples/watchdog.rs index 1b81f3f0a90..8f4e11da0e1 100644 --- a/esp32c6-hal/examples/watchdog.rs +++ b/esp32c6-hal/examples/watchdog.rs @@ -28,12 +28,13 @@ fn main() -> ! { let mut timer0 = timer_group0.timer0; let mut wdt0 = timer_group0.wdt; let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); - let _wdt1 = timer_group1.wdt; + let mut wdt1 = timer_group1.wdt; // Disable watchdog timers rtc.swd.disable(); rtc.rwdt.disable(); wdt0.start(2u64.secs()); + wdt1.disable(); timer0.start(1u64.secs()); From 730b6b39bcc36a0fb694924a6d3b259084461add Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Thu, 9 Feb 2023 08:38:30 -0800 Subject: [PATCH 43/64] Update `esp-println` dependency to fix build errors --- esp-hal-common/Cargo.toml | 3 --- esp32c6-hal/Cargo.toml | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/esp-hal-common/Cargo.toml b/esp-hal-common/Cargo.toml index b266b53446c..59330a12ed7 100644 --- a/esp-hal-common/Cargo.toml +++ b/esp-hal-common/Cargo.toml @@ -60,9 +60,6 @@ esp32c6 = { path = "C:/Users/JurajSadel/esp-pacs/esp32c6", features = ["critica esp32s2 = { version = "0.12.0", features = ["critical-section"], optional = true } esp32s3 = { version = "0.15.0", features = ["critical-section"], optional = true } -# REMOVE BEFOFE MERGE -esp-println = { git = "https://github.com/esp-rs/esp-println", features = ["esp32c6"] } - [features] esp32 = ["esp32/rt" , "xtensa", "xtensa-lx/esp32", "xtensa-lx-rt/esp32", "lock_api", "procmacros/esp32"] esp32c2 = ["esp32c2/rt", "riscv", "procmacros/esp32c2"] diff --git a/esp32c6-hal/Cargo.toml b/esp32c6-hal/Cargo.toml index da3e7f632fc..4e5542d189d 100644 --- a/esp32c6-hal/Cargo.toml +++ b/esp32c6-hal/Cargo.toml @@ -43,7 +43,7 @@ critical-section = "1.1.1" embassy-executor = { package = "embassy-executor", git = "https://github.com/embassy-rs/embassy/", rev = "cd9a65b", features = ["nightly", "integrated-timers"] } embedded-graphics = "0.7.1" esp-backtrace = { git = "https://github.com/jessebraham/esp-backtrace", branch = "feature/chip-support", features = ["esp32c6", "panic-handler", "exception-handler", "print-uart"] } -esp-println = { git = "https://github.com/esp-rs/esp-println", rev = "fc4e9cf", features = ["esp32c6"] } +esp-println = { git = "https://github.com/esp-rs/esp-println", rev = "316b5b9", features = ["esp32c6"] } sha2 = { version = "0.10.6", default-features = false} smart-leds = "0.3.0" ssd1306 = "0.7.1" @@ -60,7 +60,7 @@ vectored = ["esp-hal-common/vectored"] async = ["esp-hal-common/async", "embedded-hal-async"] embassy = ["esp-hal-common/embassy"] embassy-time-systick = ["esp-hal-common/embassy-time-systick", "embassy-time/tick-hz-16_000_000"] -embassy-time-timg0 = ["esp-hal-common/embassy-time-timg0", "embassy-time/tick-hz-1_000_000"] +embassy-time-timg0 = ["esp-hal-common/embassy-time-timg0", "embassy-time/tick-hz-1_000_000"] [[example]] name = "hello_rgb" From e903e90ebec4a0d53b8f50cc140a776967a27141 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Thu, 9 Feb 2023 08:40:08 -0800 Subject: [PATCH 44/64] Fix formatting issues causing pre-commit hook to fail --- esp-hal-common/src/aes/esp32cX.rs | 2 +- esp-hal-common/src/lib.rs | 16 ++++++++-------- esp-hal-common/src/rtc_cntl/mod.rs | 9 --------- 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/esp-hal-common/src/aes/esp32cX.rs b/esp-hal-common/src/aes/esp32cX.rs index 3142d1fe6a4..e0bc104a23e 100644 --- a/esp-hal-common/src/aes/esp32cX.rs +++ b/esp-hal-common/src/aes/esp32cX.rs @@ -55,4 +55,4 @@ impl AesFlavour for Aes256 { type KeyType<'b> = &'b [u8; 32]; const ENCRYPT_MODE: u32 = 2; const DECRYPT_MODE: u32 = 6; -} \ No newline at end of file +} diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index f80a541c4e2..100c994aa1b 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -26,14 +26,6 @@ #![cfg_attr(feature = "async", feature(async_fn_in_trait))] #![cfg_attr(feature = "async", feature(impl_trait_projections))] -#[cfg_attr(esp32, path = "peripherals/esp32.rs")] -#[cfg_attr(esp32c3, path = "peripherals/esp32c3.rs")] -#[cfg_attr(esp32c2, path = "peripherals/esp32c2.rs")] -#[cfg_attr(esp32c6, path = "peripherals/esp32c6.rs")] -#[cfg_attr(esp32s2, path = "peripherals/esp32s2.rs")] -#[cfg_attr(esp32s3, path = "peripherals/esp32s3.rs")] -pub mod peripherals; - #[cfg(riscv)] pub use esp_riscv_rt; #[cfg(riscv)] @@ -130,6 +122,14 @@ pub mod efuse; #[cfg_attr(xtensa, path = "interrupt/xtensa.rs")] pub mod interrupt; +#[cfg_attr(esp32, path = "peripherals/esp32.rs")] +#[cfg_attr(esp32c3, path = "peripherals/esp32c3.rs")] +#[cfg_attr(esp32c2, path = "peripherals/esp32c2.rs")] +#[cfg_attr(esp32c6, path = "peripherals/esp32c6.rs")] +#[cfg_attr(esp32s2, path = "peripherals/esp32s2.rs")] +#[cfg_attr(esp32s3, path = "peripherals/esp32s3.rs")] +pub mod peripherals; + /// Enumeration of CPU cores /// The actual number of available cores depends on the target. pub enum Cpu { diff --git a/esp-hal-common/src/rtc_cntl/mod.rs b/esp-hal-common/src/rtc_cntl/mod.rs index 0d5d3c3e1bf..0ee8cf46bab 100644 --- a/esp-hal-common/src/rtc_cntl/mod.rs +++ b/esp-hal-common/src/rtc_cntl/mod.rs @@ -612,7 +612,6 @@ impl Default for Rwdt { /// RTC Watchdog Timer driver impl Rwdt { pub fn listen(&mut self) { - #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; #[cfg(esp32c6)] @@ -638,7 +637,6 @@ impl Rwdt { } pub fn unlisten(&mut self) { - #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; #[cfg(esp32c6)] @@ -664,7 +662,6 @@ impl Rwdt { } pub fn clear_interrupt(&mut self) { - #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; #[cfg(esp32c6)] @@ -681,7 +678,6 @@ impl Rwdt { } pub fn is_interrupt_set(&self) -> bool { - #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; #[cfg(esp32c6)] @@ -698,7 +694,6 @@ impl Rwdt { /// Enable/disable write protection for WDT registers fn set_write_protection(&mut self, enable: bool) { - #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; #[cfg(esp32c6)] @@ -711,7 +706,6 @@ impl Rwdt { impl WatchdogDisable for Rwdt { fn disable(&mut self) { - #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; #[cfg(esp32c6)] @@ -778,7 +772,6 @@ impl WatchdogEnable for Rwdt { impl Watchdog for Rwdt { fn feed(&mut self) { - #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; #[cfg(esp32c6)] @@ -803,7 +796,6 @@ impl Swd { /// Enable/disable write protection for WDT registers fn set_write_protection(&mut self, enable: bool) { - #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; #[cfg(esp32c6)] @@ -819,7 +811,6 @@ impl Swd { #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] impl WatchdogDisable for Swd { fn disable(&mut self) { - #[cfg(not(esp32c6))] let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; #[cfg(esp32c6)] From 3622bc163b03c57a5942b4d91dccac0fd80c0842 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Thu, 9 Feb 2023 12:47:00 -0800 Subject: [PATCH 45/64] Get some more examples working --- esp-hal-common/build.rs | 1 + esp-hal-common/src/rtc_cntl/mod.rs | 9 +++++++-- esp32c6-hal/examples/blinky.rs | 7 +------ esp32c6-hal/examples/gpio_interrupt.rs | 6 +++--- esp32c6-hal/examples/hello_rgb.rs | 1 + 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/esp-hal-common/build.rs b/esp-hal-common/build.rs index 83f2fff4756..5c43dbd26b4 100644 --- a/esp-hal-common/build.rs +++ b/esp-hal-common/build.rs @@ -106,6 +106,7 @@ fn main() { "mcpwm", "rmt", "systimer", + "timg0", "timg1", "usb_serial_jtag", "plic", diff --git a/esp-hal-common/src/rtc_cntl/mod.rs b/esp-hal-common/src/rtc_cntl/mod.rs index 0ee8cf46bab..3b4f2200ab5 100644 --- a/esp-hal-common/src/rtc_cntl/mod.rs +++ b/esp-hal-common/src/rtc_cntl/mod.rs @@ -721,7 +721,6 @@ impl WatchdogDisable for Rwdt { } } -#[cfg(not(esp32c6))] impl WatchdogEnable for Rwdt { type Time = MicrosDurationU64; @@ -733,6 +732,7 @@ impl WatchdogEnable for Rwdt { let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; #[cfg(esp32c6)] let rtc_cntl = unsafe { &*LP_WDT::PTR }; + let timeout_raw = (period.into().to_millis() * (RtcClock::cycles_to_1ms() as u64)) as u32; self.set_write_protection(false); @@ -742,7 +742,12 @@ impl WatchdogEnable for Rwdt { .wdtconfig1 .modify(|_, w| w.wdt_stg0_hold().bits(timeout_raw)); - #[cfg(not(esp32))] + #[cfg(esp32c6)] + (&*LP_WDT::PTR) + .config1 + .modify(|_, w| w.wdt_stg0_hold().bits(timeout_raw)); + + #[cfg(not(any(esp32, esp32c6)))] rtc_cntl.wdtconfig1.modify(|_, w| { w.wdt_stg0_hold() .bits(timeout_raw >> (1 + Efuse::get_rwdt_multiplier())) diff --git a/esp32c6-hal/examples/blinky.rs b/esp32c6-hal/examples/blinky.rs index 2285cfc1c5b..c65e2934917 100644 --- a/esp32c6-hal/examples/blinky.rs +++ b/esp32c6-hal/examples/blinky.rs @@ -46,13 +46,8 @@ fn main() -> ! { // loop. let mut delay = Delay::new(&clocks); - // just for testing ... remove this - let rst_reason = unsafe { (0x600b0410 as *mut u32).read_volatile() & 0b11111 }; - esp_println::println!("raw rst reason {} 0x{:x}", rst_reason, rst_reason); - loop { - esp_println::println!("blinky"); led.toggle().unwrap(); - delay.delay_ms(2000u32); + delay.delay_ms(500u32); } } diff --git a/esp32c6-hal/examples/gpio_interrupt.rs b/esp32c6-hal/examples/gpio_interrupt.rs index 11afcede303..dd575a06a15 100644 --- a/esp32c6-hal/examples/gpio_interrupt.rs +++ b/esp32c6-hal/examples/gpio_interrupt.rs @@ -11,7 +11,7 @@ use core::cell::RefCell; use critical_section::Mutex; use esp32c6_hal::{ clock::ClockControl, - gpio::{Event, Gpio7, Input, PullDown, IO}, + gpio::{Event, Gpio9, Input, PullDown, IO}, interrupt, peripherals::{self, Peripherals}, prelude::*, @@ -22,7 +22,7 @@ use esp32c6_hal::{ use esp_backtrace as _; use esp_riscv_rt::{entry, riscv}; -static BUTTON: Mutex>>>> = Mutex::new(RefCell::new(None)); +static BUTTON: Mutex>>>> = Mutex::new(RefCell::new(None)); #[entry] fn main() -> ! { @@ -49,7 +49,7 @@ fn main() -> ! { let mut led = io.pins.gpio5.into_push_pull_output(); // Set GPIO9 as an input - let mut button = io.pins.gpio7.into_pull_down_input(); + let mut button = io.pins.gpio9.into_pull_down_input(); button.listen(Event::FallingEdge); critical_section::with(|cs| BUTTON.borrow_ref_mut(cs).replace(button)); diff --git a/esp32c6-hal/examples/hello_rgb.rs b/esp32c6-hal/examples/hello_rgb.rs index ba6f1f20b21..31fbd72aef5 100644 --- a/esp32c6-hal/examples/hello_rgb.rs +++ b/esp32c6-hal/examples/hello_rgb.rs @@ -65,6 +65,7 @@ fn main() -> ! { // We use one of the RMT channels to instantiate a `SmartLedsAdapter` which can // be used directly with all `smart_led` implementations + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); let mut led = ::new(pulse.channel0, io.pins.gpio8); // Initialize the Delay peripheral, and use it to toggle the LED state in a From 97474266da6d74aef9cbc53f6ab1d1e44df5a97c Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Fri, 10 Feb 2023 06:29:48 -0800 Subject: [PATCH 46/64] Working `ram` example --- esp32c6-hal/examples/ram.rs | 102 ++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 esp32c6-hal/examples/ram.rs diff --git a/esp32c6-hal/examples/ram.rs b/esp32c6-hal/examples/ram.rs new file mode 100644 index 00000000000..ef6b817b10c --- /dev/null +++ b/esp32c6-hal/examples/ram.rs @@ -0,0 +1,102 @@ +//! This shows how to use RTC memory. +//! RTC memory is retained during resets and during most sleep modes. +//! Initialized memory is always re-initialized on startup. +//! Uninitialzed memory isn't initialized on startup and can be used to keep +//! data during resets. Zeroed memory is initialized to zero on startup. +//! We can also run code from RTC memory. + +#![no_std] +#![no_main] + +use esp32c6_hal::{ + clock::ClockControl, + macros::ram, + peripherals::Peripherals, + prelude::*, + timer::TimerGroup, + Rtc, +}; +use esp_backtrace as _; +use esp_println::println; +use esp_riscv_rt::entry; +use nb::block; + +#[ram(rtc_fast)] +static mut SOME_INITED_DATA: [u8; 2] = [0xaa, 0xbb]; + +#[ram(rtc_fast, uninitialized)] +static mut SOME_UNINITED_DATA: [u8; 2] = [0; 2]; + +#[ram(rtc_fast, zeroed)] +static mut SOME_ZEROED_DATA: [u8; 8] = [0; 8]; + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut timer0 = timer_group0.timer0; + let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let mut wdt1 = timer_group1.wdt; + + // Disable MWDT flash boot protection + wdt0.disable(); + wdt1.disable(); + // The RWDT flash boot protection remains enabled and it being triggered is part + // of the example + + timer0.start(1u64.secs()); + + println!("RAM function located at {:p}", function_in_ram as *const ()); + unsafe { + println!("SOME_INITED_DATA {:x?}", SOME_INITED_DATA); + println!("SOME_UNINITED_DATA {:x?}", SOME_UNINITED_DATA); + println!("SOME_ZEROED_DATA {:x?}", SOME_ZEROED_DATA); + + SOME_INITED_DATA[0] = 0xff; + SOME_ZEROED_DATA[0] = 0xff; + + println!("SOME_INITED_DATA {:x?}", SOME_INITED_DATA); + println!("SOME_UNINITED_DATA {:x?}", SOME_UNINITED_DATA); + println!("SOME_ZEROED_DATA {:x?}", SOME_ZEROED_DATA); + + if SOME_UNINITED_DATA[0] != 0 { + SOME_UNINITED_DATA[0] = 0; + SOME_UNINITED_DATA[1] = 0; + } + + if SOME_UNINITED_DATA[1] == 0xff { + SOME_UNINITED_DATA[1] = 0; + } + + println!("Counter {}", SOME_UNINITED_DATA[1]); + SOME_UNINITED_DATA[1] += 1; + } + + println!( + "RTC_FAST function located at {:p}", + function_in_rtc_ram as *const () + ); + println!("Result {}", function_in_rtc_ram()); + + loop { + function_in_ram(); + block!(timer0.wait()).unwrap(); + } +} + +#[ram] +fn function_in_ram() { + println!("Hello world!"); +} + +#[ram(rtc_fast)] +fn function_in_rtc_ram() -> u32 { + 42 +} From e41ecdd03f76fdab56fe16ba3f0e26baf1ffcc5f Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Fri, 10 Feb 2023 07:45:17 -0800 Subject: [PATCH 47/64] Sync with changes in `main` after rebasing --- esp-hal-procmacros/Cargo.toml | 1 + esp-hal-procmacros/src/lib.rs | 4 ++++ esp32c6-hal/Cargo.toml | 5 ++--- esp32c6-hal/examples/adc.rs | 1 - esp32c6-hal/examples/advanced_serial.rs | 1 - esp32c6-hal/examples/aes.rs | 1 - esp32c6-hal/examples/blinky.rs | 1 - esp32c6-hal/examples/blinky_erased_pins.rs | 1 - esp32c6-hal/examples/embassy_hello_world.rs | 2 +- esp32c6-hal/examples/embassy_wait.rs | 2 +- esp32c6-hal/examples/gpio_interrupt.rs | 2 +- esp32c6-hal/examples/hello_rgb.rs | 1 - esp32c6-hal/examples/hello_world.rs | 1 - esp32c6-hal/examples/i2c_bmp180_calibration_data.rs | 1 - esp32c6-hal/examples/i2c_display.rs | 1 - esp32c6-hal/examples/i2s_read.rs | 1 - esp32c6-hal/examples/i2s_sound.rs | 1 - esp32c6-hal/examples/ledc.rs | 1 - esp32c6-hal/examples/mcpwm.rs | 1 - esp32c6-hal/examples/pcnt_encoder.rs | 1 - esp32c6-hal/examples/pulse_control.rs | 1 - esp32c6-hal/examples/ram.rs | 3 --- esp32c6-hal/examples/read_efuse.rs | 1 - esp32c6-hal/examples/serial_interrupts.rs | 2 +- esp32c6-hal/examples/sha.rs | 1 - esp32c6-hal/examples/spi_eh1_device_loopback.rs | 1 - esp32c6-hal/examples/spi_eh1_loopback.rs | 1 - esp32c6-hal/examples/spi_loopback.rs | 1 - esp32c6-hal/examples/spi_loopback_dma.rs | 1 - esp32c6-hal/examples/systimer.rs | 1 - esp32c6-hal/examples/timer_interrupt.rs | 2 +- esp32c6-hal/examples/usb_serial_jtag.rs | 2 +- esp32c6-hal/examples/watchdog.rs | 1 - esp32c6-hal/src/lib.rs | 11 +++++++++++ 34 files changed, 24 insertions(+), 35 deletions(-) diff --git a/esp-hal-procmacros/Cargo.toml b/esp-hal-procmacros/Cargo.toml index f130c77312e..dd8ce6ea323 100644 --- a/esp-hal-procmacros/Cargo.toml +++ b/esp-hal-procmacros/Cargo.toml @@ -30,5 +30,6 @@ xtensa = [] esp32 = [] esp32c2 = [] esp32c3 = [] +esp32c6 = [] esp32s2 = [] esp32s3 = [] diff --git a/esp-hal-procmacros/src/lib.rs b/esp-hal-procmacros/src/lib.rs index 73c385c0970..9d52a1d08c1 100644 --- a/esp-hal-procmacros/src/lib.rs +++ b/esp-hal-procmacros/src/lib.rs @@ -213,6 +213,8 @@ pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream { let hal_crate = crate_name("esp32c2-hal"); #[cfg(feature = "esp32c3")] let hal_crate = crate_name("esp32c3-hal"); + #[cfg(feature = "esp32c6")] + let hal_crate = crate_name("esp32c6-hal"); #[cfg(feature = "esp32")] let hal_crate_name = Ident::new("esp32_hal", Span::call_site().into()); @@ -224,6 +226,8 @@ pub fn interrupt(args: TokenStream, input: TokenStream) -> TokenStream { let hal_crate_name = Ident::new("esp32c2_hal", Span::call_site().into()); #[cfg(feature = "esp32c3")] let hal_crate_name = Ident::new("esp32c3_hal", Span::call_site().into()); + #[cfg(feature = "esp32c6")] + let hal_crate_name = Ident::new("esp32c6_hal", Span::call_site().into()); let interrupt_in_hal_crate = match hal_crate { Ok(FoundCrate::Itself) => { diff --git a/esp32c6-hal/Cargo.toml b/esp32c6-hal/Cargo.toml index 4e5542d189d..d0026c84bdc 100644 --- a/esp32c6-hal/Cargo.toml +++ b/esp32c6-hal/Cargo.toml @@ -33,8 +33,7 @@ embedded-hal-1 = { version = "=1.0.0-alpha.9", optional = true, package = "e embedded-hal-async = { version = "0.2.0-alpha.0", optional = true } embedded-hal-nb = { version = "=1.0.0-alpha.1", optional = true } embedded-can = { version = "0.4.1", optional = true } -esp-hal-common = { version = "0.5.0", features = ["esp32c6"], path = "../esp-hal-common" } -esp-riscv-rt = { version = "0.1.0", optional = true } +esp-hal-common = { version = "0.6.0", features = ["esp32c6"], path = "../esp-hal-common" } r0 = "1.0.0" [dev-dependencies] @@ -53,7 +52,7 @@ static_cell = "1.0.0" default = ["rt", "vectored"] direct-boot = [] eh1 = ["esp-hal-common/eh1", "dep:embedded-hal-1", "dep:embedded-hal-nb", "dep:embedded-can"] -rt = ["esp-riscv-rt"] +rt = [] smartled = ["esp-hal-common/smartled"] ufmt = ["esp-hal-common/ufmt"] vectored = ["esp-hal-common/vectored"] diff --git a/esp32c6-hal/examples/adc.rs b/esp32c6-hal/examples/adc.rs index c3583086391..592aa0d4833 100644 --- a/esp32c6-hal/examples/adc.rs +++ b/esp32c6-hal/examples/adc.rs @@ -17,7 +17,6 @@ use esp32c6_hal::{ }; use esp_backtrace as _; use esp_println::println; -use esp_riscv_rt::entry; #[entry] fn main() -> ! { diff --git a/esp32c6-hal/examples/advanced_serial.rs b/esp32c6-hal/examples/advanced_serial.rs index 30e8853d7bc..b76ea57d8ad 100644 --- a/esp32c6-hal/examples/advanced_serial.rs +++ b/esp32c6-hal/examples/advanced_serial.rs @@ -21,7 +21,6 @@ use esp32c6_hal::{ }; use esp_backtrace as _; use esp_println::println; -use esp_riscv_rt::entry; use nb::block; #[entry] diff --git a/esp32c6-hal/examples/aes.rs b/esp32c6-hal/examples/aes.rs index 3b4ca590054..e0c6861a2b3 100644 --- a/esp32c6-hal/examples/aes.rs +++ b/esp32c6-hal/examples/aes.rs @@ -15,7 +15,6 @@ use esp32c6_hal::{ }; use esp_backtrace as _; use esp_println::println; -use esp_riscv_rt::entry; #[entry] fn main() -> ! { diff --git a/esp32c6-hal/examples/blinky.rs b/esp32c6-hal/examples/blinky.rs index c65e2934917..8f59ed87e47 100644 --- a/esp32c6-hal/examples/blinky.rs +++ b/esp32c6-hal/examples/blinky.rs @@ -15,7 +15,6 @@ use esp32c6_hal::{ Rtc, }; use esp_backtrace as _; -use esp_riscv_rt::entry; #[entry] fn main() -> ! { diff --git a/esp32c6-hal/examples/blinky_erased_pins.rs b/esp32c6-hal/examples/blinky_erased_pins.rs index 11f3a88c8e6..412898f5b36 100644 --- a/esp32c6-hal/examples/blinky_erased_pins.rs +++ b/esp32c6-hal/examples/blinky_erased_pins.rs @@ -15,7 +15,6 @@ use esp32c6_hal::{ Rtc, }; use esp_backtrace as _; -use esp_riscv_rt::entry; #[entry] fn main() -> ! { diff --git a/esp32c6-hal/examples/embassy_hello_world.rs b/esp32c6-hal/examples/embassy_hello_world.rs index 88712c9da0b..197d4b56411 100644 --- a/esp32c6-hal/examples/embassy_hello_world.rs +++ b/esp32c6-hal/examples/embassy_hello_world.rs @@ -38,7 +38,7 @@ async fn run2() { static EXECUTOR: StaticCell = StaticCell::new(); -#[esp_riscv_rt::entry] +#[entry] fn main() -> ! { esp_println::println!("Init!"); let peripherals = Peripherals::take(); diff --git a/esp32c6-hal/examples/embassy_wait.rs b/esp32c6-hal/examples/embassy_wait.rs index 8844c0444b7..20e0fb91c4d 100644 --- a/esp32c6-hal/examples/embassy_wait.rs +++ b/esp32c6-hal/examples/embassy_wait.rs @@ -34,7 +34,7 @@ async fn ping(mut pin: Gpio0>) { static EXECUTOR: StaticCell = StaticCell::new(); -#[esp_riscv_rt::entry] +#[entry] fn main() -> ! { esp_println::println!("Init!"); let peripherals = Peripherals::take(); diff --git a/esp32c6-hal/examples/gpio_interrupt.rs b/esp32c6-hal/examples/gpio_interrupt.rs index dd575a06a15..64d6de3b4a1 100644 --- a/esp32c6-hal/examples/gpio_interrupt.rs +++ b/esp32c6-hal/examples/gpio_interrupt.rs @@ -15,12 +15,12 @@ use esp32c6_hal::{ interrupt, peripherals::{self, Peripherals}, prelude::*, + riscv, timer::TimerGroup, Delay, Rtc, }; use esp_backtrace as _; -use esp_riscv_rt::{entry, riscv}; static BUTTON: Mutex>>>> = Mutex::new(RefCell::new(None)); diff --git a/esp32c6-hal/examples/hello_rgb.rs b/esp32c6-hal/examples/hello_rgb.rs index 31fbd72aef5..b5a04ac37e7 100644 --- a/esp32c6-hal/examples/hello_rgb.rs +++ b/esp32c6-hal/examples/hello_rgb.rs @@ -24,7 +24,6 @@ use esp32c6_hal::{ }; #[allow(unused_imports)] use esp_backtrace as _; -use esp_riscv_rt::entry; use smart_leds::{ brightness, gamma, diff --git a/esp32c6-hal/examples/hello_world.rs b/esp32c6-hal/examples/hello_world.rs index d69b14fd3c4..c7c35d53b49 100644 --- a/esp32c6-hal/examples/hello_world.rs +++ b/esp32c6-hal/examples/hello_world.rs @@ -15,7 +15,6 @@ use esp32c6_hal::{ Uart, }; use esp_backtrace as _; -use esp_riscv_rt::entry; use nb::block; #[entry] diff --git a/esp32c6-hal/examples/i2c_bmp180_calibration_data.rs b/esp32c6-hal/examples/i2c_bmp180_calibration_data.rs index 85fc6699b43..3181beee3e2 100644 --- a/esp32c6-hal/examples/i2c_bmp180_calibration_data.rs +++ b/esp32c6-hal/examples/i2c_bmp180_calibration_data.rs @@ -20,7 +20,6 @@ use esp32c6_hal::{ }; use esp_backtrace as _; use esp_println::println; -use esp_riscv_rt::entry; #[entry] fn main() -> ! { diff --git a/esp32c6-hal/examples/i2c_display.rs b/esp32c6-hal/examples/i2c_display.rs index 9d3b0ad00be..399857ae523 100644 --- a/esp32c6-hal/examples/i2c_display.rs +++ b/esp32c6-hal/examples/i2c_display.rs @@ -29,7 +29,6 @@ use esp32c6_hal::{ Rtc, }; use esp_backtrace as _; -use esp_riscv_rt::entry; use nb::block; use ssd1306::{prelude::*, I2CDisplayInterface, Ssd1306}; diff --git a/esp32c6-hal/examples/i2s_read.rs b/esp32c6-hal/examples/i2s_read.rs index aa288a76653..f6ad4289331 100644 --- a/esp32c6-hal/examples/i2s_read.rs +++ b/esp32c6-hal/examples/i2s_read.rs @@ -27,7 +27,6 @@ use esp32c6_hal::{ }; use esp_backtrace as _; use esp_println::println; -use esp_riscv_rt::entry; #[entry] fn main() -> ! { diff --git a/esp32c6-hal/examples/i2s_sound.rs b/esp32c6-hal/examples/i2s_sound.rs index 6e63af90684..8f79b53a518 100644 --- a/esp32c6-hal/examples/i2s_sound.rs +++ b/esp32c6-hal/examples/i2s_sound.rs @@ -42,7 +42,6 @@ use esp32c6_hal::{ IO, }; use esp_backtrace as _; -use esp_riscv_rt::entry; const SINE: [i16; 64] = [ 0, 3211, 6392, 9511, 12539, 15446, 18204, 20787, 23169, 25329, 27244, 28897, 30272, 31356, diff --git a/esp32c6-hal/examples/ledc.rs b/esp32c6-hal/examples/ledc.rs index 24ed968586e..2a1339d3cb0 100644 --- a/esp32c6-hal/examples/ledc.rs +++ b/esp32c6-hal/examples/ledc.rs @@ -22,7 +22,6 @@ use esp32c6_hal::{ Rtc, }; use esp_backtrace as _; -use esp_riscv_rt::entry; #[entry] fn main() -> ! { diff --git a/esp32c6-hal/examples/mcpwm.rs b/esp32c6-hal/examples/mcpwm.rs index 6886a857303..030fa40cbdd 100644 --- a/esp32c6-hal/examples/mcpwm.rs +++ b/esp32c6-hal/examples/mcpwm.rs @@ -16,7 +16,6 @@ use esp32c6_hal::{ Rtc, }; use esp_backtrace as _; -use esp_riscv_rt::entry; #[entry] fn main() -> ! { diff --git a/esp32c6-hal/examples/pcnt_encoder.rs b/esp32c6-hal/examples/pcnt_encoder.rs index 7f21d166f9b..858b58ecbab 100644 --- a/esp32c6-hal/examples/pcnt_encoder.rs +++ b/esp32c6-hal/examples/pcnt_encoder.rs @@ -28,7 +28,6 @@ use esp_hal::{ IO, }; use esp_println::println; -use esp_riscv_rt::entry; static UNIT0: Mutex>> = Mutex::new(RefCell::new(None)); static VALUE: AtomicI32 = AtomicI32::new(0); diff --git a/esp32c6-hal/examples/pulse_control.rs b/esp32c6-hal/examples/pulse_control.rs index 54096f47c7e..597735e9ede 100644 --- a/esp32c6-hal/examples/pulse_control.rs +++ b/esp32c6-hal/examples/pulse_control.rs @@ -16,7 +16,6 @@ use esp32c6_hal::{ Rtc, }; use esp_backtrace as _; -use esp_riscv_rt::entry; #[entry] fn main() -> ! { diff --git a/esp32c6-hal/examples/ram.rs b/esp32c6-hal/examples/ram.rs index ef6b817b10c..1a66ce75318 100644 --- a/esp32c6-hal/examples/ram.rs +++ b/esp32c6-hal/examples/ram.rs @@ -14,11 +14,9 @@ use esp32c6_hal::{ peripherals::Peripherals, prelude::*, timer::TimerGroup, - Rtc, }; use esp_backtrace as _; use esp_println::println; -use esp_riscv_rt::entry; use nb::block; #[ram(rtc_fast)] @@ -38,7 +36,6 @@ fn main() -> ! { // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, // and the TIMG WDTs. - let mut rtc = Rtc::new(peripherals.LP_CLKRST); let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); let mut timer0 = timer_group0.timer0; let mut wdt0 = timer_group0.wdt; diff --git a/esp32c6-hal/examples/read_efuse.rs b/esp32c6-hal/examples/read_efuse.rs index ffbb52ab557..f5534858a35 100644 --- a/esp32c6-hal/examples/read_efuse.rs +++ b/esp32c6-hal/examples/read_efuse.rs @@ -14,7 +14,6 @@ use esp32c6_hal::{ }; use esp_backtrace as _; use esp_println::println; -use esp_riscv_rt::entry; #[entry] fn main() -> ! { diff --git a/esp32c6-hal/examples/serial_interrupts.rs b/esp32c6-hal/examples/serial_interrupts.rs index a0232043b0e..842630497c4 100644 --- a/esp32c6-hal/examples/serial_interrupts.rs +++ b/esp32c6-hal/examples/serial_interrupts.rs @@ -13,6 +13,7 @@ use esp32c6_hal::{ interrupt, peripherals::{self, Peripherals, UART0}, prelude::*, + riscv, timer::TimerGroup, uart::config::AtCmdConfig, Cpu, @@ -20,7 +21,6 @@ use esp32c6_hal::{ Uart, }; use esp_backtrace as _; -use esp_riscv_rt::{entry, riscv}; use nb::block; static SERIAL: Mutex>>> = Mutex::new(RefCell::new(None)); diff --git a/esp32c6-hal/examples/sha.rs b/esp32c6-hal/examples/sha.rs index aa841f90c70..fcd6e17d3c7 100644 --- a/esp32c6-hal/examples/sha.rs +++ b/esp32c6-hal/examples/sha.rs @@ -14,7 +14,6 @@ use esp32c6_hal::{ }; use esp_backtrace as _; use esp_println::println; -use esp_riscv_rt::entry; use nb::block; use sha2::{Digest, Sha256}; diff --git a/esp32c6-hal/examples/spi_eh1_device_loopback.rs b/esp32c6-hal/examples/spi_eh1_device_loopback.rs index 7ac85b6800b..8f90179ec9f 100644 --- a/esp32c6-hal/examples/spi_eh1_device_loopback.rs +++ b/esp32c6-hal/examples/spi_eh1_device_loopback.rs @@ -31,7 +31,6 @@ use esp32c6_hal::{ }; use esp_backtrace as _; use esp_println::{print, println}; -use esp_riscv_rt::entry; #[entry] fn main() -> ! { diff --git a/esp32c6-hal/examples/spi_eh1_loopback.rs b/esp32c6-hal/examples/spi_eh1_loopback.rs index 5edb3202f81..22bdcefe4f6 100644 --- a/esp32c6-hal/examples/spi_eh1_loopback.rs +++ b/esp32c6-hal/examples/spi_eh1_loopback.rs @@ -29,7 +29,6 @@ use esp32c6_hal::{ }; use esp_backtrace as _; use esp_println::{print, println}; -use esp_riscv_rt::entry; #[entry] fn main() -> ! { diff --git a/esp32c6-hal/examples/spi_loopback.rs b/esp32c6-hal/examples/spi_loopback.rs index e8fffecaeb4..2f3615d2fab 100644 --- a/esp32c6-hal/examples/spi_loopback.rs +++ b/esp32c6-hal/examples/spi_loopback.rs @@ -28,7 +28,6 @@ use esp32c6_hal::{ }; use esp_backtrace as _; use esp_println::println; -use esp_riscv_rt::entry; #[entry] fn main() -> ! { diff --git a/esp32c6-hal/examples/spi_loopback_dma.rs b/esp32c6-hal/examples/spi_loopback_dma.rs index c5bd1b0564b..059ffd45c34 100644 --- a/esp32c6-hal/examples/spi_loopback_dma.rs +++ b/esp32c6-hal/examples/spi_loopback_dma.rs @@ -30,7 +30,6 @@ use esp32c6_hal::{ }; use esp_backtrace as _; use esp_println::println; -use esp_riscv_rt::entry; #[entry] fn main() -> ! { diff --git a/esp32c6-hal/examples/systimer.rs b/esp32c6-hal/examples/systimer.rs index 0344b67f3a1..d252594f2c0 100644 --- a/esp32c6-hal/examples/systimer.rs +++ b/esp32c6-hal/examples/systimer.rs @@ -20,7 +20,6 @@ use esp32c6_hal::{ }; use esp_backtrace as _; use esp_println::println; -use esp_riscv_rt::entry; static ALARM0: Mutex>>> = Mutex::new(RefCell::new(None)); static ALARM1: Mutex>>> = Mutex::new(RefCell::new(None)); diff --git a/esp32c6-hal/examples/timer_interrupt.rs b/esp32c6-hal/examples/timer_interrupt.rs index dc1432649ee..048c44b89c2 100644 --- a/esp32c6-hal/examples/timer_interrupt.rs +++ b/esp32c6-hal/examples/timer_interrupt.rs @@ -13,11 +13,11 @@ use esp32c6_hal::{ interrupt, peripherals::{self, Peripherals, TIMG0, TIMG1}, prelude::*, + riscv, timer::{Timer, Timer0, TimerGroup}, Rtc, }; use esp_backtrace as _; -use esp_riscv_rt::{entry, riscv}; static TIMER0: Mutex>>>> = Mutex::new(RefCell::new(None)); static TIMER1: Mutex>>>> = Mutex::new(RefCell::new(None)); diff --git a/esp32c6-hal/examples/usb_serial_jtag.rs b/esp32c6-hal/examples/usb_serial_jtag.rs index f4371ae8b92..c13607194bd 100644 --- a/esp32c6-hal/examples/usb_serial_jtag.rs +++ b/esp32c6-hal/examples/usb_serial_jtag.rs @@ -13,13 +13,13 @@ use esp32c6_hal::{ interrupt, peripherals::{self, Peripherals, USB_DEVICE}, prelude::*, + riscv, timer::TimerGroup, Cpu, Rtc, UsbSerialJtag, }; use esp_backtrace as _; -use esp_riscv_rt::{entry, riscv}; use nb::block; static USB_SERIAL: Mutex>>> = diff --git a/esp32c6-hal/examples/watchdog.rs b/esp32c6-hal/examples/watchdog.rs index 8f4e11da0e1..92221f6751a 100644 --- a/esp32c6-hal/examples/watchdog.rs +++ b/esp32c6-hal/examples/watchdog.rs @@ -14,7 +14,6 @@ use esp32c6_hal::{ }; use esp_backtrace as _; use esp_println::println; -use esp_riscv_rt::entry; use nb::block; #[entry] diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index af3749285e0..e5a9981a4ee 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -10,6 +10,7 @@ pub use esp_hal_common::{ dma, dma::gdma, efuse, + entry, gpio, i2c, i2s, @@ -21,10 +22,13 @@ pub use esp_hal_common::{ peripherals, prelude, pulse_control, + riscv, sha, spi, systimer, timer, + trapframe, + twai, uart, utils, Cpu, @@ -67,6 +71,13 @@ extern "C" { static mut _irtc_fast_data: u32; } +#[cfg(feature = "direct-boot")] +#[doc(hidden)] +#[esp_hal_common::esp_riscv_rt::pre_init] +unsafe fn init() { + r0::init_data(&mut _srwtext, &mut _erwtext, &_irwtext); +} + #[allow(unreachable_code)] #[export_name = "_mp_hook"] #[doc(hidden)] From 28ece394aed8037de5ab607285c0b19a0cf513ae Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Fri, 10 Feb 2023 08:14:58 -0800 Subject: [PATCH 48/64] Working `embassy_spi` example --- esp-hal-common/src/interrupt/riscv.rs | 23 +++++ esp32c6-hal/Cargo.toml | 6 +- esp32c6-hal/examples/embassy_spi.rs | 135 ++++++++++++++++++++++++++ 3 files changed, 161 insertions(+), 3 deletions(-) create mode 100644 esp32c6-hal/examples/embassy_spi.rs diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index be1f24b4eb2..4b2a595056f 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -259,6 +259,7 @@ pub fn clear(_core: Cpu, which: CpuInterrupt) { } /// Get status of peripheral interrupts +#[cfg(not(esp32c6))] #[inline] pub fn get_status(_core: Cpu) -> u128 { unsafe { @@ -274,6 +275,28 @@ pub fn get_status(_core: Cpu) -> u128 { } } +/// Get status of peripheral interrupts +#[cfg(esp32c6)] +#[inline] +pub fn get_status(_core: Cpu) -> u128 { + unsafe { + ((*crate::peripherals::INTERRUPT_CORE0::PTR) + .intr_status_reg_0 + .read() + .bits() as u128) + | ((*crate::peripherals::INTERRUPT_CORE0::PTR) + .intr_status_reg_1 + .read() + .bits() as u128) + << 32 + | ((*crate::peripherals::INTERRUPT_CORE0::PTR) + .int_status_reg_2 + .read() + .bits() as u128) + << 64 + } +} + #[cfg(feature = "vectored")] pub use vectored::*; diff --git a/esp32c6-hal/Cargo.toml b/esp32c6-hal/Cargo.toml index d0026c84bdc..b62ea211227 100644 --- a/esp32c6-hal/Cargo.toml +++ b/esp32c6-hal/Cargo.toml @@ -81,6 +81,6 @@ required-features = ["async", "embassy"] name = "embassy_wait" required-features = ["async", "embassy"] -# [[example]] -# name = "embassy_spi" -# required-features = ["async", "embassy"] +[[example]] +name = "embassy_spi" +required-features = ["async", "embassy"] diff --git a/esp32c6-hal/examples/embassy_spi.rs b/esp32c6-hal/examples/embassy_spi.rs new file mode 100644 index 00000000000..45918941aa3 --- /dev/null +++ b/esp32c6-hal/examples/embassy_spi.rs @@ -0,0 +1,135 @@ +//! embassy hello world +//! +//! This is an example of running the embassy executor with multiple tasks +//! concurrently. + +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use embassy_executor::Executor; +use embassy_time::{Duration, Timer}; +use esp32c6_hal::{ + clock::ClockControl, + dma::{DmaPriority, *}, + embassy, + gdma::*, + peripherals::Peripherals, + prelude::*, + spi::{dma::SpiDma, Spi, SpiMode}, + timer::TimerGroup, + Rtc, + IO, +}; +use esp_backtrace as _; +use static_cell::StaticCell; + +macro_rules! singleton { + ($val:expr) => {{ + type T = impl Sized; + static STATIC_CELL: StaticCell = StaticCell::new(); + let (x,) = STATIC_CELL.init(($val,)); + x + }}; +} + +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, +>; + +#[embassy_executor::task] +async fn spi_task(spi: &'static mut SpiType<'static>) { + let send_buffer = [0, 1, 2, 3, 4, 5, 6, 7]; + loop { + let mut buffer = [0; 8]; + esp_println::println!("Sending bytes"); + embedded_hal_async::spi::SpiBus::transfer(spi, &mut buffer, &send_buffer) + .await + .unwrap(); + esp_println::println!("Bytes recieved: {:?}", buffer); + Timer::after(Duration::from_millis(5_000)).await; + } +} + +static EXECUTOR: StaticCell = StaticCell::new(); + +#[entry] +fn main() -> ! { + esp_println::println!("Init!"); + let peripherals = Peripherals::take(); + let mut system = peripherals.PCR.split(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + // Disable the watchdog timers. For the ESP32-C6, this includes the Super WDT, + // and the TIMG WDTs. + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let mut wdt1 = timer_group1.wdt; + + // Disable watchdog timers + rtc.swd.disable(); + rtc.rwdt.disable(); + wdt0.disable(); + wdt1.disable(); + + #[cfg(feature = "embassy-time-systick")] + embassy::init( + &clocks, + esp32c6_hal::systimer::SystemTimer::new(peripherals.SYSTIMER), + ); + + #[cfg(feature = "embassy-time-timg0")] + embassy::init(&clocks, timer_group0.timer0); + + esp32c6_hal::interrupt::enable( + esp32c6_hal::peripherals::Interrupt::DMA_IN_CH0, + esp32c6_hal::interrupt::Priority::Priority1, + ) + .unwrap(); + esp32c6_hal::interrupt::enable( + esp32c6_hal::peripherals::Interrupt::DMA_OUT_CH0, + esp32c6_hal::interrupt::Priority::Priority1, + ) + .unwrap(); + + let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); + let sclk = io.pins.gpio6; + let miso = io.pins.gpio2; + let mosi = io.pins.gpio7; + let cs = io.pins.gpio10; + + let dma = Gdma::new(peripherals.DMA, &mut system.peripheral_clock_control); + let dma_channel = dma.channel0; + + let descriptors = singleton!([0u32; 8 * 3]); + let rx_descriptors = singleton!([0u32; 8 * 3]); + + let spi = singleton!(Spi::new( + peripherals.SPI2, + sclk, + mosi, + miso, + cs, + 100u32.kHz(), + SpiMode::Mode0, + &mut system.peripheral_clock_control, + &clocks, + ) + .with_dma(dma_channel.configure( + false, + descriptors, + rx_descriptors, + DmaPriority::Priority0, + ))); + + let executor = EXECUTOR.init(Executor::new()); + executor.run(|spawner| { + spawner.spawn(spi_task(spi)).ok(); + }); +} From dd7f469ba76d71aabe952f73435ee51d18d6fad5 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Fri, 10 Feb 2023 08:31:28 -0800 Subject: [PATCH 49/64] Use a git dependency for the PAC until we publish a release --- esp-hal-common/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esp-hal-common/Cargo.toml b/esp-hal-common/Cargo.toml index 59330a12ed7..788bb43620e 100644 --- a/esp-hal-common/Cargo.toml +++ b/esp-hal-common/Cargo.toml @@ -56,7 +56,7 @@ ufmt-write = { version = "0.1.0", optional = true } esp32 = { version = "0.21.0", features = ["critical-section"], optional = true } esp32c2 = { version = "0.8.0", features = ["critical-section"], optional = true } esp32c3 = { version = "0.11.0", features = ["critical-section"], optional = true } -esp32c6 = { path = "C:/Users/JurajSadel/esp-pacs/esp32c6", features = ["critical-section"], optional = true } +esp32c6 = { git = "https://github.com/esp-rs/esp-pacs", rev = "b5a7f1a", package = "esp32c6", features = ["critical-section"], optional = true } esp32s2 = { version = "0.12.0", features = ["critical-section"], optional = true } esp32s3 = { version = "0.15.0", features = ["critical-section"], optional = true } From 7dd27e5d038d13451f34a88f89045f3326179af3 Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Tue, 14 Feb 2023 13:00:12 +0100 Subject: [PATCH 50/64] Fix I2S for ESP32-C6 --- esp-hal-common/src/i2s.rs | 100 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/esp-hal-common/src/i2s.rs b/esp-hal-common/src/i2s.rs index a68b2eda1a3..075f9cde623 100644 --- a/esp-hal-common/src/i2s.rs +++ b/esp-hal-common/src/i2s.rs @@ -1293,6 +1293,7 @@ mod private { #[cfg(any(esp32c3, esp32c6, esp32s3))] pub trait RegisterAccessPrivate: Signals + RegBlock { + #[cfg(any(esp32c3, esp32s3))] fn set_clock(&self, clock_settings: I2sClockDividers) { let i2s = self.register_block(); @@ -1392,6 +1393,105 @@ mod private { }); } + #[cfg(any(esp32c6))] + fn set_clock(&self, clock_settings: I2sClockDividers) { + let i2s = self.register_block(); + let pcr = unsafe { &*esp32c6::PCR::PTR }; // I2S clocks are configured via PCR + + let clkm_div_x: u32; + let clkm_div_y: u32; + let clkm_div_z: u32; + let clkm_div_yn1: u32; + + if clock_settings.denominator == 0 || clock_settings.numerator == 0 { + clkm_div_x = 0; + clkm_div_y = 0; + clkm_div_z = 0; + clkm_div_yn1 = 1; + } else { + if clock_settings.numerator > clock_settings.denominator / 2 { + clkm_div_x = clock_settings + .denominator + .overflowing_div( + clock_settings + .denominator + .overflowing_sub(clock_settings.numerator) + .0, + ) + .0 + .overflowing_sub(1) + .0; + clkm_div_y = clock_settings.denominator + % (clock_settings + .denominator + .overflowing_sub(clock_settings.numerator) + .0); + clkm_div_z = clock_settings + .denominator + .overflowing_sub(clock_settings.numerator) + .0; + clkm_div_yn1 = 1; + } else { + clkm_div_x = clock_settings.denominator / clock_settings.numerator - 1; + clkm_div_y = clock_settings.denominator % clock_settings.numerator; + clkm_div_z = clock_settings.numerator; + clkm_div_yn1 = 0; + } + } + + pcr.i2s_tx_clkm_div_conf.modify(|_, w| { + w.i2s_tx_clkm_div_x() + .variant(clkm_div_x as u16) + .i2s_tx_clkm_div_y() + .variant(clkm_div_y as u16) + .i2s_tx_clkm_div_yn1() + .variant(if clkm_div_yn1 != 0 { true } else { false }) + .i2s_tx_clkm_div_z() + .variant(clkm_div_z as u16) + }); + + pcr.i2s_tx_clkm_conf.modify(|_, w| { + w.i2s_tx_clkm_en() + .set_bit() + .i2s_tx_clkm_sel() + .variant(2) // for now fixed at 160MHz + .i2s_tx_clkm_div_num() + .variant(clock_settings.mclk_divider as u8) + }); + + i2s.tx_conf1.modify(|_, w| { + w.tx_bck_div_num() + .variant((clock_settings.bclk_divider - 1) as u8) + }); + + pcr.i2s_rx_clkm_div_conf.modify(|_, w| { + w.i2s_rx_clkm_div_x() + .variant(clkm_div_x as u16) + .i2s_rx_clkm_div_y() + .variant(clkm_div_y as u16) + .i2s_rx_clkm_div_yn1() + .variant(if clkm_div_yn1 != 0 { true } else { false }) + .i2s_rx_clkm_div_z() + .variant(clkm_div_z as u16) + }); + + pcr.i2s_rx_clkm_conf.modify(|_, w| { + w.i2s_rx_clkm_en() + .set_bit() + .i2s_rx_clkm_sel() + .variant(2) // for now fixed at 160MHz + .i2s_rx_clkm_div_num() + .variant(clock_settings.mclk_divider as u8) + .i2s_mclk_sel() + .variant(true) + }); + + i2s.rx_conf1.modify(|_, w| { + w.rx_bck_div_num() + .variant((clock_settings.bclk_divider - 1) as u8) + }); + } + fn configure(&self, _standard: &Standard, data_format: &DataFormat) { let i2s = self.register_block(); i2s.tx_conf1.modify(|_, w| { From 39444ba1694011c0fd1e31afc8c78103093c1f9a Mon Sep 17 00:00:00 2001 From: Scott Mabin Date: Wed, 22 Feb 2023 14:26:20 +0000 Subject: [PATCH 51/64] Fix esp32c6 direct boot (#4) * Add direct boot support for C6 * Fix direct boot for c6 - Actually copy into rtc ram - remove dummy section that is no longer needed (was just a waste of flash space) - Move RTC stuff before the no load sections --- esp32c6-hal/ld/db-esp32c6-memory.x | 2 +- esp32c6-hal/ld/db-riscv-link.x | 70 +++++++++++++----------------- esp32c6-hal/src/lib.rs | 8 ++++ 3 files changed, 40 insertions(+), 40 deletions(-) diff --git a/esp32c6-hal/ld/db-esp32c6-memory.x b/esp32c6-hal/ld/db-esp32c6-memory.x index 33949c5bfdc..b4cbf63cc93 100644 --- a/esp32c6-hal/ld/db-esp32c6-memory.x +++ b/esp32c6-hal/ld/db-esp32c6-memory.x @@ -35,4 +35,4 @@ REGION_ALIAS("REGION_HEAP", RAM); REGION_ALIAS("REGION_STACK", RAM); REGION_ALIAS("REGION_RWTEXT", RAM); -REGION_ALIAS("REGION_RTC_FAST", RTC_FAST); \ No newline at end of file +REGION_ALIAS("REGION_RTC_FAST", RTC_FAST); diff --git a/esp32c6-hal/ld/db-riscv-link.x b/esp32c6-hal/ld/db-riscv-link.x index 183304cfd0f..cac5389ef96 100644 --- a/esp32c6-hal/ld/db-riscv-link.x +++ b/esp32c6-hal/ld/db-riscv-link.x @@ -79,7 +79,7 @@ SECTIONS _erodata = .; } > REGION_RODATA - _rodata_size = _erodata - _srodata + 8; + _rodata_size = _erodata - _srodata; .data ORIGIN(RAM) : AT(_text_size + _rodata_size) { _sdata = .; @@ -91,22 +91,44 @@ SECTIONS _edata = .; } > REGION_DATA - _data_size = _edata - _sdata + 8; + _data_size = _edata - _sdata; .rwtext ORIGIN(REGION_RWTEXT) + _data_size : AT(_text_size + _rodata_size + _data_size){ _srwtext = .; *(.rwtext); . = ALIGN(4); _erwtext = .; } > REGION_RWTEXT - _rwtext_size = _erwtext - _srwtext + 8; + _rwtext_size = _erwtext - _srwtext; - .rwtext.dummy (NOLOAD): + .rtc_fast.text : AT(_text_size + _rodata_size + _data_size + _rwtext_size) { + _srtc_fast_text = .; + *(.rtc_fast.literal .rtc_fast.text .rtc_fast.literal.* .rtc_fast.text.*) + . = ALIGN(4); + _ertc_fast_text = .; + } > REGION_RTC_FAST + _fast_text_size = _ertc_fast_text - _srtc_fast_text; + + .rtc_fast.data : AT(_text_size + _rodata_size + _data_size + _rwtext_size + _fast_text_size) { - /* This section is required to skip .rwtext area because REGION_RWTEXT - * and REGION_BSS reflect the same address space on different buses. - */ - . = ORIGIN(REGION_BSS) + _rwtext_size; - } > REGION_BSS + _rtc_fast_data_start = ABSOLUTE(.); + *(.rtc_fast.data .rtc_fast.data.*) + . = ALIGN(4); + _rtc_fast_data_end = ABSOLUTE(.); + } > REGION_RTC_FAST + _rtc_fast_data_size = _rtc_fast_data_end - _rtc_fast_data_start; + + .rtc_fast.bss (NOLOAD) : ALIGN(4) + { + _rtc_fast_bss_start = ABSOLUTE(.); + *(.rtc_fast.bss .rtc_fast.bss.*) + . = ALIGN(4); + _rtc_fast_bss_end = ABSOLUTE(.); + } > REGION_RTC_FAST + + .rtc_fast.noinit (NOLOAD) : ALIGN(4) + { + *(.rtc_fast.noinit .rtc_fast.noinit.*) + } > REGION_RTC_FAST .bss (NOLOAD) : { @@ -143,36 +165,6 @@ SECTIONS _sstack = .; } > REGION_STACK - .rtc_fast.text : AT(_text_size + _rodata_size + _data_size + _rwtext_size) { - _srtc_fast_text = .; - *(.rtc_fast.literal .rtc_fast.text .rtc_fast.literal.* .rtc_fast.text.*) - . = ALIGN(4); - _ertc_fast_text = .; - } > REGION_RTC_FAST - _fast_text_size = _ertc_fast_text - _srtc_fast_text + 8; - - .rtc_fast.data : AT(_text_size + _rodata_size + _data_size + _rwtext_size + _fast_text_size) - { - _rtc_fast_data_start = ABSOLUTE(.); - *(.rtc_fast.data .rtc_fast.data.*) - . = ALIGN(4); - _rtc_fast_data_end = ABSOLUTE(.); - } > REGION_RTC_FAST - _rtc_fast_data_size = _rtc_fast_data_end - _rtc_fast_data_start + 8; - - .rtc_fast.bss (NOLOAD) : ALIGN(4) - { - _rtc_fast_bss_start = ABSOLUTE(.); - *(.rtc_fast.bss .rtc_fast.bss.*) - . = ALIGN(4); - _rtc_fast_bss_end = ABSOLUTE(.); - } > REGION_RTC_FAST - - .rtc_fast.noinit (NOLOAD) : ALIGN(4) - { - *(.rtc_fast.noinit .rtc_fast.noinit.*) - } > REGION_RTC_FAST - /* fake output .got section */ /* Dynamic relocations are unsupported. This section is only used to detect relocatable code in the input files and raise an error if relocatable code diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index e5a9981a4ee..8976d079b73 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -76,6 +76,14 @@ extern "C" { #[esp_hal_common::esp_riscv_rt::pre_init] unsafe fn init() { r0::init_data(&mut _srwtext, &mut _erwtext, &_irwtext); + + r0::init_data( + &mut _rtc_fast_data_start, + &mut _rtc_fast_data_end, + &_irtc_fast_data, + ); + + r0::init_data(&mut _srtc_fast_text, &mut _ertc_fast_text, &_irtc_fast_text); } #[allow(unreachable_code)] From d16cab70a9b941eb9de8ccbc882b04ca0fa8cded Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Thu, 23 Feb 2023 16:58:42 +0100 Subject: [PATCH 52/64] Update RWDT and refactor RTC (#3) * C6: Update RWDT and add example, refactor RTC and add not-really-good example * Update based on review comments, resolve bunch of warnings and run cargo fmt * Update C6 esp-pacs rev commit * Fix clocks_ll/esp32c6.rs * Fix riscv interrupts * Remove clock_monitor example for now * RAM example works in direct-boot mode * Add a TODO for &mut TIMG0 and cargo fmt * Fix linker script after a bad rebase * Update CI and Cargo.toml embassy required features * use riscv32imac-unknown-none-elf target for C6 in CI * change default target to riscv32imac-unknown-none-elf * add riscv32imac-unknown-none-elf target to MSRV job * another cleanup --------- Co-authored-by: bjoernQ Co-authored-by: Jesse Braham --- .github/workflows/ci.yml | 15 +- esp-hal-common/Cargo.toml | 2 +- esp-hal-common/src/clock/clocks_ll/esp32c6.rs | 8 +- esp-hal-common/src/interrupt/riscv.rs | 6 +- esp-hal-common/src/ledc/channel.rs | 4 +- esp-hal-common/src/pulse_control.rs | 4 +- esp-hal-common/src/rtc_cntl/mod.rs | 65 +- esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs | 744 +++++++++++++----- esp32c6-hal/.cargo/config.toml | 4 +- esp32c6-hal/Cargo.toml | 6 +- esp32c6-hal/examples/ledc.rs | 1 - esp32c6-hal/examples/rtc_watchdog.rs | 70 ++ esp32c6-hal/ld/db-riscv-link.x | 10 +- esp32c6-hal/src/lib.rs | 1 + 14 files changed, 682 insertions(+), 258 deletions(-) create mode 100644 esp32c6-hal/examples/rtc_watchdog.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d79221a4bdd..9827fbc931a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -108,11 +108,11 @@ jobs: # Subsequent steps can just check the examples instead, as we're already # confident that they link. - name: check esp32c3-hal (common features) - run: cargo check --manifest-path=esp32c3-hal/Cargo.toml --target=riscv32imc-unknown-none-elf --examples --features=eh1,smartled,ufmt + run: cd esp32c3-hal/ && cargo check --examples --features=eh1,smartled,ufmt - name: check esp32c3-hal (async, systick) - run: cargo check --manifest-path=esp32c3-hal/Cargo.toml --target=riscv32imc-unknown-none-elf --example=embassy_hello_world --features=embassy,embassy-time-systick + run: cd esp32c3-hal/ && cargo check --example=embassy_hello_world --features=embassy,embassy-time-systick - name: check esp32c3-hal (async, timg0) - run: cargo check --manifest-path=esp32c3-hal/Cargo.toml --target=riscv32imc-unknown-none-elf --example=embassy_hello_world --features=embassy,embassy-time-timg0 + run: cd esp32c3-hal/ && cargo check --example=embassy_hello_world --features=embassy,embassy-time-timg0 - name: check esp32c3-hal (async, gpio) run: cd esp32c3-hal/ && cargo check --example=embassy_wait --features=embassy,embassy-time-systick,async - name: check esp32c3-hal (async, spi) @@ -125,7 +125,7 @@ jobs: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@v1 with: - target: riscv32imc-unknown-none-elf + target: riscv32imac-unknown-none-elf toolchain: nightly components: rust-src - uses: Swatinem/rust-cache@v2 @@ -141,7 +141,7 @@ jobs: # Subsequent steps can just check the examples instead, as we're already # confident that they link. - name: check esp32c6-hal (common features) - run: cd esp32c6-hal/ && cargo check --examples --features=eh1,ufmt + run: cd esp32c6-hal/ && cargo check --examples --features=eh1,smartled,ufmt - name: check esp32c6-hal (async, systick) run: cd esp32c6-hal/ && cargo check --example=embassy_hello_world --features=embassy,embassy-time-systick - name: check esp32c6-hal (async, timg0) @@ -213,7 +213,6 @@ jobs: run: cd esp32s3-hal/ && cargo check --example=embassy_wait --features=embassy,embassy-time-timg0,async - name: check esp32s3-hal (async, spi) run: cd esp32s3-hal/ && cargo check --example=embassy_spi --features=embassy,embassy-time-timg0,async - # -------------------------------------------------------------------------- # MSRV @@ -224,7 +223,7 @@ jobs: - uses: actions/checkout@v3 - uses: dtolnay/rust-toolchain@v1 with: - target: riscv32imc-unknown-none-elf + target: riscv32imc-unknown-none-elf, riscv32imac-unknown-none-elf toolchain: "1.65.0" - uses: Swatinem/rust-cache@v2 @@ -329,4 +328,4 @@ jobs: - name: rustfmt (esp32s2-hal) run: cargo fmt --all --manifest-path=esp32s2-hal/Cargo.toml -- --check - name: rustfmt (esp32s3-hal) - run: cargo fmt --all --manifest-path=esp32s3-hal/Cargo.toml -- --check + run: cargo fmt --all --manifest-path=esp32s3-hal/Cargo.toml -- --check \ No newline at end of file diff --git a/esp-hal-common/Cargo.toml b/esp-hal-common/Cargo.toml index 788bb43620e..2f79b6c79dc 100644 --- a/esp-hal-common/Cargo.toml +++ b/esp-hal-common/Cargo.toml @@ -56,7 +56,7 @@ ufmt-write = { version = "0.1.0", optional = true } esp32 = { version = "0.21.0", features = ["critical-section"], optional = true } esp32c2 = { version = "0.8.0", features = ["critical-section"], optional = true } esp32c3 = { version = "0.11.0", features = ["critical-section"], optional = true } -esp32c6 = { git = "https://github.com/esp-rs/esp-pacs", rev = "b5a7f1a", package = "esp32c6", features = ["critical-section"], optional = true } +esp32c6 = { git = "https://github.com/esp-rs/esp-pacs", rev = "1124275", package = "esp32c6", features = ["critical-section"], optional = true } esp32s2 = { version = "0.12.0", features = ["critical-section"], optional = true } esp32s3 = { version = "0.15.0", features = ["critical-section"], optional = true } diff --git a/esp-hal-common/src/clock/clocks_ll/esp32c6.rs b/esp-hal-common/src/clock/clocks_ll/esp32c6.rs index 4c2afb094c4..80f9886068e 100644 --- a/esp-hal-common/src/clock/clocks_ll/esp32c6.rs +++ b/esp-hal-common/src/clock/clocks_ll/esp32c6.rs @@ -41,7 +41,7 @@ const MODEM_LPCON_CLK_I2C_MST_FO: u32 = 1 << 2; const MODEM_LPCON_I2C_MST_CLK_CONF_REG: u32 = DR_REG_MODEM_LPCON_BASE + 0x10; const MODEM_LPCON_CLK_I2C_MST_SEL_160M: u32 = 1 << 0; -pub(crate) fn esp32c6_rtc_bbpll_configure(xtal_freq: XtalClock, pll_freq: PllClock) { +pub(crate) fn esp32c6_rtc_bbpll_configure(_xtal_freq: XtalClock, _pll_freq: PllClock) { unsafe { // enable i2c mst clk by force on temporarily (MODEM_LPCON_CLK_CONF_FORCE_ON_REG as *mut u32).write_volatile( @@ -278,6 +278,8 @@ const LP_I2C_ANA_MST_I2C0_DATA_REG: u32 = DR_REG_LP_I2C_ANA_MST_BASE + 0x8; const LP_I2C_ANA_MST_I2C0_RDATA_V: u32 = 0x000000FF; const LP_I2C_ANA_MST_I2C0_RDATA_S: u32 = 0; +const REGI2C_BBPLL: u8 = 0x66; + fn regi2c_enable_block(block: u8) { reg_set_bit(MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN); reg_set_bit(LP_I2C_ANA_MST_DATE_REG, LP_I2C_ANA_MST_I2C_MAT_CLK_EN); @@ -324,7 +326,7 @@ fn regi2c_disable_block(block: u8) { } } -pub(crate) fn regi2c_write(block: u8, host_id: u8, reg_add: u8, data: u8) { +pub(crate) fn regi2c_write(block: u8, _host_id: u8, reg_add: u8, data: u8) { regi2c_enable_block(block); let temp: u32 = ((block as u32 & REGI2C_RTC_SLAVE_ID_V as u32) << REGI2C_RTC_SLAVE_ID_S as u32) @@ -337,7 +339,7 @@ pub(crate) fn regi2c_write(block: u8, host_id: u8, reg_add: u8, data: u8) { regi2c_disable_block(block); } -pub(crate) fn regi2c_write_mask(block: u8, host_id: u8, reg_add: u8, msb: u8, lsb: u8, data: u8) { +pub(crate) fn regi2c_write_mask(block: u8, _host_id: u8, reg_add: u8, msb: u8, lsb: u8, data: u8) { assert!(msb - lsb < 8); regi2c_enable_block(block); diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index 4b2a595056f..b36eabffe75 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -330,15 +330,15 @@ mod vectored { for (prio, num) in PRIORITY_TO_INTERRUPT.iter().enumerate() { set_kind( crate::get_core(), - core::mem::transmute(*num), + core::mem::transmute(*num as u32), InterruptKind::Level, ); set_priority( crate::get_core(), - core::mem::transmute(*num), + core::mem::transmute(*num as u32), core::mem::transmute((prio as u8) + 1), ); - enable_cpu_interrupt(core::mem::transmute(*num)); + enable_cpu_interrupt(core::mem::transmute(*num as u32)); } } diff --git a/esp-hal-common/src/ledc/channel.rs b/esp-hal-common/src/ledc/channel.rs index 8456bef5699..d98c0cbb14e 100644 --- a/esp-hal-common/src/ledc/channel.rs +++ b/esp-hal-common/src/ledc/channel.rs @@ -197,10 +197,10 @@ macro_rules! start_duty_without_fading { macro_rules! start_duty_without_fading { ($self: ident, $num: literal) => { paste! { - $self.ledc.[].write(|w| unsafe { + $self.ledc.[].write(|w| w.[]() .set_bit() - }); + ); $self.ledc.[].write(|w| unsafe { w.[]() .set_bit() diff --git a/esp-hal-common/src/pulse_control.rs b/esp-hal-common/src/pulse_control.rs index 7994831936a..f558dbb788f 100644 --- a/esp-hal-common/src/pulse_control.rs +++ b/esp-hal-common/src/pulse_control.rs @@ -937,7 +937,7 @@ macro_rules! rmt { pcr.rmt_sclk_conf.write(|w| w.sclk_en().set_bit()); - self.reg.sys_conf.modify(|_, w| unsafe { + self.reg.sys_conf.modify(|_, w| // Enable clock w.clk_en() .set_bit() @@ -952,7 +952,7 @@ macro_rules! rmt { .clear_bit() // Disable FIFO mode .apb_fifo_mask() - .set_bit() }); + .set_bit()); // Select clock source #[cfg(not(esp32c6))] self.reg.sys_conf.modify(|_, w| unsafe { diff --git a/esp-hal-common/src/rtc_cntl/mod.rs b/esp-hal-common/src/rtc_cntl/mod.rs index 3b4f2200ab5..8124a2b8002 100644 --- a/esp-hal-common/src/rtc_cntl/mod.rs +++ b/esp-hal-common/src/rtc_cntl/mod.rs @@ -1,15 +1,18 @@ use embedded_hal::watchdog::{Watchdog, WatchdogDisable, WatchdogEnable}; -use fugit::{HertzU32, MicrosDurationU64}; +#[cfg(not(esp32c6))] +use fugit::HertzU32; +use fugit::MicrosDurationU64; use self::rtc::SocResetReason; -#[cfg(not(any(esp32)))] +#[cfg(not(esp32c6))] +use crate::clock::{Clock, XtalClock}; +#[cfg(not(any(esp32, esp32c6)))] use crate::efuse::Efuse; #[cfg(esp32c6)] -use crate::peripherals::{LP_AON, LP_CLKRST, LP_WDT, PMU}; +use crate::peripherals::LP_WDT; #[cfg(not(esp32c6))] use crate::peripherals::{RTC_CNTL, TIMG0}; use crate::{ - clock::{Clock, XtalClock}, peripheral::{Peripheral, PeripheralRef}, Cpu, }; @@ -27,11 +30,16 @@ type RtcCntl = crate::peripherals::RTC_CNTL; #[cfg_attr(esp32s3, path = "rtc/esp32s3.rs")] mod rtc; +#[cfg(esp32c6)] +pub use rtc::RtcClock; + extern "C" { + #[allow(dead_code)] fn ets_delay_us(us: u32); fn rtc_get_reset_reason(cpu_num: u32) -> u32; } +#[cfg(not(esp32c6))] #[allow(unused)] #[derive(Debug, Clone, Copy)] /// RTC SLOW_CLK frequency values @@ -42,6 +50,7 @@ pub(crate) enum RtcFastClock { RtcFastClock8m = 1, } +#[cfg(not(esp32c6))] impl Clock for RtcFastClock { fn frequency(&self) -> HertzU32 { match self { @@ -55,6 +64,7 @@ impl Clock for RtcFastClock { } #[cfg(not(esp32c6))] +#[allow(unused)] #[derive(Debug, Clone, Copy)] /// RTC SLOW_CLK frequency values pub(crate) enum RtcSlowClock { @@ -66,21 +76,7 @@ pub(crate) enum RtcSlowClock { RtcSlowClock8mD256 = 2, } -#[cfg(esp32c6)] -#[derive(Debug, Clone, Copy, PartialEq)] -/// RTC SLOW_CLK frequency values -pub(crate) enum RtcSlowClock { - /// Internal slow RC oscillator - RtcSlowClockRtc = 0, - /// External 32 KHz XTAL - RtcSlowClock32kXtal = 1, - /// TODO - RtcSlowClock32kRc = 2, - /// Internal 150 KHz RC oscillator - RtcCalInternalOsc = 3, - RtcCalRcFast, -} - +#[cfg(not(esp32c6))] impl Clock for RtcSlowClock { fn frequency(&self) -> HertzU32 { match self { @@ -120,35 +116,10 @@ pub(crate) enum RtcCalSel { RtcCalInternalOsc = 3, } -#[cfg(esp32c6)] -#[derive(Debug, Clone, Copy, PartialEq)] -/// Clock source to be calibrated using rtc_clk_cal function -pub(crate) enum RtcCalSel { - /// Currently selected RTC SLOW_CLK - RtcCalRtcMux = -1, - /// Currently selected RTC SLOW_CLK - RtcCalRcSlow = 0, - /// External 32 KHz XTAL - RtcCal32kXtal = 1, - /// TODO - RtcCal32kRc = 2, - #[cfg(not(esp32))] - /// Internal 150 KHz RC oscillator TODO - RtcCalInternalOsc = 3, - RtcCalRcFast, -} - -#[cfg(esp32c6)] -pub(crate) enum RtcCaliClkSel { - CaliClkRcSlow = 0, - CaliClkRcFast = 1, - CaliClk32k = 2, -} - pub struct Rtc<'d> { _inner: PeripheralRef<'d, RtcCntl>, pub rwdt: Rwdt, - #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32s3, esp32c6))] pub swd: Swd, } @@ -160,7 +131,7 @@ impl<'d> Rtc<'d> { Self { _inner: rtc_cntl.into_ref(), rwdt: Rwdt::default(), - #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32s3, esp32c6))] swd: Swd::new(), } } @@ -170,9 +141,11 @@ impl<'d> Rtc<'d> { } } +#[cfg(not(esp32c6))] /// RTC Watchdog Timer pub struct RtcClock; +#[cfg(not(esp32c6))] /// RTC Watchdog Timer driver impl RtcClock { const CAL_FRACT: u32 = 19; diff --git a/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs b/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs index 985b3acaf6c..462454fab78 100644 --- a/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs +++ b/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs @@ -1,21 +1,14 @@ -use paste::paste; +use fugit::HertzU32; use strum::FromRepr; use crate::{ - clock::{ - clocks_ll::{regi2c_write, regi2c_write_mask}, - XtalClock, - }, - peripherals::{EXTMEM, LP_AON, PCR, PMU, SPI0, SPI1}, - rtc_cntl::{RtcCalSel, RtcClock, RtcFastClock, RtcSlowClock}, + clock::{clocks_ll::regi2c_write_mask, Clock, XtalClock}, + peripherals::{LP_AON, LP_CLKRST, PCR, PMU, TIMG0}, }; const I2C_DIG_REG: u8 = 0x6d; const I2C_DIG_REG_HOSTID: u8 = 0; -const I2C_ULP: u8 = 0x61; -const I2C_ULP_HOSTID: u8 = 0; - const I2C_DIG_REG_XPD_RTC_REG: u8 = 13; const I2C_DIG_REG_XPD_RTC_REG_MSB: u8 = 2; const I2C_DIG_REG_XPD_RTC_REG_LSB: u8 = 2; @@ -24,10 +17,6 @@ const I2C_DIG_REG_XPD_DIG_REG: u8 = 13; const I2C_DIG_REG_XPD_DIG_REG_MSB: u8 = 3; const I2C_DIG_REG_XPD_DIG_REG_LSB: u8 = 3; -const I2C_ULP_IR_FORCE_XPD_CK: u8 = 0; -const I2C_ULP_IR_FORCE_XPD_CK_MSB: u8 = 2; -const I2C_ULP_IR_FORCE_XPD_CK_LSB: u8 = 2; - const I2C_DIG_REG_ENIF_RTC_DREG: u8 = 5; const I2C_DIG_REG_ENIF_RTC_DREG_MSB: u8 = 7; const I2C_DIG_REG_ENIF_RTC_DREG_LSB: u8 = 7; @@ -36,27 +25,17 @@ const I2C_DIG_REG_ENIF_DIG_DREG: u8 = 7; const I2C_DIG_REG_ENIF_DIG_DREG_MSB: u8 = 7; const I2C_DIG_REG_ENIF_DIG_DREG_LSB: u8 = 7; +const I2C_DIG_REG_SCK_DCAP: u8 = 14; +const I2C_DIG_REG_SCK_DCAP_MSB: u8 = 7; +const I2C_DIG_REG_SCK_DCAP_LSB: u8 = 0; + pub(crate) fn init() { let pmu = unsafe { &*PMU::ptr() }; - // SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB); - // SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C); - // - // REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1); - // REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1); - // REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0); - // REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0); - // REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, - // PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, 25); - // REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, - // PMU_HP_SLEEP_LP_REGULATOR_DBIAS, 26); - pmu.rf_pwc .modify(|_, w| w.perif_i2c_rstb().set_bit().xpd_perif_i2c().set_bit()); unsafe { - // crate::clock::clocks_ll::regi2c_write_mask(I2C_DIG_REG, - // I2C_DIG_REG_ENIF_RTC_DREG, 1); use i2c macro from C6 clock regi2c_write_mask( I2C_DIG_REG, I2C_DIG_REG_HOSTID, @@ -104,165 +83,67 @@ pub(crate) fn configure_clock() { XtalClock::RtcXtalFreq40M )); - // RtcClock::set_fast_freq(RtcFastClock::RtcFastClock8m); + RtcClock::set_fast_freq(RtcFastClock::RtcFastClockRcFast); - // let cal_val = loop { - // RtcClock::set_slow_freq(RtcSlowClock::RtcSlowClockRtc); + let cal_val = loop { + RtcClock::set_slow_freq(RtcSlowClock::RtcSlowClockRcSlow); - // let res = RtcClock::calibrate(RtcCalSel::RtcCalRtcMux, 1024); - // if res != 0 { - // break res; - // } - // }; + let res = RtcClock::calibrate(RtcCalSel::RtcCalRtcMux, 1024); + if res != 0 { + break res; + } + }; - // unsafe { - // let lp_aon = &*LP_AON::ptr(); - // lp_aon.store1.write(|w| w.bits(cal_val)); - // } + unsafe { + let lp_aon = &*LP_AON::ptr(); + lp_aon.store1.modify(|_, w| w.bits(cal_val)); + } + + modem_clk_domain_active_state_icg_map_preinit(); } -fn calibrate_ocode() {} - -fn set_rtc_dig_dbias() {} - -/// Perform clock control related initialization -// fn clock_control_init() { -// let extmem = unsafe { &*EXTMEM::ptr() }; -// let spi_mem_0 = unsafe { &*SPI0::ptr() }; -// let spi_mem_1 = unsafe { &*SPI1::ptr() }; - -// // Clear CMMU clock force on -// extmem -// .cache_mmu_power_ctrl -// .modify(|_, w| w.cache_mmu_mem_force_on().clear_bit()); - -// // Clear tag clock force on -// extmem -// .icache_tag_power_ctrl -// .modify(|_, w| w.icache_tag_mem_force_on().clear_bit()); - -// // Clear register clock force on -// spi_mem_0.clock_gate.modify(|_, w| w.clk_en().clear_bit()); -// spi_mem_1.clock_gate.modify(|_, w| w.clk_en().clear_bit()); -// } - -/// Perform power control related initialization -// fn power_control_init() { -// let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; -// let pcr = unsafe { &*PCR::ptr() }; -// rtc_cntl -// .clk_conf -// .modify(|_, w| w.ck8m_force_pu().clear_bit()); - -// // Cancel XTAL force PU if no need to force power up -// // Cannot cancel XTAL force PU if PLL is force power on -// rtc_cntl -// .options0 -// .modify(|_, w| w.xtl_force_pu().clear_bit()); - -// // Force PD APLL -// rtc_cntl.ana_conf.modify(|_, w| { -// w.plla_force_pu() -// .clear_bit() -// .plla_force_pd() -// .set_bit() -// // Open SAR_I2C protect function to avoid SAR_I2C -// // Reset when rtc_ldo is low. -// .reset_por_force_pd() -// .clear_bit() -// }); - -// // Cancel BBPLL force PU if setting no force power up -// rtc_cntl.options0.modify(|_, w| { -// w.bbpll_force_pu() -// .clear_bit() -// .bbpll_i2c_force_pu() -// .clear_bit() -// .bb_i2c_force_pu() -// .clear_bit() -// }); -// rtc_cntl.rtc_cntl.modify(|_, w| { -// w.regulator_force_pu() -// .clear_bit() -// .dboost_force_pu() -// .clear_bit() -// .dboost_force_pd() -// .set_bit() -// }); - -// // If this mask is enabled, all soc memories cannot enter power down mode. -// // We should control soc memory power down mode from RTC, -// // so we will not touch this register any more. -// pcr -// .mem_pd_mask -// .modify(|_, w| w.lslp_mem_pd_mask().clear_bit()); - -// rtc_sleep_pu(); - -// rtc_cntl.dig_pwc.modify(|_, w| { -// w.dg_wrap_force_pu() -// .clear_bit() -// .wifi_force_pu() -// .clear_bit() -// .bt_force_pu() -// .clear_bit() -// .cpu_top_force_pu() -// .clear_bit() -// .dg_peri_force_pu() -// .clear_bit() -// }); -// rtc_cntl.dig_iso.modify(|_, w| { -// w.dg_wrap_force_noiso() -// .clear_bit() -// .wifi_force_noiso() -// .clear_bit() -// .bt_force_noiso() -// .clear_bit() -// .cpu_top_force_noiso() -// .clear_bit() -// .dg_peri_force_noiso() -// .clear_bit() -// }); - -// // Cancel digital PADS force no iso -// system -// .cpu_per_conf -// .modify(|_, w| w.cpu_wait_mode_force_on().clear_bit()); - -// // If SYSTEM_CPU_WAIT_MODE_FORCE_ON == 0, -// // the CPU clock will be closed when CPU enter WAITI mode. -// rtc_cntl.dig_iso.modify(|_, w| { -// w.dg_pad_force_unhold() -// .clear_bit() -// .dg_pad_force_noiso() -// .clear_bit() -// }); -// } - -/// Configure whether certain peripherals are powered down in deep sleep -// fn rtc_sleep_pu() { -// let rtc_cntl = unsafe { &*RTC_CNTL::ptr() }; -// let apb_ctrl = unsafe { &*APB_CTRL::ptr() }; - -// rtc_cntl.dig_pwc.modify(|_, w| { -// w.lslp_mem_force_pu() -// .clear_bit() -// .fastmem_force_lpu() -// .clear_bit() -// }); - -// apb_ctrl.front_end_mem_pd.modify(|_, w| { -// w.dc_mem_force_pu() -// .clear_bit() -// .pbus_mem_force_pu() -// .clear_bit() -// .agc_mem_force_pu() -// .clear_bit() -// }); -// apb_ctrl -// .mem_power_up -// .modify(|_, w| unsafe { w.sram_power_up().bits(0u8).rom_power_up().bits(0u8) }); -// } +fn modem_clk_domain_active_state_icg_map_preinit() { + unsafe { + let pmu = &*PMU::PTR; + let lp_clkrst = &*LP_CLKRST::PTR; + + pmu.hp_active_icg_modem + .modify(|_, w| w.hp_active_dig_icg_modem_code().bits(2)); + + const MODEM_SYSCON_CLK_CONF_POWER_ST: u32 = 0x600A9800 + 0xc; + const MODEM_LPCON_CLK_CONF_POWER_ST: u32 = 0x600A9800 + 0x20; + + (MODEM_SYSCON_CLK_CONF_POWER_ST as *mut u32).write_volatile( + (MODEM_SYSCON_CLK_CONF_POWER_ST as *mut u32).read_volatile() & !(3 << 28) | 2 << 28, + ); + + (MODEM_LPCON_CLK_CONF_POWER_ST as *mut u32).write_volatile( + (MODEM_LPCON_CLK_CONF_POWER_ST as *mut u32).read_volatile() & !(3 << 28) | 2 << 28, + ); + + (MODEM_LPCON_CLK_CONF_POWER_ST as *mut u32).write_volatile( + (MODEM_LPCON_CLK_CONF_POWER_ST as *mut u32).read_volatile() & !(3 << 28) | 2 << 28, + ); + + pmu.imm_modem_icg + .write(|w| w.update_dig_icg_modem_en().set_bit()); + pmu.imm_sleep_sysclk + .write(|w| w.update_dig_icg_switch().set_bit()); + + lp_clkrst.fosc_cntl.modify(|_, w| w.fosc_dfreq().bits(100)); + regi2c_write_mask( + I2C_DIG_REG, + I2C_DIG_REG_HOSTID, + I2C_DIG_REG_SCK_DCAP, + I2C_DIG_REG_SCK_DCAP_MSB, + I2C_DIG_REG_SCK_DCAP_LSB, + 128, + ); + lp_clkrst + .rc32k_cntl + .modify(|_, w| w.rc32k_dfreq().bits(100)); + } +} // Terminology: // @@ -315,3 +196,502 @@ pub enum SocResetReason { /// JTAG resets CPU Cpu0JtagCpu = 0x18, } + +extern "C" { + fn ets_delay_us(us: u32); +} + +#[allow(unused)] +#[derive(Debug, Clone, Copy)] +/// RTC SLOW_CLK frequency values +pub(crate) enum RtcFastClock { + /// Select RC_FAST_CLK as RTC_FAST_CLK source + RtcFastClockRcFast = 0, + /// Select XTAL_D2_CLK as RTC_FAST_CLK source + RtcFastClockXtalD2 = 1, +} + +impl Clock for RtcFastClock { + fn frequency(&self) -> HertzU32 { + match self { + RtcFastClock::RtcFastClockXtalD2 => HertzU32::Hz(40_000_000 / 2), /* TODO: Is the value correct? */ + RtcFastClock::RtcFastClockRcFast => HertzU32::Hz(17_500_000), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +/// RTC SLOW_CLK frequency values +pub(crate) enum RtcSlowClock { + /// Select RC_SLOW_CLK as RTC_SLOW_CLK source + RtcSlowClockRcSlow = 0, + /// Select XTAL32K_CLK as RTC_SLOW_CLK source + RtcSlowClock32kXtal = 1, + /// Select RC32K_CLK as RTC_SLOW_CLK source + RtcSlowClock32kRc = 2, + /// Select OSC_SLOW_CLK (external slow clock) as RTC_SLOW_CLK source + RtcSlowOscSlow = 3, +} + +impl Clock for RtcSlowClock { + fn frequency(&self) -> HertzU32 { + match self { + RtcSlowClock::RtcSlowClockRcSlow => HertzU32::Hz(136_000), + RtcSlowClock::RtcSlowClock32kXtal => HertzU32::Hz(32_768), + RtcSlowClock::RtcSlowClock32kRc => HertzU32::Hz(32_768), + RtcSlowClock::RtcSlowOscSlow => HertzU32::Hz(32_768), + } + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +/// Clock source to be calibrated using rtc_clk_cal function +pub(crate) enum RtcCalSel { + /// Currently selected RTC SLOW_CLK + RtcCalRtcMux = -1, + /// Internal 150kHz RC oscillator + RtcCalRcSlow = 0, + /// External 32kHz XTAL, as one type of 32k clock + RtcCal32kXtal = 1, + /// Internal 32kHz RC oscillator, as one type of 32k clock + RtcCal32kRc = 2, + /// External slow clock signal input by lp_pad_gpio0, as one type of 32k + /// clock + RtcCal32kOscSlow = 3, + /// Internal 20MHz RC oscillator + RtcCalRcFast, +} + +#[derive(Clone)] +pub(crate) enum RtcCaliClkSel { + CaliClkRcSlow = 0, + CaliClkRcFast = 1, + CaliClk32k = 2, +} +/// RTC Watchdog Timer +pub struct RtcClock; + +/// RTC Watchdog Timer driver +impl RtcClock { + const CAL_FRACT: u32 = 19; + + /// Enable or disable 8 MHz internal oscillator + fn enable_8m(clk_8m_en: bool, _d256_en: bool) { + let pmu = unsafe { &*PMU::PTR }; + + if clk_8m_en { + pmu.hp_sleep_lp_ck_power + .modify(|_, w| w.hp_sleep_xpd_fosc_clk().set_bit()); + + unsafe { ets_delay_us(50) }; + } else { + pmu.hp_sleep_lp_ck_power + .modify(|_, w| w.hp_sleep_xpd_fosc_clk().clear_bit()); + } + } + + /// Get main XTAL frequency + /// This is the value stored in RTC register RTC_XTAL_FREQ_REG by the + /// bootloader, as passed to rtc_clk_init function. + fn get_xtal_freq() -> XtalClock { + let xtal_freq_reg = unsafe { &*LP_AON::PTR }.store4.read().bits(); + + // Values of RTC_XTAL_FREQ_REG and RTC_APB_FREQ_REG are stored as two copies in + // lower and upper 16-bit halves. These are the routines to work with such a + // representation. + let clk_val_is_valid = |val| { + (val & 0xffffu32) == ((val >> 16u32) & 0xffffu32) && val != 0u32 && val != u32::MAX + }; + let reg_val_to_clk_val = |val| val & u16::MAX as u32; + + if !clk_val_is_valid(xtal_freq_reg) { + return XtalClock::RtcXtalFreq40M; + } + + match reg_val_to_clk_val(xtal_freq_reg) { + 40 => XtalClock::RtcXtalFreq40M, + other => XtalClock::RtcXtalFreqOther(other), + } + } + + /// Get the RTC_SLOW_CLK source + fn get_slow_freq() -> RtcSlowClock { + let lp_clrst = unsafe { &*LP_CLKRST::ptr() }; + + let slow_freq = lp_clrst.lp_clk_conf.read().slow_clk_sel().bits(); + match slow_freq { + 0 => RtcSlowClock::RtcSlowClockRcSlow, + 1 => RtcSlowClock::RtcSlowClock32kXtal, + 2 => RtcSlowClock::RtcSlowClock32kRc, + 3 => RtcSlowClock::RtcSlowOscSlow, + _ => unreachable!(), + } + } + + fn set_slow_freq(slow_freq: RtcSlowClock) { + unsafe { + let lp_clkrst = &*LP_CLKRST::PTR; + + lp_clkrst + .lp_clk_conf + .modify(|_, w| w.slow_clk_sel().bits(slow_freq as u8)); + lp_clkrst.clk_to_hp.modify(|_, w| { + w.icg_hp_xtal32k() + .bit(match slow_freq { + RtcSlowClock::RtcSlowClock32kXtal => true, + _ => false, + }) + .icg_hp_xtal32k() + .bit(match slow_freq { + RtcSlowClock::RtcSlowClock32kXtal => true, + _ => false, + }) + }); + } + } + + // TODO: IDF-5781 Some of esp32c6 SOC_RTC_FAST_CLK_SRC_XTAL_D2 rtc_fast clock + // has timing issue Force to use SOC_RTC_FAST_CLK_SRC_RC_FAST since 2nd + // stage bootloader https://github.com/espressif/esp-idf/blob/master/components/bootloader_support/src/bootloader_clock_init.c#L65-L67 + fn set_fast_freq(fast_freq: RtcFastClock) { + unsafe { + let lp_clkrst = &*LP_CLKRST::PTR; + lp_clkrst.lp_clk_conf.modify(|_, w| { + w.fast_clk_sel().bit(match fast_freq { + RtcFastClock::RtcFastClockRcFast => false, + RtcFastClock::RtcFastClockXtalD2 => true, + }) + }); + ets_delay_us(3); + } + } + + /// Calibration of RTC_SLOW_CLK is performed using a special feature of + /// TIMG0. This feature counts the number of XTAL clock cycles within a + /// given number of RTC_SLOW_CLK cycles. + fn calibrate_internal(mut cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { + const SOC_CLK_RC_FAST_FREQ_APPROX: u32 = 17_500_000; + const SOC_CLK_RC_SLOW_FREQ_APPROX: u32 = 136_000; + const SOC_CLK_XTAL32K_FREQ_APPROX: u32 = 32768; + + if cal_clk == RtcCalSel::RtcCalRtcMux { + cal_clk = match cal_clk { + RtcCalSel::RtcCalRtcMux => match RtcClock::get_slow_freq() { + RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, + RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc, + _ => cal_clk, + }, + RtcCalSel::RtcCal32kOscSlow => RtcCalSel::RtcCalRtcMux, + _ => cal_clk, + }; + } + + let lp_clkrst = unsafe { &*LP_CLKRST::ptr() }; + let pcr = unsafe { &*PCR::ptr() }; + let pmu = unsafe { &*PMU::ptr() }; + + let clk_src = RtcClock::get_slow_freq(); + + if cal_clk == RtcCalSel::RtcCalRtcMux { + cal_clk = match clk_src { + RtcSlowClock::RtcSlowClockRcSlow => RtcCalSel::RtcCalRcSlow, + RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, + RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc, + RtcSlowClock::RtcSlowOscSlow => RtcCalSel::RtcCal32kOscSlow, + }; + } + + let cali_clk_sel; + if cal_clk == RtcCalSel::RtcCalRtcMux { + cal_clk = match clk_src { + RtcSlowClock::RtcSlowClockRcSlow => RtcCalSel::RtcCalRcSlow, + RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, + RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc, + RtcSlowClock::RtcSlowOscSlow => RtcCalSel::RtcCalRcSlow, + } + } + + if cal_clk == RtcCalSel::RtcCalRcFast { + cali_clk_sel = RtcCaliClkSel::CaliClkRcFast; + } else if cal_clk == RtcCalSel::RtcCalRcSlow { + cali_clk_sel = RtcCaliClkSel::CaliClkRcSlow; + } else { + cali_clk_sel = RtcCaliClkSel::CaliClk32k; + match cal_clk { + RtcCalSel::RtcCalRtcMux | RtcCalSel::RtcCalRcSlow | RtcCalSel::RtcCalRcFast => (), + RtcCalSel::RtcCal32kRc => pcr + .ctrl_32k_conf + .modify(|_, w| unsafe { w.clk_32k_sel().bits(0) }), + RtcCalSel::RtcCal32kXtal => pcr + .ctrl_32k_conf + .modify(|_, w| unsafe { w.clk_32k_sel().bits(1) }), + RtcCalSel::RtcCal32kOscSlow => pcr + .ctrl_32k_conf + .modify(|_, w| unsafe { w.clk_32k_sel().bits(2) }), + } + } + + // Enable requested clock (150k is always on) + // Some delay is required before the time is stable + // Only enable if originaly was disabled + // If clock is already on, do nothing + + let dig_32k_xtal_enabled = lp_clkrst.clk_to_hp.read().icg_hp_xtal32k().bit_is_set(); + + if cal_clk == RtcCalSel::RtcCal32kXtal && !dig_32k_xtal_enabled { + lp_clkrst + .clk_to_hp + .modify(|_, w| w.icg_hp_xtal32k().set_bit()); + } + + // TODO: very hacky + // in ESP-IDF these are not called in this function but the fields are set + lp_clkrst + .clk_to_hp + .modify(|_, w| w.icg_hp_xtal32k().set_bit()); + pmu.hp_sleep_lp_ck_power + .modify(|_, w| w.hp_sleep_xpd_xtal32k().set_bit()); + + pmu.hp_sleep_lp_ck_power + .modify(|_, w| w.hp_sleep_xpd_rc32k().set_bit()); + + let rc_fast_enabled = pmu + .hp_sleep_lp_ck_power + .read() + .hp_sleep_xpd_fosc_clk() + .bit_is_set(); + let dig_rc_fast_enabled = lp_clkrst.clk_to_hp.read().icg_hp_fosc().bit_is_set(); + + if cal_clk == RtcCalSel::RtcCalRcFast { + if !rc_fast_enabled { + pmu.hp_sleep_lp_ck_power + .modify(|_, w| w.hp_sleep_xpd_fosc_clk().set_bit()); + unsafe { + ets_delay_us(50); + } + } + + if !dig_rc_fast_enabled { + lp_clkrst.clk_to_hp.modify(|_, w| w.icg_hp_fosc().set_bit()); + unsafe { + ets_delay_us(5); + } + } + } + + let rc32k_enabled = pmu + .hp_sleep_lp_ck_power + .read() + .hp_sleep_xpd_rc32k() + .bit_is_set(); + let dig_rc32k_enabled = lp_clkrst.clk_to_hp.read().icg_hp_osc32k().bit_is_set(); + + if cal_clk == RtcCalSel::RtcCal32kRc { + if !rc32k_enabled { + pmu.hp_sleep_lp_ck_power + .modify(|_, w| w.hp_sleep_xpd_rc32k().set_bit()); + unsafe { + ets_delay_us(300); + } + } + + if !dig_rc32k_enabled { + lp_clkrst + .clk_to_hp + .modify(|_, w| w.icg_hp_osc32k().set_bit()); + } + } + + // Check if there is already running calibration process + // TODO: &mut TIMG0 for calibration + let timg0 = unsafe { &*TIMG0::ptr() }; + + if timg0 + .rtccalicfg + .read() + .rtc_cali_start_cycling() + .bit_is_set() + { + timg0 + .rtccalicfg2 + .modify(|_, w| unsafe { w.rtc_cali_timeout_thres().bits(1) }); + + // Set small timeout threshold to accelerate the generation of timeot + // Internal circuit will be reset when timeout occurs and will not affect the + // next calibration + while !timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_set() + && !timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_set() + {} + } + + // Prepare calibration + timg0 + .rtccalicfg + .modify(|_, w| unsafe { w.rtc_cali_clk_sel().bits(cali_clk_sel.clone() as u8) }); + timg0 + .rtccalicfg + .modify(|_, w| w.rtc_cali_start_cycling().clear_bit()); + timg0 + .rtccalicfg + .modify(|_, w| unsafe { w.rtc_cali_max().bits(slowclk_cycles as u16) }); + + let expected_freq = match cali_clk_sel { + RtcCaliClkSel::CaliClk32k => { + timg0.rtccalicfg2.modify(|_, w| unsafe { + w.rtc_cali_timeout_thres().bits(slowclk_cycles << 12) + }); + SOC_CLK_XTAL32K_FREQ_APPROX + } + RtcCaliClkSel::CaliClkRcFast => { + timg0 + .rtccalicfg2 + .modify(|_, w| unsafe { w.rtc_cali_timeout_thres().bits(0x01FFFFFF) }); + SOC_CLK_RC_FAST_FREQ_APPROX + } + _ => { + timg0.rtccalicfg2.modify(|_, w| unsafe { + w.rtc_cali_timeout_thres().bits(slowclk_cycles << 10) + }); + SOC_CLK_RC_SLOW_FREQ_APPROX + } + }; + + let us_time_estimate = (HertzU32::MHz(slowclk_cycles) / expected_freq).to_Hz(); + + // Start calibration + timg0 + .rtccalicfg + .modify(|_, w| w.rtc_cali_start().clear_bit()); + timg0.rtccalicfg.modify(|_, w| w.rtc_cali_start().set_bit()); + + // Wait for calibration to finish up to another us_time_estimate + unsafe { + ets_delay_us(us_time_estimate); + } + + let cal_val = loop { + if timg0.rtccalicfg.read().rtc_cali_rdy().bit_is_set() { + break timg0.rtccalicfg1.read().rtc_cali_value().bits(); + } + + if timg0.rtccalicfg2.read().rtc_cali_timeout().bit_is_set() { + // Timed out waiting for calibration + break 0; + } + }; + + timg0 + .rtccalicfg + .modify(|_, w| w.rtc_cali_start().clear_bit()); + + if cal_clk == RtcCalSel::RtcCal32kXtal && !dig_32k_xtal_enabled { + lp_clkrst + .clk_to_hp + .modify(|_, w| w.icg_hp_xtal32k().clear_bit()); + } + + if cal_clk == RtcCalSel::RtcCalRcFast { + if rc_fast_enabled { + pmu.hp_sleep_lp_ck_power + .modify(|_, w| w.hp_sleep_xpd_fosc_clk().set_bit()); + unsafe { + ets_delay_us(50); + } + } + + if dig_rc_fast_enabled { + lp_clkrst.clk_to_hp.modify(|_, w| w.icg_hp_fosc().set_bit()); + unsafe { + ets_delay_us(5); + } + } + } + + if cal_clk == RtcCalSel::RtcCal32kRc { + if rc32k_enabled { + pmu.hp_sleep_lp_ck_power + .modify(|_, w| w.hp_sleep_xpd_rc32k().set_bit()); + unsafe { + ets_delay_us(300); + } + } + if dig_rc32k_enabled { + lp_clkrst + .clk_to_hp + .modify(|_, w| w.icg_hp_osc32k().set_bit()); + } + } + + cal_val + } + + /// Measure ratio between XTAL frequency and RTC slow clock frequency + fn get_calibration_value(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { + let xtal_freq = RtcClock::get_xtal_freq(); + let xtal_cycles = RtcClock::calibrate_internal(cal_clk, slowclk_cycles) as u64; + let divider = xtal_freq.mhz() as u64 * slowclk_cycles as u64; + let period_64 = ((xtal_cycles << RtcClock::CAL_FRACT) + divider / 2u64 - 1u64) / divider; + + (period_64 & u32::MAX as u64) as u32 + } + + /// Measure RTC slow clock's period, based on main XTAL frequency + /// + /// This function will time out and return 0 if the time for the given + /// number of cycles to be counted exceeds the expected time twice. This + /// may happen if 32k XTAL is being calibrated, but the oscillator has + /// not started up (due to incorrect loading capacitance, board design + /// issue, or lack of 32 XTAL on board). + fn calibrate(cal_clk: RtcCalSel, slowclk_cycles: u32) -> u32 { + let xtal_freq = RtcClock::get_xtal_freq(); + let xtal_cycles = RtcClock::calibrate_internal(cal_clk, slowclk_cycles) as u64; + let divider = xtal_freq.mhz() as u64 * slowclk_cycles as u64; + let period_64 = ((xtal_cycles << RtcClock::CAL_FRACT) + divider / 2u64 - 1u64) / divider; + + (period_64 & u32::MAX as u64) as u32 + } + + /// Calculate the necessary RTC_SLOW_CLK cycles to complete 1 millisecond. + pub(crate) fn cycles_to_1ms() -> u16 { + let period_13q19 = RtcClock::calibrate( + match RtcClock::get_slow_freq() { + RtcSlowClock::RtcSlowClockRcSlow => RtcCalSel::RtcCalRtcMux, + RtcSlowClock::RtcSlowClock32kXtal => RtcCalSel::RtcCal32kXtal, + RtcSlowClock::RtcSlowClock32kRc => RtcCalSel::RtcCal32kRc, + RtcSlowClock::RtcSlowOscSlow => RtcCalSel::RtcCal32kOscSlow, + // RtcSlowClock::RtcCalRcFast => RtcCalSel::RtcCalRcFast, + }, + 1024, + ); + + // 100_000_000 is used to get rid of `float` calculations + let period = (100_000_000 * period_13q19 as u64) / (1 << RtcClock::CAL_FRACT); + + (100_000_000 * 1000 / period) as u16 + } + + pub(crate) fn estimate_xtal_frequency() -> u32 { + const XTAL_FREQ_EST_CYCLES: u32 = 1024; + + let pmu = unsafe { &*PMU::PTR }; + let clk_8m_enabled = pmu + .hp_sleep_lp_ck_power + .read() + .hp_sleep_pd_osc_clk() + .bit_is_set(); + + let clk_d256_enabled = false; + + if !clk_d256_enabled { + RtcClock::enable_8m(true, true); + } + + let cal_val = RtcClock::get_calibration_value(RtcCalSel::RtcCal32kRc, XTAL_FREQ_EST_CYCLES); + let freq_hz = 1_000_000u64 * (1 << RtcClock::CAL_FRACT as u64) / cal_val as u64; + let freq_mhz = (freq_hz / 1_000_000) as u32; + + RtcClock::enable_8m(clk_8m_enabled, false); + + freq_mhz + } +} diff --git a/esp32c6-hal/.cargo/config.toml b/esp32c6-hal/.cargo/config.toml index 922b77a223d..fd739991709 100644 --- a/esp32c6-hal/.cargo/config.toml +++ b/esp32c6-hal/.cargo/config.toml @@ -1,4 +1,4 @@ -[target.riscv32imc-unknown-none-elf] +[target.riscv32imac-unknown-none-elf] runner = "espflash flash --monitor" rustflags = [ "-C", "link-arg=-Tlinkall.x", @@ -21,7 +21,7 @@ rustflags = [ ] [build] -target = "riscv32imc-unknown-none-elf" +target = "riscv32imac-unknown-none-elf" [unstable] build-std = [ "core" ] diff --git a/esp32c6-hal/Cargo.toml b/esp32c6-hal/Cargo.toml index b62ea211227..c443c8c7a07 100644 --- a/esp32c6-hal/Cargo.toml +++ b/esp32c6-hal/Cargo.toml @@ -75,12 +75,12 @@ required-features = ["eh1"] [[example]] name = "embassy_hello_world" -required-features = ["async", "embassy"] +required-features = ["embassy"] [[example]] name = "embassy_wait" -required-features = ["async", "embassy"] +required-features = ["embassy", "async"] [[example]] name = "embassy_spi" -required-features = ["async", "embassy"] +required-features = ["embassy", "async"] diff --git a/esp32c6-hal/examples/ledc.rs b/esp32c6-hal/examples/ledc.rs index 2a1339d3cb0..02066ce3f1d 100644 --- a/esp32c6-hal/examples/ledc.rs +++ b/esp32c6-hal/examples/ledc.rs @@ -70,6 +70,5 @@ fn main() -> ! { }) .unwrap(); - esp_println::println!("Dd"); loop {} } diff --git a/esp32c6-hal/examples/rtc_watchdog.rs b/esp32c6-hal/examples/rtc_watchdog.rs new file mode 100644 index 00000000000..f7a02b0d276 --- /dev/null +++ b/esp32c6-hal/examples/rtc_watchdog.rs @@ -0,0 +1,70 @@ +//! This demos the RTC Watchdog Timer (RWDT). +//! The RWDT is initially configured to trigger an interrupt after a given +//! timeout. Then, upon expiration, the RWDT is restarted and then reconfigured +//! to reset both the main system and the RTC. + +#![no_std] +#![no_main] + +use core::cell::RefCell; + +use critical_section::Mutex; +use esp32c6_hal::{ + clock::ClockControl, + interrupt, + peripherals::{self, Peripherals}, + prelude::*, + riscv, + Rtc, + Rwdt, +}; +use esp_backtrace as _; + +static RWDT: Mutex>> = Mutex::new(RefCell::new(None)); + +#[entry] +fn main() -> ! { + let peripherals = Peripherals::take(); + let system = peripherals.PCR.split(); + let _clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + + let mut rtc = Rtc::new(peripherals.LP_CLKRST); + + // Disable watchdog timers + rtc.swd.disable(); + rtc.rwdt.disable(); + + rtc.rwdt.start(2000u64.millis()); + rtc.rwdt.listen(); + + interrupt::enable( + peripherals::Interrupt::LP_WDT, + interrupt::Priority::Priority1, + ) + .unwrap(); + + critical_section::with(|cs| RWDT.borrow_ref_mut(cs).replace(rtc.rwdt)); + + unsafe { + riscv::interrupt::enable(); + } + + loop {} +} + +#[interrupt] +fn LP_WDT() { + critical_section::with(|cs| { + esp_println::println!("RWDT Interrupt"); + + let mut rwdt = RWDT.borrow_ref_mut(cs); + let rwdt = rwdt.as_mut().unwrap(); + + rwdt.clear_interrupt(); + + esp_println::println!("Restarting in 5 seconds..."); + + rwdt.start(5000u64.millis()); + rwdt.unlisten(); + }); +} diff --git a/esp32c6-hal/ld/db-riscv-link.x b/esp32c6-hal/ld/db-riscv-link.x index cac5389ef96..7df2124aafa 100644 --- a/esp32c6-hal/ld/db-riscv-link.x +++ b/esp32c6-hal/ld/db-riscv-link.x @@ -79,7 +79,7 @@ SECTIONS _erodata = .; } > REGION_RODATA - _rodata_size = _erodata - _srodata; + _rodata_size = _erodata - _srodata + 8; .data ORIGIN(RAM) : AT(_text_size + _rodata_size) { _sdata = .; @@ -91,14 +91,14 @@ SECTIONS _edata = .; } > REGION_DATA - _data_size = _edata - _sdata; + _data_size = _edata - _sdata + 8; .rwtext ORIGIN(REGION_RWTEXT) + _data_size : AT(_text_size + _rodata_size + _data_size){ _srwtext = .; *(.rwtext); . = ALIGN(4); _erwtext = .; } > REGION_RWTEXT - _rwtext_size = _erwtext - _srwtext; + _rwtext_size = _erwtext - _srwtext + 8; .rtc_fast.text : AT(_text_size + _rodata_size + _data_size + _rwtext_size) { _srtc_fast_text = .; @@ -106,7 +106,7 @@ SECTIONS . = ALIGN(4); _ertc_fast_text = .; } > REGION_RTC_FAST - _fast_text_size = _ertc_fast_text - _srtc_fast_text; + _fast_text_size = _ertc_fast_text - _srtc_fast_text + 8; .rtc_fast.data : AT(_text_size + _rodata_size + _data_size + _rwtext_size + _fast_text_size) { @@ -115,7 +115,7 @@ SECTIONS . = ALIGN(4); _rtc_fast_data_end = ABSOLUTE(.); } > REGION_RTC_FAST - _rtc_fast_data_size = _rtc_fast_data_end - _rtc_fast_data_start; + _rtc_fast_data_size = _rtc_fast_data_end - _rtc_fast_data_start + 8; .rtc_fast.bss (NOLOAD) : ALIGN(4) { diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index 8976d079b73..7dcb5fe05c9 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -35,6 +35,7 @@ pub use esp_hal_common::{ Delay, PulseControl, Rtc, + Rwdt, Uart, UsbSerialJtag, }; From 87cf4852b6f41f61aef2b9e9fbb2cf4ac06e6588 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Thu, 23 Feb 2023 08:20:51 -0800 Subject: [PATCH 53/64] Make required changes to include new `RADIO` peripheral --- esp-hal-common/build.rs | 1 + esp-hal-common/src/peripherals/esp32c6.rs | 125 +++++++++++----------- esp-hal-common/src/radio.rs | 12 ++- esp32c6-hal/Cargo.toml | 2 +- 4 files changed, 76 insertions(+), 64 deletions(-) diff --git a/esp-hal-common/build.rs b/esp-hal-common/build.rs index 5c43dbd26b4..b3e7ccd85ed 100644 --- a/esp-hal-common/build.rs +++ b/esp-hal-common/build.rs @@ -111,6 +111,7 @@ fn main() { "usb_serial_jtag", "plic", "aes", + "radio", ] } else if esp32s2 { vec![ diff --git a/esp-hal-common/src/peripherals/esp32c6.rs b/esp-hal-common/src/peripherals/esp32c6.rs index 255bf93252a..8efc84f3f2d 100644 --- a/esp-hal-common/src/peripherals/esp32c6.rs +++ b/esp-hal-common/src/peripherals/esp32c6.rs @@ -6,66 +6,67 @@ pub use pac::Interrupt; pub(crate) use self::peripherals::*; crate::peripherals! { - AES, - APB_SARADC, - ASSIST_DEBUG, - ATOMIC, - DMA, - DS, - ECC, - EFUSE, - EXTMEM, - GPIO, - GPIOSD, - HINF, - HMAC, - HP_APM, - HP_SYS, - I2C0, - I2S0, - INTERRUPT_CORE0, - INTPRI, - IO_MUX, - LEDC, - LP_PERI, - LP_ANA, - LP_AON, - LP_APM, - LP_APM0, - LP_CLKRST, - LP_I2C0, - LP_I2C_ANA_MST, - LP_IO, - LP_TEE, - LP_TIMER, - LP_UART, - LP_WDT, - MCPWM, - MEM_MONITOR, - OTP_DEBUG, - PARL_IO, - PAU, - PCNT, - PCR, - PMU, - RMT, - RNG, - RSA, - SHA, - SLCHOST, - SOC_ETM, - SPI0, - SPI1, - SPI2, - SYSTIMER, - TEE, - TIMG0, - TIMG1, - TRACE, - TWAI0, - TWAI1, - UART0, - UART1, - UHCI0, - USB_DEVICE, + AES => true, + APB_SARADC => true, + ASSIST_DEBUG => true, + ATOMIC => true, + DMA => true, + DS => true, + ECC => true, + EFUSE => true, + EXTMEM => true, + GPIO => true, + GPIOSD => true, + HINF => true, + HMAC => true, + HP_APM => true, + HP_SYS => true, + I2C0 => true, + I2S0 => true, + INTERRUPT_CORE0 => true, + INTPRI => true, + IO_MUX => true, + LEDC => true, + LP_PERI => true, + LP_ANA => true, + LP_AON => true, + LP_APM => true, + LP_APM0 => true, + LP_CLKRST => true, + LP_I2C0 => true, + LP_I2C_ANA_MST => true, + LP_IO => true, + LP_TEE => true, + LP_TIMER => true, + LP_UART => true, + LP_WDT => true, + MCPWM => true, + MEM_MONITOR => true, + OTP_DEBUG => true, + PARL_IO => true, + PAU => true, + PCNT => true, + PCR => true, + PMU => true, + RMT => true, + RNG => true, + RSA => true, + SHA => true, + SLCHOST => true, + SOC_ETM => true, + SPI0 => true, + SPI1 => true, + SPI2 => true, + SYSTIMER => true, + TEE => true, + TIMG0 => true, + TIMG1 => true, + TRACE => true, + TWAI0 => true, + TWAI1 => true, + UART0 => true, + UART1 => true, + UHCI0 => true, + USB_DEVICE => true, + RADIO => false, } diff --git a/esp-hal-common/src/radio.rs b/esp-hal-common/src/radio.rs index 437b5b4c1ea..61dc63af62a 100644 --- a/esp-hal-common/src/radio.rs +++ b/esp-hal-common/src/radio.rs @@ -38,7 +38,7 @@ impl LowRate { } cfg_if::cfg_if! { - if #[cfg(any(esp32, esp32s3, esp32c2, esp32c3))] { + if #[cfg(any(esp32, esp32c2, esp32c3, esp32s3))] { impl RadioExt for crate::peripherals::RADIO { type Components = (Wifi, Bluetooth); @@ -48,6 +48,16 @@ cfg_if::cfg_if! { } } } + } else if #[cfg(esp32c6)] { + impl RadioExt for crate::peripherals::RADIO { + type Components = (Wifi, Bluetooth, LowRate); + + fn split(self) -> Self::Components { + unsafe { + (Wifi::steal(), Bluetooth::steal(), LowRate::steal()) + } + } + } } else if #[cfg(esp32s2)] { impl RadioExt for crate::peripherals::RADIO { type Components = Wifi; diff --git a/esp32c6-hal/Cargo.toml b/esp32c6-hal/Cargo.toml index c443c8c7a07..4b695e3d6b0 100644 --- a/esp32c6-hal/Cargo.toml +++ b/esp32c6-hal/Cargo.toml @@ -33,7 +33,7 @@ embedded-hal-1 = { version = "=1.0.0-alpha.9", optional = true, package = "e embedded-hal-async = { version = "0.2.0-alpha.0", optional = true } embedded-hal-nb = { version = "=1.0.0-alpha.1", optional = true } embedded-can = { version = "0.4.1", optional = true } -esp-hal-common = { version = "0.6.0", features = ["esp32c6"], path = "../esp-hal-common" } +esp-hal-common = { version = "0.7.0", features = ["esp32c6"], path = "../esp-hal-common" } r0 = "1.0.0" [dev-dependencies] From 0d3fd8117b1f2ef6cfb8f173973b413e7fcbce2b Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Thu, 23 Feb 2023 09:30:01 -0800 Subject: [PATCH 54/64] Use published versions of PAC and `esp-println` --- esp-hal-common/Cargo.toml | 11 +++++------ esp32c6-hal/Cargo.toml | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/esp-hal-common/Cargo.toml b/esp-hal-common/Cargo.toml index 2f79b6c79dc..98ce16eff8e 100644 --- a/esp-hal-common/Cargo.toml +++ b/esp-hal-common/Cargo.toml @@ -51,20 +51,19 @@ ufmt-write = { version = "0.1.0", optional = true } # IMPORTANT: # Each supported device MUST have its PAC included below along with a -# corresponding feature. We rename the PAC packages because we cannot -# have dependencies and features with the same names. +# corresponding feature. esp32 = { version = "0.21.0", features = ["critical-section"], optional = true } esp32c2 = { version = "0.8.0", features = ["critical-section"], optional = true } esp32c3 = { version = "0.11.0", features = ["critical-section"], optional = true } -esp32c6 = { git = "https://github.com/esp-rs/esp-pacs", rev = "1124275", package = "esp32c6", features = ["critical-section"], optional = true } +esp32c6 = { version = "0.1.0", features = ["critical-section"], optional = true } esp32s2 = { version = "0.12.0", features = ["critical-section"], optional = true } esp32s3 = { version = "0.15.0", features = ["critical-section"], optional = true } [features] esp32 = ["esp32/rt" , "xtensa", "xtensa-lx/esp32", "xtensa-lx-rt/esp32", "lock_api", "procmacros/esp32"] -esp32c2 = ["esp32c2/rt", "riscv", "procmacros/esp32c2"] -esp32c3 = ["esp32c3/rt", "riscv", "procmacros/esp32c3"] -esp32c6 = ["esp32c6/rt", "riscv", "procmacros/esp32c6"] +esp32c2 = ["esp32c2/rt", "riscv", "procmacros/esp32c2"] +esp32c3 = ["esp32c3/rt", "riscv", "procmacros/esp32c3"] +esp32c6 = ["esp32c6/rt", "riscv", "procmacros/esp32c6"] esp32s2 = ["esp32s2/rt", "xtensa", "xtensa-lx/esp32s2", "xtensa-lx-rt/esp32s2", "esp-synopsys-usb-otg", "usb-device", "procmacros/esp32s2"] esp32s3 = ["esp32s3/rt", "xtensa", "xtensa-lx/esp32s3", "xtensa-lx-rt/esp32s3", "lock_api", "esp-synopsys-usb-otg", "usb-device", "procmacros/esp32s3"] diff --git a/esp32c6-hal/Cargo.toml b/esp32c6-hal/Cargo.toml index 4b695e3d6b0..cff43a9a025 100644 --- a/esp32c6-hal/Cargo.toml +++ b/esp32c6-hal/Cargo.toml @@ -42,7 +42,7 @@ critical-section = "1.1.1" embassy-executor = { package = "embassy-executor", git = "https://github.com/embassy-rs/embassy/", rev = "cd9a65b", features = ["nightly", "integrated-timers"] } embedded-graphics = "0.7.1" esp-backtrace = { git = "https://github.com/jessebraham/esp-backtrace", branch = "feature/chip-support", features = ["esp32c6", "panic-handler", "exception-handler", "print-uart"] } -esp-println = { git = "https://github.com/esp-rs/esp-println", rev = "316b5b9", features = ["esp32c6"] } +esp-println = { version = "0.4.0", features = ["esp32c6"] } sha2 = { version = "0.10.6", default-features = false} smart-leds = "0.3.0" ssd1306 = "0.7.1" From a38148793fdc389a3dabc53eb77bb1c4d1eb02a5 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Fri, 24 Feb 2023 06:24:22 -0800 Subject: [PATCH 55/64] Use the correct target extensions (`imac`) --- README.md | 16 ++++++++-------- esp32c6-hal/.cargo/config.toml | 16 ---------------- esp32c6-hal/README.md | 4 ++-- 3 files changed, 10 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 2bd15275a9c..5456c604ca1 100644 --- a/README.md +++ b/README.md @@ -12,14 +12,14 @@ This project is still in the early stages of development, and as such there shou If you have any questions, comments, or concerns, please [open an issue], [start a new discussion], or join us on [Matrix]. For additional information regarding any of the crates in this repository, please refer to the crate's README. -| Crate | Target | Technical Reference Manual | -| :-----------: | :---------------------------: | :------------------------: | -| [esp32-hal] | `xtensa-esp32-none-elf` | [ESP32] | -| [esp32c2-hal] | `riscv32imc-unknown-none-elf` | [ESP32-C2] | -| [esp32c3-hal] | `riscv32imc-unknown-none-elf` | [ESP32-C3] | -| [esp32c6-hal] | `riscv32imc-unknown-none-elf` | [ESP32-C6] | -| [esp32s2-hal] | `xtensa-esp32s2-none-elf` | [ESP32-S2] | -| [esp32s3-hal] | `xtensa-esp32s3-none-elf` | [ESP32-S3] | +| Crate | Target | Technical Reference Manual | +| :-----------: | :----------------------------: | :------------------------: | +| [esp32-hal] | `xtensa-esp32-none-elf` | [ESP32] | +| [esp32c2-hal] | `riscv32imc-unknown-none-elf` | [ESP32-C2] | +| [esp32c3-hal] | `riscv32imc-unknown-none-elf` | [ESP32-C3] | +| [esp32c6-hal] | `riscv32imac-unknown-none-elf` | [ESP32-C6] | +| [esp32s2-hal] | `xtensa-esp32s2-none-elf` | [ESP32-S2] | +| [esp32s3-hal] | `xtensa-esp32s3-none-elf` | [ESP32-S3] | [here]: https://github.com/esp-rs/esp-hal/issues/19 [esp-idf-hal]: https://github.com/esp-rs/esp-idf-hal diff --git a/esp32c6-hal/.cargo/config.toml b/esp32c6-hal/.cargo/config.toml index fd739991709..3e8a0bd0188 100644 --- a/esp32c6-hal/.cargo/config.toml +++ b/esp32c6-hal/.cargo/config.toml @@ -2,22 +2,6 @@ runner = "espflash flash --monitor" rustflags = [ "-C", "link-arg=-Tlinkall.x", - - # comment the cfgs below if you do _not_ wish to emulate atomics. - # enable the atomic codegen option for RISCV - "-C", "target-feature=+a", - # tell the core library have atomics even though it's not specified in the target definition - "--cfg", "target_has_atomic_load_store", - "--cfg", 'target_has_atomic_load_store="8"', - "--cfg", 'target_has_atomic_load_store="16"', - "--cfg", 'target_has_atomic_load_store="32"', - "--cfg", 'target_has_atomic_load_store="ptr"', - # enable cas - "--cfg", "target_has_atomic", - "--cfg", 'target_has_atomic="8"', - "--cfg", 'target_has_atomic="16"', - "--cfg", 'target_has_atomic="32"', - "--cfg", 'target_has_atomic="ptr"', ] [build] diff --git a/esp32c6-hal/README.md b/esp32c6-hal/README.md index 5f2d29f387b..4fa998f7841 100644 --- a/esp32c6-hal/README.md +++ b/esp32c6-hal/README.md @@ -7,7 +7,7 @@ `no_std` HAL for the ESP32-C6 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 `riscv32imc-unknown-none-elf` target. Refer to the [Getting Stared](#getting-started) section below for more information. +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 Stared](#getting-started) section below for more information. ## [Documentation] @@ -20,7 +20,7 @@ This device uses the RISC-V ISA, which is officially supported by the Rust compi The compilation target for this device is officially supported via the `stable` release channel and can be installed via [rustup](https://rustup.rs/): ```shell -$ rustup target add riscv32imc-unknown-none-elf +$ rustup target add riscv32imac-unknown-none-elf ``` ### Supported boot methods From 572e99d7a5e1ce782078e72a94c12b1197500a08 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Fri, 24 Feb 2023 08:45:56 -0800 Subject: [PATCH 56/64] Fix the super watchdog timer, plus a few more examples --- esp-hal-common/src/rtc_cntl/mod.rs | 8 ++++++-- esp32c6-hal/examples/blinky_erased_pins.rs | 2 +- esp32c6-hal/examples/embassy_wait.rs | 8 ++++---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/esp-hal-common/src/rtc_cntl/mod.rs b/esp-hal-common/src/rtc_cntl/mod.rs index 8124a2b8002..ed447d4787a 100644 --- a/esp-hal-common/src/rtc_cntl/mod.rs +++ b/esp-hal-common/src/rtc_cntl/mod.rs @@ -119,7 +119,7 @@ pub(crate) enum RtcCalSel { pub struct Rtc<'d> { _inner: PeripheralRef<'d, RtcCntl>, pub rwdt: Rwdt, - #[cfg(any(esp32c2, esp32c3, esp32s3, esp32c6))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] pub swd: Swd, } @@ -131,7 +131,7 @@ impl<'d> Rtc<'d> { Self { _inner: rtc_cntl.into_ref(), rwdt: Rwdt::default(), - #[cfg(any(esp32c2, esp32c3, esp32s3, esp32c6))] + #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] swd: Swd::new(), } } @@ -778,7 +778,11 @@ impl Swd { let rtc_cntl = unsafe { &*RTC_CNTL::PTR }; #[cfg(esp32c6)] let rtc_cntl = unsafe { &*LP_WDT::PTR }; + + #[cfg(not(esp32c6))] let wkey = if enable { 0u32 } else { 0x8F1D_312A }; + #[cfg(esp32c6)] + let wkey = if enable { 0u32 } else { 0x50D8_3AA1 }; rtc_cntl .swd_wprotect diff --git a/esp32c6-hal/examples/blinky_erased_pins.rs b/esp32c6-hal/examples/blinky_erased_pins.rs index 412898f5b36..776a31e14d8 100644 --- a/esp32c6-hal/examples/blinky_erased_pins.rs +++ b/esp32c6-hal/examples/blinky_erased_pins.rs @@ -41,7 +41,7 @@ fn main() -> ! { let led2 = io.pins.gpio4.into_push_pull_output(); let led3 = io.pins.gpio5.into_push_pull_output(); - let button = io.pins.gpio0.into_pull_down_input().degrade(); + let button = io.pins.gpio9.into_pull_down_input().degrade(); // you can use `into` or `degrade` let mut pins = [led1.into(), led2.into(), led3.degrade()]; diff --git a/esp32c6-hal/examples/embassy_wait.rs b/esp32c6-hal/examples/embassy_wait.rs index 20e0fb91c4d..90cf3a8c8b6 100644 --- a/esp32c6-hal/examples/embassy_wait.rs +++ b/esp32c6-hal/examples/embassy_wait.rs @@ -19,11 +19,11 @@ use esp32c6_hal::{ IO, }; use esp_backtrace as _; -use esp_hal_common::{Gpio0, Input, PullDown}; +use esp_hal_common::{Gpio9, Input, PullDown}; use static_cell::StaticCell; #[embassy_executor::task] -async fn ping(mut pin: Gpio0>) { +async fn ping(mut pin: Gpio9>) { loop { esp_println::println!("Waiting..."); pin.wait_for_rising_edge().await.unwrap(); @@ -63,8 +63,8 @@ fn main() -> ! { embassy::init(&clocks, timer_group0.timer0); let io = IO::new(peripherals.GPIO, peripherals.IO_MUX); - // GPIO 0 as input - let input = io.pins.gpio0.into_pull_down_input(); + // GPIO 9 as input + let input = io.pins.gpio9.into_pull_down_input(); // Async requires the GPIO interrupt to wake futures esp32c6_hal::interrupt::enable( From dc309ea819985d83120d37e657dadaf15d301312 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Fri, 24 Feb 2023 10:34:34 -0800 Subject: [PATCH 57/64] Fix UART clock configuration --- esp-hal-common/src/uart.rs | 78 +++++++++++++++++++++++++++++++++++++- 1 file changed, 77 insertions(+), 1 deletion(-) diff --git a/esp-hal-common/src/uart.rs b/esp-hal-common/src/uart.rs index 98afe823426..9e1a996577d 100644 --- a/esp-hal-common/src/uart.rs +++ b/esp-hal-common/src/uart.rs @@ -559,7 +559,7 @@ where self } - #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32s3))] fn change_baud(&self, baudrate: u32, clocks: &Clocks) { // we force the clock source to be APB and don't use the decimal part of the // divider @@ -592,6 +592,65 @@ where .write(|w| unsafe { w.clkdiv().bits(divider).frag().bits(0) }); } + #[cfg(esp32c6)] + fn change_baud(&self, baudrate: u32, clocks: &Clocks) { + // we force the clock source to be APB and don't use the decimal part of the + // divider + let clk = clocks.apb_clock.to_Hz(); + let max_div = 0b1111_1111_1111 - 1; + let clk_div = ((clk) + (max_div * baudrate) - 1) / (max_div * baudrate); + + // UART clocks are configured via PCR + let pcr = unsafe { &*esp32c6::PCR::PTR }; + + match self.uart.uart_number() { + 0 => { + pcr.uart0_conf + .modify(|_, w| w.uart0_rst_en().clear_bit().uart0_clk_en().set_bit()); + + pcr.uart0_sclk_conf.modify(|_, w| unsafe { + w.uart0_sclk_div_a() + .bits(0) + .uart0_sclk_div_b() + .bits(0) + .uart0_sclk_div_num() + .bits(clk_div as u8 - 1) + .uart0_sclk_sel() + .bits(0x1) // TODO: this probably shouldn't be hard-coded + .uart0_sclk_en() + .set_bit() + }); + } + 1 => { + pcr.uart1_conf + .modify(|_, w| w.uart1_rst_en().clear_bit().uart1_clk_en().set_bit()); + + pcr.uart1_sclk_conf.modify(|_, w| unsafe { + w.uart1_sclk_div_a() + .bits(0) + .uart1_sclk_div_b() + .bits(0) + .uart1_sclk_div_num() + .bits(clk_div as u8 - 1) + .uart1_sclk_sel() + .bits(0x1) // TODO: this probably shouldn't be hard-coded + .uart1_sclk_en() + .set_bit() + }); + } + _ => unreachable!(), // ESP32-C6 only has 2 UART instances + } + + let clk = clk / clk_div; + let divider = clk / baudrate; + let divider = divider as u16; + + self.uart + .register_block() + .clkdiv + .write(|w| unsafe { w.clkdiv().bits(divider).frag().bits(0) }); + } + #[cfg(any(esp32, esp32s2))] fn change_baud(&self, baudrate: u32, clocks: &Clocks) { // we force the clock source to be APB and don't use the decimal part of the @@ -615,6 +674,8 @@ where pub trait Instance { fn register_block(&self) -> &RegisterBlock; + fn uart_number(&self) -> usize; + fn disable_tx_interrupts(&mut self) { self.register_block().int_clr.write(|w| { w.txfifo_empty_int_clr() @@ -710,6 +771,11 @@ impl Instance for UART0 { self } + #[inline(always)] + fn uart_number(&self) -> usize { + 0 + } + fn tx_signal(&self) -> OutputSignal { OutputSignal::U0TXD } @@ -733,6 +799,11 @@ impl Instance for UART1 { self } + #[inline(always)] + fn uart_number(&self) -> usize { + 1 + } + fn tx_signal(&self) -> OutputSignal { OutputSignal::U1TXD } @@ -757,6 +828,11 @@ impl Instance for UART2 { self } + #[inline(always)] + fn uart_number(&self) -> usize { + 2 + } + fn tx_signal(&self) -> OutputSignal { OutputSignal::U2TXD } From 716163bf7df47dd8af4344f1167928a0efd7e4f9 Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Mon, 27 Feb 2023 09:39:52 +0100 Subject: [PATCH 58/64] Make sure to sync UART registers when configuring AT cmd detection --- esp-hal-common/src/uart.rs | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/esp-hal-common/src/uart.rs b/esp-hal-common/src/uart.rs index 9e1a996577d..97133b319da 100644 --- a/esp-hal-common/src/uart.rs +++ b/esp-hal-common/src/uart.rs @@ -343,6 +343,8 @@ where .register_block() .clk_conf .modify(|_, w| w.sclk_en().set_bit()); + + self.sync_regs(); } /// Configures the RX-FIFO threshold @@ -668,6 +670,30 @@ where .clkdiv .write(|w| unsafe { w.clkdiv().bits(divider).frag().bits(0) }); } + + #[cfg(esp32c6)] // TODO introduce a cfg symbol for this + #[inline(always)] + fn sync_regs(&mut self) { + self.uart + .register_block() + .reg_update + .modify(|_, w| w.reg_update().set_bit()); + + while self + .uart + .register_block() + .reg_update + .read() + .reg_update() + .bit_is_set() + { + // wait + } + } + + #[cfg(not(esp32c6))] + #[inline(always)] + fn sync_regs(&mut self) {} } /// UART peripheral instance From 2f5972b95af31670c8614a2161a6efb82040a99d Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Mon, 27 Feb 2023 13:41:58 +0100 Subject: [PATCH 59/64] Disable APM in direct-boot mode --- esp-hal-common/src/lib.rs | 9 +++++++++ esp32c6-hal/src/lib.rs | 2 ++ 2 files changed, 11 insertions(+) diff --git a/esp-hal-common/src/lib.rs b/esp-hal-common/src/lib.rs index 100c994aa1b..763522ea7ec 100644 --- a/esp-hal-common/src/lib.rs +++ b/esp-hal-common/src/lib.rs @@ -130,6 +130,15 @@ pub mod interrupt; #[cfg_attr(esp32s3, path = "peripherals/esp32s3.rs")] pub mod peripherals; +#[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 /// The actual number of available cores depends on the target. pub enum Cpu { diff --git a/esp32c6-hal/src/lib.rs b/esp32c6-hal/src/lib.rs index 7dcb5fe05c9..4b517a16307 100644 --- a/esp32c6-hal/src/lib.rs +++ b/esp32c6-hal/src/lib.rs @@ -85,6 +85,8 @@ unsafe fn init() { ); r0::init_data(&mut _srtc_fast_text, &mut _ertc_fast_text, &_irtc_fast_text); + + esp_hal_common::disable_apm_filter(); } #[allow(unreachable_code)] From 3eb273a3ece50a61b5d72f6a60e135a0e880441b Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Mon, 27 Feb 2023 07:41:33 -0800 Subject: [PATCH 60/64] Address a number of review comments --- esp-hal-common/src/interrupt/riscv.rs | 7 +----- esp-hal-common/src/rtc_cntl/mod.rs | 8 +++---- esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs | 25 ---------------------- esp-hal-common/src/system.rs | 2 +- 4 files changed, 5 insertions(+), 37 deletions(-) diff --git a/esp-hal-common/src/interrupt/riscv.rs b/esp-hal-common/src/interrupt/riscv.rs index b36eabffe75..f1d223f1049 100644 --- a/esp-hal-common/src/interrupt/riscv.rs +++ b/esp-hal-common/src/interrupt/riscv.rs @@ -724,12 +724,7 @@ pub fn _setup_interrupts() { }; #[cfg(esp32c6)] - write_mie(u32::MAX); -} - -#[cfg(esp32c6)] -fn write_mie(val: u32) { unsafe { - core::arch::asm!("csrw mie, {0}", in(reg) val); + core::arch::asm!("csrw mie, {0}", in(reg) u32::MAX); } } diff --git a/esp-hal-common/src/rtc_cntl/mod.rs b/esp-hal-common/src/rtc_cntl/mod.rs index ed447d4787a..8592d6d602c 100644 --- a/esp-hal-common/src/rtc_cntl/mod.rs +++ b/esp-hal-common/src/rtc_cntl/mod.rs @@ -136,6 +136,8 @@ impl<'d> Rtc<'d> { } } + // TODO: implement for ESP32-C6 + #[cfg(not(esp32c6))] pub fn estimate_xtal_frequency(&mut self) -> u32 { RtcClock::estimate_xtal_frequency() } @@ -523,6 +525,7 @@ impl RtcClock { (100_000_000 * 1000 / period) as u16 } + // TODO: implement for ESP32-C6 #[cfg(not(esp32c6))] fn estimate_xtal_frequency() -> u32 { // Number of 8M/256 clock cycles to use for XTAL frequency estimation. @@ -545,11 +548,6 @@ impl RtcClock { freq_mhz } - - #[cfg(esp32c6)] - fn estimate_xtal_frequency() -> u32 { - todo!() - } } /// Behavior of the RWDT stage if it times out diff --git a/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs b/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs index 462454fab78..c26d91de854 100644 --- a/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs +++ b/esp-hal-common/src/rtc_cntl/rtc/esp32c6.rs @@ -669,29 +669,4 @@ impl RtcClock { (100_000_000 * 1000 / period) as u16 } - - pub(crate) fn estimate_xtal_frequency() -> u32 { - const XTAL_FREQ_EST_CYCLES: u32 = 1024; - - let pmu = unsafe { &*PMU::PTR }; - let clk_8m_enabled = pmu - .hp_sleep_lp_ck_power - .read() - .hp_sleep_pd_osc_clk() - .bit_is_set(); - - let clk_d256_enabled = false; - - if !clk_d256_enabled { - RtcClock::enable_8m(true, true); - } - - let cal_val = RtcClock::get_calibration_value(RtcCalSel::RtcCal32kRc, XTAL_FREQ_EST_CYCLES); - let freq_hz = 1_000_000u64 * (1 << RtcClock::CAL_FRACT as u64) / cal_val as u64; - let freq_mhz = (freq_hz / 1_000_000) as u32; - - RtcClock::enable_8m(clk_8m_enabled, false); - - freq_mhz - } } diff --git a/esp-hal-common/src/system.rs b/esp-hal-common/src/system.rs index 66fee258f05..d58fe20a438 100644 --- a/esp-hal-common/src/system.rs +++ b/esp-hal-common/src/system.rs @@ -80,7 +80,7 @@ impl PeripheralClockControl { ) }; - #[cfg(any(esp32c2, esp32c3, esp32c6, esp32s2, esp32s3))] + #[cfg(any(esp32c2, esp32c3, esp32s2, esp32s3))] let (perip_clk_en1, perip_rst_en1) = { (&system.perip_clk_en1, &system.perip_rst_en1) }; match peripheral { From 6641a0d6a1d9fab6272b34cd65e8765ab4a4e550 Mon Sep 17 00:00:00 2001 From: Juraj Sadel Date: Mon, 27 Feb 2023 16:54:11 +0100 Subject: [PATCH 61/64] Fix `SPI` clocks and `rtc_watchdog` example (#6) * fix SPI clocks * run cargo fmt * Add comment about used default clk src * Fix rtc_watchdog example in BL mode * run cargo fmt * Update rtc_watchdog example that it works in DB mode --- esp-hal-common/src/rtc_cntl/mod.rs | 10 ++++++---- esp-hal-common/src/spi.rs | 8 ++++++++ esp32c6-hal/examples/rtc_watchdog.rs | 10 +++++++++- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/esp-hal-common/src/rtc_cntl/mod.rs b/esp-hal-common/src/rtc_cntl/mod.rs index 8592d6d602c..2ec0d77dd97 100644 --- a/esp-hal-common/src/rtc_cntl/mod.rs +++ b/esp-hal-common/src/rtc_cntl/mod.rs @@ -6,7 +6,7 @@ use fugit::MicrosDurationU64; use self::rtc::SocResetReason; #[cfg(not(esp32c6))] use crate::clock::{Clock, XtalClock}; -#[cfg(not(any(esp32, esp32c6)))] +#[cfg(not(esp32))] use crate::efuse::Efuse; #[cfg(esp32c6)] use crate::peripherals::LP_WDT; @@ -692,6 +692,7 @@ impl WatchdogDisable for Rwdt { } } +// TODO: this can be refactored impl WatchdogEnable for Rwdt { type Time = MicrosDurationU64; @@ -714,9 +715,10 @@ impl WatchdogEnable for Rwdt { .modify(|_, w| w.wdt_stg0_hold().bits(timeout_raw)); #[cfg(esp32c6)] - (&*LP_WDT::PTR) - .config1 - .modify(|_, w| w.wdt_stg0_hold().bits(timeout_raw)); + (&*LP_WDT::PTR).config1.modify(|_, w| { + w.wdt_stg0_hold() + .bits(timeout_raw >> (1 + Efuse::get_rwdt_multiplier())) + }); #[cfg(not(any(esp32, esp32c6)))] rtc_cntl.wdtconfig1.modify(|_, w| { diff --git a/esp-hal-common/src/spi.rs b/esp-hal-common/src/spi.rs index 8515bb1b0cf..63c9339fe4a 100644 --- a/esp-hal-common/src/spi.rs +++ b/esp-hal-common/src/spi.rs @@ -1330,6 +1330,14 @@ pub trait Instance { .set_bit() }); + #[cfg(esp32c6)] + unsafe { + let pcr = &*esp32c6::PCR::PTR; + + // use default clock source PLL_F80M_CLK + pcr.spi2_clkm_conf.modify(|_, w| w.spi2_clkm_sel().bits(1)); + } + reg_block.ctrl.write(|w| unsafe { w.bits(0) }); #[cfg(not(esp32))] diff --git a/esp32c6-hal/examples/rtc_watchdog.rs b/esp32c6-hal/examples/rtc_watchdog.rs index f7a02b0d276..73601b1d70f 100644 --- a/esp32c6-hal/examples/rtc_watchdog.rs +++ b/esp32c6-hal/examples/rtc_watchdog.rs @@ -15,6 +15,7 @@ use esp32c6_hal::{ peripherals::{self, Peripherals}, prelude::*, riscv, + timer::TimerGroup, Rtc, Rwdt, }; @@ -26,8 +27,15 @@ static RWDT: Mutex>> = Mutex::new(RefCell::new(None)); fn main() -> ! { let peripherals = Peripherals::take(); let system = peripherals.PCR.split(); - let _clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); + let timer_group0 = TimerGroup::new(peripherals.TIMG0, &clocks); + let mut wdt0 = timer_group0.wdt; + let timer_group1 = TimerGroup::new(peripherals.TIMG1, &clocks); + let mut wdt1 = timer_group1.wdt; + + wdt0.disable(); + wdt1.disable(); let mut rtc = Rtc::new(peripherals.LP_CLKRST); // Disable watchdog timers From 9e5f29873eac8ce09f162d81ea687726ddef46d8 Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Mon, 27 Feb 2023 08:19:02 -0800 Subject: [PATCH 62/64] README and example fixes/cleanup --- README.md | 4 ++-- esp32c6-hal/README.md | 6 +++--- esp32c6-hal/examples/hello_rgb.rs | 1 - 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 5456c604ca1..189350e7111 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ There are a number of other crates within the [esp-rs organization] which can be | [esp-backtrace] | Backtrace support for bare-metal applications | | [esp-println] | Provides `print!` and `println!` implementations | | [esp-storage] | Implementation of [embedded-storage] traits to access unencrypted flash memory | -| [esp-wifi] | Experimental `no_std` Wi-Fi/Bluetooth LE support | +| [esp-wifi] | `no_std` Wi-Fi/Bluetooth LE support | [esp-rs organization]: https://github.com/esp-rs [esp-alloc]: https://github.com/esp-rs/esp-alloc @@ -79,7 +79,7 @@ There are a number of other crates within the [esp-rs organization] which can be The **M**inimum **S**upported **R**ust **V**ersions are: -- `1.65.0` for RISC-V devices (**ESP32-C2**, **ESP32-C3**) +- `1.65.0` for RISC-V devices (**ESP32-C2**, **ESP32-C3**, **ESP32-C6**) - `1.65.0` for Xtensa devices (**ESP32**, **ESP32-S2**, **ESP32-S3**) - `1.67.0` for all `async` examples (`embassy_hello_world`, `embassy_wait`, etc.) diff --git a/esp32c6-hal/README.md b/esp32c6-hal/README.md index 4fa998f7841..1ee4625fa66 100644 --- a/esp32c6-hal/README.md +++ b/esp32c6-hal/README.md @@ -52,9 +52,9 @@ cargo espflash --release --format direct-boot --features direct-boot --example h The ROM Bootloader will identify the firmware image built with Direct Boot support and load it appropriately from the External Flash: ```shell -ESP-ROM:esp32c6-api1-20210207 -Build:Feb 7 2021 -rst:0x1 (POWERON),boot:0xc (SPI_FAST_FLASH_BOOT) +ESP-ROM:esp32c6-20220919 +Build:Sep 19 2022 +rst:0x1 (POWERON),boot:0x6e (SPI_FAST_FLASH_BOOT) Hello world! Hello world! Hello world! diff --git a/esp32c6-hal/examples/hello_rgb.rs b/esp32c6-hal/examples/hello_rgb.rs index b5a04ac37e7..7ed5a70d2b2 100644 --- a/esp32c6-hal/examples/hello_rgb.rs +++ b/esp32c6-hal/examples/hello_rgb.rs @@ -22,7 +22,6 @@ use esp32c6_hal::{ Rtc, IO, }; -#[allow(unused_imports)] use esp_backtrace as _; use smart_leds::{ brightness, From ed59cd97c262922ea362d27b85f050adc4cc366a Mon Sep 17 00:00:00 2001 From: bjoernQ Date: Mon, 27 Feb 2023 17:24:59 +0100 Subject: [PATCH 63/64] Add I2C peripheral enable and reset --- esp-hal-common/src/system.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/esp-hal-common/src/system.rs b/esp-hal-common/src/system.rs index d58fe20a438..57d34946ce3 100644 --- a/esp-hal-common/src/system.rs +++ b/esp-hal-common/src/system.rs @@ -206,9 +206,8 @@ impl PeripheralClockControl { system.spi2_conf.modify(|_, w| w.spi2_rst_en().clear_bit()); } Peripheral::I2cExt0 => { - // FIXME - // perip_clk_en0.modify(|_, w| w.i2c_ext0_clk_en().set_bit()); - // perip_rst_en0.modify(|_, w| w.i2c_ext0_rst().clear_bit()); + system.i2c_conf.modify(|_, w| w.i2c_clk_en().set_bit()); + system.i2c_conf.modify(|_, w| w.i2c_rst_en().clear_bit()); } Peripheral::Rmt => { system.rmt_conf.modify(|_, w| w.rmt_clk_en().set_bit()); From e678120a0f3e172a1f60be6293232533e656ce5e Mon Sep 17 00:00:00 2001 From: Jesse Braham Date: Mon, 27 Feb 2023 08:57:46 -0800 Subject: [PATCH 64/64] Fix `ApbSarAdc` configuration in `system.rs` --- esp-hal-common/src/system.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/esp-hal-common/src/system.rs b/esp-hal-common/src/system.rs index 57d34946ce3..5a1892040c4 100644 --- a/esp-hal-common/src/system.rs +++ b/esp-hal-common/src/system.rs @@ -222,7 +222,12 @@ impl PeripheralClockControl { system.pwm_conf.modify(|_, w| w.pwm_rst_en().clear_bit()); } Peripheral::ApbSarAdc => { - // TODO + system + .saradc_conf + .modify(|_, w| w.saradc_reg_clk_en().set_bit()); + system + .saradc_conf + .modify(|_, w| w.saradc_reg_rst_en().clear_bit()); } Peripheral::Gdma => { system.gdma_conf.modify(|_, w| w.gdma_clk_en().set_bit());