From 04ff04b4398f1cc315d4484ec47067a79e96982c Mon Sep 17 00:00:00 2001 From: KENTARO OKUDA Date: Wed, 3 Jun 2020 09:19:12 -0400 Subject: [PATCH 1/6] Fix Typoes and Improve Readability This fix typos in concurrency/index.md. --- src/concurrency/index.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/concurrency/index.md b/src/concurrency/index.md index 54c00fa0..319a0259 100644 --- a/src/concurrency/index.md +++ b/src/concurrency/index.md @@ -42,7 +42,7 @@ you can get away with such a simple approach this can be a great solution. Unlike non-embedded Rust, we will not usually have the luxury of creating heap allocations and passing references to that data into a newly-created -thread. Instead our interrupt handlers might be called at any time and must +thread. Instead, our interrupt handlers might be called at any time and must know how to access whatever shared memory we are using. At the lowest level, this means we must have _statically allocated_ mutable memory, which both the interrupt handler and the main code can refer to. @@ -124,7 +124,7 @@ fn timer() { } ``` -In this example we use `cortex_m::interrupt::free`, but other platforms will +In this example, we use `cortex_m::interrupt::free`, but other platforms will have similar mechanisms for executing code in a critical section. This is also the same as disabling interrupts, running some code, and then re-enabling interrupts. @@ -138,7 +138,7 @@ for two reasons: If `COUNTER` was being shared by multiple interrupt handlers that might _preempt_ each other, then each one might require a critical section as well. -This solves our immediate problem, but we're still left writing a lot of unsafe code which we need to carefully reason about, and we might be using critical sections needlessly. Since each critical section temporarily pauses interrupt processing, there is an associated cost of some extra code size and higher interrupt latency and jitter (interrupts may take longer to be processed, and the time until they are processed will be more variable). Whether this is a problem depends on your system, but in general we'd like to avoid it. +This solves our immediate problem, but we're still left writing a lot of unsafe code which we need to carefully reason about, and we might be using critical sections needlessly. Since each critical section temporarily pauses interrupt processing, there is an associated cost of some extra code size and higher interrupt latency and jitter (interrupts may take longer to be processed, and the time until they are processed will be more variable). Whether this is a problem depends on your system, but in general, we'd like to avoid it. It's worth noting that while a critical section guarantees no interrupts will fire, it does not provide an exclusivity guarantee on multi-core systems! The @@ -209,7 +209,7 @@ blocks which must be very carefully checked and are not ergonomic. Surely we can do better in Rust! We can abstract our counter into a safe interface which can be safely used -anywhere else in our code. For this example we'll use the critical-section +anywhere else in our code. For this example, we'll use the critical-section counter, but you could do something very similar with atomics. ```rust,ignore @@ -274,7 +274,7 @@ fn timer() { We've moved our `unsafe` code to inside our carefully-planned abstraction, and now our application code does not contain any `unsafe` blocks. -This design requires the application pass a `CriticalSection` token in: +This design requires the application to pass a `CriticalSection` token in: these tokens are only safely generated by `interrupt::free`, so by requiring one be passed in, we ensure we are operating inside a critical section, without having to actually do the lock ourselves. This guarantee is provided statically @@ -302,7 +302,7 @@ variables _must_ be Sync, since they can be accessed by multiple threads. To tell the compiler we have taken care that the `CSCounter` is in fact safe to share between threads, we implement the Sync trait explicitly. As with the previous use of critical sections, this is only safe on single-core platforms: -with multiple cores you would need to go to greater lengths to ensure safety. +with multiple cores, you would need to go to greater lengths to ensure safety. ## Mutexes @@ -383,8 +383,8 @@ to get a safe counter with no unsafe code at all! This is great for simple types like the `u32` of our counter, but what about more complex types which are not Copy? An extremely common example in an -embedded context is a peripheral struct, which generally are not Copy. -For that we can turn to `RefCell`. +embedded context is a peripheral struct, which generally is not Copy. +For that, we can turn to `RefCell`. ## Sharing Peripherals @@ -499,7 +499,7 @@ interrupt::free(|cs| { }); ``` -Finally we use `MY_GPIO` in a safe and concurrent fashion. The critical section +Finally, we use `MY_GPIO` in a safe and concurrent fashion. The critical section prevents the interrupt firing as usual, and lets us borrow the mutex. The `RefCell` then gives us an `&Option`, and tracks how long it remains borrowed - once that reference goes out of scope, the `RefCell` will be updated @@ -509,7 +509,7 @@ Since we can't move the `GPIOA` out of the `&Option`, we need to convert it to an `&Option<&GPIOA>` with `as_ref()`, which we can finally `unwrap()` to obtain the `&GPIOA` which lets us modify the peripheral. -If we need a mutable references to shared resources, then `borrow_mut` and `deref_mut` +If we need mutable references to shared resources, then `borrow_mut` and `deref_mut` should be used instead. The following code shows an example using the TIM2 timer. ```rust,ignore @@ -587,7 +587,7 @@ primitives, and often interoperate with hardware features such as DMA engines. [FreeRTOS]: https://freertos.org/ [ChibiOS]: http://chibios.org/ -At the time of writing there are not many Rust RTOS examples to point to, +At the time of writing, there are not many Rust RTOS examples to point to, but it's an interesting area so watch this space! ## Multiple Cores From ebb1de163d2307d537a7e96e29d4ea123cec76ef Mon Sep 17 00:00:00 2001 From: lonesometraveler Date: Wed, 3 Jun 2020 09:51:24 -0400 Subject: [PATCH 2/6] Update src/concurrency/index.md Co-authored-by: Adam Greig --- src/concurrency/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/concurrency/index.md b/src/concurrency/index.md index 319a0259..d769dd33 100644 --- a/src/concurrency/index.md +++ b/src/concurrency/index.md @@ -509,7 +509,7 @@ Since we can't move the `GPIOA` out of the `&Option`, we need to convert it to an `&Option<&GPIOA>` with `as_ref()`, which we can finally `unwrap()` to obtain the `&GPIOA` which lets us modify the peripheral. -If we need mutable references to shared resources, then `borrow_mut` and `deref_mut` +If we need a mutable reference to a shared resource, then `borrow_mut` and `deref_mut` should be used instead. The following code shows an example using the TIM2 timer. ```rust,ignore From ac73c46aa3c32ed3eab8f13dd7f7b8492f461080 Mon Sep 17 00:00:00 2001 From: hyperslv Date: Sat, 13 Jun 2020 16:20:24 +0300 Subject: [PATCH 3/6] Provide a note on 'extern crate' usage in edition 2018 of Rust --- src/start/qemu.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/start/qemu.md b/src/start/qemu.md index 50a70224..f069ce5e 100644 --- a/src/start/qemu.md +++ b/src/start/qemu.md @@ -121,6 +121,9 @@ nightly. the panicking behavior of the program. We will cover this in more detail in the [Panicking](panicking.md) chapter of the book. +> Note that while `extern crate` looks odd in modern Rust syntax, this declaration +> form is required since it resolves the implicit dependency in `no_std` context. + [`#[entry]`][entry] is an attribute provided by the [`cortex-m-rt`] crate that's used to mark the entry point of the program. As we are not using the standard `main` interface we need another way to indicate the entry point of the program and From d999a11a2258eccab24ab1df05794a048f35c066 Mon Sep 17 00:00:00 2001 From: hyperslv Date: Sun, 14 Jun 2020 15:13:39 +0300 Subject: [PATCH 4/6] Replace unidiomatic 'extern crate' to 'use x as _' and provide an explanation note --- src/start/exceptions.md | 4 ++-- src/start/panicking.md | 12 +++++++++--- src/start/qemu.md | 11 ++++------- src/start/registers.md | 4 ++-- src/start/semihosting.md | 6 +++--- 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/start/exceptions.md b/src/start/exceptions.md index 816188d2..3d46f4ee 100644 --- a/src/start/exceptions.md +++ b/src/start/exceptions.md @@ -62,7 +62,7 @@ times it has been called in the `COUNT` variable and then prints the value of #![no_main] #![no_std] -extern crate panic_halt; +use panic_halt as _; use core::fmt::Write; @@ -190,7 +190,7 @@ memory location. #![no_main] #![no_std] -extern crate panic_halt; +use panic_halt as _; use core::fmt::Write; use core::ptr; diff --git a/src/start/panicking.md b/src/start/panicking.md index b42423d2..bee7dbe1 100644 --- a/src/start/panicking.md +++ b/src/start/panicking.md @@ -51,11 +51,11 @@ profile. For example: // dev profile: easier to debug panics; can put a breakpoint on `rust_begin_unwind` #[cfg(debug_assertions)] -extern crate panic_halt; +use panic_halt as _; // release profile: minimize the binary size of the application #[cfg(not(debug_assertions))] -extern crate panic_abort; +use panic_abort as _; // .. ``` @@ -64,6 +64,12 @@ In this example the crate links to the `panic-halt` crate when built with the dev profile (`cargo build`), but links to the `panic-abort` crate when built with the release profile (`cargo build --release`). +> Note that the _underscore import_ form of the _use_ declaration is used to import a `#[panic_handler]` function +> symbol without importing of trait's symbol itself since it is not used elsewhere on its own. +> Sometimes you might see the `extern crate` form of importing which is used for the same reason but it is unidiomatic. +> `extern crate` should be used only for importing _"sysroot"_ crates (crates distributed with Rust itself) like `proc_macro`, +> `alloc`, `test`, and similar ones. + ## An example Here's an example that tries to index an array beyond its length. The operation @@ -73,7 +79,7 @@ results in a panic. #![no_main] #![no_std] -extern crate panic_semihosting; +use panic_semihosting as _; use cortex_m_rt::entry; diff --git a/src/start/qemu.md b/src/start/qemu.md index f069ce5e..867bea2d 100644 --- a/src/start/qemu.md +++ b/src/start/qemu.md @@ -94,7 +94,7 @@ For convenience here are the most important parts of the source code in `src/mai #![no_std] #![no_main] -extern crate panic_halt; +use panic_halt as _; use cortex_m_rt::entry; @@ -117,13 +117,10 @@ interface that most Rust programs use. The main (no pun intended) reason to go with `no_main` is that using the `main` interface in `no_std` context requires nightly. -`extern crate panic_halt;`. This crate provides a `panic_handler` that defines +`use panic_halt as _;`. This crate provides a `panic_handler` that defines the panicking behavior of the program. We will cover this in more detail in the [Panicking](panicking.md) chapter of the book. -> Note that while `extern crate` looks odd in modern Rust syntax, this declaration -> form is required since it resolves the implicit dependency in `no_std` context. - [`#[entry]`][entry] is an attribute provided by the [`cortex-m-rt`] crate that's used to mark the entry point of the program. As we are not using the standard `main` interface we need another way to indicate the entry point of the program and @@ -321,7 +318,7 @@ For convenience here's the source code of `examples/hello.rs`: #![no_main] #![no_std] -extern crate panic_halt; +use panic_halt as _; use cortex_m_rt::entry; use cortex_m_semihosting::{debug, hprintln}; @@ -512,7 +509,7 @@ list main This will show the source code, from the file examples/hello.rs. ```text -6 extern crate panic_halt; +6 use panic_halt as _; 7 8 use cortex_m_rt::entry; 9 use cortex_m_semihosting::{debug, hprintln}; diff --git a/src/start/registers.md b/src/start/registers.md index 9ab16b64..40458486 100644 --- a/src/start/registers.md +++ b/src/start/registers.md @@ -53,7 +53,7 @@ We won't get very far with our embedded software development if we restrict ours #![no_std] #![no_main] -extern crate panic_halt; // panic handler +use panic_halt as _; // panic handler use cortex_m_rt::entry; use tm4c123x; @@ -129,7 +129,7 @@ Let's see an example: #![no_std] #![no_main] -extern crate panic_halt; // panic handler +use panic_halt as _; // panic handler use cortex_m_rt::entry; use tm4c123x_hal as hal; diff --git a/src/start/semihosting.md b/src/start/semihosting.md index b4257e6f..655e931b 100644 --- a/src/start/semihosting.md +++ b/src/start/semihosting.md @@ -16,7 +16,7 @@ world!": #![no_main] #![no_std] -extern crate panic_halt; +use panic_halt as _; use cortex_m_rt::entry; use cortex_m_semihosting::hprintln; @@ -67,7 +67,7 @@ until you restart it. #![no_main] #![no_std] -extern crate panic_halt; +use panic_halt as _; use cortex_m_rt::entry; use cortex_m_semihosting::debug; @@ -105,7 +105,7 @@ stderr. #![no_main] #![no_std] -extern crate panic_semihosting; // features = ["exit"] +use panic_semihosting as _; // features = ["exit"] use cortex_m_rt::entry; use cortex_m_semihosting::debug; From a8e37ae7f979eef7db407969a33e221ae8a7902a Mon Sep 17 00:00:00 2001 From: KENTARO OKUDA Date: Sun, 14 Jun 2020 12:52:29 -0400 Subject: [PATCH 5/6] Update index.md --- src/concurrency/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/concurrency/index.md b/src/concurrency/index.md index d769dd33..ef6f7a17 100644 --- a/src/concurrency/index.md +++ b/src/concurrency/index.md @@ -274,7 +274,7 @@ fn timer() { We've moved our `unsafe` code to inside our carefully-planned abstraction, and now our application code does not contain any `unsafe` blocks. -This design requires the application to pass a `CriticalSection` token in: +This design requires that the application pass a `CriticalSection` token in: these tokens are only safely generated by `interrupt::free`, so by requiring one be passed in, we ensure we are operating inside a critical section, without having to actually do the lock ourselves. This guarantee is provided statically From c08741b648391326f75f2f4762531d8d1bf4940e Mon Sep 17 00:00:00 2001 From: hyperslv <57301860+hyperslv@users.noreply.github.com> Date: Sun, 14 Jun 2020 22:43:43 +0300 Subject: [PATCH 6/6] Update src/start/panicking.md Co-authored-by: Adam Greig --- src/start/panicking.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/start/panicking.md b/src/start/panicking.md index bee7dbe1..584d2b25 100644 --- a/src/start/panicking.md +++ b/src/start/panicking.md @@ -64,11 +64,12 @@ In this example the crate links to the `panic-halt` crate when built with the dev profile (`cargo build`), but links to the `panic-abort` crate when built with the release profile (`cargo build --release`). -> Note that the _underscore import_ form of the _use_ declaration is used to import a `#[panic_handler]` function -> symbol without importing of trait's symbol itself since it is not used elsewhere on its own. -> Sometimes you might see the `extern crate` form of importing which is used for the same reason but it is unidiomatic. -> `extern crate` should be used only for importing _"sysroot"_ crates (crates distributed with Rust itself) like `proc_macro`, -> `alloc`, `test`, and similar ones. +> The `use panic_abort as _;` form of the `use` statement is used to ensure the `panic_abort` panic handler is +> included in our final executable while making it clear to the compiler that we won't explicitly use anything from +> the crate. Without the `as _` rename, the compiler would warn that we have an unused import. +> Sometimes you might see `extern crate panic_abort` instead, which is an older style used before the +> 2018 edition of Rust, and should now only be used for "sysroot" crates (those distributed with Rust itself) such +> as `proc_macro`, `alloc`, `std`, and `test`. ## An example