1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-03-19 22:19:29 +02:00

APS updates (#2528)

These are some minor updates from walking through the session myself.

* Add some context to the `entry.S` slide, which is otherwise a bit
terrifying for someone who does not speak ARM assembly.
 * Include a simple, fake example of MMIO.
* Add a "Using It" section to the minimal UART segment, parallel to the
better UART
* Better explanation of the `unwrap` calls in the logging example.
Unwrap is never "unsafe", so remove that word.
 * Allow dead code in some `.rs` files.
 * Remove redundant warning about use of memory before MMU setup.
 * Rephase text about buddy-system
 * Fix lint warning in spin slide.
This commit is contained in:
Dustin J. Mitchell 2025-01-07 14:07:39 -05:00 committed by GitHub
parent 3764569198
commit c04d2860e8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 53 additions and 28 deletions

View File

@ -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)

View File

@ -9,9 +9,6 @@ echo incoming bytes.
<details>
- 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`.
</details>

View File

@ -8,6 +8,10 @@ Before we can start running Rust code, we need to do some initialisation.
<details>
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

View File

@ -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};

View File

@ -9,8 +9,9 @@ We can do this by implementing the `Log` trait.
<details>
- 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`.
</details>

View File

@ -5,6 +5,16 @@
- Use `&raw` to get fields of structs without creating an intermediate
reference.
```rust,editable,ignore
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

View File

@ -15,17 +15,8 @@
<details>
- 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.
</details>

View File

@ -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.
</details>

View File

@ -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}}
```
<details>
- 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`.
</details>

View File

@ -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.

View File

@ -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:
<!-- mdbook-xgettext: skip -->
@ -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

View File

@ -12,12 +12,12 @@ primitives.
```rust,editable,compile_fail
use spin::mutex::SpinMutex;
static counter: SpinMutex<u32> = SpinMutex::new(0);
static COUNTER: SpinMutex<u32> = 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());
}
```