├── .cargo └── config.toml ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE.md ├── rust-matchers.json └── workflows │ ├── changelog.yml │ ├── ci.yml │ ├── ci_nightly.yml │ ├── documentation.yml │ ├── hil.yml │ └── issue_handler.yml ├── .gitignore ├── Cargo.toml ├── LICENSE-APACHE ├── LICENSE-MIT ├── README.md ├── documentation ├── CONTRIBUTING.md └── DEVELOPER-GUIDELINES.md ├── esp-alloc ├── .clippy.toml ├── CHANGELOG.md ├── Cargo.toml ├── README.md └── src │ ├── allocators.rs │ ├── lib.rs │ └── macros.rs ├── esp-backtrace ├── CHANGELOG.md ├── Cargo.toml ├── README.md ├── build.rs └── src │ ├── lib.rs │ ├── riscv.rs │ └── xtensa.rs ├── esp-bootloader-esp-idf ├── CHANGELOG.md ├── Cargo.toml ├── README.md ├── build.rs ├── src │ ├── fmt.rs │ ├── lib.rs │ ├── non_rom.rs │ ├── ota.rs │ ├── partitions.rs │ └── rom.rs └── testdata │ ├── factory_app_two_ota.bin │ ├── factory_app_two_ota.csv │ ├── single_factory_no_ota.bin │ └── single_factory_no_ota.csv ├── esp-build ├── CHANGELOG.md ├── Cargo.toml ├── README.md └── src │ └── lib.rs ├── esp-config ├── CHANGELOG.md ├── Cargo.toml ├── README.md └── src │ ├── generate │ ├── markdown.rs │ ├── mod.rs │ ├── validator.rs │ └── value.rs │ └── lib.rs ├── esp-hal-embassy ├── .clippy.toml ├── CHANGELOG.md ├── Cargo.toml ├── MIGRATING-0.3.md ├── MIGRATING-0.4.md ├── MIGRATING-0.5.md ├── MIGRATING-0.8.0.md ├── README.md ├── build.rs └── src │ ├── executor │ ├── interrupt.rs │ ├── mod.rs │ └── thread.rs │ ├── fmt.rs │ ├── lib.rs │ ├── time_driver.rs │ └── timer_queue.rs ├── esp-hal-procmacros ├── CHANGELOG.md ├── Cargo.toml ├── README.md └── src │ ├── blocking.rs │ ├── builder.rs │ ├── embassy.rs │ ├── interrupt.rs │ ├── lib.rs │ ├── lp_core.rs │ └── ram.rs ├── esp-hal ├── .clippy.toml ├── CHANGELOG.md ├── Cargo.toml ├── MIGRATING-0.20.md ├── MIGRATING-0.21.md ├── MIGRATING-0.22.md ├── MIGRATING-0.23.md ├── MIGRATING-1.0.0-beta.0.md ├── MIGRATING-1.0.0-beta.1.md ├── README.md ├── api-baseline │ ├── esp32.json.gz │ ├── esp32c2.json.gz │ ├── esp32c3.json.gz │ ├── esp32c6.json.gz │ ├── esp32h2.json.gz │ ├── esp32s2.json.gz │ └── esp32s3.json.gz ├── build.rs ├── ld │ ├── README.md │ ├── esp32 │ │ ├── esp32.x │ │ ├── linkall.x │ │ ├── memory.x │ │ ├── rom-functions.x │ │ └── rom │ │ │ ├── additional.ld │ │ │ ├── esp32.rom.api.ld │ │ │ ├── esp32.rom.eco3.ld │ │ │ ├── esp32.rom.ld │ │ │ ├── esp32.rom.libgcc.ld │ │ │ ├── esp32.rom.redefined.ld │ │ │ ├── esp32.rom.spiflash_legacy.ld │ │ │ └── esp32.rom.syscalls.ld │ ├── esp32c2 │ │ ├── esp32c2.x │ │ ├── linkall.x │ │ ├── memory.x │ │ ├── rom-functions.x │ │ └── rom │ │ │ ├── additional.ld │ │ │ ├── esp32c2.rom.api.ld │ │ │ ├── esp32c2.rom.heap.ld │ │ │ ├── esp32c2.rom.ld │ │ │ ├── esp32c2.rom.libgcc.ld │ │ │ ├── esp32c2.rom.rvfp.ld │ │ │ └── esp32c2.rom.version.ld │ ├── esp32c3 │ │ ├── esp32c3.x │ │ ├── linkall.x │ │ ├── memory.x │ │ ├── rom-functions.x │ │ └── rom │ │ │ ├── additional.ld │ │ │ ├── esp32c3.rom.api.ld │ │ │ ├── esp32c3.rom.eco3.ld │ │ │ ├── esp32c3.rom.eco7.ld │ │ │ ├── esp32c3.rom.ld │ │ │ ├── esp32c3.rom.libgcc.ld │ │ │ └── esp32c3.rom.version.ld │ ├── esp32c6 │ │ ├── esp32c6.x │ │ ├── linkall.x │ │ ├── memory.x │ │ ├── rom-functions.x │ │ └── rom │ │ │ ├── additional.ld │ │ │ ├── esp32c6.rom.api.ld │ │ │ ├── esp32c6.rom.coexist.ld │ │ │ ├── esp32c6.rom.heap.ld │ │ │ ├── esp32c6.rom.ld │ │ │ ├── esp32c6.rom.libgcc.ld │ │ │ ├── esp32c6.rom.net80211.ld │ │ │ ├── esp32c6.rom.phy.ld │ │ │ ├── esp32c6.rom.pp.ld │ │ │ ├── esp32c6.rom.rvfp.ld │ │ │ ├── esp32c6.rom.spiflash.ld │ │ │ └── esp32c6.rom.version.ld │ ├── esp32h2 │ │ ├── esp32h2.x │ │ ├── linkall.x │ │ ├── memory.x │ │ ├── rom-functions.x │ │ └── rom │ │ │ ├── additional.ld │ │ │ ├── esp32h2.rom.api.ld │ │ │ ├── esp32h2.rom.heap.ld │ │ │ ├── esp32h2.rom.ld │ │ │ ├── esp32h2.rom.libgcc.ld │ │ │ ├── esp32h2.rom.spiflash.ld │ │ │ └── esp32h2.rom.version.ld │ ├── esp32s2 │ │ ├── esp32s2.x │ │ ├── linkall.x │ │ ├── memory.x │ │ ├── rom-functions.x │ │ └── rom │ │ │ ├── additional.ld │ │ │ ├── esp32s2.rom.api.ld │ │ │ ├── esp32s2.rom.ld │ │ │ ├── esp32s2.rom.libgcc.ld │ │ │ └── esp32s2.rom.spiflash_legacy.ld │ ├── esp32s3 │ │ ├── esp32s3.x │ │ ├── linkall.x │ │ ├── memory.x │ │ ├── rom-functions.x │ │ └── rom │ │ │ ├── additional.ld │ │ │ ├── esp32s3.rom.api.ld │ │ │ ├── esp32s3.rom.ld │ │ │ ├── esp32s3.rom.libgcc.ld │ │ │ └── esp32s3.rom.version.ld │ ├── riscv │ │ ├── asserts.x │ │ ├── debug.x │ │ └── hal-defaults.x │ ├── sections │ │ ├── dram2.x │ │ ├── fixups │ │ │ └── rtc_fast_rwdata_dummy.x │ │ ├── metadata.x │ │ ├── rodata.x │ │ ├── rodata_desc.x │ │ ├── rtc_fast.x │ │ ├── rtc_slow.x │ │ ├── rwdata.x │ │ ├── rwtext.x │ │ ├── stack.x │ │ └── text.x │ └── xtensa │ │ └── hal-defaults.x └── src │ ├── aes │ ├── esp32.rs │ ├── esp32cX.rs │ ├── esp32s2.rs │ ├── esp32s3.rs │ └── mod.rs │ ├── analog │ ├── adc │ │ ├── calibration │ │ │ ├── basic.rs │ │ │ ├── curve.rs │ │ │ ├── line.rs │ │ │ └── mod.rs │ │ ├── esp32.rs │ │ ├── mod.rs │ │ ├── riscv.rs │ │ └── xtensa.rs │ ├── dac.rs │ └── mod.rs │ ├── assist_debug.rs │ ├── asynch.rs │ ├── clock │ ├── clocks_ll │ │ ├── esp32.rs │ │ ├── esp32c2.rs │ │ ├── esp32c3.rs │ │ ├── esp32c6.rs │ │ ├── esp32h2.rs │ │ ├── esp32s2.rs │ │ └── esp32s3.rs │ └── mod.rs │ ├── config.rs │ ├── debugger.rs │ ├── delay.rs │ ├── dma │ ├── buffers.rs │ ├── gdma.rs │ ├── m2m.rs │ ├── mod.rs │ └── pdma │ │ ├── copy.rs │ │ ├── crypto.rs │ │ ├── i2s.rs │ │ ├── mod.rs │ │ └── spi.rs │ ├── ecc.rs │ ├── etm.rs │ ├── fmt.rs │ ├── gpio │ ├── asynch.rs │ ├── embedded_hal_impls.rs │ ├── etm.rs │ ├── interconnect.rs │ ├── interrupt.rs │ ├── lp_io.rs │ ├── mod.rs │ ├── placeholder.rs │ └── rtc_io.rs │ ├── hmac.rs │ ├── i2c │ ├── lp_i2c.rs │ ├── master │ │ └── mod.rs │ └── mod.rs │ ├── i2s │ ├── master.rs │ ├── mod.rs │ └── parallel.rs │ ├── interrupt │ ├── mod.rs │ ├── riscv.rs │ ├── software.rs │ └── xtensa.rs │ ├── lcd_cam │ ├── cam.rs │ ├── lcd │ │ ├── dpi.rs │ │ ├── i8080.rs │ │ └── mod.rs │ └── mod.rs │ ├── ledc │ ├── channel.rs │ ├── mod.rs │ └── timer.rs │ ├── lib.rs │ ├── macros.rs │ ├── mcpwm │ ├── mod.rs │ ├── operator.rs │ └── timer.rs │ ├── otg_fs.rs │ ├── parl_io.rs │ ├── pcnt │ ├── channel.rs │ ├── mod.rs │ └── unit.rs │ ├── peripheral.rs │ ├── reg_access.rs │ ├── rmt.rs │ ├── rng.rs │ ├── rom │ ├── crc.rs │ ├── md5.rs │ ├── mod.rs │ └── regi2c.rs │ ├── rsa │ ├── esp32.rs │ ├── esp32cX.rs │ ├── esp32sX.rs │ └── mod.rs │ ├── rtc_cntl │ ├── mod.rs │ ├── rtc │ │ ├── esp32.rs │ │ ├── esp32c2.rs │ │ ├── esp32c3.rs │ │ ├── esp32c6.rs │ │ ├── esp32h2.rs │ │ ├── esp32s2.rs │ │ └── esp32s3.rs │ └── sleep │ │ ├── esp32.rs │ │ ├── esp32c2.rs │ │ ├── esp32c3.rs │ │ ├── esp32c6.rs │ │ ├── esp32s2.rs │ │ ├── esp32s3.rs │ │ └── mod.rs │ ├── sha.rs │ ├── soc │ ├── efuse_field.rs │ ├── esp32 │ │ ├── cpu_control.rs │ │ ├── efuse │ │ │ ├── fields.rs │ │ │ └── mod.rs │ │ ├── gpio.rs │ │ ├── mod.rs │ │ ├── peripherals.rs │ │ ├── psram.rs │ │ ├── regi2c.rs │ │ └── trng.rs │ ├── esp32c2 │ │ ├── efuse │ │ │ ├── fields.rs │ │ │ └── mod.rs │ │ ├── gpio.rs │ │ ├── mod.rs │ │ ├── peripherals.rs │ │ ├── regi2c.rs │ │ └── trng.rs │ ├── esp32c3 │ │ ├── efuse │ │ │ ├── fields.rs │ │ │ └── mod.rs │ │ ├── gpio.rs │ │ ├── mod.rs │ │ ├── peripherals.rs │ │ ├── regi2c.rs │ │ └── trng.rs │ ├── esp32c6 │ │ ├── efuse │ │ │ ├── fields.rs │ │ │ └── mod.rs │ │ ├── gpio.rs │ │ ├── lp_core.rs │ │ ├── mod.rs │ │ ├── peripherals.rs │ │ ├── regi2c.rs │ │ └── trng.rs │ ├── esp32h2 │ │ ├── efuse │ │ │ ├── fields.rs │ │ │ └── mod.rs │ │ ├── gpio.rs │ │ ├── mod.rs │ │ ├── peripherals.rs │ │ ├── regi2c.rs │ │ └── trng.rs │ ├── esp32s2 │ │ ├── efuse │ │ │ ├── fields.rs │ │ │ └── mod.rs │ │ ├── gpio.rs │ │ ├── mod.rs │ │ ├── peripherals.rs │ │ ├── psram.rs │ │ ├── regi2c.rs │ │ ├── trng.rs │ │ └── ulp_core.rs │ ├── esp32s3 │ │ ├── cpu_control.rs │ │ ├── efuse │ │ │ ├── fields.rs │ │ │ └── mod.rs │ │ ├── gpio.rs │ │ ├── mod.rs │ │ ├── peripherals.rs │ │ ├── psram.rs │ │ ├── regi2c.rs │ │ ├── trng.rs │ │ └── ulp_core.rs │ ├── mod.rs │ └── psram_common.rs │ ├── spi │ ├── master.rs │ ├── mod.rs │ └── slave.rs │ ├── sync.rs │ ├── system.rs │ ├── time.rs │ ├── timer │ ├── mod.rs │ ├── systimer.rs │ └── timg.rs │ ├── touch.rs │ ├── trace.rs │ ├── tsens.rs │ ├── twai │ ├── filter.rs │ └── mod.rs │ ├── uart.rs │ └── usb_serial_jtag.rs ├── esp-ieee802154 ├── CHANGELOG.md ├── Cargo.toml ├── MIGRATING-0.4.md ├── MIGRATING-0.7.0.md ├── README.md ├── build.rs └── src │ ├── fmt.rs │ ├── frame.rs │ ├── hal.rs │ ├── lib.rs │ ├── pib.rs │ └── raw.rs ├── esp-lp-hal ├── .cargo │ └── config.toml ├── CHANGELOG.md ├── Cargo.toml ├── README.md ├── build.rs ├── examples │ ├── blinky.rs │ ├── i2c.rs │ └── uart.rs ├── ld │ ├── link-lp.x │ └── link-ulp.x └── src │ ├── delay.rs │ ├── gpio.rs │ ├── i2c.rs │ ├── lib.rs │ └── uart.rs ├── esp-metadata ├── CHANGELOG.md ├── Cargo.toml ├── README.md ├── devices │ ├── esp32.toml │ ├── esp32c2.toml │ ├── esp32c3.toml │ ├── esp32c6.toml │ ├── esp32h2.toml │ ├── esp32p4.toml │ ├── esp32s2.toml │ └── esp32s3.toml └── src │ ├── generate_cfg.rs │ └── lib.rs ├── esp-println ├── .cargo │ └── config.toml ├── .clippy.toml ├── CHANGELOG.md ├── Cargo.toml ├── README.md ├── build.rs └── src │ ├── defmt.rs │ ├── lib.rs │ └── logger.rs ├── esp-riscv-rt ├── CHANGELOG.md ├── Cargo.toml ├── README.md └── src │ └── lib.rs ├── esp-storage ├── .clippy.toml ├── CHANGELOG.md ├── Cargo.toml ├── README.md ├── build.rs └── src │ ├── common.rs │ ├── esp32.rs │ ├── esp32c2.rs │ ├── esp32c3.rs │ ├── esp32c6.rs │ ├── esp32h2.rs │ ├── esp32s2.rs │ ├── esp32s3.rs │ ├── lib.rs │ ├── ll.rs │ ├── nor_flash.rs │ ├── storage.rs │ └── stub.rs ├── esp-wifi ├── .clippy.toml ├── CHANGELOG.md ├── Cargo.toml ├── MIGRATING-0.10.md ├── MIGRATING-0.11.md ├── MIGRATING-0.13.md ├── MIGRATING-0.14.0.md ├── MIGRATING-0.9.md ├── README.md ├── build.rs └── src │ ├── ble │ ├── btdm.rs │ ├── controller │ │ └── mod.rs │ ├── mod.rs │ ├── npl.rs │ ├── os_adapter_esp32.rs │ ├── os_adapter_esp32c2.rs │ ├── os_adapter_esp32c3.rs │ ├── os_adapter_esp32c6.rs │ ├── os_adapter_esp32h2.rs │ └── os_adapter_esp32s3.rs │ ├── common_adapter │ ├── common_adapter_esp32.rs │ ├── common_adapter_esp32c2.rs │ ├── common_adapter_esp32c3.rs │ ├── common_adapter_esp32c6.rs │ ├── common_adapter_esp32h2.rs │ ├── common_adapter_esp32s2.rs │ ├── common_adapter_esp32s3.rs │ ├── mod.rs │ ├── phy_init_data_esp32.rs │ ├── phy_init_data_esp32c2.rs │ ├── phy_init_data_esp32c3.rs │ ├── phy_init_data_esp32c6.rs │ ├── phy_init_data_esp32h2.rs │ ├── phy_init_data_esp32s2.rs │ └── phy_init_data_esp32s3.rs │ ├── compat │ ├── common.rs │ ├── malloc.rs │ ├── misc.rs │ ├── mod.rs │ └── timer_compat.rs │ ├── config.rs │ ├── esp_now │ └── mod.rs │ ├── fmt.rs │ ├── lib.rs │ ├── memory_fence.rs │ ├── preempt.rs │ ├── preempt_builtin │ ├── mod.rs │ ├── preempt_riscv.rs │ ├── preempt_xtensa.rs │ └── timer │ │ ├── mod.rs │ │ ├── riscv.rs │ │ └── xtensa.rs │ ├── radio │ ├── mod.rs │ ├── radio_esp32.rs │ ├── radio_esp32c2.rs │ ├── radio_esp32c3.rs │ ├── radio_esp32c6.rs │ ├── radio_esp32h2.rs │ ├── radio_esp32s2.rs │ └── radio_esp32s3.rs │ ├── tasks.rs │ ├── time.rs │ └── wifi │ ├── event.rs │ ├── internal.rs │ ├── mod.rs │ ├── os_adapter.rs │ ├── os_adapter_esp32.rs │ ├── os_adapter_esp32c2.rs │ ├── os_adapter_esp32c3.rs │ ├── os_adapter_esp32c6.rs │ ├── os_adapter_esp32h2.rs │ ├── os_adapter_esp32s2.rs │ ├── os_adapter_esp32s3.rs │ └── state.rs ├── examples ├── .cargo │ └── config.toml ├── Cargo.toml ├── README.md ├── build.rs ├── rustfmt.toml └── src │ └── bin │ ├── debug_assist.rs │ ├── dma_extmem2mem.rs │ ├── dma_mem2mem.rs │ ├── embassy_hello_world.rs │ ├── embassy_multicore.rs │ ├── embassy_multicore_interrupt.rs │ ├── embassy_multiprio.rs │ ├── embassy_rmt_rx.rs │ ├── embassy_rmt_tx.rs │ ├── embassy_serial.rs │ ├── embassy_spi.rs │ ├── embassy_usb_serial.rs │ ├── embassy_usb_serial_jtag.rs │ ├── etm_timer.rs │ ├── flash_read_write.rs │ ├── gpio_interrupt.rs │ ├── hmac.rs │ ├── ieee802154_receive_all_frames.rs │ ├── ieee802154_receive_frame.rs │ ├── ieee802154_send_broadcast_frame.rs │ ├── ieee802154_send_frame.rs │ ├── ieee802154_sniffer.rs │ ├── lp_core_basic.rs │ ├── spi_loopback.rs │ ├── spi_loopback_dma_psram.rs │ ├── spi_slave_dma.rs │ ├── touch.rs │ ├── twai.rs │ ├── usb_serial.rs │ ├── wifi_80211_tx.rs │ ├── wifi_access_point.rs │ ├── wifi_access_point_with_sta.rs │ ├── wifi_bench.rs │ ├── wifi_ble.rs │ ├── wifi_coex.rs │ ├── wifi_csi.rs │ ├── wifi_dhcp.rs │ ├── wifi_embassy_access_point.rs │ ├── wifi_embassy_access_point_with_sta.rs │ ├── wifi_embassy_bench.rs │ ├── wifi_embassy_ble.rs │ ├── wifi_embassy_dhcp.rs │ ├── wifi_embassy_esp_now.rs │ ├── wifi_embassy_esp_now_duplex.rs │ ├── wifi_esp_now.rs │ ├── wifi_sniffer.rs │ └── wifi_static_ip.rs ├── extras ├── bench-server │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── esp-wifishark │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs └── ieee802154-sniffer │ ├── Cargo.toml │ ├── README.md │ └── src │ └── main.rs ├── hil-test ├── .cargo │ └── config.toml ├── Cargo.toml ├── README.md ├── build.rs ├── src │ └── lib.rs └── tests │ ├── aes.rs │ ├── aes_dma.rs │ ├── alloc_psram.rs │ ├── clock_monitor.rs │ ├── crc.rs │ ├── critical_section.rs │ ├── delay.rs │ ├── delay_async.rs │ ├── dma_macros.rs │ ├── dma_mem2mem.rs │ ├── ecc.rs │ ├── embassy_interrupt_executor.rs │ ├── embassy_interrupt_spi_dma.rs │ ├── embassy_timers_executors.rs │ ├── esp_wifi_ble_controller.rs │ ├── esp_wifi_floats.rs │ ├── esp_wifi_init.rs │ ├── flip_link.rs │ ├── get_time.rs │ ├── gpio.rs │ ├── gpio_custom_handler.rs │ ├── i2c.rs │ ├── i2s.rs │ ├── i2s_parallel.rs │ ├── init.rs │ ├── interrupt.rs │ ├── lcd_cam.rs │ ├── lcd_cam_i8080.rs │ ├── lcd_cam_i8080_async.rs │ ├── parl_io.rs │ ├── parl_io_tx.rs │ ├── parl_io_tx_async.rs │ ├── pcnt.rs │ ├── qspi.rs │ ├── rmt.rs │ ├── rsa.rs │ ├── rsa_async.rs │ ├── sha.rs │ ├── spi_full_duplex.rs │ ├── spi_half_duplex_read.rs │ ├── spi_half_duplex_write.rs │ ├── spi_half_duplex_write_psram.rs │ ├── spi_slave.rs │ ├── storage_read_app_desc.rs │ ├── systimer.rs │ ├── twai.rs │ ├── uart.rs │ ├── uart_async.rs │ ├── uart_regression.rs │ ├── uart_tx_rx_async.rs │ └── usb_serial_jtag.rs ├── qa-test ├── .cargo │ └── config.toml ├── Cargo.toml ├── README.md ├── build.rs └── src │ └── bin │ ├── embassy_adc.rs │ ├── embassy_adc_async_abstraction.rs │ ├── embassy_executor_benchmark.rs │ ├── embassy_i2c.rs │ ├── embassy_i2c_bmp180_calibration_data.rs │ ├── embassy_i2s_read.rs │ ├── embassy_i2s_sound.rs │ ├── gpio_interrupt_latency.rs │ ├── i2c_bmp180_calibration_data.rs │ ├── i2c_display.rs │ ├── lcd_cam_ov2640.rs │ ├── lcd_dpi.rs │ ├── lcd_i8080.rs │ ├── psram.rs │ ├── qspi_flash.rs │ ├── ram.rs │ ├── sleep_timer.rs │ ├── sleep_timer_ext0.rs │ ├── sleep_timer_ext1.rs │ ├── sleep_timer_lpio.rs │ ├── sleep_timer_rtcio.rs │ ├── spi_halfduplex_read_manufacturer_id.rs │ └── temperature_sensor.rs ├── resources ├── .prettierrc.json ├── esp-rs.svg ├── index.html.jinja ├── package_index.html.jinja └── select.html.jinja ├── rustfmt.toml ├── xtask ├── Cargo.toml ├── README.md └── src │ ├── cargo.rs │ ├── changelog.rs │ ├── commands │ ├── build.rs │ ├── check_changelog.rs │ ├── mod.rs │ ├── release.rs │ ├── release │ │ ├── bump_version.rs │ │ ├── execute_plan.rs │ │ ├── plan.rs │ │ ├── post_release.rs │ │ ├── publish.rs │ │ ├── publish_plan.rs │ │ ├── semver_check.rs │ │ └── tag_releases.rs │ └── run.rs │ ├── documentation.rs │ ├── firmware.rs │ ├── git.rs │ ├── lib.rs │ ├── main.rs │ └── semver_check.rs ├── xtensa-lx-rt-proc-macros ├── Cargo.toml └── src │ └── lib.rs ├── xtensa-lx-rt ├── CHANGELOG.md ├── Cargo.toml ├── README.md ├── build.rs ├── config │ ├── xtensa_esp32.toml │ ├── xtensa_esp32s2.toml │ └── xtensa_esp32s3.toml ├── exception-esp32.x.jinja ├── interrupt_level_masks.rs.jinja ├── src │ ├── exception.rs │ ├── exception │ │ ├── asm.rs │ │ └── context.rs │ ├── interrupt.rs │ └── lib.rs └── xtensa.in.x └── xtensa-lx ├── CHANGELOG.md ├── Cargo.toml ├── README.md ├── build.rs └── src ├── interrupt.rs ├── lib.rs ├── macros.rs └── timer.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [alias] 2 | xtask = "run --package xtask --" 3 | xdoc = "run --package xtask --features=deploy-docs,preview-docs --" 4 | xfmt = "xtask fmt-packages" 5 | qa = "xtask run example qa-test" 6 | xcheck = "run --package xtask --features=semver-checks --" 7 | xrelease = "run --package xtask --features=release -- release" 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | CHANGELOG.md merge=union 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: ["bug", "status:needs-attention"] 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Bug description 11 | 12 | 13 | 14 | ## To Reproduce 15 | 16 | 17 | 1. ... 18 | 2. ... 19 | 20 | 21 | 22 | 23 | 24 | ## Expected behavior 25 | 26 | 27 | 28 | ## Environment 29 | 30 | - Target device: [e.g. ESP32-S3] 31 | - Crate name and version: [e.g. esp-hal 0.20.0] 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | contact_links: 3 | - name: Ask questions in Matrix channel (Recommended) 4 | url: https://matrix.to/#/#esp-rs:matrix.org 5 | about: Ask any questions directly in our Matrix channel. 6 | - name: Ask questions in GitHub Discussions 7 | url: https://github.com/esp-rs/esp-hal/discussions/new 8 | about: Post your questions and engage in discussions via GitHub. 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: ["enhancement", "status:needs-attention"] 6 | assignees: '' 7 | 8 | --- 9 | 10 | ## Motivations 11 | 12 | 13 | 14 | ## Solution 15 | 16 | 17 | 18 | ## Alternatives 19 | 20 | 21 | 22 | ## Additional context 23 | 24 | 25 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Thank you for your contribution! 2 | 3 | We appreciate the time and effort you've put into this pull request. 4 | To help us review it efficiently, please ensure you've gone through the following checklist: 5 | 6 | ### Submission Checklist 📝 7 | - [ ] I have updated existing examples or added new ones (if applicable). 8 | - [ ] I have used `cargo xtask fmt-packages` command to ensure that all changed code is formatted correctly. 9 | - [ ] My changes were added to the [`CHANGELOG.md`](https://github.com/esp-rs/esp-hal/blob/main/esp-hal/CHANGELOG.md) in the **_proper_** section. 10 | - [ ] I have added necessary changes to user code to the [Migration Guide](https://github.com/esp-rs/esp-hal/blob/main/esp-hal/MIGRATING-0.21.md). 11 | - [ ] My changes are in accordance to the [esp-rs developer guidelines](https://github.com/esp-rs/esp-hal/blob/main/documentation/DEVELOPER-GUIDELINES.md) 12 | 13 | #### Extra: 14 | - [ ] I have read the [CONTRIBUTING.md guide](https://github.com/esp-rs/esp-hal/blob/main/documentation/CONTRIBUTING.md) and followed its instructions. 15 | 16 | ### Pull Request Details 📖 17 | 18 | #### Description 19 | Please provide a clear and concise description of your changes, including the motivation behind these changes. The context is crucial for the reviewers. 20 | 21 | #### Testing 22 | Describe how you tested your changes. 23 | -------------------------------------------------------------------------------- /.github/rust-matchers.json: -------------------------------------------------------------------------------- 1 | { 2 | "problemMatcher": [ 3 | { 4 | "owner": "rust-compiler", 5 | "pattern": [ 6 | { 7 | "regexp": "^(?:\\x1B\\[[0-9;]*[a-zA-Z])*(warning|warn|error)(\\[(\\S*)\\])?(?:\\x1B\\[[0-9;]*[a-zA-Z])*: (.*?)(?:\\x1B\\[[0-9;]*[a-zA-Z])*$", 8 | "severity": 1, 9 | "message": 4, 10 | "code": 3 11 | }, 12 | { 13 | "regexp": "^(?:\\x1B\\[[0-9;]*[a-zA-Z])*\\s+(?:\\x1B\\[[0-9;]*[a-zA-Z])*-->\\s(?:\\x1B\\[[0-9;]*[a-zA-Z])*(\\S+):(\\d+):(\\d+)(?:\\x1B\\[[0-9;]*[a-zA-Z])*$", 14 | "file": 1, 15 | "line": 2, 16 | "column": 3 17 | } 18 | ] 19 | }, 20 | { 21 | "owner": "rust-formatter", 22 | "pattern": [ 23 | { 24 | "regexp": "^(Diff in (\\S+)) at line (\\d+):", 25 | "message": 1, 26 | "file": 2, 27 | "line": 3 28 | } 29 | ] 30 | }, 31 | { 32 | "owner": "rust-panic", 33 | "pattern": [ 34 | { 35 | "regexp": "^.*panicked\\s+at\\s+'(.*)',\\s+(.*):(\\d+):(\\d+)$", 36 | "message": 1, 37 | "file": 2, 38 | "line": 3, 39 | "column": 4 40 | } 41 | ] 42 | } 43 | ] 44 | } -------------------------------------------------------------------------------- /.github/workflows/ci_nightly.yml: -------------------------------------------------------------------------------- 1 | name: CI - nightly 2 | 3 | on: 4 | workflow_dispatch: 5 | schedule: 6 | - cron: "0 0 * * *" 7 | 8 | env: 9 | CARGO_TERM_COLOR: always 10 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 11 | RUSTDOCFLAGS: -Dwarnings 12 | DEFMT_LOG: trace 13 | 14 | jobs: 15 | esp-hal-nightly: 16 | name: esp-hal | nightly (${{ matrix.device }}) 17 | runs-on: ubuntu-latest 18 | env: 19 | CI: 1 20 | SSID: SSID 21 | PASSWORD: PASSWORD 22 | STATIC_IP: 1.1.1.1 23 | GATEWAY_IP: 1.1.1.1 24 | HOST_IP: 1.1.1.1 25 | 26 | strategy: 27 | fail-fast: false 28 | matrix: 29 | device: [ "esp32c2", "esp32c3", "esp32c6", "esp32h2" ] 30 | steps: 31 | - uses: actions/checkout@v4 32 | 33 | # Install the Rust nightly toolchain for RISC-V devices: 34 | - uses: dtolnay/rust-toolchain@v1 35 | with: 36 | target: riscv32imc-unknown-none-elf,riscv32imac-unknown-none-elf 37 | toolchain: nightly 38 | components: rust-src, clippy, rustfmt 39 | 40 | - uses: Swatinem/rust-cache@v2 41 | 42 | - name: Build and Check 43 | shell: bash 44 | run: cargo +nightly xtask ci ${{ matrix.device }} 45 | 46 | - if: failure() 47 | name: Create or Update GitHub Issue 48 | env: 49 | GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} 50 | run: | 51 | sudo apt-get install gh -y 52 | ISSUE_NAME=$(gh issue list --state open --search "Nightly CI Failure in:title" --json number --jq '.[0].number') 53 | 54 | if [[ -z "$ISSUE_NAME" ]]; 55 | then 56 | gh issue create \ 57 | --title "Nightly CI Failure" \ 58 | --body "Nightly CI Workflow Failed! [View the failed job](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})." \ 59 | --label "ci-nightly" 60 | fi 61 | -------------------------------------------------------------------------------- /.github/workflows/issue_handler.yml: -------------------------------------------------------------------------------- 1 | name: Add new issues to project 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | 8 | jobs: 9 | add-to-project: 10 | name: Add issue to project 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/add-to-project@v0.5.0 14 | with: 15 | project-url: https://github.com/orgs/esp-rs/projects/2 16 | github-token: ${{ secrets.PAT }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | debug/ 4 | target/ 5 | 6 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 7 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 8 | Cargo.lock 9 | 10 | # These are backup files generated by rustfmt 11 | **/*.rs.bk 12 | 13 | # MSVC Windows builds of rustc generate these, which store debugging information 14 | *.pdb 15 | 16 | # Wokwi related files 17 | diagram.json 18 | wokwi.toml 19 | 20 | # We'll ignore VS Code settings (at least for now...) 21 | **/.vscode/settings.json 22 | 23 | # Ignore generated documentation 24 | docs/ 25 | 26 | # Ignore the generated release plan 27 | release_plan.jsonc 28 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | members = ["xtask"] 4 | exclude = [ 5 | "esp-alloc", 6 | "esp-backtrace", 7 | "esp-bootloader-esp-idf", 8 | "esp-build", 9 | "esp-config", 10 | "esp-hal", 11 | "esp-hal-embassy", 12 | "esp-hal-procmacros", 13 | "esp-ieee802154", 14 | "esp-lp-hal", 15 | "esp-metadata", 16 | "esp-println", 17 | "esp-riscv-rt", 18 | "esp-wifi", 19 | "esp-storage", 20 | "examples", 21 | "extras/bench-server", 22 | "extras/esp-wifishark", 23 | "extras/ieee802154-sniffer", 24 | "hil-test", 25 | "qa-test", 26 | "xtensa-lx", 27 | "xtensa-lx-rt", 28 | "xtensa-lx-rt-proc-macros", 29 | ] 30 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright 2021 esp-rs 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /esp-alloc/.clippy.toml: -------------------------------------------------------------------------------- 1 | avoid-breaking-exported-api = false 2 | -------------------------------------------------------------------------------- /esp-alloc/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ### Added 11 | 12 | 13 | ### Changed 14 | 15 | 16 | ### Fixed 17 | 18 | 19 | ### Removed 20 | 21 | 22 | ## [v0.8.0] - 2025-06-03 23 | 24 | ### Added 25 | 26 | - `allocator_api2` to support allocator APIs on stable Rust. (#3318, #3487) 27 | - `AnyMemory`, `InternalMemory`, `ExternalMemory` allocators. (#3318) 28 | - Removed the `Unused` section for `stats()` to make the output cleaner (#3486) 29 | 30 | ### Changed 31 | 32 | - Bump Rust edition to 2024, bump MSRV to 1.86. (#3391, #3560) 33 | - Update `defmt` to 1.0 (#3416) 34 | 35 | ## [0.7.0] - 2025-02-24 36 | 37 | ### Added 38 | 39 | - `esp_alloc::heap_allocator!` now accepts attributes, e.g., `esp_alloc::heap_allocator!(#[link_section = ".dram2_uninit"] size: 64000)` (#3133) 40 | 41 | ### Changed 42 | 43 | - `esp_alloc::heap_allocator!` syntax has been changed to `esp_alloc::heap_allocator!(size: 64000)` (#3135) 44 | 45 | ## 0.6.0 - 2025-01-15 46 | 47 | ### Added 48 | 49 | - `esp_alloc::HEAP.stats()` can now be used to get heap usage informations (#2137) 50 | 51 | ### Changed 52 | 53 | - Bump MSRV to 1.84 (#2951) 54 | 55 | ## 0.5.0 - 2024-10-10 56 | 57 | ### Changed 58 | 59 | - a global allocator is created in esp-alloc, now you need to add individual memory regions (up to 3) to the allocator (#2099) 60 | 61 | ## 0.4.0 - 2024-06-04 62 | 63 | ## 0.3.0 - 2023-04-25 64 | 65 | ## 0.2.1 - 2023-04-21 66 | 67 | ## 0.2.0 - 2023-02-22 68 | 69 | ## 0.1.0 - 2022-07-25 70 | 71 | [0.7.0]: https://github.com/esp-rs/esp-hal/releases/tag/esp-alloc-v0.7.0 72 | [v0.8.0]: https://github.com/esp-rs/esp-hal/compare/esp-alloc-v0.7.0...esp-alloc-v0.8.0 73 | [Unreleased]: https://github.com/esp-rs/esp-hal/compare/esp-alloc-v0.8.0...HEAD 74 | -------------------------------------------------------------------------------- /esp-alloc/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "esp-alloc" 3 | version = "0.8.0" 4 | edition = "2024" 5 | rust-version = "1.86.0" 6 | description = "A heap allocator for Espressif devices" 7 | documentation = "https://docs.espressif.com/projects/rust/esp-alloc/latest/" 8 | keywords = ["allocator", "embedded", "esp32", "espressif", "memory"] 9 | categories = ["embedded", "memory-management", "no-std"] 10 | repository = "https://github.com/esp-rs/esp-hal" 11 | license = "MIT OR Apache-2.0" 12 | 13 | [package.metadata.docs.rs] 14 | default-target = "riscv32imc-unknown-none-elf" 15 | features = ["nightly"] 16 | 17 | [lib] 18 | bench = false 19 | test = false 20 | 21 | [dependencies] 22 | allocator-api2 = { version = "0.3.0", default-features = false } 23 | defmt = { version = "1.0.1", optional = true } 24 | cfg-if = "1.0.0" 25 | critical-section = "1.2.0" 26 | enumset = "1.1.6" 27 | linked_list_allocator = { version = "0.10.5", default-features = false, features = ["const_mut_refs"] } 28 | document-features = "0.2.11" 29 | 30 | [features] 31 | default = [] 32 | 33 | ## Enable nightly rustc-only features, like `feature(allocator_api)`. 34 | nightly = [] 35 | 36 | ## Implement `defmt::Format` on certain types. 37 | defmt = ["dep:defmt", "enumset/defmt"] 38 | 39 | ## Enable this feature if you want to keep stats about the internal heap usage such as: 40 | ## - Max memory usage since initialization of the heap 41 | ## - Total allocated memory since initialization of the heap 42 | ## - Total freed memory since initialization of the heap 43 | ## 44 | ## ⚠️ Note: Enabling this feature will require extra computation every time alloc/dealloc is called. 45 | internal-heap-stats = [] 46 | -------------------------------------------------------------------------------- /esp-alloc/README.md: -------------------------------------------------------------------------------- 1 | # esp-alloc 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/esp-alloc?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-alloc) 4 | [![docs.rs](https://img.shields.io/docsrs/esp-alloc?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.espressif.com/projects/rust/esp-alloc/latest/) 5 | ![MSRV](https://img.shields.io/badge/MSRV-1.84-blue?labelColor=1C2C2E&style=flat-square) 6 | ![Crates.io](https://img.shields.io/crates/l/esp-alloc?labelColor=1C2C2E&style=flat-square) 7 | [![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) 8 | 9 | A simple `no_std` heap allocator for RISC-V and Xtensa processors from Espressif. Supports all currently available ESP32 devices. 10 | 11 | **NOTE:** using this as your global allocator requires using Rust 1.68 or greater, or the `nightly` release channel. 12 | 13 | ## Minimum Supported Rust Version (MSRV) 14 | 15 | This crate is guaranteed to compile when using the latest stable Rust version at the time of the crate's release. It _might_ compile with older versions, but that may change in any new release, including patches. 16 | 17 | ## License 18 | 19 | Licensed under either of: 20 | 21 | - Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 22 | - MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) 23 | 24 | at your option. 25 | 26 | ### Contribution 27 | 28 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in 29 | the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without 30 | any additional terms or conditions. 31 | -------------------------------------------------------------------------------- /esp-backtrace/build.rs: -------------------------------------------------------------------------------- 1 | use esp_build::assert_unique_used_features; 2 | use esp_config::{ConfigOption, generate_config}; 3 | 4 | fn main() { 5 | // Ensure that only a single chip is specified: 6 | let _ = esp_metadata::Chip::from_cargo_feature().unwrap(); 7 | 8 | // Ensure that exactly a backend is selected: 9 | assert_unique_used_features!("defmt", "println"); 10 | 11 | if cfg!(feature = "custom-halt") && cfg!(feature = "halt-cores") { 12 | panic!("Only one of `custom-halt` and `halt-cores` can be enabled"); 13 | } 14 | 15 | // emit config 16 | generate_config( 17 | "esp_backtrace", 18 | &[ConfigOption::new( 19 | "backtrace-frames", 20 | "The maximum number of frames that will be printed in a backtrace", 21 | 10, 22 | )], 23 | true, 24 | true, 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /esp-bootloader-esp-idf/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ### Added 11 | 12 | 13 | ### Changed 14 | 15 | 16 | ### Fixed 17 | 18 | 19 | ### Removed 20 | 21 | 22 | ## [v0.1.0] - 2025-06-03 23 | 24 | ### Added 25 | 26 | - Support ESP-IDF app descriptor (#3281) 27 | - Support reading partition tables and conveniently read/write partition content (#3316) 28 | - OTA-DATA partition support (#3354) 29 | 30 | ### Changed 31 | 32 | - Bump Rust edition to 2024, bump MSRV to 1.86. (#3391, #3560) 33 | - Update `defmt` to 1.0 (#3416) 34 | 35 | [v0.1.0]: https://github.com/esp-rs/esp-hal/releases/tag/esp-bootloader-esp-idf-v0.1.0 36 | [Unreleased]: https://github.com/esp-rs/esp-hal/compare/esp-bootloader-esp-idf-v0.1.0...HEAD 37 | -------------------------------------------------------------------------------- /esp-bootloader-esp-idf/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "esp-bootloader-esp-idf" 3 | version = "0.1.0" 4 | edition = "2024" 5 | rust-version = "1.86.0" 6 | description = "Functionality related to the esp-idf bootloader" 7 | documentation = "https://docs.espressif.com/projects/rust/esp-bootloader-esp-idf/latest/" 8 | keywords = ["esp32", "espressif", "no-std"] 9 | categories = ["embedded", "hardware-support", "no-std"] 10 | repository = "https://github.com/esp-rs/esp-hal" 11 | license = "MIT OR Apache-2.0" 12 | 13 | [package.metadata.docs.rs] 14 | default-target = "riscv32imac-unknown-none-elf" 15 | 16 | [lib] 17 | bench = false 18 | test = true 19 | 20 | [dependencies] 21 | defmt = { version = "1.0.1", optional = true } 22 | document-features = "0.2.11" 23 | esp-config = { version = "0.4.0", path = "../esp-config" } 24 | embedded-storage = "0.3.1" 25 | log = { version = "0.4.26", optional = true } 26 | strum = { version = "0.27.1", default-features = false, features = ["derive"] } 27 | 28 | crc = { version = "3.0.0", optional = true } 29 | md-5 = { version = "0.10.6", default-features = false, optional = true } 30 | 31 | [build-dependencies] 32 | chrono = { version = "0.4.20", default-features = false, features = ["clock"] } 33 | esp-config = { version = "0.4.0", path = "../esp-config", features = ["build"] } 34 | 35 | [features] 36 | default = ["validation"] 37 | 38 | ## Enable MD5 validation of the partition table. 39 | validation = ["dep:md-5"] 40 | 41 | ## Enable support for the `log` crate 42 | log = ["dep:log"] 43 | 44 | ## Enable support for `defmt` 45 | defmt = ["dep:defmt"] 46 | 47 | # Replace ROM functions with pure Rust implementations, needed for tests. 48 | std = ["dep:crc"] 49 | -------------------------------------------------------------------------------- /esp-bootloader-esp-idf/README.md: -------------------------------------------------------------------------------- 1 | # esp-bootloader-esp-idf 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/esp-bootloader-esp-idf?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-bootloader-esp-idf) 4 | [![docs.rs](https://img.shields.io/docsrs/esp-bootloader-esp-idf?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.espressif.com/projects/rust/esp-bootloader-esp-idf/latest/) 5 | ![MSRV](https://img.shields.io/badge/MSRV-1.86-blue?labelColor=1C2C2E&style=flat-square) 6 | ![Crates.io](https://img.shields.io/crates/l/esp-bootloader-esp-idf?labelColor=1C2C2E&style=flat-square) 7 | [![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) 8 | 9 | This offers additional support for the ESP-IDF 2nd stage bootloader. 10 | 11 | ## Minimum Supported Rust Version (MSRV) 12 | 13 | This crate is guaranteed to compile when using the latest stable Rust version at the time of the crate's release. It _might_ compile with older versions, but that may change in any new release, including patches. 14 | 15 | ## License 16 | 17 | Licensed under either of 18 | 19 | - Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or 20 | http://www.apache.org/licenses/LICENSE-2.0) 21 | - MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) 22 | 23 | at your option. 24 | 25 | ### Contribution 26 | 27 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the 28 | work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any 29 | additional terms or conditions. 30 | -------------------------------------------------------------------------------- /esp-bootloader-esp-idf/src/non_rom.rs: -------------------------------------------------------------------------------- 1 | use crc::{Algorithm, Crc}; 2 | 3 | static ALGO_CRC32_NORMAL: Algorithm = Algorithm { 4 | width: 32, 5 | poly: 0x04c11db7, 6 | init: 0, 7 | refin: true, 8 | refout: true, 9 | xorout: 0xffffffff, 10 | check: 0, 11 | residue: 0, 12 | }; 13 | 14 | pub struct Crc32 { 15 | algo: Crc, 16 | } 17 | 18 | impl Crc32 { 19 | pub fn new() -> Self { 20 | Self { 21 | algo: Crc::::new(&ALGO_CRC32_NORMAL), 22 | } 23 | } 24 | 25 | pub fn crc(&self, data: &[u8]) -> u32 { 26 | let mut digest = self.algo.digest(); 27 | digest.update(&data); 28 | digest.finalize() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /esp-bootloader-esp-idf/src/rom.rs: -------------------------------------------------------------------------------- 1 | pub struct Crc32 {} 2 | 3 | impl Crc32 { 4 | pub fn new() -> Self { 5 | Self {} 6 | } 7 | 8 | pub fn crc(&self, data: &[u8]) -> u32 { 9 | unsafe extern "C" { 10 | fn esp_rom_crc32_le(crc: u32, buf: *const u8, len: u32) -> u32; 11 | } 12 | 13 | unsafe { esp_rom_crc32_le(0, data.as_ptr(), data.len() as u32) } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /esp-bootloader-esp-idf/testdata/factory_app_two_ota.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esp-rs/esp-hal/f22ddb4a873f7303b772e31148b52d4526e129ec/esp-bootloader-esp-idf/testdata/factory_app_two_ota.bin -------------------------------------------------------------------------------- /esp-bootloader-esp-idf/testdata/factory_app_two_ota.csv: -------------------------------------------------------------------------------- 1 | # ESP-IDF Partition Table 2 | # Name, Type, SubType, Offset, Size, Flags 3 | nvs, data, nvs, 0x9000, 0x4000, 4 | otadata, data, ota, 0xd000, 0x2000, 5 | phy_init, data, phy, 0xf000, 0x1000, 6 | factory, app, factory, 0x10000, 1M, 7 | ota_0, app, ota_0, 0x110000, 1M, 8 | ota_1, app, ota_1, 0x210000, 1M, 9 | -------------------------------------------------------------------------------- /esp-bootloader-esp-idf/testdata/single_factory_no_ota.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esp-rs/esp-hal/f22ddb4a873f7303b772e31148b52d4526e129ec/esp-bootloader-esp-idf/testdata/single_factory_no_ota.bin -------------------------------------------------------------------------------- /esp-bootloader-esp-idf/testdata/single_factory_no_ota.csv: -------------------------------------------------------------------------------- 1 | # ESP-IDF Partition Table 2 | # Name, Type, SubType, Offset, Size, Flags 3 | nvs, data, nvs, 0x9000, 0x6000, 4 | phy_init, data, phy, 0xf000, 0x1000, 5 | factory, app, factory, 0x10000, 1M, 6 | -------------------------------------------------------------------------------- /esp-build/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ### Added 11 | 12 | 13 | ### Changed 14 | 15 | 16 | ### Fixed 17 | 18 | 19 | ### Removed 20 | 21 | 22 | ## [v0.3.0] - 2025-06-03 23 | 24 | ### Changed 25 | 26 | - Bump Rust edition to 2024, bump MSRV to 1.86. (#3391, #3560) 27 | 28 | ## [0.2.0] - 2025-01-15 29 | 30 | ### Changed 31 | 32 | - Use `panic` instead of `process::exit` in esp-build (#2402) 33 | - Bump MSRV to 1.84 (#2951) 34 | 35 | ## 0.1.0 - 2024-04-17 36 | 37 | ### Added 38 | 39 | - Initial release (#2518) 40 | 41 | [0.2.0]: https://github.com/esp-rs/esp-hal/releases/tag/esp-build-v0.2.0 42 | [v0.3.0]: https://github.com/esp-rs/esp-hal/compare/esp-build-v0.2.0...esp-build-v0.3.0 43 | [Unreleased]: https://github.com/esp-rs/esp-hal/compare/esp-build-v0.3.0...HEAD 44 | -------------------------------------------------------------------------------- /esp-build/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "esp-build" 3 | version = "0.3.0" 4 | edition = "2024" 5 | rust-version = "1.86.0" 6 | description = "Build utilities for esp-hal" 7 | documentation = "https://docs.espressif.com/projects/rust/esp-build/latest/" 8 | repository = "https://github.com/esp-rs/esp-hal" 9 | license = "MIT OR Apache-2.0" 10 | 11 | [lib] 12 | proc-macro = true 13 | 14 | [dependencies] 15 | quote = "1.0.40" 16 | syn = { version = "2.0.100", features = ["fold", "full"] } 17 | termcolor = "1.4.1" 18 | -------------------------------------------------------------------------------- /esp-build/README.md: -------------------------------------------------------------------------------- 1 | # esp-build 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/esp-build?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-build) 4 | [![docs.rs](https://img.shields.io/docsrs/esp-build?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.espressif.com/projects/rust/esp-build/latest/) 5 | ![MSRV](https://img.shields.io/badge/MSRV-1.84-blue?labelColor=1C2C2E&style=flat-square) 6 | ![Crates.io](https://img.shields.io/crates/l/esp-build?labelColor=1C2C2E&style=flat-square) 7 | [![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) 8 | 9 | Build utilities for use with `esp-hal` and other related packages, intended for use in [build scripts]. This package is still quite minimal, but provides: 10 | 11 | [build scripts]: https://doc.rust-lang.org/cargo/reference/build-scripts.html 12 | 13 | ## [Documentation](https://docs.espressif.com/projects/rust/esp-build/latest/) 14 | 15 | ## Minimum Supported Rust Version (MSRV) 16 | 17 | This crate is guaranteed to compile when using the latest stable Rust version at the time of the crate's release. It _might_ compile with older versions, but that may change in any new release, including patches. 18 | 19 | ## License 20 | 21 | Licensed under either of: 22 | 23 | - Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 24 | - MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) 25 | 26 | at your option. 27 | 28 | ### Contribution 29 | 30 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in 31 | the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without 32 | any additional terms or conditions. 33 | -------------------------------------------------------------------------------- /esp-config/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ### Added 11 | 12 | 13 | ### Changed 14 | 15 | 16 | ### Fixed 17 | 18 | 19 | ### Removed 20 | 21 | 22 | ## [v0.4.0] - 2025-06-03 23 | 24 | ### Added 25 | 26 | - `ConfigOption` struct (#3362) 27 | - `Stabiliy` to specify unstable options, and the version in which they became stable (#3365) 28 | 29 | ### Changed 30 | 31 | - `generate_config` now takes a slice of `ConfigOption`s instead of tuples. (#3362) 32 | - Bump Rust edition to 2024, bump MSRV to 1.86. (#3391, #3560) 33 | - `ConfigOption` favors `String` over `&str` (#3455) 34 | - Removed the `Custom` validator (#3455) 35 | 36 | ## [0.3.1] - 2025-02-24 37 | 38 | ### Added 39 | 40 | - `Enumeration` validator added (#3172) 41 | 42 | ## 0.3.0 - 2025-01-15 43 | 44 | ### Fixed 45 | 46 | - Users no longer have to manually import `esp_config_int_parse`. (#2630) 47 | 48 | ### Changed 49 | 50 | - Crate prefixes and configuration keys are now separated by `_CONFIG_` (#2848) 51 | - Bump MSRV to 1.84 (#2951) 52 | 53 | ## 0.2.0 - 2024-11-20 54 | 55 | ### Added 56 | 57 | - Add configuration validation (#2475) 58 | 59 | ## 0.1.0 - 2024-10-10 60 | 61 | ### Added 62 | 63 | - Initial release (#2518) 64 | 65 | [0.3.1]: https://github.com/esp-rs/esp-hal/releases/tag/esp-config-v0.3.1 66 | [v0.4.0]: https://github.com/esp-rs/esp-hal/compare/esp-config-v0.3.1...esp-config-v0.4.0 67 | [Unreleased]: https://github.com/esp-rs/esp-hal/compare/esp-config-v0.4.0...HEAD 68 | -------------------------------------------------------------------------------- /esp-config/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "esp-config" 3 | version = "0.4.0" 4 | edition = "2024" 5 | rust-version = "1.86.0" 6 | description = "Configure projects using esp-hal and related packages" 7 | documentation = "https://docs.espressif.com/projects/rust/esp-config/latest/" 8 | repository = "https://github.com/esp-rs/esp-hal" 9 | license = "MIT OR Apache-2.0" 10 | 11 | [lib] 12 | bench = false 13 | test = true 14 | 15 | [dependencies] 16 | document-features = "0.2.11" 17 | serde = { version = "1.0.197", features = ["derive"], optional = true } 18 | serde_json = { version = "1.0.0", optional = true } 19 | 20 | [dev-dependencies] 21 | temp-env = "0.3.6" 22 | pretty_assertions = "1.4.1" 23 | 24 | [features] 25 | ## Enable the generation and parsing of a config 26 | build = ["dep:serde","dep:serde_json"] 27 | -------------------------------------------------------------------------------- /esp-config/src/generate/markdown.rs: -------------------------------------------------------------------------------- 1 | use std::fmt::Write; 2 | 3 | use crate::{ConfigOption, Value}; 4 | 5 | pub(crate) const DOC_TABLE_HEADER: &str = r#" 6 | | Name | Description | Default value | Allowed value | 7 | |------|-------------|--------------------|--------------------| 8 | "#; 9 | 10 | pub(crate) const SELECTED_TABLE_HEADER: &str = r#" 11 | | Name | Selected value | 12 | |------|----------------| 13 | "#; 14 | 15 | pub(crate) fn write_doc_table_line(mut table: impl Write, name: &str, option: &ConfigOption) { 16 | let allowed_values = option 17 | .constraint 18 | .as_ref() 19 | .and_then(|validator| validator.description()) 20 | .unwrap_or_default(); 21 | 22 | writeln!( 23 | table, 24 | "|

{key}

{stability}

|

{description}

|
{default}
|
{allowed}
", 25 | description = option.description, 26 | key = name, 27 | stability = option.stability, 28 | default = option.default_value, 29 | allowed = allowed_values 30 | ) 31 | .unwrap(); 32 | } 33 | 34 | pub(crate) fn write_summary_table_line(mut table: impl Write, name: &str, value: &Value) { 35 | writeln!(table, "|**{name}**|{value}|").unwrap(); 36 | } 37 | -------------------------------------------------------------------------------- /esp-hal-embassy/.clippy.toml: -------------------------------------------------------------------------------- 1 | avoid-breaking-exported-api = false 2 | -------------------------------------------------------------------------------- /esp-hal-embassy/MIGRATING-0.3.md: -------------------------------------------------------------------------------- 1 | # Migration Guide from 0.3.x to v0.4.x 2 | 3 | ## Initialization 4 | 5 | You no longer have to set up clocks and pass them to `esp_hal_embassy::init`. 6 | 7 | ```diff 8 | use esp_hal::{ 9 | - clock::ClockControl, 10 | - peripherals::Peripherals, 11 | prelude::*, 12 | - system::SystemControl, 13 | }; 14 | 15 | #[esp_hal_embassy::main] 16 | async fn main(_spawner: Spawner) -> ! { 17 | - let peripherals = Peripherals::take(); 18 | - let system = SystemControl::new(peripherals.SYSTEM); 19 | - let clocks = ClockControl::boot_defaults(system.clock_control).freeze(); 20 | + let peripherals = esp_hal::init(esp_hal::Config::default()); 21 | 22 | let timg0 = TimerGroup::new(peripherals.TIMG0); 23 | - esp_hal_embassy::init(&clocks, timg0); 24 | + esp_hal_embassy::init(timg0.timer0); 25 | 26 | // ... 27 | } 28 | ``` 29 | 30 | You have to specify a timer instance (that may be a `TimerGroup` timer unit 31 | or a `SystemTimer` alarm) or an array of `AnyTimer`s when calling `init`. 32 | An example of how you can set multiple timers (for example when using 33 | multiple executors): 34 | 35 | ```rust 36 | use esp_hal::{ 37 | prelude::*, 38 | timer::{ 39 | AnyTimer, 40 | systimer::SystemTimer 41 | } 42 | }; 43 | 44 | #[esp_hal_embassy::main] 45 | async fn main(_spawner: Spawner) -> ! { 46 | let peripherals = esp_hal::init(esp_hal::Config::default()); 47 | 48 | let timg0 = TimerGroup::new(peripherals.TIMG0); 49 | let timer0: AnyTimer = timg0.timer0.into(); 50 | let timer1: AnyTimer = timg0.timer1.into(); 51 | 52 | // You can use either a TimerGroup timer, a SystemTimer alarm, 53 | // or you can mix and match them as well. 54 | let systimer = SystemTimer::new(peripherals.SYSTIMER).split::(); 55 | let timer2: AnyTimer = systimer.alarm0; 56 | 57 | esp_hal_embassy::init([timer0, timer1, timer2]); 58 | 59 | // ... 60 | } 61 | ``` 62 | 63 | Note that you only have to convert into `AnyTimer` if you want to use multiple timers. 64 | -------------------------------------------------------------------------------- /esp-hal-embassy/MIGRATING-0.4.md: -------------------------------------------------------------------------------- 1 | # Migration Guide from 0.4.x to v0.5.x 2 | 3 | You don't have to make changes to your code to update esp-hal-embassy. 4 | -------------------------------------------------------------------------------- /esp-hal-embassy/MIGRATING-0.8.0.md: -------------------------------------------------------------------------------- 1 | # Migration Guide from 0.8.0 to {{currentVersion}} 2 | -------------------------------------------------------------------------------- /esp-hal-embassy/README.md: -------------------------------------------------------------------------------- 1 | # esp-hal-embassy 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/esp-hal-embassy?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-hal-embassy) 4 | [![docs.rs](https://img.shields.io/docsrs/esp-hal-embassy?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.espressif.com/projects/rust/esp-hal-embassy/latest/) 5 | ![MSRV](https://img.shields.io/badge/MSRV-1.84-blue?labelColor=1C2C2E&style=flat-square) 6 | ![Crates.io](https://img.shields.io/crates/l/esp-hal-embassy?labelColor=1C2C2E&style=flat-square) 7 | [![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) 8 | 9 | [Embassy] support for `esp-hal`. 10 | 11 | Note that this crate currently requires you to enable the `unstable` feature on `esp-hal`. 12 | 13 | [embassy]: https://github.com/embassy-rs/embassy 14 | 15 | ## [Documentation](https://docs.espressif.com/projects/rust/esp-hal-embassy/latest/) 16 | 17 | ## Minimum Supported Rust Version (MSRV) 18 | 19 | This crate is guaranteed to compile when using the latest stable Rust version at the time of the crate's release. It _might_ compile with older versions, but that may change in any new release, including patches. 20 | 21 | ## License 22 | 23 | Licensed under either of: 24 | 25 | - Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 26 | - MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) 27 | 28 | at your option. 29 | 30 | ### Contribution 31 | 32 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in 33 | the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without 34 | any additional terms or conditions. 35 | -------------------------------------------------------------------------------- /esp-hal-procmacros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "esp-hal-procmacros" 3 | version = "0.18.0" 4 | edition = "2024" 5 | rust-version = "1.86.0" 6 | description = "Procedural macros for esp-hal" 7 | documentation = "https://docs.espressif.com/projects/rust/esp-hal-procmacros/latest/" 8 | repository = "https://github.com/esp-rs/esp-hal" 9 | license = "MIT OR Apache-2.0" 10 | 11 | [package.metadata.docs.rs] 12 | features = ["embassy", "has-ulp-core", "interrupt", "ram", "is-ulp-core"] 13 | 14 | [lib] 15 | proc-macro = true 16 | 17 | [dependencies] 18 | darling = "0.20.11" 19 | document-features = "0.2.11" 20 | litrs = "0.4.1" 21 | object = { version = "0.36.7", default-features = false, features = ["read_core", "elf"], optional = true } 22 | proc-macro-crate = "3.3.0" 23 | proc-macro-error2 = "2.0.1" 24 | proc-macro2 = "1.0.95" 25 | quote = "1.0.40" 26 | syn = { version = "2.0.100", features = ["extra-traits", "full"] } 27 | 28 | [features] 29 | ## Provide a `#[main]` procmacro to mark the entry point for Embassy applications. 30 | embassy = [] 31 | ## Indicates the target device has RTC slow memory available. 32 | rtc-slow = [] 33 | 34 | #! ### Low-power Core Feature Flags 35 | ## Indicate that the SoC contains an LP core. 36 | has-lp-core = ["dep:object"] 37 | ## Indicate that the SoC contains a ULP core. 38 | has-ulp-core = ["dep:object"] 39 | ## Provide an `#[entry]` macro for running applications on the ESP32-C6's 40 | ## LP core. 41 | is-lp-core = [] 42 | ## Provide an `#[entry]` macro for running applications on the ESP32-S2/S3's 43 | ## ULP core. 44 | is-ulp-core = [] 45 | -------------------------------------------------------------------------------- /esp-hal-procmacros/README.md: -------------------------------------------------------------------------------- 1 | # esp-hal-procmacros 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/esp-hal-procmacros?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-hal-procmacros) 4 | [![docs.rs](https://img.shields.io/docsrs/esp-hal-procmacros?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.espressif.com/projects/rust/esp-hal-procmacros/latest/) 5 | ![MSRV](https://img.shields.io/badge/MSRV-1.84-blue?labelColor=1C2C2E&style=flat-square) 6 | ![Crates.io](https://img.shields.io/crates/l/esp-hal-procmacros?labelColor=1C2C2E&style=flat-square) 7 | [![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) 8 | 9 | Procedural macros for use with `esp-hal` and other related packages. 10 | 11 | ## [Documentation](https://docs.espressif.com/projects/rust/esp-hal-procmacros/latest/) 12 | 13 | 14 | ## Minimum Supported Rust Version (MSRV) 15 | 16 | This crate is guaranteed to compile when using the latest stable Rust version at the time of the crate's release. It _might_ compile with older versions, but that may change in any new release, including patches. 17 | 18 | ## License 19 | 20 | Licensed under either of: 21 | 22 | - Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 23 | - MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) 24 | 25 | at your option. 26 | 27 | ### Contribution 28 | 29 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in 30 | the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without 31 | any additional terms or conditions. 32 | -------------------------------------------------------------------------------- /esp-hal-procmacros/src/blocking.rs: -------------------------------------------------------------------------------- 1 | #![deny(warnings)] 2 | 3 | use proc_macro::TokenStream; 4 | use proc_macro2::Span; 5 | use syn::{ 6 | ItemFn, 7 | parse::{self}, 8 | parse_macro_input, 9 | }; 10 | 11 | pub fn main(args: TokenStream, input: TokenStream) -> TokenStream { 12 | let f = parse_macro_input!(input as ItemFn); 13 | 14 | if f.sig.asyncness.is_some() { 15 | return parse::Error::new(Span::call_site(), "If you want to use `async` please use `esp-hal-embassy`'s `#[esp_hal_embassy::main]` macro instead. (See https://docs.rs/esp-hal-embassy/latest/esp_hal_embassy/)") 16 | .to_compile_error() 17 | .into(); 18 | } 19 | 20 | if !args.is_empty() { 21 | return parse::Error::new(Span::call_site(), "This attribute accepts no arguments") 22 | .to_compile_error() 23 | .into(); 24 | } 25 | 26 | quote::quote!( 27 | #[esp_hal::__macro_implementation::__entry] 28 | #f 29 | ) 30 | .into() 31 | } 32 | -------------------------------------------------------------------------------- /esp-hal/.clippy.toml: -------------------------------------------------------------------------------- 1 | avoid-breaking-exported-api = false 2 | -------------------------------------------------------------------------------- /esp-hal/MIGRATING-1.0.0-beta.1.md: -------------------------------------------------------------------------------- 1 | # Migration Guide from 1.0.0-beta.1 to {{currentVersion}} 2 | -------------------------------------------------------------------------------- /esp-hal/api-baseline/esp32.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esp-rs/esp-hal/f22ddb4a873f7303b772e31148b52d4526e129ec/esp-hal/api-baseline/esp32.json.gz -------------------------------------------------------------------------------- /esp-hal/api-baseline/esp32c2.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esp-rs/esp-hal/f22ddb4a873f7303b772e31148b52d4526e129ec/esp-hal/api-baseline/esp32c2.json.gz -------------------------------------------------------------------------------- /esp-hal/api-baseline/esp32c3.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esp-rs/esp-hal/f22ddb4a873f7303b772e31148b52d4526e129ec/esp-hal/api-baseline/esp32c3.json.gz -------------------------------------------------------------------------------- /esp-hal/api-baseline/esp32c6.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esp-rs/esp-hal/f22ddb4a873f7303b772e31148b52d4526e129ec/esp-hal/api-baseline/esp32c6.json.gz -------------------------------------------------------------------------------- /esp-hal/api-baseline/esp32h2.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esp-rs/esp-hal/f22ddb4a873f7303b772e31148b52d4526e129ec/esp-hal/api-baseline/esp32h2.json.gz -------------------------------------------------------------------------------- /esp-hal/api-baseline/esp32s2.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esp-rs/esp-hal/f22ddb4a873f7303b772e31148b52d4526e129ec/esp-hal/api-baseline/esp32s2.json.gz -------------------------------------------------------------------------------- /esp-hal/api-baseline/esp32s3.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/esp-rs/esp-hal/f22ddb4a873f7303b772e31148b52d4526e129ec/esp-hal/api-baseline/esp32s3.json.gz -------------------------------------------------------------------------------- /esp-hal/ld/README.md: -------------------------------------------------------------------------------- 1 | # ROM functions 2 | 3 | Files in the `rom` subdirectories are taken from esp-idf 4 | 5 | - DON'T include any `*newlib*` functions 6 | - systimer, wdt and mbedtls shouldn't be included 7 | - make sure to align the version you take the files from with esp-wifi-sys - NEVER randomly sync the files with other versions 8 | - some additional functions are needed from ROM - see `additional.ld` (these are usually defined in the `*newlib*` files) 9 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32/esp32.x: -------------------------------------------------------------------------------- 1 | 2 | /* before memory.x to allow override */ 3 | ENTRY(ESP32Reset) 4 | 5 | /* after memory.x to allow override */ 6 | PROVIDE(__pre_init = DefaultPreInit); 7 | PROVIDE(__zero_bss = default_mem_hook); 8 | PROVIDE(__init_data = default_mem_hook); 9 | PROVIDE(__post_init = default_post_init); 10 | 11 | INCLUDE exception.x 12 | 13 | /* ESP32 fixups */ 14 | INCLUDE "fixups/rtc_fast_rwdata_dummy.x" 15 | /* END ESP32 fixups */ 16 | 17 | /* Shared sections - ordering matters */ 18 | SECTIONS { 19 | INCLUDE "rodata_desc.x" 20 | INCLUDE "rwtext.x" 21 | INCLUDE "rwdata.x" 22 | } 23 | INCLUDE "rodata.x" 24 | INCLUDE "text.x" 25 | INCLUDE "rtc_fast.x" 26 | INCLUDE "rtc_slow.x" 27 | INCLUDE "stack.x" 28 | INCLUDE "dram2.x" 29 | /* End of Shared sections */ 30 | 31 | EXTERN(DefaultHandler); 32 | 33 | EXTERN(WIFI_EVENT); /* Force inclusion of WiFi libraries */ 34 | 35 | INCLUDE "device.x" 36 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32/linkall.x: -------------------------------------------------------------------------------- 1 | INCLUDE "memory.x" 2 | INCLUDE "alias.x" 3 | INCLUDE "esp32.x" 4 | INCLUDE "hal-defaults.x" 5 | INCLUDE "rom-functions.x" 6 | INCLUDE "metadata.x" 7 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32/rom-functions.x: -------------------------------------------------------------------------------- 1 | INCLUDE "rom/esp32.rom.api.ld" 2 | INCLUDE "rom/esp32.rom.eco3.ld" 3 | INCLUDE "rom/esp32.rom.ld" 4 | INCLUDE "rom/esp32.rom.libgcc.ld" 5 | INCLUDE "rom/esp32.rom.redefined.ld" 6 | INCLUDE "rom/esp32.rom.spiflash_legacy.ld" 7 | INCLUDE "rom/esp32.rom.syscalls.ld" 8 | 9 | INCLUDE "rom/additional.ld" 10 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32/rom/additional.ld: -------------------------------------------------------------------------------- 1 | memcmp = 0x4000c260; 2 | memcpy = 0x4000c2c8; 3 | memmove = 0x4000c3c0; 4 | memset = 0x4000c44c; 5 | 6 | PROVIDE ( strcpy = 0x400013ac ); 7 | PROVIDE ( abs = 0x40056340 ); 8 | PROVIDE ( strncpy = 0x400015d4 ); 9 | PROVIDE ( strncmp = 0x4000c5f4 ); 10 | 11 | PROVIDE ( bzero = 0x4000c1f4 ); 12 | 13 | PROVIDE ( strcat = 0x4000c518 ); 14 | PROVIDE ( strcmp = 0x40001274 ); 15 | PROVIDE ( strchr = 0x4000c53c ); 16 | PROVIDE ( strlcpy = 0x4000c584 ); 17 | PROVIDE ( strstr = 0x4000c674 ); 18 | PROVIDE ( strcasecmp = 0x400011cc ); 19 | 20 | PROVIDE ( memchr = 0x4000c244 ); 21 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32/rom/esp32.rom.eco3.ld: -------------------------------------------------------------------------------- 1 | /* 2 | ESP32 ECO3 ROM address table 3 | Secure Boot Version 2 API's imported from the ROM 4 | */ 5 | PROVIDE ( ets_secure_boot_verify_signature = 0x4006543c); 6 | PROVIDE ( ets_secure_boot_verify_boot_bootloader = 0x400655ec); 7 | PROVIDE ( ets_use_secure_boot_v2 = 0x4000f8d4); 8 | PROVIDE ( ets_rsa_pss_verify = 0x40065310); 9 | PROVIDE ( ets_mgf1_sha256 = 0x400651a8); 10 | PROVIDE ( ets_emsa_pss_verify = 0x4006520c); 11 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32/rom/esp32.rom.redefined.ld: -------------------------------------------------------------------------------- 1 | /* 2 | ROM Functions defined in this file are not used in ESP-IDF as is, 3 | and different definitions for functions with the same names are provided. 4 | This file is not used when linking ESP-IDF and is intended for reference only 5 | */ 6 | 7 | PROVIDE ( abort = 0x4000bba4 ); 8 | PROVIDE ( aes_128_cbc_decrypt = 0x4005cc7c ); 9 | PROVIDE ( aes_128_cbc_encrypt = 0x4005cc18 ); 10 | PROVIDE ( aes_unwrap = 0x4005ccf0 ); 11 | PROVIDE ( base64_decode = 0x4005ced8 ); 12 | PROVIDE ( base64_encode = 0x4005cdbc ); 13 | PROVIDE ( ets_isr_mask = 0x400067fc ); 14 | PROVIDE ( ets_isr_unmask = 0x40006808 ); 15 | PROVIDE ( ets_timer_arm = 0x40008368 ); 16 | PROVIDE ( ets_timer_arm_us = 0x400083ac ); 17 | PROVIDE ( ets_timer_disarm = 0x400083ec ); 18 | PROVIDE ( ets_timer_done = 0x40008428 ); 19 | PROVIDE ( ets_timer_init = 0x400084e8 ); 20 | PROVIDE ( ets_timer_handler_isr = 0x40008454 ); 21 | PROVIDE ( ets_timer_setfn = 0x40008350 ); 22 | PROVIDE ( hmac_md5 = 0x4005d264 ); 23 | PROVIDE ( hmac_md5_vector = 0x4005d17c ); 24 | PROVIDE ( hmac_sha1 = 0x40060acc ); 25 | PROVIDE ( hmac_sha1_vector = 0x400609e4 ); 26 | PROVIDE ( hmac_sha256 = 0x40060d58 ); 27 | PROVIDE ( hmac_sha256_vector = 0x40060c84 ); 28 | PROVIDE ( MD5Final = 0x4005db1c ); 29 | PROVIDE ( MD5Init = 0x4005da7c ); 30 | PROVIDE ( MD5Update = 0x4005da9c ); 31 | PROVIDE ( md5_vector = 0x4005db80 ); 32 | PROVIDE ( pbkdf2_sha1 = 0x40060ba4 ); 33 | PROVIDE ( rc4_skip = 0x40060928 ); 34 | PROVIDE ( sha1_prf = 0x40060ae8 ); 35 | PROVIDE ( sha1_vector = 0x40060b64 ); 36 | PROVIDE ( sha256_prf = 0x40060d70 ); 37 | PROVIDE ( sha256_vector = 0x40060e08 ); 38 | PROVIDE ( uart_tx_wait_idle = 0x40009278 ); 39 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32/rom/esp32.rom.spiflash_legacy.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | /* 7 | Address table for SPI driver functions in ESP32 ROM. 8 | These functions are only linked from ROM when SPI_FLASH_ROM_DRIVER_PATCH is not set in configuration. 9 | */ 10 | 11 | PROVIDE ( esp_rom_spiflash_write_encrypted = 0x40062e78 ); 12 | PROVIDE ( esp_rom_spiflash_erase_area = 0x400631ac ); 13 | PROVIDE ( esp_rom_spiflash_erase_block = 0x40062c4c ); 14 | PROVIDE ( esp_rom_spiflash_erase_chip = 0x40062c14 ); 15 | PROVIDE ( esp_rom_spiflash_erase_sector = 0x40062ccc ); 16 | PROVIDE ( esp_rom_spiflash_attach = 0x40062a6c ); 17 | PROVIDE ( esp_rom_spiflash_lock = 0x400628f0 ); 18 | PROVIDE ( esp_rom_spiflash_read = 0x40062ed8 ); 19 | PROVIDE ( esp_rom_spiflash_config_readmode = 0x40062b64 ); /* SPIMasterReadModeCnfig */ 20 | PROVIDE ( esp_rom_spiflash_read_status = 0x4006226c ); 21 | PROVIDE ( esp_rom_spiflash_read_statushigh = 0x40062448 ); 22 | PROVIDE ( esp_rom_spiflash_write = 0x40062d50 ); 23 | PROVIDE ( esp_rom_spiflash_enable_write = 0x40062320 ); 24 | PROVIDE ( esp_rom_spiflash_write_status = 0x400622f0 ); 25 | 26 | /* always using patched versions of these functions 27 | PROVIDE ( esp_rom_spiflash_wait_idle = 0x400622c0 ); 28 | PROVIDE ( esp_rom_spiflash_unlock = 0x400????? ); 29 | */ 30 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32c2/linkall.x: -------------------------------------------------------------------------------- 1 | INCLUDE "memory.x" 2 | 3 | REGION_ALIAS("ROTEXT", IROM); 4 | REGION_ALIAS("RODATA", DROM); 5 | 6 | REGION_ALIAS("RWDATA", DRAM); 7 | REGION_ALIAS("RWTEXT", IRAM); 8 | 9 | INCLUDE "esp32c2.x" 10 | INCLUDE "hal-defaults.x" 11 | INCLUDE "rom-functions.x" 12 | INCLUDE "metadata.x" 13 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32c2/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* 4 | https://github.com/espressif/esptool/blob/10828527038d143e049790d330ac4de76ce987d6/esptool/targets/esp32c2.py#L53-L62 5 | MEMORY_MAP = [[0x00000000, 0x00010000, "PADDING"], 6 | [0x3C000000, 0x3C400000, "DROM"], 7 | [0x3FCA0000, 0x3FCE0000, "DRAM"], 8 | [0x3FC88000, 0x3FD00000, "BYTE_ACCESSIBLE"], 9 | [0x3FF00000, 0x3FF50000, "DROM_MASK"], 10 | [0x40000000, 0x40090000, "IROM_MASK"], 11 | [0x42000000, 0x42400000, "IROM"], 12 | [0x4037C000, 0x403C0000, "IRAM"]] 13 | */ 14 | 15 | ICACHE : ORIGIN = 0x4037C000, LENGTH = 16K 16 | /* Instruction RAM */ 17 | IRAM : ORIGIN = 0x4037C000 + LENGTH(ICACHE), LENGTH = 186k 18 | /* Data RAM */ 19 | DRAM : ORIGIN = 0x3FCA0000, LENGTH = 186k 20 | 21 | /* memory available after the 2nd stage bootloader is finished */ 22 | dram2_seg ( RW ) : ORIGIN = ORIGIN(DRAM) + LENGTH(DRAM), len = 0x3fcdeb70 - (ORIGIN(DRAM) + LENGTH(DRAM)) 23 | 24 | /* External flash 25 | 26 | The 0x20 offset is a convenience for the app binary image generation. 27 | Flash cache has 64KB pages. The .bin file which is flashed to the chip 28 | has a 0x18 byte file header, and each segment has a 0x08 byte segment 29 | header. Setting this offset makes it simple to meet the flash cache MMU's 30 | constraint that (paddr % 64KB == vaddr % 64KB).) 31 | */ 32 | 33 | /* Instruction ROM */ 34 | IROM : ORIGIN = 0x42000000 + 0x20, LENGTH = 0x200000 - 0x20 35 | /* Data ROM */ 36 | DROM : ORIGIN = 0x3C000000 + 0x20, LENGTH = 0x200000 - 0x20 37 | } -------------------------------------------------------------------------------- /esp-hal/ld/esp32c2/rom-functions.x: -------------------------------------------------------------------------------- 1 | INCLUDE "rom/esp32c2.rom.api.ld" 2 | INCLUDE "rom/esp32c2.rom.heap.ld" 3 | INCLUDE "rom/esp32c2.rom.ld" 4 | INCLUDE "rom/esp32c2.rom.libgcc.ld" 5 | INCLUDE "rom/esp32c2.rom.rvfp.ld" 6 | INCLUDE "rom/esp32c2.rom.version.ld" 7 | 8 | INCLUDE "rom/additional.ld" 9 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32c2/rom/additional.ld: -------------------------------------------------------------------------------- 1 | memset = 0x40000488; 2 | memcpy = 0x4000048c; 3 | memmove = 0x40000490; 4 | memcmp = 0x40000494; 5 | 6 | strcpy = 0x40000498; 7 | strncpy = 0x4000049c; 8 | strncmp = 0x400004a4; 9 | 10 | PROVIDE ( strcat = 0x4000050c ); 11 | PROVIDE ( strcmp = 0x400004a0 ); 12 | PROVIDE ( strchr = 0x40000514 ); 13 | PROVIDE ( strlcpy = 0x40000524 ); 14 | PROVIDE ( strstr = 0x400004ac ); 15 | PROVIDE ( strcasecmp = 0x40000504 ); 16 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32c2/rom/esp32c2.rom.version.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | /* ROM version variables for esp32c2 8 | * 9 | * These addresses should be compatible with any ROM version for this chip. 10 | * 11 | * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. 12 | */ 13 | _rom_chip_id = 0x40000010; 14 | _rom_eco_version = 0x40000014; 15 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32c3/linkall.x: -------------------------------------------------------------------------------- 1 | INCLUDE "memory.x" 2 | 3 | REGION_ALIAS("ROTEXT", IROM); 4 | REGION_ALIAS("RODATA", DROM); 5 | 6 | REGION_ALIAS("RWDATA", DRAM); 7 | REGION_ALIAS("RWTEXT", IRAM); 8 | 9 | REGION_ALIAS("RTC_FAST_RWTEXT", RTC_FAST); 10 | REGION_ALIAS("RTC_FAST_RWDATA", RTC_FAST); 11 | 12 | INCLUDE "esp32c3.x" 13 | INCLUDE "hal-defaults.x" 14 | INCLUDE "rom-functions.x" 15 | INCLUDE "metadata.x" 16 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32c3/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* 4 | https://github.com/espressif/esptool/blob/ed64d20b051d05f3f522bacc6a786098b562d4b8/esptool/targets/esp32c3.py#L78-L90 5 | MEMORY_MAP = [[0x00000000, 0x00010000, "PADDING"], 6 | [0x3C000000, 0x3C800000, "DROM"], 7 | [0x3FC80000, 0x3FCE0000, "DRAM"], 8 | [0x3FC88000, 0x3FD00000, "BYTE_ACCESSIBLE"], 9 | [0x3FF00000, 0x3FF20000, "DROM_MASK"], 10 | [0x40000000, 0x40060000, "IROM_MASK"], 11 | [0x42000000, 0x42800000, "IROM"], 12 | [0x4037C000, 0x403E0000, "IRAM"], 13 | [0x50000000, 0x50002000, "RTC_IRAM"], 14 | [0x50000000, 0x50002000, "RTC_DRAM"], 15 | [0x600FE000, 0x60100000, "MEM_INTERNAL2"]] 16 | */ 17 | 18 | ICACHE : ORIGIN = 0x4037C000, LENGTH = 0x4000 19 | /* Instruction RAM */ 20 | IRAM : ORIGIN = 0x4037C000 + 0x4000, LENGTH = 313K - 0x4000 21 | /* Data RAM */ 22 | DRAM : ORIGIN = 0x3FC80000, LENGTH = 313K 23 | 24 | /* memory available after the 2nd stage bootloader is finished */ 25 | dram2_seg ( RW ) : ORIGIN = ORIGIN(DRAM) + LENGTH(DRAM), len = 0x3fcde710 - (ORIGIN(DRAM) + LENGTH(DRAM)) 26 | 27 | /* External flash 28 | 29 | The 0x20 offset is a convenience for the app binary image generation. 30 | Flash cache has 64KB pages. The .bin file which is flashed to the chip 31 | has a 0x18 byte file header, and each segment has a 0x08 byte segment 32 | header. Setting this offset makes it simple to meet the flash cache MMU's 33 | constraint that (paddr % 64KB == vaddr % 64KB).) 34 | */ 35 | 36 | /* Instruction ROM */ 37 | IROM : ORIGIN = 0x42000000 + 0x20, LENGTH = 0x400000 - 0x20 38 | /* Data ROM */ 39 | DROM : ORIGIN = 0x3C000000 + 0x20, LENGTH = 0x400000 - 0x20 40 | 41 | /* RTC fast memory (executable). Persists over deep sleep. */ 42 | RTC_FAST : ORIGIN = 0x50000000, LENGTH = 0x2000 /*- ESP_BOOTLOADER_RESERVE_RTC*/ 43 | } 44 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32c3/rom-functions.x: -------------------------------------------------------------------------------- 1 | INCLUDE "rom/esp32c3.rom.api.ld" 2 | INCLUDE "rom/esp32c3.rom.eco3.ld" 3 | /* TODO 4 | INCLUDE "rom/esp32c3.rom.eco7.ld" 5 | */ 6 | INCLUDE "rom/esp32c3.rom.ld" 7 | INCLUDE "rom/esp32c3.rom.libgcc.ld" 8 | INCLUDE "rom/esp32c3.rom.version.ld" 9 | 10 | INCLUDE "rom/additional.ld" 11 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32c3/rom/additional.ld: -------------------------------------------------------------------------------- 1 | memset = 0x40000354; 2 | memcpy = 0x40000358; 3 | memmove = 0x4000035c; 4 | memcmp = 0x40000360; 5 | 6 | strncmp = 0x40000370; 7 | strncpy = 0x40000368; 8 | strcpy = 0x40000364; 9 | 10 | abs = 0x40000424; 11 | 12 | PROVIDE(cache_dbus_mmu_set = 0x40000564); 13 | 14 | PROVIDE( strcat = 0x400003d8 ); 15 | PROVIDE( strcmp = 0x4000036c ); 16 | PROVIDE( strchr = 0x400003e0 ); 17 | PROVIDE( strlcpy = 0x400003f0 ); 18 | PROVIDE( strstr = 0x40000378 ); 19 | PROVIDE( strcasecmp = 0x400003d0 ); 20 | 21 | PROVIDE( memchr = 0x400003c8 ); 22 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32c3/rom/esp32c3.rom.version.ld: -------------------------------------------------------------------------------- 1 | /* ROM version variables for esp32c3 2 | * 3 | * These addresses should be compatible with any ROM version for this chip. 4 | * 5 | * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. 6 | */ 7 | _rom_chip_id = 0x40000010; 8 | _rom_eco_version = 0x40000014; 9 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32c6/linkall.x: -------------------------------------------------------------------------------- 1 | INCLUDE "memory.x" 2 | 3 | REGION_ALIAS("ROTEXT", ROM); 4 | REGION_ALIAS("RODATA", ROM); 5 | 6 | REGION_ALIAS("RWTEXT", RAM); 7 | REGION_ALIAS("RWDATA", RAM); 8 | 9 | REGION_ALIAS("RTC_FAST_RWTEXT", RTC_FAST); 10 | REGION_ALIAS("RTC_FAST_RWDATA", RTC_FAST); 11 | 12 | INCLUDE "esp32c6.x" 13 | INCLUDE "hal-defaults.x" 14 | INCLUDE "rom-functions.x" 15 | INCLUDE "metadata.x" 16 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32c6/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* MEMORY_MAP = [ 4 | [0x00000000, 0x00010000, "PADDING"], 5 | [0x42800000, 0x43000000, "DROM"], 6 | [0x40800000, 0x40880000, "RAM"], 7 | [0x40800000, 0x40880000, "BYTE_ACCESSIBLE"], 8 | [0x4004AC00, 0x40050000, "DROM_MASK"], 9 | [0x40000000, 0x4004AC00, "ROM_MASK"], 10 | [0x42000000, 0x42800000, "ROM"], 11 | [0x40800000, 0x40880000, "RAM"], 12 | [0x50000000, 0x50004000, "RTC_RAM"], 13 | [0x50000000, 0x50004000, "RTC_RAM"], 14 | [0x600FE000, 0x60100000, "MEM_INTERNAL2"], 15 | ] */ 16 | 17 | /* 512K of on soc RAM, 32K reserved for cache */ 18 | /* Instruction and Data RAM 19 | 0x4086E610 = 2nd stage bootloader iram_loader_seg start address 20 | see https://github.com/espressif/esp-idf/blob/03414a15508036c8fc0f51642aed7a264e9527df/components/esp_system/ld/esp32c6/memory.ld.in#L26 21 | */ 22 | RAM : ORIGIN = 0x40800000 , LENGTH = 0x6E610 23 | 24 | /* memory available after the 2nd stage bootloader is finished */ 25 | dram2_seg ( RW ) : ORIGIN = ORIGIN(RAM) + LENGTH(RAM), len = 0x4087e610 - (ORIGIN(RAM) + LENGTH(RAM)) 26 | 27 | /* External flash 28 | The 0x20 offset is a convenience for the app binary image generation. 29 | Flash cache has 64KB pages. The .bin file which is flashed to the chip 30 | has a 0x18 byte file header, and each segment has a 0x08 byte segment 31 | header. Setting this offset makes it simple to meet the flash cache MMU's 32 | constraint that (paddr % 64KB == vaddr % 64KB).) 33 | */ 34 | 35 | /* Instruction and Data ROM */ 36 | ROM : ORIGIN = 0x42000000 + 0x20, LENGTH = 0x400000 - 0x20 37 | 38 | /* RTC fast memory (executable). Persists over deep sleep. */ 39 | RTC_FAST : ORIGIN = 0x50000000, LENGTH = 16K /*- ESP_BOOTLOADER_RESERVE_RTC*/ 40 | } 41 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32c6/rom-functions.x: -------------------------------------------------------------------------------- 1 | INCLUDE "rom/esp32c6.rom.api.ld" 2 | INCLUDE "rom/esp32c6.rom.coexist.ld" 3 | INCLUDE "rom/esp32c6.rom.heap.ld" 4 | INCLUDE "rom/esp32c6.rom.ld" 5 | INCLUDE "rom/esp32c6.rom.libgcc.ld" 6 | INCLUDE "rom/esp32c6.rom.net80211.ld" 7 | INCLUDE "rom/esp32c6.rom.phy.ld" 8 | INCLUDE "rom/esp32c6.rom.pp.ld" 9 | INCLUDE "rom/esp32c6.rom.rvfp.ld" 10 | INCLUDE "rom/esp32c6.rom.spiflash.ld" 11 | INCLUDE "rom/esp32c6.rom.version.ld" 12 | 13 | INCLUDE "rom/additional.ld" 14 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32c6/rom/additional.ld: -------------------------------------------------------------------------------- 1 | memset = 0x400004a8; 2 | memcpy = 0x400004ac; 3 | memmove = 0x400004b0; 4 | memcmp = 0x400004b4; 5 | 6 | strncmp = 0x400004c4; 7 | strncpy = 0x400004bc; 8 | strcpy = 0x400004b8; 9 | 10 | abs = 0x40000578; 11 | 12 | PROVIDE(strcat = 0x4000052c); 13 | PROVIDE(strcmp = 0x400004c0); 14 | PROVIDE(strchr = 0x40000534); 15 | PROVIDE(strlcpy = 0x40000544); 16 | PROVIDE(strstr = 0x400004cc); 17 | PROVIDE(strcasecmp = 0x40000524); 18 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32c6/rom/esp32c6.rom.coexist.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | /* ROM function interface esp32c6.rom.coexist.ld for esp32c6 7 | * 8 | * 9 | * Generated from ./target/esp32c6/interface-esp32c6.yml md5sum 06c13e133e0743d09b87aba30d3e213b 10 | * 11 | * Compatible with ROM where ECO version equal or greater to 0. 12 | * 13 | * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. 14 | */ 15 | 16 | /*************************************** 17 | Group rom_coexist 18 | ***************************************/ 19 | 20 | /* Functions */ 21 | esp_coex_rom_version_get = 0x40000afc; 22 | coex_bt_release = 0x40000b00; 23 | coex_bt_request = 0x40000b04; 24 | coex_core_ble_conn_dyn_prio_get = 0x40000b08; 25 | /*coex_core_event_duration_get = 0x40000b0c;*/ 26 | coex_core_pti_get = 0x40000b10; 27 | coex_core_release = 0x40000b14; 28 | coex_core_request = 0x40000b18; 29 | coex_core_status_get = 0x40000b1c; 30 | /*coex_core_timer_idx_get = 0x40000b20;*/ 31 | coex_event_duration_get = 0x40000b24; 32 | coex_hw_timer_disable = 0x40000b28; 33 | coex_hw_timer_enable = 0x40000b2c; 34 | coex_hw_timer_set = 0x40000b30; 35 | coex_schm_interval_set = 0x40000b34; 36 | coex_schm_lock = 0x40000b38; 37 | coex_schm_unlock = 0x40000b3c; 38 | coex_status_get = 0x40000b40; 39 | coex_wifi_release = 0x40000b44; 40 | esp_coex_ble_conn_dynamic_prio_get = 0x40000b48; 41 | /* Data (.data, .bss, .rodata) */ 42 | coex_env_ptr = 0x4087ffc4; 43 | coex_pti_tab_ptr = 0x4087ffc0; 44 | coex_schm_env_ptr = 0x4087ffbc; 45 | coexist_funcs = 0x4087ffb8; 46 | g_coa_funcs_p = 0x4087ffb4; 47 | g_coex_param_ptr = 0x4087ffb0; 48 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32c6/rom/esp32c6.rom.version.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | /* ROM version variables for esp32c6 7 | * 8 | * These addresses should be compatible with any ROM version for this chip. 9 | * 10 | * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. 11 | */ 12 | _rom_chip_id = 0x40000010; 13 | _rom_eco_version = 0x40000014; 14 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32h2/linkall.x: -------------------------------------------------------------------------------- 1 | INCLUDE "memory.x" 2 | 3 | REGION_ALIAS("ROTEXT", ROM); 4 | REGION_ALIAS("RODATA", ROM); 5 | 6 | REGION_ALIAS("RWTEXT", RAM); 7 | REGION_ALIAS("RWDATA", RAM); 8 | 9 | REGION_ALIAS("RTC_FAST_RWTEXT", RTC_FAST); 10 | REGION_ALIAS("RTC_FAST_RWDATA", RTC_FAST); 11 | 12 | INCLUDE "esp32h2.x" 13 | INCLUDE "hal-defaults.x" 14 | INCLUDE "rom-functions.x" 15 | INCLUDE "metadata.x" 16 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32h2/memory.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | /* MEMORY_MAP = [ 4 | [0x00000000, 0x00010000, "PADDING"], 5 | [0x42800000, 0x43000000, "DROM"], 6 | [0x40800000, 0x40850000, "RAM"], 7 | [0x40800000, 0x40850000, "BYTE_ACCESSIBLE"], 8 | [0x4001С400, 0x40020000, "DROM_MASK"], 9 | [0x40000000, 0x4001С400, "ROM_MASK"], 10 | [0x42000000, 0x42800000, "ROM"], 11 | [0x40800000, 0x40850000, "RAM"], 12 | [0x50000000, 0x50001000, "RTC_RAM"], 13 | [0x50000000, 0x50001000, "RTC_RAM"], 14 | [0x600FE000, 0x60100000, "MEM_INTERNAL2"], 15 | ] */ 16 | 17 | 18 | /* 320K of on soc RAM, 16K reserved for cache */ 19 | /* Instruction and Data RAM 20 | 0x4083EFD0 = 2nd stage bootloader iram_loader_seg start address 21 | see https://github.com/espressif/esp-idf/blob/03414a15508036c8fc0f51642aed7a264e9527df/components/esp_system/ld/esp32h2/memory.ld.in#L26 22 | */ 23 | RAM : ORIGIN = 0x40800000, LENGTH = 0x3EFD0 24 | 25 | /* memory available after the 2nd stage bootloader is finished */ 26 | dram2_seg ( RW ) : ORIGIN = ORIGIN(RAM) + LENGTH(RAM), len = 0x4084fee0 - (ORIGIN(RAM) + LENGTH(RAM)) 27 | 28 | /* External flash 29 | 30 | The 0x20 offset is a convenience for the app binary image generation. 31 | Flash cache has 64KB pages. The .bin file which is flashed to the chip 32 | has a 0x18 byte file header, and each segment has a 0x08 byte segment 33 | header. Setting this offset makes it simple to meet the flash cache MMU's 34 | constraint that (paddr % 64KB == vaddr % 64KB).) 35 | */ 36 | 37 | /* Instruction and Data ROM */ 38 | ROM : ORIGIN = 0x42000000 + 0x20, LENGTH = 0x400000 - 0x20 39 | 40 | /* RTC fast memory (executable). Persists over deep sleep. */ 41 | RTC_FAST : ORIGIN = 0x50000000, LENGTH = 16K /*- ESP_BOOTLOADER_RESERVE_RTC*/ 42 | } 43 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32h2/rom-functions.x: -------------------------------------------------------------------------------- 1 | INCLUDE "rom/esp32h2.rom.api.ld" 2 | INCLUDE "rom/esp32h2.rom.heap.ld" 3 | INCLUDE "rom/esp32h2.rom.ld" 4 | INCLUDE "rom/esp32h2.rom.libgcc.ld" 5 | INCLUDE "rom/esp32h2.rom.spiflash.ld" 6 | INCLUDE "rom/esp32h2.rom.version.ld" 7 | 8 | INCLUDE "rom/additional.ld" 9 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32h2/rom/additional.ld: -------------------------------------------------------------------------------- 1 | memset = 0x400004a0; 2 | memcpy = 0x400004a4; 3 | memmove = 0x400004a8; 4 | memcmp = 0x400004ac; 5 | 6 | strncmp = 0x400004bc; 7 | strncpy = 0x400004b4; 8 | strcpy = 0x400004b0; 9 | 10 | abs = 0x40000570; 11 | 12 | PROVIDE( strcat = 0x40000524 ); 13 | PROVIDE( strcmp = 0x400004b8 ); 14 | PROVIDE( strchr = 0x4000052c ); 15 | PROVIDE( strlcpy = 0x4000053c ); 16 | PROVIDE( strstr = 0x400004c4 ); 17 | PROVIDE( strcasecmp = 0x4000051c ); 18 | 19 | PROVIDE( memchr = 0x40000514 ); 20 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32h2/rom/esp32h2.rom.version.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | /* ROM version variables for esp32h2 7 | * 8 | * These addresses should be compatible with any ROM version for this chip. 9 | * 10 | * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. 11 | */ 12 | _rom_chip_id = 0x40000010; 13 | _rom_eco_version = 0x40000014; 14 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32s2/esp32s2.x: -------------------------------------------------------------------------------- 1 | 2 | /* before memory.x to allow override */ 3 | ENTRY(ESP32Reset) 4 | 5 | /* after memory.x to allow override */ 6 | PROVIDE(__pre_init = DefaultPreInit); 7 | PROVIDE(__zero_bss = default_mem_hook); 8 | PROVIDE(__init_data = default_mem_hook); 9 | PROVIDE(__post_init = default_post_init); 10 | 11 | INCLUDE exception.x 12 | 13 | /* This represents .rwtext but in .data */ 14 | SECTIONS { 15 | .rwdata_dummy (NOLOAD) : ALIGN(4) 16 | { 17 | . = . + SIZEOF(.rwtext) + SIZEOF(.rwtext.wifi); 18 | } > RWDATA 19 | } 20 | INSERT BEFORE .data; 21 | 22 | INCLUDE "fixups/rtc_fast_rwdata_dummy.x" 23 | /* End of fixups for esp32s2 */ 24 | 25 | /* Shared sections - ordering matters */ 26 | SECTIONS { 27 | INCLUDE "rodata_desc.x" 28 | INCLUDE "rwtext.x" 29 | INCLUDE "rwdata.x" 30 | } 31 | INCLUDE "rodata.x" 32 | INCLUDE "text.x" 33 | INCLUDE "rtc_fast.x" 34 | INCLUDE "rtc_slow.x" 35 | INCLUDE "stack.x" 36 | INCLUDE "dram2.x" 37 | /* End of Shared sections */ 38 | 39 | EXTERN(DefaultHandler); 40 | 41 | INCLUDE "device.x" 42 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32s2/linkall.x: -------------------------------------------------------------------------------- 1 | INCLUDE "memory.x" 2 | INCLUDE "alias.x" 3 | INCLUDE "esp32s2.x" 4 | INCLUDE "hal-defaults.x" 5 | INCLUDE "rom-functions.x" 6 | INCLUDE "metadata.x" 7 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32s2/rom-functions.x: -------------------------------------------------------------------------------- 1 | INCLUDE "rom/esp32s2.rom.api.ld" 2 | INCLUDE "rom/esp32s2.rom.ld" 3 | INCLUDE "rom/esp32s2.rom.libgcc.ld" 4 | INCLUDE "rom/esp32s2.rom.spiflash_legacy.ld" 5 | 6 | INCLUDE "rom/additional.ld" 7 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32s2/rom/additional.ld: -------------------------------------------------------------------------------- 1 | memcmp = 0x4001ab40; 2 | memcpy = 0x4001aba8; 3 | memmove = 0x4001acb0; 4 | memset = 0x4001ad3c; 5 | 6 | strcpy = 0x40007cfc; 7 | strncpy = 0x40007f20; 8 | strncmp = 0x4001ae64; 9 | 10 | bzero = 0x400078c8; 11 | 12 | PROVIDE ( cache_dbus_mmu_set = 0x40018eb0 ); 13 | 14 | PROVIDE ( strcat = 0x4001ad90 ); 15 | PROVIDE ( strcmp = 0x40007be4 ); 16 | PROVIDE ( strchr = 0x4001adb0 ); 17 | PROVIDE ( strlcpy = 0x4001adf8 ); 18 | PROVIDE ( strstr = 0x4001aee8 ); 19 | PROVIDE ( strcasecmp = 0x40007b38 ); 20 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32s2/rom/esp32s2.rom.spiflash_legacy.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | /** 7 | * SPI flash driver function, compatibility names. 8 | */ 9 | 10 | PROVIDE ( g_rom_spiflash_dummy_len_plus = dummy_len_plus); 11 | PROVIDE ( g_ticks_per_us_pro = g_ticks_per_us ); 12 | PROVIDE ( g_rom_flashchip = SPI_flashchip_data ); 13 | PROVIDE ( g_rom_spiflash_chip = SPI_flashchip_data ); 14 | PROVIDE ( esp_rom_spiflash_config_param = SPIParamCfg ); 15 | PROVIDE ( esp_rom_spiflash_read = SPIRead ); 16 | PROVIDE ( esp_rom_spiflash_read_status = SPI_read_status ); 17 | PROVIDE ( esp_rom_spiflash_read_statushigh = SPI_read_status_high ); 18 | PROVIDE ( esp_rom_spiflash_read_user_cmd = SPI_user_command_read ); 19 | PROVIDE ( esp_rom_spiflash_write = SPIWrite ); 20 | PROVIDE ( esp_rom_spiflash_write_encrypted_disable = SPI_Write_Encrypt_Disable ); 21 | PROVIDE ( esp_rom_spiflash_write_encrypted_enable = SPI_Write_Encrypt_Enable ); 22 | PROVIDE ( esp_rom_spiflash_config_clk = SPIClkConfig ); 23 | PROVIDE ( esp_rom_spiflash_select_qio_pins = SelectSpiQIO ); 24 | PROVIDE ( esp_rom_spiflash_unlock = SPIUnlock ); 25 | PROVIDE ( esp_rom_spiflash_erase_sector = SPIEraseSector ); 26 | PROVIDE ( esp_rom_spiflash_erase_block = SPIEraseBlock ); 27 | PROVIDE ( esp_rom_spiflash_wait_idle = SPI_Wait_Idle ); 28 | PROVIDE ( esp_rom_spiflash_config_readmode = SPIReadModeCnfig ); 29 | PROVIDE ( esp_rom_spiflash_erase_block = SPIEraseBlock ); 30 | PROVIDE ( esp_rom_spiflash_write_encrypted = SPI_Encrypt_Write ); 31 | PROVIDE ( esp_rom_spiflash_erase_area = SPIEraseArea ); 32 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32s3/esp32s3.x: -------------------------------------------------------------------------------- 1 | /* before memory.x to allow override */ 2 | ENTRY(ESP32Reset) 3 | 4 | /* after memory.x to allow override */ 5 | PROVIDE(__pre_init = DefaultPreInit); 6 | PROVIDE(__zero_bss = default_mem_hook); 7 | PROVIDE(__init_data = default_mem_hook); 8 | PROVIDE(__post_init = default_post_init); 9 | 10 | INCLUDE exception.x 11 | 12 | SECTIONS { 13 | .rotext_dummy (NOLOAD) : 14 | { 15 | /* This dummy section represents the .rodata section within ROTEXT. 16 | * Since the same physical memory is mapped to both DROM and IROM, 17 | * we need to make sure the .rodata and .text sections don't overlap. 18 | * We skip the amount of memory taken by .rodata* in .text 19 | */ 20 | 21 | /* Start at the same alignment constraint than .flash.text */ 22 | 23 | . = ALIGN(ALIGNOF(.rodata)); 24 | . = ALIGN(ALIGNOF(.rodata.wifi)); 25 | 26 | /* Create an empty gap as big as .text section */ 27 | 28 | . = . + SIZEOF(.rodata_desc); 29 | . = . + SIZEOF(.rodata); 30 | . = . + SIZEOF(.rodata.wifi); 31 | 32 | /* Prepare the alignment of the section above. Few bytes (0x20) must be 33 | * added for the mapping header. 34 | */ 35 | 36 | . = ALIGN(0x10000) + 0x20; 37 | _rotext_reserved_start = .; 38 | } > ROTEXT 39 | } 40 | INSERT BEFORE .text; 41 | 42 | /* Similar to .rotext_dummy this represents .rwtext but in .data */ 43 | SECTIONS { 44 | .rwdata_dummy (NOLOAD) : ALIGN(4) 45 | { 46 | . = . + SIZEOF(.rwtext) + SIZEOF(.rwtext.wifi) + SIZEOF(.vectors); 47 | } > RWDATA 48 | } 49 | INSERT BEFORE .data; 50 | 51 | /* Shared sections - ordering matters */ 52 | SECTIONS { 53 | INCLUDE "rodata_desc.x" 54 | INCLUDE "rwtext.x" 55 | INCLUDE "rwdata.x" 56 | } 57 | INCLUDE "rodata.x" 58 | INCLUDE "text.x" 59 | INCLUDE "rtc_fast.x" 60 | INCLUDE "rtc_slow.x" 61 | INCLUDE "stack.x" 62 | INCLUDE "dram2.x" 63 | /* End of Shared sections */ 64 | 65 | EXTERN(DefaultHandler); 66 | 67 | INCLUDE "device.x" 68 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32s3/linkall.x: -------------------------------------------------------------------------------- 1 | INCLUDE "memory.x" 2 | INCLUDE "alias.x" 3 | INCLUDE "esp32s3.x" 4 | INCLUDE "hal-defaults.x" 5 | INCLUDE "rom-functions.x" 6 | INCLUDE "metadata.x" 7 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32s3/rom-functions.x: -------------------------------------------------------------------------------- 1 | INCLUDE "rom/esp32s3.rom.api.ld" 2 | INCLUDE "rom/esp32s3.rom.ld" 3 | INCLUDE "rom/esp32s3.rom.libgcc.ld" 4 | INCLUDE "rom/esp32s3.rom.version.ld" 5 | 6 | INCLUDE "rom/additional.ld" 7 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32s3/rom/additional.ld: -------------------------------------------------------------------------------- 1 | memset = 0x400011e8; 2 | memcpy = 0x400011f4; 3 | memmove = 0x40001200; 4 | memcmp = 0x4000120c; 5 | 6 | strcpy = 0x40001218; 7 | strncpy = 0x40001224; 8 | strncmp = 0x4000123c; 9 | 10 | bzero = 0x40001260; 11 | 12 | PROVIDE(cache_dbus_mmu_set = 0x400019b0); 13 | PROVIDE( Cache_Suspend_DCache_Autoload = 0x40001734 ); 14 | PROVIDE( Cache_Suspend_DCache = 0x400018b4 ); 15 | 16 | PROVIDE( strcat = 0x40001374 ); 17 | PROVIDE( strcmp = 0x40001230 ); 18 | PROVIDE( strchr = 0x4000138c ); 19 | PROVIDE( strlcpy = 0x400013bc ); 20 | PROVIDE( strstr = 0x40001254 ); 21 | PROVIDE( strcasecmp = 0x4000135c ); 22 | -------------------------------------------------------------------------------- /esp-hal/ld/esp32s3/rom/esp32s3.rom.version.ld: -------------------------------------------------------------------------------- 1 | /* ROM version variables for esp32s3 2 | * 3 | * These addresses should be compatible with any ROM version for this chip. 4 | * 5 | * THIS FILE WAS AUTOMATICALLY GENERATED. DO NOT EDIT. 6 | */ 7 | _rom_chip_id = 0x40000570; 8 | _rom_eco_version = 0x40000574; 9 | -------------------------------------------------------------------------------- /esp-hal/ld/riscv/asserts.x: -------------------------------------------------------------------------------- 1 | 2 | 3 | /* Do not exceed this mark in the error messages above | */ 4 | ASSERT(ORIGIN(ROTEXT) % 4 == 0, " 5 | ERROR(riscv-rt): the start of the ROTEXT must be 4-byte aligned"); 6 | 7 | ASSERT(ORIGIN(RODATA) % 4 == 0, " 8 | ERROR(riscv-rt): the start of the RODATA must be 4-byte aligned"); 9 | 10 | ASSERT(ORIGIN(REGION_DATA) % 4 == 0, " 11 | ERROR(riscv-rt): the start of the REGION_DATA must be 4-byte aligned"); 12 | 13 | ASSERT(ORIGIN(ROTEXT) % 4 == 0, " 14 | ERROR(riscv-rt): the start of the ROTEXT must be 4-byte aligned"); 15 | 16 | ASSERT(ORIGIN(REGION_STACK) % 4 == 0, " 17 | ERROR(riscv-rt): the start of the REGION_STACK must be 4-byte aligned"); 18 | 19 | ASSERT(_stext % 4 == 0, " 20 | ERROR(riscv-rt): `_stext` must be 4-byte aligned"); 21 | 22 | ASSERT(_data_start % 4 == 0 && _data_end % 4 == 0, " 23 | BUG(riscv-rt): .data is not 4-byte aligned"); 24 | 25 | ASSERT(_sidata % 4 == 0, " 26 | BUG(riscv-rt): the LMA of .data is not 4-byte aligned"); 27 | 28 | ASSERT(_bss_start % 4 == 0 && _bss_end % 4 == 0, " 29 | BUG(riscv-rt): .bss is not 4-byte aligned"); 30 | 31 | ASSERT(_stext + SIZEOF(.text) < ORIGIN(ROTEXT) + LENGTH(ROTEXT), " 32 | ERROR(riscv-rt): The .text section must be placed inside the ROTEXT region. 33 | Set _stext to an address smaller than 'ORIGIN(ROTEXT) + LENGTH(ROTEXT)'"); 34 | 35 | ASSERT(SIZEOF(.got) == 0, " 36 | .got section detected in the input files. Dynamic relocations are not 37 | supported. If you are linking to C code compiled using the `gcc` crate 38 | then modify your build script to compile the C code _without_ the 39 | -fPIC flag. See the documentation of the `gcc::Config.fpic` method for 40 | details."); 41 | 42 | /* Do not exceed this mark in the error messages above | */ -------------------------------------------------------------------------------- /esp-hal/ld/riscv/debug.x: -------------------------------------------------------------------------------- 1 | 2 | 3 | SECTIONS { 4 | .eh_frame (INFO) : { KEEP(*(.eh_frame)) } 5 | .eh_frame_hdr (INFO) : { *(.eh_frame_hdr) } 6 | } -------------------------------------------------------------------------------- /esp-hal/ld/riscv/hal-defaults.x: -------------------------------------------------------------------------------- 1 | PROVIDE(DefaultHandler = EspDefaultHandler); 2 | 3 | PROVIDE(interrupt1 = DefaultHandler); 4 | PROVIDE(interrupt2 = DefaultHandler); 5 | PROVIDE(interrupt3 = DefaultHandler); 6 | PROVIDE(interrupt4 = DefaultHandler); 7 | PROVIDE(interrupt5 = DefaultHandler); 8 | PROVIDE(interrupt6 = DefaultHandler); 9 | PROVIDE(interrupt7 = DefaultHandler); 10 | PROVIDE(interrupt8 = DefaultHandler); 11 | PROVIDE(interrupt9 = DefaultHandler); 12 | PROVIDE(interrupt10 = DefaultHandler); 13 | PROVIDE(interrupt11 = DefaultHandler); 14 | PROVIDE(interrupt12 = DefaultHandler); 15 | PROVIDE(interrupt13 = DefaultHandler); 16 | PROVIDE(interrupt14 = DefaultHandler); 17 | PROVIDE(interrupt15 = DefaultHandler); 18 | PROVIDE(interrupt16 = DefaultHandler); 19 | PROVIDE(interrupt17 = DefaultHandler); 20 | PROVIDE(interrupt18 = DefaultHandler); 21 | PROVIDE(interrupt19 = DefaultHandler); 22 | PROVIDE(interrupt20 = DefaultHandler); 23 | PROVIDE(interrupt21 = DefaultHandler); 24 | PROVIDE(interrupt22 = DefaultHandler); 25 | PROVIDE(interrupt23 = DefaultHandler); 26 | PROVIDE(interrupt24 = DefaultHandler); 27 | PROVIDE(interrupt25 = DefaultHandler); 28 | PROVIDE(interrupt26 = DefaultHandler); 29 | PROVIDE(interrupt27 = DefaultHandler); 30 | PROVIDE(interrupt28 = DefaultHandler); 31 | PROVIDE(interrupt29 = DefaultHandler); 32 | PROVIDE(interrupt30 = DefaultHandler); 33 | PROVIDE(interrupt31 = DefaultHandler); 34 | 35 | INCLUDE "device.x" 36 | -------------------------------------------------------------------------------- /esp-hal/ld/sections/dram2.x: -------------------------------------------------------------------------------- 1 | /* an uninitialized section of RAM otherwise not useable */ 2 | SECTIONS { 3 | .dram2_uninit (NOLOAD) : ALIGN(4) { 4 | *(.dram2_uninit) 5 | } > dram2_seg 6 | } 7 | -------------------------------------------------------------------------------- /esp-hal/ld/sections/fixups/rtc_fast_rwdata_dummy.x: -------------------------------------------------------------------------------- 1 | /* 2 | This fix up is required when the RTC fast memory is split across two address spaces. 3 | This fix up pads the _data bus_ address space by the size of the code accessed by the instruction bus. 4 | */ 5 | 6 | SECTIONS { 7 | .rtc_fast.dummy (NOLOAD) : 8 | { 9 | _rtc_dummy_start = ABSOLUTE(.); /* needed to make section proper size */ 10 | . = . + SIZEOF(.rtc_fast.text); 11 | _rtc_dummy_end = ABSOLUTE(.); /* needed to make section proper size */ 12 | } > RTC_FAST_RWDATA 13 | } 14 | INSERT BEFORE .rtc_fast.data; -------------------------------------------------------------------------------- /esp-hal/ld/sections/metadata.x: -------------------------------------------------------------------------------- 1 | SECTIONS { 2 | .espressif.metadata 0 (INFO) : 3 | { 4 | KEEP(*(.espressif.metadata)); 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /esp-hal/ld/sections/rodata.x: -------------------------------------------------------------------------------- 1 | 2 | 3 | SECTIONS { 4 | .rodata : ALIGN(4) 5 | { 6 | . = ALIGN (4); 7 | _rodata_start = ABSOLUTE(.); 8 | *(.rodata .rodata.*) 9 | *(.srodata .srodata.*) 10 | . = ALIGN(4); 11 | _rodata_end = ABSOLUTE(.); 12 | } > RODATA 13 | 14 | .rodata.wifi : ALIGN(4) 15 | { 16 | . = ALIGN(4); 17 | *( .rodata_wlog_*.* ) 18 | . = ALIGN(4); 19 | } > RODATA 20 | } -------------------------------------------------------------------------------- /esp-hal/ld/sections/rodata_desc.x: -------------------------------------------------------------------------------- 1 | .rodata_desc : ALIGN(4) 2 | { 3 | KEEP(*(.rodata_desc)); 4 | KEEP(*(.rodata_desc.*)); 5 | } > RODATA 6 | -------------------------------------------------------------------------------- /esp-hal/ld/sections/rtc_fast.x: -------------------------------------------------------------------------------- 1 | 2 | 3 | SECTIONS { 4 | .rtc_fast.text : { 5 | . = ALIGN(4); 6 | *(.rtc_fast.literal .rtc_fast.text .rtc_fast.literal.* .rtc_fast.text.*) 7 | . = ALIGN(4); 8 | } > RTC_FAST_RWTEXT AT > RODATA 9 | 10 | .rtc_fast.data : 11 | { 12 | . = ALIGN(4); 13 | _rtc_fast_data_start = ABSOLUTE(.); 14 | *(.rtc_fast.data .rtc_fast.data.*) 15 | _rtc_fast_data_end = ABSOLUTE(.); 16 | . = ALIGN(4); 17 | } > RTC_FAST_RWDATA AT > RODATA 18 | 19 | .rtc_fast.bss (NOLOAD) : 20 | { 21 | . = ALIGN(4); 22 | _rtc_fast_bss_start = ABSOLUTE(.); 23 | *(.rtc_fast.bss .rtc_fast.bss.*) 24 | _rtc_fast_bss_end = ABSOLUTE(.); 25 | . = ALIGN(4); 26 | } > RTC_FAST_RWDATA 27 | 28 | .rtc_fast.persistent (NOLOAD) : 29 | { 30 | . = ALIGN(4); 31 | _rtc_fast_persistent_start = ABSOLUTE(.); 32 | *(.rtc_fast.persistent .rtc_fast.persistent.*) 33 | _rtc_fast_persistent_end = ABSOLUTE(.); 34 | . = ALIGN(4); 35 | } > RTC_FAST_RWDATA 36 | } -------------------------------------------------------------------------------- /esp-hal/ld/sections/rtc_slow.x: -------------------------------------------------------------------------------- 1 | 2 | 3 | SECTIONS { 4 | .rtc_slow.text : { 5 | . = ALIGN(4); 6 | *(.rtc_slow.literal .rtc_slow.text .rtc_slow.literal.* .rtc_slow.text.*) 7 | . = ALIGN(4); 8 | } > rtc_slow_seg AT > RODATA 9 | 10 | .rtc_slow.data : 11 | { 12 | . = ALIGN(4); 13 | _rtc_slow_data_start = ABSOLUTE(.); 14 | *(.rtc_slow.data .rtc_slow.data.*) 15 | _rtc_slow_data_end = ABSOLUTE(.); 16 | . = ALIGN(4); 17 | } > rtc_slow_seg AT > RODATA 18 | 19 | .rtc_slow.bss (NOLOAD) : 20 | { 21 | . = ALIGN(4); 22 | _rtc_slow_bss_start = ABSOLUTE(.); 23 | *(.rtc_slow.bss .rtc_slow.bss.*) 24 | _rtc_slow_bss_end = ABSOLUTE(.); 25 | . = ALIGN(4); 26 | } > rtc_slow_seg 27 | 28 | .rtc_slow.persistent (NOLOAD) : 29 | { 30 | . = ALIGN(4); 31 | _rtc_slow_persistent_start = ABSOLUTE(.); 32 | *(.rtc_slow.persistent .rtc_slow.persistent.*) 33 | _rtc_slow_persistent_end = ABSOLUTE(.); 34 | . = ALIGN(4); 35 | } > rtc_slow_seg 36 | } -------------------------------------------------------------------------------- /esp-hal/ld/sections/rwdata.x: -------------------------------------------------------------------------------- 1 | .data : ALIGN(4) 2 | { 3 | _data_start = ABSOLUTE(.); 4 | . = ALIGN (4); 5 | 6 | #IF ESP_HAL_CONFIG_PLACE_SWITCH_TABLES_IN_RAM 7 | *(.rodata.*_esp_hal_internal_handler*) 8 | *(.rodata..Lswitch.table.*) 9 | *(.rodata.cst*) 10 | #ENDIF 11 | 12 | #IF ESP_HAL_CONFIG_PLACE_ANON_IN_RAM 13 | *(.rodata..Lanon .rodata..Lanon.*) 14 | #ENDIF 15 | 16 | *(.sdata .sdata.* .sdata2 .sdata2.*); 17 | *(.data .data.*); 18 | *(.data1) 19 | _data_end = ABSOLUTE(.); 20 | . = ALIGN(4); 21 | } > RWDATA 22 | 23 | /* LMA of .data */ 24 | _sidata = LOADADDR(.data); 25 | 26 | .bss (NOLOAD) : ALIGN(4) 27 | { 28 | _bss_start = ABSOLUTE(.); 29 | . = ALIGN (4); 30 | *(.dynsbss) 31 | *(.sbss) 32 | *(.sbss.*) 33 | *(.gnu.linkonce.sb.*) 34 | *(.scommon) 35 | *(.sbss2) 36 | *(.sbss2.*) 37 | *(.gnu.linkonce.sb2.*) 38 | *(.dynbss) 39 | *(.sbss .sbss.* .bss .bss.*); 40 | *(.share.mem) 41 | *(.gnu.linkonce.b.*) 42 | *(COMMON) 43 | _bss_end = ABSOLUTE(.); 44 | . = ALIGN(4); 45 | } > RWDATA 46 | 47 | .noinit (NOLOAD) : ALIGN(4) 48 | { 49 | . = ALIGN(4); 50 | *(.noinit .noinit.*) 51 | *(.uninit .uninit.*) 52 | . = ALIGN(4); 53 | } > RWDATA 54 | 55 | .data.wifi : 56 | { 57 | . = ALIGN(4); 58 | *( .dram1 .dram1.*) 59 | . = ALIGN(4); 60 | } > RWDATA 61 | -------------------------------------------------------------------------------- /esp-hal/ld/sections/rwtext.x: -------------------------------------------------------------------------------- 1 | .rwtext : ALIGN(4) 2 | { 3 | . = ALIGN (4); 4 | *(.rwtext.literal .rwtext .rwtext.literal.* .rwtext.*) 5 | . = ALIGN(4); 6 | } > RWTEXT 7 | 8 | .rwtext.wifi : 9 | { 10 | . = ALIGN(4); 11 | *( .wifi0iram .wifi0iram.*) 12 | *( .wifirxiram .wifirxiram.*) 13 | *( .wifislprxiram .wifislprxiram.*) 14 | *( .wifislpiram .wifislpiram.*) 15 | *( .phyiram .phyiram.*) 16 | *( .iram1 .iram1.*) 17 | *( .wifiextrairam.* ) 18 | *( .coexiram.* ) 19 | . = ALIGN(4); 20 | } > RWTEXT 21 | -------------------------------------------------------------------------------- /esp-hal/ld/sections/stack.x: -------------------------------------------------------------------------------- 1 | SECTIONS { 2 | /* must be last segment using RWDATA */ 3 | .stack (NOLOAD) : ALIGN(4) 4 | { 5 | _stack_end = ABSOLUTE(.); 6 | _stack_end_cpu0 = ABSOLUTE(.); 7 | 8 | /* The stack_guard for `stack-protector` mitigation - https://doc.rust-lang.org/rustc/exploit-mitigations.html#stack-smashing-protection */ 9 | __stack_chk_guard = _stack_end + ${ESP_HAL_CONFIG_STACK_GUARD_OFFSET}; 10 | 11 | /* no Xtensa chip is supported - so we can assume RISC-V */ 12 | #IF ESP_HAL_CONFIG_FLIP_LINK 13 | /* Since we cannot know how much the alignment padding of the sections will add we shrink the stack for "the worst case" 14 | */ 15 | . = . + LENGTH(RWDATA) - (SIZEOF(.trap) + SIZEOF(.rwtext) + SIZEOF(.rwtext.wifi) + SIZEOF(.data) + SIZEOF(.bss) + SIZEOF(.noinit) + SIZEOF(.data.wifi)) - 304; 16 | #ELSE 17 | . = ORIGIN(RWDATA) + LENGTH(RWDATA); 18 | #ENDIF 19 | . = ALIGN (4); 20 | _stack_start = ABSOLUTE(.); 21 | _stack_start_cpu0 = ABSOLUTE(.); 22 | } > RWDATA 23 | } 24 | -------------------------------------------------------------------------------- /esp-hal/ld/sections/text.x: -------------------------------------------------------------------------------- 1 | 2 | 3 | SECTIONS { 4 | 5 | .text : ALIGN(4) 6 | { 7 | #IF riscv 8 | KEEP(*(.init)); 9 | KEEP(*(.init.rust)); 10 | KEEP(*(.text.abort)); 11 | #ENDIF 12 | *(.literal .text .literal.* .text.*) 13 | } > ROTEXT 14 | 15 | } -------------------------------------------------------------------------------- /esp-hal/ld/xtensa/hal-defaults.x: -------------------------------------------------------------------------------- 1 | PROVIDE(DefaultHandler = EspDefaultHandler); 2 | 3 | PROVIDE(level1_interrupt = DefaultHandler); 4 | PROVIDE(level2_interrupt = DefaultHandler); 5 | PROVIDE(level3_interrupt = DefaultHandler); 6 | PROVIDE(level4_interrupt = DefaultHandler); 7 | PROVIDE(level5_interrupt = DefaultHandler); 8 | PROVIDE(level6_interrupt = DefaultHandler); 9 | PROVIDE(level7_interrupt = DefaultHandler); 10 | -------------------------------------------------------------------------------- /esp-hal/src/aes/esp32cX.rs: -------------------------------------------------------------------------------- 1 | use crate::aes::{ALIGN_SIZE, Aes, Aes128, Aes256, AesFlavour, Mode}; 2 | 3 | impl Aes<'_> { 4 | pub(super) fn init(&mut self) { 5 | self.write_dma(false); 6 | } 7 | 8 | fn write_dma(&mut self, enable_dma: bool) { 9 | self.regs() 10 | .dma_enable() 11 | .write(|w| w.dma_enable().bit(enable_dma)); 12 | } 13 | 14 | pub(super) fn write_key(&mut self, key: &[u8]) { 15 | debug_assert!(key.len() <= 8 * ALIGN_SIZE); 16 | debug_assert_eq!(key.len() % ALIGN_SIZE, 0); 17 | self.alignment_helper 18 | .volatile_write_regset(self.regs().key(0).as_ptr(), key, 8); 19 | } 20 | 21 | pub(super) fn write_block(&mut self, block: &[u8]) { 22 | debug_assert_eq!(block.len(), 4 * ALIGN_SIZE); 23 | self.alignment_helper 24 | .volatile_write_regset(self.regs().text_in(0).as_ptr(), block, 4); 25 | } 26 | 27 | pub(super) fn write_mode(&self, mode: Mode) { 28 | self.regs().mode().write(|w| unsafe { w.bits(mode as _) }); 29 | } 30 | 31 | pub(super) fn write_start(&self) { 32 | self.regs().trigger().write(|w| w.trigger().set_bit()); 33 | } 34 | 35 | pub(super) fn read_idle(&mut self) -> bool { 36 | self.regs().state().read().state().bits() == 0 37 | } 38 | 39 | pub(super) fn read_block(&self, block: &mut [u8]) { 40 | debug_assert_eq!(block.len(), 4 * ALIGN_SIZE); 41 | self.alignment_helper 42 | .volatile_read_regset(self.regs().text_out(0).as_ptr(), block, 4); 43 | } 44 | } 45 | 46 | impl AesFlavour for Aes128 { 47 | type KeyType<'b> = &'b [u8; 16]; 48 | } 49 | 50 | impl AesFlavour for Aes256 { 51 | type KeyType<'b> = &'b [u8; 32]; 52 | } 53 | -------------------------------------------------------------------------------- /esp-hal/src/analog/adc/calibration/basic.rs: -------------------------------------------------------------------------------- 1 | use core::marker::PhantomData; 2 | 3 | use crate::analog::adc::{ 4 | AdcCalEfuse, 5 | AdcCalScheme, 6 | AdcCalSource, 7 | AdcConfig, 8 | Attenuation, 9 | CalibrationAccess, 10 | }; 11 | 12 | /// Basic ADC calibration scheme 13 | /// 14 | /// Basic calibration sets the initial ADC bias value so that a zero voltage 15 | /// gives a reading of zero. The correct bias value is usually stored in efuse, 16 | /// but can also be measured at runtime by connecting the ADC input to ground 17 | /// internally. 18 | /// 19 | /// Failing to apply basic calibration can substantially reduce the ADC's output 20 | /// range because bias correction is done *before* the ADC's output is truncated 21 | /// to 12 bits. 22 | #[derive(Clone, Copy)] 23 | pub struct AdcCalBasic { 24 | /// Calibration value to set to ADC unit 25 | cal_val: u16, 26 | 27 | _phantom: PhantomData, 28 | } 29 | 30 | impl crate::private::Sealed for AdcCalBasic {} 31 | 32 | impl AdcCalScheme for AdcCalBasic 33 | where 34 | ADCI: AdcCalEfuse + CalibrationAccess, 35 | { 36 | fn new_cal(atten: Attenuation) -> Self { 37 | // Try to get init code (Dout0) from efuse 38 | // Dout0 means mean raw ADC value when zero voltage applied to input. 39 | let cal_val = ADCI::init_code(atten).unwrap_or_else(|| { 40 | // As a fallback try to calibrate via connecting input to ground internally. 41 | AdcConfig::::adc_calibrate(atten, AdcCalSource::Gnd) 42 | }); 43 | 44 | Self { 45 | cal_val, 46 | _phantom: PhantomData, 47 | } 48 | } 49 | 50 | fn adc_cal(&self) -> u16 { 51 | self.cal_val 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /esp-hal/src/analog/adc/calibration/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))] 2 | pub use self::basic::AdcCalBasic; 3 | #[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))] 4 | pub use self::curve::{AdcCalCurve, AdcHasCurveCal}; 5 | #[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))] 6 | pub use self::line::{AdcCalLine, AdcHasLineCal}; 7 | 8 | #[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))] 9 | mod basic; 10 | #[cfg(any(esp32c3, esp32c6, esp32h2, esp32s3))] 11 | mod curve; 12 | #[cfg(any(esp32c2, esp32c3, esp32c6, esp32h2, esp32s3))] 13 | mod line; 14 | -------------------------------------------------------------------------------- /esp-hal/src/analog/mod.rs: -------------------------------------------------------------------------------- 1 | //! # Analog Peripherals 2 | //! 3 | //! ## Overview 4 | //! The `analog` module provides drivers for the various analog peripherals 5 | //! available on the device. For more information about a peripheral driver, 6 | //! please refer to the relevant module documentation. 7 | 8 | #[cfg(any(adc1, adc2))] 9 | pub mod adc; 10 | #[cfg(dac)] 11 | pub mod dac; 12 | -------------------------------------------------------------------------------- /esp-hal/src/asynch.rs: -------------------------------------------------------------------------------- 1 | //! Asynchronous utilities. 2 | use core::task::Waker; 3 | 4 | use embassy_sync::waitqueue::GenericAtomicWaker; 5 | 6 | use crate::sync::RawMutex; 7 | 8 | /// Utility struct to register and wake a waker. 9 | pub struct AtomicWaker { 10 | waker: GenericAtomicWaker, 11 | } 12 | 13 | impl AtomicWaker { 14 | /// Create a new `AtomicWaker`. 15 | #[allow(clippy::new_without_default)] 16 | pub const fn new() -> Self { 17 | Self { 18 | waker: GenericAtomicWaker::new(RawMutex::new()), 19 | } 20 | } 21 | 22 | delegate::delegate! { 23 | to self.waker { 24 | /// Register a waker. Overwrites the previous waker, if any. 25 | pub fn register(&self, w: &Waker); 26 | /// Wake the registered waker, if any. 27 | pub fn wake(&self); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /esp-hal/src/debugger.rs: -------------------------------------------------------------------------------- 1 | //! Debugger utilities 2 | 3 | /// Checks if a debugger is connected. 4 | pub fn debugger_connected() -> bool { 5 | #[cfg(xtensa)] 6 | { 7 | xtensa_lx::is_debugger_attached() 8 | } 9 | 10 | #[cfg(riscv)] 11 | { 12 | crate::peripherals::ASSIST_DEBUG::regs() 13 | .core_0_debug_mode() 14 | .read() 15 | .core_0_debug_module_active() 16 | .bit_is_set() 17 | } 18 | 19 | #[cfg(not(any(xtensa, riscv)))] 20 | { 21 | false 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /esp-hal/src/gpio/placeholder.rs: -------------------------------------------------------------------------------- 1 | //! Placeholder pins/signals. 2 | //! 3 | //! These are useful to pass them into peripheral drivers where you don't want 4 | //! an actual pin but one is required. 5 | // This module also contains peripheral signal impls for `Level` to avoid 6 | // polluting the main module. 7 | 8 | use super::*; 9 | 10 | /// Placeholder pin, used when no pin is required when using a peripheral. 11 | /// 12 | /// When used as a peripheral signal, `NoPin` is equivalent to [`Level::Low`]. 13 | #[derive(Default, Clone, Copy)] 14 | pub struct NoPin; 15 | 16 | impl private::Sealed for NoPin {} 17 | 18 | impl embedded_hal::digital::ErrorType for NoPin { 19 | type Error = core::convert::Infallible; 20 | } 21 | 22 | impl embedded_hal::digital::OutputPin for NoPin { 23 | fn set_low(&mut self) -> Result<(), Self::Error> { 24 | Ok(()) 25 | } 26 | 27 | fn set_high(&mut self) -> Result<(), Self::Error> { 28 | Ok(()) 29 | } 30 | } 31 | 32 | impl embedded_hal::digital::StatefulOutputPin for NoPin { 33 | fn is_set_high(&mut self) -> Result { 34 | Ok(false) 35 | } 36 | 37 | fn is_set_low(&mut self) -> Result { 38 | Ok(false) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /esp-hal/src/i2c/mod.rs: -------------------------------------------------------------------------------- 1 | //! # Inter-Integrated Circuit (I2C) 2 | //! 3 | //! I2C is a serial, synchronous, multi-device, half-duplex communication 4 | //! protocol that allows co-existence of multiple masters and slaves on the 5 | //! same bus. I2C uses two bidirectional open-drain lines: serial data line 6 | //! (SDA) and serial clock line (SCL), pulled up by resistors. 7 | //! 8 | //! For more information, see 9 | #![doc = crate::trm_markdown_link!("i2c")] 10 | 11 | pub mod master; 12 | 13 | #[cfg(lp_i2c0)] 14 | crate::unstable_module! { 15 | pub mod lp_i2c; 16 | } 17 | 18 | crate::any_peripheral! { 19 | /// Any I2C peripheral. 20 | pub peripheral AnyI2c<'d> { 21 | #[cfg(i2c0)] 22 | I2c0(crate::peripherals::I2C0<'d>), 23 | #[cfg(i2c1)] 24 | I2c1(crate::peripherals::I2C1<'d>), 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /esp-hal/src/i2s/mod.rs: -------------------------------------------------------------------------------- 1 | //! # Inter-IC Sound (I2S) 2 | 3 | use crate::dma::DmaEligible; 4 | 5 | pub mod master; 6 | 7 | #[cfg(esp32)] 8 | pub mod parallel; 9 | 10 | crate::any_peripheral! { 11 | /// Any I2S peripheral. 12 | pub peripheral AnyI2s<'d> { 13 | #[cfg(i2s0)] 14 | I2s0(crate::peripherals::I2S0<'d>), 15 | #[cfg(i2s1)] 16 | I2s1(crate::peripherals::I2S1<'d>), 17 | } 18 | } 19 | 20 | impl<'d> DmaEligible for AnyI2s<'d> { 21 | #[cfg(gdma)] 22 | type Dma = crate::dma::AnyGdmaChannel<'d>; 23 | #[cfg(pdma)] 24 | type Dma = crate::dma::AnyI2sDmaChannel<'d>; 25 | 26 | fn dma_peripheral(&self) -> crate::dma::DmaPeripheral { 27 | match &self.0 { 28 | AnyI2sInner::I2s0(_) => crate::dma::DmaPeripheral::I2s0, 29 | #[cfg(i2s1)] 30 | AnyI2sInner::I2s1(_) => crate::dma::DmaPeripheral::I2s1, 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /esp-hal/src/soc/esp32/regi2c.rs: -------------------------------------------------------------------------------- 1 | use crate::rom::regi2c::{RegI2cMaster, RegI2cRegister, define_regi2c}; 2 | 3 | define_regi2c! { 4 | master: REGI2C_BBPLL(0x66, 4) { 5 | reg: I2C_BBPLL_IR_CAL_DELAY(0) {} 6 | reg: I2C_BBPLL_IR_CAL_EXT_CAP(1) {} 7 | reg: I2C_BBPLL_OC_LREF(2) {} 8 | reg: I2C_BBPLL_OC_DIV_REG(3) {} 9 | reg: I2C_BBPLL_OC_ENB_FCAL(4) {} 10 | reg: I2C_BBPLL_OC_DCUR(5) {} 11 | reg: I2C_BBPLL_BBADC_DSMP(9) {} 12 | reg: I2C_BBPLL_OC_ENB_VCON(10) {} 13 | reg: I2C_BBPLL_ENDIV5(11) {} 14 | reg: I2C_BBPLL_BBADC_CAL_REG(12) {} 15 | } 16 | } 17 | 18 | pub(crate) fn regi2c_read(block: u8, host_id: u8, reg_add: u8) -> u8 { 19 | unsafe extern "C" { 20 | pub(crate) fn esp_rom_regi2c_read(block: u8, block_hostid: u8, reg_add: u8) -> u8; 21 | } 22 | unsafe { esp_rom_regi2c_read(block, host_id, reg_add) } 23 | } 24 | 25 | pub(crate) fn regi2c_write(block: u8, host_id: u8, reg_add: u8, data: u8) { 26 | unsafe extern "C" { 27 | pub(crate) fn rom_i2c_writeReg(block: u8, block_hostid: u8, reg_add: u8, indata: u8); 28 | } 29 | unsafe { rom_i2c_writeReg(block, host_id, reg_add, data) }; 30 | } 31 | -------------------------------------------------------------------------------- /esp-hal/src/soc/esp32c2/mod.rs: -------------------------------------------------------------------------------- 1 | //! # SOC (System-on-Chip) module (ESP32-C2) 2 | //! 3 | //! ## Overview 4 | //! 5 | //! The `SOC` module provides access, functions and structures that are useful 6 | //! for interacting with various system-related peripherals on `ESP32-C2` chip. 7 | 8 | crate::unstable_module! { 9 | pub mod efuse; 10 | pub mod trng; 11 | } 12 | pub mod gpio; 13 | pub mod peripherals; 14 | pub(crate) mod regi2c; 15 | 16 | #[allow(unused)] 17 | pub(crate) mod registers { 18 | pub const INTERRUPT_MAP_BASE: u32 = 0x600c2000; 19 | } 20 | 21 | #[cfg_attr(not(feature = "unstable"), allow(unused))] 22 | pub(crate) mod constants { 23 | use crate::time::Rate; 24 | 25 | /// RC FAST Clock value (Hertz). 26 | pub const RC_FAST_CLK: Rate = Rate::from_khz(17500); 27 | } 28 | 29 | pub(crate) fn pre_init() {} 30 | -------------------------------------------------------------------------------- /esp-hal/src/soc/esp32c3/mod.rs: -------------------------------------------------------------------------------- 1 | //! # SOC (System-on-Chip) module (ESP32-C3) 2 | //! 3 | //! ## Overview 4 | //! 5 | //! The `SOC` module provides access, functions and structures that are useful 6 | //! for interacting with various system-related peripherals on `ESP32-C3` chip. 7 | //! 8 | //! Also few constants are defined in this module for `ESP32-C3` chip: 9 | //! * I2S_SCLK: 160_000_000 - I2S clock frequency 10 | //! * I2S_DEFAULT_CLK_SRC: 2 - I2S clock source 11 | 12 | crate::unstable_module! { 13 | pub mod efuse; 14 | pub mod trng; 15 | } 16 | pub mod gpio; 17 | pub mod peripherals; 18 | pub(crate) mod regi2c; 19 | 20 | #[allow(unused)] 21 | pub(crate) mod registers { 22 | pub const INTERRUPT_MAP_BASE: u32 = 0x600c2000; 23 | } 24 | 25 | #[cfg_attr(not(feature = "unstable"), allow(unused))] 26 | pub(crate) mod constants { 27 | use crate::time::Rate; 28 | 29 | /// The base clock frequency for the I2S peripheral (Hertz). 30 | pub const I2S_SCLK: u32 = 160_000_000; 31 | /// The default clock source for I2S operations. 32 | pub const I2S_DEFAULT_CLK_SRC: u8 = 2; 33 | 34 | /// RMT Clock source value. 35 | pub const RMT_CLOCK_SRC: u8 = 1; 36 | /// RMT Clock source frequency. 37 | pub const RMT_CLOCK_SRC_FREQ: Rate = Rate::from_mhz(80); 38 | 39 | /// RC FAST Clock value (Hertz). 40 | pub const RC_FAST_CLK: Rate = Rate::from_khz(17500); 41 | } 42 | 43 | pub(crate) fn pre_init() {} 44 | -------------------------------------------------------------------------------- /esp-hal/src/soc/psram_common.rs: -------------------------------------------------------------------------------- 1 | /// Size of PSRAM 2 | /// 3 | /// [PsramSize::AutoDetect] will try to detect the size of PSRAM 4 | #[derive(Copy, Clone, Debug, Default, PartialEq)] 5 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] 6 | pub enum PsramSize { 7 | /// Detect PSRAM size 8 | #[default] 9 | AutoDetect, 10 | /// A fixed PSRAM size 11 | Size(usize), 12 | } 13 | 14 | impl PsramSize { 15 | pub(crate) fn get(&self) -> usize { 16 | match self { 17 | PsramSize::AutoDetect => 0, 18 | PsramSize::Size(size) => *size, 19 | } 20 | } 21 | 22 | pub(crate) fn is_auto(&self) -> bool { 23 | matches!(self, PsramSize::AutoDetect) 24 | } 25 | } 26 | 27 | /// Returns the address and size of the available in external memory. 28 | #[cfg(feature = "psram")] 29 | pub fn psram_raw_parts(_psram: &crate::peripherals::PSRAM<'_>) -> (*mut u8, usize) { 30 | let range = crate::soc::psram_range(); 31 | (range.start as *mut u8, range.end - range.start) 32 | } 33 | -------------------------------------------------------------------------------- /esp-ieee802154/MIGRATING-0.4.md: -------------------------------------------------------------------------------- 1 | # Migration Guide from 0.4.x to v0.5.x 2 | 3 | ## Crate configuration changes 4 | 5 | To prevent ambiguity between configurations, we had to change the naming format of configuration 6 | keys. Before, we used `{prefix}_{key}`, which meant that esp-hal and esp-hal-* configuration keys 7 | were impossible to tell apart. To fix this issue, we are changing the separator from one underscore 8 | character to `_CONFIG_`. This also means that users will have to change their `config.toml` 9 | configurations to match the new format. 10 | 11 | ```diff 12 | [env] 13 | -ESP_IEEE802154_RX_QUEUE_SIZE = "50" 14 | +ESP_IEEE802154_CONFIG_RX_QUEUE_SIZE = "50" 15 | ``` 16 | -------------------------------------------------------------------------------- /esp-ieee802154/MIGRATING-0.7.0.md: -------------------------------------------------------------------------------- 1 | # Migration Guide from 0.7.0 to {{currentVersion}} 2 | -------------------------------------------------------------------------------- /esp-ieee802154/README.md: -------------------------------------------------------------------------------- 1 | # esp-ieee802154 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/esp-ieee802154?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-ieee802154) 4 | [![docs.rs](https://img.shields.io/docsrs/esp-ieee802154?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.espressif.com/projects/rust/esp-ieee802154/latest/) 5 | ![MSRV](https://img.shields.io/badge/MSRV-1.84-blue?labelColor=1C2C2E&style=flat-square) 6 | ![Crates.io](https://img.shields.io/crates/l/esp-ieee802154?labelColor=1C2C2E&style=flat-square) 7 | [![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) 8 | 9 | Low-level [IEEE 802.15.4] driver for the ESP32-C6 and ESP32-H2. 10 | 11 | Implements the PHY/MAC layers of the IEEE802.15.4 protocol stack, and supports sending and receiving of raw frames. 12 | 13 | [IEEE 802.15.4]: https://en.wikipedia.org/wiki/IEEE_802.15.4 14 | 15 | ## [Documentation](https://docs.espressif.com/projects/rust/esp-ieee802154/latest/) 16 | 17 | ## Minimum Supported Rust Version (MSRV) 18 | 19 | This crate is guaranteed to compile when using the latest stable Rust version at the time of the crate's release. It _might_ compile with older versions, but that may change in any new release, including patches. 20 | 21 | ## License 22 | 23 | Licensed under either of: 24 | 25 | - Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 26 | - MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) 27 | 28 | at your option. 29 | 30 | ### Contribution 31 | 32 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in 33 | the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without 34 | any additional terms or conditions. 35 | -------------------------------------------------------------------------------- /esp-ieee802154/build.rs: -------------------------------------------------------------------------------- 1 | use std::{env, path::PathBuf}; 2 | 3 | use esp_config::{ConfigOption, Validator, generate_config}; 4 | 5 | fn main() { 6 | let out = PathBuf::from(env::var_os("OUT_DIR").unwrap()); 7 | println!("cargo:rustc-link-search={}", out.display()); 8 | 9 | // emit config 10 | generate_config( 11 | "esp_ieee802154", 12 | &[ 13 | ConfigOption::new("rx_queue_size", "Size of the RX queue in frames", 50) 14 | .constraint(Validator::PositiveInteger), 15 | ], 16 | true, 17 | true, 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /esp-ieee802154/src/frame.rs: -------------------------------------------------------------------------------- 1 | use heapless::Vec; 2 | use ieee802154::mac::{FrameContent, Header}; 3 | 4 | pub(crate) const FRAME_SIZE: usize = 129; 5 | pub(crate) const FRAME_VERSION_1: u8 = 0x10; // IEEE 802.15.4 - 2006 & 2011 6 | pub(crate) const FRAME_VERSION_2: u8 = 0x20; // IEEE 802.15.4 - 2015 7 | 8 | const FRAME_AR_OFFSET: usize = 1; 9 | const FRAME_AR_BIT: u8 = 0x20; 10 | const FRAME_VERSION_OFFSET: usize = 2; 11 | const FRAME_VERSION_MASK: u8 = 0x30; 12 | 13 | /// IEEE 802.15.4 MAC frame 14 | #[derive(Debug, Clone, PartialEq, Eq)] 15 | pub struct Frame { 16 | /// Header 17 | pub header: Header, 18 | /// Content 19 | pub content: FrameContent, 20 | /// Payload 21 | pub payload: Vec, 22 | /// This is a 2-byte CRC checksum 23 | pub footer: [u8; 2], 24 | } 25 | 26 | /// IEEE 802.15.4 MAC frame which has been received 27 | #[derive(Debug, Clone, PartialEq, Eq)] 28 | pub struct ReceivedFrame { 29 | /// Frame 30 | pub frame: Frame, 31 | /// Receiver channel 32 | pub channel: u8, 33 | /// Received Signal Strength Indicator (RSSI) 34 | pub rssi: i8, 35 | /// Link Quality Indication (LQI) 36 | pub lqi: u8, 37 | } 38 | 39 | pub(crate) fn frame_is_ack_required(frame: &[u8]) -> bool { 40 | if frame.len() <= FRAME_AR_OFFSET { 41 | return false; 42 | } 43 | (frame[FRAME_AR_OFFSET] & FRAME_AR_BIT) != 0 44 | } 45 | 46 | pub(crate) fn frame_get_version(frame: &[u8]) -> u8 { 47 | if frame.len() <= FRAME_VERSION_OFFSET { 48 | return 0; 49 | } 50 | frame[FRAME_VERSION_OFFSET] & FRAME_VERSION_MASK 51 | } 52 | -------------------------------------------------------------------------------- /esp-lp-hal/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [alias] 2 | esp32c6 = "build --release --examples --features=esp32c6 --target riscv32imac-unknown-none-elf" 3 | esp32s2 = "build --release --example=blinky --features=esp32s2 --target riscv32imc-unknown-none-elf" 4 | esp32s3 = "build --release --example=blinky --features=esp32s3 --target riscv32imc-unknown-none-elf" 5 | 6 | [build] 7 | # target = "riscv32imc-unknown-none-elf" # ESP32-S2 + ESP32-S3 8 | target = "riscv32imac-unknown-none-elf" # ESP32-C6 9 | 10 | [target.'cfg(target_arch = "riscv32")'] 11 | rustflags = [ 12 | "-C", "link-arg=-Tlink.x", 13 | ] 14 | 15 | [unstable] 16 | build-std = ["core"] 17 | -------------------------------------------------------------------------------- /esp-lp-hal/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ### Added 11 | 12 | 13 | ### Changed 14 | 15 | 16 | ### Fixed 17 | 18 | 19 | ### Removed 20 | 21 | 22 | ## [v0.2.0] - 2025-06-03 23 | 24 | ### Changed 25 | 26 | - Fix gpio `input_state` and `output_state` for the ESP32-S3 and ESP32-S2 (#3191) 27 | - Bump Rust edition to 2024, bump MSRV to 1.86. (#2951, #3391, #3560) 28 | 29 | ### Removed 30 | 31 | - Remove embedded-hal 0.2.x impls and dependency from esp-lp-hal package (#2609) 32 | 33 | ## 0.1.0 - 2024-07-15 34 | 35 | ### Added 36 | 37 | - Add the `esp32c6-lp-hal` package (#714) 38 | - Add GPIO (output) and delay functionality to `esp32c6-lp-hal` (#715) 39 | - Add GPIO input support and implement additional `embedded-hal` output traits for the C6's LP core (#720) 40 | - Add the `ulp-riscv-hal` package (#840) 41 | - Add LP_UART basic driver (#1113) 42 | - Added basic `LP-I2C` driver for C6 (#1185) 43 | - Add remaining GPIO pins for ESP32-S2/S3 (#1695) 44 | - Add `wake_hp_core` for ESP32-C6 (#1723) 45 | - Implement `embedded-hal@1.x.x` traits by default instead of `embedded-hal@0.2.x` (#1754) 46 | - Implement `embedded-hal-nb` and `embedded-io` traits for UART driver (#1754) 47 | - Add `Delay.delay_millis` function (#1789) 48 | - Make some UART functions public, allowing it to be used without `embedded-hal`/`embedded-io` traits (#1789) 49 | 50 | ### Changed 51 | 52 | - Renamed to `esp-ulp-riscv-hal` (#916) 53 | - Remove 2nd level generics from GPIO pin (#1526) 54 | - GPIO Input/Output types have been converted to unit structs (#1754) 55 | 56 | [v0.2.0]: https://github.com/esp-rs/esp-hal/releases/tag/esp-lp-hal-v0.2.0 57 | [Unreleased]: https://github.com/esp-rs/esp-hal/compare/esp-lp-hal-v0.2.0...HEAD 58 | -------------------------------------------------------------------------------- /esp-lp-hal/build.rs: -------------------------------------------------------------------------------- 1 | use std::{env, error::Error, fs, path::PathBuf}; 2 | 3 | use esp_build::assert_unique_used_features; 4 | 5 | fn main() -> Result<(), Box> { 6 | // NOTE: update when adding new device support! 7 | // Ensure that exactly one chip has been specified: 8 | assert_unique_used_features!("esp32c6", "esp32s2", "esp32s3"); 9 | 10 | // NOTE: update when adding new device support! 11 | // Determine the name of the configured device: 12 | let device_name = if cfg!(feature = "esp32c6") { 13 | "esp32c6" 14 | } else if cfg!(feature = "esp32s2") { 15 | "esp32s2" 16 | } else if cfg!(feature = "esp32s3") { 17 | "esp32s3" 18 | } else { 19 | unreachable!() // We've confirmed exactly one known device was selected 20 | }; 21 | 22 | // Define all necessary configuration symbols for the configured device: 23 | println!("cargo:rustc-cfg={device_name}"); 24 | 25 | // Put the linker script somewhere the linker can find it: 26 | let out = PathBuf::from(env::var_os("OUT_DIR").unwrap()); 27 | println!("cargo:rustc-link-search={}", out.display()); 28 | 29 | // Copy the required linker script to the `out` directory: 30 | if cfg!(feature = "esp32c6") { 31 | fs::copy("ld/link-lp.x", out.join("link.x"))?; 32 | println!("cargo:rerun-if-changed=ld/link-lp.x"); 33 | } else if cfg!(feature = "esp32s2") || cfg!(feature = "esp32s3") { 34 | fs::copy("ld/link-ulp.x", out.join("link.x"))?; 35 | println!("cargo:rerun-if-changed=ld/link-ulp.x"); 36 | } 37 | 38 | // Done! 39 | Ok(()) 40 | } 41 | -------------------------------------------------------------------------------- /esp-lp-hal/examples/blinky.rs: -------------------------------------------------------------------------------- 1 | //! Counts a 32 bit value at a known point in memory, and blink GPIO1. 2 | //! 3 | //! When using the ESP32-C6's LP core, this address in memory is `0x5000_2000`. 4 | //! 5 | //! When using the ESP32-S2 or ESP32-S3's ULP core, this address in memory is 6 | //! `0x5000_0400` (but is `0x400`` from the ULP's point of view!). 7 | //! 8 | //! Make sure the LP RAM is cleared before loading the code. 9 | 10 | #![no_std] 11 | #![no_main] 12 | 13 | use embedded_hal::{delay::DelayNs, digital::OutputPin}; 14 | use esp_lp_hal::{delay::Delay, gpio::Output, prelude::*}; 15 | use panic_halt as _; 16 | 17 | cfg_if::cfg_if! { 18 | if #[cfg(feature = "esp32c6")] { 19 | const ADDRESS: u32 = 0x5000_2000; 20 | } else if #[cfg(any(feature = "esp32s2", feature = "esp32s3"))] { 21 | const ADDRESS: u32 = 0x400; 22 | } 23 | } 24 | 25 | #[entry] 26 | fn main(mut gpio1: Output<1>) -> ! { 27 | let mut i: u32 = 0; 28 | 29 | let ptr = ADDRESS as *mut u32; 30 | 31 | loop { 32 | i = i.wrapping_add(1u32); 33 | unsafe { 34 | ptr.write_volatile(i); 35 | } 36 | 37 | gpio1.set_high().unwrap(); 38 | Delay.delay_ms(500); 39 | 40 | gpio1.set_low().unwrap(); 41 | Delay.delay_ms(500); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /esp-lp-hal/examples/i2c.rs: -------------------------------------------------------------------------------- 1 | //! Uses `LP_I2C` and reads calibration data from BMP180 sensor. 2 | //! 3 | //! This example dumps the calibration data from a BMP180 sensor, to view them, 4 | //! logic analyzer or oscilloscope is required. 5 | //! 6 | //! The following wiring is assumed: 7 | //! - SDA => GPIO6 8 | //! - SCL => GPIO7 9 | 10 | //% CHIPS: esp32c6 11 | 12 | #![no_std] 13 | #![no_main] 14 | 15 | use esp_lp_hal::{i2c::LpI2c, prelude::*}; 16 | use panic_halt as _; 17 | 18 | #[entry] 19 | fn main(mut i2c: LpI2c) -> ! { 20 | let _peripherals = esp32c6_lp::Peripherals::take().unwrap(); 21 | 22 | loop { 23 | let mut data = [0u8; 22]; 24 | i2c.write_read(0x77, &[0xaa], &mut data).ok(); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /esp-lp-hal/examples/uart.rs: -------------------------------------------------------------------------------- 1 | //! Uses `LP_UART` and logs "Hello World from LP Core". 2 | //! 3 | //! Uses GPIO4 for RX and GPIO5 for TX. GPIOs can't be changed. 4 | //! 5 | //! It is neccessary to use Serial-Uart bridge connected to TX and RX to see 6 | //! logs from LP_UART. Make sure the LP RAM is cleared before loading the code. 7 | 8 | //% CHIPS: esp32c6 9 | 10 | #![no_std] 11 | #![no_main] 12 | 13 | use core::fmt::Write; 14 | 15 | use embedded_hal::delay::DelayNs; 16 | use esp_lp_hal::{delay::Delay, prelude::*, uart::LpUart}; 17 | use panic_halt as _; 18 | 19 | #[entry] 20 | fn main(mut uart: LpUart) -> ! { 21 | loop { 22 | writeln!(uart, "Hello World from LP Core").unwrap(); 23 | Delay.delay_ms(1000); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /esp-lp-hal/ld/link-lp.x: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | ENTRY(reset_vector) 8 | 9 | VECTOR_TABLE_LENGTH = 0x80; 10 | CONFIG_ULP_COPROC_RESERVE_MEM = 1024 * 16; 11 | CONFIG_ULP_SHARED_MEM = 0; 12 | RAM_LENGTH = CONFIG_ULP_COPROC_RESERVE_MEM - VECTOR_TABLE_LENGTH - CONFIG_ULP_SHARED_MEM; 13 | 14 | MEMORY 15 | { 16 | /*first 128byte for exception/interrupt vectors*/ 17 | vector_table(RX) : ORIGIN = 0x50000000, LENGTH = VECTOR_TABLE_LENGTH 18 | ram(RWX) : ORIGIN = 0x50000080, LENGTH = RAM_LENGTH 19 | } 20 | 21 | SECTIONS 22 | { 23 | .vector.text : 24 | { 25 | /* Exception/interrupt vectors */ 26 | __mtvec_base = .; 27 | KEEP (*(.init.vector)) 28 | __mtvec_end = .; 29 | } > vector_table 30 | 31 | . = ORIGIN(ram); 32 | 33 | .text ALIGN(4): 34 | { 35 | *(.text.vectors) /* Default reset vector must link to offset 0x80 */ 36 | 37 | KEEP(*(.init)); 38 | KEEP(*(.init.rust)); 39 | *(.text) 40 | *(.text*) 41 | } > ram 42 | 43 | .rodata ALIGN(4): 44 | { 45 | *(.rodata) 46 | *(.rodata*) 47 | } > ram 48 | 49 | .data ALIGN(4): 50 | { 51 | *(.data) 52 | *(.data*) 53 | *(.sdata) 54 | *(.sdata*) 55 | } > ram 56 | 57 | .bss ALIGN(4) : 58 | { 59 | *(.bss) 60 | *(.bss*) 61 | *(.sbss) 62 | *(.sbss*) 63 | PROVIDE(end = .); 64 | } > ram 65 | 66 | __stack_top = ORIGIN(ram) + LENGTH(ram); 67 | } 68 | -------------------------------------------------------------------------------- /esp-lp-hal/ld/link-ulp.x: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | ENTRY(reset_vector) 8 | 9 | CONFIG_ULP_COPROC_RESERVE_MEM = 8 * 1024; 10 | 11 | MEMORY 12 | { 13 | ram(RW) : ORIGIN = 0, LENGTH = CONFIG_ULP_COPROC_RESERVE_MEM 14 | } 15 | 16 | SECTIONS 17 | { 18 | . = ORIGIN(ram); 19 | 20 | .text : 21 | { 22 | *(.text.vectors) /* Default reset vector must link to offset 0x0 */ 23 | 24 | KEEP(*(.init)); 25 | KEEP(*(.init.rust)); 26 | *(.text) 27 | *(.text*) 28 | } >ram 29 | 30 | .rodata ALIGN(4): 31 | { 32 | *(.rodata) 33 | *(.rodata*) 34 | } > ram 35 | 36 | .data ALIGN(4): 37 | { 38 | *(.data) 39 | *(.data*) 40 | *(.sdata) 41 | *(.sdata*) 42 | } > ram 43 | 44 | .bss ALIGN(4) : 45 | { 46 | *(.bss) 47 | *(.bss*) 48 | *(.sbss) 49 | *(.sbss*) 50 | } >ram 51 | 52 | __stack_top = ORIGIN(ram) + LENGTH(ram); 53 | } 54 | -------------------------------------------------------------------------------- /esp-metadata/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ### Added 11 | 12 | - Added `Config::generate_metadata` to generate code for firmware crates. (#3604) 13 | 14 | ### Changed 15 | 16 | 17 | ### Fixed 18 | 19 | 20 | ### Removed 21 | 22 | - Removed the firmware-side component of the crate. (#3604) 23 | 24 | ## [v0.7.0] - 2025-06-03 25 | 26 | ### Added 27 | 28 | - Add ability to define memory regions, have DRAM defined there (#3300) 29 | - Provide macros to get the start/end of a memory region, make it possible to use the macros in a no-std project (#3300) 30 | 31 | ### Changed 32 | 33 | - Bump Rust edition to 2024, bump MSRV to 1.86. (#3391, #3560) 34 | 35 | ## [0.6.0] - 2025-02-24 36 | 37 | ### Added 38 | 39 | - Introduced the `adc1` and `adc2` symbols (#3082) 40 | 41 | ### Removed 42 | 43 | - Removed the `adc` symbol (#3082) 44 | 45 | ## 0.5.0 - 2025-01-15 46 | 47 | ### Added 48 | 49 | - Introduced the `wifi6` symbol (#2612) 50 | - Introduced the `gpio_bank_1` symbol (#2625) 51 | 52 | ### Changed 53 | 54 | - Bump MSRV to 1.84 (#2951) 55 | 56 | ## 0.4.0 - 2024-10-10 57 | 58 | ## 0.3.0 - 2024-08-29 59 | 60 | ## 0.2.0 - 2024-07-15 61 | 62 | ## 0.1.1 - 2024-06-04 63 | 64 | ## 0.1.0 - 2024-04-17 65 | 66 | ### Added 67 | 68 | - Initial release (#2518) 69 | 70 | [0.6.0]: https://github.com/esp-rs/esp-hal/releases/tag/esp-metadata-v0.6.0 71 | [v0.7.0]: https://github.com/esp-rs/esp-hal/compare/esp-metadata-v0.6.0...esp-metadata-v0.7.0 72 | [Unreleased]: https://github.com/esp-rs/esp-hal/compare/esp-metadata-v0.7.0...HEAD 73 | -------------------------------------------------------------------------------- /esp-metadata/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "esp-metadata" 3 | version = "0.7.0" 4 | edition = "2024" 5 | rust-version = "1.86.0" 6 | description = "Metadata for Espressif devices" 7 | documentation = "https://docs.espressif.com/projects/rust/esp-metadata/latest/" 8 | repository = "https://github.com/esp-rs/esp-hal" 9 | license = "MIT OR Apache-2.0" 10 | 11 | [dependencies] 12 | anyhow = { version = "1.0.98" } 13 | clap = { version = "4.5.37", features = ["derive"], optional = true } 14 | basic-toml = { version = "0.1.9" } 15 | serde = { version = "1.0.219", features = ["derive"] } 16 | strum = { version = "0.27.1", features = ["derive"] } 17 | proc-macro2 = { version = "1.0.36" } 18 | quote = { version = "1.0.15" } 19 | 20 | [features] 21 | default = [] 22 | clap = ["dep:clap"] 23 | -------------------------------------------------------------------------------- /esp-metadata/README.md: -------------------------------------------------------------------------------- 1 | # esp-metadata 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/esp-metadata?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-metadata) 4 | [![docs.rs](https://img.shields.io/docsrs/esp-metadata?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.espressif.com/projects/rust/esp-metadata/latest/) 5 | ![MSRV](https://img.shields.io/badge/MSRV-1.84-blue?labelColor=1C2C2E&style=flat-square) 6 | ![Crates.io](https://img.shields.io/crates/l/esp-metadata?labelColor=1C2C2E&style=flat-square) 7 | [![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) 8 | 9 | Metadata for Espressif devices, intended for use in [build scripts]. 10 | 11 | [build scripts]: https://doc.rust-lang.org/cargo/reference/build-scripts.html 12 | 13 | ## [Documentation](https://docs.espressif.com/projects/rust/esp-metadata/latest/) 14 | 15 | ## Minimum Supported Rust Version (MSRV) 16 | 17 | This crate is guaranteed to compile when using the latest stable Rust version at the time of the crate's release. It _might_ compile with older versions, but that may change in any new release, including patches. 18 | 19 | ## License 20 | 21 | Licensed under either of: 22 | 23 | - Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 24 | - MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) 25 | 26 | at your option. 27 | 28 | ### Contribution 29 | 30 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in 31 | the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without 32 | any additional terms or conditions. 33 | -------------------------------------------------------------------------------- /esp-metadata/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Metadata for Espressif devices, primarily intended for use in build scripts. 2 | mod generate_cfg; 3 | 4 | pub use generate_cfg::*; 5 | -------------------------------------------------------------------------------- /esp-println/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [unstable] 2 | build-std = ["alloc", "core"] 3 | -------------------------------------------------------------------------------- /esp-println/.clippy.toml: -------------------------------------------------------------------------------- 1 | avoid-breaking-exported-api = false 2 | -------------------------------------------------------------------------------- /esp-riscv-rt/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "esp-riscv-rt" 3 | version = "0.11.0" 4 | edition = "2024" 5 | rust-version = "1.86.0" 6 | description = "Minimal runtime / startup for RISC-V CPUs from Espressif" 7 | documentation = "https://docs.espressif.com/projects/rust/esp-riscv-rt/latest/" 8 | keywords = ["esp32", "espressif", "riscv", "runtime", "startup"] 9 | categories = ["embedded", "hardware-support", "no-std"] 10 | repository = "https://github.com/esp-rs/esp-hal" 11 | license = "MIT OR Apache-2.0" 12 | 13 | [lib] 14 | bench = false 15 | test = false 16 | 17 | [dependencies] 18 | document-features = "0.2.11" 19 | riscv = "0.12.1" 20 | riscv-rt-macros = "0.4.0" 21 | 22 | [features] 23 | ## Indicate that the device supports `mie` and `mip` instructions. 24 | has-mie-mip = [] 25 | ## Indicate that the device has RTC RAM. 26 | rtc-ram = [] 27 | 28 | # This feature is intended for testing; you probably don't want to enable it: 29 | ci = ["has-mie-mip", "rtc-ram"] 30 | -------------------------------------------------------------------------------- /esp-riscv-rt/README.md: -------------------------------------------------------------------------------- 1 | # esp-riscv-rt 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/esp-riscv-rt?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/esp-riscv-rt) 4 | [![docs.rs](https://img.shields.io/docsrs/esp-riscv-rt?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.espressif.com/projects/rust/esp-riscv-rt/latest/) 5 | ![MSRV](https://img.shields.io/badge/MSRV-1.84-blue?labelColor=1C2C2E&style=flat-square) 6 | ![Crates.io](https://img.shields.io/crates/l/esp-riscv-rt?labelColor=1C2C2E&style=flat-square) 7 | [![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) 8 | 9 | Minimal runtime / startup for RISC-V devices from Espressif. 10 | 11 | Much of the code in this package originated in the [rust-embedded/riscv] repository. 12 | 13 | [rust-embedded/riscv]: https://github.com/rust-embedded/riscv 14 | 15 | ## [Documentation](https://docs.espressif.com/projects/rust/esp-riscv-rt/latest/) 16 | 17 | ## Minimum Supported Rust Version (MSRV) 18 | 19 | This crate is guaranteed to compile when using the latest stable Rust version at the time of the crate's release. It _might_ compile with older versions, but that may change in any new release, including patches. 20 | 21 | ## License 22 | 23 | Licensed under either of: 24 | 25 | - Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) 26 | - MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) 27 | 28 | at your option. 29 | 30 | ### Contribution 31 | 32 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in 33 | the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without 34 | any additional terms or conditions. 35 | -------------------------------------------------------------------------------- /esp-storage/.clippy.toml: -------------------------------------------------------------------------------- 1 | avoid-breaking-exported-api = false 2 | -------------------------------------------------------------------------------- /esp-storage/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ### Added 11 | 12 | 13 | ### Changed 14 | 15 | 16 | ### Fixed 17 | 18 | 19 | ### Removed 20 | 21 | 22 | ## [v0.6.0] - 2025-06-03 23 | 24 | ### Changed 25 | 26 | - Bump Rust edition to 2024, bump MSRV to 1.86. (#3391, #3560) 27 | - The `low-level` feature has been removed, the gated API is always available (#3425) 28 | 29 | ### Removed 30 | 31 | - The `storage` and `nor-flash` features have been removed, the related functionality is now always available. (#3431) 32 | 33 | ## [0.5.0] - 2025-02-24 34 | 35 | ### Changed 36 | 37 | - Bump MSRV to 1.84 (#2951) 38 | - Add support for 32MB flash (#3163) 39 | 40 | ## 0.4.0 - 2024-11-20 41 | 42 | ### Added 43 | 44 | - Added trait MultiwriteNorFlash to FlashStorage (#2478) 45 | 46 | ## 0.3.1 - 2024-10-10 47 | 48 | ## 0.3.0 - 2023-08-16 49 | 50 | ## 0.2.0 - 2023-07-05 51 | 52 | ## 0.1.0 - 2022-09-26 53 | 54 | [0.5.0]: https://github.com/esp-rs/esp-hal/releases/tag/esp-storage-v0.5.0 55 | [v0.6.0]: https://github.com/esp-rs/esp-hal/compare/esp-storage-v0.5.0...esp-storage-v0.6.0 56 | [Unreleased]: https://github.com/esp-rs/esp-hal/compare/esp-storage-v0.6.0...HEAD 57 | -------------------------------------------------------------------------------- /esp-storage/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "esp-storage" 3 | version = "0.6.0" 4 | edition = "2024" 5 | rust-version = "1.86.0" 6 | description = "Implementation of embedded-storage traits to access unencrypted ESP32 flash" 7 | documentation = "https://docs.espressif.com/projects/rust/esp-storage/latest/" 8 | keywords = ["embedded-storage", "esp32", "espressif", "no-std"] 9 | categories = ["embedded", "hardware-support", "no-std"] 10 | repository = "https://github.com/esp-rs/esp-hal" 11 | license = "MIT OR Apache-2.0" 12 | 13 | [package.metadata.docs.rs] 14 | default-target = "riscv32imac-unknown-none-elf" 15 | features = ["esp32c6"] 16 | 17 | [lib] 18 | bench = false 19 | test = false 20 | 21 | [dependencies] 22 | embedded-storage = "0.3.1" 23 | 24 | # Optional dependencies 25 | critical-section = { version = "1.2.0", optional = true } 26 | 27 | # Unstable dependencies that are not (strictly) part of the public API 28 | document-features = "0.2.11" 29 | 30 | [build-dependencies] 31 | esp-build = { version = "0.3.0", path = "../esp-build" } 32 | esp-metadata = { version = "0.7.0", path = "../esp-metadata" } 33 | 34 | [features] 35 | default = ["critical-section"] 36 | 37 | ## Place the flash operations in a critical section 38 | critical-section = ["dep:critical-section"] 39 | 40 | ## Bytewise read emulation 41 | bytewise-read = [] 42 | 43 | #! ### Chip selection 44 | #! One of the following features must be enabled to select the target chip: 45 | 46 | # The following trailing spaces ("## ") are important to display the feature names. 47 | 48 | ## 49 | esp32c2 = [] 50 | ## 51 | esp32c3 = [] 52 | ## 53 | esp32c6 = [] 54 | ## 55 | esp32h2 = [] 56 | ## 57 | esp32 = [] 58 | ## 59 | esp32s2 = [] 60 | ## 61 | esp32s3 = [] 62 | ## Used for testing on a host. 63 | emulation = [] 64 | -------------------------------------------------------------------------------- /esp-storage/build.rs: -------------------------------------------------------------------------------- 1 | fn main() -> Result<(), String> { 2 | // Ensure that only a single chip is specified 3 | if !cfg!(feature = "emulation") { 4 | let _ = esp_metadata::Chip::from_cargo_feature().map_err(|e| format!("{e:?}"))?; 5 | } 6 | 7 | if cfg!(feature = "esp32") { 8 | match std::env::var("OPT_LEVEL") { 9 | Ok(level) if std::env::var("CI").is_err() => { 10 | if level != "2" && level != "3" && level != "s" { 11 | Err(format!( 12 | "Building esp-storage for ESP32 needs optimization level 2, 3 or s - yours is {level}. See https://github.com/esp-rs/esp-storage" 13 | )) 14 | } else { 15 | Ok(()) 16 | } 17 | } 18 | _ => Ok(()), 19 | } 20 | } else { 21 | Ok(()) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /esp-storage/src/esp32c2.rs: -------------------------------------------------------------------------------- 1 | use crate::maybe_with_critical_section; 2 | 3 | crate::rom_fn! { 4 | fn esp_rom_spiflash_read(src_addr: u32, data: *const u32, len: u32) -> i32 = 0x4000013c; 5 | fn esp_rom_spiflash_unlock() -> i32 = 0x40000140; 6 | fn esp_rom_spiflash_erase_sector(sector_number: u32) -> i32 = 0x40000130; 7 | fn esp_rom_spiflash_write(dest_addr: u32, data: *const u32, len: u32) -> i32 = 0x40000138; 8 | } 9 | 10 | pub(crate) fn spiflash_read(src_addr: u32, data: *const u32, len: u32) -> i32 { 11 | maybe_with_critical_section(|| esp_rom_spiflash_read(src_addr, data, len)) 12 | } 13 | 14 | pub(crate) fn spiflash_unlock() -> i32 { 15 | maybe_with_critical_section(esp_rom_spiflash_unlock) 16 | } 17 | 18 | pub(crate) fn spiflash_erase_sector(sector_number: u32) -> i32 { 19 | maybe_with_critical_section(|| esp_rom_spiflash_erase_sector(sector_number)) 20 | } 21 | 22 | pub(crate) fn spiflash_write(dest_addr: u32, data: *const u32, len: u32) -> i32 { 23 | maybe_with_critical_section(|| esp_rom_spiflash_write(dest_addr, data, len)) 24 | } 25 | -------------------------------------------------------------------------------- /esp-storage/src/esp32c3.rs: -------------------------------------------------------------------------------- 1 | use crate::maybe_with_critical_section; 2 | 3 | crate::rom_fn! { 4 | fn esp_rom_spiflash_read(src_addr: u32, data: *const u32, len: u32) -> i32 = 0x40000130; 5 | fn esp_rom_spiflash_unlock() -> i32 = 0x40000140; 6 | fn esp_rom_spiflash_erase_sector(sector_number: u32) -> i32 = 0x40000128; 7 | fn esp_rom_spiflash_write(dest_addr: u32, data: *const u32, len: u32) -> i32 = 0x4000012c; 8 | } 9 | 10 | pub(crate) fn spiflash_read(src_addr: u32, data: *const u32, len: u32) -> i32 { 11 | maybe_with_critical_section(|| esp_rom_spiflash_read(src_addr, data, len)) 12 | } 13 | 14 | pub(crate) fn spiflash_unlock() -> i32 { 15 | maybe_with_critical_section(esp_rom_spiflash_unlock) 16 | } 17 | 18 | pub(crate) fn spiflash_erase_sector(sector_number: u32) -> i32 { 19 | maybe_with_critical_section(|| esp_rom_spiflash_erase_sector(sector_number)) 20 | } 21 | 22 | pub(crate) fn spiflash_write(dest_addr: u32, data: *const u32, len: u32) -> i32 { 23 | maybe_with_critical_section(|| esp_rom_spiflash_write(dest_addr, data, len)) 24 | } 25 | -------------------------------------------------------------------------------- /esp-storage/src/esp32c6.rs: -------------------------------------------------------------------------------- 1 | use crate::maybe_with_critical_section; 2 | 3 | crate::rom_fn! { 4 | fn esp_rom_spiflash_read(src_addr: u32, data: *const u32, len: u32) -> i32 = 0x40000150; 5 | fn esp_rom_spiflash_unlock() -> i32 = 0x40000154; 6 | fn esp_rom_spiflash_erase_sector(sector_number: u32) -> i32 = 0x40000144; 7 | fn esp_rom_spiflash_write(dest_addr: u32, data: *const u32, len: u32) -> i32 = 0x4000014c; 8 | } 9 | 10 | pub(crate) fn spiflash_read(src_addr: u32, data: *const u32, len: u32) -> i32 { 11 | maybe_with_critical_section(|| esp_rom_spiflash_read(src_addr, data, len)) 12 | } 13 | 14 | pub(crate) fn spiflash_unlock() -> i32 { 15 | maybe_with_critical_section(esp_rom_spiflash_unlock) 16 | } 17 | 18 | pub(crate) fn spiflash_erase_sector(sector_number: u32) -> i32 { 19 | maybe_with_critical_section(|| esp_rom_spiflash_erase_sector(sector_number)) 20 | } 21 | 22 | pub(crate) fn spiflash_write(dest_addr: u32, data: *const u32, len: u32) -> i32 { 23 | maybe_with_critical_section(|| esp_rom_spiflash_write(dest_addr, data, len)) 24 | } 25 | -------------------------------------------------------------------------------- /esp-storage/src/esp32h2.rs: -------------------------------------------------------------------------------- 1 | use crate::maybe_with_critical_section; 2 | 3 | crate::rom_fn! { 4 | fn esp_rom_spiflash_read(src_addr: u32, data: *const u32, len: u32) -> i32 = 0x4000012c; 5 | fn esp_rom_spiflash_unlock() -> i32 = 0x40000130; 6 | fn esp_rom_spiflash_erase_sector(sector_number: u32) -> i32 = 0x40000120; 7 | fn esp_rom_spiflash_write(dest_addr: u32, data: *const u32, len: u32) -> i32 = 0x40000128; 8 | } 9 | 10 | pub(crate) fn spiflash_read(src_addr: u32, data: *const u32, len: u32) -> i32 { 11 | maybe_with_critical_section(|| esp_rom_spiflash_read(src_addr, data, len)) 12 | } 13 | 14 | pub(crate) fn spiflash_unlock() -> i32 { 15 | maybe_with_critical_section(esp_rom_spiflash_unlock) 16 | } 17 | 18 | pub(crate) fn spiflash_erase_sector(sector_number: u32) -> i32 { 19 | maybe_with_critical_section(|| esp_rom_spiflash_erase_sector(sector_number)) 20 | } 21 | 22 | pub(crate) fn spiflash_write(dest_addr: u32, data: *const u32, len: u32) -> i32 { 23 | maybe_with_critical_section(|| esp_rom_spiflash_write(dest_addr, data, len)) 24 | } 25 | -------------------------------------------------------------------------------- /esp-storage/src/esp32s2.rs: -------------------------------------------------------------------------------- 1 | use crate::maybe_with_critical_section; 2 | 3 | crate::rom_fn! { 4 | fn esp_rom_spiflash_read(src_addr: u32, data: *const u32, len: u32) -> i32 = 0x4001728c; 5 | fn esp_rom_spiflash_unlock() -> i32 = 0x40016e88; 6 | fn esp_rom_spiflash_erase_sector(sector_number: u32) -> i32 = 0x4001716c; 7 | fn esp_rom_spiflash_write(dest_addr: u32, data: *const u32, len: u32) -> i32 = 0x400171cc; 8 | } 9 | 10 | pub(crate) fn spiflash_read(src_addr: u32, data: *const u32, len: u32) -> i32 { 11 | maybe_with_critical_section(|| esp_rom_spiflash_read(src_addr, data, len)) 12 | } 13 | 14 | pub(crate) fn spiflash_unlock() -> i32 { 15 | maybe_with_critical_section(esp_rom_spiflash_unlock) 16 | } 17 | 18 | pub(crate) fn spiflash_erase_sector(sector_number: u32) -> i32 { 19 | maybe_with_critical_section(|| esp_rom_spiflash_erase_sector(sector_number)) 20 | } 21 | 22 | pub(crate) fn spiflash_write(dest_addr: u32, data: *const u32, len: u32) -> i32 { 23 | maybe_with_critical_section(|| esp_rom_spiflash_write(dest_addr, data, len)) 24 | } 25 | -------------------------------------------------------------------------------- /esp-storage/src/esp32s3.rs: -------------------------------------------------------------------------------- 1 | use crate::maybe_with_critical_section; 2 | 3 | crate::rom_fn! { 4 | fn esp_rom_spiflash_read(src_addr: u32, data: *const u32, len: u32) -> i32 = 0x40000a20; 5 | fn esp_rom_spiflash_unlock() -> i32 = 0x40000a2c; 6 | fn esp_rom_spiflash_erase_sector(sector_number: u32) -> i32 = 0x400009fc; 7 | fn esp_rom_spiflash_write(dest_addr: u32, data: *const u32, len: u32) -> i32 = 0x40000a14; 8 | } 9 | 10 | #[inline(always)] 11 | #[unsafe(link_section = ".rwtext")] 12 | pub(crate) fn spiflash_read(src_addr: u32, data: *const u32, len: u32) -> i32 { 13 | maybe_with_critical_section(|| esp_rom_spiflash_read(src_addr, data, len)) 14 | } 15 | 16 | #[inline(always)] 17 | #[unsafe(link_section = ".rwtext")] 18 | pub(crate) fn spiflash_unlock() -> i32 { 19 | maybe_with_critical_section(esp_rom_spiflash_unlock) 20 | } 21 | 22 | #[inline(always)] 23 | #[unsafe(link_section = ".rwtext")] 24 | pub(crate) fn spiflash_erase_sector(sector_number: u32) -> i32 { 25 | maybe_with_critical_section(|| esp_rom_spiflash_erase_sector(sector_number)) 26 | } 27 | 28 | #[inline(always)] 29 | #[unsafe(link_section = ".rwtext")] 30 | pub(crate) fn spiflash_write(dest_addr: u32, data: *const u32, len: u32) -> i32 { 31 | maybe_with_critical_section(|| esp_rom_spiflash_write(dest_addr, data, len)) 32 | } 33 | -------------------------------------------------------------------------------- /esp-storage/src/ll.rs: -------------------------------------------------------------------------------- 1 | //! # Low-level API 2 | //! 3 | //! ⚠️ This is a low-level API and should be used with caution. ⚠️ 4 | //! 5 | //! This gives you access to the underlying low level functionality. 6 | //! These operate on raw pointers and all functions here are unsafe. 7 | //! No pre-conditions are checked by any of these functions. 8 | 9 | use crate::chip_specific; 10 | 11 | /// Low-level SPI NOR Flash read 12 | /// 13 | /// # Safety 14 | /// 15 | /// The `src_addr` + `len` should not exceeds the size of flash. 16 | /// The `data` expected to points to word-aligned pre-allocated buffer with size 17 | /// greater or equals to `len`. 18 | pub unsafe fn spiflash_read(src_addr: u32, data: *mut u32, len: u32) -> Result<(), i32> { 19 | match chip_specific::spiflash_read(src_addr, data, len) { 20 | 0 => Ok(()), 21 | value => Err(value), 22 | } 23 | } 24 | 25 | /// Low-level SPI NOR Flash unlock 26 | /// 27 | /// # Safety 28 | pub unsafe fn spiflash_unlock() -> Result<(), i32> { 29 | match chip_specific::spiflash_unlock() { 30 | 0 => Ok(()), 31 | value => Err(value), 32 | } 33 | } 34 | 35 | /// Low-level SPI NOR Flash erase 36 | /// 37 | /// # Safety 38 | /// 39 | /// The `sector_number` * sector_size should not exceeds the size of flash. 40 | pub unsafe fn spiflash_erase_sector(sector_number: u32) -> Result<(), i32> { 41 | match chip_specific::spiflash_erase_sector(sector_number) { 42 | 0 => Ok(()), 43 | value => Err(value), 44 | } 45 | } 46 | 47 | /// Low-level SPI NOR Flash write 48 | /// 49 | /// # Safety 50 | /// 51 | /// The `dest_addr` + `len` should not exceeds the size of flash. 52 | /// The `data` expected to points to word-aligned buffer with size greater or 53 | /// equals to `len`. 54 | pub unsafe fn spiflash_write(dest_addr: u32, data: *const u32, len: u32) -> Result<(), i32> { 55 | match chip_specific::spiflash_write(dest_addr, data, len) { 56 | 0 => Ok(()), 57 | value => Err(value), 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /esp-wifi/.clippy.toml: -------------------------------------------------------------------------------- 1 | avoid-breaking-exported-api = false 2 | -------------------------------------------------------------------------------- /esp-wifi/MIGRATING-0.13.md: -------------------------------------------------------------------------------- 1 | # Migration Guide from 0.13.x to 0.14.0 2 | 3 | ## Initializing esp-wifi 4 | 5 | esp-wifi can no longer be initialized with a `PeriodicTimer`. 6 | 7 | ## Initializing esp-now 8 | 9 | An instance of `esp-now` is now available via the wifi interfaces - there are no separate constructors anymore. 10 | 11 | ```diff 12 | - let mut esp_now = esp_wifi::esp_now::EspNow::new(&esp_wifi_ctrl, peripherals.WIFI).unwrap(); 13 | + let (mut controller, interfaces) = esp_wifi::wifi::new(&esp_wifi_ctrl, wifi).unwrap(); 14 | + controller.set_mode(esp_wifi::wifi::WifiMode::Sta).unwrap(); 15 | + controller.start().unwrap(); 16 | + 17 | + let mut esp_now = interfaces.esp_now; 18 | ``` 19 | 20 | ## Getting the sniffer 21 | 22 | The sniffer is now part of `Interfaces` 23 | 24 | ```diff 25 | - let mut sniffer = controller.take_sniffer().unwrap(); 26 | + let mut sniffer = interfaces.sniffer; 27 | ``` 28 | 29 | ## The public API is using `alloc` instead of `heapless` now 30 | 31 | General usage doesn't change with some small exceptions. 32 | 33 | ```diff 34 | - let res: Result<(heapless::Vec, usize), WifiError> = controller.scan_n(); 35 | + let res: Result, WifiError> = controller.scan_n(10); 36 | ``` 37 | 38 | Some code can be simplified now. 39 | ```diff 40 | - ssid: SSID.try_into().unwrap(), 41 | - password: PASSWORD.try_into().unwrap(), 42 | + ssid: SSID.into(), 43 | + password: PASSWORD.into(), 44 | ``` 45 | 46 | ## `AccessPointInfo` doesn't include the `protocols` field anymore 47 | 48 | That field was never populated and has been removed. 49 | -------------------------------------------------------------------------------- /esp-wifi/MIGRATING-0.14.0.md: -------------------------------------------------------------------------------- 1 | # Migration Guide from 0.14.0 to {{currentVersion}} 2 | 3 | ## Deinitialization 4 | 5 | `esp_wifi::EspWifiController::deinit` got removed and you should just drop the `EspWifiController` instead. 6 | 7 | ```diff 8 | - esp_wifi_ctrl.deinit(); 9 | + core::mem::drop(esp_wifi_ctrl); 10 | ``` 11 | Since `esp_wifi::deinit_unchecked` is now removed there is no unsafe way to forcefully deinit the controller. 12 | Drop the instance of `EspWifiController` instead (see above). 13 | -------------------------------------------------------------------------------- /esp-wifi/src/compat/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod common; 2 | pub mod malloc; 3 | pub mod misc; 4 | pub mod timer_compat; 5 | 6 | #[unsafe(no_mangle)] 7 | unsafe extern "C" fn _putchar(c: u8) { 8 | static mut BUFFER: [u8; 256] = [0u8; 256]; 9 | static mut IDX: usize = 0; 10 | 11 | unsafe { 12 | let buffer = core::ptr::addr_of_mut!(BUFFER); 13 | if c == 0 || c == b'\n' || IDX == (*buffer).len() - 1 { 14 | if c != 0 { 15 | BUFFER[IDX] = c; 16 | } else { 17 | IDX = IDX.saturating_sub(1); 18 | } 19 | 20 | info!("{}", core::str::from_utf8_unchecked(&BUFFER[..IDX])); 21 | IDX = 0; 22 | } else { 23 | BUFFER[IDX] = c; 24 | IDX += 1; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /esp-wifi/src/config.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | #[cfg_attr(feature = "defmt", derive(defmt::Format))] 3 | /// Tunable parameters for the WiFi driver 4 | #[allow(unused)] // currently there are no ble tunables 5 | pub(crate) struct EspWifiConfig { 6 | pub(crate) rx_queue_size: usize, 7 | pub(crate) tx_queue_size: usize, 8 | pub(crate) static_rx_buf_num: usize, 9 | pub(crate) dynamic_rx_buf_num: usize, 10 | pub(crate) static_tx_buf_num: usize, 11 | pub(crate) dynamic_tx_buf_num: usize, 12 | pub(crate) ampdu_rx_enable: bool, 13 | pub(crate) ampdu_tx_enable: bool, 14 | pub(crate) amsdu_tx_enable: bool, 15 | pub(crate) rx_ba_win: usize, 16 | pub(crate) max_burst_size: usize, 17 | pub(crate) country_code: &'static str, 18 | pub(crate) country_code_operating_class: u8, 19 | pub(crate) mtu: usize, 20 | pub(crate) tick_rate_hz: u32, 21 | pub(crate) listen_interval: u16, 22 | pub(crate) beacon_timeout: u16, 23 | pub(crate) ap_beacon_timeout: u16, 24 | pub(crate) failure_retry_cnt: u8, 25 | pub(crate) scan_method: u32, 26 | } 27 | 28 | #[non_exhaustive] 29 | #[derive(Default)] 30 | pub enum PowerSaveMode { 31 | #[default] 32 | None, 33 | Minimum, 34 | Maximum, 35 | } 36 | 37 | impl From for esp_wifi_sys::include::wifi_ps_type_t { 38 | fn from(s: PowerSaveMode) -> Self { 39 | match s { 40 | PowerSaveMode::None => esp_wifi_sys::include::wifi_ps_type_t_WIFI_PS_NONE, 41 | PowerSaveMode::Minimum => esp_wifi_sys::include::wifi_ps_type_t_WIFI_PS_MIN_MODEM, 42 | PowerSaveMode::Maximum => esp_wifi_sys::include::wifi_ps_type_t_WIFI_PS_MAX_MODEM, 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /esp-wifi/src/memory_fence.rs: -------------------------------------------------------------------------------- 1 | pub(crate) fn memory_fence() { 2 | #[cfg(xtensa)] 3 | unsafe { 4 | core::arch::asm!("memw"); 5 | } 6 | 7 | #[cfg(riscv)] 8 | unsafe { 9 | core::arch::asm!("fence"); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /esp-wifi/src/preempt_builtin/preempt_xtensa.rs: -------------------------------------------------------------------------------- 1 | use esp_wifi_sys::c_types; 2 | 3 | use super::*; 4 | pub use crate::hal::trapframe::TrapFrame; 5 | 6 | pub(crate) fn new_task_context( 7 | task_fn: extern "C" fn(*mut c_types::c_void), 8 | param: *mut c_types::c_void, 9 | stack_top: *mut (), 10 | ) -> TrapFrame { 11 | // stack must be aligned by 16 12 | let stack_top = stack_top as u32; 13 | let stack_top = stack_top - (stack_top % 16); 14 | 15 | unsafe { 16 | *((stack_top - 4) as *mut u32) = 0; 17 | *((stack_top - 8) as *mut u32) = 0; 18 | *((stack_top - 12) as *mut u32) = stack_top; 19 | *((stack_top - 16) as *mut u32) = 0; 20 | } 21 | 22 | TrapFrame { 23 | PC: task_fn as usize as u32, 24 | A0: 0, 25 | A1: stack_top, 26 | A6: param as usize as u32, 27 | 28 | // For windowed ABI set WOE and CALLINC (pretend task was 'call4'd) 29 | PS: 0x00040000 | ((1 & 3) << 16), 30 | 31 | ..Default::default() 32 | } 33 | } 34 | 35 | pub(crate) fn restore_task_context(ctx: &mut Context, trap_frame: &mut TrapFrame) { 36 | *trap_frame = ctx.trap_frame; 37 | } 38 | 39 | pub(crate) fn save_task_context(ctx: &mut Context, trap_frame: &TrapFrame) { 40 | ctx.trap_frame = *trap_frame; 41 | } 42 | -------------------------------------------------------------------------------- /esp-wifi/src/preempt_builtin/timer/riscv.rs: -------------------------------------------------------------------------------- 1 | #[cfg(any(esp32c6, esp32h2))] 2 | use peripherals::INTPRI as SystemPeripheral; 3 | #[cfg(not(any(esp32c6, esp32h2)))] 4 | use peripherals::SYSTEM as SystemPeripheral; 5 | 6 | use crate::{ 7 | TimeBase, 8 | hal::{ 9 | interrupt::{self, TrapFrame}, 10 | peripherals::{self, Interrupt}, 11 | riscv, 12 | }, 13 | preempt_builtin::{task_switch, timer::setup_timebase}, 14 | }; 15 | 16 | pub(crate) fn setup_timer(timer: TimeBase) { 17 | // make sure the scheduling won't start before everything is setup 18 | riscv::interrupt::disable(); 19 | 20 | setup_timebase(timer); 21 | } 22 | 23 | pub(crate) fn setup_multitasking() { 24 | unwrap!(interrupt::enable( 25 | Interrupt::FROM_CPU_INTR2, 26 | interrupt::Priority::Priority1, 27 | )); 28 | 29 | unsafe { 30 | riscv::interrupt::enable(); 31 | } 32 | } 33 | 34 | pub(crate) fn disable_multitasking() { 35 | interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::FROM_CPU_INTR2); 36 | } 37 | 38 | #[unsafe(no_mangle)] 39 | extern "C" fn FROM_CPU_INTR2(trap_frame: &mut TrapFrame) { 40 | // clear FROM_CPU_INTR3 41 | SystemPeripheral::regs() 42 | .cpu_intr_from_cpu_2() 43 | .modify(|_, w| w.cpu_intr_from_cpu_2().clear_bit()); 44 | 45 | task_switch(trap_frame); 46 | } 47 | 48 | pub(crate) fn yield_task() { 49 | SystemPeripheral::regs() 50 | .cpu_intr_from_cpu_2() 51 | .modify(|_, w| w.cpu_intr_from_cpu_2().set_bit()); 52 | } 53 | -------------------------------------------------------------------------------- /esp-wifi/src/preempt_builtin/timer/xtensa.rs: -------------------------------------------------------------------------------- 1 | pub(crate) use crate::preempt_builtin::timer::setup_timebase as setup_timer; 2 | use crate::{ 3 | hal::{trapframe::TrapFrame, xtensa_lx, xtensa_lx_rt}, 4 | preempt_builtin::task_switch, 5 | }; 6 | 7 | // ESP32 uses Software1 (priority 3) for task switching, because it reserves 8 | // Software0 for the Bluetooth stack. 9 | const SW_INTERRUPT: u32 = if cfg!(esp32) { 1 << 29 } else { 1 << 7 }; 10 | 11 | pub(crate) fn setup_multitasking() { 12 | unsafe { 13 | let enabled = xtensa_lx::interrupt::disable(); 14 | xtensa_lx::interrupt::enable_mask( 15 | SW_INTERRUPT 16 | | xtensa_lx_rt::interrupt::CpuInterruptLevel::Level2.mask() 17 | | xtensa_lx_rt::interrupt::CpuInterruptLevel::Level6.mask() 18 | | enabled, 19 | ); 20 | } 21 | } 22 | 23 | pub(crate) fn disable_multitasking() { 24 | xtensa_lx::interrupt::disable_mask(SW_INTERRUPT); 25 | } 26 | 27 | #[allow(non_snake_case)] 28 | #[cfg_attr(not(esp32), unsafe(export_name = "Software0"))] 29 | #[cfg_attr(esp32, unsafe(export_name = "Software1"))] 30 | fn task_switch_interrupt(context: &mut TrapFrame) { 31 | let intr = SW_INTERRUPT; 32 | unsafe { core::arch::asm!("wsr.intclear {0}", in(reg) intr, options(nostack)) }; 33 | 34 | task_switch(context); 35 | } 36 | 37 | pub(crate) fn yield_task() { 38 | let intr = SW_INTERRUPT; 39 | unsafe { core::arch::asm!("wsr.intset {0}", in(reg) intr, options(nostack)) }; 40 | } 41 | -------------------------------------------------------------------------------- /esp-wifi/src/radio/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg_attr(esp32, path = "radio_esp32.rs")] 2 | #[cfg_attr(esp32c2, path = "radio_esp32c2.rs")] 3 | #[cfg_attr(esp32c3, path = "radio_esp32c3.rs")] 4 | #[cfg_attr(esp32c6, path = "radio_esp32c6.rs")] 5 | #[cfg_attr(esp32h2, path = "radio_esp32h2.rs")] 6 | #[cfg_attr(esp32s3, path = "radio_esp32s3.rs")] 7 | #[cfg_attr(esp32s2, path = "radio_esp32s2.rs")] 8 | mod chip_specific; 9 | 10 | pub(crate) use chip_specific::*; 11 | -------------------------------------------------------------------------------- /esp-wifi/src/radio/radio_esp32h2.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "ble")] 2 | use crate::{ 3 | binary, 4 | hal::{interrupt, peripherals::Interrupt}, 5 | }; 6 | 7 | pub(crate) fn setup_radio_isr() { 8 | // no-op 9 | } 10 | 11 | pub(crate) fn shutdown_radio_isr() { 12 | #[cfg(feature = "ble")] 13 | { 14 | interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::LP_BLE_TIMER); 15 | interrupt::disable(crate::hal::system::Cpu::ProCpu, Interrupt::BT_MAC); 16 | } 17 | } 18 | 19 | #[cfg(feature = "ble")] 20 | #[unsafe(no_mangle)] 21 | extern "C" fn LP_BLE_TIMER() { 22 | unsafe { 23 | trace!("LP_TIMER interrupt"); 24 | 25 | let (fnc, arg) = crate::ble::npl::ble_os_adapter_chip_specific::ISR_INTERRUPT_3; 26 | 27 | trace!("interrupt LP_TIMER {:?} {:?}", fnc, arg); 28 | 29 | if !fnc.is_null() { 30 | trace!("interrupt LP_TIMER call"); 31 | 32 | let fnc: fn(*mut binary::c_types::c_void) = core::mem::transmute(fnc); 33 | fnc(arg); 34 | trace!("LP_TIMER done"); 35 | } 36 | 37 | trace!("interrupt LP_TIMER done"); 38 | }; 39 | } 40 | 41 | #[cfg(feature = "ble")] 42 | #[unsafe(no_mangle)] 43 | extern "C" fn BT_MAC() { 44 | unsafe { 45 | trace!("BT_MAC interrupt"); 46 | 47 | let (fnc, arg) = crate::ble::npl::ble_os_adapter_chip_specific::ISR_INTERRUPT_15; 48 | 49 | trace!("interrupt BT_MAC {:?} {:?}", fnc, arg); 50 | 51 | if !fnc.is_null() { 52 | trace!("interrupt BT_MAC call"); 53 | 54 | let fnc: fn(*mut binary::c_types::c_void) = core::mem::transmute(fnc); 55 | fnc(arg); 56 | trace!("BT_MAC done"); 57 | } 58 | 59 | trace!("interrupt BT_MAC done"); 60 | }; 61 | } 62 | -------------------------------------------------------------------------------- /esp-wifi/src/radio/radio_esp32s2.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "wifi")] 2 | #[allow(unused_imports)] 3 | use crate::hal::{interrupt, peripherals}; 4 | 5 | pub(crate) fn setup_radio_isr() { 6 | // wifi enabled in set_isr 7 | // ble not supported 8 | } 9 | 10 | pub(crate) fn shutdown_radio_isr() { 11 | // ble not supported 12 | } 13 | 14 | #[cfg(feature = "wifi")] 15 | #[unsafe(no_mangle)] 16 | extern "C" fn WIFI_MAC() { 17 | unsafe { 18 | let (fnc, arg) = crate::wifi::os_adapter::ISR_INTERRUPT_1; 19 | trace!("interrupt WIFI_MAC {:?} {:?}", fnc, arg); 20 | 21 | if !fnc.is_null() { 22 | let fnc: fn(*mut crate::binary::c_types::c_void) = core::mem::transmute(fnc); 23 | fnc(arg); 24 | } 25 | } 26 | } 27 | 28 | #[cfg(feature = "wifi")] 29 | #[unsafe(no_mangle)] 30 | extern "C" fn WIFI_PWR() { 31 | unsafe { 32 | let (fnc, arg) = crate::wifi::os_adapter::ISR_INTERRUPT_1; 33 | 34 | trace!("interrupt WIFI_PWR {:?} {:?}", fnc, arg); 35 | 36 | if !fnc.is_null() { 37 | let fnc: fn(*mut crate::binary::c_types::c_void) = core::mem::transmute(fnc); 38 | fnc(arg); 39 | } 40 | 41 | trace!("interrupt 1 done"); 42 | }; 43 | } 44 | -------------------------------------------------------------------------------- /esp-wifi/src/tasks.rs: -------------------------------------------------------------------------------- 1 | use crate::{ 2 | compat::timer_compat::TIMERS, 3 | preempt::{task_create, yield_task}, 4 | time::systimer_count, 5 | }; 6 | 7 | /// Initializes the `timer` task for the Wi-Fi driver. 8 | pub(crate) fn init_tasks() { 9 | // schedule the timer task 10 | task_create(timer_task, core::ptr::null_mut(), 8192); 11 | } 12 | 13 | /// Entry point for the timer task responsible for handling scheduled timer 14 | /// events. 15 | pub(crate) extern "C" fn timer_task(_param: *mut esp_wifi_sys::c_types::c_void) { 16 | loop { 17 | let current_timestamp = systimer_count(); 18 | let to_run = TIMERS.with(|timers| { 19 | let to_run = unsafe { timers.find_next_due(current_timestamp) }?; 20 | 21 | to_run.active = to_run.periodic; 22 | 23 | if to_run.periodic { 24 | to_run.started = current_timestamp; 25 | } 26 | 27 | Some(to_run.callback) 28 | }); 29 | 30 | // run the due timer callback NOT in an interrupt free context 31 | if let Some(to_run) = to_run { 32 | trace!("trigger timer...."); 33 | to_run.call(); 34 | trace!("timer callback called"); 35 | } else { 36 | yield_task(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /esp-wifi/src/time.rs: -------------------------------------------------------------------------------- 1 | // Time keeping 2 | pub const TICKS_PER_SECOND: u64 = 1_000_000; 3 | 4 | /// Current systimer count value 5 | /// A tick is 1 / 1_000_000 seconds 6 | /// This function must not be called in a critical section. Doing so may return 7 | /// an incorrect value. 8 | pub(crate) fn systimer_count() -> u64 { 9 | esp_hal::time::Instant::now() 10 | .duration_since_epoch() 11 | .as_micros() 12 | } 13 | 14 | // TODO: use an Instance type instead... 15 | #[cfg(target_arch = "riscv32")] 16 | pub(crate) fn time_diff(start: u64, end: u64) -> u64 { 17 | // 52-bit wrapping sub 18 | end.wrapping_sub(start) & 0x000f_ffff_ffff_ffff 19 | } 20 | 21 | // TODO: use an Instance type instead... 22 | #[cfg(target_arch = "xtensa")] 23 | pub(crate) fn time_diff(start: u64, end: u64) -> u64 { 24 | end.wrapping_sub(start) 25 | } 26 | 27 | #[allow(unused)] 28 | pub(crate) fn micros_to_ticks(us: u64) -> u64 { 29 | us * (TICKS_PER_SECOND / 1_000_000) 30 | } 31 | 32 | #[allow(unused)] 33 | pub(crate) fn millis_to_ticks(ms: u64) -> u64 { 34 | ms * (TICKS_PER_SECOND / 1_000) 35 | } 36 | 37 | #[allow(unused)] 38 | pub(crate) fn ticks_to_micros(ticks: u64) -> u64 { 39 | ticks / (TICKS_PER_SECOND / 1_000_000) 40 | } 41 | 42 | #[allow(unused)] 43 | pub(crate) fn ticks_to_millis(ticks: u64) -> u64 { 44 | ticks / (TICKS_PER_SECOND / 1_000) 45 | } 46 | 47 | /// Do not call this in a critical section! 48 | pub(crate) fn elapsed_time_since(start: u64) -> u64 { 49 | let now = systimer_count(); 50 | time_diff(start, now) 51 | } 52 | -------------------------------------------------------------------------------- /examples/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [alias] 2 | esp32 = "run --release --features=esp32 --target=xtensa-esp32-none-elf" 3 | esp32c2 = "run --release --features=esp32c2 --target=riscv32imc-unknown-none-elf" 4 | esp32c3 = "run --release --features=esp32c3 --target=riscv32imc-unknown-none-elf" 5 | esp32c6 = "run --release --features=esp32c6 --target=riscv32imac-unknown-none-elf" 6 | esp32h2 = "run --release --features=esp32h2 --target=riscv32imac-unknown-none-elf" 7 | esp32s2 = "run --release --features=esp32s2 --target=xtensa-esp32s2-none-elf" 8 | esp32s3 = "run --release --features=esp32s3 --target=xtensa-esp32s3-none-elf" 9 | 10 | [target.'cfg(target_arch = "riscv32")'] 11 | runner = "espflash flash --monitor" 12 | rustflags = [ 13 | "-C", "link-arg=-Tlinkall.x", 14 | "-C", "force-frame-pointers", 15 | ] 16 | 17 | [target.'cfg(target_arch = "xtensa")'] 18 | runner = "espflash flash --monitor" 19 | rustflags = [ 20 | # GNU LD 21 | "-C", "link-arg=-Wl,-Tlinkall.x", 22 | "-C", "link-arg=-nostartfiles", 23 | 24 | # LLD 25 | # "-C", "link-arg=-Tlinkall.x", 26 | # "-C", "linker=rust-lld", 27 | ] 28 | 29 | [env] 30 | ESP_LOG = "info" 31 | SSID = "SSID" 32 | PASSWORD = "PASSWORD" 33 | STATIC_IP = "1.1.1.1 " 34 | GATEWAY_IP = "1.1.1.1" 35 | HOST_IP = "1.1.1.1" 36 | 37 | [unstable] 38 | build-std = ["alloc", "core"] 39 | -------------------------------------------------------------------------------- /examples/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // Allow building examples in CI in debug mode 3 | println!("cargo:rustc-check-cfg=cfg(is_not_release)"); 4 | println!("cargo:rerun-if-env-changed=CI"); 5 | if std::env::var("CI").is_err() { 6 | if let Ok(level) = std::env::var("OPT_LEVEL") { 7 | if level == "0" || level == "1" { 8 | println!("cargo::rustc-cfg=is_not_release"); 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/rustfmt.toml: -------------------------------------------------------------------------------- 1 | # Imports 2 | group_imports = "StdExternalCrate" 3 | imports_granularity = "Crate" 4 | imports_layout = "HorizontalVertical" 5 | -------------------------------------------------------------------------------- /examples/src/bin/embassy_hello_world.rs: -------------------------------------------------------------------------------- 1 | //! embassy hello world 2 | //! 3 | //! This is an example of running the embassy executor with multiple tasks 4 | //! concurrently. 5 | 6 | //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 7 | //% FEATURES: embassy esp-hal/unstable 8 | 9 | #![no_std] 10 | #![no_main] 11 | 12 | use embassy_executor::Spawner; 13 | use embassy_time::{Duration, Timer}; 14 | use esp_backtrace as _; 15 | use esp_hal::timer::timg::TimerGroup; 16 | 17 | esp_bootloader_esp_idf::esp_app_desc!(); 18 | 19 | #[embassy_executor::task] 20 | async fn run() { 21 | loop { 22 | esp_println::println!("Hello world from embassy using esp-hal-async!"); 23 | Timer::after(Duration::from_millis(1_000)).await; 24 | } 25 | } 26 | 27 | #[esp_hal_embassy::main] 28 | async fn main(spawner: Spawner) { 29 | esp_println::logger::init_logger_from_env(); 30 | let peripherals = esp_hal::init(esp_hal::Config::default()); 31 | 32 | esp_println::println!("Init!"); 33 | 34 | let timg0 = TimerGroup::new(peripherals.TIMG0); 35 | esp_hal_embassy::init(timg0.timer0); 36 | 37 | spawner.spawn(run()).ok(); 38 | 39 | loop { 40 | esp_println::println!("Bing!"); 41 | Timer::after(Duration::from_millis(5_000)).await; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /examples/src/bin/embassy_rmt_tx.rs: -------------------------------------------------------------------------------- 1 | //! Demonstrates generating pulse sequences with RMT 2 | //! 3 | //! Connect a logic analyzer to GPIO4 to see the generated pulses. 4 | //! 5 | //! The following wiring is assumed: 6 | //! - generated pulses => GPIO4 7 | 8 | //% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 9 | //% FEATURES: embassy esp-hal/unstable 10 | 11 | #![no_std] 12 | #![no_main] 13 | 14 | use embassy_executor::Spawner; 15 | use embassy_time::{Duration, Timer}; 16 | use esp_backtrace as _; 17 | use esp_hal::{ 18 | gpio::Level, 19 | rmt::{PulseCode, Rmt, TxChannelAsync, TxChannelConfig, TxChannelCreatorAsync}, 20 | time::Rate, 21 | timer::timg::TimerGroup, 22 | }; 23 | use esp_println::println; 24 | 25 | esp_bootloader_esp_idf::esp_app_desc!(); 26 | 27 | #[esp_hal_embassy::main] 28 | async fn main(_spawner: Spawner) { 29 | println!("Init!"); 30 | let peripherals = esp_hal::init(esp_hal::Config::default()); 31 | 32 | let timg0 = TimerGroup::new(peripherals.TIMG0); 33 | esp_hal_embassy::init(timg0.timer0); 34 | 35 | cfg_if::cfg_if! { 36 | if #[cfg(feature = "esp32h2")] { 37 | let freq = Rate::from_mhz(32); 38 | } else { 39 | let freq = Rate::from_mhz(80); 40 | } 41 | }; 42 | 43 | let rmt = Rmt::new(peripherals.RMT, freq).unwrap().into_async(); 44 | 45 | let mut channel = rmt 46 | .channel0 47 | .configure( 48 | peripherals.GPIO4, 49 | TxChannelConfig::default().with_clk_divider(255), 50 | ) 51 | .unwrap(); 52 | 53 | let mut data = [PulseCode::new(Level::High, 200, Level::Low, 50); 20]; 54 | 55 | data[data.len() - 2] = PulseCode::new(Level::High, 3000, Level::Low, 500); 56 | data[data.len() - 1] = PulseCode::empty(); 57 | 58 | loop { 59 | println!("transmit"); 60 | channel.transmit(&data).await.unwrap(); 61 | println!("transmitted\n"); 62 | Timer::after(Duration::from_millis(500)).await; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /examples/src/bin/etm_timer.rs: -------------------------------------------------------------------------------- 1 | //! Control LED by the boot button via ETM without involving the CPU. 2 | 3 | //! The following wiring is assumed: 4 | //! - LED => GPIO2 5 | 6 | //% CHIPS: esp32c6 esp32h2 7 | //% FEATURES: esp-hal/unstable 8 | 9 | #![no_std] 10 | #![no_main] 11 | 12 | use esp_backtrace as _; 13 | use esp_hal::{ 14 | etm::Etm, 15 | gpio::{ 16 | Level, 17 | Output, 18 | OutputConfig, 19 | Pull, 20 | etm::{Channels, OutputConfig as EtmOutputConfig}, 21 | }, 22 | main, 23 | time::Duration, 24 | timer::{ 25 | PeriodicTimer, 26 | systimer::{SystemTimer, etm::Event}, 27 | }, 28 | }; 29 | 30 | esp_bootloader_esp_idf::esp_app_desc!(); 31 | 32 | #[main] 33 | fn main() -> ! { 34 | let peripherals = esp_hal::init(esp_hal::Config::default()); 35 | 36 | let mut led = Output::new(peripherals.GPIO2, Level::Low, OutputConfig::default()); 37 | led.set_high(); 38 | 39 | let syst = SystemTimer::new(peripherals.SYSTIMER); 40 | let alarm = syst.alarm0; 41 | 42 | let timer_event = Event::new(&alarm); 43 | 44 | // setup ETM 45 | let gpio_ext = Channels::new(peripherals.GPIO_SD); 46 | let led_task = gpio_ext.channel0_task.toggle( 47 | led, 48 | EtmOutputConfig { 49 | open_drain: false, 50 | pull: Pull::None, 51 | initial_state: Level::Low, 52 | }, 53 | ); 54 | 55 | let etm = Etm::new(peripherals.SOC_ETM); 56 | let channel0 = etm.channel0; 57 | 58 | // make sure the configured channel doesn't get dropped - dropping it will 59 | // disable the channel 60 | let _configured_channel = channel0.setup(&timer_event, &led_task); 61 | 62 | let mut timer = PeriodicTimer::new(alarm); 63 | timer.start(Duration::from_secs(1)).unwrap(); 64 | 65 | // the LED is controlled by the button without involving the CPU 66 | loop {} 67 | } 68 | -------------------------------------------------------------------------------- /examples/src/bin/ieee802154_receive_all_frames.rs: -------------------------------------------------------------------------------- 1 | //% CHIPS: esp32c6 esp32h2 2 | //% FEATURES: esp-ieee802154 esp-hal/unstable 3 | 4 | #![no_std] 5 | #![no_main] 6 | 7 | use esp_backtrace as _; 8 | use esp_hal::main; 9 | use esp_ieee802154::{Config, Ieee802154}; 10 | use esp_println::println; 11 | 12 | esp_bootloader_esp_idf::esp_app_desc!(); 13 | 14 | #[main] 15 | fn main() -> ! { 16 | let peripherals = esp_hal::init(esp_hal::Config::default()); 17 | let mut ieee802154 = Ieee802154::new(peripherals.IEEE802154, peripherals.RADIO_CLK); 18 | 19 | ieee802154.set_config(Config { 20 | channel: 15, 21 | promiscuous: true, 22 | rx_when_idle: true, 23 | auto_ack_rx: false, 24 | auto_ack_tx: false, 25 | ..Default::default() 26 | }); 27 | 28 | println!("Start receiving:"); 29 | ieee802154.start_receive(); 30 | 31 | loop { 32 | if let Some(frame) = ieee802154.received() { 33 | println!("Received {:?}\n", &frame); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /examples/src/bin/ieee802154_receive_frame.rs: -------------------------------------------------------------------------------- 1 | //% CHIPS: esp32c6 esp32h2 2 | //% FEATURES: esp-ieee802154 esp-hal/unstable 3 | 4 | #![no_std] 5 | #![no_main] 6 | 7 | use esp_backtrace as _; 8 | use esp_hal::main; 9 | use esp_ieee802154::{Config, Ieee802154}; 10 | use esp_println::println; 11 | 12 | esp_bootloader_esp_idf::esp_app_desc!(); 13 | 14 | #[main] 15 | fn main() -> ! { 16 | let peripherals = esp_hal::init(esp_hal::Config::default()); 17 | let mut ieee802154 = Ieee802154::new(peripherals.IEEE802154, peripherals.RADIO_CLK); 18 | 19 | ieee802154.set_config(Config { 20 | channel: 15, 21 | promiscuous: false, 22 | rx_when_idle: true, 23 | auto_ack_rx: true, 24 | auto_ack_tx: true, 25 | pan_id: Some(0x4242), 26 | short_addr: Some(0x2323), 27 | ..Default::default() 28 | }); 29 | 30 | println!("Start receiving:"); 31 | ieee802154.start_receive(); 32 | 33 | loop { 34 | if let Some(frame) = ieee802154.received() { 35 | println!("Received {:?}\n", &frame); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /examples/src/bin/lp_core_basic.rs: -------------------------------------------------------------------------------- 1 | //! This shows a very basic example of running code on the LP core. 2 | //! 3 | //! Code on LP core increments a counter and continuously toggles LED. The 4 | //! current value is printed by the HP core. 5 | //! 6 | //! ⚠️ Make sure to first compile the `esp-lp-hal/examples/blinky.rs` example ⚠️ 7 | //! 8 | //! The following wiring is assumed: 9 | //! - LED => GPIO1 10 | 11 | //% CHIPS: esp32c6 12 | //% FEATURES: esp-hal/unstable 13 | 14 | #![no_std] 15 | #![no_main] 16 | 17 | use esp_backtrace as _; 18 | use esp_hal::{ 19 | gpio::lp_io::LowPowerOutput, 20 | load_lp_code, 21 | lp_core::{LpCore, LpCoreWakeupSource}, 22 | main, 23 | }; 24 | use esp_println::{print, println}; 25 | 26 | esp_bootloader_esp_idf::esp_app_desc!(); 27 | 28 | #[main] 29 | fn main() -> ! { 30 | let peripherals = esp_hal::init(esp_hal::Config::default()); 31 | 32 | // configure GPIO 1 as LP output pin 33 | 34 | let lp_pin = LowPowerOutput::new(peripherals.GPIO1); 35 | 36 | let mut lp_core = LpCore::new(peripherals.LP_CORE); 37 | lp_core.stop(); 38 | println!("lp core stopped"); 39 | 40 | // load code to LP core 41 | let lp_core_code = 42 | load_lp_code!("../esp-lp-hal/target/riscv32imac-unknown-none-elf/release/examples/blinky"); 43 | 44 | // start LP core 45 | lp_core_code.run(&mut lp_core, LpCoreWakeupSource::HpCpu, lp_pin); 46 | println!("lpcore run"); 47 | 48 | let data = (0x5000_2000) as *mut u32; 49 | loop { 50 | print!("Current {:x} \u{000d}", unsafe { 51 | data.read_volatile() 52 | }); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /examples/src/bin/spi_loopback.rs: -------------------------------------------------------------------------------- 1 | //! SPI loopback test 2 | //! 3 | //! The following wiring is assumed: 4 | //! - SCLK => GPIO0 5 | //! - MISO/MOSI => GPIO2 6 | //! - CS => GPIO5 7 | //! 8 | //! Depending on your target and the board you are using you have to change the 9 | //! pins. 10 | //! 11 | //! This example transfers data via SPI. 12 | 13 | //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 14 | //% FEATURES: esp-hal/unstable 15 | 16 | #![no_std] 17 | #![no_main] 18 | 19 | use esp_backtrace as _; 20 | use esp_hal::{ 21 | delay::Delay, 22 | main, 23 | spi::{ 24 | Mode, 25 | master::{Config, Spi}, 26 | }, 27 | time::Rate, 28 | }; 29 | use esp_println::println; 30 | 31 | esp_bootloader_esp_idf::esp_app_desc!(); 32 | 33 | #[main] 34 | fn main() -> ! { 35 | let peripherals = esp_hal::init(esp_hal::Config::default()); 36 | 37 | let sclk = peripherals.GPIO0; 38 | let miso_mosi = peripherals.GPIO2; 39 | let cs = peripherals.GPIO5; 40 | 41 | let miso = unsafe { miso_mosi.clone_unchecked() }; 42 | 43 | let mut spi = Spi::new( 44 | peripherals.SPI2, 45 | Config::default() 46 | .with_frequency(Rate::from_khz(100)) 47 | .with_mode(Mode::_0), 48 | ) 49 | .unwrap() 50 | .with_sck(sclk) 51 | .with_miso(miso) // order matters 52 | .with_mosi(miso_mosi) // order matters 53 | .with_cs(cs); 54 | 55 | let delay = Delay::new(); 56 | 57 | loop { 58 | let mut data = [0xde, 0xca, 0xfb, 0xad]; 59 | spi.transfer(&mut data).unwrap(); 60 | println!("{:x?}", data); 61 | 62 | delay.delay_millis(250); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /extras/bench-server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "bench-server" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | pretty_env_logger = "0.5.0" 8 | log = "0.4.0" -------------------------------------------------------------------------------- /extras/esp-wifishark/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "esp-wifishark" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | r-extcap = "0.2.4" 8 | pcap-file = "2.0.0" 9 | serialport = "4.2.1" 10 | clap = { version = "4.3.5", features = ["derive"] } 11 | -------------------------------------------------------------------------------- /extras/esp-wifishark/README.md: -------------------------------------------------------------------------------- 1 | # esp-wifishark 2 | 3 | This is an extcap to be used with esp-wifi and the `dump_packets` config option. 4 | 5 | To use it build via `cargo build --release` and copy the resulting executable to the Wireshark's `extcap` folder. 6 | 7 | Then you should see two new capture interfaces in Wireshark 8 | - esp-wifi HCI capture (for Bluetooth HCI) 9 | - esp-wifi Ethernet capture (for WiFi traffic) 10 | 11 | If you are running an application using esp-wifi's `dump_packets` config and logging at INFO level active these capture interfaces can connect via serialport to give you insights on what is going on. 12 | 13 | By default it tries to identify exactly one serialport. If that doesn't work for you, you can configure the serialport via the Wireshark UI. 14 | -------------------------------------------------------------------------------- /extras/ieee802154-sniffer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sniffer" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | r-extcap = "0.2.4" 8 | pcap-file = "2.0.0" 9 | serialport = "4.2.0" 10 | clap = { version = "4.1.7", features = ["derive"] } 11 | -------------------------------------------------------------------------------- /extras/ieee802154-sniffer/README.md: -------------------------------------------------------------------------------- 1 | # IEEE 802.15.4 Sniffer 2 | 3 | This is an extcap to be used with the `ieee802154_sniffer` example. (Make sure the ESP32-C6/ESP32-H2 is connected via UART-bridge, not JTAG-Serial) 4 | 5 | To use it, build via `cargo build --release` and copy the resulting executable to the Wireshark's `extcap` folder. 6 | 7 | Then you should see a new capture interface in Wireshark 8 | 9 | If you are running the ieee802154_sniffer example this capture interface can connect via serialport to give you insights on what is going on. 10 | 11 | By default it tries to identify exactly one serialport. If that doesn't work for you, you can configure the serialport via the Wireshark UI. 12 | 13 | In Wireshark use `ITU-T-CRC-16` as `FCS format` 14 | -------------------------------------------------------------------------------- /hil-test/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.'cfg(target_arch = "riscv32")'] 2 | runner = "probe-rs run --preverify" 3 | rustflags = [ 4 | "-C", "link-arg=-Tembedded-test.x", 5 | "-C", "link-arg=-Tdefmt.x", 6 | "-C", "link-arg=-Tlinkall.x", 7 | "-C", "force-frame-pointers" 8 | ] 9 | 10 | [target.'cfg(target_arch = "xtensa")'] 11 | runner = "probe-rs run --preverify" 12 | rustflags = [ 13 | "-C", "link-arg=-nostartfiles", 14 | "-C", "link-arg=-Tembedded-test.x", 15 | "-C", "link-arg=-Tdefmt.x", 16 | "-C", "link-arg=-Wl,-Tlinkall.x", 17 | ] 18 | 19 | [env] 20 | DEFMT_LOG = "info,embedded_test=warn" 21 | ESP_HAL_EMBASSY_CONFIG_TIMER_QUEUE="multiple-integrated" 22 | 23 | [unstable] 24 | build-std = ["core", "alloc"] 25 | 26 | [net] 27 | git-fetch-with-cli = true 28 | -------------------------------------------------------------------------------- /hil-test/build.rs: -------------------------------------------------------------------------------- 1 | use std::error::Error; 2 | 3 | use esp_metadata::{Chip, Config}; 4 | 5 | fn main() -> Result<(), Box> { 6 | // Load the configuration file for the configured device: 7 | let chip = Chip::from_cargo_feature()?; 8 | let config = Config::for_chip(&chip); 9 | 10 | // Define all necessary configuration symbols for the configured device: 11 | config.define_symbols(); 12 | 13 | Ok(()) 14 | } 15 | -------------------------------------------------------------------------------- /hil-test/tests/clock_monitor.rs: -------------------------------------------------------------------------------- 1 | //! Clock Monitor Test 2 | 3 | //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 4 | //% FEATURES: unstable 5 | 6 | #![no_std] 7 | #![no_main] 8 | 9 | use esp_hal::rtc_cntl::Rtc; 10 | use hil_test as _; 11 | 12 | esp_bootloader_esp_idf::esp_app_desc!(); 13 | 14 | struct Context<'a> { 15 | rtc: Rtc<'a>, 16 | } 17 | 18 | #[cfg(test)] 19 | #[embedded_test::tests(default_timeout = 3)] 20 | mod tests { 21 | use super::*; 22 | 23 | #[init] 24 | fn init() -> Context<'static> { 25 | let peripherals = esp_hal::init(esp_hal::Config::default()); 26 | let rtc = Rtc::new(peripherals.LPWR); 27 | 28 | Context { rtc } 29 | } 30 | 31 | #[test] 32 | fn test_estimated_clock(mut ctx: Context<'static>) { 33 | cfg_if::cfg_if! { 34 | if #[cfg(feature = "esp32c2")] { 35 | // 26 MHz 36 | let expected_range = 23..=29; 37 | } else if #[cfg(feature = "esp32h2")] { 38 | // 32 MHz 39 | let expected_range = 29..=35; 40 | } else { 41 | // 40 MHz 42 | let expected_range = 35..=45; 43 | } 44 | } 45 | 46 | let measured_frequency = ctx.rtc.estimate_xtal_frequency(); 47 | defmt::assert!( 48 | expected_range.contains(&measured_frequency), 49 | "Measured frequency: {}", 50 | measured_frequency 51 | ); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /hil-test/tests/flip_link.rs: -------------------------------------------------------------------------------- 1 | //! Tests flip_link 2 | 3 | //% CHIPS: esp32c6 esp32h2 4 | //% FEATURES: unstable defmt 5 | //% ENV: ESP_HAL_CONFIG_FLIP_LINK = true 6 | 7 | #![no_std] 8 | #![no_main] 9 | 10 | use hil_test as _; 11 | 12 | esp_bootloader_esp_idf::esp_app_desc!(); 13 | 14 | #[cfg(test)] 15 | #[embedded_test::tests(default_timeout = 3)] 16 | mod tests { 17 | #[test] 18 | fn test() { 19 | let _p = esp_hal::init(Default::default()); 20 | defmt::info!("Hello, world!"); 21 | defmt::assert_eq!(1 + 1, 2); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /hil-test/tests/get_time.rs: -------------------------------------------------------------------------------- 1 | //! time::Instant::now Test 2 | 3 | //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 4 | //% FEATURES: unstable 5 | 6 | #![no_std] 7 | #![no_main] 8 | 9 | use esp_hal::delay::Delay; 10 | use hil_test as _; 11 | 12 | esp_bootloader_esp_idf::esp_app_desc!(); 13 | 14 | struct Context { 15 | delay: Delay, 16 | } 17 | 18 | fn time_moves_forward_during(ctx: Context, f: F) { 19 | let t1 = esp_hal::time::Instant::now(); 20 | f(ctx); 21 | let t2 = esp_hal::time::Instant::now(); 22 | 23 | assert!(t2 > t1); 24 | } 25 | 26 | #[cfg(test)] 27 | #[embedded_test::tests(default_timeout = 3)] 28 | mod tests { 29 | use super::*; 30 | 31 | #[init] 32 | fn init() -> Context { 33 | let _ = esp_hal::init(esp_hal::Config::default()); 34 | 35 | let delay = Delay::new(); 36 | 37 | Context { delay } 38 | } 39 | 40 | #[test] 41 | fn test_current_time(ctx: Context) { 42 | let t1 = esp_hal::time::Instant::now(); 43 | ctx.delay.delay_millis(500); 44 | let t2 = esp_hal::time::Instant::now(); 45 | 46 | assert!(t2 > t1); 47 | assert!((t2 - t1).as_millis() >= 500u64); 48 | } 49 | 50 | #[cfg(systimer)] 51 | #[test] 52 | fn test_current_time_construct_systimer(ctx: Context) { 53 | time_moves_forward_during(ctx, |_| { 54 | // construct the timer in between calls to current_time 55 | let _ = esp_hal::timer::systimer::SystemTimer::new(unsafe { 56 | esp_hal::peripherals::SYSTIMER::steal() 57 | }); 58 | }) 59 | } 60 | 61 | #[cfg(esp32)] 62 | #[test] 63 | fn test_current_time_construct_timg0(ctx: Context) { 64 | time_moves_forward_during(ctx, |_| { 65 | // construct the timer in between calls to current_time 66 | let _ = esp_hal::timer::timg::TimerGroup::new(unsafe { 67 | esp_hal::peripherals::TIMG0::steal() 68 | }); 69 | }) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /hil-test/tests/twai.rs: -------------------------------------------------------------------------------- 1 | //! TWAI test 2 | 3 | //% CHIPS: esp32 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 4 | //% FEATURES: unstable 5 | 6 | #![no_std] 7 | #![no_main] 8 | 9 | use embedded_can::Frame; 10 | use esp_hal::{ 11 | Blocking, 12 | twai::{self, EspTwaiFrame, StandardId, TwaiMode, filter::SingleStandardFilter}, 13 | }; 14 | use hil_test as _; 15 | use nb::block; 16 | 17 | esp_bootloader_esp_idf::esp_app_desc!(); 18 | 19 | struct Context { 20 | twai: twai::Twai<'static, Blocking>, 21 | } 22 | 23 | #[cfg(test)] 24 | #[embedded_test::tests(default_timeout = 3)] 25 | mod tests { 26 | use super::*; 27 | 28 | #[init] 29 | fn init() -> Context { 30 | let peripherals = esp_hal::init(esp_hal::Config::default()); 31 | 32 | let (loopback_pin, _) = hil_test::common_test_pins!(peripherals); 33 | 34 | let (rx, tx) = unsafe { loopback_pin.split() }; 35 | 36 | let mut config = twai::TwaiConfiguration::new( 37 | peripherals.TWAI0, 38 | rx, 39 | tx, 40 | twai::BaudRate::B1000K, 41 | TwaiMode::SelfTest, 42 | ); 43 | 44 | config.set_filter(SingleStandardFilter::new( 45 | b"00000000000", 46 | b"x", 47 | [b"xxxxxxxx", b"xxxxxxxx"], 48 | )); 49 | 50 | let twai = config.start(); 51 | 52 | Context { twai } 53 | } 54 | 55 | #[test] 56 | fn test_send_receive(mut ctx: Context) { 57 | let frame = EspTwaiFrame::new_self_reception(StandardId::ZERO, &[1, 2, 3]).unwrap(); 58 | block!(ctx.twai.transmit(&frame)).unwrap(); 59 | 60 | let frame = block!(ctx.twai.receive()).unwrap(); 61 | 62 | assert_eq!(frame.data(), &[1, 2, 3]) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /hil-test/tests/uart_regression.rs: -------------------------------------------------------------------------------- 1 | //! Misc UART TX/RX regression tests 2 | 3 | //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 4 | //% FEATURES: unstable 5 | 6 | #![no_std] 7 | #![no_main] 8 | 9 | esp_bootloader_esp_idf::esp_app_desc!(); 10 | 11 | #[cfg(test)] 12 | #[embedded_test::tests(default_timeout = 3)] 13 | mod tests { 14 | use esp_hal::{ 15 | gpio::Flex, 16 | uart::{self, UartRx, UartTx}, 17 | }; 18 | use hil_test as _; 19 | 20 | #[test] 21 | fn test_that_creating_tx_does_not_cause_a_pulse() { 22 | let peripherals = esp_hal::init(esp_hal::Config::default()); 23 | 24 | let (rx, tx) = hil_test::common_test_pins!(peripherals); 25 | 26 | let mut rx = UartRx::new(peripherals.UART1, uart::Config::default()) 27 | .unwrap() 28 | .with_rx(rx); 29 | 30 | // Start from a low level to verify that UartTx sets the level high initially, 31 | // but don't enable output otherwise we actually pull down against RX's 32 | // pullup resistor. 33 | let mut tx = Flex::new(tx); 34 | tx.set_low(); 35 | 36 | // set up TX and send a byte 37 | let mut tx = UartTx::new(peripherals.UART0, uart::Config::default()) 38 | .unwrap() 39 | .with_tx(tx); 40 | 41 | tx.flush().unwrap(); 42 | tx.write(&[0x42]).unwrap(); 43 | let mut byte = [0u8; 1]; 44 | rx.read(&mut byte).unwrap(); 45 | 46 | assert_eq!(byte[0], 0x42); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /hil-test/tests/usb_serial_jtag.rs: -------------------------------------------------------------------------------- 1 | //! USB Serial JTAG tests 2 | 3 | //% CHIPS: esp32c3 esp32c6 esp32h2 esp32s3 4 | //% FEATURES: unstable 5 | 6 | #![no_std] 7 | #![no_main] 8 | 9 | #[cfg(test)] 10 | #[embedded_test::tests(default_timeout = 3)] 11 | mod tests { 12 | use esp_hal::usb_serial_jtag::UsbSerialJtag; 13 | use hil_test as _; 14 | 15 | esp_bootloader_esp_idf::esp_app_desc!(); 16 | 17 | #[test] 18 | fn creating_peripheral_does_not_break_debug_connection() { 19 | let peripherals = esp_hal::init(esp_hal::Config::default()); 20 | 21 | _ = UsbSerialJtag::new(peripherals.USB_DEVICE) 22 | .into_async() 23 | .split(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /qa-test/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [alias] 2 | esp32 = "run --release --features=esp32 --target=xtensa-esp32-none-elf" 3 | esp32c2 = "run --release --features=esp32c2 --target=riscv32imc-unknown-none-elf" 4 | esp32c3 = "run --release --features=esp32c3 --target=riscv32imc-unknown-none-elf" 5 | esp32c6 = "run --release --features=esp32c6 --target=riscv32imac-unknown-none-elf" 6 | esp32h2 = "run --release --features=esp32h2 --target=riscv32imac-unknown-none-elf" 7 | esp32s2 = "run --release --features=esp32s2 --target=xtensa-esp32s2-none-elf" 8 | esp32s3 = "run --release --features=esp32s3 --target=xtensa-esp32s3-none-elf" 9 | 10 | [target.'cfg(target_arch = "riscv32")'] 11 | runner = "espflash flash --monitor" 12 | rustflags = [ 13 | "-C", "link-arg=-Tlinkall.x", 14 | "-C", "force-frame-pointers", 15 | ] 16 | 17 | [target.'cfg(target_arch = "xtensa")'] 18 | runner = "espflash flash --monitor" 19 | rustflags = [ 20 | # GNU LD 21 | "-C", "link-arg=-Wl,-Tlinkall.x", 22 | "-C", "link-arg=-nostartfiles", 23 | 24 | # LLD 25 | # "-C", "link-arg=-Tlinkall.x", 26 | # "-C", "linker=rust-lld", 27 | ] 28 | 29 | [env] 30 | ESP_LOG = "info" 31 | ESP_HAL_EMBASSY_CONFIG_TIMER_QUEUE="multiple-integrated" 32 | 33 | [unstable] 34 | build-std = ["alloc", "core"] 35 | -------------------------------------------------------------------------------- /qa-test/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "qa-test" 3 | version = "0.0.0" 4 | edition = "2024" 5 | license = "MIT OR Apache-2.0" 6 | publish = false 7 | 8 | [dependencies] 9 | cfg-if = "1.0.0" 10 | embassy-executor = { version = "0.7.0", features = ["task-arena-size-12288"] } 11 | embassy-time = "0.4.0" 12 | embassy-futures = "0.1.1" 13 | embassy-sync = "0.6.1" 14 | embedded-graphics = "0.8.1" 15 | embedded-hal-async = "1.0.0" 16 | esp-alloc = { path = "../esp-alloc" } 17 | esp-backtrace = { path = "../esp-backtrace", features = ["exception-handler", "panic-handler", "println"] } 18 | esp-bootloader-esp-idf = { path = "../esp-bootloader-esp-idf" } 19 | esp-hal = { path = "../esp-hal", features = ["unstable", "log-04"] } 20 | esp-hal-embassy = { path = "../esp-hal-embassy" } 21 | esp-println = { path = "../esp-println", features = ["log-04"] } 22 | lis3dh-async = "0.9.3" 23 | ssd1306 = "0.10.0" 24 | 25 | [features] 26 | unstable = [] 27 | esp32 = ["esp-backtrace/esp32", "esp-hal/esp32", "esp-hal-embassy/esp32", "esp-println/esp32"] 28 | esp32c2 = ["esp-backtrace/esp32c2", "esp-hal/esp32c2", "esp-hal-embassy/esp32c2", "esp-println/esp32c2"] 29 | esp32c3 = ["esp-backtrace/esp32c3", "esp-hal/esp32c3", "esp-hal-embassy/esp32c3", "esp-println/esp32c3"] 30 | esp32c6 = ["esp-backtrace/esp32c6", "esp-hal/esp32c6", "esp-hal-embassy/esp32c6", "esp-println/esp32c6"] 31 | esp32h2 = ["esp-backtrace/esp32h2", "esp-hal/esp32h2", "esp-hal-embassy/esp32h2", "esp-println/esp32h2"] 32 | esp32s2 = ["esp-backtrace/esp32s2", "esp-hal/esp32s2", "esp-hal-embassy/esp32s2", "esp-println/esp32s2"] 33 | esp32s3 = ["esp-backtrace/esp32s3", "esp-hal/esp32s3", "esp-hal-embassy/esp32s3", "esp-println/esp32s3"] 34 | 35 | [profile.release] 36 | debug = 2 37 | debug-assertions = true 38 | lto = "fat" 39 | codegen-units = 1 40 | -------------------------------------------------------------------------------- /qa-test/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | // Allow building QA tests in CI in debug mode 3 | println!("cargo:rustc-check-cfg=cfg(is_not_release)"); 4 | println!("cargo:rerun-if-env-changed=CI"); 5 | if std::env::var("CI").is_err() { 6 | if let Ok(level) = std::env::var("OPT_LEVEL") { 7 | if level == "0" || level == "1" { 8 | println!("cargo::rustc-cfg=is_not_release"); 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /qa-test/src/bin/embassy_adc.rs: -------------------------------------------------------------------------------- 1 | //! This shows how to asynchronously read ADC data 2 | //! 3 | //! PINS 4 | //! GPIO4 for ADC1 5 | //! ONLY ESP32-C3: GPIO5 for ADC2 6 | 7 | //% CHIPS: esp32c2 esp32c3 esp32c6 esp32h2 8 | 9 | #![no_std] 10 | #![no_main] 11 | 12 | use embassy_executor::Spawner; 13 | use esp_backtrace as _; 14 | use esp_hal::{ 15 | analog::adc::{Adc, AdcConfig, Attenuation}, 16 | delay::Delay, 17 | timer::timg::TimerGroup, 18 | }; 19 | use esp_println::println; 20 | 21 | esp_bootloader_esp_idf::esp_app_desc!(); 22 | 23 | #[esp_hal_embassy::main] 24 | async fn main(_spawner: Spawner) { 25 | esp_println::logger::init_logger_from_env(); 26 | let peripherals = esp_hal::init(esp_hal::Config::default()); 27 | 28 | let timg0 = TimerGroup::new(peripherals.TIMG0); 29 | esp_hal_embassy::init(timg0.timer0); 30 | 31 | let mut adc1_config = AdcConfig::new(); 32 | let analog_pin1 = peripherals.GPIO4; 33 | let mut pin1 = adc1_config.enable_pin(analog_pin1, Attenuation::_11dB); 34 | let mut adc1 = Adc::new(peripherals.ADC1, adc1_config).into_async(); 35 | 36 | cfg_if::cfg_if! { 37 | if #[cfg(feature = "esp32c3")] { 38 | let mut adc2_config = AdcConfig::new(); 39 | let analog_pin2 = peripherals.GPIO5; 40 | let mut pin2 = adc2_config.enable_pin(analog_pin2, Attenuation::_11dB); 41 | let mut adc2 = Adc::new(peripherals.ADC2, adc2_config).into_async(); 42 | } 43 | } 44 | 45 | let delay = Delay::new(); 46 | 47 | loop { 48 | let adc1_value: u16 = adc1.read_oneshot(&mut pin1).await; 49 | println!("ADC1 value: {}", adc1_value); 50 | cfg_if::cfg_if! { 51 | if #[cfg(feature = "esp32c3")] { 52 | let adc2_value: u16 = adc2.read_oneshot(&mut pin2).await; 53 | println!("ADC2 value: {}", adc2_value); 54 | } 55 | } 56 | delay.delay_millis(1000); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /qa-test/src/bin/embassy_i2c.rs: -------------------------------------------------------------------------------- 1 | //! Embassy I2C 2 | //! 3 | //! Depending on your target and the board you are using you have to change the 4 | //! pins. 5 | //! 6 | //! This is an example of running the embassy executor with IC2. It uses an 7 | //! LIS3DH to get accelerometer data. 8 | //! 9 | //! Following pins are used: 10 | //! - SDA => GPIO4 11 | //! - SCL => GPIO5 12 | 13 | //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 14 | 15 | #![no_std] 16 | #![no_main] 17 | 18 | use embassy_executor::Spawner; 19 | use embassy_time::{Duration, Timer}; 20 | use esp_backtrace as _; 21 | use esp_hal::{ 22 | i2c::master::{Config, I2c}, 23 | time::Rate, 24 | timer::timg::TimerGroup, 25 | }; 26 | use lis3dh_async::{Lis3dh, Range, SlaveAddr}; 27 | 28 | esp_bootloader_esp_idf::esp_app_desc!(); 29 | 30 | #[esp_hal_embassy::main] 31 | async fn main(_spawner: Spawner) { 32 | let peripherals = esp_hal::init(esp_hal::Config::default()); 33 | 34 | let timg0 = TimerGroup::new(peripherals.TIMG0); 35 | esp_hal_embassy::init(timg0.timer0); 36 | 37 | let i2c0 = I2c::new( 38 | peripherals.I2C0, 39 | Config::default().with_frequency(Rate::from_khz(400)), 40 | ) 41 | .unwrap() 42 | .with_sda(peripherals.GPIO4) 43 | .with_scl(peripherals.GPIO5) 44 | .into_async(); 45 | 46 | let mut lis3dh = Lis3dh::new_i2c(i2c0, SlaveAddr::Alternate).await.unwrap(); 47 | lis3dh.set_range(Range::G8).await.unwrap(); 48 | 49 | loop { 50 | let norm = lis3dh.accel_norm().await.unwrap(); 51 | esp_println::println!("X: {:+.5} Y: {:+.5} Z: {:+.5}", norm.x, norm.y, norm.z); 52 | 53 | Timer::after(Duration::from_millis(100)).await; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /qa-test/src/bin/embassy_i2c_bmp180_calibration_data.rs: -------------------------------------------------------------------------------- 1 | //! Embassy "async" version of ead calibration data from BMP180 sensor 2 | //! 3 | //! This example dumps the calibration data from a BMP180 sensor by reading by 4 | //! reading with the direct I2C API and the embedded-hal-async I2C API. 5 | //! 6 | //! Following pins are used: 7 | //! - SDA => GPIO4 8 | //! - SCL => GPIO5 9 | //! 10 | //! Depending on your target and the board you are using you have to change the 11 | //! pins. 12 | 13 | //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 14 | //% TAG: bmp180 15 | 16 | #![no_std] 17 | #![no_main] 18 | 19 | use embassy_executor::Spawner; 20 | use embassy_time::{Duration, Timer}; 21 | use esp_backtrace as _; 22 | use esp_hal::{ 23 | i2c::master::{Config, I2c}, 24 | time::Rate, 25 | timer::timg::TimerGroup, 26 | }; 27 | 28 | esp_bootloader_esp_idf::esp_app_desc!(); 29 | 30 | #[esp_hal_embassy::main] 31 | async fn main(_spawner: Spawner) { 32 | let peripherals = esp_hal::init(esp_hal::Config::default()); 33 | 34 | let timg0 = TimerGroup::new(peripherals.TIMG0); 35 | esp_hal_embassy::init(timg0.timer0); 36 | 37 | let mut i2c = I2c::new( 38 | peripherals.I2C0, 39 | Config::default().with_frequency(Rate::from_khz(400)), 40 | ) 41 | .unwrap() 42 | .with_sda(peripherals.GPIO4) 43 | .with_scl(peripherals.GPIO5) 44 | .into_async(); 45 | 46 | loop { 47 | let mut data = [0u8; 22]; 48 | i2c.write_read_async(0x77, &[0xaa], &mut data) 49 | .await 50 | .unwrap(); 51 | esp_println::println!("direct: {:02x?}", data); 52 | read_data(&mut i2c).await; 53 | Timer::after(Duration::from_millis(1000)).await; 54 | } 55 | } 56 | 57 | async fn read_data(i2c: &mut I2C) 58 | where 59 | I2C: embedded_hal_async::i2c::I2c, 60 | { 61 | let mut data = [0u8; 22]; 62 | i2c.write_read(0x77, &[0xaa], &mut data).await.unwrap(); 63 | 64 | esp_println::println!("embedded_hal: {:02x?}", data); 65 | } 66 | -------------------------------------------------------------------------------- /qa-test/src/bin/i2c_bmp180_calibration_data.rs: -------------------------------------------------------------------------------- 1 | //! Read calibration data from BMP180 sensor 2 | //! 3 | //! This example dumps the calibration data from a BMP180 sensor 4 | //! 5 | //! The following wiring is assumed: 6 | //! - SDA => GPIO4 7 | //! - SCL => GPIO5 8 | 9 | //% CHIPS: esp32 esp32c2 esp32c3 esp32c6 esp32h2 esp32s2 esp32s3 10 | //% TAG: bmp180 11 | 12 | #![no_std] 13 | #![no_main] 14 | 15 | use esp_backtrace as _; 16 | use esp_hal::{ 17 | i2c::master::{Config, I2c}, 18 | main, 19 | }; 20 | use esp_println::println; 21 | 22 | esp_bootloader_esp_idf::esp_app_desc!(); 23 | 24 | #[main] 25 | fn main() -> ! { 26 | let peripherals = esp_hal::init(esp_hal::Config::default()); 27 | 28 | // Create a new peripheral object with the described wiring and standard 29 | // I2C clock speed: 30 | let mut i2c = I2c::new(peripherals.I2C0, Config::default()) 31 | .unwrap() 32 | .with_sda(peripherals.GPIO4) 33 | .with_scl(peripherals.GPIO5); 34 | 35 | loop { 36 | let mut data = [0u8; 22]; 37 | i2c.write_read(0x77, &[0xaa], &mut data).ok(); 38 | 39 | println!("{:02x?}", data); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /qa-test/src/bin/sleep_timer.rs: -------------------------------------------------------------------------------- 1 | //! Demonstrates deep sleep with timer wakeup 2 | 3 | //% CHIPS: esp32 esp32c3 esp32c6 esp32s2 esp32s3 esp32c2 4 | 5 | #![no_std] 6 | #![no_main] 7 | 8 | use core::time::Duration; 9 | 10 | use esp_backtrace as _; 11 | use esp_hal::{ 12 | delay::Delay, 13 | main, 14 | rtc_cntl::{Rtc, SocResetReason, reset_reason, sleep::TimerWakeupSource, wakeup_cause}, 15 | system::Cpu, 16 | }; 17 | use esp_println::println; 18 | 19 | esp_bootloader_esp_idf::esp_app_desc!(); 20 | 21 | #[main] 22 | fn main() -> ! { 23 | let peripherals = esp_hal::init(esp_hal::Config::default()); 24 | 25 | let delay = Delay::new(); 26 | let mut rtc = Rtc::new(peripherals.LPWR); 27 | 28 | println!("up and runnning!"); 29 | let reason = reset_reason(Cpu::ProCpu).unwrap_or(SocResetReason::ChipPowerOn); 30 | println!("reset reason: {:?}", reason); 31 | let wake_reason = wakeup_cause(); 32 | println!("wake reason: {:?}", wake_reason); 33 | 34 | let timer = TimerWakeupSource::new(Duration::from_secs(5)); 35 | println!("sleeping!"); 36 | delay.delay_millis(100); 37 | rtc.sleep_deep(&[&timer]); 38 | } 39 | -------------------------------------------------------------------------------- /qa-test/src/bin/sleep_timer_ext0.rs: -------------------------------------------------------------------------------- 1 | //! Demonstrates deep sleep with timer and ext0 wakeup 2 | //! 3 | //! The following wiring is assumed: 4 | //! - ext0 wakeup pin => GPIO4 5 | 6 | //% CHIPS: esp32 esp32s2 esp32s3 7 | 8 | #![no_std] 9 | #![no_main] 10 | 11 | use core::time::Duration; 12 | 13 | use esp_backtrace as _; 14 | use esp_hal::{ 15 | delay::Delay, 16 | gpio::{Input, InputConfig, Pull}, 17 | main, 18 | rtc_cntl::{ 19 | Rtc, 20 | SocResetReason, 21 | reset_reason, 22 | sleep::{Ext0WakeupSource, TimerWakeupSource, WakeupLevel}, 23 | wakeup_cause, 24 | }, 25 | system::Cpu, 26 | }; 27 | use esp_println::println; 28 | 29 | esp_bootloader_esp_idf::esp_app_desc!(); 30 | 31 | #[main] 32 | fn main() -> ! { 33 | let peripherals = esp_hal::init(esp_hal::Config::default()); 34 | 35 | let mut rtc = Rtc::new(peripherals.LPWR); 36 | 37 | let mut pin4 = peripherals.GPIO4; 38 | let ext0_pin = Input::new( 39 | pin4.reborrow(), 40 | InputConfig::default().with_pull(Pull::None), 41 | ); 42 | 43 | println!("up and runnning!"); 44 | let reason = reset_reason(Cpu::ProCpu).unwrap_or(SocResetReason::ChipPowerOn); 45 | println!("reset reason: {:?}", reason); 46 | let wake_reason = wakeup_cause(); 47 | println!("wake reason: {:?}", wake_reason); 48 | 49 | let delay = Delay::new(); 50 | 51 | core::mem::drop(ext0_pin); 52 | 53 | let timer = TimerWakeupSource::new(Duration::from_secs(30)); 54 | let ext0 = Ext0WakeupSource::new(pin4, WakeupLevel::High); 55 | println!("sleeping!"); 56 | delay.delay_millis(100); 57 | rtc.sleep_deep(&[&timer, &ext0]); 58 | } 59 | -------------------------------------------------------------------------------- /qa-test/src/bin/sleep_timer_ext1.rs: -------------------------------------------------------------------------------- 1 | //! Demonstrates deep sleep with timer and ext1 wakeup 2 | //! 3 | //! The following wiring is assumed: 4 | //! - ext1 wakeup pins => GPIO2, GPIO4 5 | 6 | //% CHIPS: esp32 esp32s2 esp32s3 7 | 8 | #![no_std] 9 | #![no_main] 10 | 11 | use core::time::Duration; 12 | 13 | use esp_backtrace as _; 14 | use esp_hal::{ 15 | delay::Delay, 16 | gpio::{Input, InputConfig, Pull, RtcPin}, 17 | main, 18 | rtc_cntl::{ 19 | Rtc, 20 | SocResetReason, 21 | reset_reason, 22 | sleep::{Ext1WakeupSource, TimerWakeupSource, WakeupLevel}, 23 | wakeup_cause, 24 | }, 25 | system::Cpu, 26 | }; 27 | use esp_println::println; 28 | 29 | esp_bootloader_esp_idf::esp_app_desc!(); 30 | 31 | #[main] 32 | fn main() -> ! { 33 | let peripherals = esp_hal::init(esp_hal::Config::default()); 34 | 35 | let mut rtc = Rtc::new(peripherals.LPWR); 36 | 37 | let mut pin_2 = peripherals.GPIO2; 38 | let mut pin_4 = peripherals.GPIO4; 39 | let input = Input::new( 40 | pin_4.reborrow(), 41 | InputConfig::default().with_pull(Pull::None), 42 | ); 43 | 44 | println!("up and runnning!"); 45 | let reason = reset_reason(Cpu::ProCpu).unwrap_or(SocResetReason::ChipPowerOn); 46 | println!("reset reason: {:?}", reason); 47 | let wake_reason = wakeup_cause(); 48 | println!("wake reason: {:?}", wake_reason); 49 | 50 | let delay = Delay::new(); 51 | 52 | let timer = TimerWakeupSource::new(Duration::from_secs(30)); 53 | core::mem::drop(input); 54 | let mut wakeup_pins: [&mut dyn RtcPin; 2] = [&mut pin_4, &mut pin_2]; 55 | let ext1 = Ext1WakeupSource::new(&mut wakeup_pins, WakeupLevel::High); 56 | println!("sleeping!"); 57 | delay.delay_millis(100); 58 | rtc.sleep_deep(&[&timer, &ext1]); 59 | } 60 | -------------------------------------------------------------------------------- /qa-test/src/bin/sleep_timer_lpio.rs: -------------------------------------------------------------------------------- 1 | //! Demonstrates deep sleep with timer, using low and high level pins as wakeup 2 | //! sources. 3 | //! 4 | //! The following wiring is assumed: 5 | //! - ext1 wakeup pin => GPIO2 (low level) / GPIO3 (high level) 6 | 7 | //% CHIPS: esp32c6 8 | 9 | #![no_std] 10 | #![no_main] 11 | 12 | use core::time::Duration; 13 | 14 | use esp_backtrace as _; 15 | use esp_hal::{ 16 | delay::Delay, 17 | gpio::{Input, InputConfig, Pull, RtcPinWithResistors}, 18 | main, 19 | rtc_cntl::{ 20 | Rtc, 21 | SocResetReason, 22 | reset_reason, 23 | sleep::{Ext1WakeupSource, TimerWakeupSource, WakeupLevel}, 24 | wakeup_cause, 25 | }, 26 | system::Cpu, 27 | }; 28 | use esp_println::println; 29 | 30 | esp_bootloader_esp_idf::esp_app_desc!(); 31 | 32 | #[main] 33 | fn main() -> ! { 34 | let peripherals = esp_hal::init(esp_hal::Config::default()); 35 | 36 | let mut rtc = Rtc::new(peripherals.LPWR); 37 | 38 | let mut pin2 = peripherals.GPIO2; 39 | let mut pin3 = peripherals.GPIO3; 40 | let input = Input::new( 41 | pin2.reborrow(), 42 | InputConfig::default().with_pull(Pull::None), 43 | ); 44 | 45 | println!("up and runnning!"); 46 | let reason = reset_reason(Cpu::ProCpu).unwrap_or(SocResetReason::ChipPowerOn); 47 | println!("reset reason: {:?}", reason); 48 | let wake_reason = wakeup_cause(); 49 | println!("wake reason: {:?}", wake_reason); 50 | 51 | let delay = Delay::new(); 52 | let timer = TimerWakeupSource::new(Duration::from_secs(10)); 53 | 54 | core::mem::drop(input); 55 | 56 | let wakeup_pins: &mut [(&mut dyn RtcPinWithResistors, WakeupLevel)] = &mut [ 57 | (&mut pin2, WakeupLevel::Low), 58 | (&mut pin3, WakeupLevel::High), 59 | ]; 60 | 61 | let rtcio = Ext1WakeupSource::new(wakeup_pins); 62 | println!("sleeping!"); 63 | delay.delay_millis(100); 64 | rtc.sleep_deep(&[&timer, &rtcio]); 65 | } 66 | -------------------------------------------------------------------------------- /qa-test/src/bin/temperature_sensor.rs: -------------------------------------------------------------------------------- 1 | //! This example uses the internal temperature sensor to measure the chip's 2 | //! temperature 3 | 4 | //% CHIPS: esp32c6 esp32c3 5 | 6 | #![no_std] 7 | #![no_main] 8 | 9 | use esp_backtrace as _; 10 | use esp_hal::{ 11 | delay::Delay, 12 | main, 13 | tsens::{Config, TemperatureSensor}, 14 | }; 15 | use esp_println::println; 16 | 17 | esp_bootloader_esp_idf::esp_app_desc!(); 18 | 19 | #[main] 20 | fn main() -> ! { 21 | esp_println::logger::init_logger_from_env(); 22 | let peripherals = esp_hal::init(esp_hal::Config::default()); 23 | 24 | let temperature_sensor = TemperatureSensor::new(peripherals.TSENS, Config::default()).unwrap(); 25 | let delay = Delay::new(); 26 | 27 | // Wait for the sensor to stabilize 28 | delay.delay_micros(200); 29 | 30 | loop { 31 | let temp = temperature_sensor.get_temperature(); 32 | println!("Temperature: {:.2}°C", temp.to_celsius()); 33 | delay.delay_millis(1_000); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /resources/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "tabWidth": 2 4 | } 5 | -------------------------------------------------------------------------------- /resources/select.html.jinja: -------------------------------------------------------------------------------- 1 |
2 | 3 | 6 |
7 | 8 | 49 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | # Comments 2 | format_code_in_doc_comments = true 3 | normalize_comments = true 4 | wrap_comments = true 5 | 6 | # Enums 7 | enum_discrim_align_threshold = 35 8 | 9 | # Imports 10 | group_imports = "StdExternalCrate" 11 | imports_granularity = "Crate" 12 | imports_layout = "HorizontalVertical" 13 | -------------------------------------------------------------------------------- /xtask/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xtask" 3 | version = "0.0.0" 4 | edition = "2024" 5 | publish = false 6 | 7 | [dependencies] 8 | anyhow = "1.0.93" 9 | basic-toml = "0.1.9" 10 | clap = { version = "4.5.20", features = ["derive", "wrap_help"] } 11 | console = "0.15.10" 12 | env_logger = "0.11.5" 13 | esp-metadata = { path = "../esp-metadata", features = ["clap"] } 14 | jiff = { version = "0.2.13" } 15 | kuchikiki = "0.8.2" 16 | log = "0.4.22" 17 | minijinja = "2.5.0" 18 | opener = { version = "0.7.2", optional = true } 19 | rocket = { version = "0.5.1", optional = true } 20 | semver = { version = "1.0.23", features = ["serde"] } 21 | serde = { version = "1.0.215", features = ["derive"] } 22 | serde_json = "1.0.70" 23 | strum = { version = "0.27.1", features = ["derive"] } 24 | toml_edit = "0.22.22" 25 | walkdir = "2.5.0" 26 | 27 | # Only required when building documentation for deployment: 28 | reqwest = { version = "0.12.12", features = [ 29 | "blocking", 30 | "json", 31 | "native-tls-vendored", 32 | ], optional = true } 33 | 34 | # This pulls a gazillion crates - don't include it by default 35 | cargo-semver-checks = { version = "0.41.0", optional = true } 36 | 37 | # THIS NEEDS TO MATCH THE rustfmt-json FORMAT - see https://github.com/rust-lang/rustdoc-types/blob/trunk/CHANGELOG.md 38 | rustdoc-types = { version = "0.35.0", optional = true } 39 | 40 | flate2 = { version = "1.1.1", optional = true } 41 | temp-file = { version = "0.1.9", optional = true } 42 | urlencoding = { version = "2.1.3", optional = true } 43 | 44 | [dev-dependencies] 45 | pretty_assertions = "1.2.0" 46 | 47 | [features] 48 | deploy-docs = ["dep:reqwest"] 49 | preview-docs = ["dep:opener", "dep:rocket"] 50 | semver-checks = [ "dep:cargo-semver-checks", "dep:rustdoc-types", "dep:flate2", "dep:temp-file" ] 51 | release = ["semver-checks", "dep:opener", "dep:urlencoding"] 52 | -------------------------------------------------------------------------------- /xtask/src/commands/check_changelog.rs: -------------------------------------------------------------------------------- 1 | use std::path::Path; 2 | 3 | use anyhow::{Context, Result, bail}; 4 | 5 | use crate::{Package, changelog::Changelog}; 6 | 7 | pub fn check_changelog(workspace: &Path, packages: &[Package], normalize: bool) -> Result<()> { 8 | let mut failed = false; 9 | for package in packages { 10 | if let Err(e) = check_changelog_for_package(workspace, *package, normalize) { 11 | eprintln!("Error checking changelog for package {}: {:?}", package, e); 12 | failed = true; 13 | } 14 | } 15 | 16 | if failed { 17 | bail!("One or more changelogs failed to check."); 18 | } 19 | 20 | Ok(()) 21 | } 22 | 23 | fn check_changelog_for_package(workspace: &Path, package: Package, normalize: bool) -> Result<()> { 24 | let changelog_path = workspace.join(package.to_string()).join("CHANGELOG.md"); 25 | 26 | if !changelog_path.exists() { 27 | // No changelog exists for this package 28 | return Ok(()); 29 | } 30 | 31 | log::info!(" Checking changelog for package: {package}"); 32 | 33 | // Let's parse the old changelog first 34 | let changelog_str = std::fs::read_to_string(&changelog_path) 35 | .with_context(|| format!("Could not read {}", changelog_path.display()))?; 36 | 37 | let changelog = Changelog::parse(&changelog_str) 38 | .with_context(|| format!("Could not parse {}", changelog_path.display()))?; 39 | 40 | if normalize { 41 | std::fs::write(&changelog_path, changelog.to_string())?; 42 | } 43 | 44 | Ok(()) 45 | } 46 | -------------------------------------------------------------------------------- /xtask/src/commands/release/publish.rs: -------------------------------------------------------------------------------- 1 | use std::path::Path; 2 | 3 | use anyhow::{Result, ensure}; 4 | use clap::Args; 5 | 6 | use crate::{Package, cargo::CargoArgsBuilder, windows_safe_path}; 7 | 8 | #[derive(Debug, Args)] 9 | pub struct PublishArgs { 10 | /// Package to publish (performs a dry-run by default). 11 | #[arg(value_enum)] 12 | package: Package, 13 | 14 | /// Do not pass the `--dry-run` argument, actually try to publish. 15 | #[arg(long)] 16 | no_dry_run: bool, 17 | } 18 | 19 | pub fn publish(workspace: &Path, args: PublishArgs) -> Result<()> { 20 | let package_name = args.package.to_string(); 21 | let package_path = windows_safe_path(&workspace.join(&package_name)); 22 | 23 | ensure!( 24 | args.package.is_published(workspace), 25 | "Invalid package '{}' specified, this package should not be published!", 26 | args.package 27 | ); 28 | 29 | let mut publish_args = if args.package.has_chip_features() { 30 | vec!["--no-verify"] 31 | } else { 32 | vec![] 33 | }; 34 | 35 | if !args.no_dry_run { 36 | publish_args.push("--dry-run"); 37 | } 38 | 39 | let builder = CargoArgsBuilder::default() 40 | .subcommand("publish") 41 | .args(&publish_args); 42 | 43 | let args = builder.build(); 44 | log::debug!("{args:#?}"); 45 | 46 | // Execute `cargo publish` command from the package root: 47 | crate::cargo::run(&args, &package_path)?; 48 | 49 | Ok(()) 50 | } 51 | -------------------------------------------------------------------------------- /xtask/src/git.rs: -------------------------------------------------------------------------------- 1 | use std::process::Command; 2 | 3 | use anyhow::{Context, Result}; 4 | 5 | pub fn current_branch() -> Result { 6 | let status = Command::new("git") 7 | .arg("rev-parse") 8 | .arg("--abbrev-ref") 9 | .arg("HEAD") 10 | .output() 11 | .context("Failed to get current branch")?; 12 | 13 | Ok(String::from_utf8_lossy(&status.stdout).trim().to_string()) 14 | } 15 | 16 | #[cfg(feature = "release")] 17 | pub fn ensure_workspace_clean(workspace: &std::path::Path) -> Result<()> { 18 | std::env::set_current_dir(workspace) 19 | .with_context(|| format!("Failed to change directory to {}", workspace.display()))?; 20 | 21 | let status = Command::new("git") 22 | .arg("status") 23 | .arg("--porcelain") 24 | .output() 25 | .context("Failed to check git status")?; 26 | 27 | anyhow::ensure!( 28 | String::from_utf8_lossy(&status.stdout).trim().is_empty(), 29 | "The workspace is not clean. Please commit or stash your changes before running this command." 30 | ); 31 | 32 | Ok(()) 33 | } 34 | 35 | #[cfg(feature = "release")] 36 | pub fn get_remote_name_for(repo: &str) -> Result { 37 | let remotes = Command::new("git") 38 | .arg("remote") 39 | .arg("-v") 40 | .output() 41 | .context("Failed to get remote URL")?; 42 | 43 | let remotes = String::from_utf8_lossy(&remotes.stdout); 44 | 45 | for line in remotes.lines() { 46 | if line.contains(repo) { 47 | let parts: Vec<_> = line.split_whitespace().collect(); 48 | if parts.len() >= 2 { 49 | return Ok(parts[0].to_string()); 50 | } 51 | } 52 | } 53 | 54 | anyhow::bail!("Failed to find remote name for {repo}"); 55 | } 56 | -------------------------------------------------------------------------------- /xtensa-lx-rt-proc-macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xtensa-lx-rt-proc-macros" 3 | version = "0.3.0" 4 | edition = "2024" 5 | rust-version = "1.86.0" 6 | description = "Attributes re-exported in `xtensa-lx-rt`" 7 | documentation = "https://docs.espressif.com/projects/rust/xtensa-lx-rt-proc-macros/latest/" 8 | repository = "https://github.com/esp-rs/esp-hal" 9 | license = "MIT OR Apache-2.0" 10 | keywords = ["esp32", "xtensa-lx-rt", "runtime", "startup"] 11 | categories = ["embedded", "no-std"] 12 | 13 | [lib] 14 | proc-macro = true 15 | 16 | [dependencies] 17 | darling = "0.20.11" 18 | proc-macro2 = "1.0.95" 19 | quote = "1.0" 20 | syn = { version = "2.0", features = ["extra-traits", "full"] } 21 | -------------------------------------------------------------------------------- /xtensa-lx-rt/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ### Added 11 | 12 | 13 | ### Changed 14 | 15 | 16 | ### Fixed 17 | 18 | 19 | ### Removed 20 | 21 | - The `esp32`, `esp32s2` and `esp32s3` features have been removed. (#3598) 22 | 23 | ## [v0.19.0] - 2025-06-03 24 | 25 | ### Changed 26 | 27 | - Bump Rust edition to 2024, bump MSRV to 1.85. (#3391) 28 | 29 | ## [0.18.0] - 2025-01-15 30 | 31 | ### Changed 32 | 33 | - Bump MSRV to 1.84 (#2951) 34 | 35 | ## 0.17.2 - 2024-11-20 36 | 37 | ### Fixed 38 | 39 | - Fixed saving the state of the FPU co-processor. (#2311) 40 | 41 | ## 0.17.1 - 2024-09-02 42 | 43 | ### Added 44 | 45 | - Better diagnostics when using floats inside an interrupt handler when using the default hard fault handler (#2044) 46 | 47 | ### Fixed 48 | 49 | - Store state of FP coprocessor in stack memory (#2057) 50 | 51 | ## Initial releases 52 | 53 | [0.18.0]: https://github.com/esp-rs/esp-hal/releases/tag/xtensa-lx-rt-v0.18.0 54 | [v0.19.0]: https://github.com/esp-rs/esp-hal/compare/xtensa-lx-rt-v0.18.0...xtensa-lx-rt-v0.19.0 55 | [Unreleased]: https://github.com/esp-rs/esp-hal/compare/xtensa-lx-rt-v0.19.0...HEAD 56 | -------------------------------------------------------------------------------- /xtensa-lx-rt/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xtensa-lx-rt" 3 | version = "0.19.0" 4 | edition = "2024" 5 | rust-version = "1.86.0" 6 | description = "Minimal startup/runtime for Xtensa LX CPUs" 7 | documentation = "https://docs.espressif.com/projects/rust/xtensa-lx-rt/latest/" 8 | repository = "https://github.com/esp-rs/esp-hal" 9 | license = "MIT OR Apache-2.0" 10 | keywords = ["lx", "peripheral", "register", "xtensa"] 11 | categories = ["embedded", "hardware-support", "no-std"] 12 | 13 | [lib] 14 | bench = false 15 | test = false 16 | 17 | [dependencies] 18 | document-features = "0.2.11" 19 | macros = { version = "0.3.0", package = "xtensa-lx-rt-proc-macros", path = "../xtensa-lx-rt-proc-macros" } 20 | r0 = "1.0.0" 21 | xtensa-lx = { version = "0.11.0", path = "../xtensa-lx" } 22 | 23 | [build-dependencies] 24 | anyhow = "1.0.98" 25 | enum-as-inner = "0.6.1" 26 | minijinja = "2.9.0" 27 | serde = { version = "1.0.219", features = ["derive"] } 28 | strum = { version = "0.27.1", features = ["derive"] } 29 | toml = "0.8.20" 30 | 31 | [features] 32 | ## Save and restore float registers for exceptions 33 | float-save-restore = [] 34 | 35 | [lints.rust] 36 | unexpected_cfgs = "allow" 37 | -------------------------------------------------------------------------------- /xtensa-lx-rt/interrupt_level_masks.rs.jinja: -------------------------------------------------------------------------------- 1 | pub enum CpuInterruptLevel { 2 | Level1, 3 | Level2, 4 | Level3, 5 | Level4, 6 | Level5, 7 | Level6, 8 | Level7, 9 | } 10 | 11 | impl CpuInterruptLevel { 12 | pub fn mask(&self) -> u32 { 13 | match &self { 14 | CpuInterruptLevel::Level1 => {{ XCHAL_INTLEVEL1_MASK }}u32, 15 | CpuInterruptLevel::Level2 => {{ XCHAL_INTLEVEL2_MASK }}u32, 16 | CpuInterruptLevel::Level3 => {{ XCHAL_INTLEVEL3_MASK }}u32, 17 | CpuInterruptLevel::Level4 => {{ XCHAL_INTLEVEL4_MASK }}u32, 18 | CpuInterruptLevel::Level5 => {{ XCHAL_INTLEVEL5_MASK }}u32, 19 | CpuInterruptLevel::Level6 => {{ XCHAL_INTLEVEL6_MASK }}u32, 20 | CpuInterruptLevel::Level7 => {{ XCHAL_INTLEVEL7_MASK }}u32, 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /xtensa-lx-rt/src/interrupt.rs: -------------------------------------------------------------------------------- 1 | //! Interrupts 2 | 3 | include!(concat!(env!("OUT_DIR"), "/interrupt_level_masks.rs")); 4 | -------------------------------------------------------------------------------- /xtensa-lx-rt/xtensa.in.x: -------------------------------------------------------------------------------- 1 | 2 | /* before memory.x to allow override */ 3 | ENTRY(Reset) 4 | 5 | INCLUDE memory.x 6 | 7 | /* after memory.x to allow override */ 8 | PROVIDE(__pre_init = DefaultPreInit); 9 | PROVIDE(__zero_bss = default_mem_hook); 10 | PROVIDE(__init_data = default_mem_hook); 11 | PROVIDE(__post_init = default_post_init); 12 | 13 | INCLUDE exception.x 14 | 15 | SECTIONS { 16 | .text : ALIGN(4) 17 | { 18 | _stext = .; 19 | . = ALIGN (4); 20 | _text_start = ABSOLUTE(.); 21 | . = ALIGN (4); 22 | *(.literal .text .literal.* .text.*) 23 | _text_end = ABSOLUTE(.); 24 | _etext = .; 25 | } > ROTEXT 26 | 27 | .rodata : ALIGN(4) 28 | { 29 | _rodata_start = ABSOLUTE(.); 30 | . = ALIGN (4); 31 | *(.rodata .rodata.*) 32 | _rodata_end = ABSOLUTE(.); 33 | } > RODATA 34 | 35 | .data : ALIGN(4) 36 | { 37 | _data_start = ABSOLUTE(.); 38 | . = ALIGN (4); 39 | *(.data .data.*) 40 | _data_end = ABSOLUTE(.); 41 | } > RWDATA AT > RODATA 42 | 43 | /* LMA of .data */ 44 | _sidata = LOADADDR(.data); 45 | 46 | .bss (NOLOAD) : ALIGN(4) 47 | { 48 | _bss_start = ABSOLUTE(.); 49 | . = ALIGN (4); 50 | *(.bss .bss.* COMMON) 51 | _bss_end = ABSOLUTE(.); 52 | } > RWDATA 53 | 54 | .noinit (NOLOAD) : ALIGN(4) 55 | { 56 | . = ALIGN(4); 57 | *(.noinit .noinit.*) 58 | } > RWDATA 59 | 60 | .rwtext : ALIGN(4) 61 | { 62 | . = ALIGN (4); 63 | *(.rwtext.literal .rwtext .rwtext.literal.* .rwtext.*) 64 | } > RWTEXT 65 | 66 | /* must be last segment using RWTEXT */ 67 | .text_heap_start (NOLOAD) : ALIGN(4) 68 | { 69 | . = ALIGN (4); 70 | _text_heap_start = ABSOLUTE(.); 71 | } > RWTEXT 72 | 73 | /* must be last segment using RWDATA */ 74 | .heap_start (NOLOAD) : ALIGN(4) 75 | { 76 | . = ALIGN (4); 77 | _heap_start = ABSOLUTE(.); 78 | } > RWDATA 79 | } 80 | -------------------------------------------------------------------------------- /xtensa-lx/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [Unreleased] 9 | 10 | ### Added 11 | 12 | 13 | ### Changed 14 | 15 | 16 | ### Fixed 17 | 18 | 19 | ### Removed 20 | 21 | 22 | ## [v0.11.0] - 2025-06-03 23 | 24 | ### Changed 25 | 26 | - Bump Rust edition to 2024, bump MSRV to 1.85. (#3391) 27 | 28 | ## [0.10.0] - 2025-01-15 29 | 30 | ### Fixed 31 | 32 | - Fixed `interrupt:free` incorrectly providing `CriticalSection` (#2537) 33 | 34 | ### Changed 35 | 36 | - The `singleton` macro has been updated to match the cortex-m counterpart (#2537) 37 | - Bump MSRV to 1.84 (#2951) 38 | 39 | ### Removed 40 | 41 | - The `spin` feature and `mutex` module has been removed. (#2537) 42 | - The `InterruptNumber` trait has been removed. (#2537) 43 | 44 | ## 0.9.0 - 2024-02-21 45 | 46 | ## 0.8.0 - 2023-02-23 47 | 48 | ## 0.7.0 - 2022-04-20 49 | 50 | ## 0.6.0 - 2022-01-16 51 | 52 | ## 0.5.0 - 2022-01-15 53 | 54 | ## 0.4.0 - 2021-08-11 55 | 56 | ## 0.3.0 - 2020-09-19 57 | 58 | [0.10.0]: https://github.com/esp-rs/esp-hal/releases/tag/xtensa-lx-v0.10.0 59 | [v0.11.0]: https://github.com/esp-rs/esp-hal/compare/xtensa-lx-v0.10.0...xtensa-lx-v0.11.0 60 | [Unreleased]: https://github.com/esp-rs/esp-hal/compare/xtensa-lx-v0.11.0...HEAD 61 | -------------------------------------------------------------------------------- /xtensa-lx/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "xtensa-lx" 3 | version = "0.11.0" 4 | edition = "2024" 5 | rust-version = "1.86.0" 6 | description = "Low-level access to Xtensa LX processors and peripherals" 7 | documentation = "https://docs.espressif.com/projects/rust/xtensa-lx/latest/" 8 | repository = "https://github.com/esp-rs/esp-hal" 9 | license = "MIT OR Apache-2.0" 10 | categories = ["embedded", "hardware-support", "no-std"] 11 | keywords = ["lx", "peripheral", "register", "xtensa"] 12 | links = "xtensa-lx" 13 | 14 | [lib] 15 | bench = false 16 | test = false 17 | 18 | [dependencies] 19 | critical-section = "1.2.0" 20 | document-features = "0.2.11" 21 | 22 | [features] 23 | -------------------------------------------------------------------------------- /xtensa-lx/README.md: -------------------------------------------------------------------------------- 1 | # `xtensa-lx` 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/xtensa-lx?labelColor=1C2C2E&color=C96329&logo=Rust&style=flat-square)](https://crates.io/crates/xtensa-lx) 4 | [![docs.rs](https://img.shields.io/docsrs/xtensa-lx?labelColor=1C2C2E&color=C96329&logo=rust&style=flat-square)](https://docs.espressif.com/projects/rust/xtensa-lx/latest/) 5 | ![MSRV](https://img.shields.io/badge/MSRV-1.84-blue?labelColor=1C2C2E&style=flat-square) 6 | ![Crates.io](https://img.shields.io/crates/l/xtensa-lx?labelColor=1C2C2E&style=flat-square) 7 | [![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) 8 | 9 | Low level access to Xtensa LX processors. 10 | 11 | ## [Documentation](https://docs.espressif.com/projects/rust/xtensa-lx/latest/) 12 | 13 | ## Minimum Supported Rust Version (MSRV) 14 | 15 | This crate is guaranteed to compile when using the latest stable Rust version at the time of the crate's release. It _might_ compile with older versions, but that may change in any new release, including patches. 16 | 17 | ## License 18 | 19 | Licensed under either of 20 | 21 | - Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or 22 | http://www.apache.org/licenses/LICENSE-2.0) 23 | - MIT license ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT) 24 | 25 | at your option. 26 | 27 | ### Contribution 28 | 29 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the 30 | work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any 31 | additional terms or conditions. 32 | -------------------------------------------------------------------------------- /xtensa-lx/build.rs: -------------------------------------------------------------------------------- 1 | // We can't remove build.rs because our Cargo.toml contains the `links` key. 2 | // directive. 3 | fn main() {} 4 | --------------------------------------------------------------------------------