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());
}
```