Move malloc etc to esp-alloc, common C functions to esp-rom-sys, define "C functions" in esp-radio weak (#3890)

* Provide malloc, free and friends in esp-alloc

* Mute warning

* Remove some (now unused) global symbols

* Have a way to opt-out of esp-alloc's malloc,free etc.

* Fixes

* Move some common C functions from esp-radio to esp-rom-sys

* Fix

* Make esp-readio symbols weakly linked

* CHANGELOG.md

* Align MSRV, cleanup visibility

* Init before `assume_init`

* Linker script fixes

* Fix examples

* Remove heapless - esp-radio is alloc

* Fix examples

* Whitespace

* realloc_internal

* Make `__esp_radio_putchar` a no-op if `sys-logs` is not enabled
This commit is contained in:
Björn Quentin 2025-08-05 13:58:31 +02:00 committed by GitHub
parent 97cc5e4d7a
commit 3ab3490d62
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
54 changed files with 999 additions and 482 deletions

View File

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- New default feature (`compat`) enables implementations for `malloc`, `free`, `calloc`, `realloc` (#3890)
### Changed
- Make stats structs fields public (#3828)

View File

@ -28,7 +28,7 @@ linked_list_allocator = { version = "0.10.5", default-features = false, features
document-features = "0.2.11"
[features]
default = []
default = ["compat"]
## Enable nightly rustc-only features, like `feature(allocator_api)`.
nightly = []
@ -43,3 +43,6 @@ defmt = ["dep:defmt", "enumset/defmt"]
##
## ⚠️ Note: Enabling this feature will require extra computation every time alloc/dealloc is called.
internal-heap-stats = []
## Provide C-compatibility functions (malloc, free, ...)
compat = []

View File

@ -144,6 +144,8 @@
mod allocators;
mod macros;
#[cfg(feature = "compat")]
mod malloc;
use core::{
alloc::{GlobalAlloc, Layout},

119
esp-alloc/src/malloc.rs Normal file
View File

@ -0,0 +1,119 @@
#[unsafe(no_mangle)]
pub unsafe extern "C" fn malloc(size: usize) -> *mut u8 {
unsafe { malloc_with_caps(size, enumset::EnumSet::empty()) }
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn malloc_internal(size: usize) -> *mut u8 {
unsafe { malloc_with_caps(size, crate::MemoryCapability::Internal.into()) }
}
unsafe fn malloc_with_caps(
size: usize,
caps: enumset::EnumSet<crate::MemoryCapability>,
) -> *mut u8 {
let total_size = size + 4;
unsafe {
let ptr = crate::HEAP.alloc_caps(
caps,
core::alloc::Layout::from_size_align_unchecked(total_size, 4),
);
if ptr.is_null() {
return ptr;
}
*(ptr as *mut usize) = total_size;
ptr.offset(4)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn free(ptr: *mut u8) {
if ptr.is_null() {
return;
}
use core::alloc::GlobalAlloc;
unsafe {
let ptr = ptr.offset(-4);
let total_size = *(ptr as *const usize);
crate::HEAP.dealloc(
ptr,
core::alloc::Layout::from_size_align_unchecked(total_size, 4),
)
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn calloc(number: u32, size: usize) -> *mut u8 {
let total_size = number as usize * size;
unsafe {
let ptr = malloc(total_size);
if !ptr.is_null() {
for i in 0..total_size as isize {
ptr.offset(i).write_volatile(0);
}
}
ptr
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn calloc_internal(number: u32, size: usize) -> *mut u8 {
let total_size = number as usize * size;
unsafe {
let ptr = malloc_internal(total_size);
if !ptr.is_null() {
for i in 0..total_size as isize {
ptr.offset(i).write_volatile(0);
}
}
ptr
}
}
#[unsafe(no_mangle)]
unsafe extern "C" fn realloc(ptr: *mut u8, new_size: usize) -> *mut u8 {
unsafe { realloc_with_caps(ptr, new_size, enumset::EnumSet::empty()) }
}
#[unsafe(no_mangle)]
unsafe extern "C" fn realloc_internal(ptr: *mut u8, new_size: usize) -> *mut u8 {
unsafe { realloc_with_caps(ptr, new_size, crate::MemoryCapability::Internal.into()) }
}
unsafe fn realloc_with_caps(
ptr: *mut u8,
new_size: usize,
caps: enumset::EnumSet<crate::MemoryCapability>,
) -> *mut u8 {
unsafe extern "C" {
fn memcpy(d: *mut u8, s: *const u8, l: usize);
}
unsafe {
let p = malloc_with_caps(new_size, caps);
if !p.is_null() && !ptr.is_null() {
let len = usize::min(
(ptr as *const u32).sub(1).read_volatile() as usize,
new_size,
);
memcpy(p, ptr, len);
free(ptr);
}
p
}
}
#[unsafe(no_mangle)]
unsafe extern "C" fn get_free_internal_heap_size() -> usize {
crate::HEAP.free_caps(crate::MemoryCapability::Internal.into())
}

View File

@ -215,6 +215,7 @@ impl Chip {
"pm_support_ext1_wakeup",
"pm_support_touch_sensor_wakeup",
"ulp_supported",
"btdm",
"soc",
"adc",
"aes",
@ -369,6 +370,7 @@ impl Chip {
"cargo:rustc-cfg=pm_support_ext1_wakeup",
"cargo:rustc-cfg=pm_support_touch_sensor_wakeup",
"cargo:rustc-cfg=ulp_supported",
"cargo:rustc-cfg=btdm",
"cargo:rustc-cfg=soc",
"cargo:rustc-cfg=adc",
"cargo:rustc-cfg=aes",
@ -505,6 +507,7 @@ impl Chip {
"pm_support_bt_wakeup",
"uart_support_wakeup_int",
"gpio_support_deepsleep_wakeup",
"npl",
"soc",
"adc",
"assist_debug",
@ -620,6 +623,7 @@ impl Chip {
"cargo:rustc-cfg=pm_support_bt_wakeup",
"cargo:rustc-cfg=uart_support_wakeup_int",
"cargo:rustc-cfg=gpio_support_deepsleep_wakeup",
"cargo:rustc-cfg=npl",
"cargo:rustc-cfg=soc",
"cargo:rustc-cfg=adc",
"cargo:rustc-cfg=assist_debug",
@ -748,6 +752,7 @@ impl Chip {
"pm_support_bt_wakeup",
"uart_support_wakeup_int",
"gpio_support_deepsleep_wakeup",
"btdm",
"soc",
"adc",
"aes",
@ -891,6 +896,7 @@ impl Chip {
"cargo:rustc-cfg=pm_support_bt_wakeup",
"cargo:rustc-cfg=uart_support_wakeup_int",
"cargo:rustc-cfg=gpio_support_deepsleep_wakeup",
"cargo:rustc-cfg=btdm",
"cargo:rustc-cfg=soc",
"cargo:rustc-cfg=adc",
"cargo:rustc-cfg=aes",
@ -1079,6 +1085,7 @@ impl Chip {
"gpio_support_deepsleep_wakeup",
"uart_support_wakeup_int",
"pm_support_ext1_wakeup",
"npl",
"soc",
"adc",
"aes",
@ -1278,6 +1285,7 @@ impl Chip {
"cargo:rustc-cfg=gpio_support_deepsleep_wakeup",
"cargo:rustc-cfg=uart_support_wakeup_int",
"cargo:rustc-cfg=pm_support_ext1_wakeup",
"cargo:rustc-cfg=npl",
"cargo:rustc-cfg=soc",
"cargo:rustc-cfg=adc",
"cargo:rustc-cfg=aes",
@ -1462,6 +1470,7 @@ impl Chip {
"rom_crc_le",
"rom_crc_be",
"rom_md5_bsd",
"npl",
"soc",
"adc",
"aes",
@ -1635,6 +1644,7 @@ impl Chip {
"cargo:rustc-cfg=rom_crc_le",
"cargo:rustc-cfg=rom_crc_be",
"cargo:rustc-cfg=rom_md5_bsd",
"cargo:rustc-cfg=npl",
"cargo:rustc-cfg=soc",
"cargo:rustc-cfg=adc",
"cargo:rustc-cfg=aes",
@ -2159,6 +2169,7 @@ impl Chip {
"uart_support_wakeup_int",
"ulp_supported",
"riscv_coproc_supported",
"btdm",
"soc",
"adc",
"aes",
@ -2344,6 +2355,7 @@ impl Chip {
"cargo:rustc-cfg=uart_support_wakeup_int",
"cargo:rustc-cfg=ulp_supported",
"cargo:rustc-cfg=riscv_coproc_supported",
"cargo:rustc-cfg=btdm",
"cargo:rustc-cfg=soc",
"cargo:rustc-cfg=adc",
"cargo:rustc-cfg=aes",
@ -2530,6 +2542,7 @@ impl Config {
println!("cargo:rustc-check-cfg=cfg(pm_support_ext1_wakeup)");
println!("cargo:rustc-check-cfg=cfg(pm_support_touch_sensor_wakeup)");
println!("cargo:rustc-check-cfg=cfg(ulp_supported)");
println!("cargo:rustc-check-cfg=cfg(btdm)");
println!("cargo:rustc-check-cfg=cfg(soc)");
println!("cargo:rustc-check-cfg=cfg(adc)");
println!("cargo:rustc-check-cfg=cfg(aes)");
@ -2616,6 +2629,7 @@ impl Config {
println!("cargo:rustc-check-cfg=cfg(pm_support_bt_wakeup)");
println!("cargo:rustc-check-cfg=cfg(uart_support_wakeup_int)");
println!("cargo:rustc-check-cfg=cfg(gpio_support_deepsleep_wakeup)");
println!("cargo:rustc-check-cfg=cfg(npl)");
println!("cargo:rustc-check-cfg=cfg(assist_debug)");
println!("cargo:rustc-check-cfg=cfg(ecc)");
println!("cargo:rustc-check-cfg=cfg(systimer)");

View File

@ -95,6 +95,9 @@ symbols = [
"pm_support_ext1_wakeup",
"pm_support_touch_sensor_wakeup",
"ulp_supported",
# Which bluetooth implementation
"btdm",
]
memory = [{ name = "dram", start = 0x3FFA_E000, end = 0x4000_0000 }]

View File

@ -73,6 +73,9 @@ symbols = [
"pm_support_bt_wakeup",
"uart_support_wakeup_int",
"gpio_support_deepsleep_wakeup",
# Which bluetooth implementation
"npl",
]
memory = [{ name = "dram", start = 0x3FCA_0000, end = 0x3FCE_0000 }]

View File

@ -82,6 +82,9 @@ symbols = [
"pm_support_bt_wakeup",
"uart_support_wakeup_int",
"gpio_support_deepsleep_wakeup",
# Which bluetooth implementation
"btdm",
]
memory = [{ name = "dram", start = 0x3FC8_0000, end = 0x3FCE_0000 }]

View File

@ -123,6 +123,9 @@ symbols = [
"gpio_support_deepsleep_wakeup",
"uart_support_wakeup_int",
"pm_support_ext1_wakeup",
# Which bluetooth implementation
"npl",
]
memory = [{ name = "dram", start = 0x4080_0000, end = 0x4088_0000 }]

View File

@ -102,6 +102,9 @@ symbols = [
"rom_crc_le",
"rom_crc_be",
"rom_md5_bsd",
# Which bluetooth implementation
"npl",
]
memory = [{ name = "dram", start = 0x4080_0000, end = 0x4085_0000 }]

View File

@ -107,6 +107,9 @@ symbols = [
"uart_support_wakeup_int",
"ulp_supported",
"riscv_coproc_supported",
# Which bluetooth implementation
"btdm",
]
memory = [{ name = "dram", start = 0x3FC8_8000, end = 0x3FD0_0000 }]

View File

@ -19,7 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `esp-wifi` has been renamed to `esp-radio`. (#3858)
- Removed `EspWifi` prefix from structs in the package codebase. (#3869)
- Rename `esp-wifi` to `esp-radio`. (#3858)
- `esp-ieee802154` package has been folded into `esp-radio`. (#3861)
- `esp-ieee802154` package has been folded into `esp-radio`, it's now alloc. (#3861, #3890)
- `ble`, `esp-now`, `csi`, `sniffer`, `esp-ieee802154` and `smoltcp` features and APIs marked as unstable (#3865)
### Fixed

View File

@ -25,7 +25,6 @@ enumset = { version = "1.1.6", default-features = false, optional = true }
embedded-io = { version = "0.6.1", default-features = false }
embedded-io-async = { version = "0.6.1" }
esp-radio-preempt-driver = { version = "0.0.1", path = "../esp-radio-preempt-driver" }
heapless = "0.8.0"
instability = "0.3.9"
# Unstable dependencies that are not (strictly) part of the public API
@ -109,12 +108,16 @@ esp32s3 = [
"xtensa-lx-rt/float-save-restore",
]
## Use `esp-alloc` for dynamic allocations.
## Use `esp-alloc` with the `compat` feature for dynamic allocations.
##
## If you opt-out you need to provide implementations for the following functions:
## - `pub extern "C" fn esp_radio_free_internal_heap() -> usize`
## - `pub extern "C" fn esp_radio_allocate_from_internal_ram(size: usize) -> *mut u8`
## - `pub extern "C" fn esp_radio_deallocate_internal_ram(ptr: *mut u8)`
## - `pub extern "C" fn malloc(size: usize) -> *mut u8`
## - `pub extern "C" fn malloc_internal(size: usize) -> *mut u8`
## - `pub extern "C" fn free(ptr: *mut u8)`
## - `pub extern "C" fn calloc(number: u32, size: usize) -> *mut u8`
## - `pub extern "C" fn calloc_internal(number: u32, size: usize) -> *mut u8`
## - `pub extern "C" fn realloc(ptr: *mut u8, new_size: usize) -> *mut u8`
## - `pub extern "C" fn get_free_internal_heap_size() -> usize;`
esp-alloc = ["dep:esp-alloc"]
## Logs the WiFi logs from the driver at log level info (needs a nightly-compiler)

View File

@ -33,13 +33,19 @@ Furthermore, `esp_wifi::init` no longer requires `RNG` or a timer.
## Memory allocation functions
The names of functions for which the user must provide an implementation in order to use their own allocator have been changed to match `esp-radio` crate name.
The way to provide your own implementation of heap memory allocations (if not using `esp-alloc`) has changed.
Provide these symbols:
```diff
- pub extern "C" fn esp_wifi_free_internal_heap() ...
- pub extern "C" fn esp_wifi_allocate_from_internal_ram(size: usize) ...
- pub extern "C" fn esp_wifi_deallocate_internal_ram(ptr: *mut u8) ...
+ pub extern "C" fn esp_radio_free_internal_heap() ...
+ pub extern "C" fn esp_radio_allocate_from_internal_ram(size: usize) ...
+ pub extern "C" fn esp_radio_deallocate_internal_ram(ptr: *mut u8) ...
+ pub extern "C" fn malloc(size: usize) -> *mut u8 ...
+ pub extern "C" fn malloc_internal(size: usize) -> *mut u8 ...
+ pub extern "C" fn free(ptr: *mut u8) ...
+ pub extern "C" fn calloc(number: u32, size: usize) -> *mut u8 ...
+ pub extern "C" fn calloc_internal(number: u32, size: usize) -> *mut u8 ...
+ pub extern "C" fn realloc(ptr: *mut u8, new_size: usize) -> *mut u8 ...
+ pub extern "C" fn get_free_internal_heap_size() -> usize; ...
```

View File

@ -1,6 +1,12 @@
use std::error::Error;
use std::{
collections::HashMap,
error::Error,
fs::File,
io::{BufRead, Write},
path::Path,
};
use esp_config::generate_config_from_yaml_definition;
use esp_config::{Value, generate_config_from_yaml_definition};
use esp_metadata_generated::Chip;
#[macro_export]
@ -113,7 +119,26 @@ fn main() -> Result<(), Box<dyn Error>> {
println!("cargo:rerun-if-changed=./esp_config.yml");
let cfg_yaml = std::fs::read_to_string("./esp_config.yml")
.expect("Failed to read esp_config.yml for esp-radio");
generate_config_from_yaml_definition(&cfg_yaml, true, true, Some(chip)).unwrap();
let cfg = generate_config_from_yaml_definition(&cfg_yaml, true, true, Some(chip)).unwrap();
let out = std::path::PathBuf::from(std::env::var_os("OUT_DIR").unwrap());
println!("cargo:rustc-link-search={}", out.display());
println!("cargo:rerun-if-changed=./ld/");
let config = [
#[cfg(feature = "wifi")]
"wifi",
#[cfg(feature = "ble")]
"ble",
];
preprocess_file(
&config,
&cfg,
format!("./ld/{}_provides.x", chip.name()),
out.join("libesp-radio.a"),
)?;
// exploit the fact that linkers treat an unknown library format as a linker
// script
println!("cargo:rustc-link-lib=esp-radio");
Ok(())
}
@ -121,3 +146,82 @@ fn main() -> Result<(), Box<dyn Error>> {
fn print_warning(message: impl core::fmt::Display) {
println!("cargo:warning={message}");
}
fn preprocess_file(
config: &[&str],
cfg: &HashMap<String, Value>,
src: impl AsRef<Path>,
dst: impl AsRef<Path>,
) -> std::io::Result<()> {
println!("cargo:rerun-if-changed={}", src.as_ref().display());
let file = File::open(src)?;
let mut out_file = File::create(dst)?;
let mut take = Vec::new();
take.push(true);
for line in std::io::BufReader::new(file).lines() {
let line = substitute_config(cfg, &line?);
let trimmed = line.trim();
if let Some(condition) = trimmed.strip_prefix("#IF ") {
let should_take = take.iter().all(|v| *v);
let should_take = should_take && config.contains(&condition);
take.push(should_take);
continue;
} else if trimmed == "#ELSE" {
let taken = take.pop().unwrap();
let should_take = take.iter().all(|v| *v);
let should_take = should_take && !taken;
take.push(should_take);
continue;
} else if trimmed == "#ENDIF" {
take.pop();
continue;
}
if *take.last().unwrap() {
out_file.write_all(line.as_bytes())?;
let _ = out_file.write(b"\n")?;
}
}
Ok(())
}
fn substitute_config(cfg: &HashMap<String, Value>, line: &str) -> String {
let mut result = String::new();
let mut chars = line.chars().peekable();
while let Some(c) = chars.next() {
if c != '$' {
result.push(c);
continue;
}
let Some('{') = chars.peek() else {
result.push(c);
continue;
};
chars.next();
let mut key = String::new();
for c in chars.by_ref() {
if c == '}' {
break;
}
key.push(c);
}
match cfg
.get(&key)
.unwrap_or_else(|| panic!("missing config key: {key}"))
{
Value::Bool(true) => result.push('1'),
Value::Bool(false) => result.push('0'),
Value::Integer(value) => result.push_str(&value.to_string()),
Value::String(value) => result.push_str(value),
}
}
result
}

View File

@ -0,0 +1,51 @@
EXTERN( __esp_radio_strdup );
EXTERN( __ESP_RADIO_G_WIFI_OSI_FUNCS );
EXTERN( __ESP_RADIO_G_WIFI_FEATURE_CAPS );
EXTERN( __ESP_RADIO_WIFI_EVENT );
EXTERN( __esp_radio_gettimeofday );
EXTERN( __esp_radio_esp_fill_random );
EXTERN( __esp_radio_strrchr );
EXTERN( __esp_radio_misc_nvs_deinit );
EXTERN( __esp_radio_misc_nvs_init );
EXTERN( __esp_radio_misc_nvs_restore );
EXTERN( __ESP_RADIO_G_LOG_LEVEL );
EXTERN( __ESP_RADIO_G_MISC_NVS );
EXTERN( __esp_radio_esp_dport_access_reg_read );
EXTERN( __esp_radio_rtc_get_xtal );
EXTERN( __esp_radio_putchar );
EXTERN( __esp_radio_putchar );
EXTERN( __esp_radio_fwrite );
EXTERN( __esp_radio_fopen );
EXTERN( __esp_radio_fgets );
EXTERN( __esp_radio_fclose );
EXTERN( __esp_radio_sleep );
EXTERN( __esp_radio_usleep );
EXTERN( __esp_radio_phy_enter_critical );
EXTERN( __esp_radio_phy_exit_critical );
EXTERN( __esp_radio_esp_timer_get_time );
PROVIDE( strdup = __esp_radio_strdup );
PROVIDE( g_wifi_osi_funcs = __ESP_RADIO_G_WIFI_OSI_FUNCS );
PROVIDE( g_wifi_feature_caps = __ESP_RADIO_G_WIFI_FEATURE_CAPS );
PROVIDE( WIFI_EVENT = __ESP_RADIO_WIFI_EVENT );
PROVIDE( gettimeofday = __esp_radio_gettimeofday );
PROVIDE( esp_fill_random = __esp_radio_esp_fill_random );
PROVIDE( strrchr = __esp_radio_strrchr );
PROVIDE( misc_nvs_deinit = __esp_radio_misc_nvs_deinit );
PROVIDE( misc_nvs_init = __esp_radio_misc_nvs_init );
PROVIDE( misc_nvs_restore = __esp_radio_misc_nvs_restore );
PROVIDE( g_log_level = __ESP_RADIO_G_LOG_LEVEL );
PROVIDE( g_misc_nvs = __ESP_RADIO_G_MISC_NVS );
PROVIDE( esp_dport_access_reg_read = __esp_radio_esp_dport_access_reg_read );
PROVIDE( rtc_get_xtal = __esp_radio_rtc_get_xtal );
PROVIDE( putchar = __esp_radio_putchar );
PROVIDE( _putchar = __esp_radio_putchar );
PROVIDE( fwrite = __esp_radio_fwrite );
PROVIDE( fopen = __esp_radio_fopen );
PROVIDE( fgets = __esp_radio_fgets );
PROVIDE( fclose = __esp_radio_fclose );
PROVIDE( sleep = __esp_radio_sleep );
PROVIDE( usleep = __esp_radio_usleep );
PROVIDE( phy_enter_critical = __esp_radio_phy_enter_critical );
PROVIDE( phy_exit_critical = __esp_radio_phy_exit_critical );
PROVIDE( esp_timer_get_time = __esp_radio_esp_timer_get_time );

View File

@ -0,0 +1,47 @@
EXTERN( __esp_radio_strdup );
EXTERN( __ESP_RADIO_G_WIFI_OSI_FUNCS );
EXTERN( __ESP_RADIO_G_WIFI_FEATURE_CAPS );
EXTERN( __ESP_RADIO_WIFI_EVENT );
EXTERN( __esp_radio_gettimeofday );
EXTERN( __esp_radio_esp_fill_random );
EXTERN( __esp_radio_strrchr );
EXTERN( __esp_radio_esp_dport_access_reg_read );
EXTERN( __esp_radio_rtc_get_xtal );
EXTERN( __esp_radio_putchar );
EXTERN( __esp_radio_putchar );
EXTERN( __esp_radio_fwrite );
EXTERN( __esp_radio_fopen );
EXTERN( __esp_radio_fgets );
EXTERN( __esp_radio_fclose );
EXTERN( __esp_radio_esp_timer_get_time );
PROVIDE( strdup = __esp_radio_strdup );
PROVIDE( g_wifi_osi_funcs = __ESP_RADIO_G_WIFI_OSI_FUNCS );
PROVIDE( g_wifi_feature_caps = __ESP_RADIO_G_WIFI_FEATURE_CAPS );
PROVIDE( WIFI_EVENT = __ESP_RADIO_WIFI_EVENT );
PROVIDE( gettimeofday = __esp_radio_gettimeofday );
PROVIDE( esp_fill_random = __esp_radio_esp_fill_random );
PROVIDE( strrchr = __esp_radio_strrchr );
PROVIDE( esp_dport_access_reg_read = __esp_radio_esp_dport_access_reg_read );
PROVIDE( rtc_get_xtal = __esp_radio_rtc_get_xtal );
PROVIDE( putchar = __esp_radio_putchar );
PROVIDE( _putchar = __esp_radio_putchar );
PROVIDE( fwrite = __esp_radio_fwrite );
PROVIDE( fopen = __esp_radio_fopen );
PROVIDE( fgets = __esp_radio_fgets );
PROVIDE( fclose = __esp_radio_fclose );
PROVIDE( esp_timer_get_time = __esp_radio_esp_timer_get_time );
#IF wifi
EXTERN( __esp_radio_misc_nvs_deinit );
EXTERN( __esp_radio_misc_nvs_init );
EXTERN( __ESP_RADIO_G_LOG_LEVEL );
EXTERN( __esp_radio_sleep );
EXTERN( __esp_radio_usleep );
PROVIDE( misc_nvs_deinit = __esp_radio_misc_nvs_deinit );
PROVIDE( misc_nvs_init = __esp_radio_misc_nvs_init );
PROVIDE( g_log_level = __ESP_RADIO_G_LOG_LEVEL );
PROVIDE( sleep = __esp_radio_sleep );
PROVIDE( usleep = __esp_radio_usleep );
#ENDIF

View File

@ -0,0 +1,49 @@
EXTERN( __esp_radio_strdup );
EXTERN( __ESP_RADIO_G_WIFI_OSI_FUNCS );
EXTERN( __ESP_RADIO_G_WIFI_FEATURE_CAPS );
EXTERN( __ESP_RADIO_WIFI_EVENT );
EXTERN( __esp_radio_gettimeofday );
EXTERN( __esp_radio_esp_fill_random );
EXTERN( __esp_radio_strrchr );
EXTERN( __esp_radio_esp_dport_access_reg_read );
EXTERN( __esp_radio_rtc_get_xtal );
EXTERN( __esp_radio_putchar );
EXTERN( __esp_radio_putchar );
EXTERN( __esp_radio_fwrite );
EXTERN( __esp_radio_fopen );
EXTERN( __esp_radio_fgets );
EXTERN( __esp_radio_fclose );
EXTERN( __esp_radio_esp_timer_get_time );
PROVIDE( strdup = __esp_radio_strdup );
PROVIDE( g_wifi_osi_funcs = __ESP_RADIO_G_WIFI_OSI_FUNCS );
PROVIDE( g_wifi_feature_caps = __ESP_RADIO_G_WIFI_FEATURE_CAPS );
PROVIDE( WIFI_EVENT = __ESP_RADIO_WIFI_EVENT );
PROVIDE( gettimeofday = __esp_radio_gettimeofday );
PROVIDE( esp_fill_random = __esp_radio_esp_fill_random );
PROVIDE( strrchr = __esp_radio_strrchr );
PROVIDE( esp_dport_access_reg_read = __esp_radio_esp_dport_access_reg_read );
PROVIDE( rtc_get_xtal = __esp_radio_rtc_get_xtal );
PROVIDE( putchar = __esp_radio_putchar );
PROVIDE( _putchar = __esp_radio_putchar );
PROVIDE( fwrite = __esp_radio_fwrite );
PROVIDE( fopen = __esp_radio_fopen );
PROVIDE( fgets = __esp_radio_fgets );
PROVIDE( fclose = __esp_radio_fclose );
PROVIDE( esp_timer_get_time = __esp_radio_esp_timer_get_time );
#IF wifi
EXTERN( __esp_radio_misc_nvs_deinit );
EXTERN( __esp_radio_misc_nvs_init );
EXTERN( __ESP_RADIO_G_LOG_LEVEL );
EXTERN( __ESP_RADIO_G_MISC_NVS );
EXTERN( __esp_radio_sleep );
EXTERN( __esp_radio_usleep );
PROVIDE( misc_nvs_deinit = __esp_radio_misc_nvs_deinit );
PROVIDE( misc_nvs_init = __esp_radio_misc_nvs_init );
PROVIDE( g_log_level = __ESP_RADIO_G_LOG_LEVEL );
PROVIDE( g_misc_nvs = __ESP_RADIO_G_MISC_NVS );
PROVIDE( sleep = __esp_radio_sleep );
PROVIDE( usleep = __esp_radio_usleep );
#ENDIF

View File

@ -0,0 +1,47 @@
EXTERN( __esp_radio_strdup );
EXTERN( __ESP_RADIO_G_WIFI_OSI_FUNCS );
EXTERN( __ESP_RADIO_G_WIFI_FEATURE_CAPS );
EXTERN( __ESP_RADIO_WIFI_EVENT );
EXTERN( __esp_radio_gettimeofday );
EXTERN( __esp_radio_esp_fill_random );
EXTERN( __esp_radio_strrchr );
EXTERN( __esp_radio_esp_dport_access_reg_read );
EXTERN( __esp_radio_rtc_get_xtal );
EXTERN( __esp_radio_putchar );
EXTERN( __esp_radio_putchar );
EXTERN( __esp_radio_fwrite );
EXTERN( __esp_radio_fopen );
EXTERN( __esp_radio_fgets );
EXTERN( __esp_radio_fclose );
EXTERN( __esp_radio_esp_timer_get_time );
PROVIDE( strdup = __esp_radio_strdup );
PROVIDE( g_wifi_osi_funcs = __ESP_RADIO_G_WIFI_OSI_FUNCS );
PROVIDE( g_wifi_feature_caps = __ESP_RADIO_G_WIFI_FEATURE_CAPS );
PROVIDE( WIFI_EVENT = __ESP_RADIO_WIFI_EVENT );
PROVIDE( gettimeofday = __esp_radio_gettimeofday );
PROVIDE( esp_fill_random = __esp_radio_esp_fill_random );
PROVIDE( strrchr = __esp_radio_strrchr );
PROVIDE( esp_dport_access_reg_read = __esp_radio_esp_dport_access_reg_read );
PROVIDE( rtc_get_xtal = __esp_radio_rtc_get_xtal );
PROVIDE( putchar = __esp_radio_putchar );
PROVIDE( _putchar = __esp_radio_putchar );
PROVIDE( fwrite = __esp_radio_fwrite );
PROVIDE( fopen = __esp_radio_fopen );
PROVIDE( fgets = __esp_radio_fgets );
PROVIDE( fclose = __esp_radio_fclose );
PROVIDE( esp_timer_get_time = __esp_radio_esp_timer_get_time );
#IF wifi
EXTERN( __esp_radio_misc_nvs_deinit );
EXTERN( __esp_radio_misc_nvs_init );
EXTERN( __ESP_RADIO_G_LOG_LEVEL );
EXTERN( __esp_radio_sleep );
EXTERN( __esp_radio_usleep );
PROVIDE( misc_nvs_deinit = __esp_radio_misc_nvs_deinit );
PROVIDE( misc_nvs_init = __esp_radio_misc_nvs_init );
PROVIDE( g_log_level = __ESP_RADIO_G_LOG_LEVEL );
PROVIDE( sleep = __esp_radio_sleep );
PROVIDE( usleep = __esp_radio_usleep );
#ENDIF

View File

@ -0,0 +1,39 @@
EXTERN( __esp_radio_strdup );
EXTERN( __ESP_RADIO_G_WIFI_OSI_FUNCS );
EXTERN( __ESP_RADIO_G_WIFI_FEATURE_CAPS );
EXTERN( __ESP_RADIO_WIFI_EVENT );
EXTERN( __esp_radio_gettimeofday );
EXTERN( __esp_radio_esp_fill_random );
EXTERN( __esp_radio_strrchr );
EXTERN( __esp_radio_misc_nvs_deinit );
EXTERN( __esp_radio_misc_nvs_init );
EXTERN( __ESP_RADIO_G_LOG_LEVEL );
EXTERN( __esp_radio_esp_dport_access_reg_read );
EXTERN( __esp_radio_rtc_get_xtal );
EXTERN( __esp_radio_putchar );
EXTERN( __esp_radio_putchar );
EXTERN( __esp_radio_fwrite );
EXTERN( __esp_radio_fopen );
EXTERN( __esp_radio_fgets );
EXTERN( __esp_radio_fclose );
EXTERN( __esp_radio_esp_timer_get_time );
PROVIDE( strdup = __esp_radio_strdup );
PROVIDE( g_wifi_osi_funcs = __ESP_RADIO_G_WIFI_OSI_FUNCS );
PROVIDE( g_wifi_feature_caps = __ESP_RADIO_G_WIFI_FEATURE_CAPS );
PROVIDE( WIFI_EVENT = __ESP_RADIO_WIFI_EVENT );
PROVIDE( gettimeofday = __esp_radio_gettimeofday );
PROVIDE( esp_fill_random = __esp_radio_esp_fill_random );
PROVIDE( strrchr = __esp_radio_strrchr );
PROVIDE( misc_nvs_deinit = __esp_radio_misc_nvs_deinit );
PROVIDE( misc_nvs_init = __esp_radio_misc_nvs_init );
PROVIDE( g_log_level = __ESP_RADIO_G_LOG_LEVEL );
PROVIDE( esp_dport_access_reg_read = __esp_radio_esp_dport_access_reg_read );
PROVIDE( rtc_get_xtal = __esp_radio_rtc_get_xtal );
PROVIDE( putchar = __esp_radio_putchar );
PROVIDE( _putchar = __esp_radio_putchar );
PROVIDE( fwrite = __esp_radio_fwrite );
PROVIDE( fopen = __esp_radio_fopen );
PROVIDE( fgets = __esp_radio_fgets );
PROVIDE( fclose = __esp_radio_fclose );
PROVIDE( esp_timer_get_time = __esp_radio_esp_timer_get_time );

View File

@ -0,0 +1,51 @@
EXTERN( __esp_radio_strdup );
EXTERN( __esp_radio_esp_timer_get_time );
EXTERN( __ESP_RADIO_G_WIFI_OSI_FUNCS );
EXTERN( __ESP_RADIO_G_WIFI_FEATURE_CAPS );
EXTERN( __ESP_RADIO_WIFI_EVENT );
EXTERN( __esp_radio_gettimeofday );
EXTERN( __esp_radio_esp_fill_random );
EXTERN( __esp_radio_strrchr );
EXTERN( __esp_radio_misc_nvs_deinit );
EXTERN( __esp_radio_misc_nvs_init );
EXTERN( __esp_radio_misc_nvs_restore );
EXTERN( __ESP_RADIO_G_LOG_LEVEL );
EXTERN( __ESP_RADIO_G_MISC_NVS );
EXTERN( __esp_radio_esp_dport_access_reg_read );
EXTERN( __esp_radio_rtc_get_xtal );
EXTERN( __esp_radio_putchar );
EXTERN( __esp_radio_putchar );
EXTERN( __esp_radio_fwrite );
EXTERN( __esp_radio_fopen );
EXTERN( __esp_radio_fgets );
EXTERN( __esp_radio_fclose );
EXTERN( __esp_radio_sleep );
EXTERN( __esp_radio_usleep );
EXTERN( __esp_radio_phy_enter_critical );
EXTERN( __esp_radio_phy_exit_critical );
PROVIDE( strdup = __esp_radio_strdup );
PROVIDE( esp_timer_get_time = __esp_radio_esp_timer_get_time );
PROVIDE( g_wifi_osi_funcs = __ESP_RADIO_G_WIFI_OSI_FUNCS );
PROVIDE( g_wifi_feature_caps = __ESP_RADIO_G_WIFI_FEATURE_CAPS );
PROVIDE( WIFI_EVENT = __ESP_RADIO_WIFI_EVENT );
PROVIDE( gettimeofday = __esp_radio_gettimeofday );
PROVIDE( esp_fill_random = __esp_radio_esp_fill_random );
PROVIDE( strrchr = __esp_radio_strrchr );
PROVIDE( misc_nvs_deinit = __esp_radio_misc_nvs_deinit );
PROVIDE( misc_nvs_init = __esp_radio_misc_nvs_init );
PROVIDE( misc_nvs_restore = __esp_radio_misc_nvs_restore );
PROVIDE( g_log_level = __ESP_RADIO_G_LOG_LEVEL );
PROVIDE( g_misc_nvs = __ESP_RADIO_G_MISC_NVS );
PROVIDE( esp_dport_access_reg_read = __esp_radio_esp_dport_access_reg_read );
PROVIDE( rtc_get_xtal = __esp_radio_rtc_get_xtal );
PROVIDE( putchar = __esp_radio_putchar );
PROVIDE( _putchar = __esp_radio_putchar );
PROVIDE( fwrite = __esp_radio_fwrite );
PROVIDE( fopen = __esp_radio_fopen );
PROVIDE( fgets = __esp_radio_fgets );
PROVIDE( fclose = __esp_radio_fclose );
PROVIDE( sleep = __esp_radio_sleep );
PROVIDE( usleep = __esp_radio_usleep );
PROVIDE( phy_enter_critical = __esp_radio_phy_enter_critical );
PROVIDE( phy_exit_critical = __esp_radio_phy_exit_critical );

View File

@ -0,0 +1,47 @@
EXTERN( __esp_radio_strdup );
EXTERN( __ESP_RADIO_G_WIFI_OSI_FUNCS );
EXTERN( __ESP_RADIO_G_WIFI_FEATURE_CAPS );
EXTERN( __ESP_RADIO_WIFI_EVENT );
EXTERN( __esp_radio_gettimeofday );
EXTERN( __esp_radio_esp_fill_random );
EXTERN( __esp_radio_strrchr );
EXTERN( __esp_radio_misc_nvs_deinit );
EXTERN( __esp_radio_misc_nvs_init );
EXTERN( __esp_radio_misc_nvs_restore );
EXTERN( __ESP_RADIO_G_LOG_LEVEL );
EXTERN( __ESP_RADIO_G_MISC_NVS );
EXTERN( __esp_radio_esp_dport_access_reg_read );
EXTERN( __esp_radio_rtc_get_xtal );
EXTERN( __esp_radio_putchar );
EXTERN( __esp_radio_putchar );
EXTERN( __esp_radio_fwrite );
EXTERN( __esp_radio_fopen );
EXTERN( __esp_radio_fgets );
EXTERN( __esp_radio_fclose );
EXTERN( __esp_radio_sleep );
EXTERN( __esp_radio_usleep );
EXTERN( __esp_radio_esp_timer_get_time );
PROVIDE( strdup = __esp_radio_strdup );
PROVIDE( g_wifi_osi_funcs = __ESP_RADIO_G_WIFI_OSI_FUNCS );
PROVIDE( g_wifi_feature_caps = __ESP_RADIO_G_WIFI_FEATURE_CAPS );
PROVIDE( WIFI_EVENT = __ESP_RADIO_WIFI_EVENT );
PROVIDE( gettimeofday = __esp_radio_gettimeofday );
PROVIDE( esp_fill_random = __esp_radio_esp_fill_random );
PROVIDE( strrchr = __esp_radio_strrchr );
PROVIDE( misc_nvs_deinit = __esp_radio_misc_nvs_deinit );
PROVIDE( misc_nvs_init = __esp_radio_misc_nvs_init );
PROVIDE( misc_nvs_restore = __esp_radio_misc_nvs_restore );
PROVIDE( g_log_level = __ESP_RADIO_G_LOG_LEVEL );
PROVIDE( g_misc_nvs = __ESP_RADIO_G_MISC_NVS );
PROVIDE( esp_dport_access_reg_read = __esp_radio_esp_dport_access_reg_read );
PROVIDE( rtc_get_xtal = __esp_radio_rtc_get_xtal );
PROVIDE( putchar = __esp_radio_putchar );
PROVIDE( _putchar = __esp_radio_putchar );
PROVIDE( fwrite = __esp_radio_fwrite );
PROVIDE( fopen = __esp_radio_fopen );
PROVIDE( fgets = __esp_radio_fgets );
PROVIDE( fclose = __esp_radio_fclose );
PROVIDE( sleep = __esp_radio_sleep );
PROVIDE( usleep = __esp_radio_usleep );
PROVIDE( esp_timer_get_time = __esp_radio_esp_timer_get_time );

View File

@ -14,9 +14,9 @@ use core::{cell::RefCell, mem::MaybeUninit};
pub(crate) use ble::{ble_deinit, ble_init, send_hci};
use critical_section::Mutex;
#[cfg(any(esp32, esp32c3, esp32s3))]
#[cfg(btdm)]
use self::btdm as ble;
#[cfg(any(esp32c2, esp32c6, esp32h2))]
#[cfg(npl)]
use self::npl as ble;
unstable_module! {
@ -29,7 +29,7 @@ pub(crate) unsafe extern "C" fn malloc(size: u32) -> *mut crate::binary::c_types
#[cfg(any(esp32, esp32c3, esp32s3))]
pub(crate) unsafe extern "C" fn malloc_internal(size: u32) -> *mut crate::binary::c_types::c_void {
unsafe { crate::compat::malloc::malloc(size as usize).cast() }
unsafe { crate::compat::malloc::malloc_internal(size as usize).cast() }
}
pub(crate) unsafe extern "C" fn free(ptr: *mut crate::binary::c_types::c_void) {

View File

@ -130,17 +130,3 @@ pub(super) unsafe extern "C" fn esp_reset_rpa_moudle() {
let mut bt = unsafe { BT::steal() };
bt.reset_rpa();
}
#[allow(improper_ctypes_definitions)]
#[unsafe(no_mangle)]
unsafe extern "C" fn jrand48(
_xsubi: [crate::binary::c_types::c_ushort; 3],
) -> crate::binary::c_types::c_long {
// this is not very random but good enough for now - it's apparently not used
// for crypto
unsafe {
static mut VALUE: u32 = 0;
VALUE = VALUE.wrapping_add(3);
VALUE as i32
}
}

View File

@ -130,17 +130,3 @@ pub(super) unsafe extern "C" fn esp_reset_rpa_moudle() {
let mut bt = unsafe { BT::steal() };
bt.reset_rpa();
}
#[allow(improper_ctypes_definitions)]
#[unsafe(no_mangle)]
unsafe extern "C" fn jrand48(
_xsubi: [crate::binary::c_types::c_ushort; 3],
) -> crate::binary::c_types::c_long {
// this is not very random but good enough for now - it's apparently not used
// for crypto
unsafe {
static mut VALUE: u32 = 0;
VALUE = VALUE.wrapping_add(3);
VALUE as i32
}
}

View File

@ -124,7 +124,7 @@ fn phy_digital_regs_store() {
/// *************************************************************************
#[ram]
#[unsafe(no_mangle)]
unsafe extern "C" fn esp_dport_access_reg_read(reg: u32) -> u32 {
unsafe extern "C" fn __esp_radio_esp_dport_access_reg_read(reg: u32) -> u32 {
unsafe {
// trace!("esp_dport_access_reg_read {:x} => {:x}", reg, res);
(reg as *mut u32).read_volatile()
@ -146,7 +146,7 @@ unsafe extern "C" fn esp_dport_access_reg_read(reg: u32) -> u32 {
/// *************************************************************************
#[ram]
#[unsafe(no_mangle)]
unsafe extern "C" fn phy_enter_critical() -> u32 {
unsafe extern "C" fn __esp_radio_phy_enter_critical() -> u32 {
trace!("phy_enter_critical");
unsafe { core::mem::transmute(critical_section::acquire()) }
@ -167,7 +167,7 @@ unsafe extern "C" fn phy_enter_critical() -> u32 {
/// *************************************************************************
#[ram]
#[unsafe(no_mangle)]
unsafe extern "C" fn phy_exit_critical(level: u32) {
unsafe extern "C" fn __esp_radio_phy_exit_critical(level: u32) {
trace!("phy_exit_critical {}", level);
unsafe {
@ -179,7 +179,7 @@ unsafe extern "C" fn phy_exit_critical(level: u32) {
#[ram]
#[unsafe(no_mangle)]
unsafe extern "C" fn rtc_get_xtal() -> u32 {
unsafe extern "C" fn __esp_radio_rtc_get_xtal() -> u32 {
use esp_hal::clock::Clock;
let xtal = crate::hal::rtc_cntl::RtcClock::xtal_freq();
@ -187,26 +187,23 @@ unsafe extern "C" fn rtc_get_xtal() -> u32 {
}
#[unsafe(no_mangle)]
unsafe extern "C" fn misc_nvs_deinit() {
unsafe extern "C" fn __esp_radio_misc_nvs_deinit() {
trace!("misc_nvs_deinit")
}
#[unsafe(no_mangle)]
unsafe extern "C" fn misc_nvs_init() -> i32 {
unsafe extern "C" fn __esp_radio_misc_nvs_init() -> i32 {
trace!("misc_nvs_init");
0
}
#[unsafe(no_mangle)]
unsafe extern "C" fn misc_nvs_restore() -> i32 {
unsafe extern "C" fn __esp_radio_misc_nvs_restore() -> i32 {
todo!("misc_nvs_restore")
}
#[unsafe(no_mangle)]
static mut g_log_mod: i32 = 0;
static mut __ESP_RADIO_G_LOG_LEVEL: i32 = 0;
#[unsafe(no_mangle)]
static mut g_log_level: i32 = 0;
#[unsafe(no_mangle)]
pub static mut g_misc_nvs: u32 = 0;
pub static mut __ESP_RADIO_G_MISC_NVS: u32 = 0;

View File

@ -142,7 +142,7 @@ fn phy_digital_regs_store() {
/// *************************************************************************
#[ram]
#[unsafe(no_mangle)]
unsafe extern "C" fn phy_enter_critical() -> u32 {
unsafe extern "C" fn __esp_radio_phy_enter_critical() -> u32 {
trace!("phy_enter_critical");
unsafe { core::mem::transmute(critical_section::acquire()) }
@ -163,7 +163,7 @@ unsafe extern "C" fn phy_enter_critical() -> u32 {
/// *************************************************************************
#[ram]
#[unsafe(no_mangle)]
unsafe extern "C" fn phy_exit_critical(level: u32) {
unsafe extern "C" fn __esp_radio_phy_exit_critical(level: u32) {
trace!("phy_exit_critical {}", level);
unsafe {
@ -174,33 +174,25 @@ unsafe extern "C" fn phy_exit_critical(level: u32) {
}
#[unsafe(no_mangle)]
unsafe extern "C" fn abort() {
unsafe extern "C" fn __esp_radio_misc_nvs_deinit() {
trace!("misc_nvs_deinit")
}
#[unsafe(no_mangle)]
unsafe extern "C" fn misc_nvs_deinit() {
trace!("misc_nvs_deinit")
}
#[unsafe(no_mangle)]
unsafe extern "C" fn misc_nvs_init() -> i32 {
unsafe extern "C" fn __esp_radio_misc_nvs_init() -> i32 {
trace!("misc_nvs_init");
0
}
#[unsafe(no_mangle)]
unsafe extern "C" fn misc_nvs_restore() -> i32 {
unsafe extern "C" fn __esp_radio_misc_nvs_restore() -> i32 {
todo!("misc_nvs_restore")
}
#[unsafe(no_mangle)]
static mut g_log_mod: i32 = 0;
static mut __ESP_RADIO_G_LOG_LEVEL: i32 = 0;
#[unsafe(no_mangle)]
static mut g_log_level: i32 = 0;
#[unsafe(no_mangle)]
pub static mut g_misc_nvs: &u32 = unsafe { &*core::ptr::addr_of!(NVS) };
pub static mut __ESP_RADIO_G_MISC_NVS: &u32 = unsafe { &*core::ptr::addr_of!(NVS) };
pub static mut NVS: u32 = 0;

View File

@ -143,31 +143,23 @@ fn phy_digital_regs_store() {
}
#[unsafe(no_mangle)]
unsafe extern "C" fn abort() {
unsafe extern "C" fn __esp_radio_misc_nvs_deinit() {
trace!("misc_nvs_deinit")
}
#[unsafe(no_mangle)]
unsafe extern "C" fn misc_nvs_deinit() {
trace!("misc_nvs_deinit")
}
#[unsafe(no_mangle)]
unsafe extern "C" fn misc_nvs_init() -> i32 {
unsafe extern "C" fn __esp_radio_misc_nvs_init() -> i32 {
trace!("misc_nvs_init");
0
}
#[unsafe(no_mangle)]
unsafe extern "C" fn misc_nvs_restore() -> i32 {
unsafe extern "C" fn __esp_radio_misc_nvs_restore() -> i32 {
todo!("misc_nvs_restore")
}
#[unsafe(no_mangle)]
static mut g_log_mod: i32 = 0;
static mut __ESP_RADIO_G_LOG_LEVEL: i32 = 0;
#[unsafe(no_mangle)]
static mut g_log_level: i32 = 0;
#[unsafe(no_mangle)]
pub static mut g_misc_nvs: u32 = 0;
pub static mut __ESP_RADIO_G_MISC_NVS: u32 = 0;

View File

@ -12,7 +12,7 @@ use portable_atomic::{AtomicU32, Ordering};
use crate::{
binary::include::{esp_event_base_t, esp_timer_get_time},
compat::{common::*, timer_compat::*},
compat::common::*,
hal::{self, clock::ModemClockController, ram},
};
@ -118,7 +118,6 @@ pub unsafe extern "C" fn semphr_give(semphr: *mut crate::binary::c_types::c_void
/// *************************************************************************
#[allow(unused)]
#[ram]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn random() -> crate::binary::c_types::c_ulong {
trace!("random");
@ -218,26 +217,26 @@ pub unsafe extern "C" fn puts(s: *const c_char) {
// #define ESP_EVENT_DEFINE_BASE(id) esp_event_base_t id = #id
#[unsafe(no_mangle)]
static mut WIFI_EVENT: esp_event_base_t = c"WIFI_EVENT".as_ptr();
static mut __ESP_RADIO_WIFI_EVENT: esp_event_base_t = c"WIFI_EVENT".as_ptr();
#[unsafe(no_mangle)]
#[cfg(feature = "wifi")]
pub unsafe extern "C" fn ets_timer_disarm(timer: *mut crate::binary::c_types::c_void) {
compat_timer_disarm(timer.cast());
crate::compat::timer_compat::compat_timer_disarm(timer.cast());
}
#[unsafe(no_mangle)]
#[cfg(feature = "wifi")]
pub unsafe extern "C" fn ets_timer_done(timer: *mut crate::binary::c_types::c_void) {
compat_timer_done(timer.cast());
crate::compat::timer_compat::compat_timer_done(timer.cast());
}
#[unsafe(no_mangle)]
#[cfg(feature = "wifi")]
pub unsafe extern "C" fn ets_timer_setfn(
ptimer: *mut crate::binary::c_types::c_void,
pfunction: *mut crate::binary::c_types::c_void,
parg: *mut crate::binary::c_types::c_void,
) {
unsafe {
compat_timer_setfn(
crate::compat::timer_compat::compat_timer_setfn(
ptimer.cast(),
core::mem::transmute::<
*mut crate::binary::c_types::c_void,
@ -248,26 +247,26 @@ pub unsafe extern "C" fn ets_timer_setfn(
}
}
#[unsafe(no_mangle)]
#[cfg(feature = "wifi")]
pub unsafe extern "C" fn ets_timer_arm(
timer: *mut crate::binary::c_types::c_void,
tmout: u32,
repeat: bool,
) {
compat_timer_arm(timer.cast(), tmout, repeat);
crate::compat::timer_compat::compat_timer_arm(timer.cast(), tmout, repeat);
}
#[unsafe(no_mangle)]
#[cfg(feature = "wifi")]
pub unsafe extern "C" fn ets_timer_arm_us(
timer: *mut crate::binary::c_types::c_void,
tmout: u32,
repeat: bool,
) {
compat_timer_arm_us(timer.cast(), tmout, repeat);
crate::compat::timer_compat::compat_timer_arm_us(timer.cast(), tmout, repeat);
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn gettimeofday(tv: *mut timeval, _tz: *mut ()) -> i32 {
pub unsafe extern "C" fn __esp_radio_gettimeofday(tv: *mut timeval, _tz: *mut ()) -> i32 {
if !tv.is_null() {
unsafe {
let microseconds = esp_timer_get_time();
@ -279,8 +278,24 @@ pub unsafe extern "C" fn gettimeofday(tv: *mut timeval, _tz: *mut ()) -> i32 {
0
}
/// **************************************************************************
/// Name: esp_timer_get_time
///
/// Description:
/// Get time in microseconds since boot.
///
/// Returned Value:
/// System time in micros
///
/// *************************************************************************
#[unsafe(no_mangle)]
pub unsafe extern "C" fn esp_fill_random(dst: *mut u8, len: u32) {
pub unsafe extern "C" fn __esp_radio_esp_timer_get_time() -> i64 {
trace!("esp_timer_get_time");
crate::time::ticks_to_micros(crate::time::systimer_count()) as i64
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn __esp_radio_esp_fill_random(dst: *mut u8, len: u32) {
trace!("esp_fill_random");
unsafe {
let dst = core::slice::from_raw_parts_mut(dst, len as usize);
@ -294,7 +309,7 @@ pub unsafe extern "C" fn esp_fill_random(dst: *mut u8, len: u32) {
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strrchr(_s: *const (), _c: u32) -> *const u8 {
pub unsafe extern "C" fn __esp_radio_strrchr(_s: *const (), _c: u32) -> *const u8 {
todo!("strrchr");
}

View File

@ -1,5 +1,6 @@
#![allow(unused)]
use alloc::{boxed::Box, vec::Vec};
use core::{
cell::RefCell,
fmt::Write,
@ -7,7 +8,6 @@ use core::{
ptr::{self, addr_of, addr_of_mut},
};
use allocator_api2::{boxed::Box, vec::Vec};
use esp_hal::time::{Duration, Instant};
use esp_wifi_sys::{c_types::c_char, include::malloc};
@ -15,7 +15,6 @@ use super::malloc::free;
use crate::{
CONFIG,
binary::c_types::{c_int, c_void},
compat::malloc::InternalMemory,
hal::sync::Locked,
memory_fence::memory_fence,
preempt::{current_task, yield_task},
@ -67,14 +66,19 @@ pub struct RawQueue {
capacity: usize,
current_read: usize,
current_write: usize,
storage: Box<[u8], InternalMemory>,
storage: Box<[u8]>,
}
impl RawQueue {
/// This allocates underlying storage. See [release_storage]
pub fn new(capacity: usize, item_size: usize) -> Self {
let storage =
unsafe { Box::new_zeroed_slice_in(capacity * item_size, InternalMemory).assume_init() };
let storage = unsafe {
let mut boxed = Box::new_uninit_slice(capacity * item_size);
for i in 0..capacity * item_size {
boxed[i].write(0);
}
boxed.assume_init()
};
Self {
item_size,
@ -143,7 +147,7 @@ impl RawQueue {
return;
}
let mut tmp_item = Vec::<u8, _>::new_in(InternalMemory);
let mut tmp_item = Vec::<u8>::new();
tmp_item.reserve_exact(self.item_size);
tmp_item.resize(self.item_size, 0);
@ -173,21 +177,6 @@ pub unsafe fn str_from_c<'a>(s: *const c_char) -> &'a str {
}
}
#[unsafe(no_mangle)]
unsafe extern "C" fn strnlen(chars: *const c_char, maxlen: usize) -> usize {
let mut len = 0;
loop {
unsafe {
if chars.offset(len).read_volatile() == 0 {
break;
}
len += 1;
}
}
len as usize
}
pub(crate) fn sem_create(max: u32, init: u32) -> *mut c_void {
unsafe {
let ptr = malloc(4) as *mut u32;
@ -432,9 +421,3 @@ unsafe extern "C" fn usleep(us: u32) -> c_int {
esp_radio_preempt_driver::usleep(us);
0
}
#[unsafe(no_mangle)]
unsafe extern "C" fn putchar(c: i32) -> c_int {
trace!("putchar {}", c as u8 as char);
c
}

View File

@ -1,151 +1,25 @@
#[unsafe(no_mangle)]
pub unsafe extern "C" fn malloc(size: usize) -> *mut u8 {
trace!("alloc {}", size);
//! These symbols are expected to be present.
//!
//! `esp-alloc` will provide them. The user is expected to provide implementation if
//! they don't want to use `esp-alloc`
unsafe extern "C" {
fn esp_radio_allocate_from_internal_ram(size: usize) -> *mut u8;
}
unsafe extern "C" {
pub fn malloc(size: usize) -> *mut u8;
let ptr = unsafe { esp_radio_allocate_from_internal_ram(size) };
#[cfg(any(feature = "wifi", not(npl)))]
pub fn malloc_internal(size: usize) -> *mut u8;
if ptr.is_null() {
warn!("Unable to allocate {} bytes", size);
}
pub fn free(ptr: *mut u8);
ptr
#[cfg(feature = "wifi")]
pub fn realloc_internal(ptr: *mut u8, size: usize) -> *mut u8;
#[cfg(any(feature = "wifi", all(feature = "ble", npl)))]
pub fn calloc(number: u32, size: usize) -> *mut u8;
#[cfg(feature = "wifi")]
pub fn calloc_internal(number: u32, size: usize) -> *mut u8;
#[cfg(feature = "wifi")]
pub fn get_free_internal_heap_size() -> usize;
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn free(ptr: *mut u8) {
trace!("free {:?}", ptr);
if ptr.is_null() {
warn!("Attempt to free null pointer");
return;
}
unsafe extern "C" {
fn esp_radio_deallocate_internal_ram(ptr: *mut u8);
}
unsafe {
esp_radio_deallocate_internal_ram(ptr);
}
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn calloc(number: u32, size: usize) -> *mut u8 {
trace!("calloc {} {}", number, size);
let total_size = number as usize * size;
unsafe {
let ptr = malloc(total_size);
if !ptr.is_null() {
for i in 0..total_size as isize {
ptr.offset(i).write_volatile(0);
}
}
ptr
}
}
#[unsafe(no_mangle)]
unsafe extern "C" fn realloc(ptr: *mut u8, new_size: usize) -> *mut u8 {
trace!("realloc {:?} {}", ptr, new_size);
unsafe extern "C" {
fn memcpy(d: *mut u8, s: *const u8, l: usize);
}
unsafe {
let p = malloc(new_size);
if !p.is_null() && !ptr.is_null() {
let len = usize::min(
(ptr as *const u32).sub(1).read_volatile() as usize,
new_size,
);
memcpy(p, ptr, len);
free(ptr);
}
p
}
}
#[cfg(feature = "esp-alloc")]
#[doc(hidden)]
#[unsafe(no_mangle)]
pub extern "C" fn esp_radio_free_internal_heap() -> usize {
esp_alloc::HEAP.free_caps(esp_alloc::MemoryCapability::Internal.into())
}
#[cfg(feature = "esp-alloc")]
#[doc(hidden)]
#[unsafe(no_mangle)]
pub extern "C" fn esp_radio_allocate_from_internal_ram(size: usize) -> *mut u8 {
let total_size = size + 4;
unsafe {
let ptr = esp_alloc::HEAP.alloc_caps(
esp_alloc::MemoryCapability::Internal.into(),
core::alloc::Layout::from_size_align_unchecked(total_size, 4),
);
if ptr.is_null() {
return ptr;
}
*(ptr as *mut usize) = total_size;
ptr.offset(4)
}
}
#[cfg(feature = "esp-alloc")]
#[doc(hidden)]
#[unsafe(no_mangle)]
pub extern "C" fn esp_radio_deallocate_internal_ram(ptr: *mut u8) {
use core::alloc::GlobalAlloc;
unsafe {
let ptr = ptr.offset(-4);
let total_size = *(ptr as *const usize);
esp_alloc::HEAP.dealloc(
ptr,
core::alloc::Layout::from_size_align_unchecked(total_size, 4),
)
}
}
// Polyfill the InternalMemory allocator
#[cfg(not(feature = "esp-alloc"))]
mod esp_alloc {
use core::{alloc::Layout, ptr::NonNull};
use allocator_api2::alloc::{AllocError, Allocator};
/// An allocator that uses internal memory only.
pub struct InternalMemory;
unsafe impl Allocator for InternalMemory {
fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
unsafe extern "C" {
fn esp_radio_allocate_from_internal_ram(size: usize) -> *mut u8;
}
let raw_ptr = unsafe { esp_radio_allocate_from_internal_ram(layout.size()) };
let ptr = NonNull::new(raw_ptr).ok_or(AllocError)?;
Ok(NonNull::slice_from_raw_parts(ptr, layout.size()))
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, _layout: Layout) {
unsafe extern "C" {
fn esp_radio_deallocate_internal_ram(ptr: *mut u8);
}
unsafe {
esp_radio_deallocate_internal_ram(ptr.as_ptr());
}
}
}
}
pub(crate) use esp_alloc::InternalMemory;

View File

@ -2,28 +2,33 @@ use crate::compat::malloc::malloc;
// these are not called but needed for linking
#[unsafe(no_mangle)]
unsafe extern "C" fn fwrite(ptr: *const (), size: usize, count: usize, stream: *const ()) -> usize {
unsafe extern "C" fn __esp_radio_fwrite(
ptr: *const (),
size: usize,
count: usize,
stream: *const (),
) -> usize {
todo!("fwrite {:?} {} {} {:?}", ptr, size, count, stream)
}
#[unsafe(no_mangle)]
unsafe extern "C" fn fopen(filename: *const u8, mode: *const u8) -> *const () {
unsafe extern "C" fn __esp_radio_fopen(filename: *const u8, mode: *const u8) -> *const () {
todo!("fopen {:?} {:?}", filename, mode)
}
#[unsafe(no_mangle)]
unsafe extern "C" fn fgets(str: *const u8, count: u32, file: *const ()) -> *const u8 {
unsafe extern "C" fn __esp_radio_fgets(str: *const u8, count: u32, file: *const ()) -> *const u8 {
todo!("fgets {:?} {} {:?}", str, count, file)
}
#[unsafe(no_mangle)]
unsafe extern "C" fn fclose(stream: *const ()) -> i32 {
unsafe extern "C" fn __esp_radio_fclose(stream: *const ()) -> i32 {
todo!("fclose {:?}", stream);
}
// We cannot just use the ROM function since it needs to allocate memory
#[unsafe(no_mangle)]
unsafe extern "C" fn strdup(str: *const core::ffi::c_char) -> *const core::ffi::c_char {
unsafe extern "C" fn __esp_radio_strdup(str: *const core::ffi::c_char) -> *const core::ffi::c_char {
trace!("strdup {:?}", str);
unsafe {
@ -36,122 +41,3 @@ unsafe extern "C" fn strdup(str: *const core::ffi::c_char) -> *const core::ffi::
p.cast()
}
}
// We cannot just use the ROM function since it calls `__getreent`
//
// From docs: The __getreent() function returns a per-task pointer to struct
// _reent in newlib libc. This structure is allocated on the TCB of each task.
// i.e. it assumes a FreeRTOS task calling it.
#[unsafe(no_mangle)]
unsafe extern "C" fn atoi(str: *const i8) -> i32 {
trace!("atoi {:?}", str);
let mut sign: i32 = 1;
let mut res: i32 = 0;
let mut idx = 0;
// skip leading spaces
while unsafe { str.add(idx).read() } as u8 == b' ' {
idx += 1;
}
// check sign
let c = unsafe { str.add(idx).read() } as u8;
if c == b'-' || c == b'+' {
if c == b'-' {
sign = -1;
}
idx += 1;
}
// parse number digit by digit
loop {
let c = unsafe { str.add(idx).read() } as u8;
if !c.is_ascii_digit() {
break;
}
// if the result would exceed the bounds - return max-value
if res > i32::MAX / 10 || (res == i32::MAX / 10 && c - b'0' > 7) {
return if sign == 1 { i32::MAX } else { i32::MIN };
}
res = 10 * res + (c - b'0') as i32;
idx += 1;
}
res * sign
}
// We cannot just use the ROM function since it calls `__getreent`
//
// From docs: The __getreent() function returns a per-task pointer to struct
// _reent in newlib libc. This structure is allocated on the TCB of each task.
// i.e. it assumes a FreeRTOS task calling it.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strcasecmp(
s1: *const core::ffi::c_char,
s2: *const core::ffi::c_char,
) -> i32 {
let mut i = 0;
loop {
unsafe {
let s1_i = s1.add(i);
let s2_i = s2.add(i);
let val = (*s1_i).to_ascii_lowercase() as i32 - (*s2_i).to_ascii_lowercase() as i32;
if val != 0 || *s1_i == 0 {
return val;
}
}
i += 1;
}
}
#[derive(Debug, Copy, Clone)]
#[repr(C)]
struct Tm {
tm_sec: u32, // seconds after the minute - [0, 60] including leap second
tm_min: u32, // minutes after the hour - [0, 59]
tm_hour: u32, // hours since midnight - [0, 23]
tm_mday: u32, // day of the month - [1, 31]
tm_mon: u32, // months since January - [0, 11]
tm_year: u32, // years since 1900
tm_wday: u32, // days since Sunday - [0, 6]
tm_yday: u32, // days since January 1 - [0, 365]
tm_isdst: u32, // daylight savings time flag
}
#[unsafe(no_mangle)]
unsafe extern "C" fn mktime(time: *const Tm) -> i64 {
trace!("mktime {:?}", time);
let time = unsafe { *time };
// Simplified implementation, ignoring time zones, leap seconds, and other
// complexities
let mut days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
let is_leap_year = |year: u32| {
year.is_multiple_of(4) && (!year.is_multiple_of(100) || year.is_multiple_of(400))
};
let mut days = 0;
let year = time.tm_year + 1900;
for y in 1970..year {
days += if is_leap_year(y) { 366 } else { 365 };
}
if is_leap_year(year) {
days_in_month[1] = 29;
}
for m in 0..time.tm_mon {
days += days_in_month[m as usize];
}
days += time.tm_mday - 1;
let seconds = days * 24 * 60 * 60 + time.tm_hour * 60 * 60 + time.tm_min * 60 + time.tm_sec;
seconds as i64
}

View File

@ -4,24 +4,27 @@ pub mod misc;
pub mod timer_compat;
#[unsafe(no_mangle)]
unsafe extern "C" fn _putchar(c: u8) {
static mut BUFFER: [u8; 256] = [0u8; 256];
static mut IDX: usize = 0;
unsafe extern "C" fn __esp_radio_putchar(_c: u8) {
#[cfg(feature = "sys-logs")]
{
static mut BUFFER: [u8; 256] = [0u8; 256];
static mut IDX: usize = 0;
unsafe {
let buffer = core::ptr::addr_of_mut!(BUFFER);
if c == 0 || c == b'\n' || IDX == (*buffer).len() - 1 {
if c != 0 {
BUFFER[IDX] = c;
unsafe {
let buffer = core::ptr::addr_of_mut!(BUFFER);
if _c == 0 || _c == b'\n' || IDX == (*buffer).len() - 1 {
if _c != 0 {
BUFFER[IDX] = _c;
} else {
IDX = IDX.saturating_sub(1);
}
info!("{}", core::str::from_utf8_unchecked(&BUFFER[..IDX]));
IDX = 0;
} else {
IDX = IDX.saturating_sub(1);
BUFFER[IDX] = _c;
IDX += 1;
}
info!("{}", core::str::from_utf8_unchecked(&BUFFER[..IDX]));
IDX = 0;
} else {
BUFFER[IDX] = c;
IDX += 1;
}
}
}

View File

@ -42,6 +42,7 @@ pub(crate) struct Timer {
next: Option<Box<Timer>>,
}
#[cfg(any(feature = "wifi", all(feature = "ble", npl)))]
impl Timer {
pub(crate) fn id(&self) -> usize {
self.ets_timer as usize
@ -57,18 +58,6 @@ impl TimerQueue {
Self { head: None }
}
fn find(&mut self, ets_timer: *mut ets_timer) -> Option<&mut Box<Timer>> {
let mut current = self.head.as_mut();
while let Some(timer) = current {
if core::ptr::eq(timer.ets_timer, ets_timer) {
return Some(timer);
}
current = timer.next.as_mut();
}
None
}
pub(crate) unsafe fn find_next_due(
&mut self,
current_timestamp: u64,
@ -85,7 +74,23 @@ impl TimerQueue {
None
}
}
#[cfg(any(feature = "wifi", all(feature = "ble", npl)))]
impl TimerQueue {
fn find(&mut self, ets_timer: *mut ets_timer) -> Option<&mut Box<Timer>> {
let mut current = self.head.as_mut();
while let Some(timer) = current {
if core::ptr::eq(timer.ets_timer, ets_timer) {
return Some(timer);
}
current = timer.next.as_mut();
}
None
}
#[cfg(feature = "wifi")]
fn remove(&mut self, ets_timer: *mut ets_timer) {
if let Some(head) = self.head.as_mut()
&& core::ptr::eq(head.ets_timer, ets_timer)
@ -144,10 +149,12 @@ unsafe impl Send for TimerQueue {}
pub(crate) static TIMERS: Locked<TimerQueue> = Locked::new(TimerQueue::new());
#[cfg(any(feature = "wifi", all(feature = "ble", npl)))]
pub(crate) fn compat_timer_arm(ets_timer: *mut ets_timer, tmout: u32, repeat: bool) {
compat_timer_arm_us(ets_timer, tmout * 1000, repeat);
}
#[cfg(any(feature = "wifi", all(feature = "ble", npl)))]
pub(crate) fn compat_timer_arm_us(ets_timer: *mut ets_timer, us: u32, repeat: bool) {
let systick = crate::time::systimer_count();
let ticks = crate::time::micros_to_ticks(us as u64);
@ -169,6 +176,7 @@ pub(crate) fn compat_timer_arm_us(ets_timer: *mut ets_timer, us: u32, repeat: bo
})
}
#[cfg(any(feature = "wifi", all(feature = "ble", npl)))]
pub fn compat_timer_disarm(ets_timer: *mut ets_timer) {
trace!("timer disarm");
TIMERS.with(|timers| {
@ -181,6 +189,7 @@ pub fn compat_timer_disarm(ets_timer: *mut ets_timer) {
})
}
#[cfg(feature = "wifi")]
pub fn compat_timer_done(ets_timer: *mut ets_timer) {
trace!("timer done");
TIMERS.with(|timers| {
@ -200,6 +209,7 @@ pub fn compat_timer_done(ets_timer: *mut ets_timer) {
})
}
#[cfg(any(feature = "wifi", all(feature = "ble", npl)))]
pub(crate) fn compat_timer_setfn(
ets_timer: *mut ets_timer,
pfunction: unsafe extern "C" fn(*mut c_types::c_void),

View File

@ -1,4 +1,5 @@
use heapless::Vec;
use alloc::vec::Vec;
use ieee802154::mac::{FrameContent, Header};
pub(crate) const FRAME_SIZE: usize = 129;
@ -18,7 +19,7 @@ pub struct Frame {
/// Content
pub content: FrameContent,
/// Payload
pub payload: Vec<u8, FRAME_SIZE>,
pub payload: Vec<u8>,
/// This is a 2-byte CRC checksum
pub footer: [u8; 2],
}

View File

@ -15,13 +15,13 @@
//! [IEEE 802.15.4]: https://en.wikipedia.org/wiki/IEEE_802.15.4
//! [esp-openthread]: https://github.com/esp-rs/esp-openthread
use alloc::vec::Vec;
use core::cell::RefCell;
use byte::{BytesExt, TryRead};
use critical_section::Mutex;
use esp_config::*;
use esp_hal::{clock::PhyClockGuard, peripherals::IEEE802154};
use heapless::Vec;
use ieee802154::mac::{self, FooterMode, FrameSerDesContext};
use self::{
@ -188,7 +188,7 @@ impl<'a> Ieee802154<'a> {
frame: Frame {
header: decoded.header,
content: decoded.content,
payload: Vec::from_slice(decoded.payload).unwrap(),
payload: decoded.payload.to_vec(),
footer: decoded.footer,
},
channel: raw.channel,

View File

@ -1,3 +1,4 @@
use alloc::collections::VecDeque as Queue;
use core::cell::RefCell;
use critical_section::Mutex;
@ -16,7 +17,6 @@ use esp_wifi_sys::include::{
ieee802154_coex_event_t_IEEE802154_MIDDLE,
register_chipv7_phy,
};
use heapless::spsc::Queue;
use super::{
frame::{
@ -33,8 +33,7 @@ use super::{
const PHY_ENABLE_VERSION_PRINT: u32 = 1;
static mut RX_BUFFER: [u8; FRAME_SIZE] = [0u8; FRAME_SIZE];
static RX_QUEUE: Mutex<RefCell<Queue<RawReceived, { crate::CONFIG.rx_queue_size }>>> =
Mutex::new(RefCell::new(Queue::new()));
static RX_QUEUE: Mutex<RefCell<Queue<RawReceived>>> = Mutex::new(RefCell::new(Queue::new()));
static STATE: Mutex<RefCell<Ieee802154State>> = Mutex::new(RefCell::new(Ieee802154State::Idle));
unsafe extern "C" {
@ -234,7 +233,7 @@ pub fn ieee802154_receive() -> i32 {
pub fn ieee802154_poll() -> Option<RawReceived> {
critical_section::with(|cs| {
let mut queue = RX_QUEUE.borrow_ref_mut(cs);
queue.dequeue()
queue.pop_front()
})
}
@ -391,12 +390,12 @@ fn ZB_MAC() {
);
critical_section::with(|cs| {
let mut queue = RX_QUEUE.borrow_ref_mut(cs);
if !queue.is_full() {
if queue.len() <= crate::CONFIG.rx_queue_size {
let item = RawReceived {
data: RX_BUFFER,
channel: freq_to_channel(freq()),
};
queue.enqueue(item).ok();
queue.push_back(item);
} else {
warn!("Receive queue full");
}

View File

@ -24,7 +24,7 @@ pub(super) static mut G_COEX_ADAPTER_FUNCS: crate::binary::include::coex_adapter
_is_in_isr: Some(is_in_isr_wrapper),
_malloc_internal: Some(malloc),
_free: Some(free),
_esp_timer_get_time: Some(esp_timer_get_time),
_esp_timer_get_time: Some(__esp_radio_esp_timer_get_time),
_env_is_chip: Some(env_is_chip),
_magic: crate::binary::include::COEX_ADAPTER_MAGIC as i32,
_timer_disarm: Some(ets_timer_disarm),
@ -67,7 +67,7 @@ unsafe extern "C" fn is_in_isr_wrapper() -> i32 {
}
#[unsafe(no_mangle)]
static g_wifi_osi_funcs: wifi_osi_funcs_t = wifi_osi_funcs_t {
static __ESP_RADIO_G_WIFI_OSI_FUNCS: wifi_osi_funcs_t = wifi_osi_funcs_t {
_version: ESP_WIFI_OS_ADAPTER_VERSION as i32,
_env_is_chip: Some(env_is_chip),
_set_intr: Some(set_intr),
@ -134,7 +134,7 @@ static g_wifi_osi_funcs: wifi_osi_funcs_t = wifi_osi_funcs_t {
_wifi_clock_disable: Some(wifi_clock_disable),
_wifi_rtc_enable_iso: Some(wifi_rtc_enable_iso),
_wifi_rtc_disable_iso: Some(wifi_rtc_disable_iso),
_esp_timer_get_time: Some(esp_timer_get_time),
_esp_timer_get_time: Some(__esp_radio_esp_timer_get_time),
_nvs_set_i8: Some(nvs_set_i8),
_nvs_get_i8: Some(nvs_get_i8),
_nvs_set_u8: Some(nvs_set_u8),
@ -161,7 +161,7 @@ static g_wifi_osi_funcs: wifi_osi_funcs_t = wifi_osi_funcs_t {
_log_timestamp: Some(log_timestamp),
_malloc_internal: Some(malloc_internal),
_realloc_internal: Some(realloc_internal),
_calloc_internal: Some(calloc_internal),
_calloc_internal: Some(calloc_internal_wrapper),
_zalloc_internal: Some(zalloc_internal),
_wifi_malloc: Some(wifi_malloc),
_wifi_realloc: Some(wifi_realloc),
@ -222,10 +222,10 @@ const WIFI_ENABLE_ENTERPRISE: u64 = 1 << 7;
const WIFI_FEATURE_CAPS: u64 = WIFI_ENABLE_WPA3_SAE | WIFI_ENABLE_ENTERPRISE;
#[unsafe(no_mangle)]
pub(super) static mut g_wifi_feature_caps: u64 = WIFI_FEATURE_CAPS;
pub(super) static mut __ESP_RADIO_G_WIFI_FEATURE_CAPS: u64 = WIFI_FEATURE_CAPS;
pub(super) static mut G_CONFIG: wifi_init_config_t = wifi_init_config_t {
osi_funcs: core::ptr::addr_of!(g_wifi_osi_funcs).cast_mut(),
osi_funcs: core::ptr::addr_of!(__ESP_RADIO_G_WIFI_OSI_FUNCS).cast_mut(),
// dummy for now - populated in init
wpa_crypto_funcs: wpa_crypto_funcs_t {

View File

@ -1377,7 +1377,7 @@ pub fn ap_mac(mac: &mut [u8; 6]) {
pub(crate) fn wifi_init() -> Result<(), WifiError> {
unsafe {
internal::G_CONFIG.wpa_crypto_funcs = g_wifi_default_wpa_crypto_funcs;
internal::G_CONFIG.feature_caps = internal::g_wifi_feature_caps;
internal::G_CONFIG.feature_caps = internal::__ESP_RADIO_G_WIFI_FEATURE_CAPS;
#[cfg(coex)]
esp_wifi_result!(coex_init())?;
@ -1403,7 +1403,7 @@ pub(crate) fn wifi_init() -> Result<(), WifiError> {
#[cfg(any(esp32, esp32s3))]
{
static mut NVS_STRUCT: [u32; 12] = [0; 12];
chip_specific::g_misc_nvs = addr_of!(NVS_STRUCT) as u32;
chip_specific::__ESP_RADIO_G_MISC_NVS = addr_of!(NVS_STRUCT) as u32;
}
Ok(())

View File

@ -27,7 +27,7 @@ use crate::{
thread_sem_get,
unlock_mutex,
},
malloc::calloc,
malloc::calloc_internal,
},
hal::{
clock::ModemClockController,
@ -910,11 +910,7 @@ pub unsafe extern "C" fn event_post(
///
/// *************************************************************************
pub unsafe extern "C" fn get_free_heap_size() -> u32 {
unsafe extern "C" {
fn esp_radio_free_internal_heap() -> usize;
}
unsafe { esp_radio_free_internal_heap() as u32 }
unsafe { crate::compat::malloc::get_free_internal_heap_size() as u32 }
}
/// **************************************************************************
@ -1119,22 +1115,6 @@ pub unsafe extern "C" fn wifi_rtc_disable_iso() {
todo!("wifi_rtc_disable_iso")
}
/// **************************************************************************
/// Name: esp_timer_get_time
///
/// Description:
/// Get time in microseconds since boot.
///
/// Returned Value:
/// System time in micros
///
/// *************************************************************************
#[unsafe(no_mangle)]
pub unsafe extern "C" fn esp_timer_get_time() -> i64 {
trace!("esp_timer_get_time");
crate::time::ticks_to_micros(crate::time::systimer_count()) as i64
}
/// **************************************************************************
/// Name: esp_nvs_set_i8
///
@ -1413,7 +1393,7 @@ pub unsafe extern "C" fn nvs_erase_key(
pub unsafe extern "C" fn get_random(buf: *mut u8, len: usize) -> crate::binary::c_types::c_int {
trace!("get_random");
unsafe {
crate::common_adapter::esp_fill_random(buf, len as u32);
crate::common_adapter::__esp_radio_esp_fill_random(buf, len as u32);
}
0
}
@ -1530,7 +1510,7 @@ pub unsafe extern "C" fn log_timestamp() -> u32 {
///
/// *************************************************************************
pub unsafe extern "C" fn malloc_internal(size: usize) -> *mut crate::binary::c_types::c_void {
unsafe { crate::compat::malloc::malloc(size).cast() }
unsafe { crate::compat::malloc::malloc_internal(size).cast() }
}
/// **************************************************************************
@ -1548,10 +1528,10 @@ pub unsafe extern "C" fn malloc_internal(size: usize) -> *mut crate::binary::c_t
///
/// *************************************************************************
pub unsafe extern "C" fn realloc_internal(
_ptr: *mut crate::binary::c_types::c_void,
_size: usize,
ptr: *mut crate::binary::c_types::c_void,
size: usize,
) -> *mut crate::binary::c_types::c_void {
todo!("realloc_internal")
unsafe { crate::compat::malloc::realloc_internal(ptr.cast(), size).cast() }
}
/// **************************************************************************
@ -1568,11 +1548,11 @@ pub unsafe extern "C" fn realloc_internal(
/// New memory pointer
///
/// *************************************************************************
pub unsafe extern "C" fn calloc_internal(
pub unsafe extern "C" fn calloc_internal_wrapper(
n: usize,
size: usize,
) -> *mut crate::binary::c_types::c_void {
unsafe { calloc(n as u32, size) as *mut crate::binary::c_types::c_void }
unsafe { calloc_internal(n as u32, size) as *mut crate::binary::c_types::c_void }
}
/// **************************************************************************
@ -1589,7 +1569,7 @@ pub unsafe extern "C" fn calloc_internal(
///
/// *************************************************************************
pub unsafe extern "C" fn zalloc_internal(size: usize) -> *mut crate::binary::c_types::c_void {
unsafe { calloc(size as u32, 1usize) as *mut crate::binary::c_types::c_void }
unsafe { calloc_internal(size as u32, 1usize) as *mut crate::binary::c_types::c_void }
}
/// **************************************************************************
@ -1606,7 +1586,7 @@ pub unsafe extern "C" fn zalloc_internal(size: usize) -> *mut crate::binary::c_t
///
/// *************************************************************************
pub unsafe extern "C" fn wifi_malloc(size: usize) -> *mut crate::binary::c_types::c_void {
unsafe { malloc(size) }
unsafe { malloc_internal(size) }
}
/// **************************************************************************
@ -1624,10 +1604,10 @@ pub unsafe extern "C" fn wifi_malloc(size: usize) -> *mut crate::binary::c_types
///
/// *************************************************************************
pub unsafe extern "C" fn wifi_realloc(
_ptr: *mut crate::binary::c_types::c_void,
_size: usize,
ptr: *mut crate::binary::c_types::c_void,
size: usize,
) -> *mut crate::binary::c_types::c_void {
todo!("wifi_realloc")
unsafe { realloc_internal(ptr, size) }
}
/// **************************************************************************
@ -1646,7 +1626,7 @@ pub unsafe extern "C" fn wifi_realloc(
/// *************************************************************************
pub unsafe extern "C" fn wifi_calloc(n: usize, size: usize) -> *mut crate::binary::c_types::c_void {
trace!("wifi_calloc {} {}", n, size);
unsafe { calloc(n as u32, size) as *mut crate::binary::c_types::c_void }
unsafe { calloc_internal(n as u32, size) as *mut crate::binary::c_types::c_void }
}
/// **************************************************************************

View File

@ -2,7 +2,7 @@
name = "esp-rom-sys"
version = "0.1.1"
edition = "2024"
rust-version = "1.86.0"
rust-version = "1.87.0"
description = "ROM code support"
documentation = "https://docs.espressif.com/projects/rust/esp-rom-sys/latest/"
keywords = ["embedded", "esp32", "espressif"]

View File

@ -18,3 +18,11 @@ PROVIDE ( strstr = 0x4000c674 );
PROVIDE ( strcasecmp = 0x400011cc );
PROVIDE ( memchr = 0x4000c244 );
EXTERN(__mktime);
EXTERN(__strnlen);
EXTERN(__atoi);
PROVIDE ( strnlen = __strnlen );
PROVIDE ( atoi = __atoi );
PROVIDE ( mktime = __mktime );

View File

@ -13,3 +13,11 @@ PROVIDE ( strchr = 0x40000514 );
PROVIDE ( strlcpy = 0x40000524 );
PROVIDE ( strstr = 0x400004ac );
PROVIDE ( strcasecmp = 0x40000504 );
EXTERN(__mktime);
EXTERN(__strnlen);
EXTERN(__atoi);
PROVIDE ( strnlen = __strnlen );
PROVIDE ( atoi = __atoi );
PROVIDE ( mktime = __mktime );

View File

@ -19,3 +19,11 @@ PROVIDE( strstr = 0x40000378 );
PROVIDE( strcasecmp = 0x400003d0 );
PROVIDE( memchr = 0x400003c8 );
EXTERN(__mktime);
EXTERN(__strnlen);
EXTERN(__atoi);
PROVIDE ( strnlen = __strnlen );
PROVIDE ( atoi = __atoi );
PROVIDE ( mktime = __mktime );

View File

@ -15,3 +15,11 @@ PROVIDE(strchr = 0x40000534);
PROVIDE(strlcpy = 0x40000544);
PROVIDE(strstr = 0x400004cc);
PROVIDE(strcasecmp = 0x40000524);
EXTERN(__mktime);
EXTERN(__strnlen);
EXTERN(__atoi);
PROVIDE ( strnlen = __strnlen );
PROVIDE ( atoi = __atoi );
PROVIDE ( mktime = __mktime );

View File

@ -17,3 +17,11 @@ PROVIDE( strstr = 0x400004c4 );
PROVIDE( strcasecmp = 0x4000051c );
PROVIDE( memchr = 0x40000514 );
EXTERN(__mktime);
EXTERN(__strnlen);
EXTERN(__atoi);
PROVIDE ( strnlen = __strnlen );
PROVIDE ( atoi = __atoi );
PROVIDE ( mktime = __mktime );

View File

@ -16,4 +16,13 @@ PROVIDE ( strcmp = 0x40007be4 );
PROVIDE ( strchr = 0x4001adb0 );
PROVIDE ( strlcpy = 0x4001adf8 );
PROVIDE ( strstr = 0x4001aee8 );
PROVIDE ( strcasecmp = 0x40007b38 );
EXTERN(__strcasecmp);
EXTERN(__mktime);
EXTERN(__strnlen);
EXTERN(__atoi);
PROVIDE ( strcasecmp = __strcasecmp );
PROVIDE ( strnlen = __strnlen );
PROVIDE ( atoi = __atoi );
PROVIDE ( mktime = __mktime );

View File

@ -19,3 +19,11 @@ PROVIDE( strchr = 0x4000138c );
PROVIDE( strlcpy = 0x400013bc );
PROVIDE( strstr = 0x40001254 );
PROVIDE( strcasecmp = 0x4000135c );
EXTERN(__mktime);
EXTERN(__strnlen);
EXTERN(__atoi);
PROVIDE ( strnlen = __strnlen );
PROVIDE ( atoi = __atoi );
PROVIDE ( mktime = __mktime );

View File

@ -5,6 +5,8 @@
#![allow(rustdoc::bare_urls)]
#![no_std]
use core::ffi::c_char;
#[doc(hidden)]
/// Helper macro for checking doctest code snippets
#[macro_export]
@ -60,3 +62,139 @@ unsafe extern "C" fn __assert_func(
);
}
}
// We cannot just use the ROM function since (on some targets, currently ESP32-S2) it calls
// `__getreent`
//
// From docs: The __getreent() function returns a per-task pointer to struct
// _reent in newlib libc. This structure is allocated on the TCB of each task.
// i.e. it assumes a FreeRTOS task calling it.
#[unsafe(no_mangle)]
unsafe extern "C" fn __strcasecmp(
s1: *const core::ffi::c_char,
s2: *const core::ffi::c_char,
) -> i32 {
let mut i = 0;
loop {
unsafe {
let s1_i = s1.add(i);
let s2_i = s2.add(i);
let val = (*s1_i).to_ascii_lowercase() as i32 - (*s2_i).to_ascii_lowercase() as i32;
if val != 0 || *s1_i == 0 {
return val;
}
}
i += 1;
}
}
#[unsafe(no_mangle)]
unsafe extern "C" fn __strnlen(chars: *const c_char, maxlen: isize) -> usize {
let mut len = 0;
loop {
unsafe {
if chars.offset(len).read_volatile() == 0 {
break;
}
len += 1;
if len >= maxlen {
break;
}
}
}
len as usize
}
// We cannot just use the ROM function since it calls `__getreent`
//
// From docs: The __getreent() function returns a per-task pointer to struct
// _reent in newlib libc. This structure is allocated on the TCB of each task.
// i.e. it assumes a FreeRTOS task calling it.
#[unsafe(no_mangle)]
unsafe extern "C" fn __atoi(str: *const i8) -> i32 {
let mut sign: i32 = 1;
let mut res: i32 = 0;
let mut idx = 0;
// skip leading spaces
while unsafe { str.add(idx).read() } as u8 == b' ' {
idx += 1;
}
// check sign
let c = unsafe { str.add(idx).read() } as u8;
if c == b'-' || c == b'+' {
if c == b'-' {
sign = -1;
}
idx += 1;
}
// parse number digit by digit
loop {
let c = unsafe { str.add(idx).read() } as u8;
if !c.is_ascii_digit() {
break;
}
// if the result would exceed the bounds - return max-value
if res > i32::MAX / 10 || (res == i32::MAX / 10 && c - b'0' > 7) {
return if sign == 1 { i32::MAX } else { i32::MIN };
}
res = 10 * res + (c - b'0') as i32;
idx += 1;
}
res * sign
}
#[derive(Debug, Copy, Clone)]
#[repr(C)]
struct Tm {
tm_sec: u32, // seconds after the minute - [0, 60] including leap second
tm_min: u32, // minutes after the hour - [0, 59]
tm_hour: u32, // hours since midnight - [0, 23]
tm_mday: u32, // day of the month - [1, 31]
tm_mon: u32, // months since January - [0, 11]
tm_year: u32, // years since 1900
tm_wday: u32, // days since Sunday - [0, 6]
tm_yday: u32, // days since January 1 - [0, 365]
tm_isdst: u32, // daylight savings time flag
}
#[unsafe(no_mangle)]
unsafe extern "C" fn __mktime(time: *const Tm) -> i64 {
let time = unsafe { *time };
// Simplified implementation, ignoring time zones, leap seconds, and other
// complexities
let mut days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
let is_leap_year = |year: u32| {
year.is_multiple_of(4) && (!year.is_multiple_of(100) || year.is_multiple_of(400))
};
let mut days = 0;
let year = time.tm_year + 1900;
for y in 1970..year {
days += if is_leap_year(y) { 366 } else { 365 };
}
if is_leap_year(year) {
days_in_month[1] = 29;
}
for m in 0..time.tm_mon {
days += days_in_month[m as usize];
}
days += time.tm_mday - 1;
let seconds = days * 24 * 60 * 60 + time.tm_hour * 60 * 60 + time.tm_min * 60 + time.tm_sec;
seconds as i64
}

View File

@ -4,6 +4,7 @@
#![no_std]
#![no_main]
use esp_alloc as _;
use esp_backtrace as _;
use esp_hal::main;
use esp_println::println;
@ -14,6 +15,9 @@ esp_bootloader_esp_idf::esp_app_desc!();
#[main]
fn main() -> ! {
let peripherals = esp_hal::init(esp_hal::Config::default());
esp_alloc::heap_allocator!(size: 24 * 1024);
let mut ieee802154 = Ieee802154::new(peripherals.IEEE802154);
ieee802154.set_config(Config {

View File

@ -4,6 +4,7 @@
#![no_std]
#![no_main]
use esp_alloc as _;
use esp_backtrace as _;
use esp_hal::main;
use esp_println::println;
@ -14,6 +15,9 @@ esp_bootloader_esp_idf::esp_app_desc!();
#[main]
fn main() -> ! {
let peripherals = esp_hal::init(esp_hal::Config::default());
esp_alloc::heap_allocator!(size: 24 * 1024);
let mut ieee802154 = Ieee802154::new(peripherals.IEEE802154);
ieee802154.set_config(Config {

View File

@ -4,6 +4,7 @@
#![no_std]
#![no_main]
use esp_alloc as _;
use esp_backtrace as _;
use esp_hal::{delay::Delay, main};
use esp_println::println;
@ -24,6 +25,8 @@ esp_bootloader_esp_idf::esp_app_desc!();
fn main() -> ! {
let peripherals = esp_hal::init(esp_hal::Config::default());
esp_alloc::heap_allocator!(size: 24 * 1024);
let delay = Delay::new();
let mut ieee802154 = Ieee802154::new(peripherals.IEEE802154);
@ -54,7 +57,7 @@ fn main() -> ! {
auxiliary_security_header: None,
},
content: FrameContent::Data,
payload: heapless::Vec::from_slice(b"Hello World").unwrap(),
payload: b"Hello World".to_vec(),
footer: [0u8; 2],
})
.ok();

View File

@ -4,6 +4,7 @@
#![no_std]
#![no_main]
use esp_alloc as _;
use esp_backtrace as _;
use esp_hal::{delay::Delay, main};
use esp_println::println;
@ -24,6 +25,8 @@ esp_bootloader_esp_idf::esp_app_desc!();
fn main() -> ! {
let peripherals = esp_hal::init(esp_hal::Config::default());
esp_alloc::heap_allocator!(size: 24 * 1024);
let delay = Delay::new();
let mut ieee802154 = Ieee802154::new(peripherals.IEEE802154);
@ -54,7 +57,7 @@ fn main() -> ! {
auxiliary_security_header: None,
},
content: FrameContent::Data,
payload: heapless::Vec::from_slice(b"Hello World").unwrap(),
payload: b"Hello World".to_vec(),
footer: [0u8; 2],
})
.ok();

View File

@ -10,6 +10,7 @@
#![no_std]
#![no_main]
use esp_alloc as _;
use esp_backtrace as _;
use esp_hal::{
main,
@ -25,6 +26,8 @@ esp_bootloader_esp_idf::esp_app_desc!();
fn main() -> ! {
let peripherals = esp_hal::init(esp_hal::Config::default());
esp_alloc::heap_allocator!(size: 24 * 1024);
// Default pins for Uart communication
cfg_if::cfg_if! {
if #[cfg(feature = "esp32c6")] {