diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 47e81978ef1e..ebf5779e92dc 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -336,6 +336,7 @@ - [MMIO](bare-metal/aps/mmio.md) - [Let's Write a UART Driver](bare-metal/aps/uart.md) - [More Traits](bare-metal/aps/uart/traits.md) + - [Using It](bare-metal/aps/uart/using.md) - [A Better UART Driver](bare-metal/aps/better-uart.md) - [Bitflags](bare-metal/aps/better-uart/bitflags.md) - [Multiple Registers](bare-metal/aps/better-uart/registers.md) diff --git a/src/bare-metal/aps/better-uart/using.md b/src/bare-metal/aps/better-uart/using.md index 159c8e3db479..a71872080cc3 100644 --- a/src/bare-metal/aps/better-uart/using.md +++ b/src/bare-metal/aps/better-uart/using.md @@ -9,9 +9,6 @@ echo incoming bytes.
-- As in the [inline assembly](../inline-assembly.md) example, this `main` - function is called from our entry point code in `entry.S`. See the speaker - notes there for details. - Run the example in QEMU with `make qemu` under `src/bare-metal/aps/examples`.
diff --git a/src/bare-metal/aps/entry-point.md b/src/bare-metal/aps/entry-point.md index 783e73df6323..ab5f4b4c2542 100644 --- a/src/bare-metal/aps/entry-point.md +++ b/src/bare-metal/aps/entry-point.md @@ -8,6 +8,10 @@ Before we can start running Rust code, we need to do some initialisation.
+This code is in `src/bare-metal/aps/examples/entry.S`. It's not necessary to +understand this in detail -- the takeaway is that typically some low-level setup +is needed to meet Rust's expectations of the system. + - This is the same as it would be for C: initialising the processor state, zeroing the BSS, and setting up the stack pointer. - The BSS (block starting symbol, for historical reasons) is the part of the diff --git a/src/bare-metal/aps/examples/src/pl011.rs b/src/bare-metal/aps/examples/src/pl011.rs index 36d765e3adc8..2aef3621c1f1 100644 --- a/src/bare-metal/aps/examples/src/pl011.rs +++ b/src/bare-metal/aps/examples/src/pl011.rs @@ -11,6 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +#![allow(dead_code)] use core::fmt::{self, Write}; diff --git a/src/bare-metal/aps/logging.md b/src/bare-metal/aps/logging.md index 0d11f62212c0..933b8f0d96c7 100644 --- a/src/bare-metal/aps/logging.md +++ b/src/bare-metal/aps/logging.md @@ -9,8 +9,9 @@ We can do this by implementing the `Log` trait.
-- The unwrap in `log` is safe because we initialise `LOGGER` before calling - `set_logger`. +- The first unwrap in `log` will succeed because we initialise `LOGGER` before + calling `set_logger`. The second will succeed because `Uart::write_str` always + returns `Ok`.
diff --git a/src/bare-metal/aps/mmio.md b/src/bare-metal/aps/mmio.md index 5660a3052c70..27ccc84bc77c 100644 --- a/src/bare-metal/aps/mmio.md +++ b/src/bare-metal/aps/mmio.md @@ -5,6 +5,16 @@ - Use `&raw` to get fields of structs without creating an intermediate reference. +```rust +const SOME_DEVICE_REGISTER: *mut u64 = 0x800_0000 as _; +// SAFETY: Some device is mapped at this address. +unsafe { + SOME_DEVICE_REGISTER.write_volatile(0xff); + SOME_DEVICE_REGISTER.write_volatile(0x80); + assert_eq!(SOME_DEVICE_REGISTER.read_volatile(), 0xaa); +} +``` + [`pointer::read_volatile`]: https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.read_volatile [`pointer::write_volatile`]: https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.write_volatile [`addr_of!`]: https://doc.rust-lang.org/stable/core/ptr/macro.addr_of.html diff --git a/src/bare-metal/aps/other-projects.md b/src/bare-metal/aps/other-projects.md index cf61d36b624b..220e8bdf64cd 100644 --- a/src/bare-metal/aps/other-projects.md +++ b/src/bare-metal/aps/other-projects.md @@ -15,17 +15,8 @@
- The RaspberryPi OS tutorial runs Rust code before the MMU and caches are - enabled. This will read and write memory (e.g. the stack). However: - - Without the MMU and cache, unaligned accesses will fault. It builds with - `aarch64-unknown-none` which sets `+strict-align` to prevent the compiler - generating unaligned accesses so it should be alright, but this is not - necessarily the case in general. - - If it were running in a VM, this can lead to cache coherency issues. The - problem is that the VM is accessing memory directly with the cache disabled, - while the host has cacheable aliases to the same memory. Even if the host - doesn't explicitly access the memory, speculative accesses can lead to cache - fills, and then changes from one or the other will get lost. Again this is - alright in this particular case (running directly on the hardware with no - hypervisor), but isn't a good pattern in general. + enabled. This will read and write memory (e.g. the stack). However, this has + the problems mentioned at the beginning of this session regarding unaligned + access and cache coherency.
diff --git a/src/bare-metal/aps/uart/traits.md b/src/bare-metal/aps/uart/traits.md index 1f69e9ffa44c..b947a5f8211d 100644 --- a/src/bare-metal/aps/uart/traits.md +++ b/src/bare-metal/aps/uart/traits.md @@ -11,7 +11,8 @@ too. - Implementing `Write` lets us use the `write!` and `writeln!` macros with our `Uart` type. -- Run the example in QEMU with `make qemu_minimal` under - `src/bare-metal/aps/examples`. + +- `Send` is an auto-trait, but not implemented automatically because it is not + implemented for pointers.
diff --git a/src/bare-metal/aps/uart/using.md b/src/bare-metal/aps/uart/using.md new file mode 100644 index 000000000000..d8b6054af1ee --- /dev/null +++ b/src/bare-metal/aps/uart/using.md @@ -0,0 +1,17 @@ +# Using it + +Let's write a small program using our driver to write to the serial console. + +```rust,editable,compile_fail +{{#include ../examples/src/main_minimal.rs:main}} +``` + +
+ +- As in the [inline assembly](../inline-assembly.md) example, this `main` + function is called from our entry point code in `entry.S`. See the speaker + notes there for details. +- Run the example in QEMU with `make qemu_minimal` under + `src/bare-metal/aps/examples`. + +
diff --git a/src/bare-metal/useful-crates.md b/src/bare-metal/useful-crates.md index 393017738775..0df0fe56bb84 100644 --- a/src/bare-metal/useful-crates.md +++ b/src/bare-metal/useful-crates.md @@ -1,4 +1,4 @@ # Useful crates -We'll go over a few crates which solve some common problems in bare-metal +We'll look at a few crates which solve some common problems in bare-metal programming. diff --git a/src/bare-metal/useful-crates/buddy_system_allocator.md b/src/bare-metal/useful-crates/buddy_system_allocator.md index b834066914ab..8dcd117af261 100644 --- a/src/bare-metal/useful-crates/buddy_system_allocator.md +++ b/src/bare-metal/useful-crates/buddy_system_allocator.md @@ -1,10 +1,11 @@ # `buddy_system_allocator` [`buddy_system_allocator`][1] is a crate implementing a basic buddy system -allocator. It can be used both for [`LockedHeap`][2] implementing -[`GlobalAlloc`][3] so you can use the standard `alloc` crate (as we saw -[before][4]), or for allocating other address space. For example, we might want -to allocate MMIO space for PCI BARs: +allocator. It can be used both to implement [`GlobalAlloc`][3] (using +[`LockedHeap`][2]) so you can use the standard `alloc` crate (as we saw +[before][4]), or for allocating other address space (using +[`FrameAllocator`][5]) . For example, we might want to allocate MMIO space for +PCI BARs: @@ -25,3 +26,4 @@ to allocate MMIO space for PCI BARs: [2]: https://docs.rs/buddy_system_allocator/0.9.0/buddy_system_allocator/struct.LockedHeap.html [3]: https://doc.rust-lang.org/core/alloc/trait.GlobalAlloc.html [4]: ../alloc.md +[5]: https://docs.rs/buddy_system_allocator/0.9.0/buddy_system_allocator/struct.FrameAllocator.html diff --git a/src/bare-metal/useful-crates/spin.md b/src/bare-metal/useful-crates/spin.md index 19b83bac4793..42f9f1de27d1 100644 --- a/src/bare-metal/useful-crates/spin.md +++ b/src/bare-metal/useful-crates/spin.md @@ -12,12 +12,12 @@ primitives. ```rust,editable,compile_fail use spin::mutex::SpinMutex; -static counter: SpinMutex = SpinMutex::new(0); +static COUNTER: SpinMutex = SpinMutex::new(0); fn main() { - println!("count: {}", counter.lock()); - *counter.lock() += 2; - println!("count: {}", counter.lock()); + println!("count: {}", COUNTER.lock()); + *COUNTER.lock() += 2; + println!("count: {}", COUNTER.lock()); } ```