Skip to content

Commit

Permalink
Auto merge of #2310 - ivmarkov:master, r=Amanieu
Browse files Browse the repository at this point in the history
Support for the ESP-IDF framework (Xtensa and RiscV arch)

Dear all,

This PR is implementing support for the [ESP-IDF](https://github.com/espressif/esp-idf) newlib-based framework, which is the open source SDK provided by Espressif for their MCU family (esp32, esp32s2, esp32c3 and all other forthcoming ones).

Note that this is the second PR on that topic. Approx. an year ago, `@reitermarkus` contributed an [initial set of changes](0dec549#diff-6c07c29bb7b11b27a308055cca03f299266fd8f05af5a65208b64ff715359c89) which are merged already.

Note also that this PR has a [sibling PR against Rust's libStd](rust-lang/rust#87666) which enables **full STD support for the Espressif chipsets** (that is, modulo process support as we are obviously talking about non-kernel bare metal platform here).

A short overview of the changes:
* The original contribution of `@reitermarkus` is renamed from `xtensa.rs` to `espidf.rs` and all branching through this patch is no longer done based on `target_arch = "xtensa"`, but based on `target_os = "espidf"` (this `target_os` value is to be used by the upcoming Rust targets for the ESP-IDF framework). The primary reason for this change is that branching for ESP-IDF based only on the architecture is no longer valid: the newer Espressif chips (esp32c3 and other upcoming ones) are based on the RISCV32IM(A)C architecture, so this patch now supports both Xtensa and RiscV32. Moreover, I would expect that - given the popularity of the riscv ISA - there will be *other* ports of newlib to riscv which will surely have the layout and sizes of the structures etc. different from the ESP-IDF framework.
*  The `pthread` structures had sizes which did not match what is used in the ESP-IDF. Ditto for the various `*_INITIALIZER` constants, which do not use 0x00, but 0xff sequences there
* The BSD socket API on ESP-IDF is prefixed with `lwip_`. Rather than doing heavyweight proxying in Rust libStd, it is best to just address this here with a custom `link_name`, just like it had been done for MacOS and other systems.
* Similar to the `l4re` case, the libc crate should NOT issue a link command  to the CRT lib for the ESP-IDF, due to the way the SDK is linked
* Various other small fixes: primarily - declaration of standard APIs that are available in the ESP-IDF SDK

I should also admit that the patch has one little ESP-IDF-specific cheat:
* Since the `pthread` support in ESP-IDF is still lacking RW-locks, I've implemented it as a temporary workaround by simply remapping (with `"link_name"`) the `pthread_rwlock_*` symbols to their equivalent `pthread_mutex_*` symbols. While this implementation is suboptimal, it reduces significantly the PR changeset surface of the other PR which is against Rust libStd.
  • Loading branch information
bors committed Aug 2, 2021
2 parents a1e0f47 + 85210e6 commit ca93b20
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 25 deletions.
18 changes: 16 additions & 2 deletions src/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,8 @@ pub const ATF_PUBL: ::c_int = 0x08;
pub const ATF_USETRAILERS: ::c_int = 0x10;

cfg_if! {
if #[cfg(target_os = "l4re")] {
// required libraries for L4Re are linked externally, ATM
if #[cfg(any(target_os = "l4re", target_os = "espidf"))] {
// required libraries for L4Re and the ESP-IDF framework are linked externally, ATM
} else if #[cfg(feature = "std")] {
// cargo build, don't pull in anything extra as the libstd dep
// already pulls in all libs.
Expand Down Expand Up @@ -576,6 +576,7 @@ extern "C" {
)))]
#[cfg_attr(target_os = "netbsd", link_name = "__socket30")]
#[cfg_attr(target_os = "illumos", link_name = "__xnet_socket")]
#[cfg_attr(target_os = "espidf", link_name = "lwip_socket")]
pub fn socket(domain: ::c_int, ty: ::c_int, protocol: ::c_int) -> ::c_int;
#[cfg(not(all(
libc_cfg_target_vendor,
Expand All @@ -587,11 +588,13 @@ extern "C" {
link_name = "connect$UNIX2003"
)]
#[cfg_attr(target_os = "illumos", link_name = "__xnet_connect")]
#[cfg_attr(target_os = "espidf", link_name = "lwip_connect")]
pub fn connect(socket: ::c_int, address: *const sockaddr, len: socklen_t) -> ::c_int;
#[cfg_attr(
all(target_os = "macos", target_arch = "x86"),
link_name = "listen$UNIX2003"
)]
#[cfg_attr(target_os = "espidf", link_name = "lwip_listen")]
pub fn listen(socket: ::c_int, backlog: ::c_int) -> ::c_int;
#[cfg(not(all(
libc_cfg_target_vendor,
Expand All @@ -602,6 +605,7 @@ extern "C" {
all(target_os = "macos", target_arch = "x86"),
link_name = "accept$UNIX2003"
)]
#[cfg_attr(target_os = "espidf", link_name = "lwip_accept")]
pub fn accept(socket: ::c_int, address: *mut sockaddr, address_len: *mut socklen_t) -> ::c_int;
#[cfg(not(all(
libc_cfg_target_vendor,
Expand All @@ -612,6 +616,7 @@ extern "C" {
all(target_os = "macos", target_arch = "x86"),
link_name = "getpeername$UNIX2003"
)]
#[cfg_attr(target_os = "espidf", link_name = "lwip_getpeername")]
pub fn getpeername(
socket: ::c_int,
address: *mut sockaddr,
Expand All @@ -626,11 +631,13 @@ extern "C" {
all(target_os = "macos", target_arch = "x86"),
link_name = "getsockname$UNIX2003"
)]
#[cfg_attr(target_os = "espidf", link_name = "lwip_getsockname")]
pub fn getsockname(
socket: ::c_int,
address: *mut sockaddr,
address_len: *mut socklen_t,
) -> ::c_int;
#[cfg_attr(target_os = "espidf", link_name = "lwip_setsockopt")]
pub fn setsockopt(
socket: ::c_int,
level: ::c_int,
Expand Down Expand Up @@ -659,6 +666,7 @@ extern "C" {
link_name = "sendto$UNIX2003"
)]
#[cfg_attr(target_os = "illumos", link_name = "__xnet_sendto")]
#[cfg_attr(target_os = "espidf", link_name = "lwip_sendto")]
pub fn sendto(
socket: ::c_int,
buf: *const ::c_void,
Expand All @@ -667,6 +675,7 @@ extern "C" {
addr: *const sockaddr,
addrlen: socklen_t,
) -> ::ssize_t;
#[cfg_attr(target_os = "espidf", link_name = "lwip_shutdown")]
pub fn shutdown(socket: ::c_int, how: ::c_int) -> ::c_int;

#[cfg_attr(
Expand Down Expand Up @@ -1122,6 +1131,7 @@ extern "C" {
pub fn pthread_rwlockattr_destroy(attr: *mut pthread_rwlockattr_t) -> ::c_int;

#[cfg_attr(target_os = "illumos", link_name = "__xnet_getsockopt")]
#[cfg_attr(target_os = "espidf", link_name = "lwip_getsockopt")]
pub fn getsockopt(
sockfd: ::c_int,
level: ::c_int,
Expand All @@ -1147,6 +1157,7 @@ extern "C" {
target_vendor = "nintendo"
)))]
#[cfg_attr(target_os = "illumos", link_name = "__xnet_getaddrinfo")]
#[cfg_attr(target_os = "espidf", link_name = "lwip_getaddrinfo")]
pub fn getaddrinfo(
node: *const c_char,
service: *const c_char,
Expand All @@ -1158,6 +1169,7 @@ extern "C" {
target_arch = "powerpc",
target_vendor = "nintendo"
)))]
#[cfg_attr(target_os = "espidf", link_name = "lwip_freeaddrinfo")]
pub fn freeaddrinfo(res: *mut addrinfo);
pub fn gai_strerror(errcode: ::c_int) -> *const ::c_char;
#[cfg_attr(
Expand Down Expand Up @@ -1233,11 +1245,13 @@ extern "C" {
all(target_os = "macos", target_arch = "x86"),
link_name = "send$UNIX2003"
)]
#[cfg_attr(target_os = "espidf", link_name = "lwip_send")]
pub fn send(socket: ::c_int, buf: *const ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t;
#[cfg_attr(
all(target_os = "macos", target_arch = "x86"),
link_name = "recv$UNIX2003"
)]
#[cfg_attr(target_os = "espidf", link_name = "lwip_recv")]
pub fn recv(socket: ::c_int, buf: *mut ::c_void, len: ::size_t, flags: ::c_int) -> ::ssize_t;
#[cfg_attr(
all(target_os = "macos", target_arch = "x86"),
Expand Down
16 changes: 13 additions & 3 deletions src/unix/newlib/xtensa/mod.rs → src/unix/newlib/espidf/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,20 @@ pub const MSG_WAITALL: ::c_int = 0x02;
pub const MSG_MORE: ::c_int = 0x10;
pub const MSG_NOSIGNAL: ::c_int = 0x20;

pub const PTHREAD_STACK_MIN: ::size_t = 768;

extern "C" {
pub fn pthread_create(
native: *mut ::pthread_t,
attr: *const ::pthread_attr_t,
f: extern "C" fn(_: *mut ::c_void) -> *mut ::c_void,
value: *mut ::c_void,
) -> ::c_int;

pub fn getrandom(buf: *mut ::c_void, buflen: ::size_t, flags: ::c_uint) -> ::ssize_t;

#[link_name = "lwip_sendmsg"]
pub fn sendmsg(s: ::c_int, msg: *const ::msghdr, flags: ::c_int) -> ::ssize_t;
#[link_name = "lwip_recvmsg"]
pub fn recvmsg(s: ::c_int, msg: *mut ::msghdr, flags: ::c_int) -> ::ssize_t;

pub fn writev(s: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::c_int;
pub fn readv(fd: ::c_int, iov: *const ::iovec, iovcnt: ::c_int) -> ::ssize_t;
}
52 changes: 32 additions & 20 deletions src/unix/newlib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,16 +33,14 @@ s! {
pub ai_protocol: ::c_int,
pub ai_addrlen: socklen_t,

#[cfg(not(all(libc_cfg_target_vendor, target_arch = "powerpc",
target_vendor = "nintendo")))]
#[cfg(target_arch = "xtensa")]
#[cfg(target_os = "espidf")]
pub ai_addr: *mut sockaddr,

pub ai_canonname: *mut ::c_char,

#[cfg(not(all(libc_cfg_target_vendor, target_arch = "powerpc",
target_vendor = "nintendo")))]
#[cfg(not(target_arch = "xtensa"))]
#[cfg(not(any(
target_os = "espidf",
all(libc_cfg_target_vendor, target_arch = "powerpc", target_vendor = "nintendo"))))]
pub ai_addr: *mut sockaddr,

pub ai_next: *mut addrinfo,
Expand Down Expand Up @@ -232,23 +230,37 @@ s! {
// unverified constants
align_const! {
pub const PTHREAD_MUTEX_INITIALIZER: pthread_mutex_t = pthread_mutex_t {
size: [0; __SIZEOF_PTHREAD_MUTEX_T],
size: [__PTHREAD_INITIALIZER_BYTE; __SIZEOF_PTHREAD_MUTEX_T],
};
pub const PTHREAD_COND_INITIALIZER: pthread_cond_t = pthread_cond_t {
size: [0; __SIZEOF_PTHREAD_COND_T],
size: [__PTHREAD_INITIALIZER_BYTE; __SIZEOF_PTHREAD_COND_T],
};
pub const PTHREAD_RWLOCK_INITIALIZER: pthread_rwlock_t = pthread_rwlock_t {
size: [0; __SIZEOF_PTHREAD_RWLOCK_T],
size: [__PTHREAD_INITIALIZER_BYTE; __SIZEOF_PTHREAD_RWLOCK_T],
};
}
pub const NCCS: usize = 32;
pub const __SIZEOF_PTHREAD_ATTR_T: usize = 56;
pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40;
pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4;
pub const __SIZEOF_PTHREAD_COND_T: usize = 48;
pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4;
pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56;
pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8;
cfg_if! {
if #[cfg(target_os = "espidf")] {
const __PTHREAD_INITIALIZER_BYTE: u8 = 0xff;
pub const __SIZEOF_PTHREAD_ATTR_T: usize = 32;
pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 4;
pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 12;
pub const __SIZEOF_PTHREAD_COND_T: usize = 4;
pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 8;
pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 4;
pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 12;
} else {
const __PTHREAD_INITIALIZER_BYTE: u8 = 0;
pub const __SIZEOF_PTHREAD_ATTR_T: usize = 56;
pub const __SIZEOF_PTHREAD_MUTEX_T: usize = 40;
pub const __SIZEOF_PTHREAD_MUTEXATTR_T: usize = 4;
pub const __SIZEOF_PTHREAD_COND_T: usize = 48;
pub const __SIZEOF_PTHREAD_CONDATTR_T: usize = 4;
pub const __SIZEOF_PTHREAD_RWLOCK_T: usize = 56;
pub const __SIZEOF_PTHREAD_RWLOCKATTR_T: usize = 8;
}
}
pub const __SIZEOF_PTHREAD_BARRIER_T: usize = 32;
pub const __SIZEOF_PTHREAD_BARRIERATTR_T: usize = 4;
pub const __PTHREAD_MUTEX_HAVE_PREV: usize = 1;
Expand Down Expand Up @@ -688,15 +700,15 @@ extern "C" {
}

cfg_if! {
if #[cfg(target_arch = "arm")] {
if #[cfg(target_os = "espidf")] {
mod espidf;
pub use self::espidf::*;
} else if #[cfg(target_arch = "arm")] {
mod arm;
pub use self::arm::*;
} else if #[cfg(target_arch = "aarch64")] {
mod aarch64;
pub use self::aarch64::*;
} else if #[cfg(target_arch = "xtensa")] {
mod xtensa;
pub use self::xtensa::*;
} else if #[cfg(target_arch = "powerpc")] {
mod powerpc;
pub use self::powerpc::*;
Expand Down

0 comments on commit ca93b20

Please sign in to comment.