From 9835e2ae736235810b4ea1c162ca5e65c547e770 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 18 May 2024 04:49:50 +0200 Subject: Merging upstream version 1.71.1+dfsg1. Signed-off-by: Daniel Baumann --- .../src/interoperability/c-with-rust.md | 6 ++- .../embedded-book/src/interoperability/index.md | 51 +++++++++++----------- src/doc/embedded-book/src/intro/index.md | 1 + src/doc/embedded-book/src/start/exceptions.md | 4 +- src/doc/embedded-book/src/start/registers.md | 2 +- 5 files changed, 34 insertions(+), 30 deletions(-) (limited to 'src/doc/embedded-book') diff --git a/src/doc/embedded-book/src/interoperability/c-with-rust.md b/src/doc/embedded-book/src/interoperability/c-with-rust.md index 6bec3bd87..9c56c6aaa 100644 --- a/src/doc/embedded-book/src/interoperability/c-with-rust.md +++ b/src/doc/embedded-book/src/interoperability/c-with-rust.md @@ -127,7 +127,9 @@ In the simplest case of compiling a single C file as a dependency to a static li ```rust,ignore fn main() { cc::Build::new() - .file("foo.c") - .compile("libfoo.a"); + .file("src/foo.c") + .compile("foo"); } ``` + +The `build.rs` is placed at the root of the package. Then `cargo build` will compile and execute it before the build of the package. A static archive named `libfoo.a` is generated and placed in the `target` directory. diff --git a/src/doc/embedded-book/src/interoperability/index.md b/src/doc/embedded-book/src/interoperability/index.md index 4ff5fd9df..267bd6788 100644 --- a/src/doc/embedded-book/src/interoperability/index.md +++ b/src/doc/embedded-book/src/interoperability/index.md @@ -2,40 +2,42 @@ Interoperability between Rust and C code is always dependent on transforming data between the two languages. -For this purposes there are two dedicated modules +For this purpose, there is a dedicated module in the `stdlib` called -[`std::ffi`](https://doc.rust-lang.org/std/ffi/index.html) and -[`std::os::raw`](https://doc.rust-lang.org/std/os/raw/index.html). +[`std::ffi`](https://doc.rust-lang.org/std/ffi/index.html). -`std::os::raw` deals with low-level primitive types that can -be converted implicitly by the compiler -because the memory layout between Rust and C -is similar enough or the same. +`std::ffi` provides type definitions for C primitive types, +such as `char`, `int`, and `long`. +It also provides some utility for converting more complex +types such as strings, mapping both `&str` and `String` +to C types that are easier and safer to handle. -`std::ffi` provides some utility for converting more complex -types such as Strings, mapping both `&str` and `String` -to C-types that are easier and safer to handle. - -Neither of these modules are available in `core`, but you can find a `#![no_std]` -compatible version of `std::ffi::{CStr,CString}` in the [`cstr_core`] crate, and -most of the `std::os::raw` types in the [`cty`] crate. +As of Rust 1.30, +functionalities of `std::ffi` are available +in either `core::ffi` or `alloc::ffi` +depending on whether or not memory allocation is involved. +The [`cty`] crate and the [`cstr_core`] crate +also offer similar functionalities. [`cstr_core`]: https://crates.io/crates/cstr_core [`cty`]: https://crates.io/crates/cty -| Rust type | Intermediate | C type | -|------------|--------------|--------------| -| String | CString | *char | -| &str | CStr | *const char | -| () | c_void | void | -| u32 or u64 | c_uint | unsigned int | -| etc | ... | ... | +| Rust type | Intermediate | C type | +|----------------|--------------|----------------| +| `String` | `CString` | `char *` | +| `&str` | `CStr` | `const char *` | +| `()` | `c_void` | `void` | +| `u32` or `u64` | `c_uint` | `unsigned int` | +| etc | ... | ... | -As mentioned above, primitive types can be converted -by the compiler implicitly. +A value of a C primitive type can be used +as one of the corresponding Rust type and vice versa, +since the former is simply a type alias of the latter. +For example, the following code compiles on platforms +where `unsigned int` is 32-bit long. ```rust,ignore -unsafe fn foo(num: u32) { +fn foo(num: u32) { let c_num: c_uint = num; let r_num: u32 = c_num; } @@ -51,7 +53,6 @@ We are collecting examples and use cases for this on our issue tracker in [issue #61]: https://github.com/rust-embedded/book/issues/61 - ## Interoperability with RTOSs Integrating Rust with an RTOS such as FreeRTOS or ChibiOS is still a work in diff --git a/src/doc/embedded-book/src/intro/index.md b/src/doc/embedded-book/src/intro/index.md index 7a600fee0..272c2428f 100644 --- a/src/doc/embedded-book/src/intro/index.md +++ b/src/doc/embedded-book/src/intro/index.md @@ -60,6 +60,7 @@ If you are unfamiliar with anything mentioned above or if you want more informat | Rust, Embedded | [Embedded Rust Bookshelf](https://docs.rust-embedded.org) | Here you can find several other resources provided by Rust's Embedded Working Group. | | Rust, Embedded | [Embedonomicon](https://docs.rust-embedded.org/embedonomicon/) | The nitty gritty details when doing embedded programming in Rust. | | Rust, Embedded | [embedded FAQ](https://docs.rust-embedded.org/faq.html) | Frequently asked questions about Rust in an embedded context. | +| Rust, Embedded | [Comprehensive Rust 🦀: Bare Metal](https://google.github.io/comprehensive-rust/bare-metal.html) | Teaching material for a 1-day class on bare-metal Rust development | | Interrupts | [Interrupt](https://en.wikipedia.org/wiki/Interrupt) | - | | Memory-mapped IO/Peripherals | [Memory-mapped I/O](https://en.wikipedia.org/wiki/Memory-mapped_I/O) | - | | SPI, UART, RS232, USB, I2C, TTL | [Stack Exchange about SPI, UART, and other interfaces](https://electronics.stackexchange.com/questions/37814/usart-uart-rs232-usb-spi-i2c-ttl-etc-what-are-all-of-these-and-how-do-th) | - | diff --git a/src/doc/embedded-book/src/start/exceptions.md b/src/doc/embedded-book/src/start/exceptions.md index b15717da9..bd9b85b76 100644 --- a/src/doc/embedded-book/src/start/exceptions.md +++ b/src/doc/embedded-book/src/start/exceptions.md @@ -50,7 +50,7 @@ possible. > Note that the `exception` attribute transforms definitions of static variables > inside the function by wrapping them into `unsafe` blocks and providing us > with new appropriate variables of type `&mut` of the same name. -> Thus we can derefence the reference via `*` to access the values of the variables without +> Thus we can dereference the reference via `*` to access the values of the variables without > needing to wrap them in an `unsafe` block. ## A complete example @@ -258,7 +258,7 @@ ResetTrampoline: 800094c: b #-0x4 ``` -You can lookup the value of the program counter `0x0800094a` in the dissassembly. +You can lookup the value of the program counter `0x0800094a` in the disassembly. You'll see that a load operation (`ldr r0, [r0]` ) caused the exception. The `r0` field of `ExceptionFrame` will tell you the value of register `r0` was `0x3fff_fffe` at that time. diff --git a/src/doc/embedded-book/src/start/registers.md b/src/doc/embedded-book/src/start/registers.md index fe184792c..2d4a8e85b 100644 --- a/src/doc/embedded-book/src/start/registers.md +++ b/src/doc/embedded-book/src/start/registers.md @@ -134,7 +134,7 @@ pwm0.enable.write(temp); // Uh oh! Wrong variable! ## Using a HAL crate -The HAL crate for a chip typically works by implementing a custom Trait for the raw structures exposed by the PAC. Often this trait will define a function called `constrain()` for single peripherals or `split()` for things like GPIO ports with multiple pins. This function will consume the underlying raw peripheral structure and return a new object with a higher-level API. This API may also do things like have the Serial port `new` function require a borrow on some `Clock` structure, which can only be generated by calling the function which configures the PLLs and sets up all the clock frequencies. In this way, it is statically impossible to create a Serial port object without first having configured the clock rates, or for the Serial port object to mis-convert the baud rate into clock ticks. Some crates even define special traits for the states each GPIO pin can be in, requiring the user to put a pin into the correct state (say, by selecting the appropriate Alternate Function Mode) before passing the pin into Peripheral. All with no run-time cost! +The HAL crate for a chip typically works by implementing a custom Trait for the raw structures exposed by the PAC. Often this trait will define a function called `constrain()` for single peripherals or `split()` for things like GPIO ports with multiple pins. This function will consume the underlying raw peripheral structure and return a new object with a higher-level API. This API may also do things like have the Serial port `new` function require a borrow on some `Clock` structure, which can only be generated by calling the function which configures the PLLs and sets up all the clock frequencies. In this way, it is statically impossible to create a Serial port object without first having configured the clock rates, or for the Serial port object to misconvert the baud rate into clock ticks. Some crates even define special traits for the states each GPIO pin can be in, requiring the user to put a pin into the correct state (say, by selecting the appropriate Alternate Function Mode) before passing the pin into Peripheral. All with no run-time cost! Let's see an example: -- cgit v1.2.3